From 27ac046d8a534dc691e86f43d94192f50cd54254 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 5 Aug 2020 17:24:50 -0700 Subject: [PATCH 01/84] Rename *Test.java -> *Tests.java Rename a few test classes that accidentally ended in `Test` instead of `Tests`. Issue gh-8945 --- .../{AclClassIdUtilsTest.java => AclClassIdUtilsTests.java} | 2 +- ....java => LdapAuthenticationProviderConfigurerTests.java} | 2 +- ...nTest.java => ServerHttpSecurityConfigurationTests.java} | 2 +- ...anTest.java => UserDetailsResourceFactoryBeanTests.java} | 2 +- .../security/config/http/FormLoginConfigTests.java | 6 +++--- .../{WebConfigUtilsTest.java => WebConfigUtilsTests.java} | 2 +- ...ssorTest.java => MessageSecurityPostProcessorTests.java} | 2 +- .../security/config/http/FormLoginConfigTests-UsingSpel.xml | 6 +++--- ...RsaKeyConvertersTest.java => RsaKeyConvertersTests.java} | 2 +- ...a => BouncyCastleAesBytesEncryptorEquivalencyTests.java} | 2 +- ...torTest.java => BouncyCastleAesBytesEncryptorTests.java} | 2 +- ...dMessageMatcherTest.java => AndMessageMatcherTests.java} | 2 +- ...OrMessageMatcherTest.java => OrMessageMatcherTests.java} | 2 +- ...RegistrationsTest.java => ClientRegistrationsTests.java} | 2 +- ...AuthorizationCodeAuthenticationTokenConverterTests.java} | 2 +- ...java => MapOAuth2AccessTokenResponseConverterTests.java} | 2 +- ...java => OAuth2AccessTokenResponseMapConverterTests.java} | 2 +- ...adExchangeMatcherReactiveAuthorizationManagerTests.java} | 2 +- ...etadataFilterTest.java => Saml2MetadataFilterTests.java} | 2 +- .../debug/{DebugFilterTest.java => DebugFilterTests.java} | 2 +- ...ReactivePreAuthenticatedAuthenticationManagerTests.java} | 2 +- 21 files changed, 25 insertions(+), 25 deletions(-) rename acl/src/test/java/org/springframework/security/acls/jdbc/{AclClassIdUtilsTest.java => AclClassIdUtilsTests.java} (99%) rename config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/ldap/{LdapAuthenticationProviderConfigurerTest.java => LdapAuthenticationProviderConfigurerTests.java} (96%) rename config/src/test/java/org/springframework/security/config/annotation/web/reactive/{ServerHttpSecurityConfigurationTest.java => ServerHttpSecurityConfigurationTests.java} (97%) rename config/src/test/java/org/springframework/security/config/core/userdetails/{UserDetailsResourceFactoryBeanTest.java => UserDetailsResourceFactoryBeanTests.java} (98%) rename config/src/test/java/org/springframework/security/config/http/{WebConfigUtilsTest.java => WebConfigUtilsTests.java} (97%) rename config/src/test/java/org/springframework/security/config/websocket/{MessageSecurityPostProcessorTest.java => MessageSecurityPostProcessorTests.java} (96%) rename core/src/test/java/org/springframework/security/converter/{RsaKeyConvertersTest.java => RsaKeyConvertersTests.java} (99%) rename crypto/src/test/java/org/springframework/security/crypto/encrypt/{BouncyCastleAesBytesEncryptorEquivalencyTest.java => BouncyCastleAesBytesEncryptorEquivalencyTests.java} (98%) rename crypto/src/test/java/org/springframework/security/crypto/encrypt/{BouncyCastleAesBytesEncryptorTest.java => BouncyCastleAesBytesEncryptorTests.java} (98%) rename messaging/src/test/java/org/springframework/security/messaging/util/matcher/{AndMessageMatcherTest.java => AndMessageMatcherTests.java} (98%) rename messaging/src/test/java/org/springframework/security/messaging/util/matcher/{OrMessageMatcherTest.java => OrMessageMatcherTests.java} (98%) rename oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/{ClientRegistrationsTest.java => ClientRegistrationsTests.java} (99%) rename oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/{ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTest.java => ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests.java} (99%) rename oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/{MapOAuth2AccessTokenResponseConverterTest.java => MapOAuth2AccessTokenResponseConverterTests.java} (98%) rename oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/{OAuth2AccessTokenResponseMapConverterTest.java => OAuth2AccessTokenResponseMapConverterTests.java} (98%) rename rsocket/src/test/java/org/springframework/security/rsocket/authorization/{PayloadExchangeMatcherReactiveAuthorizationManagerTest.java => PayloadExchangeMatcherReactiveAuthorizationManagerTests.java} (99%) rename saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/{Saml2MetadataFilterTest.java => Saml2MetadataFilterTests.java} (99%) rename web/src/test/java/org/springframework/security/web/debug/{DebugFilterTest.java => DebugFilterTests.java} (99%) rename web/src/test/java/org/springframework/security/web/server/authentication/{ReactivePreAuthenticatedAuthenticationManagerTest.java => ReactivePreAuthenticatedAuthenticationManagerTests.java} (98%) diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/AclClassIdUtilsTest.java b/acl/src/test/java/org/springframework/security/acls/jdbc/AclClassIdUtilsTests.java similarity index 99% rename from acl/src/test/java/org/springframework/security/acls/jdbc/AclClassIdUtilsTest.java rename to acl/src/test/java/org/springframework/security/acls/jdbc/AclClassIdUtilsTests.java index 5dd2e36f31..d41341c466 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/AclClassIdUtilsTest.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/AclClassIdUtilsTests.java @@ -37,7 +37,7 @@ import static org.mockito.BDDMockito.given; * @author paulwheeler */ @RunWith(MockitoJUnitRunner.class) -public class AclClassIdUtilsTest { +public class AclClassIdUtilsTests { private static final Long DEFAULT_IDENTIFIER = 999L; private static final BigInteger BIGINT_IDENTIFIER = new BigInteger("999"); diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurerTest.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurerTests.java similarity index 96% rename from config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurerTest.java rename to config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurerTests.java index f3f33a91d9..b8b98509e6 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurerTest.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurerTests.java @@ -24,7 +24,7 @@ import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper import static org.assertj.core.api.Assertions.assertThat; -public class LdapAuthenticationProviderConfigurerTest { +public class LdapAuthenticationProviderConfigurerTests { private LdapAuthenticationProviderConfigurer configurer; diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationTest.java b/config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationTests.java similarity index 97% rename from config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationTest.java rename to config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationTests.java index 31c07cc2e0..c7ae2e2d78 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationTest.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationTests.java @@ -30,7 +30,7 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Eleftheria Stein */ -public class ServerHttpSecurityConfigurationTest { +public class ServerHttpSecurityConfigurationTests { @Rule public final SpringTestRule spring = new SpringTestRule(); diff --git a/config/src/test/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBeanTest.java b/config/src/test/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBeanTests.java similarity index 98% rename from config/src/test/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBeanTest.java rename to config/src/test/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBeanTests.java index 8b53fc0e34..6317995e78 100644 --- a/config/src/test/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBeanTest.java +++ b/config/src/test/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBeanTests.java @@ -35,7 +35,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; * @since 5.0 */ @RunWith(MockitoJUnitRunner.class) -public class UserDetailsResourceFactoryBeanTest { +public class UserDetailsResourceFactoryBeanTests { @Mock ResourceLoader resourceLoader; diff --git a/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java b/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java index 1fd9c265e2..56bbe0b062 100644 --- a/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java @@ -95,16 +95,16 @@ public class FormLoginConfigTests { .param("username", "user") .param("password", "password") .with(csrf())) - .andExpect(redirectedUrl(WebConfigUtilsTest.URL + "/default")); + .andExpect(redirectedUrl(WebConfigUtilsTests.URL + "/default")); this.mvc.perform(post("/login") .param("username", "user") .param("password", "wrong") .with(csrf())) - .andExpect(redirectedUrl(WebConfigUtilsTest.URL + "/failure")); + .andExpect(redirectedUrl(WebConfigUtilsTests.URL + "/failure")); this.mvc.perform(get("/")) - .andExpect(redirectedUrl("http://localhost" + WebConfigUtilsTest.URL + "/login")); + .andExpect(redirectedUrl("http://localhost" + WebConfigUtilsTests.URL + "/login")); } @Test diff --git a/config/src/test/java/org/springframework/security/config/http/WebConfigUtilsTest.java b/config/src/test/java/org/springframework/security/config/http/WebConfigUtilsTests.java similarity index 97% rename from config/src/test/java/org/springframework/security/config/http/WebConfigUtilsTest.java rename to config/src/test/java/org/springframework/security/config/http/WebConfigUtilsTests.java index 0eb0023f65..532fea1706 100644 --- a/config/src/test/java/org/springframework/security/config/http/WebConfigUtilsTest.java +++ b/config/src/test/java/org/springframework/security/config/http/WebConfigUtilsTests.java @@ -26,7 +26,7 @@ import org.springframework.beans.factory.xml.ParserContext; @RunWith(PowerMockRunner.class) @PrepareOnlyThisForTest(ParserContext.class) -public class WebConfigUtilsTest { +public class WebConfigUtilsTests { public final static String URL = "/url"; @Mock diff --git a/config/src/test/java/org/springframework/security/config/websocket/MessageSecurityPostProcessorTest.java b/config/src/test/java/org/springframework/security/config/websocket/MessageSecurityPostProcessorTests.java similarity index 96% rename from config/src/test/java/org/springframework/security/config/websocket/MessageSecurityPostProcessorTest.java rename to config/src/test/java/org/springframework/security/config/websocket/MessageSecurityPostProcessorTests.java index e05ee31365..cf8a615684 100644 --- a/config/src/test/java/org/springframework/security/config/websocket/MessageSecurityPostProcessorTest.java +++ b/config/src/test/java/org/springframework/security/config/websocket/MessageSecurityPostProcessorTests.java @@ -20,7 +20,7 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry; -public class MessageSecurityPostProcessorTest { +public class MessageSecurityPostProcessorTests { private WebSocketMessageBrokerSecurityBeanDefinitionParser.MessageSecurityPostProcessor postProcessor = new WebSocketMessageBrokerSecurityBeanDefinitionParser.MessageSecurityPostProcessor("id", false); diff --git a/config/src/test/resources/org/springframework/security/config/http/FormLoginConfigTests-UsingSpel.xml b/config/src/test/resources/org/springframework/security/config/http/FormLoginConfigTests-UsingSpel.xml index 7cc3784f25..8146964536 100644 --- a/config/src/test/resources/org/springframework/security/config/http/FormLoginConfigTests-UsingSpel.xml +++ b/config/src/test/resources/org/springframework/security/config/http/FormLoginConfigTests-UsingSpel.xml @@ -27,9 +27,9 @@ + default-target-url="#{T(org.springframework.security.config.http.WebConfigUtilsTests).URL}/default" + authentication-failure-url="#{T(org.springframework.security.config.http.WebConfigUtilsTests).URL}/failure" + login-page="#{T(org.springframework.security.config.http.WebConfigUtilsTests).URL}/login"/> diff --git a/core/src/test/java/org/springframework/security/converter/RsaKeyConvertersTest.java b/core/src/test/java/org/springframework/security/converter/RsaKeyConvertersTests.java similarity index 99% rename from core/src/test/java/org/springframework/security/converter/RsaKeyConvertersTest.java rename to core/src/test/java/org/springframework/security/converter/RsaKeyConvertersTests.java index f1ba277e12..90a4450149 100644 --- a/core/src/test/java/org/springframework/security/converter/RsaKeyConvertersTest.java +++ b/core/src/test/java/org/springframework/security/converter/RsaKeyConvertersTests.java @@ -32,7 +32,7 @@ import org.springframework.core.convert.converter.Converter; /** * Tests for {@link RsaKeyConverters} */ -public class RsaKeyConvertersTest { +public class RsaKeyConvertersTests { private static final String PKCS8_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" + "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCMk7CKSTfu3QoV\n" + "HoPVXxwZO+qweztd36cVWYqGOZinrOR2crWFu50AgR2CsdIH0+cqo7F4Vx7/3O8i\n" + diff --git a/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorEquivalencyTest.java b/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorEquivalencyTests.java similarity index 98% rename from crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorEquivalencyTest.java rename to crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorEquivalencyTests.java index 548b3791af..d4c5c73e72 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorEquivalencyTest.java +++ b/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorEquivalencyTests.java @@ -27,7 +27,7 @@ import org.springframework.security.crypto.encrypt.AesBytesEncryptor.CipherAlgor import org.springframework.security.crypto.keygen.BytesKeyGenerator; import org.springframework.security.crypto.keygen.KeyGenerators; -public class BouncyCastleAesBytesEncryptorEquivalencyTest { +public class BouncyCastleAesBytesEncryptorEquivalencyTests { private byte[] testData; private String password; diff --git a/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorTest.java b/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorTests.java similarity index 98% rename from crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorTest.java rename to crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorTests.java index 3efe507387..f4bd049c33 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorTest.java +++ b/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorTests.java @@ -25,7 +25,7 @@ import org.junit.Test; import org.springframework.security.crypto.codec.Hex; import org.springframework.security.crypto.keygen.KeyGenerators; -public class BouncyCastleAesBytesEncryptorTest { +public class BouncyCastleAesBytesEncryptorTests { private byte[] testData; private String password; diff --git a/messaging/src/test/java/org/springframework/security/messaging/util/matcher/AndMessageMatcherTest.java b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/AndMessageMatcherTests.java similarity index 98% rename from messaging/src/test/java/org/springframework/security/messaging/util/matcher/AndMessageMatcherTest.java rename to messaging/src/test/java/org/springframework/security/messaging/util/matcher/AndMessageMatcherTests.java index a765f18e77..f0d3777729 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/util/matcher/AndMessageMatcherTest.java +++ b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/AndMessageMatcherTests.java @@ -29,7 +29,7 @@ import org.mockito.junit.MockitoJUnitRunner; import org.springframework.messaging.Message; @RunWith(MockitoJUnitRunner.class) -public class AndMessageMatcherTest { +public class AndMessageMatcherTests { @Mock private MessageMatcher delegate; diff --git a/messaging/src/test/java/org/springframework/security/messaging/util/matcher/OrMessageMatcherTest.java b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/OrMessageMatcherTests.java similarity index 98% rename from messaging/src/test/java/org/springframework/security/messaging/util/matcher/OrMessageMatcherTest.java rename to messaging/src/test/java/org/springframework/security/messaging/util/matcher/OrMessageMatcherTests.java index 0e132cffe5..8f4843ab43 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/util/matcher/OrMessageMatcherTest.java +++ b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/OrMessageMatcherTests.java @@ -29,7 +29,7 @@ import org.mockito.junit.MockitoJUnitRunner; import org.springframework.messaging.Message; @RunWith(MockitoJUnitRunner.class) -public class OrMessageMatcherTest { +public class OrMessageMatcherTests { @Mock private MessageMatcher delegate; diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationsTest.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationsTests.java similarity index 99% rename from oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationsTest.java rename to oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationsTests.java index 03677717b1..2f3a239738 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationsTest.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationsTests.java @@ -42,7 +42,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Rafiullah Hamedy * @since 5.1 */ -public class ClientRegistrationsTest { +public class ClientRegistrationsTests { /** * Contains all optional parameters that are found in ClientRegistration diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTest.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests.java similarity index 99% rename from oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTest.java rename to oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests.java index 9f921392d8..feb4ab5d7c 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTest.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests.java @@ -47,7 +47,7 @@ import static org.mockito.Mockito.when; * @since 5.1 */ @RunWith(MockitoJUnitRunner.class) -public class ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTest { +public class ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests { @Mock private ReactiveClientRegistrationRepository clientRegistrationRepository; diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/MapOAuth2AccessTokenResponseConverterTest.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/MapOAuth2AccessTokenResponseConverterTests.java similarity index 98% rename from oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/MapOAuth2AccessTokenResponseConverterTest.java rename to oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/MapOAuth2AccessTokenResponseConverterTests.java index 56dd03f83f..6af7ed499d 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/MapOAuth2AccessTokenResponseConverterTest.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/MapOAuth2AccessTokenResponseConverterTests.java @@ -32,7 +32,7 @@ import org.springframework.security.oauth2.core.OAuth2RefreshToken; * * @author Nikita Konev */ -public class MapOAuth2AccessTokenResponseConverterTest { +public class MapOAuth2AccessTokenResponseConverterTests { private MapOAuth2AccessTokenResponseConverter messageConverter; diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseMapConverterTest.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseMapConverterTests.java similarity index 98% rename from oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseMapConverterTest.java rename to oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseMapConverterTests.java index cdeb3dd73d..980155b6c9 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseMapConverterTest.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseMapConverterTests.java @@ -31,7 +31,7 @@ import org.springframework.security.oauth2.core.OAuth2AccessToken; * * @author Nikita Konev */ -public class OAuth2AccessTokenResponseMapConverterTest { +public class OAuth2AccessTokenResponseMapConverterTests { private OAuth2AccessTokenResponseMapConverter messageConverter; diff --git a/rsocket/src/test/java/org/springframework/security/rsocket/authorization/PayloadExchangeMatcherReactiveAuthorizationManagerTest.java b/rsocket/src/test/java/org/springframework/security/rsocket/authorization/PayloadExchangeMatcherReactiveAuthorizationManagerTests.java similarity index 99% rename from rsocket/src/test/java/org/springframework/security/rsocket/authorization/PayloadExchangeMatcherReactiveAuthorizationManagerTest.java rename to rsocket/src/test/java/org/springframework/security/rsocket/authorization/PayloadExchangeMatcherReactiveAuthorizationManagerTests.java index 03a614b792..2a0fceafe3 100644 --- a/rsocket/src/test/java/org/springframework/security/rsocket/authorization/PayloadExchangeMatcherReactiveAuthorizationManagerTest.java +++ b/rsocket/src/test/java/org/springframework/security/rsocket/authorization/PayloadExchangeMatcherReactiveAuthorizationManagerTests.java @@ -37,7 +37,7 @@ import static org.mockito.Mockito.when; * @author Rob Winch */ @RunWith(MockitoJUnitRunner.class) -public class PayloadExchangeMatcherReactiveAuthorizationManagerTest { +public class PayloadExchangeMatcherReactiveAuthorizationManagerTests { @Mock private ReactiveAuthorizationManager authz; diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilterTest.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilterTests.java similarity index 99% rename from saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilterTest.java rename to saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilterTests.java index 4c490bd284..658afcbd96 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilterTest.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilterTests.java @@ -39,7 +39,7 @@ import static org.springframework.security.saml2.provider.service.registration.T /** * Tests for {@link Saml2MetadataFilter} */ -public class Saml2MetadataFilterTest { +public class Saml2MetadataFilterTests { RelyingPartyRegistrationRepository repository; Saml2MetadataResolver resolver; diff --git a/web/src/test/java/org/springframework/security/web/debug/DebugFilterTest.java b/web/src/test/java/org/springframework/security/web/debug/DebugFilterTests.java similarity index 99% rename from web/src/test/java/org/springframework/security/web/debug/DebugFilterTest.java rename to web/src/test/java/org/springframework/security/web/debug/DebugFilterTests.java index 7570448e5e..728630334f 100644 --- a/web/src/test/java/org/springframework/security/web/debug/DebugFilterTest.java +++ b/web/src/test/java/org/springframework/security/web/debug/DebugFilterTests.java @@ -48,7 +48,7 @@ import org.springframework.test.util.ReflectionTestUtils; */ @RunWith(PowerMockRunner.class) @PrepareOnlyThisForTest(Logger.class) -public class DebugFilterTest { +public class DebugFilterTests { @Captor private ArgumentCaptor requestCaptor; @Captor diff --git a/web/src/test/java/org/springframework/security/web/server/authentication/ReactivePreAuthenticatedAuthenticationManagerTest.java b/web/src/test/java/org/springframework/security/web/server/authentication/ReactivePreAuthenticatedAuthenticationManagerTests.java similarity index 98% rename from web/src/test/java/org/springframework/security/web/server/authentication/ReactivePreAuthenticatedAuthenticationManagerTest.java rename to web/src/test/java/org/springframework/security/web/server/authentication/ReactivePreAuthenticatedAuthenticationManagerTests.java index 16925d7b9e..9dacbd93a6 100644 --- a/web/src/test/java/org/springframework/security/web/server/authentication/ReactivePreAuthenticatedAuthenticationManagerTest.java +++ b/web/src/test/java/org/springframework/security/web/server/authentication/ReactivePreAuthenticatedAuthenticationManagerTests.java @@ -39,7 +39,7 @@ import static org.mockito.Mockito.when; * @author Alexey Nesterov * @since 5.2 */ -public class ReactivePreAuthenticatedAuthenticationManagerTest { +public class ReactivePreAuthenticatedAuthenticationManagerTests { private ReactiveUserDetailsService mockUserDetailsService = mock(ReactiveUserDetailsService.class); From 103d822e46e7df613e37d2ee619df2dc348153b6 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 23 Jul 2020 12:40:37 -0700 Subject: [PATCH 02/84] Add noformat blocks around http config Find `http` config using a regex search of `^\s*https*$` and protect them against formatting. Issue gh-8945 --- .../WebSecurityConfigurerAdapter.java | 4 +-- .../web/configurers/X509Configurer.java | 4 +-- .../WebFluxSecurityConfiguration.java | 6 ++++ .../config/web/server/ServerHttpSecurity.java | 4 +++ .../annotation/issue50/SecurityConfig.java | 8 ++--- .../annotation/sec2758/Sec2758Tests.java | 2 ++ ...RequestMatcherRegistryAnyMatcherTests.java | 10 ++++++ ...mpleWebSecurityConfigurerAdapterTests.java | 6 ++++ .../web/builders/HttpConfigurationTests.java | 6 ++++ .../web/builders/NamespaceHttpTests.java | 36 +++++++++++++++++++ .../configuration/EnableWebSecurityTests.java | 2 ++ .../WebSecurityConfigurationTests.java | 24 +++++++++++++ .../configurers/AnonymousConfigurerTests.java | 2 ++ .../configurers/FormLoginConfigurerTests.java | 2 ++ .../HttpSecurityAntMatchersTests.java | 4 +++ .../configurers/HttpSecurityLogoutTests.java | 2 ++ .../LogoutConfigurerClearSiteDataTests.java | 2 ++ .../configurers/NamespaceHttpBasicTests.java | 8 +++++ .../NamespaceHttpCustomFilterTests.java | 10 ++++++ .../NamespaceHttpExpressionHandlerTests.java | 3 +- .../NamespaceHttpFormLoginTests.java | 7 +++- .../NamespaceHttpHeadersTests.java | 20 +++++++++++ .../NamespaceHttpInterceptUrlTests.java | 2 ++ .../configurers/NamespaceHttpJeeTests.java | 4 +++ .../configurers/NamespaceHttpLogoutTests.java | 5 ++- .../NamespaceHttpOpenIDLoginTests.java | 10 ++++-- .../NamespaceHttpPortMappingsTests.java | 2 ++ .../NamespaceHttpRequestCacheTests.java | 4 +++ ...aceHttpServerAccessDeniedHandlerTests.java | 4 +++ .../configurers/NamespaceHttpX509Tests.java | 12 +++++++ .../NamespaceSessionManagementTests.java | 14 ++++++++ .../configurers/PermitAllSupportTests.java | 4 +++ .../PortMapperConfigurerTests.java | 2 ++ .../RequestCacheConfigurerTests.java | 2 ++ ...ionManagementConfigurerServlet31Tests.java | 4 +-- ...rerSessionAuthenticationStrategyTests.java | 4 +-- ...tConfigurerSessionCreationPolicyTests.java | 2 ++ ...onfigurerTransientAuthenticationTests.java | 5 ++- .../client/OAuth2ClientConfigurerTests.java | 2 ++ .../client/OAuth2LoginConfigurerTests.java | 22 ++++++++++++ .../OAuth2ResourceServerConfigurerTests.java | 6 ++-- .../saml2/Saml2LoginConfigurerTests.java | 4 +++ .../core/GrantedAuthorityDefaultsJcTests.java | 2 ++ .../customconfigurer/CustomConfigurer.java | 6 ++-- .../CustomHttpSecurityConfigurerTests.java | 4 +++ .../web/server/OAuth2ClientSpecTests.java | 6 ++++ .../config/web/server/OAuth2LoginTests.java | 10 ++++-- .../server/OAuth2ResourceServerSpecTests.java | 6 +--- .../web/servlet/request/Sec2935Tests.java | 2 ++ ...rocessorsAuthenticationStatelessTests.java | 5 ++- ...equestPostProcessorsOAuth2ClientTests.java | 2 ++ ...RequestPostProcessorsOAuth2LoginTests.java | 2 ++ ...vcRequestPostProcessorsOidcLoginTests.java | 2 ++ ...RequestPostProcessorsOpaqueTokenTests.java | 2 ++ ...sorsTestSecurityContextStatelessTests.java | 5 ++- .../csrf/CustomCsrfShowcaseTests.java | 4 +-- .../CustomConfigAuthenticationTests.java | 4 +-- ...oginRequestBuilderAuthenticationTests.java | 4 +-- .../DefaultfSecurityRequestsTests.java | 4 +-- .../secured/SecurityRequestsTests.java | 4 +-- .../secured/WithUserAuthenticationTests.java | 4 +-- ...WithUserClassLevelAuthenticationTests.java | 4 +-- .../WithUserDetailsAuthenticationTests.java | 4 +-- ...rDetailsClassLevelAuthenticationTests.java | 4 +-- .../test/web/support/WebTestUtilsTests.java | 8 ++--- 65 files changed, 325 insertions(+), 59 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java index 4667967f99..6f3819549f 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java @@ -357,18 +357,18 @@ public abstract class WebSecurityConfigurerAdapter implements * @param http the {@link HttpSecurity} to modify * @throws Exception if an error occurs */ - // @formatter:off protected void configure(HttpSecurity http) throws Exception { logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity)."); + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin().and() .httpBasic(); + // @formatter:on } - // @formatter:on /** * Gets the ApplicationContext diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java index 7b35c367ad..55d56086ed 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java @@ -169,17 +169,17 @@ public final class X509Configurer> extends return this; } - // @formatter:off @Override public void init(H http) { PreAuthenticatedAuthenticationProvider authenticationProvider = new PreAuthenticatedAuthenticationProvider(); authenticationProvider.setPreAuthenticatedUserDetailsService(getAuthenticationUserDetailsService(http)); + // @formatter:off http .authenticationProvider(authenticationProvider) .setSharedObject(AuthenticationEntryPoint.class, new Http403ForbiddenEntryPoint()); + // @formatter:on } - // @formatter:on @Override public void configure(H http) { diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java index 7fa4b1c6dd..368d99c015 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java @@ -96,16 +96,20 @@ class WebFluxSecurityConfiguration { * @return */ private SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + // @formatter:off http .authorizeExchange() .anyExchange().authenticated(); + // @formatter:on if (isOAuth2Present && OAuth2ClasspathGuard.shouldConfigure(this.context)) { OAuth2ClasspathGuard.configure(this.context, http); } else { + // @formatter:off http .httpBasic().and() .formLogin(); + // @formatter:on } SecurityWebFilterChain result = http.build(); @@ -114,9 +118,11 @@ class WebFluxSecurityConfiguration { private static class OAuth2ClasspathGuard { static void configure(ApplicationContext context, ServerHttpSecurity http) { + // @formatter:off http .oauth2Login().and() .oauth2Client(); + // @formatter:on } static boolean shouldConfigure(ApplicationContext context) { diff --git a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java index 8334fce3eb..63fc32a93c 100644 --- a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java +++ b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java @@ -1812,6 +1812,7 @@ public class ServerHttpSecurity { private void registerDefaultCsrfOverride(ServerHttpSecurity http) { if ( http.csrf != null && !http.csrf.specifiedRequireCsrfProtectionMatcher ) { + // @formatter:off http .csrf() .requireCsrfProtectionMatcher( @@ -1819,6 +1820,7 @@ public class ServerHttpSecurity { CsrfWebFilter.DEFAULT_CSRF_MATCHER, new NegatedServerWebExchangeMatcher( this.authenticationConverterServerWebExchangeMatcher))); + // @formatter:on } } @@ -1920,8 +1922,10 @@ public class ServerHttpSecurity { AuthenticationWebFilter oauth2 = new BearerTokenAuthenticationWebFilter(authenticationManager); oauth2.setServerAuthenticationConverter(bearerTokenConverter); oauth2.setAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(entryPoint)); + // @formatter:off http .addFilterAt(oauth2, SecurityWebFiltersOrder.AUTHENTICATION); + // @formatter:on } protected ReactiveJwtDecoder getJwtDecoder() { diff --git a/config/src/test/java/org/springframework/security/config/annotation/issue50/SecurityConfig.java b/config/src/test/java/org/springframework/security/config/annotation/issue50/SecurityConfig.java index 6c9e56e5c6..b7051ebe51 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/issue50/SecurityConfig.java +++ b/config/src/test/java/org/springframework/security/config/annotation/issue50/SecurityConfig.java @@ -45,22 +45,22 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserRepository myUserRepository; - // @formatter:off @Override protected void configure(AuthenticationManagerBuilder auth) { + // @formatter:off auth .authenticationProvider(authenticationProvider()); + // @formatter:on } - // @formatter:on - // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .antMatchers("/*").permitAll(); + // @formatter:on } - // @formatter:on @Bean @Override diff --git a/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java b/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java index 9cf8126e3e..53441757f8 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java @@ -96,9 +96,11 @@ public class Sec2758Tests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().access("hasAnyRole('CUSTOM')"); + // @formatter:on } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java index e0124a570f..b2694200b0 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java @@ -35,10 +35,12 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests{ @EnableWebSecurity static class AntMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() .antMatchers("/demo/**").permitAll(); + // @formatter:on } } @@ -51,10 +53,12 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests{ @EnableWebSecurity static class MvcMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() .mvcMatchers("/demo/**").permitAll(); + // @formatter:on } } @@ -67,10 +71,12 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests{ @EnableWebSecurity static class RegexMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() .regexMatchers(".*").permitAll(); + // @formatter:on } } @@ -83,10 +89,12 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests{ @EnableWebSecurity static class AnyRequestAfterItselfConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() .anyRequest().permitAll(); + // @formatter:on } } @@ -99,10 +107,12 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests{ @EnableWebSecurity static class RequestMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() .requestMatchers(new AntPathRequestMatcher("/**")).permitAll(); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java index b8304f9e13..218f261433 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java @@ -218,6 +218,7 @@ public class SampleWebSecurityConfigurerAdapterTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .antMatchers("/signup", "/about").permitAll() @@ -227,6 +228,7 @@ public class SampleWebSecurityConfigurerAdapterTests { .loginPage("/login") // set permitAll for all URLs associated with Form Login .permitAll(); + // @formatter:on } @Override @@ -354,6 +356,7 @@ public class SampleWebSecurityConfigurerAdapterTests { @Order(1) public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .antMatcher("/api/**") .authorizeRequests() @@ -361,6 +364,7 @@ public class SampleWebSecurityConfigurerAdapterTests { .antMatchers("/api/**").hasRole("USER") .and() .httpBasic(); + // @formatter:on } } @@ -375,6 +379,7 @@ public class SampleWebSecurityConfigurerAdapterTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .antMatchers("/signup", "/about").permitAll() @@ -383,6 +388,7 @@ public class SampleWebSecurityConfigurerAdapterTests { .formLogin() .loginPage("/login") .permitAll(); + // @formatter:on } } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java index dbeda6bdd2..00fa2b4e96 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java @@ -68,8 +68,10 @@ public class HttpConfigurationTests { static class UnregisteredFilterConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) { + // @formatter:off http .addFilter(new UnregisteredFilter()); + // @formatter:on } protected void configure(AuthenticationManagerBuilder auth) throws Exception { @@ -105,8 +107,10 @@ public class HttpConfigurationTests { static CasAuthenticationFilter CAS_AUTHENTICATION_FILTER; protected void configure(HttpSecurity http) { + // @formatter:off http .addFilter(CAS_AUTHENTICATION_FILTER); + // @formatter:on } } @@ -124,6 +128,7 @@ public class HttpConfigurationTests { static class RequestMatcherRegistryConfigs extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .requestMatchers() .antMatchers("/api/**") @@ -133,6 +138,7 @@ public class HttpConfigurationTests { .antMatchers("/**").hasRole("USER") .and() .httpBasic(); + // @formatter:on } } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java index d219a50dbe..d94e54403e 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java @@ -94,10 +94,12 @@ public class NamespaceHttpTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().permitAll() .accessDecisionManager(ACCESS_DECISION_MANAGER); + // @formatter:on } } @@ -114,6 +116,7 @@ public class NamespaceHttpTests { static class AccessDeniedPageConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .antMatchers("/admin").hasRole("ADMIN") @@ -121,6 +124,7 @@ public class NamespaceHttpTests { .and() .exceptionHandling() .accessDeniedPage("/AccessDeniedPage"); + // @formatter:on } } @@ -145,11 +149,13 @@ public class NamespaceHttpTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin(); + // @formatter:on } } @@ -168,12 +174,14 @@ public class NamespaceHttpTests { static class CreateSessionAlwaysConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().permitAll() .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.ALWAYS); + // @formatter:on } } @@ -191,12 +199,14 @@ public class NamespaceHttpTests { static class CreateSessionStatelessConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().permitAll() .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); + // @formatter:on } } @@ -220,6 +230,7 @@ public class NamespaceHttpTests { static class IfRequiredConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .antMatchers("/unsecure").permitAll() @@ -229,6 +240,7 @@ public class NamespaceHttpTests { .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .and() .formLogin(); + // @formatter:on } } @@ -246,12 +258,14 @@ public class NamespaceHttpTests { static class CreateSessionNeverConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().anonymous() .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER); + // @formatter:on } } @@ -268,6 +282,7 @@ public class NamespaceHttpTests { static class EntryPointRefConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() @@ -276,6 +291,7 @@ public class NamespaceHttpTests { .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/entry-point")) .and() .formLogin(); + // @formatter:on } } @@ -299,8 +315,10 @@ public class NamespaceHttpTests { static class JaasApiProvisionConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) { + // @formatter:off http .addFilter(new JaasApiIntegrationFilter()); + // @formatter:on } } @@ -317,12 +335,14 @@ public class NamespaceHttpTests { static class RealmConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() .and() .httpBasic() .realmName("RealmConfig"); + // @formatter:on } } @@ -341,8 +361,10 @@ public class NamespaceHttpTests { static class RequestMatcherAntConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) { + // @formatter:off http .antMatcher("/api/**"); + // @formatter:on } } @@ -361,8 +383,10 @@ public class NamespaceHttpTests { static class RequestMatcherRegexConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) { + // @formatter:off http .regexMatcher("/regex/.*"); + // @formatter:on } } @@ -381,8 +405,10 @@ public class NamespaceHttpTests { static class RequestMatcherRefConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) { + // @formatter:off http .requestMatcher(new MyRequestMatcher()); + // @formatter:on } static class MyRequestMatcher implements RequestMatcher { @@ -439,6 +465,7 @@ public class NamespaceHttpTests { static class SecurityContextRepoConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() @@ -447,6 +474,7 @@ public class NamespaceHttpTests { .securityContextRepository(new NullSecurityContextRepository()) .and() .formLogin(); + // @formatter:on } @Override @@ -470,12 +498,14 @@ public class NamespaceHttpTests { static class ServletApiProvisionConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().permitAll() .and() .servletApi() .disable(); + // @formatter:on } } @@ -492,9 +522,11 @@ public class NamespaceHttpTests { static class ServletApiProvisionDefaultsConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().permitAll(); + // @formatter:on } } @@ -525,11 +557,13 @@ public class NamespaceHttpTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .antMatchers("/users**", "/sessions/**").hasRole("USER") .antMatchers("/signup").permitAll() .anyRequest().hasRole("USER"); + // @formatter:on } @Override @@ -560,11 +594,13 @@ public class NamespaceHttpTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .apply(new UrlAuthorizationConfigurer<>(getApplicationContext())).getRegistry() .antMatchers("/users**", "/sessions/**").hasRole("USER") .antMatchers("/signup").hasRole("ANONYMOUS") .anyRequest().hasRole("USER"); + // @formatter:on } @Override diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java index 180dcac62b..fd77bea5d5 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java @@ -77,11 +77,13 @@ public class EnableWebSecurityTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .antMatchers("/*").hasRole("USER") .and() .formLogin(); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java index 29dab5ac05..6f27f16b18 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java @@ -127,10 +127,12 @@ public class WebSecurityConfigurationTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .antMatcher("/role1/**") .authorizeRequests() .anyRequest().hasRole("1"); + // @formatter:on } } @@ -139,10 +141,12 @@ public class WebSecurityConfigurationTests { static class WebConfigurer2 extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .antMatcher("/role2/**") .authorizeRequests() .anyRequest().hasRole("2"); + // @formatter:on } } @@ -151,10 +155,12 @@ public class WebSecurityConfigurationTests { static class WebConfigurer3 extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .antMatcher("/role3/**") .authorizeRequests() .anyRequest().hasRole("3"); + // @formatter:on } } @@ -163,9 +169,11 @@ public class WebSecurityConfigurationTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("4"); + // @formatter:on } } } @@ -258,10 +266,12 @@ public class WebSecurityConfigurationTests { static class WebConfigurer1 extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .antMatcher("/role1/**") .authorizeRequests() .anyRequest().hasRole("1"); + // @formatter:on } } @@ -269,10 +279,12 @@ public class WebSecurityConfigurationTests { static class WebConfigurer2 extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .antMatcher("/role2/**") .authorizeRequests() .anyRequest().hasRole("2"); + // @formatter:on } } } @@ -319,10 +331,12 @@ public class WebSecurityConfigurationTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() .expressionHandler(EXPRESSION_HANDLER); + // @formatter:on } } @@ -357,9 +371,11 @@ public class WebSecurityConfigurationTests { static class WebSecurityExpressionHandlerDefaultsConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated(); + // @formatter:on } } @@ -436,9 +452,11 @@ public class WebSecurityConfigurationTests { static class WebInvocationPrivilegeEvaluatorDefaultsConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated(); + // @formatter:on } } @@ -475,9 +493,11 @@ public class WebSecurityConfigurationTests { static class DefaultExpressionHandlerSetsBeanResolverConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().access("request.method == 'GET' ? @b.grant() : @b.deny()"); + // @formatter:on } @RestController @@ -571,10 +591,12 @@ public class WebSecurityConfigurationTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .antMatcher("/anonymous/**") .authorizeRequests() .anyRequest().anonymous(); + // @formatter:on } } @@ -583,9 +605,11 @@ public class WebSecurityConfigurationTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated(); + // @formatter:on } } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.java index 11d80e02d8..fca1d0ab8e 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.java @@ -60,12 +60,14 @@ public class AnonymousConfigurerTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .anonymous() .key("key") .principal("principal") .and() .anonymous(); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.java index 991e598581..736cc130a6 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.java @@ -83,10 +83,12 @@ public class FormLoginConfigurerTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .formLogin().and() .requestCache() .requestCache(this.requestCache); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java index 1fc9ec3dbf..29184b43ec 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java @@ -78,12 +78,14 @@ public class HttpSecurityAntMatchersTests { @Configuration static class AntMatchersNoPatternsConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .requestMatchers() .antMatchers(HttpMethod.POST) .and() .authorizeRequests() .anyRequest().denyAll(); + // @formatter:on } @Override @@ -108,6 +110,7 @@ public class HttpSecurityAntMatchersTests { @Configuration static class AntMatchersEmptyPatternsConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .requestMatchers() .antMatchers("/never/") @@ -115,6 +118,7 @@ public class HttpSecurityAntMatchersTests { .and() .authorizeRequests() .anyRequest().denyAll(); + // @formatter:on } @Override diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java index 315a85a74b..673705ef3a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java @@ -85,10 +85,12 @@ public class HttpSecurityLogoutTests { @Configuration static class ClearAuthenticationFalseConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .csrf().disable() .logout() .clearAuthentication(false); + // @formatter:on } @Override diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerClearSiteDataTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerClearSiteDataTests.java index a46fdaba66..79d32b7467 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerClearSiteDataTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerClearSiteDataTests.java @@ -97,9 +97,11 @@ public class LogoutConfigurerClearSiteDataTests { static class HttpLogoutConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .logout() .addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(SOURCE))); + // @formatter:on } } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java index 9a66e356fd..967b12d8ea 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java @@ -95,11 +95,13 @@ public class NamespaceHttpBasicTests { @EnableWebSecurity static class HttpBasicConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") .and() .httpBasic(); + // @formatter:on } } @@ -151,11 +153,13 @@ public class NamespaceHttpBasicTests { static class CustomHttpBasicConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") .and() .httpBasic().realmName("Custom Realm"); + // @formatter:on } } @@ -207,9 +211,11 @@ public class NamespaceHttpBasicTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .httpBasic() .authenticationDetailsSource(this.authenticationDetailsSource); + // @formatter:on } @Bean @@ -278,12 +284,14 @@ public class NamespaceHttpBasicTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") .and() .httpBasic() .authenticationEntryPoint(this.authenticationEntryPoint); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java index b4d07cc1ab..8e23245742 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java @@ -67,9 +67,11 @@ public class NamespaceHttpCustomFilterTests { @EnableWebSecurity static class CustomFilterBeforeConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class) .formLogin(); + // @formatter:on } } @@ -82,9 +84,11 @@ public class NamespaceHttpCustomFilterTests { @EnableWebSecurity static class CustomFilterAfterConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .addFilterAfter(new CustomFilter(), UsernamePasswordAuthenticationFilter.class) .formLogin(); + // @formatter:on } } @@ -102,10 +106,12 @@ public class NamespaceHttpCustomFilterTests { } protected void configure(HttpSecurity http) { + // @formatter:off http // this works so long as the CustomFilter extends one of the standard filters // if not, use addFilterBefore or addFilterAfter .addFilter(new CustomFilter()); + // @formatter:on } } @@ -124,8 +130,10 @@ public class NamespaceHttpCustomFilterTests { } protected void configure(HttpSecurity http) { + // @formatter:off http .addFilterAt(new OtherCustomFilter(), UsernamePasswordAuthenticationFilter.class); + // @formatter:on } } @@ -147,11 +155,13 @@ public class NamespaceHttpCustomFilterTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") .and() .addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java index c031809554..3c5af7d6e9 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java @@ -86,11 +86,12 @@ public class NamespaceHttpExpressionHandlerTests { protected void configure(HttpSecurity http) throws Exception { DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler(); handler.setExpressionParser(expressionParser()); - + // @formatter:off http .authorizeRequests() .expressionHandler(handler) .anyRequest().access("hasRole('USER')"); + // @formatter:on } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java index f33623f1ce..553033215c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java @@ -90,11 +90,13 @@ public class NamespaceHttpFormLoginTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") .and() .formLogin(); + // @formatter:on } } @@ -120,6 +122,7 @@ public class NamespaceHttpFormLoginTests { static class FormLoginCustomConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { boolean alwaysUseDefaultSuccess = true; + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") @@ -131,6 +134,7 @@ public class NamespaceHttpFormLoginTests { .failureUrl("/authentication/login?failed") // form-login@authentication-failure-url .loginProcessingUrl("/authentication/login/process") // form-login@login-processing-url .defaultSuccessUrl("/default", alwaysUseDefaultSuccess); // form-login@default-target-url / form-login@always-use-default-target + // @formatter:on } } @@ -159,7 +163,7 @@ public class NamespaceHttpFormLoginTests { SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler(); successHandler.setDefaultTargetUrl("/custom/targetUrl"); - + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") @@ -170,6 +174,7 @@ public class NamespaceHttpFormLoginTests { .successHandler(successHandler) // form-login@authentication-success-handler-ref .authenticationDetailsSource(authenticationDetailsSource()) // form-login@authentication-details-source-ref .and(); + // @formatter:on } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java index 6496668b7d..22a29ce700 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java @@ -77,8 +77,10 @@ public class NamespaceHttpHeadersTests { static class HeadersDefaultConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .headers(); + // @formatter:on } } @@ -94,10 +96,12 @@ public class NamespaceHttpHeadersTests { static class HeadersCacheControlConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .headers() .defaultsDisabled() .cacheControl(); + // @formatter:on } } @@ -113,10 +117,12 @@ public class NamespaceHttpHeadersTests { static class HstsConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .headers() .defaultsDisabled() .httpStrictTransportSecurity(); + // @formatter:on } } @@ -132,6 +138,7 @@ public class NamespaceHttpHeadersTests { static class HstsCustomConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .headers() // hsts@request-matcher-ref, hsts@max-age-seconds, hsts@include-subdomains @@ -140,6 +147,7 @@ public class NamespaceHttpHeadersTests { .requestMatcher(AnyRequestMatcher.INSTANCE) .maxAgeInSeconds(15768000) .includeSubDomains(false); + // @formatter:on } } @@ -155,12 +163,14 @@ public class NamespaceHttpHeadersTests { static class FrameOptionsSameOriginConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .headers() // frame-options@policy=SAMEORIGIN .defaultsDisabled() .frameOptions() .sameOrigin(); + // @formatter:on } } @@ -178,12 +188,14 @@ public class NamespaceHttpHeadersTests { static class FrameOptionsAllowFromConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .headers() // frame-options@ref .defaultsDisabled() .addHeaderWriter(new XFrameOptionsHeaderWriter( new StaticAllowFromStrategy(URI.create("https://example.com")))); + // @formatter:on } } @@ -199,11 +211,13 @@ public class NamespaceHttpHeadersTests { static class XssProtectionConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .headers() // xss-protection .defaultsDisabled() .xssProtection(); + // @formatter:on } } @@ -219,6 +233,7 @@ public class NamespaceHttpHeadersTests { static class XssProtectionCustomConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .headers() // xss-protection@enabled and xss-protection@block @@ -226,6 +241,7 @@ public class NamespaceHttpHeadersTests { .xssProtection() .xssProtectionEnabled(true) .block(false); + // @formatter:on } } @@ -241,11 +257,13 @@ public class NamespaceHttpHeadersTests { static class ContentTypeOptionsConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .headers() // content-type-options .defaultsDisabled() .contentTypeOptions(); + // @formatter:on } } @@ -263,10 +281,12 @@ public class NamespaceHttpHeadersTests { static class HeaderRefConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .headers() .defaultsDisabled() .addHeaderWriter(new StaticHeadersWriter("customHeaderName", "customHeaderValue")); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java index 26fcdfcac6..76aa167d30 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java @@ -120,6 +120,7 @@ public class NamespaceHttpInterceptUrlTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() // the line below is similar to intercept-url@pattern: @@ -142,6 +143,7 @@ public class NamespaceHttpInterceptUrlTests { // the line below is similar to intercept-url@requires-channel="http": // .anyRequest().requiresInsecure(); + // @formatter:on } protected void configure(AuthenticationManagerBuilder auth) throws Exception { diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.java index ed06b41183..f9841f024a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.java @@ -83,12 +83,14 @@ public class NamespaceHttpJeeTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("user") .and() .jee() .mappableRoles("user", "admin"); + // @formatter:on } } @@ -120,6 +122,7 @@ public class NamespaceHttpJeeTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("user") @@ -127,6 +130,7 @@ public class NamespaceHttpJeeTests { .jee() .mappableAuthorities("ROLE_user", "ROLE_admin") .authenticatedUserDetailsService(this.authenticationUserDetailsService); + // @formatter:on } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java index f0edd6301c..6a74081ee4 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java @@ -122,12 +122,14 @@ public class NamespaceHttpLogoutTests { static class CustomHttpLogoutConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .logout() .deleteCookies("remove") // logout@delete-cookies .invalidateHttpSession(false) // logout@invalidate-session=false (default is true) .logoutUrl("/custom-logout") // logout@logout-url (default is /logout) .logoutSuccessUrl("/logout-success"); // logout@success-url (default is /login?logout) + // @formatter:on } } @@ -182,10 +184,11 @@ public class NamespaceHttpLogoutTests { SimpleUrlLogoutSuccessHandler logoutSuccessHandler = new SimpleUrlLogoutSuccessHandler(); logoutSuccessHandler.setDefaultTargetUrl("/SuccessHandlerRefHttpLogoutConfig"); - + // @formatter:off http .logout() .logoutSuccessHandler(logoutSuccessHandler); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java index c2be226617..04bbe88d51 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java @@ -97,12 +97,14 @@ public class NamespaceHttpOpenIDLoginTests { static class OpenIDLoginConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") .and() .openidLogin() .permitAll(); + // @formatter:on } } @@ -159,6 +161,7 @@ public class NamespaceHttpOpenIDLoginTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") @@ -191,6 +194,7 @@ public class NamespaceHttpOpenIDLoginTests { .and() .and() .permitAll(); + // @formatter:on } } @@ -209,6 +213,7 @@ public class NamespaceHttpOpenIDLoginTests { @Override protected void configure(HttpSecurity http) throws Exception { boolean alwaysUseDefaultSuccess = true; + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") @@ -219,6 +224,7 @@ public class NamespaceHttpOpenIDLoginTests { .failureUrl("/authentication/login?failed") // openid-login@authentication-failure-url .loginProcessingUrl("/authentication/login/process") // openid-login@login-processing-url .defaultSuccessUrl("/default", alwaysUseDefaultSuccess); // openid-login@default-target-url / openid-login@always-use-default-target + // @formatter:on } } @@ -267,7 +273,7 @@ public class NamespaceHttpOpenIDLoginTests { SavedRequestAwareAuthenticationSuccessHandler handler = new SavedRequestAwareAuthenticationSuccessHandler(); handler.setDefaultTargetUrl("/custom/targetUrl"); - + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") @@ -285,7 +291,7 @@ public class NamespaceHttpOpenIDLoginTests { return filter; } }); - + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.java index cd246b87f7..f742f4c9e9 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.java @@ -64,6 +64,7 @@ public class NamespaceHttpPortMappingsTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") @@ -74,6 +75,7 @@ public class NamespaceHttpPortMappingsTests { .requiresChannel() .antMatchers("/login", "/secured/**").requiresSecure() .anyRequest().requiresInsecure(); + // @formatter:on } protected void configure(AuthenticationManagerBuilder auth) throws Exception { diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java index 9d1cf59ef4..ac895fc284 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java @@ -67,12 +67,14 @@ public class NamespaceHttpRequestCacheTests { @EnableWebSecurity static class RequestCacheRefConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() .and() .requestCache() .requestCache(requestCache()); + // @formatter:on } protected void configure(AuthenticationManagerBuilder auth) throws Exception { @@ -104,9 +106,11 @@ public class NamespaceHttpRequestCacheTests { @EnableWebSecurity static class DefaultRequestCacheRefConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated(); + // @formatter:on } protected void configure(AuthenticationManagerBuilder auth) throws Exception { diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpServerAccessDeniedHandlerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpServerAccessDeniedHandlerTests.java index 0aea788b3d..94c07da54c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpServerAccessDeniedHandlerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpServerAccessDeniedHandlerTests.java @@ -70,12 +70,14 @@ public class NamespaceHttpServerAccessDeniedHandlerTests { @EnableWebSecurity static class AccessDeniedPageConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().denyAll() .and() .exceptionHandling() .accessDeniedPage("/AccessDeniedPageConfig"); + // @formatter:on } } @@ -121,12 +123,14 @@ public class NamespaceHttpServerAccessDeniedHandlerTests { @EnableWebSecurity static class AccessDeniedHandlerRefConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().denyAll() .and() .exceptionHandling() .accessDeniedHandler(accessDeniedHandler()); + // @formatter:on } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java index beaeb1f73a..6f9d7d7cc4 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java @@ -88,11 +88,13 @@ public class NamespaceHttpX509Tests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") .and() .x509(); + // @formatter:on } } @@ -119,12 +121,14 @@ public class NamespaceHttpX509Tests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") .and() .x509() .authenticationDetailsSource(authenticationDetailsSource()); + // @formatter:on } @Bean @@ -155,12 +159,14 @@ public class NamespaceHttpX509Tests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") .and() .x509() .subjectPrincipalRegex("CN=(.*?)@example.com(?:,|$)"); + // @formatter:on } } @@ -184,12 +190,14 @@ public class NamespaceHttpX509Tests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") .and() .x509() .x509PrincipalExtractor(this::extractCommonName); + // @formatter:on } private String extractCommonName(X509Certificate certificate) { @@ -221,12 +229,14 @@ public class NamespaceHttpX509Tests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") .and() .x509() .userDetailsService(username -> USER); + // @formatter:on } } @@ -248,12 +258,14 @@ public class NamespaceHttpX509Tests { } protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().hasRole("USER") .and() .x509() .authenticationUserDetailsService(authentication -> USER); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java index e3a1f6bde0..e163d7946e 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java @@ -174,6 +174,7 @@ public class NamespaceSessionManagementTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() @@ -187,6 +188,7 @@ public class NamespaceSessionManagementTests { .maxSessionsPreventsLogin(true) // session-management/concurrency-control@error-if-maximum-exceeded .expiredUrl("/expired-session") // session-management/concurrency-control@expired-url .sessionRegistry(sessionRegistry()); // session-management/concurrency-control@session-registry-ref + // @formatter:on } @Bean @@ -219,9 +221,11 @@ public class NamespaceSessionManagementTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .sessionManagement() .invalidSessionStrategy(invalidSessionStrategy()); + // @formatter:on } @Bean @@ -250,11 +254,13 @@ public class NamespaceSessionManagementTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .sessionManagement() .sessionAuthenticationStrategy(sessionAuthenticationStrategy()) // session-management@session-authentication-strategy-ref .and() .httpBasic(); + // @formatter:on } @Bean @@ -283,11 +289,13 @@ public class NamespaceSessionManagementTests { static class SFPNoneSessionManagementConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .sessionManagement() .sessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy()) .and() .httpBasic(); + // @formatter:on } } @@ -314,10 +322,12 @@ public class NamespaceSessionManagementTests { static class SFPMigrateSessionManagementConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .sessionManagement() .and() .httpBasic(); + // @formatter:on } } @@ -338,10 +348,12 @@ public class NamespaceSessionManagementTests { static class SFPPostProcessedConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .sessionManagement() .and() .httpBasic(); + // @formatter:on } @Bean @@ -373,11 +385,13 @@ public class NamespaceSessionManagementTests { static class SFPNewSessionSessionManagementConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .sessionManagement() .sessionFixation().newSession() .and() .httpBasic(); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.java index eda13cb8b2..be0d8b9cd2 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.java @@ -63,6 +63,7 @@ public class PermitAllSupportTests { static class PermitAllConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() @@ -70,6 +71,7 @@ public class PermitAllSupportTests { .formLogin() .loginPage("/xyz").permitAll() .loginProcessingUrl("/abc?def").permitAll(); + // @formatter:on } } @@ -85,9 +87,11 @@ public class PermitAllSupportTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .formLogin() .permitAll(); + // @formatter:on } } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java index bd68d2ecec..715e079c9e 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java @@ -54,6 +54,7 @@ public class PortMapperConfigurerTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .requiresChannel() .anyRequest().requiresSecure() @@ -62,6 +63,7 @@ public class PortMapperConfigurerTests { .http(543).mapsTo(123) .and() .portMapper(); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java index c2ec1211f5..5b22f8662f 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java @@ -260,11 +260,13 @@ public class RequestCacheConfigurerTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin(); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java index 3c5d5725db..f9d5a64972 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java @@ -103,15 +103,15 @@ public class SessionManagementConfigurerServlet31Tests { @EnableWebSecurity static class SessionManagementDefaultSessionFixationServlet31Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .formLogin() .and() .sessionManagement(); + // @formatter:on } - // @formatter:on // @formatter:off @Override diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionAuthenticationStrategyTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionAuthenticationStrategyTests.java index 519b4a9703..6d4b39966f 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionAuthenticationStrategyTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionAuthenticationStrategyTests.java @@ -60,16 +60,16 @@ public class SessionManagementConfigurerSessionAuthenticationStrategyTests { static class CustomSessionAuthenticationStrategyConfig extends WebSecurityConfigurerAdapter { static SessionAuthenticationStrategy customSessionAuthenticationStrategy = mock(SessionAuthenticationStrategy.class); - // @formatter:off @Override public void configure(HttpSecurity http) throws Exception { + // @formatter:off http .formLogin() .and() .sessionManagement() .sessionAuthenticationStrategy(customSessionAuthenticationStrategy); + // @formatter:on } - // @formatter:on // @formatter:off @Override diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java index aaea0b4343..c3412a840a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java @@ -80,8 +80,10 @@ public class SessionManagementConfigurerSessionCreationPolicyTests { @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); + // @formatter:off http .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + // @formatter:on http.setSharedObject(SessionCreationPolicy.class, SessionCreationPolicy.ALWAYS); } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTransientAuthenticationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTransientAuthenticationTests.java index 184943bec6..98d863223d 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTransientAuthenticationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTransientAuthenticationTests.java @@ -70,9 +70,10 @@ public class SessionManagementConfigurerTransientAuthenticationTests { @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); - + // @formatter:off http .csrf().disable(); + // @formatter:on } @Override @@ -86,8 +87,10 @@ public class SessionManagementConfigurerTransientAuthenticationTests { static class AlwaysCreateSessionConfig extends WithTransientAuthenticationConfig { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerTests.java index 43e934c6bf..c2944260aa 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerTests.java @@ -268,6 +268,7 @@ public class OAuth2ClientConfigurerTests { static class OAuth2ClientConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() @@ -279,6 +280,7 @@ public class OAuth2ClientConfigurerTests { .authorizationCodeGrant() .authorizationRequestResolver(authorizationRequestResolver) .accessTokenResponseClient(accessTokenResponseClient); + // @formatter:on } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java index 48274c5e08..7daea6e6c6 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java @@ -617,10 +617,12 @@ public class OAuth2LoginConfigurerTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .oauth2Login() .clientRegistrationRepository( new InMemoryClientRegistrationRepository(GOOGLE_CLIENT_REGISTRATION)); + // @formatter:on super.configure(http); } @@ -658,12 +660,14 @@ public class OAuth2LoginConfigurerTests { static class OAuth2LoginConfigCustomWithConfigurer extends CommonWebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .oauth2Login() .clientRegistrationRepository( new InMemoryClientRegistrationRepository(GOOGLE_CLIENT_REGISTRATION)) .userInfoEndpoint() .userAuthoritiesMapper(createGrantedAuthoritiesMapper()); + // @formatter:on super.configure(http); } } @@ -672,8 +676,10 @@ public class OAuth2LoginConfigurerTests { static class OAuth2LoginConfigCustomWithBeanRegistration extends CommonWebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .oauth2Login(); + // @formatter:on super.configure(http); } @@ -692,6 +698,7 @@ public class OAuth2LoginConfigurerTests { static class OAuth2LoginConfigCustomUserServiceBeanRegistration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() @@ -702,6 +709,7 @@ public class OAuth2LoginConfigurerTests { .oauth2Login() .tokenEndpoint() .accessTokenResponseClient(createOauth2AccessTokenResponseClient()); + // @formatter:on } @Bean @@ -739,11 +747,13 @@ public class OAuth2LoginConfigurerTests { static class OAuth2LoginConfigLoginProcessingUrl extends CommonWebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .oauth2Login() .clientRegistrationRepository( new InMemoryClientRegistrationRepository(GOOGLE_CLIENT_REGISTRATION)) .loginProcessingUrl("/login/oauth2/*"); + // @formatter:on super.configure(http); } } @@ -757,11 +767,13 @@ public class OAuth2LoginConfigurerTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .oauth2Login() .clientRegistrationRepository(this.clientRegistrationRepository) .authorizationEndpoint() .authorizationRequestResolver(this.resolver); + // @formatter:on super.configure(http); } } @@ -775,6 +787,7 @@ public class OAuth2LoginConfigurerTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .oauth2Login(oauth2Login -> oauth2Login @@ -784,6 +797,7 @@ public class OAuth2LoginConfigurerTests { .authorizationRequestResolver(this.resolver) ) ); + // @formatter:on super.configure(http); } } @@ -792,11 +806,13 @@ public class OAuth2LoginConfigurerTests { static class OAuth2LoginConfigMultipleClients extends CommonWebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .oauth2Login() .clientRegistrationRepository( new InMemoryClientRegistrationRepository( GOOGLE_CLIENT_REGISTRATION, GITHUB_CLIENT_REGISTRATION)); + // @formatter:on super.configure(http); } } @@ -805,11 +821,13 @@ public class OAuth2LoginConfigurerTests { static class OAuth2LoginConfigCustomLoginPage extends CommonWebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .oauth2Login() .clientRegistrationRepository( new InMemoryClientRegistrationRepository(GOOGLE_CLIENT_REGISTRATION)) .loginPage("/custom-login"); + // @formatter:on super.configure(http); } } @@ -835,9 +853,11 @@ public class OAuth2LoginConfigurerTests { static class OAuth2LoginConfigWithOidcLogoutSuccessHandler extends CommonWebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .logout() .logoutSuccessHandler(oidcLogoutSuccessHandler()); + // @formatter:on super.configure(http); } @@ -859,6 +879,7 @@ public class OAuth2LoginConfigurerTests { private static abstract class CommonWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() @@ -873,6 +894,7 @@ public class OAuth2LoginConfigurerTests { .userInfoEndpoint() .userService(createOauth2UserService()) .oidcUserService(createOidcUserService()); + // @formatter:on } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java index cf552a6ece..957c383d96 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java @@ -1761,7 +1761,6 @@ public class OAuth2ResourceServerConfigurerTests { @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off - http .authorizeRequests() .anyRequest().authenticated() @@ -1769,7 +1768,6 @@ public class OAuth2ResourceServerConfigurerTests { .oauth2ResourceServer() .jwt() .jwtAuthenticationConverter(getJwtAuthenticationConverter()); - // @formatter:on } @@ -1783,7 +1781,6 @@ public class OAuth2ResourceServerConfigurerTests { @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off - http .authorizeRequests() .antMatchers("/requires-read-scope").access("hasAuthority('message:read')") @@ -1791,7 +1788,6 @@ public class OAuth2ResourceServerConfigurerTests { .oauth2ResourceServer() .jwt() .jwtAuthenticationConverter(getJwtAuthenticationConverter()); - // @formatter:on } @@ -2255,6 +2251,7 @@ public class OAuth2ResourceServerConfigurerTests { .jwt() .and() .opaqueToken(); + // @formatter:on } } @@ -2306,6 +2303,7 @@ public class OAuth2ResourceServerConfigurerTests { .oauth2ResourceServer() .authenticationManagerResolver(mock(AuthenticationManagerResolver.class)) .opaqueToken(); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java index d4be974be4..598f5bf09c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java @@ -300,11 +300,13 @@ public class Saml2LoginConfigurerTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests(authz -> authz .anyRequest().authenticated() ) .saml2Login(withDefaults()); + // @formatter:on } @Bean @@ -319,11 +321,13 @@ public class Saml2LoginConfigurerTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests(authz -> authz .anyRequest().authenticated() ) .saml2Login(saml2 -> {}); + // @formatter:on } @Bean diff --git a/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java index c26ec69d11..d62e1f8821 100644 --- a/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java +++ b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java @@ -165,9 +165,11 @@ public class GrantedAuthorityDefaultsJcTests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().access("hasRole('USER')"); + // @formatter:on } @Bean diff --git a/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomConfigurer.java b/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomConfigurer.java index d377d0dc35..cf2f5bace0 100644 --- a/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomConfigurer.java +++ b/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomConfigurer.java @@ -42,17 +42,19 @@ public class CustomConfigurer extends SecurityConfigurerAdapter c.requestCache(this.requestCache)); + // @formatter:on return http.build(); } } @@ -274,6 +278,7 @@ public class OAuth2ClientSpecTests { @Bean public SecurityWebFilterChain springSecurityFilter(ServerHttpSecurity http) { + // @formatter:off http .oauth2Client(oauth2Client -> oauth2Client @@ -281,6 +286,7 @@ public class OAuth2ClientSpecTests { .authenticationManager(this.manager) .authorizationRequestRepository(this.authorizationRequestRepository)) .requestCache(c -> c.requestCache(this.requestCache)); + // @formatter:on return http.build(); } } diff --git a/config/src/test/java/org/springframework/security/config/web/server/OAuth2LoginTests.java b/config/src/test/java/org/springframework/security/config/web/server/OAuth2LoginTests.java index b1e5662a3e..d8ab7c8481 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/OAuth2LoginTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/OAuth2LoginTests.java @@ -253,12 +253,14 @@ public class OAuth2LoginTests { @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { + // @formatter:off http .requestCache() .requestCache(this.requestCache) .and() .oauth2Login() .authorizationRequestRepository(this.authorizationRequestRepository); + // @formatter:on return http.build(); } @@ -395,6 +397,7 @@ public class OAuth2LoginTests { @Bean public SecurityWebFilterChain springSecurityFilter(ServerHttpSecurity http) { + // @formatter:off http .authorizeExchange() .anyExchange().authenticated() @@ -406,6 +409,7 @@ public class OAuth2LoginTests { .authorizationRequestResolver(resolver) .authenticationSuccessHandler(successHandler) .authenticationFailureHandler(failureHandler); + // @formatter:on return http.build(); } } @@ -474,6 +478,7 @@ public class OAuth2LoginTests { @Bean public SecurityWebFilterChain springSecurityFilter(ServerHttpSecurity http) { + // @formatter:off http .authorizeExchange(exchanges -> exchanges @@ -487,6 +492,7 @@ public class OAuth2LoginTests { .authorizationRequestResolver(resolver) .authenticationSuccessHandler(successHandler) ); + // @formatter:on return http.build(); } } @@ -715,7 +721,7 @@ public class OAuth2LoginTests { @Bean public SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { - + // @formatter:off http .csrf().disable() .logout() @@ -726,7 +732,7 @@ public class OAuth2LoginTests { new InMemoryReactiveClientRegistrationRepository(this.withLogout))) .and() .securityContextRepository(this.repository); - + // @formatter:on return http.build(); } diff --git a/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java b/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java index 943fe62d71..f0e1f3765a 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java @@ -486,8 +486,6 @@ public class OAuth2ResourceServerSpecTests { .jwt() .publicKey(publicKey()); // @formatter:on - - return http.build(); } } @@ -511,7 +509,6 @@ public class OAuth2ResourceServerSpecTests { ) ); // @formatter:on - return http.build(); } } @@ -533,8 +530,6 @@ public class OAuth2ResourceServerSpecTests { .jwt() .publicKey(this.key); // @formatter:on - - return http.build(); } } @@ -877,6 +872,7 @@ public class OAuth2ResourceServerSpecTests { .oauth2ResourceServer() .authenticationManagerResolver(mock(ReactiveAuthenticationManagerResolver.class)) .opaqueToken(); + // @formatter:on return http.build(); } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/Sec2935Tests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/Sec2935Tests.java index 03499732a8..58633511ce 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/Sec2935Tests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/Sec2935Tests.java @@ -148,12 +148,14 @@ public class Sec2935Tests { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .httpBasic(); + // @formatter:on } @Autowired diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests.java index d0a00f5cdd..e4d84b99d9 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests.java @@ -72,16 +72,15 @@ public class SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests { @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); - + // @formatter:off http .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); + // @formatter:on } - // @formatter:on // @formatter:off @Autowired diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2ClientTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2ClientTests.java index 13450d318f..0f2b0e75ff 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2ClientTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2ClientTests.java @@ -165,11 +165,13 @@ public class SecurityMockMvcRequestPostProcessorsOAuth2ClientTests { static class OAuth2ClientConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests(authz -> authz .anyRequest().permitAll() ) .oauth2Client(); + // @formatter:on } @Bean diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2LoginTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2LoginTests.java index 52e8941eaf..deb4d0bb9d 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2LoginTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2LoginTests.java @@ -167,11 +167,13 @@ public class SecurityMockMvcRequestPostProcessorsOAuth2LoginTests { static class OAuth2LoginConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests(authorize -> authorize .mvcMatchers("/admin/**").hasAuthority("SCOPE_admin") .anyRequest().hasAuthority("SCOPE_read") ).oauth2Login(); + // @formatter:on } @Bean diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOidcLoginTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOidcLoginTests.java index 4728d78a4d..6171c335f5 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOidcLoginTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOidcLoginTests.java @@ -173,12 +173,14 @@ public class SecurityMockMvcRequestPostProcessorsOidcLoginTests { static class OAuth2LoginConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .mvcMatchers("/admin/**").hasAuthority("SCOPE_admin") .anyRequest().hasAuthority("SCOPE_read") .and() .oauth2Login(); + // @formatter:on } @Bean diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOpaqueTokenTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOpaqueTokenTests.java index 041a4d2e0f..572b672e81 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOpaqueTokenTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOpaqueTokenTests.java @@ -130,6 +130,7 @@ public class SecurityMockMvcRequestPostProcessorsOpaqueTokenTests { static class OAuth2LoginConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .mvcMatchers("/admin/**").hasAuthority("SCOPE_admin") @@ -138,6 +139,7 @@ public class SecurityMockMvcRequestPostProcessorsOpaqueTokenTests { .oauth2ResourceServer() .opaqueToken() .introspector(mock(OpaqueTokenIntrospector.class)); + // @formatter:on } @RestController diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTests.java index a82709e4ad..b957c7c98e 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTests.java @@ -72,16 +72,15 @@ public class SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTes @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); - + // @formatter:off http .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); + // @formatter:on } - // @formatter:on // @formatter:off @Autowired diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CustomCsrfShowcaseTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CustomCsrfShowcaseTests.java index dfcdf91bfc..8ce1ec6637 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CustomCsrfShowcaseTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CustomCsrfShowcaseTests.java @@ -74,14 +74,14 @@ public class CustomCsrfShowcaseTests { @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .csrf() .csrfTokenRepository(repo()); + // @formatter:on } - // @formatter:on // @formatter:off @Autowired diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomConfigAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomConfigAuthenticationTests.java index c2a45bc74e..eedcc107fc 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomConfigAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomConfigAuthenticationTests.java @@ -91,9 +91,9 @@ public class CustomConfigAuthenticationTests { @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() @@ -105,8 +105,8 @@ public class CustomConfigAuthenticationTests { .usernameParameter("user") .passwordParameter("pass") .loginPage("/authenticate"); + // @formatter:on } - // @formatter:on // @formatter:off @Bean diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomLoginRequestBuilderAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomLoginRequestBuilderAuthenticationTests.java index 820f66d49a..821efe3b88 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomLoginRequestBuilderAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomLoginRequestBuilderAuthenticationTests.java @@ -81,9 +81,9 @@ public class CustomLoginRequestBuilderAuthenticationTests { @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .anyRequest().authenticated() @@ -92,8 +92,8 @@ public class CustomLoginRequestBuilderAuthenticationTests { .usernameParameter("user") .passwordParameter("pass") .loginPage("/authenticate"); + // @formatter:on } - // @formatter:on // @formatter:off @Bean diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/DefaultfSecurityRequestsTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/DefaultfSecurityRequestsTests.java index ea580da186..a1bf100d43 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/DefaultfSecurityRequestsTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/DefaultfSecurityRequestsTests.java @@ -85,17 +85,17 @@ public class DefaultfSecurityRequestsTests { @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .httpBasic(); + // @formatter:on } - // @formatter:on // @formatter:off @Autowired diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/SecurityRequestsTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/SecurityRequestsTests.java index e1bb963c04..226197aa38 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/SecurityRequestsTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/SecurityRequestsTests.java @@ -103,17 +103,17 @@ public class SecurityRequestsTests { @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .formLogin(); + // @formatter:on } - // @formatter:on // @formatter:off @Autowired diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserAuthenticationTests.java index 46b6df9861..cfdc27f7af 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserAuthenticationTests.java @@ -87,17 +87,17 @@ public class WithUserAuthenticationTests { @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .formLogin(); + // @formatter:on } - // @formatter:on // @formatter:off @Autowired diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserClassLevelAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserClassLevelAuthenticationTests.java index 7ebb3e4c51..951245aa12 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserClassLevelAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserClassLevelAuthenticationTests.java @@ -87,17 +87,17 @@ public class WithUserClassLevelAuthenticationTests { @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .httpBasic(); + // @formatter:on } - // @formatter:on // @formatter:off @Autowired diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsAuthenticationTests.java index 75ea96fcdd..5d89232bc8 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsAuthenticationTests.java @@ -79,17 +79,17 @@ public class WithUserDetailsAuthenticationTests { @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .formLogin(); + // @formatter:on } - // @formatter:on @Bean @Override diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsClassLevelAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsClassLevelAuthenticationTests.java index 56b2f324b8..23c19d12b6 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsClassLevelAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsClassLevelAuthenticationTests.java @@ -79,17 +79,17 @@ public class WithUserDetailsClassLevelAuthenticationTests { @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .formLogin(); + // @formatter:on } - // @formatter:on @Bean @Override diff --git a/test/src/test/java/org/springframework/security/test/web/support/WebTestUtilsTests.java b/test/src/test/java/org/springframework/security/test/web/support/WebTestUtilsTests.java index c7aead4ed9..914eb046b5 100644 --- a/test/src/test/java/org/springframework/security/test/web/support/WebTestUtilsTests.java +++ b/test/src/test/java/org/springframework/security/test/web/support/WebTestUtilsTests.java @@ -189,29 +189,29 @@ public class WebTestUtilsTests { static CsrfTokenRepository CSRF_REPO; static SecurityContextRepository CONTEXT_REPO; - // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { + // @formatter:off http .csrf() .csrfTokenRepository(CSRF_REPO) .and() .securityContext() .securityContextRepository(CONTEXT_REPO); + // @formatter:on } - // @formatter:on } @EnableWebSecurity static class PartialSecurityConfig extends WebSecurityConfigurerAdapter { - // @formatter:off @Override public void configure(HttpSecurity http) { + // @formatter:off http .antMatcher("/willnotmatchthis"); + // @formatter:on } - // @formatter:on } @Configuration From 63b5998fadd3c3e016106a43a68bc3d827966356 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 23 Jul 2020 12:58:41 -0700 Subject: [PATCH 03/84] Add noformat blocks around auth config Find `auth` config using a regex search of `^\s*auths*$` and protect them against formatting. Issue gh-8945 --- ...onProviderBuilderSecurityBuilderTests.java | 28 +++++++++---------- ...AuthenticationProviderConfigurerTests.java | 14 ++++++---- ...dapAuthenticationProviderTestsConfigs.java | 16 +++++------ .../AuthenticationManagerBuilderTests.java | 4 +++ .../BaseAuthenticationConfig.java | 2 ++ .../NamespaceAuthenticationManagerTests.java | 6 ++++ .../NamespaceAuthenticationProviderTests.java | 4 +++ .../NamespaceJdbcUserServiceTests.java | 4 +++ .../NamespacePasswordEncoderTests.java | 6 ++++ .../PasswordEncoderConfigurerTests.java | 8 +++--- .../AuthenticationConfigurationTests.java | 2 ++ ...lobalMethodSecurityConfigurationTests.java | 2 ++ ...SampleEnableGlobalMethodSecurityTests.java | 4 +++ ...mpleWebSecurityConfigurerAdapterTests.java | 6 ++++ ...curityConfigurerAdapterPowermockTests.java | 2 ++ .../WebSecurityConfigurerAdapterTests.java | 10 +++++++ .../web/builders/HttpConfigurationTests.java | 2 ++ .../web/builders/NamespaceHttpTests.java | 2 ++ ...icationPrincipalArgumentResolverTests.java | 2 ++ .../configuration/EnableWebSecurityTests.java | 2 ++ .../HttpSecurityAntMatchersTests.java | 4 +++ .../configurers/HttpSecurityLogoutTests.java | 2 ++ .../NamespaceHttpExpressionHandlerTests.java | 2 ++ .../NamespaceHttpInterceptUrlTests.java | 2 ++ .../NamespaceHttpPortMappingsTests.java | 2 ++ .../NamespaceHttpRequestCacheTests.java | 4 +++ .../configurers/NamespaceHttpX509Tests.java | 10 +++++++ .../configurers/NamespaceRememberMeTests.java | 2 ++ ...ionManagementConfigurerServlet31Tests.java | 4 +-- ...rerSessionAuthenticationStrategyTests.java | 4 +-- ...onfigurerTransientAuthenticationTests.java | 2 ++ .../core/GrantedAuthorityDefaultsJcTests.java | 2 ++ .../showcase/WithMockUserParentTests.java | 4 +-- .../context/showcase/WithMockUserTests.java | 4 +-- .../showcase/WithUserDetailsTests.java | 4 +-- ...rocessorsAuthenticationStatelessTests.java | 4 +-- ...sorsTestSecurityContextStatelessTests.java | 4 +-- .../showcase/csrf/CsrfShowcaseTests.java | 4 +-- .../csrf/CustomCsrfShowcaseTests.java | 4 +-- .../csrf/DefaultCsrfShowcaseTests.java | 4 +-- .../DefaultfSecurityRequestsTests.java | 4 +-- .../secured/SecurityRequestsTests.java | 4 +-- .../secured/WithUserAuthenticationTests.java | 4 +-- ...WithUserClassLevelAuthenticationTests.java | 4 +-- .../WithUserDetailsAuthenticationTests.java | 4 +-- ...rDetailsClassLevelAuthenticationTests.java | 4 +-- 46 files changed, 158 insertions(+), 64 deletions(-) diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java index 9ff0675bc2..42736b22e4 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java @@ -74,14 +74,14 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { @EnableWebSecurity static class DefaultLdapConfig extends BaseLdapProviderConfig { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .contextSource(contextSource()) .userDnPatterns("uid={0},ou=people"); + // @formatter:on } - // @formatter:on } @Test @@ -94,15 +94,15 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { @EnableWebSecurity static class GroupRolesConfig extends BaseLdapProviderConfig { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .contextSource(contextSource()) .userDnPatterns("uid={0},ou=people") .groupRoleAttribute("group"); + // @formatter:on } - // @formatter:on } @Test @@ -115,15 +115,15 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { @EnableWebSecurity static class GroupSearchConfig extends BaseLdapProviderConfig { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .contextSource(contextSource()) .userDnPatterns("uid={0},ou=people") .groupSearchFilter("ou=groupName"); + // @formatter:on } - // @formatter:on } @Test @@ -137,16 +137,16 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { @EnableWebSecurity static class GroupSubtreeSearchConfig extends BaseLdapProviderConfig { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .contextSource(contextSource()) .userDnPatterns("uid={0},ou=people") .groupSearchFilter("ou=groupName") .groupSearchSubtree(true); + // @formatter:on } - // @formatter:on } @Test @@ -159,15 +159,15 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { @EnableWebSecurity static class RolePrefixConfig extends BaseLdapProviderConfig { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .contextSource(contextSource()) .userDnPatterns("uid={0},ou=people") .rolePrefix("role_"); + // @formatter:on } - // @formatter:on } @Test @@ -180,16 +180,16 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { @EnableWebSecurity static class BindAuthenticationConfig extends BaseLdapServerConfig { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .contextSource(contextSource()) .groupSearchBase("ou=groups") .groupSearchFilter("(member={0})") .userDnPatterns("uid={0},ou=people"); + // @formatter:on } - // @formatter:on } // SEC-2472 @@ -203,8 +203,8 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { @EnableWebSecurity static class PasswordEncoderConfig extends BaseLdapServerConfig { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .contextSource(contextSource()) @@ -212,8 +212,8 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { .groupSearchBase("ou=groups") .groupSearchFilter("(member={0})") .userDnPatterns("uid={0},ou=people"); + // @formatter:on } - // @formatter:on } private LdapAuthenticationProvider ldapProvider() { diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.java index 3cf29d6338..ab5960f1c4 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.java @@ -83,8 +83,8 @@ public class LdapAuthenticationProviderConfigurerTests { @EnableWebSecurity static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .groupSearchBase("ou=groups") @@ -95,14 +95,14 @@ public class LdapAuthenticationProviderConfigurerTests { .groupSearchBase("ou=groups") .groupSearchFilter("(member={0})") .userDnPatterns("uid={0},ou=people"); + // @formatter:on } - // @formatter:on } @EnableWebSecurity static class MultiLdapWithCustomRolePrefixAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .groupSearchBase("ou=groups") @@ -115,14 +115,15 @@ public class LdapAuthenticationProviderConfigurerTests { .groupSearchFilter("(member={0})") .userDnPatterns("uid={0},ou=people") .rolePrefix("RUOLO_"); + // @formatter:on } - // @formatter:on } @EnableWebSecurity static class LdapWithRandomPortConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .groupSearchBase("ou=groups") @@ -130,20 +131,21 @@ public class LdapAuthenticationProviderConfigurerTests { .userDnPatterns("uid={0},ou=people") .contextSource() .port(0); + // @formatter:on } } @EnableWebSecurity static class GroupSubtreeSearchConfig extends BaseLdapProviderConfig { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .groupSearchBase("ou=groups") .groupSearchFilter("(member={0})") .groupSearchSubtree(true) .userDnPatterns("uid={0},ou=people"); + // @formatter:on } - // @formatter:on } } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java index c349ce6a1b..d73fb3a801 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java @@ -29,21 +29,21 @@ import org.springframework.security.ldap.userdetails.PersonContextMapper; public class NamespaceLdapAuthenticationProviderTestsConfigs { @EnableWebSecurity static class LdapAuthenticationProviderConfig extends WebSecurityConfigurerAdapter { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .groupSearchBase("ou=groups") .userDnPatterns("uid={0},ou=people"); // ldap-server@user-dn-pattern + // @formatter:on } - // @formatter:on } @EnableWebSecurity static class CustomLdapAuthenticationProviderConfig extends WebSecurityConfigurerAdapter { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .groupRoleAttribute("cn") // ldap-authentication-provider@group-role-attribute @@ -63,28 +63,28 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs { .root("dc=springframework,dc=org") // ldap-server@root // .url("ldap://localhost:33389/dc-springframework,dc=org") this overrides root and port and is used for external ; + // @formatter:on } - // @formatter:on } @EnableWebSecurity static class CustomAuthoritiesPopulatorConfig extends WebSecurityConfigurerAdapter { static LdapAuthoritiesPopulator LAP; - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .userSearchFilter("(uid={0})") .ldapAuthoritiesPopulator(LAP); + // @formatter:on } - // @formatter:on } @EnableWebSecurity static class PasswordCompareLdapConfig extends WebSecurityConfigurerAdapter { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .ldapAuthentication() .groupSearchBase("ou=groups") @@ -92,7 +92,7 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs { .passwordCompare() .passwordEncoder(new BCryptPasswordEncoder()) // ldap-authentication-provider/password-compare/password-encoder@ref .passwordAttribute("userPassword"); // ldap-authentication-provider/password-compare@password-attribute + // @formatter:on } - // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java index 6b02c0cb3f..6fac5b0e29 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java @@ -113,9 +113,11 @@ public class AuthenticationManagerBuilderTests { static class PasswordEncoderGlobalConfig extends WebSecurityConfigurerAdapter { @Autowired void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); + // @formatter:on } @Bean @@ -139,9 +141,11 @@ public class AuthenticationManagerBuilderTests { @EnableWebSecurity static class PasswordEncoderConfig extends WebSecurityConfigurerAdapter { protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); + // @formatter:on } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/BaseAuthenticationConfig.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/BaseAuthenticationConfig.java index 172d463d46..b2546aee46 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/BaseAuthenticationConfig.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/BaseAuthenticationConfig.java @@ -28,9 +28,11 @@ import org.springframework.security.config.annotation.authentication.builders.Au public class BaseAuthenticationConfig { @Autowired protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER").and() .withUser("admin").password("password").roles("USER", "ADMIN"); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.java index 31c48eca29..cab352ce61 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.java @@ -55,9 +55,11 @@ public class NamespaceAuthenticationManagerTests { static class EraseCredentialsTrueDefaultConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } } @@ -77,10 +79,12 @@ public class NamespaceAuthenticationManagerTests { static class EraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter { @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .eraseCredentials(false) .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } } @@ -97,10 +101,12 @@ public class NamespaceAuthenticationManagerTests { static class GlobalEraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .eraseCredentials(false) .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java index b26b9fc2c6..d4ec0812ca 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java @@ -56,8 +56,10 @@ public class NamespaceAuthenticationProviderTests { @EnableWebSecurity static class AuthenticationProviderRefConfig extends WebSecurityConfigurerAdapter { protected void configure(AuthenticationManagerBuilder auth) { + // @formatter:off auth .authenticationProvider(authenticationProvider()); + // @formatter:on } @Bean @@ -80,8 +82,10 @@ public class NamespaceAuthenticationProviderTests { @EnableWebSecurity static class UserServiceRefConfig extends WebSecurityConfigurerAdapter { protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .userDetailsService(userDetailsService()); + // @formatter:on } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.java index b1242b5a3f..8e17e22a47 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.java @@ -63,11 +63,13 @@ public class NamespaceJdbcUserServiceTests { private DataSource dataSource; protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .jdbcAuthentication() .withDefaultSchema() .withUser(PasswordEncodedUser.user()) .dataSource(this.dataSource); // jdbc-user-service@data-source-ref + // @formatter:on } } @@ -94,6 +96,7 @@ public class NamespaceJdbcUserServiceTests { private DataSource dataSource; protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .jdbcAuthentication() // jdbc-user-service@dataSource @@ -108,6 +111,7 @@ public class NamespaceJdbcUserServiceTests { .groupAuthoritiesByUsername(JdbcUserDetailsManager.DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY) // jdbc-user-service@role-prefix .rolePrefix("ROLE_"); + // @formatter:on } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.java index d8c2ce0ccc..61a34154e5 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.java @@ -61,10 +61,12 @@ public class NamespacePasswordEncoderTests { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password(encoder.encode("password")).roles("USER").and() .passwordEncoder(encoder); + // @formatter:on } } @@ -82,12 +84,14 @@ public class NamespacePasswordEncoderTests { protected void configure(AuthenticationManagerBuilder auth) throws Exception { BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + // @formatter:off auth .jdbcAuthentication() .withDefaultSchema() .dataSource(dataSource()) .withUser("user").password(encoder.encode("password")).roles("USER").and() .passwordEncoder(encoder); + // @formatter:on } @Bean @@ -116,9 +120,11 @@ public class NamespacePasswordEncoderTests { .roles("USER") .build(); InMemoryUserDetailsManager uds = new InMemoryUserDetailsManager(user); + // @formatter:off auth .userDetailsService(uds) .passwordEncoder(encoder); + // @formatter:on } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.java index e145d411c5..2b2287b4f2 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.java @@ -49,15 +49,15 @@ public class PasswordEncoderConfigurerTests { @EnableWebSecurity static class PasswordEncoderConfig extends WebSecurityConfigurerAdapter { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { BCryptPasswordEncoder encoder = passwordEncoder(); + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password(encoder.encode("password")).roles("USER").and() .passwordEncoder(encoder); + // @formatter:on } - // @formatter:on @Override protected void configure(HttpSecurity http) { @@ -80,15 +80,15 @@ public class PasswordEncoderConfigurerTests { @EnableWebSecurity static class PasswordEncoderNoAuthManagerLoadsConfig extends WebSecurityConfigurerAdapter { - // @formatter:off protected void configure(AuthenticationManagerBuilder auth) throws Exception { BCryptPasswordEncoder encoder = passwordEncoder(); + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password(encoder.encode("password")).roles("USER").and() .passwordEncoder(encoder); + // @formatter:on } - // @formatter:on @Bean public BCryptPasswordEncoder passwordEncoder() { diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java index 3ba459170f..14546c85f7 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java @@ -241,9 +241,11 @@ public class AuthenticationConfigurationTests { static class ConfiguresInMemoryConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { public void init(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java index 221a63d24c..902af21b20 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java @@ -134,8 +134,10 @@ public class GlobalMethodSecurityConfigurationTests { public static class InMemoryAuthWithGlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication(); + // @formatter:on } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.java index ea690af732..13ffa15645 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.java @@ -74,10 +74,12 @@ public class SampleEnableGlobalMethodSecurityTests { @Autowired protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER").and() .withUser("admin").password("password").roles("USER", "ADMIN"); + // @formatter:on } } @@ -109,10 +111,12 @@ public class SampleEnableGlobalMethodSecurityTests { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER").and() .withUser("admin").password("password").roles("USER", "ADMIN"); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java index 218f261433..760152d496 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java @@ -135,9 +135,11 @@ public class SampleWebSecurityConfigurerAdapterTests { public static class HelloWorldWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } } @@ -233,10 +235,12 @@ public class SampleWebSecurityConfigurerAdapterTests { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()) .withUser(PasswordEncodedUser.admin()); + // @formatter:on } } @@ -346,10 +350,12 @@ public class SampleWebSecurityConfigurerAdapterTests { public static class SampleMultiHttpSecurityConfig { @Autowired protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()) .withUser(PasswordEncodedUser.admin()); + // @formatter:on } @Configuration diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterPowermockTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterPowermockTests.java index c35cdb39fe..a0643fcf3f 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterPowermockTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterPowermockTests.java @@ -146,9 +146,11 @@ public class WebSecurityConfigurerAdapterPowermockTests { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } @Override diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.java index 8f784aa513..4d8bf244d1 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.java @@ -96,9 +96,11 @@ public class WebSecurityConfigurerAdapterTests { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } @Override @@ -125,9 +127,11 @@ public class WebSecurityConfigurerAdapterTests { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } @Override @@ -152,9 +156,11 @@ public class WebSecurityConfigurerAdapterTests { static class InMemoryConfigureProtectedConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } @Override @@ -180,9 +186,11 @@ public class WebSecurityConfigurerAdapterTests { static class InMemoryConfigureGlobalConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } @Override @@ -283,9 +291,11 @@ public class WebSecurityConfigurerAdapterTests { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java index 00fa2b4e96..620abd0367 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java @@ -75,9 +75,11 @@ public class HttpConfigurationTests { } protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java index d94e54403e..a5a33c4fe5 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java @@ -479,9 +479,11 @@ public class NamespaceHttpTests { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/AuthenticationPrincipalArgumentResolverTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/AuthenticationPrincipalArgumentResolverTests.java index 9392335bb8..021865f318 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/AuthenticationPrincipalArgumentResolverTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/AuthenticationPrincipalArgumentResolverTests.java @@ -79,8 +79,10 @@ public class AuthenticationPrincipalArgumentResolverTests { static class Config { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication(); + // @formatter:off } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java index fd77bea5d5..35dac47b9c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java @@ -64,9 +64,11 @@ public class EnableWebSecurityTests { static class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } @Bean diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java index 29184b43ec..45836760f6 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java @@ -90,8 +90,10 @@ public class HttpSecurityAntMatchersTests { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication(); + // @formatter:on } } @@ -123,8 +125,10 @@ public class HttpSecurityAntMatchersTests { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication(); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java index 673705ef3a..e7a80a6e7b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java @@ -95,8 +95,10 @@ public class HttpSecurityLogoutTests { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication(); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java index 3c5af7d6e9..7bea9d6eac 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java @@ -77,9 +77,11 @@ public class NamespaceHttpExpressionHandlerTests { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("rod").password("password").roles("USER", "ADMIN"); + // @formatter:on } @Override diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java index 76aa167d30..bea987ff28 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java @@ -147,10 +147,12 @@ public class NamespaceHttpInterceptUrlTests { } protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER").and() .withUser("admin").password("password").roles("USER", "ADMIN"); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.java index f742f4c9e9..062d561a06 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.java @@ -79,10 +79,12 @@ public class NamespaceHttpPortMappingsTests { } protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER").and() .withUser("admin").password("password").roles("USER", "ADMIN"); + // @formatter:on } } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java index ac895fc284..4504f74d6f 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java @@ -78,10 +78,12 @@ public class NamespaceHttpRequestCacheTests { } protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()) .withUser(PasswordEncodedUser.admin()); + // @formatter:on } @Bean @@ -114,10 +116,12 @@ public class NamespaceHttpRequestCacheTests { } protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()) .withUser(PasswordEncodedUser.admin()); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java index 6f9d7d7cc4..f77c04facd 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java @@ -81,9 +81,11 @@ public class NamespaceHttpX509Tests { public static class X509Config extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("rod").password("password").roles("USER", "ADMIN"); + // @formatter:on } @Override @@ -114,9 +116,11 @@ public class NamespaceHttpX509Tests { static class AuthenticationDetailsSourceRefConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("rod").password("password").roles("USER", "ADMIN"); + // @formatter:on } @Override @@ -152,9 +156,11 @@ public class NamespaceHttpX509Tests { public static class SubjectPrincipalRegexConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("rod").password("password").roles("USER", "ADMIN"); + // @formatter:on } @Override @@ -183,9 +189,11 @@ public class NamespaceHttpX509Tests { public static class CustomPrincipalExtractorConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("rod@example.com").password("password").roles("USER", "ADMIN"); + // @formatter:on } @Override @@ -222,9 +230,11 @@ public class NamespaceHttpX509Tests { public static class UserDetailsServiceRefConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("rod").password("password").roles("USER", "ADMIN"); + // @formatter:on } @Override diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java index b1e03fe1d7..41673a98cb 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java @@ -441,8 +441,10 @@ public class NamespaceRememberMeTests { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .userDetailsService(USERDETAILS_SERVICE); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java index f9d5a64972..cd8d78f5bf 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java @@ -113,14 +113,14 @@ public class SessionManagementConfigurerServlet31Tests { // @formatter:on } - // @formatter:off @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } - // @formatter:on } private void loadConfig(Class... classes) { diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionAuthenticationStrategyTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionAuthenticationStrategyTests.java index 6d4b39966f..eb8f2d0e02 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionAuthenticationStrategyTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionAuthenticationStrategyTests.java @@ -71,13 +71,13 @@ public class SessionManagementConfigurerSessionAuthenticationStrategyTests { // @formatter:on } - // @formatter:off @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser(PasswordEncodedUser.user()); + // @formatter:on } - // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTransientAuthenticationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTransientAuthenticationTests.java index 98d863223d..b8f99f009c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTransientAuthenticationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTransientAuthenticationTests.java @@ -78,8 +78,10 @@ public class SessionManagementConfigurerTransientAuthenticationTests { @Override protected void configure(AuthenticationManagerBuilder auth) { + // @formatter:off auth .authenticationProvider(new TransientAuthenticationProvider()); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java index d62e1f8821..dcf6e5995f 100644 --- a/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java +++ b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java @@ -158,9 +158,11 @@ public class GrantedAuthorityDefaultsJcTests { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); + // @formatter:on } @Override diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserParentTests.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserParentTests.java index 0f25882073..a15edc44d6 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserParentTests.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserParentTests.java @@ -48,13 +48,13 @@ public class WithMockUserParentTests extends WithMockUserParent { @EnableGlobalMethodSecurity(prePostEnabled = true) @ComponentScan(basePackageClasses = HelloMessageService.class) static class Config { - // @formatter:off @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); + // @formatter:on } - // @formatter:on } } \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java index eafe930b31..a525f310b5 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java @@ -77,13 +77,13 @@ public class WithMockUserTests { @EnableGlobalMethodSecurity(prePostEnabled = true) @ComponentScan(basePackageClasses = HelloMessageService.class) static class Config { - // @formatter:off @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); + // @formatter:on } - // @formatter:on } } \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java index 55a8af3d38..8143f4f01a 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java @@ -77,13 +77,13 @@ public class WithUserDetailsTests { @EnableGlobalMethodSecurity(prePostEnabled = true) @ComponentScan(basePackageClasses = HelloMessageService.class) static class Config { - // @formatter:off @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .userDetailsService(myUserDetailsService()); + // @formatter:on } - // @formatter:on @Bean public UserDetailsService myUserDetailsService() { diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests.java index e4d84b99d9..51c92c5032 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests.java @@ -82,13 +82,13 @@ public class SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests { // @formatter:on } - // @formatter:off @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication(); + // @formatter:on } - // @formatter:on @RestController static class Controller { diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTests.java index b957c7c98e..cc01f37ac1 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTests.java @@ -82,13 +82,13 @@ public class SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTes // @formatter:on } - // @formatter:off @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication(); + // @formatter:on } - // @formatter:on @RestController static class Controller { diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CsrfShowcaseTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CsrfShowcaseTests.java index bf5f71edfe..b61a4247ef 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CsrfShowcaseTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CsrfShowcaseTests.java @@ -75,13 +75,13 @@ public class CsrfShowcaseTests { protected void configure(HttpSecurity http) { } - // @formatter:off @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); + // @formatter:on } - // @formatter:on } } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CustomCsrfShowcaseTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CustomCsrfShowcaseTests.java index 8ce1ec6637..ad66e089a1 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CustomCsrfShowcaseTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CustomCsrfShowcaseTests.java @@ -83,14 +83,14 @@ public class CustomCsrfShowcaseTests { // @formatter:on } - // @formatter:off @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); + // @formatter:on } - // @formatter:on @Bean public CsrfTokenRepository repo() { diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/DefaultCsrfShowcaseTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/DefaultCsrfShowcaseTests.java index 4554ca660d..42081d209f 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/DefaultCsrfShowcaseTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/DefaultCsrfShowcaseTests.java @@ -70,13 +70,13 @@ public class DefaultCsrfShowcaseTests { protected void configure(HttpSecurity http) { } - // @formatter:off @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); + // @formatter:on } - // @formatter:on } } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/DefaultfSecurityRequestsTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/DefaultfSecurityRequestsTests.java index a1bf100d43..31858ba6d6 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/DefaultfSecurityRequestsTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/DefaultfSecurityRequestsTests.java @@ -97,13 +97,13 @@ public class DefaultfSecurityRequestsTests { // @formatter:on } - // @formatter:off @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); + // @formatter:on } - // @formatter:on } } \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/SecurityRequestsTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/SecurityRequestsTests.java index 226197aa38..4514754ff5 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/SecurityRequestsTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/SecurityRequestsTests.java @@ -115,14 +115,14 @@ public class SecurityRequestsTests { // @formatter:on } - // @formatter:off @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); + // @formatter:on } - // @formatter:on @Override @Bean diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserAuthenticationTests.java index cfdc27f7af..4a58ac6bde 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserAuthenticationTests.java @@ -99,13 +99,13 @@ public class WithUserAuthenticationTests { // @formatter:on } - // @formatter:off @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); + // @formatter:on } - // @formatter:on } } \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserClassLevelAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserClassLevelAuthenticationTests.java index 951245aa12..a0bd420579 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserClassLevelAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserClassLevelAuthenticationTests.java @@ -99,13 +99,13 @@ public class WithUserClassLevelAuthenticationTests { // @formatter:on } - // @formatter:off @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); + // @formatter:on } - // @formatter:on } } \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsAuthenticationTests.java index 5d89232bc8..be7234f3ef 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsAuthenticationTests.java @@ -97,14 +97,14 @@ public class WithUserDetailsAuthenticationTests { return super.userDetailsServiceBean(); } - // @formatter:off @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER").and() .withUser("admin").password("password").roles("USER", "ADMIN"); + // @formatter:on } - // @formatter:on } } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsClassLevelAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsClassLevelAuthenticationTests.java index 23c19d12b6..9c34d662df 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsClassLevelAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsClassLevelAuthenticationTests.java @@ -97,14 +97,14 @@ public class WithUserDetailsClassLevelAuthenticationTests { return super.userDetailsServiceBean(); } - // @formatter:off @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER").and() .withUser("admin").password("password").roles("USER", "ADMIN"); + // @formatter:on } - // @formatter:on } } From 6979125ccf3d169f47ea8e6f4b6e1007a0a213ba Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 23 Jul 2020 13:05:15 -0700 Subject: [PATCH 04/84] Add noformat blocks around User.withUsername Find `User.withUsername` calls and protect them against formatting. Issue gh-8945 --- .../core/userdetails/UserDetailsMapFactoryBean.java | 2 ++ .../authentication/NamespacePasswordEncoderTests.java | 2 ++ .../web/reactive/EnableWebFluxSecurityTests.java | 2 ++ .../UserDetailsResourceFactoryBeanTests.java | 3 ++- ...veUserDetailsServiceAuthenticationManagerTests.java | 4 ++++ ...lsRepositoryReactiveAuthenticationManagerTests.java | 10 ++++++++-- .../MapReactiveUserDetailsServiceTests.java | 2 ++ .../security/core/userdetails/UserTests.java | 4 ++++ 8 files changed, 26 insertions(+), 3 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java b/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java index 0048eb7e4e..f455fd7363 100644 --- a/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java @@ -67,12 +67,14 @@ public class UserDetailsMapFactoryBean implements FactoryBean users = factory.getObject(); - + // @formatter:off UserDetails expectedUser = User.withUsername("user") .password("password") .authorities("ROLE_USER") .build(); + // @formatter:on assertThat(users).containsExactly(expectedUser); } } diff --git a/core/src/test/java/org/springframework/security/authentication/ReactiveUserDetailsServiceAuthenticationManagerTests.java b/core/src/test/java/org/springframework/security/authentication/ReactiveUserDetailsServiceAuthenticationManagerTests.java index 73011471b0..d6352818cc 100644 --- a/core/src/test/java/org/springframework/security/authentication/ReactiveUserDetailsServiceAuthenticationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authentication/ReactiveUserDetailsServiceAuthenticationManagerTests.java @@ -76,10 +76,12 @@ public class ReactiveUserDetailsServiceAuthenticationManagerTests { @Test public void authenticateWhenPasswordNotEqualThenBadCredentials() { + // @formatter:off UserDetails user = PasswordEncodedUser.withUsername(this.username) .password(this.password) .roles("USER") .build(); + // @formatter:on when(repository.findByUsername(user.getUsername())).thenReturn(Mono.just(user)); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, this.password + "INVALID"); @@ -93,10 +95,12 @@ public class ReactiveUserDetailsServiceAuthenticationManagerTests { @Test public void authenticateWhenSuccessThenSuccess() { + // @formatter:off UserDetails user = PasswordEncodedUser.withUsername(this.username) .password(this.password) .roles("USER") .build(); + // @formatter:on when(repository.findByUsername(user.getUsername())).thenReturn(Mono.just(user)); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password); diff --git a/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManagerTests.java b/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManagerTests.java index 793edd5db3..937b61edb2 100644 --- a/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManagerTests.java @@ -59,10 +59,12 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests { @Mock private UserDetailsChecker postAuthenticationChecks; + // @formatter:off private UserDetails user = User.withUsername("user") .password("password") .roles("USER") .build(); + // @formatter:on private UserDetailsRepositoryReactiveAuthenticationManager manager; @@ -176,12 +178,13 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests { @Test(expected = AccountExpiredException.class) public void authenticateWhenAccountExpiredThenException() { this.manager.setPasswordEncoder(this.encoder); - + // @formatter:off UserDetails expiredUser = User.withUsername("user") .password("password") .roles("USER") .accountExpired(true) .build(); + // @formatter:on when(this.userDetailsService.findByUsername(any())).thenReturn(Mono.just(expiredUser)); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( @@ -193,12 +196,13 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests { @Test(expected = LockedException.class) public void authenticateWhenAccountLockedThenException() { this.manager.setPasswordEncoder(this.encoder); - + // @formatter:off UserDetails lockedUser = User.withUsername("user") .password("password") .roles("USER") .accountLocked(true) .build(); + // @formatter:on when(this.userDetailsService.findByUsername(any())).thenReturn(Mono.just(lockedUser)); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( @@ -211,11 +215,13 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests { public void authenticateWhenAccountDisabledThenException() { this.manager.setPasswordEncoder(this.encoder); + // @formatter:off UserDetails disabledUser = User.withUsername("user") .password("password") .roles("USER") .disabled(true) .build(); + // @formatter:on when(this.userDetailsService.findByUsername(any())).thenReturn(Mono.just(disabledUser)); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( diff --git a/core/src/test/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsServiceTests.java b/core/src/test/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsServiceTests.java index 97154ac416..3bf1fd7007 100644 --- a/core/src/test/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsServiceTests.java +++ b/core/src/test/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsServiceTests.java @@ -27,10 +27,12 @@ import org.junit.Test; import reactor.core.publisher.Mono; public class MapReactiveUserDetailsServiceTests { + // @formatter:off private static final UserDetails USER_DETAILS = User.withUsername("user") .password("password") .roles("USER") .build(); + // @formatter:on private MapReactiveUserDetailsService users = new MapReactiveUserDetailsService(Arrays.asList(USER_DETAILS)); diff --git a/core/src/test/java/org/springframework/security/core/userdetails/UserTests.java b/core/src/test/java/org/springframework/security/core/userdetails/UserTests.java index 00478f6474..36f4ce417e 100644 --- a/core/src/test/java/org/springframework/security/core/userdetails/UserTests.java +++ b/core/src/test/java/org/springframework/security/core/userdetails/UserTests.java @@ -203,11 +203,13 @@ public class UserTests { @Test public void withUsernameWhenPasswordAndPasswordEncoderThenEncodes() { + // @formatter:off UserDetails withEncodedPassword = User.withUsername("user") .passwordEncoder(p -> p + "encoded") .password("password") .roles("USER") .build(); + // @formatter:on assertThat(withEncodedPassword.getPassword()).isEqualTo("passwordencoded"); } @@ -215,12 +217,14 @@ public class UserTests { @Test public void withUsernameWhenPasswordAndPasswordEncoderTwiceThenEncodesOnce() { Function encoder = p -> p + "encoded"; + // @formatter:off UserDetails withEncodedPassword = User.withUsername("user") .passwordEncoder(encoder) .password("password") .passwordEncoder(encoder) .roles("USER") .build(); + // @formatter:on assertThat(withEncodedPassword.getPassword()).isEqualTo("passwordencoded"); } From 8e092f8d2cc8d33fef9905703cc87c3deef5d678 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 23 Jul 2020 13:23:10 -0700 Subject: [PATCH 05/84] Add noformat blocks around withDefaultPasswordEncoder Find `withDefaultPasswordEncoder` calls and protect them against formatting. Issue gh-8945 --- .../config/annotation/rsocket/HelloRSocketITests.java | 2 ++ .../rsocket/RSocketMessageHandlerConnectionITests.java | 3 ++- .../annotation/rsocket/RSocketMessageHandlerITests.java | 2 ++ .../config/annotation/rsocket/SimpleAuthenticationITests.java | 2 ++ .../web/configurers/ExceptionHandlingConfigurerTests.java | 2 ++ .../annotation/web/configurers/HttpBasicConfigurerTests.java | 2 ++ .../annotation/web/configurers/NamespaceHttpBasicTests.java | 2 ++ .../web/configurers/NamespaceHttpCustomFilterTests.java | 2 ++ .../web/configurers/NamespaceHttpFormLoginTests.java | 2 ++ .../web/configurers/NamespaceHttpOpenIDLoginTests.java | 2 ++ .../annotation/web/configurers/NamespaceRememberMeTests.java | 2 ++ .../web/configurers/NamespaceSessionManagementTests.java | 2 ++ .../annotation/web/configurers/RememberMeConfigurerTests.java | 2 ++ .../web/configurers/RequestCacheConfigurerTests.java | 2 ++ .../server/resource/OAuth2ResourceServerConfigurerTests.java | 4 ++++ .../servlet/response/SecurityMockMvcResultMatchersTests.java | 4 ++-- .../SecurityMockWithAuthoritiesMvcResultMatchersTests.java | 4 ++-- .../test/web/servlet/showcase/login/AuthenticationTests.java | 4 ++-- 18 files changed, 38 insertions(+), 7 deletions(-) diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/HelloRSocketITests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/HelloRSocketITests.java index 876e22d2a5..624332b308 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/HelloRSocketITests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/HelloRSocketITests.java @@ -147,11 +147,13 @@ public class HelloRSocketITests { @Bean MapReactiveUserDetailsService uds() { + // @formatter:off UserDetails rob = User.withDefaultPasswordEncoder() .username("rob") .password("password") .roles("USER", "ADMIN") .build(); + // @formatter:on return new MapReactiveUserDetailsService(rob); } } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerConnectionITests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerConnectionITests.java index 269bcbb951..66cafbebef 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerConnectionITests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerConnectionITests.java @@ -268,6 +268,7 @@ public class RSocketMessageHandlerConnectionITests { @Bean MapReactiveUserDetailsService uds() { + // @formatter:off UserDetails admin = User.withDefaultPasswordEncoder() .username("admin") .password("password") @@ -278,12 +279,12 @@ public class RSocketMessageHandlerConnectionITests { .password("password") .roles("USER", "SETUP") .build(); - UserDetails evil = User.withDefaultPasswordEncoder() .username("evil") .password("password") .roles("EVIL") .build(); + // @formatter:on return new MapReactiveUserDetailsService(admin, user, evil); } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerITests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerITests.java index 19f5e1010c..0256651580 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerITests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerITests.java @@ -237,6 +237,7 @@ public class RSocketMessageHandlerITests { @Bean MapReactiveUserDetailsService uds() { + // @formatter:off UserDetails rob = User.withDefaultPasswordEncoder() .username("rob") .password("password") @@ -247,6 +248,7 @@ public class RSocketMessageHandlerITests { .password("password") .roles("USER") .build(); + // @formatter:on return new MapReactiveUserDetailsService(rob, rossen); } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/SimpleAuthenticationITests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/SimpleAuthenticationITests.java index 9c9f4607c3..1e01b26cd8 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/SimpleAuthenticationITests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/SimpleAuthenticationITests.java @@ -165,11 +165,13 @@ public class SimpleAuthenticationITests { @Bean MapReactiveUserDetailsService uds() { + // @formatter:off UserDetails rob = User.withDefaultPasswordEncoder() .username("rob") .password("password") .roles("USER", "ADMIN") .build(); + // @formatter:on return new MapReactiveUserDetailsService(rob); } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.java index bd452d0090..5b4ea82259 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.java @@ -251,12 +251,14 @@ public class ExceptionHandlingConfigurerTests { @Bean public InMemoryUserDetailsManager userDetailsManager() { + // @formatter:off return new InMemoryUserDetailsManager(User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build() ); + // @formatter:off } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.java index 4a33b440e5..455621bedb 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.java @@ -259,11 +259,13 @@ public class HttpBasicConfigurerTests { @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build() + // @formatter:on ); } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java index 967b12d8ea..30239fcf54 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java @@ -83,11 +83,13 @@ public class NamespaceHttpBasicTests { @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build() + // @formatter:on ); } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java index 8e23245742..9c504e0c8f 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java @@ -170,11 +170,13 @@ public class NamespaceHttpCustomFilterTests { @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build()); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java index 553033215c..04fd811943 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java @@ -188,11 +188,13 @@ public class NamespaceHttpFormLoginTests { @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build()); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java index 04bbe88d51..7687bab5d5 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java @@ -300,11 +300,13 @@ public class NamespaceHttpOpenIDLoginTests { @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build()); + // @formatter:on } } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java index 41673a98cb..b46aab6f9b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java @@ -499,11 +499,13 @@ public class NamespaceRememberMeTests { @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build()); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java index e163d7946e..21ba2ef19d 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java @@ -413,11 +413,13 @@ public class NamespaceSessionManagementTests { @Bean UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build()); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java index 1cba7745fe..2988162ff0 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java @@ -190,11 +190,13 @@ public class RememberMeConfigurerTests { @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build() + // @formatter:on ); } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java index 5b22f8662f..3647b0210a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java @@ -399,12 +399,14 @@ public class RequestCacheConfigurerTests { @Bean public InMemoryUserDetailsManager userDetailsManager() { + // @formatter:off return new InMemoryUserDetailsManager(User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build() ); + // @formatter:on } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java index 957c383d96..a830d226c1 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java @@ -1746,11 +1746,13 @@ public class OAuth2ResourceServerConfigurerTests { @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( + // @formatter:off org.springframework.security.core.userdetails.User.withDefaultPasswordEncoder() .username("basic-user") .password("basic-password") .roles("USER") .build()); + // @formatter:on } } @@ -1819,11 +1821,13 @@ public class OAuth2ResourceServerConfigurerTests { @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( + // @formatter:off org.springframework.security.core.userdetails.User.withDefaultPasswordEncoder() .username("basic-user") .password("basic-password") .roles("USER") .build()); + // @formatter:on } } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchersTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchersTests.java index 9a63cfe4fa..fdb23bcf24 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchersTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchersTests.java @@ -100,13 +100,13 @@ public class SecurityMockMvcResultMatchersTests { @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Bean public UserDetailsService userDetailsService() { + // @formatter:off UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("USER", "SELLER").build(); + // @formatter:on return new InMemoryUserDetailsManager(user); } - // @formatter:on @RestController static class Controller { diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockWithAuthoritiesMvcResultMatchersTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockWithAuthoritiesMvcResultMatchersTests.java index 5f4b7af1f9..5753a20f98 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockWithAuthoritiesMvcResultMatchersTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockWithAuthoritiesMvcResultMatchersTests.java @@ -80,13 +80,13 @@ public class SecurityMockWithAuthoritiesMvcResultMatchersTests { @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Bean public UserDetailsService userDetailsService() { + // @formatter:off UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("ADMIN", "SELLER").build(); return new InMemoryUserDetailsManager(user); + // @formatter:on } - // @formatter:on @RestController static class Controller { diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/AuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/AuthenticationTests.java index 660872ea58..bc445ea770 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/AuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/AuthenticationTests.java @@ -90,12 +90,12 @@ public class AuthenticationTests { @EnableWebSecurity @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { - // @formatter:off @Bean public UserDetailsService userDetailsService() { + // @formatter:off UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build(); return new InMemoryUserDetailsManager(user); + // @formatter:on } - // @formatter:on } } From 9caa39e3701be9a3fa778c6c1a2b3564cd126bfb Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 23 Jul 2020 14:55:09 -0700 Subject: [PATCH 06/84] Fix malformed formatter-on/off javadoc Remove the formatter-on/formatter-off comments from Javadoc examples so that they don't confuse checkstyle. The comments are not necessary in the Javadoc since `pre` blocks are not formatted in the same way as code. Issue gh-8945 --- .../security/config/annotation/rsocket/RSocketSecurity.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurity.java index 8ab04005e8..d36acdbc44 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurity.java @@ -56,7 +56,6 @@ import java.util.List; *
  * @EnableRSocketSecurity
  * public class SecurityConfig {
- *     // @formatter:off
  *     @Bean
  *     PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) {
  *         rsocket
@@ -66,9 +65,7 @@ import java.util.List;
  *             );
  *         return rsocket.build();
  *     }
- *     // @formatter:on
  *
- *     // @formatter:off
  *     @Bean
  *     public MapReactiveUserDetailsService userDetailsService() {
  *          UserDetails user = User.withDefaultPasswordEncoder()
@@ -78,7 +75,6 @@ import java.util.List;
  *               .build();
  *          return new MapReactiveUserDetailsService(user);
  *     }
- *     // @formatter:on
  * }
  * 
* @@ -87,7 +83,6 @@ import java.util.List; *
  * @EnableRSocketSecurity
  * public class SecurityConfig {
- *     // @formatter:off
  *     @Bean
  *     PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) {
  *         rsocket
@@ -102,7 +97,6 @@ import java.util.List;
  *             );
  *         return rsocket.build();
  *     }
- *     // @formatter:on
  * }
  * 
* @author Rob Winch From 81d9c6cac552d95c3455960d0fae61afb68990ee Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 23 Jul 2020 14:15:24 -0700 Subject: [PATCH 07/84] Add spring-javaformat plugin Add spring-javaformat plugin but disable it for all sample projects. Issue gh-8945 --- build.gradle | 13 ++++++++++++- gradle.properties | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ace768def7..66c2497d07 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ buildscript { dependencies { classpath 'io.spring.gradle:spring-build-conventions:0.0.33.RELEASE' + classpath "io.spring.javaformat:spring-javaformat-gradle-plugin:$springJavaformatVersion" classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion" classpath 'io.spring.nohttp:nohttp-gradle:0.0.5.RELEASE' classpath "io.freefair.gradle:aspectj-plugin:5.0.1" @@ -34,12 +35,22 @@ subprojects { plugins.withType(JavaPlugin) { project.sourceCompatibility='1.8' } - tasks.withType(JavaCompile) { options.encoding = "UTF-8" } } +allprojects { + apply plugin: 'io.spring.javaformat' + if (project.name.contains('sample')) { + tasks.whenTaskAdded { task -> + if (task.name.contains('format') || task.name.contains('checkFormat')) { + task.enabled = false + } + } + } +} + nohttp { allowlistFile = project.file("etc/nohttp/allowlist.lines") } diff --git a/gradle.properties b/gradle.properties index 8030f9eddc..aca683ccc0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,6 @@ aspectjVersion=1.9.3 gaeVersion=1.9.80 +springJavaformatVersion=0.0.24 springBootVersion=2.4.0-M1 version=5.4.0-SNAPSHOT kotlinVersion=1.3.72 From b7fc18262d86a8ceb390a6b5649d1ecc50245f08 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 10 Aug 2020 16:39:17 -0500 Subject: [PATCH 08/84] Reformat code using spring-javaformat Run `./gradlew format` to reformat all java files. Issue gh-8945 --- .../security/acls/AclEntryVoter.java | 45 +- .../acls/AclPermissionCacheOptimizer.java | 8 +- .../security/acls/AclPermissionEvaluator.java | 33 +- .../afterinvocation/AbstractAclProvider.java | 24 +- ...InvocationCollectionFilteringProvider.java | 26 +- .../AclEntryAfterInvocationProvider.java | 25 +- .../acls/afterinvocation/ArrayFilterer.java | 10 +- .../afterinvocation/CollectionFilterer.java | 6 +- .../acls/afterinvocation/Filterer.java | 5 +- .../acls/afterinvocation/package-info.java | 5 +- .../acls/domain/AbstractPermission.java | 4 +- .../acls/domain/AccessControlEntryImpl.java | 25 +- .../acls/domain/AclAuthorizationStrategy.java | 4 + .../domain/AclAuthorizationStrategyImpl.java | 16 +- .../acls/domain/AclFormattingUtils.java | 14 +- .../security/acls/domain/AclImpl.java | 103 +- .../security/acls/domain/AuditLogger.java | 2 + .../security/acls/domain/BasePermission.java | 6 + .../acls/domain/ConsoleAuditLogger.java | 2 + .../acls/domain/CumulativePermission.java | 6 +- .../acls/domain/DefaultPermissionFactory.java | 8 +- .../DefaultPermissionGrantingStrategy.java | 23 +- .../acls/domain/EhCacheBasedAclCache.java | 13 +- .../acls/domain/GrantedAuthoritySid.java | 8 +- .../domain/IdentityUnavailableException.java | 4 +- .../acls/domain/ObjectIdentityImpl.java | 17 +- .../ObjectIdentityRetrievalStrategyImpl.java | 5 +- .../acls/domain/PermissionFactory.java | 3 +- .../security/acls/domain/PrincipalSid.java | 2 + .../acls/domain/SidRetrievalStrategyImpl.java | 1 + .../acls/domain/SpringCacheBasedAclCache.java | 13 +- .../security/acls/domain/package-info.java | 1 - .../security/acls/jdbc/AclClassIdUtils.java | 43 +- .../acls/jdbc/BasicLookupStrategy.java | 200 ++-- .../security/acls/jdbc/JdbcAclService.java | 50 +- .../acls/jdbc/JdbcMutableAclService.java | 105 +- .../security/acls/jdbc/LookupStrategy.java | 4 +- .../security/acls/jdbc/package-info.java | 1 - .../acls/model/AccessControlEntry.java | 8 +- .../security/acls/model/Acl.java | 15 +- .../security/acls/model/AclCache.java | 2 + .../acls/model/AclDataAccessException.java | 3 +- .../security/acls/model/AclService.java | 22 +- .../acls/model/AlreadyExistsException.java | 4 +- .../model/AuditableAccessControlEntry.java | 2 + .../security/acls/model/AuditableAcl.java | 2 + .../acls/model/ChildrenExistException.java | 4 +- .../security/acls/model/MutableAcl.java | 9 +- .../acls/model/MutableAclService.java | 12 +- .../acls/model/NotFoundException.java | 4 +- .../security/acls/model/ObjectIdentity.java | 5 +- .../acls/model/ObjectIdentityGenerator.java | 1 - .../ObjectIdentityRetrievalStrategy.java | 2 + .../security/acls/model/OwnershipAcl.java | 2 + .../security/acls/model/Permission.java | 6 +- .../model/PermissionGrantingStrategy.java | 7 +- .../security/acls/model/Sid.java | 5 +- .../acls/model/SidRetrievalStrategy.java | 2 + .../acls/model/UnloadedSidException.java | 4 +- .../security/acls/model/package-info.java | 4 +- .../security/acls/package-info.java | 12 +- .../acls/AclFormattingUtilsTests.java | 32 +- .../AclPermissionCacheOptimizerTests.java | 3 +- .../acls/AclPermissionEvaluatorTests.java | 2 +- .../security/acls/TargetObjectWithUUID.java | 1 + ...ationCollectionFilteringProviderTests.java | 21 +- .../AclEntryAfterInvocationProviderTests.java | 66 +- .../domain/AccessControlImplEntryTests.java | 46 +- .../AclAuthorizationStrategyImplTests.java | 11 +- .../security/acls/domain/AclImplTests.java | 303 ++--- .../AclImplementationSecurityCheckTests.java | 144 +-- .../acls/domain/AuditLoggerTests.java | 5 + .../acls/domain/ObjectIdentityImplTests.java | 8 +- ...ectIdentityRetrievalStrategyImplTests.java | 2 + .../security/acls/domain/PermissionTests.java | 53 +- .../acls/domain/SpecialPermission.java | 3 + .../AbstractBasicLookupStrategyTests.java | 61 +- .../acls/jdbc/AclClassIdUtilsTests.java | 6 +- .../acls/jdbc/BasicLookupStrategyTests.java | 3 +- .../BasicLookupStrategyTestsDbHelper.java | 9 +- ...icLookupStrategyWithAclClassTypeTests.java | 26 +- .../security/acls/jdbc/DatabaseSeeder.java | 2 + .../acls/jdbc/EhCacheBasedAclCacheTests.java | 60 +- .../acls/jdbc/JdbcAclServiceTests.java | 26 +- .../acls/jdbc/JdbcMutableAclServiceTests.java | 93 +- ...cMutableAclServiceTestsWithAclClassId.java | 22 +- .../jdbc/SpringCacheBasedAclCacheTests.java | 51 +- .../security/acls/sid/CustomSid.java | 2 + .../acls/sid/SidRetrievalStrategyTests.java | 8 +- .../security/acls/sid/SidTests.java | 52 +- .../aspect/AnnotationSecurityAspectTests.java | 43 +- .../security/cas/SamlServiceProperties.java | 1 + .../security/cas/ServiceProperties.java | 9 +- .../CasAssertionAuthenticationToken.java | 1 + .../CasAuthenticationProvider.java | 76 +- .../CasAuthenticationToken.java | 73 +- .../EhCacheBasedTicketCache.java | 9 +- .../NullStatelessTicketCache.java | 2 +- .../SpringCacheBasedTicketCache.java | 11 +- .../authentication/StatelessTicketCache.java | 10 +- .../cas/authentication/package-info.java | 4 +- .../cas/jackson2/AssertionImplMixin.java | 25 +- .../jackson2/AttributePrincipalImplMixin.java | 22 +- .../jackson2/CasAuthenticationTokenMixin.java | 17 +- .../cas/jackson2/CasJackson2Module.java | 14 +- .../security/cas/package-info.java | 4 +- ...bstractCasAssertionUserDetailsService.java | 6 +- ...AssertionAttributesUserDetailsService.java | 22 +- .../cas/web/CasAuthenticationEntryPoint.java | 33 +- .../cas/web/CasAuthenticationFilter.java | 82 +- .../DefaultServiceAuthenticationDetails.java | 14 +- .../ServiceAuthenticationDetails.java | 3 +- .../ServiceAuthenticationDetailsSource.java | 17 +- .../cas/web/authentication/package-info.java | 1 - .../security/cas/web/package-info.java | 1 - .../AbstractStatelessTicketCacheTests.java | 4 +- .../CasAuthenticationProviderTests.java | 36 +- .../CasAuthenticationTokenTests.java | 86 +- .../EhCacheBasedTicketCacheTests.java | 2 + .../NullStatelessTicketCacheTests.java | 1 + .../SpringCacheBasedTicketCacheTests.java | 5 +- .../CasAuthenticationTokenMixinTests.java | 53 +- ...tionAttributesUserDetailsServiceTests.java | 7 +- .../web/CasAuthenticationEntryPointTests.java | 14 +- .../cas/web/CasAuthenticationFilterTests.java | 27 +- .../cas/web/ServicePropertiesTests.java | 2 + ...aultServiceAuthenticationDetailsTests.java | 39 +- ...onProviderBuilderSecurityBuilderTests.java | 39 +- ...AuthenticationProviderConfigurerTests.java | 21 +- ...espaceLdapAuthenticationProviderTests.java | 12 +- ...dapAuthenticationProviderTestsConfigs.java | 13 +- .../annotation/rsocket/HelloHandler.java | 20 +- .../rsocket/HelloRSocketITests.java | 43 +- .../config/annotation/rsocket/JwtITests.java | 63 +- ...RSocketMessageHandlerConnectionITests.java | 151 +-- .../rsocket/RSocketMessageHandlerITests.java | 116 +- .../rsocket/SimpleAuthenticationITests.java | 52 +- ...LdapProviderBeanDefinitionParserTests.java | 106 +- .../LdapServerBeanDefinitionParserTests.java | 17 +- ...pUserServiceBeanDefinitionParserTests.java | 36 +- .../security/config/BeanIds.java | 25 +- .../security/config/Customizer.java | 6 +- .../config/DebugBeanDefinitionParser.java | 5 +- .../security/config/Elements.java | 52 + .../config/SecurityNamespaceHandler.java | 55 +- .../AbstractConfiguredSecurityBuilder.java | 42 +- .../annotation/AbstractSecurityBuilder.java | 6 +- .../annotation/AlreadyBuiltException.java | 1 + .../annotation/ObjectPostProcessor.java | 3 +- .../config/annotation/SecurityBuilder.java | 3 +- .../config/annotation/SecurityConfigurer.java | 6 +- .../annotation/SecurityConfigurerAdapter.java | 22 +- .../ProviderManagerBuilder.java | 10 +- .../AuthenticationManagerBuilder.java | 55 +- .../AuthenticationConfiguration.java | 93 +- .../EnableGlobalAuthentication.java | 1 + ...GlobalAuthenticationConfigurerAdapter.java | 5 +- ...ticationProviderBeanManagerConfigurer.java | 29 +- ...alizeUserDetailsBeanManagerConfigurer.java | 21 +- .../LdapAuthenticationProviderConfigurer.java | 122 +- .../InMemoryUserDetailsManagerConfigurer.java | 2 +- .../JdbcUserDetailsManagerConfigurer.java | 17 +- .../UserDetailsManagerConfigurer.java | 24 +- .../AbstractDaoAuthenticationConfigurer.java | 8 +- .../DaoAuthenticationConfigurer.java | 5 +- .../UserDetailsAwareConfigurer.java | 2 +- .../UserDetailsServiceConfigurer.java | 2 +- ...utowireBeanFactoryObjectPostProcessor.java | 20 +- .../ObjectPostProcessorConfiguration.java | 5 +- .../EnableGlobalMethodSecurity.java | 8 +- .../EnableReactiveMethodSecurity.java | 21 +- ...thodSecurityAspectJAutoProxyRegistrar.java | 16 +- .../GlobalMethodSecurityConfiguration.java | 114 +- .../GlobalMethodSecuritySelector.java | 21 +- .../Jsr250MetadataSourceConfiguration.java | 1 + ...ecurityMetadataSourceAdvisorRegistrar.java | 19 +- .../ReactiveMethodSecurityConfiguration.java | 17 +- .../ReactiveMethodSecuritySelector.java | 18 +- .../rsocket/EnableRSocketSecurity.java | 4 +- .../rsocket/PayloadInterceptorOrder.java | 8 +- .../annotation/rsocket/RSocketSecurity.java | 67 +- .../rsocket/RSocketSecurityConfiguration.java | 12 +- ...ocketAcceptorInterceptorConfiguration.java | 20 +- .../web/AbstractRequestMatcherRegistry.java | 55 +- .../annotation/web/HttpSecurityBuilder.java | 25 +- .../annotation/web/WebSecurityConfigurer.java | 8 +- .../web/builders/FilterComparator.java | 43 +- .../annotation/web/builders/HttpSecurity.java | 597 +++++----- .../annotation/web/builders/WebSecurity.java | 98 +- ...edWebSecurityConfigurersIgnoreParents.java | 7 +- .../web/configuration/EnableWebSecurity.java | 7 +- .../HttpSecurityConfiguration.java | 33 +- .../OAuth2ClientConfiguration.java | 41 +- .../configuration/OAuth2ImportSelector.java | 19 +- .../SecurityReactorContextConfiguration.java | 30 +- .../SpringWebMvcImportSelector.java | 4 +- .../WebMvcSecurityConfiguration.java | 8 +- .../WebSecurityConfiguration.java | 28 +- .../WebSecurityConfigurerAdapter.java | 161 ++- ...bstractAuthenticationFilterConfigurer.java | 79 +- ...ConfigAttributeRequestMatcherRegistry.java | 23 +- .../configurers/AbstractHttpConfigurer.java | 2 +- .../AbstractInterceptUrlConfigurer.java | 37 +- .../web/configurers/AnonymousConfigurer.java | 30 +- .../ChannelSecurityConfigurer.java | 36 +- .../web/configurers/CorsConfigurer.java | 38 +- .../web/configurers/CsrfConfigurer.java | 87 +- .../DefaultLoginPageConfigurer.java | 14 +- .../ExceptionHandlingConfigurer.java | 46 +- .../ExpressionUrlAuthorizationConfigurer.java | 87 +- .../web/configurers/FormLoginConfigurer.java | 10 +- .../web/configurers/HeadersConfigurer.java | 262 ++--- .../web/configurers/HttpBasicConfigurer.java | 64 +- .../web/configurers/JeeConfigurer.java | 35 +- .../web/configurers/LogoutConfigurer.java | 79 +- .../web/configurers/PermitAllSupport.java | 23 +- .../web/configurers/PortMapperConfigurer.java | 10 +- .../web/configurers/RememberMeConfigurer.java | 99 +- .../configurers/RequestCacheConfigurer.java | 16 +- .../SecurityContextConfigurer.java | 17 +- .../web/configurers/ServletApiConfigurer.java | 24 +- .../SessionManagementConfigurer.java | 157 ++- .../UrlAuthorizationConfigurer.java | 59 +- .../web/configurers/X509Configurer.java | 31 +- .../client/ImplicitGrantConfigurer.java | 31 +- .../oauth2/client/OAuth2ClientConfigurer.java | 82 +- .../client/OAuth2ClientConfigurerUtils.java | 55 +- .../oauth2/client/OAuth2LoginConfigurer.java | 263 +++-- .../OAuth2ResourceServerConfigurer.java | 145 +-- .../openid/OpenIDLoginConfigurer.java | 75 +- .../saml2/Saml2LoginConfigurer.java | 132 +-- ...MessageSecurityMetadataSourceRegistry.java | 96 +- .../web/reactive/EnableWebFluxSecurity.java | 5 +- .../ReactiveOAuth2ClientImportSelector.java | 24 +- .../ServerHttpSecurityConfiguration.java | 22 +- .../WebFluxSecurityConfiguration.java | 13 +- .../configuration/EnableWebMvcSecurity.java | 2 +- .../WebMvcSecurityConfiguration.java | 7 +- ...urityWebSocketMessageBrokerConfigurer.java | 49 +- ...serDetailsServiceBeanDefinitionParser.java | 33 +- ...enticationManagerBeanDefinitionParser.java | 66 +- .../AuthenticationManagerFactoryBean.java | 14 +- ...nticationProviderBeanDefinitionParser.java | 31 +- .../JdbcUserServiceBeanDefinitionParser.java | 14 +- .../authentication/PasswordEncoderParser.java | 13 +- .../UserServiceBeanDefinitionParser.java | 19 +- .../config/authentication/package-info.java | 1 - .../config/core/GrantedAuthorityDefaults.java | 2 +- ...UserDetailsServiceResourceFactoryBean.java | 39 +- .../UserDetailsMapFactoryBean.java | 12 +- .../UserDetailsResourceFactoryBean.java | 35 +- .../RsaKeyConversionServicePostProcessor.java | 27 +- ...SecurityDebugBeanFactoryPostProcessor.java | 23 +- .../http/AuthenticationConfigBuilder.java | 357 +++--- .../config/http/ChannelAttributeFactory.java | 7 +- .../config/http/CorsBeanDefinitionParser.java | 6 +- .../config/http/CsrfBeanDefinitionParser.java | 70 +- .../http/DefaultFilterChainValidator.java | 58 +- .../http/FilterChainBeanDefinitionParser.java | 8 +- ...FilterChainMapBeanDefinitionDecorator.java | 36 +- ...nvocationSecurityMetadataSourceParser.java | 103 +- .../http/FormLoginBeanDefinitionParser.java | 102 +- .../GrantedAuthorityDefaultsParserUtils.java | 19 +- ...HandlerMappingIntrospectorFactoryBean.java | 12 +- .../http/HeadersBeanDefinitionParser.java | 164 ++- .../config/http/HttpConfigurationBuilder.java | 275 +++-- .../HttpFirewallBeanDefinitionParser.java | 13 +- .../HttpSecurityBeanDefinitionParser.java | 148 +-- .../http/LogoutBeanDefinitionParser.java | 24 +- .../security/config/http/MatcherType.java | 9 +- .../OAuth2ClientBeanDefinitionParser.java | 44 +- ...OAuth2ClientBeanDefinitionParserUtils.java | 22 +- ...uth2ClientWebMvcSecurityPostProcessor.java | 14 +- .../http/OAuth2LoginBeanDefinitionParser.java | 87 +- ...th2ResourceServerBeanDefinitionParser.java | 119 +- .../PortMappingsBeanDefinitionParser.java | 15 +- .../http/RememberMeBeanDefinitionParser.java | 61 +- .../security/config/http/SecurityFilters.java | 45 +- .../config/http/SessionCreationPolicy.java | 2 + .../http/UserDetailsServiceFactoryBean.java | 21 +- .../security/config/http/WebConfigUtils.java | 8 +- .../security/config/http/package-info.java | 1 - .../ContextSourceSettingPostProcessor.java | 30 +- .../LdapProviderBeanDefinitionParser.java | 49 +- .../ldap/LdapServerBeanDefinitionParser.java | 44 +- .../LdapUserServiceBeanDefinitionParser.java | 69 +- .../security/config/ldap/package-info.java | 1 - ...balMethodSecurityBeanDefinitionParser.java | 266 ++--- ...terceptMethodsBeanDefinitionDecorator.java | 32 +- .../config/method/MethodConfigUtils.java | 14 +- ...ityMetadataSourceBeanDefinitionParser.java | 12 +- .../method/ProtectPointcutPostProcessor.java | 40 +- .../security/config/method/package-info.java | 4 +- ...ientRegistrationsBeanDefinitionParser.java | 68 +- .../oauth2/client/CommonOAuth2Provider.java | 20 +- .../security/config/package-info.java | 5 +- ...UserDetailsManagerResourceFactoryBean.java | 41 +- ...tractServerWebExchangeMatcherRegistry.java | 52 +- .../web/server/SecurityWebFiltersOrder.java | 20 +- .../config/web/server/ServerHttpSecurity.java | 1015 +++++++++-------- ...ageBrokerSecurityBeanDefinitionParser.java | 86 +- .../BeanNameCollectingPostProcessor.java | 9 +- .../security/CollectingAppListener.java | 5 + .../security/config/ConfigTestUtils.java | 9 +- .../security/config/DataSourcePopulator.java | 8 +- .../config/FilterChainProxyConfigTests.java | 35 +- .../config/InvalidConfigurationTests.java | 5 +- .../config/MockAfterInvocationProvider.java | 5 +- .../security/config/MockEventListener.java | 5 +- .../config/MockTransactionManager.java | 5 +- .../MockUserServiceBeanPostProcessor.java | 10 +- .../PostProcessedMockUserDetailsService.java | 2 + .../config/SecurityNamespaceHandlerTests.java | 39 +- .../security/config/TestBusinessBean.java | 1 + .../security/config/TestBusinessBeanImpl.java | 5 +- .../config/TransactionalTestBusinessBean.java | 2 + .../ConcereteSecurityConfigurerAdapter.java | 5 +- .../annotation/ObjectPostProcessorTests.java | 9 +- ...SecurityConfigurerAdapterClosureTests.java | 8 +- .../SecurityConfigurerAdapterTests.java | 4 + .../AuthenticationManagerBuilderTests.java | 43 +- .../BaseAuthenticationConfig.java | 4 +- .../NamespaceAuthenticationManagerTests.java | 18 +- .../NamespaceAuthenticationProviderTests.java | 11 +- .../NamespaceJdbcUserServiceTests.java | 21 +- .../NamespacePasswordEncoderTests.java | 16 +- .../PasswordEncoderConfigurerTests.java | 11 +- ...thenticationConfigurationPublishTests.java | 6 +- .../AuthenticationConfigurationTests.java | 253 ++-- .../EnableGlobalAuthenticationTests.java | 12 +- ...AuthenticationProviderConfigurerTests.java | 1 + .../UserDetailsManagerConfigurerTests.java | 45 +- .../AroundMethodInterceptor.java | 2 + ...reBeanFactoryObjectPostProcessorTests.java | 9 +- .../configuration/MyAdvisedBean.java | 1 + .../annotation/issue50/ApplicationConfig.java | 2 + .../annotation/issue50/Issue50Tests.java | 11 +- .../annotation/issue50/SecurityConfig.java | 8 +- .../annotation/issue50/domain/User.java | 3 +- .../issue50/repo/UserRepository.java | 1 + .../method/configuration/Authz.java | 4 +- .../DelegatingReactiveMessageService.java | 38 +- .../EnableReactiveMethodSecurityTests.java | 259 ++--- ...lobalMethodSecurityConfigurationTests.java | 139 ++- .../configuration/MethodSecurityService.java | 2 + .../MethodSecurityServiceConfig.java | 2 + .../MethodSecurityServiceImpl.java | 1 + ...lMethodSecurityExpressionHandlerTests.java | 22 +- .../NamespaceGlobalMethodSecurityTests.java | 205 ++-- .../configuration/ReactiveMessageService.java | 14 + ...ctiveMethodSecurityConfigurationTests.java | 41 +- ...SampleEnableGlobalMethodSecurityTests.java | 29 +- .../annotation/sec2758/Sec2758Tests.java | 24 +- ...bstractConfiguredSecurityBuilderTests.java | 34 +- ...RequestMatcherRegistryAnyMatcherTests.java | 15 +- .../AbstractRequestMatcherRegistryTests.java | 3 + .../web/HttpSecurityHeadersTests.java | 31 +- ...mpleWebSecurityConfigurerAdapterTests.java | 38 +- ...curityConfigurerAdapterPowermockTests.java | 33 +- .../WebSecurityConfigurerAdapterTests.java | 119 +- .../web/builders/HttpConfigurationTests.java | 26 +- .../web/builders/NamespaceHttpTests.java | 151 ++- .../web/builders/WebSecurityTests.java | 19 +- ...icationPrincipalArgumentResolverTests.java | 14 +- .../configuration/EnableWebSecurityTests.java | 29 +- .../HttpSecurityConfigurationTests.java | 91 +- .../OAuth2ClientConfigurationTests.java | 70 +- .../web/configuration/Sec2515Tests.java | 12 +- ...ntextConfigurationResourceServerTests.java | 43 +- ...urityReactorContextConfigurationTests.java | 129 +-- .../WebMvcSecurityConfigurationTests.java | 15 +- .../WebSecurityConfigurationTests.java | 149 +-- .../configuration/sec2377/Sec2377Tests.java | 4 +- ...gAttributeRequestMatcherRegistryTests.java | 17 +- .../configurers/AnonymousConfigurerTests.java | 22 +- .../configurers/AuthorizeRequestsTests.java | 93 +- .../ChannelSecurityConfigurerTests.java | 25 +- .../web/configurers/CorsConfigurerTests.java | 77 +- ...onfigurerIgnoringRequestMatchersTests.java | 62 +- .../CsrfConfigurerNoWebMvcTests.java | 6 + .../web/configurers/CsrfConfigurerTests.java | 223 ++-- .../web/configurers/DefaultFiltersTests.java | 21 +- .../DefaultLoginPageConfigurerTests.java | 389 +++---- ...ingConfigurerAccessDeniedHandlerTests.java | 50 +- .../ExceptionHandlingConfigurerTests.java | 95 +- ...essionUrlAuthorizationConfigurerTests.java | 291 +++-- .../configurers/FormLoginConfigurerTests.java | 143 ++- .../HeadersConfigurerEagerHeadersTests.java | 29 +- .../configurers/HeadersConfigurerTests.java | 170 +-- .../configurers/HttpBasicConfigurerTests.java | 45 +- .../HttpSecurityAntMatchersTests.java | 8 +- .../configurers/HttpSecurityLogoutTests.java | 9 +- .../HttpSecurityRequestMatchersTests.java | 65 +- .../web/configurers/Issue55Tests.java | 26 +- .../web/configurers/JeeConfigurerTests.java | 68 +- .../LogoutConfigurerClearSiteDataTests.java | 17 +- .../configurers/LogoutConfigurerTests.java | 131 +-- .../web/configurers/NamespaceDebugTests.java | 6 +- .../NamespaceHttpAnonymousTests.java | 50 +- .../configurers/NamespaceHttpBasicTests.java | 101 +- .../NamespaceHttpCustomFilterTests.java | 38 +- .../NamespaceHttpExpressionHandlerTests.java | 12 +- .../NamespaceHttpFirewallTests.java | 19 +- .../NamespaceHttpFormLoginTests.java | 55 +- .../NamespaceHttpHeadersTests.java | 46 +- .../NamespaceHttpInterceptUrlTests.java | 37 +- .../configurers/NamespaceHttpJeeTests.java | 37 +- .../configurers/NamespaceHttpLogoutTests.java | 56 +- .../NamespaceHttpOpenIDLoginTests.java | 81 +- .../NamespaceHttpPortMappingsTests.java | 9 +- .../NamespaceHttpRequestCacheTests.java | 12 +- ...aceHttpServerAccessDeniedHandlerTests.java | 35 +- .../configurers/NamespaceHttpX509Tests.java | 55 +- .../configurers/NamespaceRememberMeTests.java | 150 +-- .../NamespaceSessionManagementTests.java | 155 ++- .../configurers/PermitAllSupportTests.java | 16 +- .../PortMapperConfigurerTests.java | 16 +- .../RememberMeConfigurerTests.java | 137 +-- .../RequestCacheConfigurerTests.java | 180 ++- .../RequestMatcherConfigurerTests.java | 15 +- .../SecurityContextConfigurerTests.java | 24 +- .../ServletApiConfigurerTests.java | 69 +- ...ionManagementConfigurerServlet31Tests.java | 21 +- ...rerSessionAuthenticationStrategyTests.java | 10 +- ...tConfigurerSessionCreationPolicyTests.java | 23 +- .../SessionManagementConfigurerTests.java | 115 +- ...onfigurerTransientAuthenticationTests.java | 14 +- .../UrlAuthorizationConfigurerTests.java | 34 +- .../configurers/UrlAuthorizationsTests.java | 52 +- .../web/configurers/X509ConfigurerTests.java | 29 +- .../client/OAuth2ClientConfigurerTests.java | 132 +-- .../client/OAuth2LoginConfigurerTests.java | 227 ++-- .../OAuth2ResourceServerConfigurerTests.java | 784 ++++++------- .../openid/OpenIDLoginConfigurerTests.java | 88 +- .../saml2/Saml2LoginConfigurerTests.java | 142 +-- .../saml2/TestSaml2Credentials.java | 123 +- ...geSecurityMetadataSourceRegistryTests.java | 111 +- .../reactive/EnableWebFluxSecurityTests.java | 214 ++-- ...erverHttpSecurityConfigurationBuilder.java | 9 +- .../ServerHttpSecurityConfigurationTests.java | 3 + .../WebFluxSecurityConfigurationTests.java | 3 + ...SocketMessageBrokerConfigurerDocTests.java | 17 +- ...WebSocketMessageBrokerConfigurerTests.java | 125 +- ...cutorSubscribableChannelPostProcessor.java | 7 +- ...uthenticationConfigurationGh3935Tests.java | 22 +- ...ationManagerBeanDefinitionParserTests.java | 53 +- ...tionProviderBeanDefinitionParserTests.java | 91 +- ...cUserServiceBeanDefinitionParserTests.java | 67 +- .../PasswordEncoderParserTests.java | 19 +- .../UserServiceBeanDefinitionParserTests.java | 45 +- .../core/GrantedAuthorityDefaultsJcTests.java | 8 +- .../GrantedAuthorityDefaultsXmlTests.java | 5 + .../config/core/HelloWorldMessageService.java | 1 + .../security/config/core/MessageService.java | 3 + ...ceFactoryBeanPropertiesResourceITests.java | 11 +- ...yBeanPropertiesResourceLocationITests.java | 8 +- ...erviceResourceFactoryBeanStringITests.java | 8 +- .../UserDetailsResourceFactoryBeanTests.java | 18 +- ...eyConversionServicePostProcessorTests.java | 83 +- .../config/debug/AuthProviderDependency.java | 1 + ...ityDebugBeanFactoryPostProcessorTests.java | 6 +- .../debug/TestAuthenticationProvider.java | 6 +- .../security/config/doc/Attribute.java | 6 +- .../security/config/doc/Element.java | 68 +- .../config/doc/SpringSecurityXsdParser.java | 62 +- .../security/config/doc/XmlNode.java | 21 +- .../security/config/doc/XmlParser.java | 5 +- .../security/config/doc/XmlSupport.java | 4 +- .../config/doc/XsdDocumentedTests.java | 216 ++-- .../config/http/AccessDeniedConfigTests.java | 24 +- .../http/CsrfBeanDefinitionParserTests.java | 5 +- .../security/config/http/CsrfConfigTests.java | 354 ++---- .../DefaultFilterChainValidatorTests.java | 33 +- ...tadataSourceBeanDefinitionParserTests.java | 34 +- .../FormLoginBeanDefinitionParserTests.java | 254 ++--- .../config/http/FormLoginConfigTests.java | 107 +- .../security/config/http/HttpConfigTests.java | 25 +- .../config/http/HttpCorsConfigTests.java | 52 +- .../config/http/HttpHeadersConfigTests.java | 478 +++----- .../config/http/HttpInterceptUrlTests.java | 20 +- .../config/http/InterceptUrlConfigTests.java | 130 +-- .../config/http/MiscHttpConfigTests.java | 369 +++--- .../http/MultiHttpBlockConfigTests.java | 37 +- .../config/http/NamespaceHttpBasicTests.java | 7 +- ...OAuth2ClientBeanDefinitionParserTests.java | 78 +- .../OAuth2LoginBeanDefinitionParserTests.java | 91 +- ...sourceServerBeanDefinitionParserTests.java | 480 +++----- .../config/http/OpenIDConfigTests.java | 77 +- .../http/PlaceHolderAndELConfigTests.java | 70 +- .../config/http/RememberMeConfigTests.java | 146 +-- ...yContextHolderAwareRequestConfigTests.java | 94 +- .../http/SecurityFiltersAssertions.java | 9 +- ...SessionManagementConfigServlet31Tests.java | 33 +- .../http/SessionManagementConfigTests.java | 257 ++--- ...entConfigTransientAuthenticationTests.java | 14 +- .../config/http/WebConfigUtilsTests.java | 5 +- .../customconfigurer/CustomConfigurer.java | 9 +- .../CustomHttpSecurityConfigurerTests.java | 6 + .../security/config/method/Contact.java | 2 + .../config/method/ContactPermission.java | 4 +- ...thodSecurityBeanDefinitionParserTests.java | 156 ++- ...ptMethodsBeanDefinitionDecoratorTests.java | 20 +- ...tationDrivenBeanDefinitionParserTests.java | 20 +- .../method/PreAuthorizeServiceImpl.java | 6 +- .../config/method/PreAuthorizeTests.java | 15 +- .../security/config/method/Sec2196Tests.java | 12 +- .../config/method/SecuredAdminRole.java | 4 +- ...tationDrivenBeanDefinitionParserTests.java | 15 +- .../config/method/SecuredServiceImpl.java | 12 +- .../security/config/method/SecuredTests.java | 9 +- .../method/TestPermissionEvaluator.java | 7 +- ...lobalMethodSecurityConfigurationTests.java | 8 + .../sec2136/JpaPermissionEvaluator.java | 10 +- .../config/method/sec2136/Sec2136Tests.java | 2 +- .../config/method/sec2499/Sec2499Tests.java | 6 +- ...egistrationsBeanDefinitionParserTests.java | 113 +- .../client/CommonOAuth2ProviderTests.java | 80 +- ...ceFactoryBeanPropertiesResourceITests.java | 5 +- ...yBeanPropertiesResourceLocationITests.java | 5 +- ...anagerResourceFactoryBeanStringITests.java | 5 +- .../config/test/SpringTestContext.java | 27 +- .../security/config/test/SpringTestRule.java | 8 +- .../AuthenticationTestConfiguration.java | 2 + ...activeAuthenticationTestConfiguration.java | 2 + .../util/InMemoryXmlApplicationContext.java | 5 +- .../InMemoryXmlWebApplicationContext.java | 4 +- .../server/AuthorizeExchangeSpecTests.java | 107 +- .../config/web/server/CorsSpecTests.java | 23 +- .../server/ExceptionHandlingSpecTests.java | 182 +-- .../config/web/server/FormLoginTests.java | 340 ++---- .../config/web/server/HeaderSpecTests.java | 144 +-- .../web/server/HttpsRedirectSpecTests.java | 73 +- .../config/web/server/LogoutSpecTests.java | 194 +--- .../web/server/OAuth2ClientSpecTests.java | 94 +- .../config/web/server/OAuth2LoginTests.java | 249 ++-- .../server/OAuth2ResourceServerSpecTests.java | 263 ++--- .../config/web/server/RequestCacheTests.java | 101 +- .../web/server/ServerHttpSecurityTests.java | 273 ++--- .../web/server/TestingServerHttpSecurity.java | 5 +- .../MessageSecurityPostProcessorTests.java | 5 +- .../WebSocketMessageBrokerConfigTests.java | 76 +- .../server/HtmlUnitWebTestClient.java | 72 +- .../server/MockWebResponseBuilder.java | 13 +- .../WebTestClientHtmlUnitDriverBuilder.java | 5 +- ...bTestClientHtmlUnitDriverBuilderTests.java | 42 +- .../server/WebTestClientWebConnection.java | 16 +- ...SecurityInterceptorWithAopConfigTests.java | 42 +- .../access/AccessDecisionManager.java | 13 +- .../security/access/AccessDecisionVoter.java | 13 +- .../access/AccessDeniedException.java | 4 +- .../access/AfterInvocationProvider.java | 11 +- .../access/AuthorizationServiceException.java | 4 +- .../security/access/ConfigAttribute.java | 3 +- .../access/PermissionCacheOptimizer.java | 3 +- .../security/access/PermissionEvaluator.java | 11 +- .../security/access/SecurityConfig.java | 5 +- .../access/SecurityMetadataSource.java | 11 +- .../AnnotationMetadataExtractor.java | 1 + .../Jsr250MethodSecurityMetadataSource.java | 8 +- .../annotation/Jsr250SecurityConfig.java | 8 +- .../access/annotation/Jsr250Voter.java | 7 +- .../security/access/annotation/Secured.java | 6 +- ...curedAnnotationSecurityMetadataSource.java | 19 +- .../event/AbstractAuthorizationEvent.java | 3 +- ...uthenticationCredentialsNotFoundEvent.java | 10 +- .../event/AuthorizationFailureEvent.java | 17 +- .../access/event/AuthorizedEvent.java | 10 +- .../security/access/event/LoggerListener.java | 25 +- .../access/event/PublicInvocationEvent.java | 3 +- .../security/access/event/package-info.java | 1 - .../AbstractSecurityExpressionHandler.java | 28 +- .../DenyAllPermissionEvaluator.java | 15 +- .../access/expression/ExpressionUtils.java | 4 +- .../expression/SecurityExpressionHandler.java | 2 + .../SecurityExpressionOperations.java | 10 +- .../expression/SecurityExpressionRoot.java | 26 +- ...tExpressionBasedMethodConfigAttribute.java | 20 +- ...efaultMethodSecurityExpressionHandler.java | 82 +- ...essionBasedAnnotationAttributeFactory.java | 44 +- .../ExpressionBasedPostInvocationAdvice.java | 23 +- .../ExpressionBasedPreInvocationAdvice.java | 28 +- .../MethodSecurityEvaluationContext.java | 5 +- .../MethodSecurityExpressionHandler.java | 6 +- .../MethodSecurityExpressionOperations.java | 2 + .../method/MethodSecurityExpressionRoot.java | 8 +- .../PostInvocationExpressionAttribute.java | 20 +- .../PreInvocationExpressionAttribute.java | 21 +- .../expression/method/package-info.java | 1 - .../access/expression/package-info.java | 7 +- .../hierarchicalroles/NullRoleHierarchy.java | 1 - .../hierarchicalroles/RoleHierarchy.java | 1 - .../RoleHierarchyAuthoritiesMapper.java | 5 +- .../hierarchicalroles/RoleHierarchyImpl.java | 58 +- .../hierarchicalroles/RoleHierarchyUtils.java | 10 +- .../hierarchicalroles/package-info.java | 1 - .../AbstractSecurityInterceptor.java | 131 +-- .../intercept/AfterInvocationManager.java | 14 +- .../AfterInvocationProviderManager.java | 23 +- .../intercept/InterceptorStatusToken.java | 10 +- .../MethodInvocationPrivilegeEvaluator.java | 20 +- .../access/intercept/NullRunAsManager.java | 5 +- .../RunAsImplAuthenticationProvider.java | 15 +- .../access/intercept/RunAsManager.java | 11 +- .../access/intercept/RunAsManagerImpl.java | 17 +- .../access/intercept/RunAsUserToken.java | 7 +- .../MethodSecurityInterceptor.java | 8 +- .../MethodSecurityMetadataSourceAdvisor.java | 43 +- .../intercept/aopalliance/package-info.java | 4 +- .../intercept/aspectj/AspectJCallback.java | 2 + .../AspectJMethodSecurityInterceptor.java | 7 +- .../aspectj/MethodInvocationAdapter.java | 10 +- .../intercept/aspectj/package-info.java | 4 +- .../access/intercept/package-info.java | 30 +- ...tFallbackMethodSecurityMetadataSource.java | 8 +- .../AbstractMethodSecurityMetadataSource.java | 4 +- ...elegatingMethodSecurityMetadataSource.java | 31 +- .../MapBasedMethodSecurityMetadataSource.java | 70 +- .../method/MethodSecurityMetadataSource.java | 2 + .../security/access/method/P.java | 1 + .../security/access/method/package-info.java | 5 +- .../security/access/package-info.java | 9 +- .../access/prepost/PostAuthorize.java | 2 + .../security/access/prepost/PostFilter.java | 2 + .../prepost/PostInvocationAdviceProvider.java | 13 +- .../prepost/PostInvocationAttribute.java | 4 +- .../PostInvocationAuthorizationAdvice.java | 4 +- .../security/access/prepost/PreAuthorize.java | 2 + .../security/access/prepost/PreFilter.java | 2 + .../prepost/PreInvocationAttribute.java | 4 +- .../PreInvocationAuthorizationAdvice.java | 9 +- ...PreInvocationAuthorizationAdviceVoter.java | 11 +- ...rePostAdviceReactiveMethodInterceptor.java | 53 +- ...ePostAnnotationSecurityMetadataSource.java | 51 +- .../PrePostInvocationAttributeFactory.java | 9 +- .../security/access/prepost/package-info.java | 9 +- .../vote/AbstractAccessDecisionManager.java | 14 +- .../access/vote/AbstractAclVoter.java | 7 +- .../access/vote/AffirmativeBased.java | 11 +- .../access/vote/AuthenticatedVoter.java | 30 +- .../security/access/vote/ConsensusBased.java | 19 +- .../access/vote/RoleHierarchyVoter.java | 8 +- .../security/access/vote/RoleVoter.java | 14 +- .../security/access/vote/UnanimousBased.java | 12 +- .../security/access/vote/package-info.java | 1 - .../AbstractAuthenticationToken.java | 25 +- ...rDetailsReactiveAuthenticationManager.java | 57 +- .../AccountExpiredException.java | 4 +- .../AccountStatusException.java | 2 + .../AccountStatusUserDetailsChecker.java | 20 +- .../AnonymousAuthenticationProvider.java | 16 +- .../AnonymousAuthenticationToken.java | 22 +- ...nticationCredentialsNotFoundException.java | 4 +- .../AuthenticationDetailsSource.java | 4 +- .../AuthenticationEventPublisher.java | 5 +- .../authentication/AuthenticationManager.java | 8 +- .../AuthenticationManagerResolver.java | 4 +- .../AuthenticationProvider.java | 10 +- .../AuthenticationServiceException.java | 4 +- .../AuthenticationTrustResolver.java | 6 +- .../AuthenticationTrustResolverImpl.java | 3 + .../BadCredentialsException.java | 4 +- .../CachingUserDetailsService.java | 7 +- .../CredentialsExpiredException.java | 4 +- .../DefaultAuthenticationEventPublisher.java | 102 +- ...legatingReactiveAuthenticationManager.java | 20 +- .../authentication/DisabledException.java | 4 +- .../InsufficientAuthenticationException.java | 4 +- ...nternalAuthenticationServiceException.java | 4 +- .../authentication/LockedException.java | 4 +- .../authentication/ProviderManager.java | 85 +- .../ProviderNotFoundException.java | 3 +- .../ReactiveAuthenticationManager.java | 2 +- .../ReactiveAuthenticationManagerAdapter.java | 26 +- ...ReactiveAuthenticationManagerResolver.java | 5 +- .../RememberMeAuthenticationProvider.java | 17 +- .../RememberMeAuthenticationToken.java | 24 +- .../TestingAuthenticationProvider.java | 5 +- .../TestingAuthenticationToken.java | 10 +- ...positoryReactiveAuthenticationManager.java | 7 +- .../UsernamePasswordAuthenticationToken.java | 3 +- ...ractUserDetailsAuthenticationProvider.java | 90 +- .../dao/DaoAuthenticationProvider.java | 39 +- .../authentication/dao/package-info.java | 1 - .../event/AbstractAuthenticationEvent.java | 3 +- .../AbstractAuthenticationFailureEvent.java | 8 +- ...henticationFailureBadCredentialsEvent.java | 8 +- ...icationFailureCredentialsExpiredEvent.java | 5 +- .../AuthenticationFailureDisabledEvent.java | 8 +- .../AuthenticationFailureExpiredEvent.java | 5 +- .../AuthenticationFailureLockedEvent.java | 5 +- ...nticationFailureProviderNotFoundEvent.java | 5 +- ...henticationFailureProxyUntrustedEvent.java | 8 +- ...nticationFailureServiceExceptionEvent.java | 5 +- .../event/AuthenticationSuccessEvent.java | 2 + ...InteractiveAuthenticationSuccessEvent.java | 6 +- .../authentication/event/LoggerListener.java | 11 +- .../authentication/event/package-info.java | 9 +- .../AbstractJaasAuthenticationProvider.java | 85 +- .../authentication/jaas/AuthorityGranter.java | 4 +- .../DefaultJaasAuthenticationProvider.java | 9 +- .../jaas/DefaultLoginExceptionResolver.java | 2 + .../JaasAuthenticationCallbackHandler.java | 19 +- .../jaas/JaasAuthenticationProvider.java | 30 +- .../jaas/JaasAuthenticationToken.java | 8 +- .../jaas/JaasGrantedAuthority.java | 3 +- .../jaas/JaasNameCallbackHandler.java | 12 +- .../jaas/JaasPasswordCallbackHandler.java | 15 +- .../jaas/LoginExceptionResolver.java | 4 +- .../jaas/SecurityContextLoginModule.java | 19 +- .../jaas/event/JaasAuthenticationEvent.java | 4 +- .../event/JaasAuthenticationFailedEvent.java | 2 + .../event/JaasAuthenticationSuccessEvent.java | 2 + .../jaas/event/package-info.java | 5 +- .../jaas/memory/InMemoryConfiguration.java | 15 +- .../jaas/memory/package-info.java | 1 - .../authentication/jaas/package-info.java | 1 - .../security/authentication/package-info.java | 13 +- .../rcp/RemoteAuthenticationException.java | 2 +- .../rcp/RemoteAuthenticationManager.java | 9 +- .../rcp/RemoteAuthenticationManagerImpl.java | 12 +- .../rcp/RemoteAuthenticationProvider.java | 21 +- .../authentication/rcp/package-info.java | 4 +- ...enticatedReactiveAuthorizationManager.java | 13 +- ...AuthorityReactiveAuthorizationManager.java | 17 +- .../authorization/AuthorizationDecision.java | 2 + .../ReactiveAuthorizationManager.java | 16 +- ...tractDelegatingSecurityContextSupport.java | 2 +- .../DelegatingSecurityContextCallable.java | 34 +- .../DelegatingSecurityContextExecutor.java | 10 +- ...egatingSecurityContextExecutorService.java | 24 +- .../DelegatingSecurityContextRunnable.java | 19 +- ...curityContextScheduledExecutorService.java | 23 +- .../DelegatingApplicationListener.java | 9 +- .../security/converter/RsaKeyConverters.java | 54 +- .../security/core/AuthenticatedPrincipal.java | 16 +- .../security/core/Authentication.java | 9 +- .../core/AuthenticationException.java | 2 - .../security/core/ComparableVersion.java | 37 +- .../security/core/CredentialsContainer.java | 2 + .../security/core/GrantedAuthority.java | 3 +- .../core/SpringSecurityCoreVersion.java | 19 +- .../core/SpringSecurityMessageSource.java | 2 + .../security/core/Transient.java | 7 +- .../annotation/AuthenticationPrincipal.java | 3 +- .../annotation/CurrentSecurityContext.java | 19 +- .../core/authority/AuthorityUtils.java | 13 +- .../GrantedAuthoritiesContainer.java | 2 + .../authority/SimpleGrantedAuthority.java | 1 + .../Attributes2GrantedAuthoritiesMapper.java | 6 +- .../mapping/GrantedAuthoritiesMapper.java | 5 +- ...edAttributes2GrantedAuthoritiesMapper.java | 44 +- .../mapping/MappableAttributesRetriever.java | 3 +- .../mapping/NullAuthoritiesMapper.java | 5 +- ...leAttributes2GrantedAuthoritiesMapper.java | 9 +- .../mapping/SimpleAuthorityMapper.java | 20 +- .../SimpleMappableAttributesRetriever.java | 1 + .../core/authority/mapping/package-info.java | 5 +- .../security/core/authority/package-info.java | 1 - .../GlobalSecurityContextHolderStrategy.java | 2 + ...eadLocalSecurityContextHolderStrategy.java | 6 +- .../ReactiveSecurityContextHolder.java | 8 +- .../core/context/SecurityContext.java | 4 +- .../core/context/SecurityContextHolder.java | 16 +- .../SecurityContextHolderStrategy.java | 5 +- .../core/context/SecurityContextImpl.java | 4 +- ...eadLocalSecurityContextHolderStrategy.java | 6 +- .../security/core/context/package-info.java | 16 +- .../security/core/package-info.java | 5 +- .../AnnotationParameterNameDiscoverer.java | 28 +- ...efaultSecurityParameterNameDiscoverer.java | 14 +- .../security/core/parameters/P.java | 1 + .../core/session/AbstractSessionEvent.java | 1 + .../core/session/SessionCreationEvent.java | 1 + .../core/session/SessionDestroyedEvent.java | 2 +- .../core/session/SessionIdChangedEvent.java | 10 +- .../core/session/SessionInformation.java | 4 + .../core/session/SessionRegistry.java | 13 +- .../core/session/SessionRegistryImpl.java | 44 +- .../security/core/session/package-info.java | 10 +- .../security/core/token/DefaultToken.java | 10 +- .../KeyBasedPersistenceTokenService.java | 24 +- .../core/token/SecureRandomFactoryBean.java | 4 +- .../core/token/Sha512DigestUtils.java | 5 - .../security/core/token/Token.java | 4 +- .../security/core/token/TokenService.java | 4 +- .../security/core/token/package-info.java | 1 - .../AuthenticationUserDetailsService.java | 2 +- .../MapReactiveUserDetailsService.java | 16 +- .../ReactiveUserDetailsPasswordService.java | 3 +- .../ReactiveUserDetailsService.java | 1 + .../security/core/userdetails/User.java | 111 +- .../security/core/userdetails/UserCache.java | 7 +- .../core/userdetails/UserDetails.java | 13 +- .../UserDetailsByNameServiceWrapper.java | 8 +- .../core/userdetails/UserDetailsChecker.java | 3 +- .../UserDetailsPasswordService.java | 7 +- .../core/userdetails/UserDetailsService.java | 6 +- .../UsernameNotFoundException.java | 4 +- .../cache/EhCacheBasedUserCache.java | 6 +- .../core/userdetails/cache/NullUserCache.java | 2 + .../cache/SpringCacheBasedUserCache.java | 1 + .../core/userdetails/cache/package-info.java | 4 +- .../core/userdetails/jdbc/JdbcDaoImpl.java | 101 +- .../core/userdetails/jdbc/package-info.java | 1 - .../userdetails/memory/UserAttribute.java | 10 +- .../memory/UserAttributeEditor.java | 2 + .../core/userdetails/memory/package-info.java | 1 - .../core/userdetails/package-info.java | 10 +- .../AnonymousAuthenticationTokenMixin.java | 21 +- .../BadCredentialsExceptionMixin.java | 16 +- .../security/jackson2/CoreJackson2Module.java | 26 +- .../RememberMeAuthenticationTokenMixin.java | 23 +- .../jackson2/SecurityJackson2Modules.java | 95 +- .../jackson2/SimpleGrantedAuthorityMixin.java | 6 +- .../UnmodifiableListDeserializer.java | 4 +- .../jackson2/UnmodifiableListMixin.java | 4 +- .../jackson2/UnmodifiableSetDeserializer.java | 4 +- .../jackson2/UnmodifiableSetMixin.java | 8 +- .../security/jackson2/UserDeserializer.java | 27 +- .../security/jackson2/UserMixin.java | 13 +- ...sswordAuthenticationTokenDeserializer.java | 39 +- ...rnamePasswordAuthenticationTokenMixin.java | 13 +- .../security/provisioning/GroupManager.java | 6 +- .../InMemoryUserDetailsManager.java | 29 +- .../provisioning/JdbcUserDetailsManager.java | 151 +-- .../security/provisioning/MutableUser.java | 3 +- .../provisioning/MutableUserDetails.java | 1 - .../provisioning/UserDetailsManager.java | 1 - .../security/provisioning/package-info.java | 5 +- ...SecurityContextSchedulingTaskExecutor.java | 13 +- ...elegatingSecurityContextTaskScheduler.java | 6 +- ...atingSecurityContextAsyncTaskExecutor.java | 14 +- ...DelegatingSecurityContextTaskExecutor.java | 13 +- .../security/util/FieldUtils.java | 16 +- .../security/util/InMemoryResource.java | 3 + .../security/util/MethodInvocationUtils.java | 18 +- .../security/util/SimpleMethodInvocation.java | 4 + .../security/util/package-info.java | 8 +- .../security/ITargetObject.java | 2 + .../security/OtherTargetObject.java | 2 + .../security/PopulatedDatabase.java | 44 +- .../security/TargetObject.java | 13 +- .../security/TestDataSource.java | 2 + ...ticationCredentialsNotFoundEventTests.java | 8 +- .../AuthorizationFailureEventTests.java | 16 +- .../security/access/AuthorizedEventTests.java | 7 +- .../security/access/SecurityConfigTests.java | 4 +- .../access/annotation/BusinessService.java | 1 + .../annotation/BusinessServiceImpl.java | 2 +- .../security/access/annotation/Entity.java | 2 + ...xpressionProtectedBusinessServiceImpl.java | 1 + .../annotation/Jsr250BusinessServiceImpl.java | 2 +- ...r250MethodSecurityMetadataSourceTests.java | 52 +- .../access/annotation/Jsr250VoterTests.java | 22 +- ...AnnotationSecurityMetadataSourceTests.java | 80 +- .../annotation/sec2150/CrudRepository.java | 1 + .../sec2150/MethodInvocationFactory.java | 5 +- .../annotation/sec2150/PersonRepository.java | 1 + ...bstractSecurityExpressionHandlerTests.java | 17 +- .../SecurityExpressionRootTests.java | 7 +- ...tMethodSecurityExpressionHandlerTests.java | 32 +- ...pressionBasedPreInvocationAdviceTests.java | 74 +- .../method/MethodExpressionVoterTests.java | 71 +- .../MethodSecurityEvaluationContextTests.java | 17 +- .../MethodSecurityExpressionRootTests.java | 10 +- ...AnnotationSecurityMetadataSourceTests.java | 105 +- .../expression/method/SecurityRules.java | 2 + .../HierarchicalRolesTestHelper.java | 12 +- .../RoleHierarchyAuthoritiesMapperTests.java | 4 +- .../RoleHierarchyImplTests.java | 183 ++- .../RoleHierarchyUtilsTests.java | 2 + .../hierarchicalroles/TestHelperTests.java | 149 +-- .../AbstractSecurityInterceptorTests.java | 15 +- .../AfterInvocationProviderManagerTests.java | 75 +- .../InterceptorStatusTokenTests.java | 1 + .../intercept/NullRunAsManagerTests.java | 2 + .../RunAsImplAuthenticationProviderTests.java | 10 +- .../intercept/RunAsManagerImplTests.java | 20 +- .../access/intercept/RunAsUserTokenTests.java | 18 +- .../MethodSecurityInterceptorTests.java | 63 +- ...hodSecurityMetadataSourceAdvisorTests.java | 16 +- ...AspectJMethodSecurityInterceptorTests.java | 31 +- ...asedMethodSecurityMetadataSourceTests.java | 8 + ...thodInvocationPrivilegeEvaluatorTests.java | 22 +- .../method/MockMethodInvocation.java | 10 +- ...tingMethodSecurityMetadataSourceTests.java | 9 +- ...vocationAuthorizationAdviceVoterTests.java | 3 + .../AbstractAccessDecisionManagerTests.java | 12 +- .../access/vote/AbstractAclVoterTests.java | 11 +- .../access/vote/AffirmativeBasedTests.java | 31 +- .../access/vote/AuthenticatedVoterTests.java | 52 +- .../access/vote/ConsensusBasedTests.java | 7 +- .../security/access/vote/DenyAgainVoter.java | 4 +- .../security/access/vote/DenyVoter.java | 5 +- .../access/vote/RoleHierarchyVoterTests.java | 7 +- .../security/access/vote/RoleVoterTests.java | 9 +- .../access/vote/SomeDomainObject.java | 2 + .../access/vote/SomeDomainObjectManager.java | 2 + .../access/vote/UnanimousBasedTests.java | 13 +- .../AbstractAuthenticationTokenTests.java | 47 +- .../AuthenticationTrustResolverImplTests.java | 33 +- ...aultAuthenticationEventPublisherTests.java | 72 +- ...ingReactiveAuthenticationManagerTests.java | 26 +- .../authentication/ProviderManagerTests.java | 81 +- ...tiveAuthenticationManagerAdapterTests.java | 7 +- ...ailsServiceAuthenticationManagerTests.java | 35 +- .../authentication/TestAuthentication.java | 1 + .../TestingAuthenticationProviderTests.java | 8 +- .../TestingAuthenticationTokenTests.java | 12 +- ...oryReactiveAuthenticationManagerTests.java | 43 +- ...rnamePasswordAuthenticationTokenTests.java | 8 +- .../AnonymousAuthenticationProviderTests.java | 28 +- .../AnonymousAuthenticationTokenTests.java | 44 +- .../dao/DaoAuthenticationProviderTests.java | 146 +-- .../authentication/dao/MockUserCache.java | 2 + .../event/AuthenticationEventTests.java | 9 +- .../event/LoggerListenerTests.java | 10 +- ...efaultJaasAuthenticationProviderTests.java | 23 +- .../jaas/JaasAuthenticationProviderTests.java | 63 +- .../authentication/jaas/JaasEventCheck.java | 3 + .../jaas/JaasGrantedAuthorityTests.java | 8 +- .../authentication/jaas/Sec760Tests.java | 24 +- .../jaas/SecurityContextLoginModuleTests.java | 31 +- .../jaas/TestAuthorityGranter.java | 3 +- .../jaas/TestCallbackHandler.java | 2 + .../authentication/jaas/TestLoginModule.java | 10 +- .../memory/InMemoryConfigurationTests.java | 43 +- .../RemoteAuthenticationManagerImplTests.java | 8 +- .../RemoteAuthenticationProviderTests.java | 29 +- ...RememberMeAuthenticationProviderTests.java | 27 +- .../RememberMeAuthenticationTokenTests.java | 38 +- ...atedReactiveAuthorizationManagerTests.java | 9 +- ...rityReactiveAuthorizationManagerTests.java | 10 +- ...ngSecurityContextExecutorServiceTests.java | 25 +- ...elegatingSecurityContextExecutorTests.java | 6 +- ...yContextScheduledExecutorServiceTests.java | 28 +- ...tDelegatingSecurityContextTestSupport.java | 19 +- ...ngSecurityContextExecutorServiceTests.java | 5 +- ...elegatingSecurityContextExecutorTests.java | 4 +- ...yContextScheduledExecutorServiceTests.java | 4 +- ...elegatingSecurityContextCallableTests.java | 17 +- ...elegatingSecurityContextRunnableTests.java | 11 +- ...DelegatingSecurityContextSupportTests.java | 11 +- ...ngSecurityContextExecutorServiceTests.java | 5 +- ...elegatingSecurityContextExecutorTests.java | 4 +- ...yContextScheduledExecutorServiceTests.java | 8 +- .../DelegatingApplicationListenerTests.java | 1 + .../converter/RsaKeyConvertersTests.java | 100 +- .../security/core/JavaVersionTests.java | 2 +- .../core/SpringSecurityCoreVersionTests.java | 7 +- .../SpringSecurityMessageSourceTests.java | 13 +- .../core/authority/AuthorityUtilsTests.java | 1 + ...ributes2GrantedAuthoritiesMapperTests.java | 30 +- .../mapping/SimpleAuthoritiesMapperTests.java | 15 +- .../SimpleMappableRolesRetrieverTests.java | 7 +- ...leRoles2GrantedAuthoritiesMapperTests.java | 13 +- .../ReactiveSecurityContextHolderTests.java | 48 +- .../context/SecurityContextHolderTests.java | 4 +- .../context/SecurityContextImplTests.java | 1 + ...nnotationParameterNameDiscovererTests.java | 91 +- ...tSecurityParameterNameDiscovererTests.java | 20 +- .../core/session/SessionInformationTests.java | 4 +- .../session/SessionRegistryImplTests.java | 17 +- .../core/token/DefaultTokenTests.java | 2 + .../KeyBasedPersistenceTokenServiceTests.java | 1 + .../token/SecureRandomFactoryBeanTests.java | 5 +- .../MapReactiveUserDetailsServiceTests.java | 3 +- .../userdetails/MockUserDetailsService.java | 9 +- .../core/userdetails/PasswordEncodedUser.java | 8 +- .../UserDetailsByNameServiceWrapperTests.java | 12 +- .../security/core/userdetails/UserTests.java | 36 +- .../cache/EhCacheBasedUserCacheTests.java | 5 +- .../userdetails/cache/NullUserCacheTests.java | 1 + .../cache/SpringCacheBasedUserCacheTests.java | 2 + .../userdetails/jdbc/JdbcDaoImplTests.java | 16 +- .../memory/UserAttributeEditorTests.java | 1 + .../security/jackson2/AbstractMixinTests.java | 2 + ...nonymousAuthenticationTokenMixinTests.java | 21 +- .../BadCredentialsExceptionMixinTests.java | 1 + ...memberMeAuthenticationTokenMixinTests.java | 26 +- .../jackson2/SecurityContextMixinTests.java | 4 +- .../SecurityJackson2ModulesTests.java | 24 +- .../SimpleGrantedAuthorityMixinTests.java | 1 + .../jackson2/UserDeserializerTests.java | 13 +- ...PasswordAuthenticationTokenMixinTests.java | 68 +- .../InMemoryUserDetailsManagerTests.java | 9 +- .../JdbcUserDetailsManagerTests.java | 55 +- ...ityContextSchedulingTaskExecutorTests.java | 5 +- ...ityContextSchedulingTaskExecutorTests.java | 5 +- ...tingSecurityContextTaskSchedulerTests.java | 5 +- ...ityContextSchedulingTaskExecutorTests.java | 8 +- ...SecurityContextAsyncTaskExecutorTests.java | 6 +- ...SecurityContextAsyncTaskExecutorTests.java | 4 +- ...atingSecurityContextTaskExecutorTests.java | 5 +- ...SecurityContextAsyncTaskExecutorTests.java | 7 +- ...atingSecurityContextTaskExecutorTests.java | 8 +- .../security/util/FieldUtilsTests.java | 7 +- .../security/util/InMemoryResourceTests.java | 1 + .../util/MethodInvocationUtilsTests.java | 23 +- .../crypto/argon2/Argon2EncodingUtils.java | 91 +- .../crypto/argon2/Argon2PasswordEncoder.java | 37 +- .../security/crypto/bcrypt/BCrypt.java | 700 +++++------- .../crypto/bcrypt/BCryptPasswordEncoder.java | 33 +- .../security/crypto/codec/Base64.java | 142 +-- .../security/crypto/codec/Hex.java | 9 +- .../security/crypto/codec/Utf8.java | 2 + .../security/crypto/codec/package-info.java | 1 - .../crypto/encrypt/AesBytesEncryptor.java | 41 +- .../BouncyCastleAesBytesEncryptor.java | 8 +- .../BouncyCastleAesCbcBytesEncryptor.java | 13 +- .../BouncyCastleAesGcmBytesEncryptor.java | 12 +- .../crypto/encrypt/BytesEncryptor.java | 1 + .../security/crypto/encrypt/CipherUtils.java | 22 +- .../security/crypto/encrypt/Encryptors.java | 21 +- .../encrypt/HexEncodingTextEncryptor.java | 1 + .../factory/PasswordEncoderFactories.java | 21 +- .../keygen/Base64StringKeyGenerator.java | 4 + .../crypto/keygen/BytesKeyGenerator.java | 1 + .../keygen/HexEncodingStringKeyGenerator.java | 1 + .../security/crypto/keygen/KeyGenerators.java | 2 + .../crypto/keygen/StringKeyGenerator.java | 1 + .../password/AbstractPasswordEncoder.java | 1 + .../password/DelegatingPasswordEncoder.java | 47 +- .../security/crypto/password/Digester.java | 1 + .../password/LdapShaPasswordEncoder.java | 24 +- .../security/crypto/password/Md4.java | 12 +- .../crypto/password/Md4PasswordEncoder.java | 30 +- .../MessageDigestPasswordEncoder.java | 16 +- .../crypto/password/NoOpPasswordEncoder.java | 10 +- .../crypto/password/PasswordEncoder.java | 2 +- .../crypto/password/PasswordEncoderUtils.java | 4 +- .../password/Pbkdf2PasswordEncoder.java | 33 +- .../password/StandardPasswordEncoder.java | 8 +- .../crypto/scrypt/SCryptPasswordEncoder.java | 56 +- .../argon2/Argon2EncodingUtilsTests.java | 72 +- .../argon2/Argon2PasswordEncoderTests.java | 7 +- .../bcrypt/BCryptPasswordEncoderTests.java | 21 +- .../security/crypto/bcrypt/BCryptTests.java | 31 +- .../security/crypto/codec/Base64Tests.java | 7 +- .../security/crypto/codec/HexTests.java | 7 +- .../security/crypto/codec/Utf8Tests.java | 1 + .../encrypt/AesBytesEncryptorTests.java | 6 +- ...stleAesBytesEncryptorEquivalencyTests.java | 19 +- .../BouncyCastleAesBytesEncryptorTests.java | 9 +- .../crypto/encrypt/CryptoAssumptions.java | 10 +- .../crypto/encrypt/EncryptorsTests.java | 9 +- .../PasswordEncoderFactoriesTests.java | 1 + .../keygen/Base64StringKeyGeneratorTests.java | 2 + .../DelegatingPasswordEncoderTests.java | 28 +- .../password/LdapShaPasswordEncoderTests.java | 2 + .../password/Md4PasswordEncoderTests.java | 3 +- .../MessageDigestPasswordEncoderTests.java | 4 +- .../password/PasswordEncoderUtilsTests.java | 1 + .../password/Pbkdf2PasswordEncoderTests.java | 15 +- .../scrypt/SCryptPasswordEncoderTests.java | 2 +- .../crypto/util/EncodingUtilsTests.java | 19 +- .../SecurityEvaluationContextExtension.java | 6 +- ...curityEvaluationContextExtensionTests.java | 14 +- ...amespaceWithMultipleInterceptorsTests.java | 7 +- .../HttpPathParameterStrippingTests.java | 11 +- .../integration/MultiAnnotationTests.java | 11 +- .../SEC933ApplicationContextTests.java | 1 + .../SEC936ApplicationContextTests.java | 9 +- .../integration/StubUserRepository.java | 1 + .../PythonInterpreterBasedSecurityTests.java | 5 +- .../FilterChainPerformanceTests.java | 19 +- .../ProtectPointcutPerformanceTests.java | 7 +- .../integration/UserDetailsServiceImpl.java | 1 + .../MultiAnnotationService.java | 1 + .../multiannotation/PreAuthorizeService.java | 2 +- .../PreAuthorizeServiceImpl.java | 2 + .../multiannotation/SecuredService.java | 3 +- .../multiannotation/SecuredServiceImpl.java | 3 +- ...PythonInterpreterPostInvocationAdvice.java | 9 +- .../PythonInterpreterPreInvocationAdvice.java | 14 +- ...thonInterpreterPreInvocationAttribute.java | 2 + ...eterPrePostInvocationAttributeFactory.java | 12 +- .../AbstractWebServerIntegrationTests.java | 7 +- .../integration/BasicAuthenticationTests.java | 16 +- .../ConcurrentSessionManagementTests.java | 57 +- .../security/itest/web/TestController.java | 1 + .../ldap/ApacheDsContainerConfig.java | 7 +- ...faultSpringSecurityContextSourceTests.java | 48 +- .../SpringSecurityLdapTemplateITests.java | 49 +- .../BindAuthenticatorTests.java | 48 +- .../PasswordComparisonAuthenticatorTests.java | 26 +- .../FilterBasedLdapUserSearchTests.java | 22 +- .../ldap/server/ApacheDSContainerTests.java | 39 +- .../server/ApacheDSEmbeddedLdifTests.java | 13 +- .../server/UnboundIdContainerLdifTests.java | 25 +- .../ldap/server/UnboundIdContainerTests.java | 12 +- .../DefaultLdapAuthoritiesPopulatorTests.java | 62 +- ...UserDetailsManagerModifyPasswordTests.java | 19 +- .../LdapUserDetailsManagerTests.java | 22 +- .../NestedLdapAuthoritiesPopulatorTests.java | 63 +- .../ldap/DefaultLdapUsernameToDnMapper.java | 3 + .../DefaultSpringSecurityContextSource.java | 10 +- .../security/ldap/LdapEncoder.java | 486 ++++---- .../security/ldap/LdapUsernameToDnMapper.java | 2 + .../security/ldap/LdapUtils.java | 19 +- .../ldap/SpringSecurityLdapTemplate.java | 85 +- .../AbstractLdapAuthenticationProvider.java | 57 +- .../AbstractLdapAuthenticator.java | 14 +- .../authentication/BindAuthenticator.java | 28 +- .../LdapAuthenticationProvider.java | 35 +- .../authentication/LdapAuthenticator.java | 4 +- .../ldap/authentication/LdapEncoder.java | 486 ++++---- .../NullLdapAuthoritiesPopulator.java | 6 +- .../PasswordComparisonAuthenticator.java | 28 +- .../SpringSecurityAuthenticationSource.java | 15 +- ...etailsServiceLdapAuthoritiesPopulator.java | 10 +- ...ctiveDirectoryAuthenticationException.java | 5 +- ...veDirectoryLdapAuthenticationProvider.java | 103 +- .../ldap/authentication/package-info.java | 12 +- .../security/ldap/package-info.java | 1 - .../PasswordPolicyAwareContextSource.java | 16 +- .../ldap/ppolicy/PasswordPolicyControl.java | 5 +- .../PasswordPolicyControlExtractor.java | 4 +- .../ppolicy/PasswordPolicyControlFactory.java | 4 +- .../ldap/ppolicy/PasswordPolicyData.java | 2 + .../ppolicy/PasswordPolicyErrorStatus.java | 29 +- .../ldap/ppolicy/PasswordPolicyException.java | 2 + .../PasswordPolicyResponseControl.java | 56 +- .../security/ldap/ppolicy/package-info.java | 8 +- .../search/FilterBasedLdapUserSearch.java | 45 +- .../security/ldap/search/LdapUserSearch.java | 4 +- .../security/ldap/search/package-info.java | 4 +- .../ldap/server/ApacheDSContainer.java | 60 +- .../ldap/server/UnboundIdContainer.java | 10 +- .../security/ldap/server/package-info.java | 4 +- .../DefaultLdapAuthoritiesPopulator.java | 43 +- .../ldap/userdetails/InetOrgPerson.java | 24 +- .../InetOrgPersonContextMapper.java | 4 +- .../userdetails/LdapAuthoritiesPopulator.java | 7 +- .../ldap/userdetails/LdapAuthority.java | 9 +- .../ldap/userdetails/LdapUserDetails.java | 3 +- .../ldap/userdetails/LdapUserDetailsImpl.java | 19 +- .../userdetails/LdapUserDetailsManager.java | 143 ++- .../userdetails/LdapUserDetailsMapper.java | 22 +- .../userdetails/LdapUserDetailsService.java | 18 +- .../NestedLdapAuthoritiesPopulator.java | 40 +- .../security/ldap/userdetails/Person.java | 6 + .../ldap/userdetails/PersonContextMapper.java | 1 + .../userdetails/UserDetailsContextMapper.java | 2 +- .../ldap/userdetails/package-info.java | 1 - .../security/ldap/LdapUtilsTests.java | 35 +- ...ringSecurityAuthenticationSourceTests.java | 15 +- .../ldap/SpringSecurityLdapTemplateTests.java | 11 +- .../LdapAuthenticationProviderTests.java | 93 +- .../ldap/authentication/MockUserSearch.java | 4 +- ...swordComparisonAuthenticatorMockTests.java | 17 +- ...ectoryLdapAuthenticationProviderTests.java | 148 +-- .../ppolicy/OpenLDAPIntegrationTestSuite.java | 2 + ...PasswordPolicyAwareContextSourceTests.java | 23 +- .../PasswordPolicyControlFactoryTests.java | 4 +- .../PasswordPolicyResponseControlTests.java | 14 +- .../ldap/userdetails/InetOrgPersonTests.java | 17 +- .../ldap/userdetails/LdapAuthorityTests.java | 5 +- .../LdapUserDetailsMapperTests.java | 14 +- .../LdapUserDetailsServiceTests.java | 22 +- ...sServiceLdapAuthoritiesPopulatorTests.java | 7 +- ...faultMessageSecurityExpressionHandler.java | 12 +- .../EvaluationContextPostProcessor.java | 17 +- ...dMessageSecurityMetadataSourceFactory.java | 12 +- .../MessageExpressionConfigAttribute.java | 13 +- .../expression/MessageExpressionVoter.java | 17 +- .../MessageSecurityExpressionRoot.java | 1 + .../intercept/ChannelSecurityInterceptor.java | 12 +- .../DefaultMessageSecurityMetadataSource.java | 12 +- .../MessageSecurityMetadataSource.java | 2 +- ...thenticationPrincipalArgumentResolver.java | 23 +- .../SecurityContextChannelInterceptor.java | 24 +- ...thenticationPrincipalArgumentResolver.java | 49 +- ...urrentSecurityContextArgumentResolver.java | 55 +- .../AbstractMessageMatcherComposite.java | 7 +- .../util/matcher/AndMessageMatcher.java | 4 +- .../util/matcher/MessageMatcher.java | 1 + .../util/matcher/OrMessageMatcher.java | 4 +- .../SimpDestinationMessageMatcher.java | 53 +- .../util/matcher/SimpMessageTypeMatcher.java | 3 +- .../web/csrf/CsrfChannelInterceptor.java | 8 +- .../server/CsrfTokenHandshakeInterceptor.java | 11 +- ...MessageSecurityExpressionHandlerTests.java | 30 +- ...ageSecurityMetadataSourceFactoryTests.java | 15 +- ...MessageExpressionConfigAttributeTests.java | 5 +- .../MessageExpressionVoterTests.java | 47 +- .../ChannelSecurityInterceptorTests.java | 33 +- ...ultMessageSecurityMetadataSourceTests.java | 9 +- ...icationPrincipalArgumentResolverTests.java | 58 +- ...ecurityContextChannelInterceptorTests.java | 54 +- .../handler/invocation/ResolvableMethod.java | 164 ++- ...icationPrincipalArgumentResolverTests.java | 27 +- ...tSecurityContextArgumentResolverTests.java | 30 +- .../util/matcher/AndMessageMatcherTests.java | 2 + .../util/matcher/OrMessageMatcherTests.java | 2 + .../SimpDestinationMessageMatcherTests.java | 40 +- .../matcher/SimpMessageTypeMatcherTests.java | 14 +- .../web/csrf/CsrfChannelInterceptorTests.java | 5 +- .../CsrfTokenHandshakeInterceptorTests.java | 3 +- ...ionCodeOAuth2AuthorizedClientProvider.java | 26 +- ...eactiveOAuth2AuthorizedClientProvider.java | 32 +- ...tServiceOAuth2AuthorizedClientManager.java | 159 +-- ...ReactiveOAuth2AuthorizedClientManager.java | 173 +-- .../client/ClientAuthorizationException.java | 14 +- .../ClientAuthorizationRequiredException.java | 10 +- ...entialsOAuth2AuthorizedClientProvider.java | 63 +- ...eactiveOAuth2AuthorizedClientProvider.java | 60 +- ...egatingOAuth2AuthorizedClientProvider.java | 24 +- ...eactiveOAuth2AuthorizedClientProvider.java | 37 +- ...InMemoryOAuth2AuthorizedClientService.java | 26 +- ...ReactiveOAuth2AuthorizedClientService.java | 20 +- .../JdbcOAuth2AuthorizedClientService.java | 182 +-- .../client/OAuth2AuthorizationContext.java | 70 +- .../OAuth2AuthorizationFailureHandler.java | 23 +- .../OAuth2AuthorizationSuccessHandler.java | 26 +- .../oauth2/client/OAuth2AuthorizeRequest.java | 64 +- .../oauth2/client/OAuth2AuthorizedClient.java | 26 +- .../client/OAuth2AuthorizedClientId.java | 5 +- .../client/OAuth2AuthorizedClientManager.java | 35 +- .../OAuth2AuthorizedClientProvider.java | 21 +- ...OAuth2AuthorizedClientProviderBuilder.java | 142 ++- .../client/OAuth2AuthorizedClientService.java | 27 +- ...asswordOAuth2AuthorizedClientProvider.java | 83 +- ...eactiveOAuth2AuthorizedClientProvider.java | 84 +- ...tiveOAuth2AuthorizationFailureHandler.java | 26 +- ...tiveOAuth2AuthorizationSuccessHandler.java | 21 +- ...ReactiveOAuth2AuthorizedClientManager.java | 37 +- ...eactiveOAuth2AuthorizedClientProvider.java | 21 +- ...OAuth2AuthorizedClientProviderBuilder.java | 160 +-- ...ReactiveOAuth2AuthorizedClientService.java | 33 +- ...shTokenOAuth2AuthorizedClientProvider.java | 71 +- ...eactiveOAuth2AuthorizedClientProvider.java | 76 +- ...ientOAuth2AuthorizationFailureHandler.java | 117 +- ...tiveOAuth2AuthorizationFailureHandler.java | 122 +- .../RegisteredOAuth2AuthorizedClient.java | 15 +- .../OAuth2AuthenticationToken.java | 29 +- ...thorizationCodeAuthenticationProvider.java | 60 +- ...2AuthorizationCodeAuthenticationToken.java | 41 +- ...tionCodeReactiveAuthenticationManager.java | 54 +- .../OAuth2LoginAuthenticationProvider.java | 88 +- .../OAuth2LoginAuthenticationToken.java | 47 +- ...th2LoginReactiveAuthenticationManager.java | 91 +- .../client/authentication/package-info.java | 4 +- ...stractOAuth2AuthorizationGrantRequest.java | 13 +- ...activeOAuth2AccessTokenResponseClient.java | 94 +- ...tAuthorizationCodeTokenResponseClient.java | 68 +- ...tClientCredentialsTokenResponseClient.java | 68 +- .../DefaultPasswordTokenResponseClient.java | 65 +- ...efaultRefreshTokenTokenResponseClient.java | 64 +- ...sAuthorizationCodeTokenResponseClient.java | 63 +- .../OAuth2AccessTokenResponseClient.java | 35 +- .../OAuth2AuthorizationCodeGrantRequest.java | 20 +- ...zationCodeGrantRequestEntityConverter.java | 27 +- ...2AuthorizationGrantRequestEntityUtils.java | 10 +- .../OAuth2ClientCredentialsGrantRequest.java | 15 +- ...redentialsGrantRequestEntityConverter.java | 24 +- .../endpoint/OAuth2PasswordGrantRequest.java | 16 +- ...h2PasswordGrantRequestEntityConverter.java | 21 +- .../OAuth2RefreshTokenGrantRequest.java | 26 +- ...freshTokenGrantRequestEntityConverter.java | 19 +- ...activeOAuth2AccessTokenResponseClient.java | 34 +- ...eAuthorizationCodeTokenResponseClient.java | 30 +- ...eClientCredentialsTokenResponseClient.java | 22 +- ...ntReactivePasswordTokenResponseClient.java | 27 +- ...activeRefreshTokenTokenResponseClient.java | 32 +- .../oauth2/client/endpoint/package-info.java | 4 +- .../http/OAuth2ErrorResponseErrorHandler.java | 13 +- .../ClientRegistrationDeserializer.java | 35 +- .../jackson2/ClientRegistrationMixin.java | 5 +- .../jackson2/DefaultOAuth2UserMixin.java | 4 +- .../client/jackson2/DefaultOidcUserMixin.java | 9 +- .../oauth2/client/jackson2/JsonNodeUtils.java | 10 +- .../jackson2/OAuth2AccessTokenMixin.java | 10 +- .../OAuth2AuthenticationExceptionMixin.java | 8 +- .../OAuth2AuthenticationTokenMixin.java | 6 +- ...Auth2AuthorizationRequestDeserializer.java | 27 +- .../OAuth2AuthorizationRequestMixin.java | 1 + .../jackson2/OAuth2AuthorizedClientMixin.java | 4 +- .../jackson2/OAuth2ClientJackson2Module.java | 45 +- .../client/jackson2/OAuth2ErrorMixin.java | 7 +- .../jackson2/OAuth2RefreshTokenMixin.java | 5 +- .../jackson2/OAuth2UserAuthorityMixin.java | 4 +- .../client/jackson2/OidcIdTokenMixin.java | 8 +- .../jackson2/OidcUserAuthorityMixin.java | 7 +- .../client/jackson2/OidcUserInfoMixin.java | 1 + .../oauth2/client/jackson2/StdConverters.java | 30 +- .../jackson2/UnmodifiableMapDeserializer.java | 1 + .../client/jackson2/UnmodifiableMapMixin.java | 6 +- .../DefaultOidcIdTokenValidatorFactory.java | 6 +- ...thorizationCodeAuthenticationProvider.java | 141 ++- ...tionCodeReactiveAuthenticationManager.java | 134 ++- .../OidcIdTokenDecoderFactory.java | 124 +- .../authentication/OidcIdTokenValidator.java | 44 +- .../ReactiveOidcIdTokenDecoderFactory.java | 122 +- .../oidc/authentication/package-info.java | 4 +- .../OidcReactiveOAuth2UserService.java | 102 +- .../client/oidc/userinfo/OidcUserRequest.java | 15 +- .../oidc/userinfo/OidcUserRequestUtils.java | 34 +- .../client/oidc/userinfo/OidcUserService.java | 97 +- .../client/oidc/userinfo/package-info.java | 4 +- ...dcClientInitiatedLogoutSuccessHandler.java | 32 +- ...ntInitiatedServerLogoutSuccessHandler.java | 61 +- .../registration/ClientRegistration.java | 209 ++-- .../ClientRegistrationRepository.java | 13 +- .../registration/ClientRegistrations.java | 155 +-- .../InMemoryClientRegistrationRepository.java | 25 +- ...yReactiveClientRegistrationRepository.java | 16 +- .../ReactiveClientRegistrationRepository.java | 13 +- .../client/registration/package-info.java | 3 +- .../CustomUserTypesOAuth2UserService.java | 46 +- .../userinfo/DefaultOAuth2UserService.java | 91 +- .../DefaultReactiveOAuth2UserService.java | 105 +- .../userinfo/DelegatingOAuth2UserService.java | 22 +- .../client/userinfo/OAuth2UserRequest.java | 18 +- .../OAuth2UserRequestEntityConverter.java | 21 +- .../client/userinfo/OAuth2UserService.java | 18 +- .../userinfo/ReactiveOAuth2UserService.java | 18 +- .../oauth2/client/userinfo/package-info.java | 4 +- ...cipalOAuth2AuthorizedClientRepository.java | 66 +- .../web/AuthorizationRequestRepository.java | 38 +- ...ultOAuth2AuthorizationRequestResolver.java | 138 ++- .../DefaultOAuth2AuthorizedClientManager.java | 171 +-- ...ReactiveOAuth2AuthorizedClientManager.java | 248 ++-- ...nOAuth2AuthorizationRequestRepository.java | 27 +- ...ssionOAuth2AuthorizedClientRepository.java | 22 +- .../OAuth2AuthorizationCodeGrantFilter.java | 138 ++- ...th2AuthorizationRequestRedirectFilter.java | 131 ++- .../OAuth2AuthorizationRequestResolver.java | 23 +- .../web/OAuth2AuthorizationResponseUtils.java | 25 +- .../web/OAuth2AuthorizedClientRepository.java | 39 +- .../web/OAuth2LoginAuthenticationFilter.java | 145 +-- ...Auth2AuthorizedClientArgumentResolver.java | 107 +- ...uthorizedClientExchangeFilterFunction.java | 578 +++++----- ...uthorizedClientExchangeFilterFunction.java | 465 ++++---- ...Auth2AuthorizedClientArgumentResolver.java | 60 +- ...erverOAuth2AuthorizedClientRepository.java | 53 +- ...verOAuth2AuthorizationRequestResolver.java | 151 +-- ...OAuth2AuthorizationCodeGrantWebFilter.java | 158 +-- ...AuthorizationRequestRedirectWebFilter.java | 80 +- .../OAuth2AuthorizationResponseUtils.java | 25 +- .../ServerAuthorizationRequestRepository.java | 30 +- ...ationCodeAuthenticationTokenConverter.java | 45 +- ...verOAuth2AuthorizationRequestResolver.java | 23 +- ...erverOAuth2AuthorizedClientRepository.java | 35 +- ...erverOAuth2AuthorizedClientRepository.java | 18 +- ...2ServerAuthorizationRequestRepository.java | 89 +- ...erverOAuth2AuthorizedClientRepository.java | 56 +- .../OAuth2LoginAuthenticationWebFilter.java | 25 +- ...deOAuth2AuthorizedClientProviderTests.java | 27 +- ...veOAuth2AuthorizedClientProviderTests.java | 27 +- ...iceOAuth2AuthorizedClientManagerTests.java | 173 +-- ...iveOAuth2AuthorizedClientManagerTests.java | 285 +++-- ...lsOAuth2AuthorizedClientProviderTests.java | 73 +- ...veOAuth2AuthorizedClientProviderTests.java | 76 +- ...ngOAuth2AuthorizedClientProviderTests.java | 17 +- ...veOAuth2AuthorizedClientProviderTests.java | 33 +- ...oryOAuth2AuthorizedClientServiceTests.java | 64 +- ...iveOAuth2AuthorizedClientServiceTests.java | 114 +- ...dbcOAuth2AuthorizedClientServiceTests.java | 281 ++--- .../OAuth2AuthorizationContextTests.java | 29 +- .../client/OAuth2AuthorizeRequestTests.java | 48 +- .../client/OAuth2AuthorizedClientIdTests.java | 7 +- ...2AuthorizedClientProviderBuilderTests.java | 141 +-- .../client/OAuth2AuthorizedClientTests.java | 8 +- ...rdOAuth2AuthorizedClientProviderTests.java | 120 +- ...veOAuth2AuthorizedClientProviderTests.java | 123 +- ...2AuthorizedClientProviderBuilderTests.java | 159 +-- ...enOAuth2AuthorizedClientProviderTests.java | 106 +- ...veOAuth2AuthorizedClientProviderTests.java | 112 +- .../OAuth2AuthenticationTokenTests.java | 8 +- ...zationCodeAuthenticationProviderTests.java | 29 +- ...orizationCodeAuthenticationTokenTests.java | 29 +- ...odeReactiveAuthenticationManagerTests.java | 21 +- ...Auth2LoginAuthenticationProviderTests.java | 87 +- .../OAuth2LoginAuthenticationTokenTests.java | 39 +- ...ginReactiveAuthenticationManagerTests.java | 74 +- .../TestOAuth2AuthenticationTokens.java | 1 + ...AuthorizationCodeAuthenticationTokens.java | 1 + ...orizationCodeTokenResponseClientTests.java | 183 ++- ...ntCredentialsTokenResponseClientTests.java | 180 ++- ...faultPasswordTokenResponseClientTests.java | 75 +- ...tRefreshTokenTokenResponseClientTests.java | 76 +- ...orizationCodeTokenResponseClientTests.java | 183 ++- ...nCodeGrantRequestEntityConverterTests.java | 88 +- ...th2AuthorizationCodeGrantRequestTests.java | 7 +- ...tialsGrantRequestEntityConverterTests.java | 24 +- ...th2ClientCredentialsGrantRequestTests.java | 31 +- ...swordGrantRequestEntityConverterTests.java | 18 +- .../OAuth2PasswordGrantRequestTests.java | 23 +- ...TokenGrantRequestEntityConverterTests.java | 24 +- .../OAuth2RefreshTokenGrantRequestTests.java | 13 +- ...orizationCodeTokenResponseClientTests.java | 299 +++-- ...ntCredentialsTokenResponseClientTests.java | 72 +- ...ctivePasswordTokenResponseClientTests.java | 76 +- ...eRefreshTokenTokenResponseClientTests.java | 75 +- .../OAuth2ErrorResponseErrorHandlerTests.java | 14 +- ...uth2AuthenticationExceptionMixinTests.java | 37 +- .../OAuth2AuthenticationTokenMixinTests.java | 98 +- .../OAuth2AuthorizationRequestMixinTests.java | 57 +- .../OAuth2AuthorizedClientMixinTests.java | 138 +-- ...zationCodeAuthenticationProviderTests.java | 121 +- ...odeReactiveAuthenticationManagerTests.java | 102 +- .../OidcIdTokenDecoderFactoryTests.java | 40 +- .../OidcIdTokenValidatorTests.java | 90 +- ...eactiveOidcIdTokenDecoderFactoryTests.java | 40 +- .../OidcReactiveOAuth2UserServiceTests.java | 43 +- .../oidc/userinfo/OidcUserRequestTests.java | 14 +- .../userinfo/OidcUserRequestUtilsTests.java | 9 +- .../oidc/userinfo/OidcUserServiceTests.java | 227 ++-- ...entInitiatedLogoutSuccessHandlerTests.java | 65 +- ...tiatedServerLogoutSuccessHandlerTests.java | 60 +- .../registration/ClientRegistrationTests.java | 618 ++++------ .../ClientRegistrationsTests.java | 200 ++-- ...moryClientRegistrationRepositoryTests.java | 2 + ...tiveClientRegistrationRepositoryTests.java | 6 +- .../registration/TestClientRegistrations.java | 46 +- ...CustomUserTypesOAuth2UserServiceTests.java | 63 +- .../DefaultOAuth2UserServiceTests.java | 169 ++- ...DefaultReactiveOAuth2UserServiceTests.java | 113 +- .../DelegatingOAuth2UserServiceTests.java | 12 +- ...OAuth2UserRequestEntityConverterTests.java | 36 +- .../userinfo/OAuth2UserRequestTests.java | 26 +- ...OAuth2AuthorizedClientRepositoryTests.java | 38 +- ...uth2AuthorizationRequestResolverTests.java | 242 ++-- ...ultOAuth2AuthorizedClientManagerTests.java | 233 ++-- ...iveOAuth2AuthorizedClientManagerTests.java | 325 +++--- ...h2AuthorizationRequestRepositoryTests.java | 134 ++- ...OAuth2AuthorizedClientRepositoryTests.java | 120 +- ...uth2AuthorizationCodeGrantFilterTests.java | 105 +- ...thorizationRequestRedirectFilterTests.java | 160 ++- .../OAuth2LoginAuthenticationFilterTests.java | 142 ++- ...AuthorizedClientArgumentResolverTests.java | 183 +-- .../function/client/MockExchangeFunction.java | 2 + ...zedClientExchangeFilterFunctionITests.java | 224 ++-- ...izedClientExchangeFilterFunctionTests.java | 500 ++++---- ...zedClientExchangeFilterFunctionITests.java | 168 ++- ...izedClientExchangeFilterFunctionTests.java | 369 +++--- ...AuthorizedClientArgumentResolverTests.java | 62 +- ...OAuth2AuthorizedClientRepositoryTests.java | 49 +- ...uth2AuthorizationRequestResolverTests.java | 134 +-- ...2AuthorizationCodeGrantWebFilterTests.java | 159 ++- ...rizationRequestRedirectWebFilterTests.java | 74 +- ...CodeAuthenticationTokenConverterTests.java | 59 +- ...OAuth2AuthorizedClientRepositoryTests.java | 74 +- ...erAuthorizationRequestRepositoryTests.java | 145 +-- ...OAuth2AuthorizedClientRepositoryTests.java | 119 +- ...uth2LoginAuthenticationWebFilterTests.java | 43 +- .../oauth2/core/AbstractOAuth2Token.java | 16 +- .../oauth2/core/AuthenticationMethod.java | 14 +- .../oauth2/core/AuthorizationGrantType.java | 29 +- .../security/oauth2/core/ClaimAccessor.java | 76 +- .../core/ClientAuthenticationMethod.java | 12 +- .../DefaultOAuth2AuthenticatedPrincipal.java | 16 +- .../core/DelegatingOAuth2TokenValidator.java | 12 +- .../oauth2/core/OAuth2AccessToken.java | 42 +- .../core/OAuth2AuthenticatedPrincipal.java | 12 +- .../core/OAuth2AuthenticationException.java | 22 +- .../core/OAuth2AuthorizationException.java | 7 +- .../security/oauth2/core/OAuth2Error.java | 24 +- .../oauth2/core/OAuth2ErrorCodes.java | 73 +- .../oauth2/core/OAuth2RefreshToken.java | 16 +- .../oauth2/core/OAuth2TokenValidator.java | 6 +- .../core/OAuth2TokenValidatorResult.java | 10 +- .../converter/ClaimConversionService.java | 12 +- .../core/converter/ClaimTypeConverter.java | 6 +- .../converter/ObjectToBooleanConverter.java | 1 + .../converter/ObjectToInstantConverter.java | 7 +- .../ObjectToListStringConverter.java | 8 +- .../ObjectToMapStringObjectConverter.java | 5 +- .../converter/ObjectToStringConverter.java | 1 + .../core/converter/ObjectToURLConverter.java | 4 +- ...MapOAuth2AccessTokenResponseConverter.java | 35 +- .../endpoint/OAuth2AccessTokenResponse.java | 53 +- ...OAuth2AccessTokenResponseMapConverter.java | 8 +- .../endpoint/OAuth2AuthorizationExchange.java | 18 +- .../endpoint/OAuth2AuthorizationRequest.java | 142 ++- .../endpoint/OAuth2AuthorizationResponse.java | 52 +- .../OAuth2AuthorizationResponseType.java | 23 +- .../core/endpoint/OAuth2ParameterNames.java | 13 +- .../core/endpoint/PkceParameterNames.java | 8 +- .../oauth2/core/endpoint/package-info.java | 4 +- .../http/converter/HttpMessageConverters.java | 14 +- ...cessTokenResponseHttpMessageConverter.java | 76 +- .../OAuth2ErrorHttpMessageConverter.java | 66 +- .../core/oidc/AddressStandardClaim.java | 24 +- .../oidc/DefaultAddressStandardClaim.java | 43 +- .../core/oidc/IdTokenClaimAccessor.java | 32 +- .../oauth2/core/oidc/IdTokenClaimNames.java | 14 +- .../oauth2/core/oidc/OidcIdToken.java | 49 +- .../security/oauth2/core/oidc/OidcScopes.java | 20 +- .../oauth2/core/oidc/OidcUserInfo.java | 54 +- .../core/oidc/StandardClaimAccessor.java | 56 +- .../oauth2/core/oidc/StandardClaimNames.java | 27 +- .../oidc/endpoint/OidcParameterNames.java | 8 +- .../core/oidc/user/DefaultOidcUser.java | 31 +- .../oauth2/core/oidc/user/OidcUser.java | 28 +- .../core/oidc/user/OidcUserAuthority.java | 25 +- .../oauth2/core/oidc/user/package-info.java | 3 +- .../security/oauth2/core/package-info.java | 3 +- .../oauth2/core/user/DefaultOAuth2User.java | 31 +- .../security/oauth2/core/user/OAuth2User.java | 23 +- .../oauth2/core/user/OAuth2UserAuthority.java | 11 +- ...Auth2AccessTokenResponseBodyExtractor.java | 45 +- .../function/OAuth2BodyExtractors.java | 5 +- .../core/AuthenticationMethodTests.java | 1 + .../core/AuthorizationGrantTypeTests.java | 1 + .../oauth2/core/ClaimAccessorTests.java | 27 +- .../core/ClientAuthenticationMethodTests.java | 1 + ...aultOAuth2AuthenticatedPrincipalTests.java | 24 +- .../DelegatingOAuth2TokenValidatorTests.java | 61 +- .../oauth2/core/OAuth2AccessTokenTests.java | 12 +- .../oauth2/core/OAuth2ErrorTests.java | 4 + .../core/OAuth2TokenValidatorResultTests.java | 5 +- .../oauth2/core/TestOAuth2AccessTokens.java | 13 +- .../oauth2/core/TestOAuth2RefreshTokens.java | 2 + .../ClaimConversionServiceTests.java | 8 +- .../converter/ClaimTypeConverterTests.java | 16 +- ...uth2AccessTokenResponseConverterTests.java | 2 +- ...2AccessTokenResponseMapConverterTests.java | 19 +- .../OAuth2AccessTokenResponseTests.java | 97 +- .../OAuth2AuthorizationExchangeTests.java | 5 +- .../OAuth2AuthorizationRequestTests.java | 241 ++-- .../OAuth2AuthorizationResponseTests.java | 64 +- .../OAuth2AuthorizationResponseTypeTests.java | 1 + .../TestOAuth2AccessTokenResponses.java | 8 +- .../TestOAuth2AuthorizationExchanges.java | 1 + .../TestOAuth2AuthorizationRequests.java | 8 +- .../TestOAuth2AuthorizationResponses.java | 4 +- ...okenResponseHttpMessageConverterTests.java | 100 +- .../OAuth2ErrorHttpMessageConverterTests.java | 36 +- .../DefaultAddressStandardClaimTests.java | 18 +- .../core/oidc/OidcIdTokenBuilderTests.java | 50 +- .../oauth2/core/oidc/OidcIdTokenTests.java | 31 +- .../core/oidc/OidcUserInfoBuilderTests.java | 31 +- .../oauth2/core/oidc/OidcUserInfoTests.java | 40 + .../oauth2/core/oidc/TestOidcIdTokens.java | 10 +- .../core/oidc/user/DefaultOidcUserTests.java | 28 +- .../oidc/user/OidcUserAuthorityTests.java | 15 +- .../oauth2/core/oidc/user/TestOidcUsers.java | 24 +- .../core/user/DefaultOAuth2UserTests.java | 9 +- .../core/user/OAuth2UserAuthorityTests.java | 3 + .../oauth2/core/user/TestOAuth2Users.java | 8 +- .../function/OAuth2BodyExtractorsTests.java | 31 +- .../oauth2/jose/jws/JwsAlgorithm.java | 16 +- .../oauth2/jose/jws/JwsAlgorithms.java | 16 +- .../oauth2/jose/jws/MacAlgorithm.java | 20 +- .../oauth2/jose/jws/SignatureAlgorithm.java | 19 +- .../security/oauth2/jwt/BadJwtException.java | 7 +- .../security/oauth2/jwt/Jwt.java | 52 +- .../security/oauth2/jwt/JwtClaimAccessor.java | 46 +- .../security/oauth2/jwt/JwtClaimNames.java | 19 +- .../oauth2/jwt/JwtClaimValidator.java | 25 +- .../security/oauth2/jwt/JwtDecoder.java | 32 +- .../oauth2/jwt/JwtDecoderFactory.java | 10 +- .../JwtDecoderProviderConfigurationUtils.java | 44 +- .../security/oauth2/jwt/JwtDecoders.java | 90 +- .../security/oauth2/jwt/JwtException.java | 3 +- .../oauth2/jwt/JwtIssuerValidator.java | 2 +- .../oauth2/jwt/JwtTimestampValidator.java | 24 +- .../oauth2/jwt/JwtValidationException.java | 9 +- .../security/oauth2/jwt/JwtValidators.java | 24 +- .../jwt/MappedJwtClaimSetConverter.java | 32 +- .../security/oauth2/jwt/NimbusJwtDecoder.java | 200 ++-- .../jwt/NimbusJwtDecoderJwkSupport.java | 39 +- .../oauth2/jwt/NimbusReactiveJwtDecoder.java | 229 ++-- .../oauth2/jwt/ReactiveJWKSource.java | 3 + .../oauth2/jwt/ReactiveJWKSourceAdapter.java | 3 + .../oauth2/jwt/ReactiveJwtDecoder.java | 31 +- .../oauth2/jwt/ReactiveJwtDecoderFactory.java | 11 +- .../oauth2/jwt/ReactiveJwtDecoders.java | 93 +- .../oauth2/jwt/ReactiveRemoteJWKSource.java | 20 +- .../oauth2/jwt/SingleKeyJWSKeySelector.java | 3 + .../security/oauth2/jose/TestKeys.java | 81 +- .../oauth2/jose/jws/MacAlgorithmTests.java | 1 + .../jose/jws/SignatureAlgorithmTests.java | 1 + .../security/oauth2/jwt/JwtBuilderTests.java | 82 +- .../oauth2/jwt/JwtClaimValidatorTests.java | 16 +- .../security/oauth2/jwt/JwtDecodersTests.java | 107 +- .../oauth2/jwt/JwtIssuerValidatorTests.java | 14 +- .../security/oauth2/jwt/JwtTests.java | 28 +- .../jwt/JwtTimestampValidatorTests.java | 34 +- .../jwt/MappedJwtClaimSetConverterTests.java | 29 +- .../jwt/NimbusJwtDecoderJwkSupportTests.java | 47 +- .../oauth2/jwt/NimbusJwtDecoderTests.java | 236 ++-- .../jwt/NimbusReactiveJwtDecoderTests.java | 209 ++-- .../oauth2/jwt/ReactiveJwtDecodersTests.java | 92 +- .../jwt/ReactiveRemoteJWKSourceTests.java | 31 +- .../security/oauth2/jwt/TestJwts.java | 18 +- .../BearerTokenAuthenticationToken.java | 17 +- .../server/resource/BearerTokenError.java | 44 +- .../resource/BearerTokenErrorCodes.java | 19 +- .../server/resource/BearerTokenErrors.java | 49 +- .../resource/InvalidBearerTokenException.java | 13 +- ...bstractOAuth2TokenAuthenticationToken.java | 28 +- .../BearerTokenAuthentication.java | 9 +- .../JwtAuthenticationConverter.java | 21 +- .../JwtAuthenticationProvider.java | 34 +- .../JwtAuthenticationToken.java | 9 +- ...JwtBearerTokenAuthenticationConverter.java | 21 +- .../JwtGrantedAuthoritiesConverter.java | 24 +- ...wtIssuerAuthenticationManagerResolver.java | 68 +- ...ReactiveAuthenticationManagerResolver.java | 96 +- .../JwtReactiveAuthenticationManager.java | 25 +- .../OpaqueTokenAuthenticationProvider.java | 41 +- ...queTokenReactiveAuthenticationManager.java | 59 +- .../ReactiveJwtAuthenticationConverter.java | 21 +- ...tiveJwtAuthenticationConverterAdapter.java | 2 + ...JwtGrantedAuthoritiesConverterAdapter.java | 13 +- .../resource/authentication/package-info.java | 3 +- .../BadOpaqueTokenException.java | 7 +- .../NimbusOpaqueTokenIntrospector.java | 40 +- ...NimbusReactiveOpaqueTokenIntrospector.java | 58 +- ...h2IntrospectionAuthenticatedPrincipal.java | 29 +- .../OAuth2IntrospectionClaimAccessor.java | 36 +- .../OAuth2IntrospectionClaimNames.java | 10 +- .../OAuth2IntrospectionException.java | 2 + .../OpaqueTokenIntrospector.java | 11 +- .../ReactiveOpaqueTokenIntrospector.java | 11 +- .../BearerTokenAuthenticationEntryPoint.java | 27 +- .../web/BearerTokenAuthenticationFilter.java | 44 +- .../resource/web/BearerTokenResolver.java | 14 +- .../web/DefaultBearerTokenResolver.java | 29 +- .../web/HeaderBearerTokenResolver.java | 1 + .../BearerTokenAccessDeniedHandler.java | 29 +- .../BearerTokenServerAccessDeniedHandler.java | 26 +- .../ServerBearerExchangeFilterFunction.java | 31 +- .../ServletBearerExchangeFilterFunction.java | 44 +- ...erTokenServerAuthenticationEntryPoint.java | 16 +- ...verBearerTokenAuthenticationConverter.java | 48 +- .../TestOAuth2AuthenticatedPrincipals.java | 13 +- .../BearerTokenAuthenticationTokenTests.java | 8 +- .../resource/BearerTokenErrorTests.java | 33 +- .../resource/BearerTokenErrorsTests.java | 2 + ...icationEventPublisherBearerTokenTests.java | 5 +- .../BearerTokenAuthenticationTests.java | 42 +- .../JwtAuthenticationConverterTests.java | 15 +- .../JwtAuthenticationProviderTests.java | 26 +- .../JwtAuthenticationTokenTests.java | 4 +- ...arerTokenAuthenticationConverterTests.java | 32 +- .../JwtGrantedAuthoritiesConverterTests.java | 54 +- ...uerAuthenticationManagerResolverTests.java | 72 +- ...iveAuthenticationManagerResolverTests.java | 83 +- ...JwtReactiveAuthenticationManagerTests.java | 18 +- ...paqueTokenAuthenticationProviderTests.java | 32 +- ...kenReactiveAuthenticationManagerTests.java | 38 +- ...wtAuthenticationConverterAdapterTests.java | 27 +- ...activeJwtAuthenticationConverterTests.java | 12 +- ...antedAuthoritiesConverterAdapterTests.java | 19 +- .../TestBearerTokenAuthentications.java | 17 +- .../NimbusOpaqueTokenIntrospectorTests.java | 184 ++- ...sReactiveOpaqueTokenIntrospectorTests.java | 115 +- ...rospectionAuthenticatedPrincipalTests.java | 49 +- ...rerTokenAuthenticationEntryPointTests.java | 55 +- .../BearerTokenAuthenticationFilterTests.java | 85 +- .../web/DefaultBearerTokenResolverTests.java | 3 + .../web/HeaderBearerTokenResolverTests.java | 13 +- .../resource/web/MockExchangeFunction.java | 2 + .../BearerTokenAccessDeniedHandlerTests.java | 20 +- ...erTokenServerAccessDeniedHandlerTests.java | 23 +- ...rverBearerExchangeFilterFunctionTests.java | 33 +- ...vletBearerExchangeFilterFunctionTests.java | 38 +- ...enServerAuthenticationEntryPointTests.java | 18 +- ...arerTokenAuthenticationConverterTests.java | 85 +- .../AuthenticationCancelledException.java | 7 +- .../security/openid/AxFetchListFactory.java | 7 +- .../openid/NullAxFetchListFactory.java | 7 +- .../security/openid/OpenID4JavaConsumer.java | 63 +- .../security/openid/OpenIDAttribute.java | 13 +- .../openid/OpenIDAuthenticationFilter.java | 39 +- .../openid/OpenIDAuthenticationProvider.java | 37 +- .../openid/OpenIDAuthenticationStatus.java | 7 +- .../openid/OpenIDAuthenticationToken.java | 20 +- .../security/openid/OpenIDConsumer.java | 13 +- .../openid/OpenIDConsumerException.java | 7 +- .../openid/RegexBasedAxFetchListFactory.java | 6 +- .../security/openid/package-info.java | 1 - .../security/openid/MockOpenIDConsumer.java | 13 +- .../openid/OpenID4JavaConsumerTests.java | 72 +- .../OpenIDAuthenticationFilterTests.java | 21 +- .../OpenIDAuthenticationProviderTests.java | 48 +- .../security/remoting/dns/DnsResolver.java | 13 +- .../remoting/dns/JndiDnsResolver.java | 28 +- .../security/remoting/dns/package-info.java | 1 - ...ationSimpleHttpInvokerRequestExecutor.java | 17 +- .../remoting/httpinvoker/package-info.java | 7 +- .../security/remoting/package-info.java | 1 - .../ContextPropagatingRemoteInvocation.java | 22 +- ...extPropagatingRemoteInvocationFactory.java | 2 + .../security/remoting/rmi/package-info.java | 9 +- .../remoting/dns/JndiDnsResolverTests.java | 30 +- ...SimpleHttpInvokerRequestExecutorTests.java | 12 +- ...ntextPropagatingRemoteInvocationTests.java | 24 +- .../security/rsocket/api/PayloadExchange.java | 2 + .../rsocket/api/PayloadExchangeType.java | 15 +- .../rsocket/api/PayloadInterceptor.java | 8 +- .../rsocket/api/PayloadInterceptorChain.java | 6 +- .../AnonymousPayloadInterceptor.java | 27 +- ...uthenticationPayloadExchangeConverter.java | 29 +- .../AuthenticationPayloadInterceptor.java | 16 +- ...uthenticationPayloadExchangeConverter.java | 17 +- .../BearerPayloadExchangeConverter.java | 13 +- ...ayloadExchangeAuthenticationConverter.java | 3 + .../AuthorizationPayloadInterceptor.java | 11 +- ...geMatcherReactiveAuthorizationManager.java | 24 +- .../core/ContextPayloadInterceptorChain.java | 15 +- .../rsocket/core/DefaultPayloadExchange.java | 1 + .../core/PayloadInterceptorRSocket.java | 59 +- .../rsocket/core/PayloadSocketAcceptor.java | 18 +- .../PayloadSocketAcceptorInterceptor.java | 8 +- .../SecuritySocketAcceptorInterceptor.java | 7 +- .../metadata/BasicAuthenticationDecoder.java | 61 +- .../metadata/BasicAuthenticationEncoder.java | 25 +- .../BearerTokenAuthenticationEncoder.java | 29 +- .../rsocket/metadata/BearerTokenMetadata.java | 13 +- .../metadata/SimpleAuthenticationEncoder.java | 30 +- .../metadata/UsernamePasswordMetadata.java | 9 +- .../PayloadExchangeAuthorizationContext.java | 3 + .../util/matcher/PayloadExchangeMatcher.java | 8 +- .../matcher/PayloadExchangeMatcherEntry.java | 3 + .../util/matcher/PayloadExchangeMatchers.java | 13 +- .../matcher/RoutePayloadExchangeMatcher.java | 17 +- .../AnonymousPayloadInterceptorTests.java | 20 +- ...AuthenticationPayloadInterceptorChain.java | 2 + ...AuthenticationPayloadInterceptorTests.java | 54 +- .../AuthorizationPayloadInterceptorTests.java | 37 +- ...cherReactiveAuthorizationManagerTests.java | 57 +- .../CaptureSecurityContextSocketAcceptor.java | 9 +- .../core/PayloadInterceptorRSocketTests.java | 125 +- ...PayloadSocketAcceptorInterceptorTests.java | 11 +- .../core/PayloadSocketAcceptorTests.java | 25 +- .../BasicAuthenticationDecoderTests.java | 10 +- .../RoutePayloadExchangeMatcherTests.java | 13 +- .../core/OpenSamlInitializationService.java | 75 +- .../security/saml2/core/Saml2Error.java | 16 +- .../security/saml2/core/Saml2ErrorCodes.java | 72 +- .../saml2/core/Saml2X509Credential.java | 67 +- .../credentials/Saml2X509Credential.java | 75 +- .../AbstractSaml2AuthenticationRequest.java | 51 +- .../DefaultSaml2AuthenticatedPrincipal.java | 2 + .../OpenSamlAuthenticationProvider.java | 235 ++-- .../OpenSamlAuthenticationRequestFactory.java | 129 +-- .../Saml2AuthenticatedPrincipal.java | 5 +- .../authentication/Saml2Authentication.java | 16 +- .../Saml2AuthenticationException.java | 63 +- .../Saml2AuthenticationRequest.java | 75 +- .../Saml2AuthenticationRequestContext.java | 55 +- .../Saml2AuthenticationRequestFactory.java | 108 +- .../Saml2AuthenticationToken.java | 56 +- .../service/authentication/Saml2Error.java | 15 +- .../authentication/Saml2ErrorCodes.java | 72 +- .../Saml2PostAuthenticationRequest.java | 35 +- .../Saml2RedirectAuthenticationRequest.java | 43 +- .../service/authentication/Saml2Utils.java | 4 +- .../metadata/OpenSamlMetadataResolver.java | 25 +- .../metadata/Saml2MetadataResolver.java | 6 +- ...oryRelyingPartyRegistrationRepository.java | 7 +- ...gistrationBuilderHttpMessageConverter.java | 53 +- .../RelyingPartyRegistration.java | 482 ++++---- .../RelyingPartyRegistrationRepository.java | 5 +- .../RelyingPartyRegistrations.java | 21 +- .../registration/Saml2MessageBinding.java | 15 +- .../Saml2WebSsoAuthenticationFilter.java | 40 +- ...aml2WebSsoAuthenticationRequestFilter.java | 114 +- ...faultRelyingPartyRegistrationResolver.java | 41 +- ...2AuthenticationRequestContextResolver.java | 27 +- ...2AuthenticationRequestContextResolver.java | 9 +- .../Saml2AuthenticationTokenConverter.java | 18 +- .../service/web/Saml2MetadataFilter.java | 10 +- .../OpenSamlInitializationServiceTests.java | 6 +- .../security/saml2/core/Saml2Utils.java | 3 +- .../saml2/core/Saml2X509CredentialTests.java | 64 +- .../saml2/core/TestSaml2X509Credentials.java | 171 ++- .../credentials/Saml2X509CredentialTests.java | 65 +- .../credentials/TestSaml2X509Credentials.java | 171 ++- ...faultSaml2AuthenticatedPrincipalTests.java | 7 +- .../OpenSamlAuthenticationProviderTests.java | 71 +- ...SamlAuthenticationRequestFactoryTests.java | 87 +- ...aml2AuthenticationRequestFactoryTests.java | 23 +- .../authentication/TestOpenSamlObjects.java | 60 +- ...estSaml2AuthenticationRequestContexts.java | 6 +- .../OpenSamlMetadataResolverTests.java | 24 +- ...ationBuilderHttpMessageConverterTests.java | 98 +- .../RelyingPartyRegistrationTests.java | 60 +- .../RelyingPartyRegistrationsTests.java | 149 +-- .../TestRelyingPartyRegistrations.java | 30 +- .../Saml2WebSsoAuthenticationFilterTests.java | 7 +- ...ebSsoAuthenticationRequestFilterTests.java | 112 +- ...RelyingPartyRegistrationResolverTests.java | 15 +- ...enticationRequestContextResolverTests.java | 33 +- ...aml2AuthenticationTokenConverterTests.java | 31 +- .../service/web/Saml2MetadataFilterTests.java | 17 +- .../security/taglibs/TagLibConfig.java | 3 +- .../taglibs/authz/AbstractAuthorizeTag.java | 53 +- .../taglibs/authz/AccessControlListTag.java | 22 +- .../taglibs/authz/AuthenticationTag.java | 5 + .../taglibs/authz/JspAuthorizeTag.java | 12 +- .../security/taglibs/authz/package-info.java | 1 - .../taglibs/csrf/AbstractCsrfTag.java | 4 +- .../security/taglibs/csrf/CsrfInputTag.java | 4 +- .../taglibs/csrf/CsrfMetaTagsTag.java | 8 +- .../security/taglibs/package-info.java | 1 - .../security/taglibs/TldTests.java | 5 +- .../authz/AbstractAuthorizeTagTests.java | 16 +- .../authz/AccessControlListTagTests.java | 12 +- .../taglibs/authz/AuthenticationTagTests.java | 25 +- .../taglibs/authz/AuthorizeTagTests.java | 31 +- .../taglibs/csrf/AbstractCsrfTagTests.java | 29 +- .../taglibs/csrf/CsrfInputTagTests.java | 14 +- .../taglibs/csrf/CsrfMetaTagsTagTests.java | 21 +- .../context/TestSecurityContextHolder.java | 11 +- .../SecurityTestExecutionListeners.java | 14 +- .../DelegatingTestExecutionListener.java | 4 +- .../ReactorContextTestExecutionListener.java | 25 +- .../context/support/TestExecutionEvent.java | 11 +- .../context/support/WithAnonymousUser.java | 16 +- ...thAnonymousUserSecurityContextFactory.java | 9 +- .../test/context/support/WithMockUser.java | 7 +- .../WithMockUserSecurityContextFactory.java | 27 +- .../context/support/WithSecurityContext.java | 2 +- .../support/WithSecurityContextFactory.java | 3 +- ...hSecurityContextTestExecutionListener.java | 68 +- .../test/context/support/WithUserDetails.java | 8 +- ...WithUserDetailsSecurityContextFactory.java | 35 +- .../server/SecurityMockServerConfigurers.java | 450 ++++---- .../SecurityMockMvcRequestBuilders.java | 54 +- .../SecurityMockMvcRequestPostProcessors.java | 473 ++++---- .../SecurityMockMvcResultMatchers.java | 63 +- .../setup/SecurityMockMvcConfigurer.java | 38 +- .../setup/SecurityMockMvcConfigurers.java | 8 +- .../test/web/support/WebTestUtils.java | 34 +- .../TestSecurityContextHolderTests.java | 1 + .../SecurityTestExecutionListenerTests.java | 11 +- .../context/showcase/CustomUserDetails.java | 4 + .../context/showcase/WithMockCustomUser.java | 3 +- ...hMockCustomUserSecurityContextFactory.java | 12 +- .../showcase/WithMockUserParentTests.java | 3 + .../context/showcase/WithMockUserTests.java | 7 +- .../showcase/WithUserDetailsTests.java | 10 +- .../showcase/service/HelloMessageService.java | 4 +- .../showcase/service/MessageService.java | 2 + ...ctorContextTestExecutionListenerTests.java | 79 +- .../support/WithAnonymousUserTests.java | 12 +- ...thMockUserSecurityContextFactoryTests.java | 16 +- .../context/support/WithMockUserTests.java | 14 +- ...ityContextTestExcecutionListenerTests.java | 27 +- ...rityContextTestExecutionListenerTests.java | 24 +- ...serDetailsSecurityContextFactoryTests.java | 22 +- .../context/support/WithUserDetailsTests.java | 16 +- .../AbstractMockServerConfigurersTests.java | 12 +- ...yMockServerConfigurerOpaqueTokenTests.java | 67 +- ...tyMockServerConfigurersAnnotatedTests.java | 97 +- ...kServerConfigurersClassAnnotatedTests.java | 35 +- ...SecurityMockServerConfigurersJwtTests.java | 80 +- ...ockServerConfigurersOAuth2ClientTests.java | 99 +- ...MockServerConfigurersOAuth2LoginTests.java | 107 +- ...tyMockServerConfigurersOidcLoginTests.java | 114 +- .../SecurityMockServerConfigurersTests.java | 108 +- .../web/servlet/request/Sec2935Tests.java | 78 +- ...yMockMvcRequestBuildersFormLoginTests.java | 30 +- ...MockMvcRequestBuildersFormLogoutTests.java | 34 +- ...rocessorsAuthenticationStatelessTests.java | 4 + ...uestPostProcessorsAuthenticationTests.java | 9 +- ...RequestPostProcessorsCertificateTests.java | 12 +- ...estPostProcessorsCsrfDebugFilterTests.java | 3 + ...MockMvcRequestPostProcessorsCsrfTests.java | 18 +- ...ckMvcRequestPostProcessorsDigestTests.java | 25 +- ...yMockMvcRequestPostProcessorsJwtTests.java | 35 +- ...equestPostProcessorsOAuth2ClientTests.java | 59 +- ...RequestPostProcessorsOAuth2LoginTests.java | 75 +- ...vcRequestPostProcessorsOidcLoginTests.java | 67 +- ...RequestPostProcessorsOpaqueTokenTests.java | 44 +- ...estPostProcessorsSecurityContextTests.java | 9 +- ...sorsTestSecurityContextStatelessTests.java | 7 +- ...ostProcessorsTestSecurityContextTests.java | 9 +- ...RequestPostProcessorsUserDetailsTests.java | 12 +- ...MockMvcRequestPostProcessorsUserTests.java | 46 +- .../web/servlet/response/Gh3409Tests.java | 2 + .../SecurityMockMvcResultMatchersTests.java | 15 +- ...WithAuthoritiesMvcResultMatchersTests.java | 11 +- .../setup/SecurityMockMvcConfigurerTests.java | 16 +- .../SecurityMockMvcConfigurersTests.java | 33 +- .../showcase/csrf/CsrfShowcaseTests.java | 2 + .../csrf/CustomCsrfShowcaseTests.java | 6 +- .../csrf/DefaultCsrfShowcaseTests.java | 6 +- .../showcase/login/AuthenticationTests.java | 21 +- .../CustomConfigAuthenticationTests.java | 17 +- ...oginRequestBuilderAuthenticationTests.java | 15 +- .../DefaultfSecurityRequestsTests.java | 9 +- .../secured/SecurityRequestsTests.java | 13 +- .../showcase/secured/WithAdminRob.java | 3 +- .../secured/WithUserAuthenticationTests.java | 11 +- ...WithUserClassLevelAuthenticationTests.java | 6 +- .../WithUserDetailsAuthenticationTests.java | 7 +- ...rDetailsClassLevelAuthenticationTests.java | 8 +- .../test/web/support/WebTestUtilsTests.java | 47 +- .../web/AuthenticationEntryPoint.java | 7 +- .../security/web/DefaultRedirectStrategy.java | 8 +- .../web/DefaultSecurityFilterChain.java | 5 +- .../security/web/FilterChainProxy.java | 62 +- .../security/web/FilterInvocation.java | 51 +- .../security/web/PortMapper.java | 6 +- .../security/web/PortMapperImpl.java | 13 +- .../security/web/PortResolver.java | 4 +- .../security/web/PortResolverImpl.java | 2 + .../security/web/RedirectStrategy.java | 4 +- .../security/web/SecurityFilterChain.java | 3 +- .../security/web/WebAttributes.java | 6 +- .../web/access/AccessDeniedHandler.java | 9 +- .../web/access/AccessDeniedHandlerImpl.java | 13 +- ...efaultWebInvocationPrivilegeEvaluator.java | 28 +- .../access/DelegatingAccessDeniedHandler.java | 8 +- .../access/ExceptionTranslationFilter.java | 75 +- ...tMatcherDelegatingAccessDeniedHandler.java | 17 +- .../WebInvocationPrivilegeEvaluator.java | 3 +- .../channel/AbstractRetryEntryPoint.java | 15 +- .../channel/ChannelDecisionManager.java | 7 +- .../channel/ChannelDecisionManagerImpl.java | 9 +- .../web/access/channel/ChannelEntryPoint.java | 6 +- .../channel/ChannelProcessingFilter.java | 21 +- .../web/access/channel/ChannelProcessor.java | 7 +- .../channel/InsecureChannelProcessor.java | 6 +- .../channel/RetryWithHttpEntryPoint.java | 1 + .../channel/RetryWithHttpsEntryPoint.java | 1 + .../channel/SecureChannelProcessor.java | 9 +- .../web/access/channel/package-info.java | 1 - ...ariableEvaluationContextPostProcessor.java | 3 +- .../DefaultWebSecurityExpressionHandler.java | 24 +- .../DelegatingEvaluationContext.java | 2 + .../EvaluationContextPostProcessor.java | 18 +- ...ilterInvocationSecurityMetadataSource.java | 44 +- .../WebExpressionConfigAttribute.java | 9 +- .../access/expression/WebExpressionVoter.java | 18 +- .../expression/WebSecurityExpressionRoot.java | 3 +- .../web/access/expression/package-info.java | 1 - ...ilterInvocationSecurityMetadataSource.java | 16 +- ...ilterInvocationSecurityMetadataSource.java | 1 + .../intercept/FilterSecurityInterceptor.java | 17 +- .../web/access/intercept/RequestKey.java | 3 + .../web/access/intercept/package-info.java | 1 - .../security/web/access/package-info.java | 1 - ...bstractAuthenticationProcessingFilter.java | 111 +- ...AuthenticationTargetUrlRequestHandler.java | 34 +- .../AnonymousAuthenticationFilter.java | 21 +- .../AuthenticationConverter.java | 11 +- ...uthenticationEntryPointFailureHandler.java | 1 + .../AuthenticationFailureHandler.java | 6 +- .../authentication/AuthenticationFilter.java | 35 +- .../AuthenticationSuccessHandler.java | 15 +- .../DelegatingAuthenticationEntryPoint.java | 9 +- ...elegatingAuthenticationFailureHandler.java | 12 +- ...onMappingAuthenticationFailureHandler.java | 18 +- .../ForwardAuthenticationFailureHandler.java | 107 +- .../ForwardAuthenticationSuccessHandler.java | 105 +- .../Http403ForbiddenEntryPoint.java | 7 +- .../authentication/HttpStatusEntryPoint.java | 3 +- .../LoginUrlAuthenticationEntryPoint.java | 41 +- .../NullRememberMeServices.java | 5 +- .../authentication/RememberMeServices.java | 16 +- ...uestAwareAuthenticationSuccessHandler.java | 51 +- ...SimpleUrlAuthenticationFailureHandler.java | 26 +- ...SimpleUrlAuthenticationSuccessHandler.java | 11 +- .../UsernamePasswordAuthenticationFilter.java | 33 +- .../WebAuthenticationDetails.java | 6 +- .../WebAuthenticationDetailsSource.java | 5 +- .../logout/CompositeLogoutHandler.java | 9 +- .../logout/CookieClearingLogoutHandler.java | 17 +- .../DelegatingLogoutSuccessHandler.java | 149 ++- .../logout/ForwardLogoutSuccessHandler.java | 7 +- .../logout/HeaderWriterLogoutHandler.java | 7 +- ...tpStatusReturningLogoutSuccessHandler.java | 5 +- .../authentication/logout/LogoutFilter.java | 17 +- .../authentication/logout/LogoutHandler.java | 6 +- .../logout/LogoutSuccessHandler.java | 4 +- .../logout/SecurityContextLogoutHandler.java | 9 +- .../logout/SimpleUrlLogoutSuccessHandler.java | 8 +- .../authentication/logout/package-info.java | 1 - .../web/authentication/package-info.java | 1 - ...tractPreAuthenticatedProcessingFilter.java | 64 +- ...reAuthenticatedAuthenticationProvider.java | 27 +- .../PreAuthenticatedAuthenticationToken.java | 3 +- ...enticatedCredentialsNotFoundException.java | 2 +- ...dGrantedAuthoritiesUserDetailsService.java | 17 +- ...edAuthoritiesWebAuthenticationDetails.java | 9 +- .../RequestAttributeAuthenticationFilter.java | 21 +- .../RequestHeaderAuthenticationFilter.java | 20 +- ...ticatedWebAuthenticationDetailsSource.java | 29 +- .../J2eePreAuthenticatedProcessingFilter.java | 7 +- .../WebXmlMappableAttributesRetriever.java | 18 +- .../preauth/j2ee/package-info.java | 6 +- .../authentication/preauth/package-info.java | 5 +- .../DefaultWASUsernameAndGroupsExtractor.java | 75 +- .../WASUsernameAndGroupsExtractor.java | 1 + ...pherePreAuthenticatedProcessingFilter.java | 5 +- ...ticatedWebAuthenticationDetailsSource.java | 17 +- .../preauth/websphere/package-info.java | 1 - .../x509/SubjectDnX509PrincipalExtractor.java | 17 +- .../x509/X509AuthenticationFilter.java | 5 +- .../preauth/x509/X509PrincipalExtractor.java | 1 + .../preauth/x509/package-info.java | 6 +- .../AbstractRememberMeServices.java | 94 +- .../rememberme/CookieTheftException.java | 2 + .../InMemoryTokenRepositoryImpl.java | 9 +- .../rememberme/InvalidCookieException.java | 2 + .../rememberme/JdbcTokenRepositoryImpl.java | 31 +- .../rememberme/PersistentRememberMeToken.java | 8 +- ...ersistentTokenBasedRememberMeServices.java | 71 +- .../rememberme/PersistentTokenRepository.java | 1 - .../RememberMeAuthenticationException.java | 3 +- .../RememberMeAuthenticationFilter.java | 45 +- .../TokenBasedRememberMeServices.java | 47 +- .../rememberme/package-info.java | 5 +- ...ractSessionFixationProtectionStrategy.java | 33 +- ...ChangeSessionIdAuthenticationStrategy.java | 4 +- ...ompositeSessionAuthenticationStrategy.java | 20 +- ...tSessionControlAuthenticationStrategy.java | 45 +- .../NullAuthenticatedSessionStrategy.java | 9 +- ...RegisterSessionAuthenticationStrategy.java | 13 +- .../SessionAuthenticationStrategy.java | 5 +- .../SessionFixationProtectionEvent.java | 8 +- .../SessionFixationProtectionStrategy.java | 10 +- .../authentication/session/package-info.java | 4 +- .../AuthenticationSwitchUserEvent.java | 6 +- .../SwitchUserAuthorityChanger.java | 8 +- .../switchuser/SwitchUserFilter.java | 113 +- .../SwitchUserGrantedAuthority.java | 4 +- .../switchuser/package-info.java | 1 - .../ui/DefaultLoginPageGeneratingFilter.java | 140 +-- .../ui/DefaultLogoutPageGeneratingFilter.java | 41 +- .../web/authentication/ui/package-info.java | 6 +- .../www/BasicAuthenticationConverter.java | 13 +- .../www/BasicAuthenticationEntryPoint.java | 4 +- .../www/BasicAuthenticationFilter.java | 43 +- .../authentication/www/DigestAuthUtils.java | 26 +- .../www/DigestAuthenticationEntryPoint.java | 21 +- .../www/DigestAuthenticationFilter.java | 168 ++- .../www/NonceExpiredException.java | 4 +- .../web/authentication/www/package-info.java | 4 +- .../annotation/AuthenticationPrincipal.java | 6 +- ...thenticationPrincipalArgumentResolver.java | 33 +- ...ractSecurityWebApplicationInitializer.java | 45 +- .../context/HttpRequestResponseHolder.java | 6 +- .../HttpSessionSecurityContextRepository.java | 93 +- .../NullSecurityContextRepository.java | 3 +- ...ContextOnUpdateOrErrorResponseWrapper.java | 9 +- .../SecurityContextPersistenceFilter.java | 10 +- .../context/SecurityContextRepository.java | 9 +- .../security/web/context/package-info.java | 4 +- ...yContextCallableProcessingInterceptor.java | 8 +- .../WebAsyncManagerIntegrationFilter.java | 5 +- .../SecurityWebApplicationContextUtils.java | 25 +- .../web/csrf/CookieCsrfTokenRepository.java | 51 +- .../web/csrf/CsrfAuthenticationStrategy.java | 6 +- .../security/web/csrf/CsrfException.java | 1 + .../security/web/csrf/CsrfFilter.java | 35 +- .../security/web/csrf/CsrfLogoutHandler.java | 5 +- .../security/web/csrf/CsrfToken.java | 2 - .../web/csrf/CsrfTokenRepository.java | 8 +- .../security/web/csrf/DefaultCsrfToken.java | 1 + .../csrf/HttpSessionCsrfTokenRepository.java | 16 +- .../web/csrf/InvalidCsrfTokenException.java | 11 +- .../web/csrf/LazyCsrfTokenRepository.java | 22 +- .../web/csrf/MissingCsrfTokenException.java | 1 + .../security/web/debug/DebugFilter.java | 29 +- .../security/web/debug/Logger.java | 2 + .../web/firewall/DefaultHttpFirewall.java | 56 +- .../DefaultRequestRejectedHandler.java | 5 +- .../web/firewall/FirewalledRequest.java | 3 +- .../web/firewall/FirewalledResponse.java | 6 +- .../security/web/firewall/HttpFirewall.java | 6 +- .../HttpStatusRequestRejectedHandler.java | 5 +- .../firewall/RequestRejectedException.java | 2 + .../web/firewall/RequestRejectedHandler.java | 7 +- .../security/web/firewall/RequestWrapper.java | 22 +- .../web/firewall/StrictHttpFirewall.java | 310 +++-- .../security/web/header/Header.java | 3 +- .../security/web/header/HeaderWriter.java | 3 +- .../web/header/HeaderWriterFilter.java | 35 +- .../writers/CacheControlHeadersWriter.java | 11 +- .../writers/ClearSiteDataHeaderWriter.java | 40 +- .../header/writers/CompositeHeaderWriter.java | 4 +- .../ContentSecurityPolicyHeaderWriter.java | 55 +- .../DelegatingRequestMatcherHeaderWriter.java | 10 +- .../writers/FeaturePolicyHeaderWriter.java | 2 - .../web/header/writers/HpkpHeaderWriter.java | 132 ++- .../web/header/writers/HstsHeaderWriter.java | 47 +- .../writers/ReferrerPolicyHeaderWriter.java | 29 +- .../header/writers/StaticHeadersWriter.java | 1 + .../XContentTypeOptionsHeaderWriter.java | 1 + .../writers/XXssProtectionHeaderWriter.java | 7 +- ...ractRequestParameterAllowFromStrategy.java | 9 +- .../frameoptions/AllowFromStrategy.java | 8 +- .../frameoptions/RegExpAllowFromStrategy.java | 11 +- .../frameoptions/StaticAllowFromStrategy.java | 7 +- .../WhiteListedAllowFromStrategy.java | 10 +- .../XFrameOptionsHeaderWriter.java | 25 +- .../security/web/http/SecurityHeaders.java | 7 +- .../web/jaasapi/JaasApiIntegrationFilter.java | 16 +- .../security/web/jaasapi/package-info.java | 3 +- .../web/jackson2/CookieDeserializer.java | 10 +- .../security/web/jackson2/CookieMixin.java | 1 + .../web/jackson2/DefaultCsrfTokenMixin.java | 12 +- .../jackson2/DefaultSavedRequestMixin.java | 7 +- ...icatedAuthenticationTokenDeserializer.java | 30 +- ...AuthenticatedAuthenticationTokenMixin.java | 13 +- .../web/jackson2/SavedCookieMixin.java | 15 +- .../WebAuthenticationDetailsMixin.java | 6 +- .../web/jackson2/WebJackson2Module.java | 17 +- .../jackson2/WebServletJackson2Module.java | 15 +- ...thenticationPrincipalArgumentResolver.java | 28 +- .../annotation/CsrfTokenArgumentResolver.java | 20 +- ...urrentSecurityContextArgumentResolver.java | 36 +- .../security/web/package-info.java | 4 +- ...thenticationPrincipalArgumentResolver.java | 26 +- ...urrentSecurityContextArgumentResolver.java | 20 +- .../view/CsrfRequestDataValueProcessor.java | 14 +- .../web/savedrequest/CookieRequestCache.java | 33 +- .../web/savedrequest/DefaultSavedRequest.java | 64 +- .../security/web/savedrequest/Enumerator.java | 11 +- .../web/savedrequest/FastHttpDateFormat.java | 13 +- .../savedrequest/HttpSessionRequestCache.java | 25 +- .../web/savedrequest/NullRequestCache.java | 6 +- .../web/savedrequest/RequestCache.java | 7 +- .../savedrequest/RequestCacheAwareFilter.java | 11 +- .../web/savedrequest/SavedCookie.java | 18 +- .../web/savedrequest/SavedRequest.java | 1 + .../SavedRequestAwareWrapper.java | 3 + .../web/savedrequest/SimpleSavedRequest.java | 6 +- .../web/savedrequest/package-info.java | 10 +- .../server/DefaultServerRedirectStrategy.java | 7 +- ...egatingServerAuthenticationEntryPoint.java | 51 +- .../server/MatcherSecurityWebFilterChain.java | 10 +- .../web/server/SecurityWebFilterChain.java | 10 +- .../ServerAuthenticationEntryPoint.java | 5 +- ...erverFormLoginAuthenticationConverter.java | 13 +- ...erverHttpBasicAuthenticationConverter.java | 17 +- .../web/server/ServerRedirectStrategy.java | 4 +- .../web/server/WebFilterChainProxy.java | 15 +- .../web/server/WebFilterExchange.java | 8 +- .../AnonymousAuthenticationWebFilter.java | 48 +- ...tionConverterServerWebExchangeMatcher.java | 12 +- .../AuthenticationWebFilter.java | 129 ++- ...ingServerAuthenticationSuccessHandler.java | 11 +- ...tpBasicServerAuthenticationEntryPoint.java | 7 +- .../HttpStatusServerEntryPoint.java | 2 + ...PreAuthenticatedAuthenticationManager.java | 31 +- ...edirectServerAuthenticationEntryPoint.java | 7 +- ...ectServerAuthenticationFailureHandler.java | 8 +- ...ectServerAuthenticationSuccessHandler.java | 24 +- .../ServerAuthenticationConverter.java | 10 +- ...uthenticationEntryPointFailureHandler.java | 18 +- .../ServerAuthenticationFailureHandler.java | 2 + .../ServerAuthenticationSuccessHandler.java | 6 +- ...erverFormLoginAuthenticationConverter.java | 1 + ...erverHttpBasicAuthenticationConverter.java | 5 +- .../ServerX509AuthenticationConverter.java | 9 +- .../authentication/SwitchUserWebFilter.java | 144 ++- ...ainServerAuthenticationSuccessHandler.java | 8 +- .../logout/DelegatingServerLogoutHandler.java | 7 +- .../HeaderWriterServerLogoutHandler.java | 14 +- ...usReturningServerLogoutSuccessHandler.java | 20 +- .../logout/LogoutWebFilter.java | 46 +- .../RedirectServerLogoutSuccessHandler.java | 6 +- .../SecurityContextServerLogoutHandler.java | 16 +- .../logout/ServerLogoutHandler.java | 3 + .../logout/ServerLogoutSuccessHandler.java | 5 +- .../authorization/AuthorizationContext.java | 3 + .../authorization/AuthorizationWebFilter.java | 30 +- ...elegatingReactiveAuthorizationManager.java | 32 +- .../ExceptionTranslationWebFilter.java | 24 +- .../HttpStatusServerAccessDeniedHandler.java | 17 +- .../ServerAccessDeniedHandler.java | 2 +- ...geDelegatingServerAccessDeniedHandler.java | 50 +- .../NoOpServerSecurityContextRepository.java | 12 +- .../context/ReactorContextWebFilter.java | 14 +- .../SecurityContextServerWebExchange.java | 6 +- ...rityContextServerWebExchangeWebFilter.java | 4 +- .../ServerSecurityContextRepository.java | 2 + ...essionServerSecurityContextRepository.java | 55 +- .../csrf/CookieServerCsrfTokenRepository.java | 23 +- .../web/server/csrf/CsrfException.java | 1 + .../server/csrf/CsrfServerLogoutHandler.java | 8 +- .../security/web/server/csrf/CsrfToken.java | 1 - .../web/server/csrf/CsrfWebFilter.java | 82 +- .../web/server/csrf/DefaultCsrfToken.java | 1 + .../csrf/ServerCsrfTokenRepository.java | 5 +- .../WebSessionServerCsrfTokenRepository.java | 29 +- .../CacheControlServerHttpHeadersWriter.java | 8 +- .../ClearSiteDataServerHttpHeadersWriter.java | 43 +- .../CompositeServerHttpHeadersWriter.java | 8 +- ...SecurityPolicyServerHttpHeadersWriter.java | 6 +- ...entTypeOptionsServerHttpHeadersWriter.java | 10 +- .../FeaturePolicyServerHttpHeadersWriter.java | 7 +- .../header/HttpHeaderWriterWebFilter.java | 1 + ...ReferrerPolicyServerHttpHeadersWriter.java | 3 +- .../header/ServerHttpHeadersWriter.java | 4 +- .../header/StaticServerHttpHeadersWriter.java | 14 +- ...nsportSecurityServerHttpHeadersWriter.java | 25 +- ...entTypeOptionsServerHttpHeadersWriter.java | 10 +- .../XFrameOptionsServerHttpHeadersWriter.java | 27 +- ...XXssProtectionServerHttpHeadersWriter.java | 21 +- .../jackson2/DefaultCsrfServerTokenMixin.java | 17 +- .../jackson2/WebServerJackson2Module.java | 13 +- .../CookieServerRequestCache.java | 45 +- .../savedrequest/NoOpServerRequestCache.java | 12 +- .../savedrequest/ServerRequestCache.java | 5 +- .../ServerRequestCacheWebFilter.java | 8 +- .../WebSessionServerRequestCache.java | 58 +- .../transport/HttpsRedirectWebFilter.java | 26 +- .../ui/LoginPageGeneratingWebFilter.java | 64 +- .../ui/LogoutPageGeneratingWebFilter.java | 62 +- .../matcher/AndServerWebExchangeMatcher.java | 42 +- .../MediaTypeServerWebExchangeMatcher.java | 27 +- .../NegatedServerWebExchangeMatcher.java | 32 +- .../matcher/OrServerWebExchangeMatcher.java | 41 +- ...PatternParserServerWebExchangeMatcher.java | 40 +- .../matcher/ServerWebExchangeMatcher.java | 8 +- .../ServerWebExchangeMatcherEntry.java | 4 + .../matcher/ServerWebExchangeMatchers.java | 8 +- .../csrf/CsrfRequestDataValueProcessor.java | 8 +- .../util/matcher/MvcRequestMatcher.java | 16 +- .../HttpServlet3RequestFactory.java | 59 +- .../servletapi/HttpServletRequestFactory.java | 1 + ...curityContextHolderAwareRequestFilter.java | 12 +- ...urityContextHolderAwareRequestWrapper.java | 13 +- .../security/web/servletapi/package-info.java | 7 +- .../web/session/ConcurrentSessionFilter.java | 57 +- .../web/session/HttpSessionCreatedEvent.java | 2 + .../session/HttpSessionDestroyedEvent.java | 2 + .../session/HttpSessionEventPublisher.java | 5 +- .../session/HttpSessionIdChangedEvent.java | 7 +- .../InvalidSessionAccessDeniedHandler.java | 5 +- .../SessionInformationExpiredEvent.java | 7 +- .../SessionInformationExpiredStrategy.java | 4 +- .../web/session/SessionManagementFilter.java | 36 +- .../SimpleRedirectInvalidSessionStrategy.java | 15 +- ...rectSessionInformationExpiredStrategy.java | 13 +- .../security/web/session/package-info.java | 1 - .../web/util/OnCommittedResponseWrapper.java | 10 +- .../security/web/util/RedirectUrlBuilder.java | 8 + .../security/web/util/TextEscapeUtils.java | 10 +- .../security/web/util/ThrowableAnalyzer.java | 31 +- .../web/util/ThrowableCauseExtractor.java | 4 +- .../security/web/util/UrlUtils.java | 23 +- .../web/util/matcher/AndRequestMatcher.java | 7 +- .../util/matcher/AntPathRequestMatcher.java | 60 +- .../web/util/matcher/AnyRequestMatcher.java | 2 + .../web/util/matcher/ELRequestMatcher.java | 3 +- .../web/util/matcher/IpAddressMatcher.java | 7 +- .../util/matcher/MediaTypeRequestMatcher.java | 27 +- .../util/matcher/NegatedRequestMatcher.java | 2 + .../web/util/matcher/OrRequestMatcher.java | 8 +- .../web/util/matcher/RegexRequestMatcher.java | 17 +- .../matcher/RequestHeaderRequestMatcher.java | 12 +- .../web/util/matcher/RequestMatcher.java | 37 +- .../matcher/RequestVariablesExtractor.java | 5 +- .../security/web/util/package-info.java | 1 - .../security/MockFilterConfig.java | 3 +- .../security/MockPortResolver.java | 3 + .../reactive/server/WebTestClientBuilder.java | 5 +- .../web/reactive/server/WebTestHandler.java | 8 +- .../web/DefaultRedirectStrategyTests.java | 18 +- .../security/web/FilterChainProxyTests.java | 79 +- .../security/web/FilterInvocationTests.java | 9 +- .../security/web/PortMapperImplTests.java | 19 +- .../security/web/PortResolverImplTests.java | 1 + ...tWebInvocationPrivilegeEvaluatorTests.java | 35 +- .../DelegatingAccessDeniedHandlerTests.java | 18 +- .../ExceptionTranslationFilterTests.java | 69 +- ...herDelegatingAccessDeniedHandlerTests.java | 5 + .../ChannelDecisionManagerImplTests.java | 29 +- .../channel/ChannelProcessingFilterTests.java | 56 +- .../InsecureChannelProcessorTests.java | 17 +- .../channel/RetryWithHttpEntryPointTests.java | 21 +- .../RetryWithHttpsEntryPointTests.java | 19 +- .../channel/SecureChannelProcessorTests.java | 17 +- ...leEvaluationContextPostProcessorTests.java | 13 +- ...aultWebSecurityExpressionHandlerTests.java | 16 +- .../DelegatingEvaluationContextTests.java | 3 + ...InvocationSecurityMetadataSourceTests.java | 10 +- .../expression/WebExpressionVoterTests.java | 34 +- .../WebSecurityExpressionRootTests.java | 10 +- ...InvocationSecurityMetadataSourceTests.java | 28 +- .../FilterSecurityInterceptorTests.java | 31 +- .../web/access/intercept/RequestKeyTests.java | 5 +- ...ctAuthenticationProcessingFilterTests.java | 87 +- .../AnonymousAuthenticationFilterTests.java | 28 +- .../AuthenticationFilterTests.java | 41 +- ...DefaultLoginPageGeneratingFilterTests.java | 57 +- ...gAuthenticationEntryPointContextTests.java | 11 +- ...legatingAuthenticationEntryPointTests.java | 3 + ...pingAuthenticationFailureHandlerTests.java | 10 +- ...rwardAuthenticaionSuccessHandlerTests.java | 117 +- ...wardAuthenticationFailureHandlerTests.java | 120 +- .../HttpStatusEntryPointTests.java | 4 +- ...LoginUrlAuthenticationEntryPointTests.java | 41 +- ...wareAuthenticationSuccessHandlerTests.java | 1 + ...eUrlAuthenticationFailureHandlerTests.java | 13 +- ...eUrlAuthenticationSuccessHandlerTests.java | 15 +- ...namePasswordAuthenticationFilterTests.java | 63 +- .../logout/CompositeLogoutHandlerTests.java | 24 +- .../CookieClearingLogoutHandlerTests.java | 6 +- .../DelegatingLogoutSuccessHandlerTests.java | 29 +- .../HeaderWriterLogoutHandlerTests.java | 5 +- .../logout/LogoutHandlerTests.java | 2 + ...cessEventPublishingLogoutHandlerTests.java | 2 + .../SecurityContextLogoutHandlerTests.java | 15 +- .../SimpleUrlLogoutSuccessHandlerTests.java | 1 - ...PreAuthenticatedProcessingFilterTests.java | 96 +- .../Http403ForbiddenEntryPointTests.java | 8 +- ...henticatedAuthenticationProviderTests.java | 34 +- ...AuthenticatedAuthenticationTokenTests.java | 17 +- ...tedAuthoritiesUserDetailsServiceTests.java | 18 +- ...horitiesWebAuthenticationDetailsTests.java | 6 +- ...estAttributeAuthenticationFilterTests.java | 22 +- ...equestHeaderAuthenticationFilterTests.java | 12 +- ...edWebAuthenticationDetailsSourceTests.java | 21 +- ...PreAuthenticatedProcessingFilterTests.java | 14 +- .../WebXmlJ2eeDefinedRolesRetrieverTests.java | 4 +- ...PreAuthenticatedProcessingFilterTests.java | 16 +- .../SubjectDnX509PrincipalExtractorTests.java | 11 +- .../preauth/x509/X509TestUtils.java | 9 +- .../AbstractRememberMeServicesTests.java | 74 +- .../JdbcTokenRepositoryImplTests.java | 61 +- .../NullRememberMeServicesTests.java | 2 + ...tentTokenBasedRememberMeServicesTests.java | 55 +- .../RememberMeAuthenticationFilterTests.java | 43 +- .../TokenBasedRememberMeServicesTests.java | 99 +- ...eSessionIdAuthenticationStrategyTests.java | 1 + ...iteSessionAuthenticationStrategyTests.java | 11 +- ...ionControlAuthenticationStrategyTests.java | 49 +- ...terSessionAuthenticationStrategyTests.java | 5 +- .../switchuser/SwitchUserFilterTests.java | 75 +- .../SwitchUserGrantedAuthorityTests.java | 8 +- ...efaultLogoutPageGeneratingFilterTests.java | 51 +- .../BasicAuthenticationConverterTests.java | 1 + .../BasicAuthenticationEntryPointTests.java | 4 +- .../www/BasicAuthenticationFilterTests.java | 95 +- .../www/DigestAuthUtilsTests.java | 36 +- .../DigestAuthenticationEntryPointTests.java | 14 +- .../www/DigestAuthenticationFilterTests.java | 246 ++-- ...icationPrincipalArgumentResolverTests.java | 58 +- .../ConcurrentSessionFilterTests.java | 64 +- ...ecurityWebApplicationInitializerTests.java | 161 ++- ...SessionSecurityContextRepositoryTests.java | 241 ++-- ...xtOnUpdateOrErrorResponseWrapperTests.java | 16 +- ...SecurityContextPersistenceFilterTests.java | 26 +- ...extCallableProcessingInterceptorTests.java | 5 +- ...WebAsyncManagerIntegrationFilterTests.java | 49 +- .../csrf/CookieCsrfTokenRepositoryTests.java | 61 +- .../csrf/CsrfAuthenticationStrategyTests.java | 63 +- .../security/web/csrf/CsrfFilterTests.java | 161 +-- .../web/csrf/CsrfLogoutHandlerTests.java | 4 +- .../web/csrf/DefaultCsrfTokenTests.java | 4 + .../HttpSessionCsrfTokenRepositoryTests.java | 6 +- .../csrf/LazyCsrfTokenRepositoryTests.java | 7 +- .../csrf/MissingCsrfTokenExceptionTests.java | 1 - .../security/web/debug/DebugFilterTests.java | 22 +- .../firewall/DefaultHttpFirewallTests.java | 15 +- .../DefaultRequestRejectedHandlerTests.java | 9 +- .../web/firewall/FirewalledResponseTests.java | 4 + ...HttpStatusRequestRejectedHandlerTests.java | 10 +- .../web/firewall/RequestWrapperTests.java | 2 + .../web/firewall/StrictHttpFirewallTests.java | 30 +- .../web/header/HeaderWriterFilterTests.java | 30 +- .../CacheControlHeadersWriterTests.java | 15 +- .../ClearSiteDataHeaderWriterTests.java | 9 +- .../writers/CompositeHeaderWriterTests.java | 4 +- ...ontentSecurityPolicyHeaderWriterTests.java | 24 +- ...gatingRequestMatcherHeaderWriterTests.java | 2 + .../FeaturePolicyHeaderWriterTests.java | 11 +- .../header/writers/HpkpHeaderWriterTests.java | 25 +- .../header/writers/HstsHeaderWriterTests.java | 27 +- .../ReferrerPolicyHeaderWriterTests.java | 4 + .../writers/StaticHeaderWriterTests.java | 26 +- .../XContentTypeOptionsHeaderWriterTests.java | 4 +- .../XXssProtectionHeaderWriterTests.java | 1 + ...equestParameterAllowFromStrategyTests.java | 22 +- .../FrameOptionsHeaderWriterTests.java | 11 +- .../RegExpAllowFromStrategyTests.java | 8 +- .../StaticAllowFromStrategyTests.java | 1 + .../XFrameOptionsHeaderWriterTests.java | 7 +- .../JaasApiIntegrationFilterTests.java | 35 +- .../web/jackson2/AbstractMixinTests.java | 1 + .../web/jackson2/CookieMixinTests.java | 1 + .../jackson2/DefaultCsrfTokenMixinTests.java | 1 + .../DefaultSavedRequestMixinTests.java | 16 +- ...nticatedAuthenticationTokenMixinTests.java | 14 +- .../web/jackson2/SavedCookieMixinTests.java | 2 + .../WebAuthenticationDetailsMixinTests.java | 10 +- .../security/web/method/ResolvableMethod.java | 145 ++- ...icationPrincipalArgumentResolverTests.java | 77 +- .../CsrfTokenArgumentResolverTests.java | 17 +- ...tSecurityContextArgumentResolverTests.java | 94 +- ...icationPrincipalArgumentResolverTests.java | 56 +- ...tSecurityContextArgumentResolverTests.java | 152 ++- .../CsrfRequestDataValueProcessorTests.java | 25 +- .../savedrequest/CookieRequestCacheTests.java | 6 +- .../DefaultSavedRequestTests.java | 10 +- .../HttpSessionRequestCacheTests.java | 34 +- .../RequestCacheAwareFilterTests.java | 10 +- .../web/savedrequest/SavedCookieTests.java | 2 + .../SavedRequestAwareWrapperTests.java | 24 +- .../savedrequest/SimpleSavedRequestTests.java | 4 +- .../DefaultServerRedirectStrategyTests.java | 10 +- ...ngServerAuthenticationEntryPointTests.java | 25 +- .../web/server/WebFilterChainProxyTests.java | 12 +- .../web/server/WebFilterExchangeTests.java | 7 +- ...AnonymousAuthenticationWebFilterTests.java | 19 +- ...onverterServerWebExchangeMatcherTests.java | 10 +- .../AuthenticationWebFilterTests.java | 205 ++-- ...rverAuthenticationSuccessHandlerTests.java | 35 +- ...icServerAuthenticationEntryPointTests.java | 21 +- .../HttpStatusServerEntryPointTests.java | 11 +- ...thenticatedAuthenticationManagerTests.java | 17 +- ...ctServerAuthenticationEntryPointTests.java | 16 +- ...rverAuthenticationFailureHandlerTests.java | 19 +- ...rverAuthenticationSuccessHandlerTests.java | 21 +- ...ticationEntryPointFailureHandlerTests.java | 4 + ...FormLoginAuthenticationConverterTests.java | 2 + ...HttpBasicAuthenticationConverterTests.java | 23 +- ...erverX509AuthenticationConverterTests.java | 2 + .../SwitchUserWebFilterTests.java | 234 ++-- .../DelegatingServerLogoutHandlerTests.java | 36 +- .../HeaderWriterServerLogoutHandlerTests.java | 1 + ...urningServerLogoutSuccessHandlerTests.java | 6 +- .../logout/LogoutWebFilterTests.java | 32 +- .../AuthorizationWebFilterTests.java | 69 +- ...tingReactiveAuthorizationManagerTests.java | 19 +- .../ExceptionTranslationWebFilterTests.java | 38 +- ...pStatusServerAccessDeniedHandlerTests.java | 4 + ...egatingServerAccessDeniedHandlerTests.java | 5 + ...pServerSecurityContextRepositoryTests.java | 9 +- .../context/ReactorContextWebFilterTests.java | 23 +- ...ontextServerWebExchangeWebFilterTests.java | 53 +- ...nServerSecurityContextRepositoryTests.java | 4 +- .../CookieServerCsrfTokenRepositoryTests.java | 19 +- .../csrf/CsrfServerLogoutHandlerTests.java | 13 +- .../web/server/csrf/CsrfWebFilterTests.java | 151 +-- ...SessionServerCsrfTokenRepositoryTests.java | 21 +- ...heControlServerHttpHeadersWriterTests.java | 15 +- ...rSiteDataServerHttpHeadersWriterTests.java | 33 +- ...CompositeServerHttpHeadersWriterTests.java | 38 +- ...ityPolicyServerHttpHeadersWriterTests.java | 20 +- ...urePolicyServerHttpHeadersWriterTests.java | 6 +- .../HttpHeaderWriterWebFilterTests.java | 6 +- ...rerPolicyServerHttpHeadersWriterTests.java | 7 +- .../StaticServerHttpHeadersWriterTests.java | 35 +- ...tSecurityServerHttpHeadersWriterTests.java | 2 + ...peOptionsServerHttpHeadersWriterTests.java | 8 +- ...meOptionsServerHttpHeadersWriterTests.java | 1 + ...rotectionServerHttpHeadersWriterTests.java | 1 + .../DefaultCsrfServerTokenMixinTests.java | 1 + .../CookieServerRequestCacheTests.java | 26 +- .../ServerRequestCacheWebFilterTests.java | 2 + .../WebSessionServerRequestCacheTests.java | 14 +- .../HttpsRedirectWebFilterTests.java | 17 +- .../ui/LoginPageGeneratingWebFilterTests.java | 5 +- .../AndServerWebExchangeMatcherTests.java | 3 + ...ediaTypeServerWebExchangeMatcherTests.java | 5 +- .../NegatedServerWebExchangeMatcherTests.java | 3 + .../OrServerWebExchangeMatcherTests.java | 5 +- ...hMatcherServerWebExchangeMatcherTests.java | 6 + .../ServerWebExchangeMatchersTests.java | 18 +- .../CsrfRequestDataValueProcessorTests.java | 18 +- .../util/matcher/MvcRequestMatcherTests.java | 55 +- ...yContextHolderAwareRequestFilterTests.java | 103 +- ...ContextHolderAwareRequestWrapperTests.java | 39 +- ...ultSessionAuthenticationStrategyTests.java | 47 +- .../HttpSessionDestroyedEventTests.java | 2 +- .../HttpSessionEventPublisherTests.java | 16 +- .../web/session/MockApplicationListener.java | 4 + .../SessionInformationExpiredEventTests.java | 6 +- .../session/SessionManagementFilterTests.java | 28 +- .../util/OnCommittedResponseWrapperTests.java | 18 +- .../web/util/TextEscapeUtilsTests.java | 4 +- .../web/util/ThrowableAnalyzerTests.java | 47 +- .../security/web/util/UrlUtilsTests.java | 1 - .../util/matcher/AndRequestMatcherTests.java | 5 +- .../matcher/AntPathRequestMatcherTests.java | 40 +- .../util/matcher/ELRequestMatcherTests.java | 13 +- .../util/matcher/IpAddressMatcherTests.java | 15 +- ...diaTypeRequestMatcherRequestHCNSTests.java | 30 +- .../matcher/MediaTypeRequestMatcherTests.java | 64 +- .../matcher/NegatedRequestMatcherTests.java | 3 +- .../util/matcher/OrRequestMatcherTests.java | 5 +- .../matcher/RegexRequestMatcherTests.java | 4 +- .../RequestHeaderRequestMatcherTests.java | 21 +- 2487 files changed, 41506 insertions(+), 46548 deletions(-) diff --git a/acl/src/main/java/org/springframework/security/acls/AclEntryVoter.java b/acl/src/main/java/org/springframework/security/acls/AclEntryVoter.java index 0d5ebcc4e4..80f38fd296 100644 --- a/acl/src/main/java/org/springframework/security/acls/AclEntryVoter.java +++ b/acl/src/main/java/org/springframework/security/acls/AclEntryVoter.java @@ -92,10 +92,10 @@ import org.springframework.util.StringUtils; *

* All comparisons and prefixes are case sensitive. * - * * @author Ben Alex */ public class AclEntryVoter extends AbstractAclVoter { + // ~ Static fields/initializers // ===================================================================================== @@ -105,23 +105,26 @@ public class AclEntryVoter extends AbstractAclVoter { // ================================================================================================ private AclService aclService; + private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); + private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); + private String internalMethod; + private String processConfigAttribute; + private List requirePermission; // ~ Constructors // =================================================================================================== - public AclEntryVoter(AclService aclService, String processConfigAttribute, - Permission[] requirePermission) { + public AclEntryVoter(AclService aclService, String processConfigAttribute, Permission[] requirePermission) { Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory"); Assert.notNull(aclService, "An AclService is mandatory"); if ((requirePermission == null) || (requirePermission.length == 0)) { - throw new IllegalArgumentException( - "One or more requirePermission entries is mandatory"); + throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); } this.aclService = aclService; @@ -138,7 +141,6 @@ public class AclEntryVoter extends AbstractAclVoter { * evaluation. This is useful if a domain object contains a parent that an ACL * evaluation should be targeted for, instead of the child domain object (which * perhaps is being created and as such does not yet have any ACL permissions) - * * @return null to use the domain object, or the name of a method (that * requires no arguments) that should be invoked to obtain an Object * which will be the domain object used for ACL evaluation @@ -155,10 +157,8 @@ public class AclEntryVoter extends AbstractAclVoter { return processConfigAttribute; } - public void setObjectIdentityRetrievalStrategy( - ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { - Assert.notNull(objectIdentityRetrievalStrategy, - "ObjectIdentityRetrievalStrategy required"); + public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { + Assert.notNull(objectIdentityRetrievalStrategy, "ObjectIdentityRetrievalStrategy required"); this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; } @@ -168,12 +168,10 @@ public class AclEntryVoter extends AbstractAclVoter { } public boolean supports(ConfigAttribute attribute) { - return (attribute.getAttribute() != null) - && attribute.getAttribute().equals(getProcessConfigAttribute()); + return (attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute()); } - public int vote(Authentication authentication, MethodInvocation object, - Collection attributes) { + public int vote(Authentication authentication, MethodInvocation object, Collection attributes) { for (ConfigAttribute attr : attributes) { @@ -201,30 +199,25 @@ public class AclEntryVoter extends AbstractAclVoter { domainObject = method.invoke(domainObject); } catch (NoSuchMethodException nsme) { - throw new AuthorizationServiceException("Object of class '" - + domainObject.getClass() - + "' does not provide the requested internalMethod: " - + internalMethod); + throw new AuthorizationServiceException("Object of class '" + domainObject.getClass() + + "' does not provide the requested internalMethod: " + internalMethod); } catch (IllegalAccessException iae) { logger.debug("IllegalAccessException", iae); throw new AuthorizationServiceException( - "Problem invoking internalMethod: " + internalMethod - + " for object: " + domainObject); + "Problem invoking internalMethod: " + internalMethod + " for object: " + domainObject); } catch (InvocationTargetException ite) { logger.debug("InvocationTargetException", ite); throw new AuthorizationServiceException( - "Problem invoking internalMethod: " + internalMethod - + " for object: " + domainObject); + "Problem invoking internalMethod: " + internalMethod + " for object: " + domainObject); } } // Obtain the OID applicable to the domain object - ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy - .getObjectIdentity(domainObject); + ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject); // Obtain the SIDs applicable to the principal List sids = sidRetrievalStrategy.getSids(authentication); @@ -253,7 +246,8 @@ public class AclEntryVoter extends AbstractAclVoter { } else { if (logger.isDebugEnabled()) { - logger.debug("Voting to deny access - ACLs returned, but insufficient permissions for this principal"); + logger.debug( + "Voting to deny access - ACLs returned, but insufficient permissions for this principal"); } return ACCESS_DENIED; @@ -271,4 +265,5 @@ public class AclEntryVoter extends AbstractAclVoter { // No configuration attribute matched, so abstain return ACCESS_ABSTAIN; } + } diff --git a/acl/src/main/java/org/springframework/security/acls/AclPermissionCacheOptimizer.java b/acl/src/main/java/org/springframework/security/acls/AclPermissionCacheOptimizer.java index de440a5115..1b87dea11a 100644 --- a/acl/src/main/java/org/springframework/security/acls/AclPermissionCacheOptimizer.java +++ b/acl/src/main/java/org/springframework/security/acls/AclPermissionCacheOptimizer.java @@ -38,9 +38,13 @@ import org.springframework.security.core.Authentication; * @since 3.1 */ public class AclPermissionCacheOptimizer implements PermissionCacheOptimizer { + private final Log logger = LogFactory.getLog(getClass()); + private final AclService aclService; + private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); + private ObjectIdentityRetrievalStrategy oidRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); public AclPermissionCacheOptimizer(AclService aclService) { @@ -71,12 +75,12 @@ public class AclPermissionCacheOptimizer implements PermissionCacheOptimizer { aclService.readAclsById(oidsToCache, sids); } - public void setObjectIdentityRetrievalStrategy( - ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { + public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { this.oidRetrievalStrategy = objectIdentityRetrievalStrategy; } public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { this.sidRetrievalStrategy = sidRetrievalStrategy; } + } diff --git a/acl/src/main/java/org/springframework/security/acls/AclPermissionEvaluator.java b/acl/src/main/java/org/springframework/security/acls/AclPermissionEvaluator.java index b6d362a305..7cdfab8286 100644 --- a/acl/src/main/java/org/springframework/security/acls/AclPermissionEvaluator.java +++ b/acl/src/main/java/org/springframework/security/acls/AclPermissionEvaluator.java @@ -51,9 +51,13 @@ public class AclPermissionEvaluator implements PermissionEvaluator { private final Log logger = LogFactory.getLog(getClass()); private final AclService aclService; + private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); + private ObjectIdentityGenerator objectIdentityGenerator = new ObjectIdentityRetrievalStrategyImpl(); + private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); + private PermissionFactory permissionFactory = new DefaultPermissionFactory(); public AclPermissionEvaluator(AclService aclService) { @@ -65,28 +69,24 @@ public class AclPermissionEvaluator implements PermissionEvaluator { * the ACL configuration. If the domain object is null, returns false (this can always * be overridden using a null check in the expression itself). */ - public boolean hasPermission(Authentication authentication, Object domainObject, - Object permission) { + public boolean hasPermission(Authentication authentication, Object domainObject, Object permission) { if (domainObject == null) { return false; } - ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy - .getObjectIdentity(domainObject); + ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject); return checkPermission(authentication, objectIdentity, permission); } - public boolean hasPermission(Authentication authentication, Serializable targetId, - String targetType, Object permission) { - ObjectIdentity objectIdentity = objectIdentityGenerator.createObjectIdentity( - targetId, targetType); - - return checkPermission(authentication, objectIdentity, permission); - } - - private boolean checkPermission(Authentication authentication, ObjectIdentity oid, + public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) { + ObjectIdentity objectIdentity = objectIdentityGenerator.createObjectIdentity(targetId, targetType); + + return checkPermission(authentication, objectIdentity, permission); + } + + private boolean checkPermission(Authentication authentication, ObjectIdentity oid, Object permission) { // Obtain the SIDs applicable to the principal List sids = sidRetrievalStrategy.getSids(authentication); List requiredPermission = resolvePermission(permission); @@ -94,8 +94,7 @@ public class AclPermissionEvaluator implements PermissionEvaluator { final boolean debug = logger.isDebugEnabled(); if (debug) { - logger.debug("Checking permission '" + permission + "' for object '" + oid - + "'"); + logger.debug("Checking permission '" + permission + "' for object '" + oid + "'"); } try { @@ -157,8 +156,7 @@ public class AclPermissionEvaluator implements PermissionEvaluator { throw new IllegalArgumentException("Unsupported permission: " + permission); } - public void setObjectIdentityRetrievalStrategy( - ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { + public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; } @@ -173,4 +171,5 @@ public class AclPermissionEvaluator implements PermissionEvaluator { public void setPermissionFactory(PermissionFactory permissionFactory) { this.permissionFactory = permissionFactory; } + } diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java b/acl/src/main/java/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java index 4e7db49438..96956db09b 100644 --- a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java +++ b/acl/src/main/java/org/springframework/security/acls/afterinvocation/AbstractAclProvider.java @@ -40,14 +40,20 @@ import org.springframework.util.Assert; * @author Ben Alex */ public abstract class AbstractAclProvider implements AfterInvocationProvider { + // ~ Instance fields // ================================================================================================ protected final AclService aclService; + protected Class processDomainObjectClass = Object.class; + protected ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); + protected SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); + protected String processConfigAttribute; + protected final List requirePermission; // ~ Constructors @@ -59,8 +65,7 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider { Assert.notNull(aclService, "An AclService is mandatory"); if (requirePermission == null || requirePermission.isEmpty()) { - throw new IllegalArgumentException( - "One or more requirePermission entries is mandatory"); + throw new IllegalArgumentException("One or more requirePermission entries is mandatory"); } this.aclService = aclService; @@ -77,8 +82,7 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider { protected boolean hasPermission(Authentication authentication, Object domainObject) { // Obtain the OID applicable to the domain object - ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy - .getObjectIdentity(domainObject); + ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject); // Obtain the SIDs applicable to the principal List sids = sidRetrievalStrategy.getSids(authentication); @@ -94,10 +98,8 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider { } } - public void setObjectIdentityRetrievalStrategy( - ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { - Assert.notNull(objectIdentityRetrievalStrategy, - "ObjectIdentityRetrievalStrategy required"); + public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { + Assert.notNull(objectIdentityRetrievalStrategy, "ObjectIdentityRetrievalStrategy required"); this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; } @@ -107,8 +109,7 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider { } public void setProcessDomainObjectClass(Class processDomainObjectClass) { - Assert.notNull(processDomainObjectClass, - "processDomainObjectClass cannot be set to null"); + Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null"); this.processDomainObjectClass = processDomainObjectClass; } @@ -124,12 +125,11 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider { /** * This implementation supports any type of class, because it does not query the * presented secure object. - * * @param clazz the secure object - * * @return always true */ public boolean supports(Class clazz) { return true; } + } diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java b/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java index 2e7e2a35ed..bf73dc8c70 100644 --- a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java +++ b/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProvider.java @@ -60,13 +60,12 @@ import org.springframework.security.core.Authentication; * @author Ben Alex * @author Paulo Neves */ -public class AclEntryAfterInvocationCollectionFilteringProvider extends - AbstractAclProvider { +public class AclEntryAfterInvocationCollectionFilteringProvider extends AbstractAclProvider { + // ~ Static fields/initializers // ===================================================================================== - protected static final Log logger = LogFactory - .getLog(AclEntryAfterInvocationCollectionFilteringProvider.class); + protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationCollectionFilteringProvider.class); // ~ Constructors // =================================================================================================== @@ -80,9 +79,8 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends // ======================================================================================================== @SuppressWarnings("unchecked") - public Object decide(Authentication authentication, Object object, - Collection config, Object returnedObject) - throws AccessDeniedException { + public Object decide(Authentication authentication, Object object, Collection config, + Object returnedObject) throws AccessDeniedException { if (returnedObject == null) { logger.debug("Return object is null, skipping"); @@ -105,19 +103,15 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends filterer = new ArrayFilterer((Object[]) returnedObject); } else { - throw new AuthorizationServiceException( - "A Collection or an array (or null) was required as the " - + "returnedObject, but the returnedObject was: " - + returnedObject); + throw new AuthorizationServiceException("A Collection or an array (or null) was required as the " + + "returnedObject, but the returnedObject was: " + returnedObject); } // Locate unauthorised Collection elements for (Object domainObject : filterer) { // Ignore nulls or entries which aren't instances of the configured domain // object class - if (domainObject == null - || !getProcessDomainObjectClass().isAssignableFrom( - domainObject.getClass())) { + if (domainObject == null || !getProcessDomainObjectClass().isAssignableFrom(domainObject.getClass())) { continue; } @@ -125,8 +119,7 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends filterer.remove(domainObject); if (logger.isDebugEnabled()) { - logger.debug("Principal is NOT authorised for element: " - + domainObject); + logger.debug("Principal is NOT authorised for element: " + domainObject); } } } @@ -136,4 +129,5 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends return returnedObject; } + } diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java b/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java index 9a27f21572..f816868e6d 100644 --- a/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java +++ b/acl/src/main/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProvider.java @@ -58,13 +58,12 @@ import org.springframework.security.core.SpringSecurityMessageSource; *

* All comparisons and prefixes are case sensitive. */ -public class AclEntryAfterInvocationProvider extends AbstractAclProvider implements - MessageSourceAware { +public class AclEntryAfterInvocationProvider extends AbstractAclProvider implements MessageSourceAware { + // ~ Static fields/initializers // ===================================================================================== - protected static final Log logger = LogFactory - .getLog(AclEntryAfterInvocationProvider.class); + protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationProvider.class); // ~ Instance fields // ================================================================================================ @@ -74,22 +73,20 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme // ~ Constructors // =================================================================================================== - public AclEntryAfterInvocationProvider(AclService aclService, - List requirePermission) { + public AclEntryAfterInvocationProvider(AclService aclService, List requirePermission) { this(aclService, "AFTER_ACL_READ", requirePermission); } - public AclEntryAfterInvocationProvider(AclService aclService, - String processConfigAttribute, List requirePermission) { + public AclEntryAfterInvocationProvider(AclService aclService, String processConfigAttribute, + List requirePermission) { super(aclService, processConfigAttribute, requirePermission); } // ~ Methods // ======================================================================================================== - public Object decide(Authentication authentication, Object object, - Collection config, Object returnedObject) - throws AccessDeniedException { + public Object decide(Authentication authentication, Object object, Collection config, + Object returnedObject) throws AccessDeniedException { if (returnedObject == null) { // AclManager interface contract prohibits nulls @@ -117,9 +114,8 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme logger.debug("Denying access"); - throw new AccessDeniedException(messages.getMessage( - "AclEntryAfterInvocationProvider.noPermission", new Object[] { - authentication.getName(), returnedObject }, + throw new AccessDeniedException(messages.getMessage("AclEntryAfterInvocationProvider.noPermission", + new Object[] { authentication.getName(), returnedObject }, "Authentication {0} has NO permissions to the domain object {1}")); } @@ -129,4 +125,5 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/ArrayFilterer.java b/acl/src/main/java/org/springframework/security/acls/afterinvocation/ArrayFilterer.java index 1ffc3c7049..ed7e8031a7 100644 --- a/acl/src/main/java/org/springframework/security/acls/afterinvocation/ArrayFilterer.java +++ b/acl/src/main/java/org/springframework/security/acls/afterinvocation/ArrayFilterer.java @@ -32,6 +32,7 @@ import org.apache.commons.logging.LogFactory; * @author Paulo Neves */ class ArrayFilterer implements Filterer { + // ~ Static fields/initializers // ===================================================================================== @@ -41,6 +42,7 @@ class ArrayFilterer implements Filterer { // ================================================================================================ private final Set removeList; + private final T[] list; // ~ Constructors @@ -67,8 +69,7 @@ class ArrayFilterer implements Filterer { // Recreate an array of same type and filter the removed objects. int originalSize = list.length; int sizeOfResultingList = originalSize - removeList.size(); - T[] filtered = (T[]) Array.newInstance(list.getClass().getComponentType(), - sizeOfResultingList); + T[] filtered = (T[]) Array.newInstance(list.getClass().getComponentType(), sizeOfResultingList); for (int i = 0, j = 0; i < list.length; i++) { T object = list[i]; @@ -80,8 +81,8 @@ class ArrayFilterer implements Filterer { } if (logger.isDebugEnabled()) { - logger.debug("Original array contained " + originalSize - + " elements; now contains " + sizeOfResultingList + " elements"); + logger.debug("Original array contained " + originalSize + " elements; now contains " + sizeOfResultingList + + " elements"); } return filtered; @@ -119,4 +120,5 @@ class ArrayFilterer implements Filterer { public void remove(T object) { removeList.add(object); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/CollectionFilterer.java b/acl/src/main/java/org/springframework/security/acls/afterinvocation/CollectionFilterer.java index b937dd32d0..9d5fb816d7 100644 --- a/acl/src/main/java/org/springframework/security/acls/afterinvocation/CollectionFilterer.java +++ b/acl/src/main/java/org/springframework/security/acls/afterinvocation/CollectionFilterer.java @@ -31,6 +31,7 @@ import java.util.Set; * @author Paulo Neves */ class CollectionFilterer implements Filterer { + // ~ Static fields/initializers // ===================================================================================== @@ -77,8 +78,8 @@ class CollectionFilterer implements Filterer { } if (logger.isDebugEnabled()) { - logger.debug("Original collection contained " + originalSize - + " elements; now contains " + collection.size() + " elements"); + logger.debug("Original collection contained " + originalSize + " elements; now contains " + + collection.size() + " elements"); } return collection; @@ -99,4 +100,5 @@ class CollectionFilterer implements Filterer { public void remove(T object) { removeList.add(object); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/Filterer.java b/acl/src/main/java/org/springframework/security/acls/afterinvocation/Filterer.java index 2f9b35b575..019e206731 100644 --- a/acl/src/main/java/org/springframework/security/acls/afterinvocation/Filterer.java +++ b/acl/src/main/java/org/springframework/security/acls/afterinvocation/Filterer.java @@ -25,27 +25,26 @@ import java.util.Iterator; * @author Paulo Neves */ interface Filterer extends Iterable { + // ~ Methods // ======================================================================================================== /** * Gets the filtered collection or array. - * * @return the filtered collection or array */ Object getFilteredObject(); /** * Returns an iterator over the filtered collection or array. - * * @return an Iterator */ Iterator iterator(); /** * Removes the given object from the resulting list. - * * @param object the object to be removed */ void remove(T object); + } diff --git a/acl/src/main/java/org/springframework/security/acls/afterinvocation/package-info.java b/acl/src/main/java/org/springframework/security/acls/afterinvocation/package-info.java index ab6c3e4251..57897ef56f 100644 --- a/acl/src/main/java/org/springframework/security/acls/afterinvocation/package-info.java +++ b/acl/src/main/java/org/springframework/security/acls/afterinvocation/package-info.java @@ -14,8 +14,7 @@ * limitations under the License. */ /** - * After-invocation providers for collection and array filtering. Consider using a {@code PostFilter} annotation in - * preference. + * After-invocation providers for collection and array filtering. Consider using a + * {@code PostFilter} annotation in preference. */ package org.springframework.security.acls.afterinvocation; - diff --git a/acl/src/main/java/org/springframework/security/acls/domain/AbstractPermission.java b/acl/src/main/java/org/springframework/security/acls/domain/AbstractPermission.java index ce679f4b49..9afd5a22c3 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/AbstractPermission.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/AbstractPermission.java @@ -29,6 +29,7 @@ public abstract class AbstractPermission implements Permission { // ================================================================================================ protected final char code; + protected int mask; // ~ Constructors @@ -36,7 +37,6 @@ public abstract class AbstractPermission implements Permission { /** * Sets the permission mask and uses the '*' character to represent active bits when * represented as a bit pattern string. - * * @param mask the integer bit mask for the permission */ protected AbstractPermission(int mask) { @@ -46,7 +46,6 @@ public abstract class AbstractPermission implements Permission { /** * Sets the permission mask and uses the specified character for active bits. - * * @param mask the integer bit mask for the permission * @param code the character to print for each active bit in the mask (see * {@link Permission#getPattern()}) @@ -88,4 +87,5 @@ public abstract class AbstractPermission implements Permission { public final int hashCode() { return this.mask; } + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/AccessControlEntryImpl.java b/acl/src/main/java/org/springframework/security/acls/domain/AccessControlEntryImpl.java index fb41f101d6..c6702efa94 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/AccessControlEntryImpl.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/AccessControlEntryImpl.java @@ -30,25 +30,30 @@ import java.io.Serializable; * * @author Ben Alex */ -public class AccessControlEntryImpl implements AccessControlEntry, - AuditableAccessControlEntry { +public class AccessControlEntryImpl implements AccessControlEntry, AuditableAccessControlEntry { + // ~ Instance fields // ================================================================================================ private final Acl acl; + private Permission permission; + private final Serializable id; + private final Sid sid; + private boolean auditFailure = false; + private boolean auditSuccess = false; + private final boolean granting; // ~ Constructors // =================================================================================================== - public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, - Permission permission, boolean granting, boolean auditSuccess, - boolean auditFailure) { + public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, Permission permission, boolean granting, + boolean auditSuccess, boolean auditFailure) { Assert.notNull(acl, "Acl required"); Assert.notNull(sid, "Sid required"); Assert.notNull(permission, "Permission required"); @@ -93,8 +98,7 @@ public class AccessControlEntryImpl implements AccessControlEntry, } else { // Both this.acl.objectIdentity and rhs.acl.objectIdentity are non-null - if (!this.acl.getObjectIdentity() - .equals(rhs.getAcl().getObjectIdentity())) { + if (!this.acl.getObjectIdentity().equals(rhs.getAcl().getObjectIdentity())) { return false; } } @@ -118,10 +122,8 @@ public class AccessControlEntryImpl implements AccessControlEntry, } } - if ((this.auditFailure != rhs.isAuditFailure()) - || (this.auditSuccess != rhs.isAuditSuccess()) - || (this.granting != rhs.isGranting()) - || !this.permission.equals(rhs.getPermission()) + if ((this.auditFailure != rhs.isAuditFailure()) || (this.auditSuccess != rhs.isAuditSuccess()) + || (this.granting != rhs.isGranting()) || !this.permission.equals(rhs.getPermission()) || !this.sid.equals(rhs.getSid())) { return false; } @@ -202,4 +204,5 @@ public class AccessControlEntryImpl implements AccessControlEntry, return sb.toString(); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategy.java b/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategy.java index 0ac6d86fd5..5c94ab46cc 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategy.java @@ -25,15 +25,19 @@ import org.springframework.security.acls.model.Acl; * @author Ben Alex */ public interface AclAuthorizationStrategy { + // ~ Static fields/initializers // ===================================================================================== int CHANGE_OWNERSHIP = 0; + int CHANGE_AUDITING = 1; + int CHANGE_GENERAL = 2; // ~ Methods // ======================================================================================================== void securityCheck(Acl acl, int changeType); + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategyImpl.java b/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategyImpl.java index 47693fc023..2ad9004121 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategyImpl.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/AclAuthorizationStrategyImpl.java @@ -45,12 +45,16 @@ import java.util.Set; * @author Ben Alex */ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy { + // ~ Instance fields // ================================================================================================ private final GrantedAuthority gaGeneralChanges; + private final GrantedAuthority gaModifyAuditing; + private final GrantedAuthority gaTakeOwnership; + private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); // ~ Constructors @@ -59,7 +63,6 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy { /** * Constructor. The only mandatory parameter relates to the system-wide * {@link GrantedAuthority} instances that can be held to always permit ACL changes. - * * @param auths the GrantedAuthoritys that have special permissions * (index 0 is the authority needed to change ownership, index 1 is the authority * needed to modify auditing details, index 2 is the authority needed to change other @@ -86,14 +89,11 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy { public void securityCheck(Acl acl, int changeType) { if ((SecurityContextHolder.getContext() == null) || (SecurityContextHolder.getContext().getAuthentication() == null) - || !SecurityContextHolder.getContext().getAuthentication() - .isAuthenticated()) { - throw new AccessDeniedException( - "Authenticated principal required to operate with ACLs"); + || !SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) { + throw new AccessDeniedException("Authenticated principal required to operate with ACLs"); } - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // Check if authorized by virtue of ACL ownership Sid currentUser = createCurrentUser(authentication); @@ -138,7 +138,6 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy { /** * Creates a principal-like sid from the authentication information. - * * @param authentication the authentication information that can provide principal and * thus the sid's id will be dependant on the value inside * @return a sid with the ID taken from the authentication information @@ -151,4 +150,5 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy { Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required"); this.sidRetrievalStrategy = sidRetrievalStrategy; } + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/AclFormattingUtils.java b/acl/src/main/java/org/springframework/security/acls/domain/AclFormattingUtils.java index c9809204ae..aedb5b8e5e 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/AclFormattingUtils.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/AclFormattingUtils.java @@ -70,9 +70,7 @@ public abstract class AclFormattingUtils { * bit being denoted by character '*'. *

* Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}. - * * @param i the integer bit mask to print the active bits for - * * @return a 32-character representation of the bit mask */ public static String printBinary(int i) { @@ -84,22 +82,17 @@ public abstract class AclFormattingUtils { * bit being denoted by the passed character. *

* Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}. - * * @param mask the integer bit mask to print the active bits for * @param code the character to print when an active bit is detected - * * @return a 32-character representation of the bit mask */ public static String printBinary(int mask, char code) { - Assert.doesNotContain(Character.toString(code), - Character.toString(Permission.RESERVED_ON), + Assert.doesNotContain(Character.toString(code), Character.toString(Permission.RESERVED_ON), () -> Permission.RESERVED_ON + " is a reserved character code"); - Assert.doesNotContain(Character.toString(code), - Character.toString(Permission.RESERVED_OFF), + Assert.doesNotContain(Character.toString(code), Character.toString(Permission.RESERVED_OFF), () -> Permission.RESERVED_OFF + " is a reserved character code"); - return printBinary(mask, Permission.RESERVED_ON, Permission.RESERVED_OFF) - .replace(Permission.RESERVED_ON, code); + return printBinary(mask, Permission.RESERVED_ON, Permission.RESERVED_OFF).replace(Permission.RESERVED_ON, code); } private static String printBinary(int i, char on, char off) { @@ -109,4 +102,5 @@ public abstract class AclFormattingUtils { return temp2.replace('0', off).replace('1', on); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/AclImpl.java b/acl/src/main/java/org/springframework/security/acls/domain/AclImpl.java index 472b33eaf4..c5860b233a 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/AclImpl.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/AclImpl.java @@ -38,18 +38,27 @@ import org.springframework.util.Assert; * @author Ben Alex */ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { + // ~ Instance fields // ================================================================================================ private Acl parentAcl; + private transient AclAuthorizationStrategy aclAuthorizationStrategy; + private transient PermissionGrantingStrategy permissionGrantingStrategy; + private final List aces = new ArrayList<>(); + private ObjectIdentity objectIdentity; + private Serializable id; + private Sid owner; // OwnershipAcl + private List loadedSids = null; // includes all SIDs the WHERE clause covered, // even if there was no ACE for a SID + private boolean entriesInheriting = true; // ~ Constructors @@ -59,14 +68,13 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { * Minimal constructor, which should be used * {@link org.springframework.security.acls.model.MutableAclService#createAcl(ObjectIdentity)} * . - * * @param objectIdentity the object identity this ACL relates to (required) * @param id the primary key assigned to this ACL (required) * @param aclAuthorizationStrategy authorization strategy (required) * @param auditLogger audit logger (required) */ - public AclImpl(ObjectIdentity objectIdentity, Serializable id, - AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) { + public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy, + AuditLogger auditLogger) { Assert.notNull(objectIdentity, "Object Identity required"); Assert.notNull(id, "Id required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); @@ -74,14 +82,12 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { this.objectIdentity = objectIdentity; this.id = id; this.aclAuthorizationStrategy = aclAuthorizationStrategy; - this.permissionGrantingStrategy = new DefaultPermissionGrantingStrategy( - auditLogger); + this.permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(auditLogger); } /** * Full constructor, which should be used by persistence tools that do not provide * field-level access features. - * * @param objectIdentity the object identity this ACL relates to * @param id the primary key assigned to this ACL * @param aclAuthorizationStrategy authorization strategy @@ -93,10 +99,9 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { * @param entriesInheriting if ACEs from the parent should inherit into this ACL * @param owner the owner (required) */ - public AclImpl(ObjectIdentity objectIdentity, Serializable id, - AclAuthorizationStrategy aclAuthorizationStrategy, - PermissionGrantingStrategy grantingStrategy, Acl parentAcl, - List loadedSids, boolean entriesInheriting, Sid owner) { + public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy, + PermissionGrantingStrategy grantingStrategy, Acl parentAcl, List loadedSids, boolean entriesInheriting, + Sid owner) { Assert.notNull(objectIdentity, "Object Identity required"); Assert.notNull(id, "Id required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); @@ -125,8 +130,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { @Override public void deleteAce(int aceIndex) throws NotFoundException { - aclAuthorizationStrategy.securityCheck(this, - AclAuthorizationStrategy.CHANGE_GENERAL); + aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); verifyAceIndexExists(aceIndex); synchronized (aces) { @@ -139,30 +143,26 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { throw new NotFoundException("aceIndex must be greater than or equal to zero"); } if (aceIndex >= this.aces.size()) { - throw new NotFoundException( - "aceIndex must refer to an index of the AccessControlEntry list. " - + "List size is " + aces.size() + ", index was " + aceIndex); + throw new NotFoundException("aceIndex must refer to an index of the AccessControlEntry list. " + + "List size is " + aces.size() + ", index was " + aceIndex); } } @Override - public void insertAce(int atIndexLocation, Permission permission, Sid sid, - boolean granting) throws NotFoundException { - aclAuthorizationStrategy.securityCheck(this, - AclAuthorizationStrategy.CHANGE_GENERAL); + public void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting) + throws NotFoundException { + aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); Assert.notNull(permission, "Permission required"); Assert.notNull(sid, "Sid required"); if (atIndexLocation < 0) { - throw new NotFoundException( - "atIndexLocation must be greater than or equal to zero"); + throw new NotFoundException("atIndexLocation must be greater than or equal to zero"); } if (atIndexLocation > this.aces.size()) { throw new NotFoundException( "atIndexLocation must be less than or equal to the size of the AccessControlEntry collection"); } - AccessControlEntryImpl ace = new AccessControlEntryImpl(null, this, sid, - permission, granting, false, false); + AccessControlEntryImpl ace = new AccessControlEntryImpl(null, this, sid, permission, granting, false, false); synchronized (aces) { this.aces.add(atIndexLocation, ace); @@ -193,14 +193,13 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { /** * Delegates to the {@link PermissionGrantingStrategy}. - * * @throws UnloadedSidException if the passed SIDs are unknown to this ACL because the * ACL was only loaded for a subset of SIDs * @see DefaultPermissionGrantingStrategy */ @Override - public boolean isGranted(List permission, List sids, - boolean administrativeMode) throws NotFoundException, UnloadedSidException { + public boolean isGranted(List permission, List sids, boolean administrativeMode) + throws NotFoundException, UnloadedSidException { Assert.notEmpty(permission, "Permissions required"); Assert.notEmpty(sids, "SIDs required"); @@ -208,8 +207,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { throw new UnloadedSidException("ACL was not loaded for one or more SID"); } - return permissionGrantingStrategy.isGranted(this, permission, sids, - administrativeMode); + return permissionGrantingStrategy.isGranted(this, permission, sids, administrativeMode); } @Override @@ -243,15 +241,13 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { @Override public void setEntriesInheriting(boolean entriesInheriting) { - aclAuthorizationStrategy.securityCheck(this, - AclAuthorizationStrategy.CHANGE_GENERAL); + aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); this.entriesInheriting = entriesInheriting; } @Override public void setOwner(Sid newOwner) { - aclAuthorizationStrategy.securityCheck(this, - AclAuthorizationStrategy.CHANGE_OWNERSHIP); + aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_OWNERSHIP); Assert.notNull(newOwner, "Owner required"); this.owner = newOwner; } @@ -263,10 +259,8 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { @Override public void setParent(Acl newParent) { - aclAuthorizationStrategy.securityCheck(this, - AclAuthorizationStrategy.CHANGE_GENERAL); - Assert.isTrue(newParent == null || !newParent.equals(this), - "Cannot be the parent of yourself"); + aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); + Assert.isTrue(newParent == null || !newParent.equals(this), "Cannot be the parent of yourself"); this.parentAcl = newParent; } @@ -277,8 +271,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { @Override public void updateAce(int aceIndex, Permission permission) throws NotFoundException { - aclAuthorizationStrategy.securityCheck(this, - AclAuthorizationStrategy.CHANGE_GENERAL); + aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL); verifyAceIndexExists(aceIndex); synchronized (aces) { @@ -289,8 +282,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { @Override public void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure) { - aclAuthorizationStrategy.securityCheck(this, - AclAuthorizationStrategy.CHANGE_AUDITING); + aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_AUDITING); verifyAceIndexExists(aceIndex); synchronized (aces) { @@ -306,26 +298,19 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { AclImpl rhs = (AclImpl) obj; if (this.aces.equals(rhs.aces)) { if ((this.parentAcl == null && rhs.parentAcl == null) - || (this.parentAcl != null && this.parentAcl - .equals(rhs.parentAcl))) { + || (this.parentAcl != null && this.parentAcl.equals(rhs.parentAcl))) { if ((this.objectIdentity == null && rhs.objectIdentity == null) - || (this.objectIdentity != null && this.objectIdentity - .equals(rhs.objectIdentity))) { - if ((this.id == null && rhs.id == null) - || (this.id != null && this.id.equals(rhs.id))) { + || (this.objectIdentity != null && this.objectIdentity.equals(rhs.objectIdentity))) { + if ((this.id == null && rhs.id == null) || (this.id != null && this.id.equals(rhs.id))) { if ((this.owner == null && rhs.owner == null) - || (this.owner != null && this.owner - .equals(rhs.owner))) { + || (this.owner != null && this.owner.equals(rhs.owner))) { if (this.entriesInheriting == rhs.entriesInheriting) { if ((this.loadedSids == null && rhs.loadedSids == null)) { return true; } - if (this.loadedSids != null - && (this.loadedSids.size() == rhs.loadedSids - .size())) { + if (this.loadedSids != null && (this.loadedSids.size() == rhs.loadedSids.size())) { for (int i = 0; i < this.loadedSids.size(); i++) { - if (!this.loadedSids.get(i).equals( - rhs.loadedSids.get(i))) { + if (!this.loadedSids.get(i).equals(rhs.loadedSids.get(i))) { return false; } } @@ -345,9 +330,8 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { public int hashCode() { int result = this.parentAcl != null ? this.parentAcl.hashCode() : 0; result = 31 * result + this.aclAuthorizationStrategy.hashCode(); - result = 31 * result + (this.permissionGrantingStrategy != null ? - this.permissionGrantingStrategy.hashCode() : - 0); + result = 31 * result + + (this.permissionGrantingStrategy != null ? this.permissionGrantingStrategy.hashCode() : 0); result = 31 * result + (this.aces != null ? this.aces.hashCode() : 0); result = 31 * result + this.objectIdentity.hashCode(); result = 31 * result + this.id.hashCode(); @@ -382,12 +366,9 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { } sb.append("inheriting: ").append(this.entriesInheriting).append("; "); - sb.append("parent: ").append( - (this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity() - .toString()); + sb.append("parent: ").append((this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity().toString()); sb.append("; "); - sb.append("aclAuthorizationStrategy: ").append(this.aclAuthorizationStrategy) - .append("; "); + sb.append("aclAuthorizationStrategy: ").append(this.aclAuthorizationStrategy).append("; "); sb.append("permissionGrantingStrategy: ").append(this.permissionGrantingStrategy); sb.append("]"); diff --git a/acl/src/main/java/org/springframework/security/acls/domain/AuditLogger.java b/acl/src/main/java/org/springframework/security/acls/domain/AuditLogger.java index ff5bb69733..4c08537e07 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/AuditLogger.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/AuditLogger.java @@ -24,8 +24,10 @@ import org.springframework.security.acls.model.AccessControlEntry; * */ public interface AuditLogger { + // ~ Methods // ======================================================================================================== void logIfNeeded(boolean granted, AccessControlEntry ace); + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/BasePermission.java b/acl/src/main/java/org/springframework/security/acls/domain/BasePermission.java index 02981215f8..c0bc3ce92b 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/BasePermission.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/BasePermission.java @@ -28,10 +28,15 @@ import org.springframework.security.acls.model.Permission; * @author Ben Alex */ public class BasePermission extends AbstractPermission { + public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1 + public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2 + public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4 + public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8 + public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16 protected BasePermission(int mask) { @@ -41,4 +46,5 @@ public class BasePermission extends AbstractPermission { protected BasePermission(int mask, char code) { super(mask, code); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/ConsoleAuditLogger.java b/acl/src/main/java/org/springframework/security/acls/domain/ConsoleAuditLogger.java index 1ceac22e15..f4eaaeb8da 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/ConsoleAuditLogger.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/ConsoleAuditLogger.java @@ -26,6 +26,7 @@ import org.springframework.util.Assert; * @author Ben Alex */ public class ConsoleAuditLogger implements AuditLogger { + // ~ Methods // ======================================================================================================== @@ -43,4 +44,5 @@ public class ConsoleAuditLogger implements AuditLogger { } } } + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/CumulativePermission.java b/acl/src/main/java/org/springframework/security/acls/domain/CumulativePermission.java index 49e2c55af4..c120868ea8 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/CumulativePermission.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/CumulativePermission.java @@ -37,8 +37,7 @@ public class CumulativePermission extends AbstractPermission { public CumulativePermission clear(Permission permission) { this.mask &= ~permission.getMask(); - this.pattern = AclFormattingUtils.demergePatterns(this.pattern, - permission.getPattern()); + this.pattern = AclFormattingUtils.demergePatterns(this.pattern, permission.getPattern()); return this; } @@ -52,8 +51,7 @@ public class CumulativePermission extends AbstractPermission { public CumulativePermission set(Permission permission) { this.mask |= permission.getMask(); - this.pattern = AclFormattingUtils.mergePatterns(this.pattern, - permission.getPattern()); + this.pattern = AclFormattingUtils.mergePatterns(this.pattern, permission.getPattern()); return this; } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionFactory.java b/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionFactory.java index 8061a916b5..a830067997 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionFactory.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionFactory.java @@ -38,7 +38,9 @@ import org.springframework.util.Assert; * @since 2.0.3 */ public class DefaultPermissionFactory implements PermissionFactory { + private final Map registeredPermissionsByInteger = new HashMap<>(); + private final Map registeredPermissionsByName = new HashMap<>(); /** @@ -57,7 +59,6 @@ public class DefaultPermissionFactory implements PermissionFactory { /** * Registers a map of named Permission instances. - * * @param namedPermissions the map of Permissions, keyed by name. */ public DefaultPermissionFactory(Map namedPermissions) { @@ -71,7 +72,6 @@ public class DefaultPermissionFactory implements PermissionFactory { *

* These permissions will be registered under the name of the field. See * {@link BasePermission} for an example. - * * @param clazz a {@link Permission} class with public static fields to register */ protected void registerPublicPermissions(Class clazz) { @@ -130,8 +130,8 @@ public class DefaultPermissionFactory implements PermissionFactory { Permission p = registeredPermissionsByInteger.get(permissionToCheck); if (p == null) { - throw new IllegalStateException("Mask '" + permissionToCheck - + "' does not have a corresponding static Permission"); + throw new IllegalStateException( + "Mask '" + permissionToCheck + "' does not have a corresponding static Permission"); } permission.set(p); } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionGrantingStrategy.java b/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionGrantingStrategy.java index 3f54678873..18027573d5 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionGrantingStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/DefaultPermissionGrantingStrategy.java @@ -61,20 +61,17 @@ public class DefaultPermissionGrantingStrategy implements PermissionGrantingStra * decide how to handle the permission check. Similarly, if any of the SID arguments * presented to the method were not loaded by the ACL, * UnloadedSidException will be thrown. - * * @param permission the exact permissions to scan for (order is important) * @param sids the exact SIDs to scan for (order is important) * @param administrativeMode if true denotes the query is for * administrative purposes and no auditing will be undertaken - * * @return true if one of the permissions has been granted, * false if one of the permissions has been specifically revoked - * * @throws NotFoundException if an exact ACE for one of the permission bit masks and * SID combination could not be found */ - public boolean isGranted(Acl acl, List permission, List sids, - boolean administrativeMode) throws NotFoundException { + public boolean isGranted(Acl acl, List permission, List sids, boolean administrativeMode) + throws NotFoundException { final List aces = acl.getEntries(); @@ -87,8 +84,7 @@ public class DefaultPermissionGrantingStrategy implements PermissionGrantingStra for (AccessControlEntry ace : aces) { - if (isGranted(ace, p) - && ace.getSid().equals(sid)) { + if (isGranted(ace, p) && ace.getSid().equals(sid)) { // Found a matching ACE, so its authorization decision will // prevail if (ace.isGranting()) { @@ -137,24 +133,21 @@ public class DefaultPermissionGrantingStrategy implements PermissionGrantingStra } else { // We either have no parent, or we're the uppermost parent - throw new NotFoundException( - "Unable to locate a matching ACE for passed permissions and SIDs"); + throw new NotFoundException("Unable to locate a matching ACE for passed permissions and SIDs"); } } /** - * Compares an ACE Permission to the given Permission. - * By default, we compare the Permission masks for exact match. - * Subclasses of this strategy can override this behavior and implement - * more sophisticated comparisons, e.g. a bitwise comparison for ACEs that grant access. - *

{@code
+	 * Compares an ACE Permission to the given Permission. By default, we compare the
+	 * Permission masks for exact match. Subclasses of this strategy can override this
+	 * behavior and implement more sophisticated comparisons, e.g. a bitwise comparison
+	 * for ACEs that grant access. 
{@code
 	 * if (ace.isGranting() && p.getMask() != 0) {
 	 *    return (ace.getPermission().getMask() & p.getMask()) != 0;
 	 * } else {
 	 *    return ace.getPermission().getMask() == p.getMask();
 	 * }
 	 * }
- * * @param ace the ACE from the Acl holding the mask. * @param p the Permission we are checking against. * @return true, if the respective masks are considered to be equal. diff --git a/acl/src/main/java/org/springframework/security/acls/domain/EhCacheBasedAclCache.java b/acl/src/main/java/org/springframework/security/acls/domain/EhCacheBasedAclCache.java index 6cf4658e35..2d5a3cb779 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/EhCacheBasedAclCache.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/EhCacheBasedAclCache.java @@ -38,18 +38,20 @@ import org.springframework.util.Assert; * @author Ben Alex */ public class EhCacheBasedAclCache implements AclCache { + // ~ Instance fields // ================================================================================================ private final Ehcache cache; + private PermissionGrantingStrategy permissionGrantingStrategy; + private AclAuthorizationStrategy aclAuthorizationStrategy; // ~ Constructors // =================================================================================================== - public EhCacheBasedAclCache(Ehcache cache, - PermissionGrantingStrategy permissionGrantingStrategy, + public EhCacheBasedAclCache(Ehcache cache, PermissionGrantingStrategy permissionGrantingStrategy, AclAuthorizationStrategy aclAuthorizationStrategy) { Assert.notNull(cache, "Cache required"); Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required"); @@ -144,10 +146,8 @@ public class EhCacheBasedAclCache implements AclCache { private MutableAcl initializeTransientFields(MutableAcl value) { if (value instanceof AclImpl) { - FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, - this.aclAuthorizationStrategy); - FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value, - this.permissionGrantingStrategy); + FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, this.aclAuthorizationStrategy); + FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value, this.permissionGrantingStrategy); } if (value.getParentAcl() != null) { @@ -159,4 +159,5 @@ public class EhCacheBasedAclCache implements AclCache { public void clearCache() { cache.removeAll(); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/GrantedAuthoritySid.java b/acl/src/main/java/org/springframework/security/acls/domain/GrantedAuthoritySid.java index c8bf8ad20a..16155f03ee 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/GrantedAuthoritySid.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/GrantedAuthoritySid.java @@ -31,6 +31,7 @@ import org.springframework.util.Assert; * @author Ben Alex */ public class GrantedAuthoritySid implements Sid { + // ~ Instance fields // ================================================================================================ @@ -46,8 +47,7 @@ public class GrantedAuthoritySid implements Sid { public GrantedAuthoritySid(GrantedAuthority grantedAuthority) { Assert.notNull(grantedAuthority, "GrantedAuthority required"); - Assert.notNull( - grantedAuthority.getAuthority(), + Assert.notNull(grantedAuthority.getAuthority(), "This Sid is only compatible with GrantedAuthoritys that provide a non-null getAuthority()"); this.grantedAuthority = grantedAuthority.getAuthority(); } @@ -63,8 +63,7 @@ public class GrantedAuthoritySid implements Sid { // Delegate to getGrantedAuthority() to perform actual comparison (both should be // identical) - return ((GrantedAuthoritySid) object).getGrantedAuthority().equals( - this.getGrantedAuthority()); + return ((GrantedAuthoritySid) object).getGrantedAuthority().equals(this.getGrantedAuthority()); } @Override @@ -80,4 +79,5 @@ public class GrantedAuthoritySid implements Sid { public String toString() { return "GrantedAuthoritySid[" + this.grantedAuthority + "]"; } + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/IdentityUnavailableException.java b/acl/src/main/java/org/springframework/security/acls/domain/IdentityUnavailableException.java index 5157646e1e..9b1f2dc933 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/IdentityUnavailableException.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/IdentityUnavailableException.java @@ -21,12 +21,12 @@ package org.springframework.security.acls.domain; * @author Ben Alex */ public class IdentityUnavailableException extends RuntimeException { + // ~ Constructors // =================================================================================================== /** * Constructs an IdentityUnavailableException with the specified message. - * * @param msg the detail message */ public IdentityUnavailableException(String msg) { @@ -36,11 +36,11 @@ public class IdentityUnavailableException extends RuntimeException { /** * Constructs an IdentityUnavailableException with the specified message * and root cause. - * * @param msg the detail message * @param t root cause */ public IdentityUnavailableException(String msg, Throwable t) { super(msg, t); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityImpl.java b/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityImpl.java index 484b43a3a6..249a8b37ce 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityImpl.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityImpl.java @@ -31,10 +31,12 @@ import org.springframework.util.ClassUtils; * @author Ben Alex */ public class ObjectIdentityImpl implements ObjectIdentity { + // ~ Instance fields // ================================================================================================ private final String type; + private Serializable identifier; // ~ Constructors @@ -66,9 +68,7 @@ public class ObjectIdentityImpl implements ObjectIdentity { *

* The class name of the object passed will be considered the {@link #type}, so if * more control is required, a different constructor should be used. - * * @param object the domain object instance to create an identity for. - * * @throws IdentityUnavailableException if identity could not be extracted */ public ObjectIdentityImpl(Object object) throws IdentityUnavailableException { @@ -84,13 +84,11 @@ public class ObjectIdentityImpl implements ObjectIdentity { result = method.invoke(object); } catch (Exception e) { - throw new IdentityUnavailableException( - "Could not extract identity from object " + object, e); + throw new IdentityUnavailableException("Could not extract identity from object " + object, e); } Assert.notNull(result, "getId() is required to return a non-null value"); - Assert.isInstanceOf(Serializable.class, result, - "Getter must provide a return value of type Serializable"); + Assert.isInstanceOf(Serializable.class, result, "Getter must provide a return value of type Serializable"); this.identifier = (Serializable) result; } @@ -105,9 +103,7 @@ public class ObjectIdentityImpl implements ObjectIdentity { *

* Numeric identities (Integer and Long values) are considered equal if they are * numerically equal. Other serializable types are evaluated using a simple equality. - * * @param arg0 object to compare - * * @return true if the presented object matches this object */ @Override @@ -120,8 +116,7 @@ public class ObjectIdentityImpl implements ObjectIdentity { if (identifier instanceof Number && other.identifier instanceof Number) { // Integers and Longs with same value should be considered equal - if (((Number) identifier).longValue() != ((Number) other.identifier) - .longValue()) { + if (((Number) identifier).longValue() != ((Number) other.identifier).longValue()) { return false; } } @@ -147,7 +142,6 @@ public class ObjectIdentityImpl implements ObjectIdentity { /** * Important so caching operates properly. - * * @return the hash */ @Override @@ -166,4 +160,5 @@ public class ObjectIdentityImpl implements ObjectIdentity { return sb.toString(); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImpl.java b/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImpl.java index 2fe0538c80..a789719b94 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImpl.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImpl.java @@ -29,8 +29,8 @@ import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy; * * @author Ben Alex */ -public class ObjectIdentityRetrievalStrategyImpl implements - ObjectIdentityRetrievalStrategy, ObjectIdentityGenerator { +public class ObjectIdentityRetrievalStrategyImpl implements ObjectIdentityRetrievalStrategy, ObjectIdentityGenerator { + // ~ Methods // ======================================================================================================== @@ -41,4 +41,5 @@ public class ObjectIdentityRetrievalStrategyImpl implements public ObjectIdentity createObjectIdentity(Serializable id, String type) { return new ObjectIdentityImpl(type, id); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/PermissionFactory.java b/acl/src/main/java/org/springframework/security/acls/domain/PermissionFactory.java index 5d99deb201..cad03adcd9 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/PermissionFactory.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/PermissionFactory.java @@ -32,9 +32,7 @@ public interface PermissionFactory { /** * Dynamically creates a CumulativePermission or * BasePermission representing the active bits in the passed mask. - * * @param mask to build - * * @return a Permission representing the requested object */ Permission buildFromMask(int mask); @@ -42,4 +40,5 @@ public interface PermissionFactory { Permission buildFromName(String name); List buildFromNames(List names); + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/PrincipalSid.java b/acl/src/main/java/org/springframework/security/acls/domain/PrincipalSid.java index 2680b669c0..5f89653a1d 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/PrincipalSid.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/PrincipalSid.java @@ -31,6 +31,7 @@ import org.springframework.util.Assert; * @author Ben Alex */ public class PrincipalSid implements Sid { + // ~ Instance fields // ================================================================================================ @@ -78,4 +79,5 @@ public class PrincipalSid implements Sid { public String toString() { return "PrincipalSid[" + this.principal + "]"; } + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/SidRetrievalStrategyImpl.java b/acl/src/main/java/org/springframework/security/acls/domain/SidRetrievalStrategyImpl.java index 2cf19291e6..d5611c505b 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/SidRetrievalStrategyImpl.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/SidRetrievalStrategyImpl.java @@ -67,4 +67,5 @@ public class SidRetrievalStrategyImpl implements SidRetrievalStrategy { return sids; } + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/SpringCacheBasedAclCache.java b/acl/src/main/java/org/springframework/security/acls/domain/SpringCacheBasedAclCache.java index 67410e9643..d14c3c85f5 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/SpringCacheBasedAclCache.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/SpringCacheBasedAclCache.java @@ -39,18 +39,20 @@ import java.io.Serializable; * @since 3.2 */ public class SpringCacheBasedAclCache implements AclCache { + // ~ Instance fields // ================================================================================================ private final Cache cache; + private PermissionGrantingStrategy permissionGrantingStrategy; + private AclAuthorizationStrategy aclAuthorizationStrategy; // ~ Constructors // =================================================================================================== - public SpringCacheBasedAclCache(Cache cache, - PermissionGrantingStrategy permissionGrantingStrategy, + public SpringCacheBasedAclCache(Cache cache, PermissionGrantingStrategy permissionGrantingStrategy, AclAuthorizationStrategy aclAuthorizationStrategy) { Assert.notNull(cache, "Cache required"); Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required"); @@ -120,10 +122,8 @@ public class SpringCacheBasedAclCache implements AclCache { private MutableAcl initializeTransientFields(MutableAcl value) { if (value instanceof AclImpl) { - FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, - this.aclAuthorizationStrategy); - FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value, - this.permissionGrantingStrategy); + FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, this.aclAuthorizationStrategy); + FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value, this.permissionGrantingStrategy); } if (value.getParentAcl() != null) { @@ -135,4 +135,5 @@ public class SpringCacheBasedAclCache implements AclCache { public void clearCache() { cache.clear(); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/domain/package-info.java b/acl/src/main/java/org/springframework/security/acls/domain/package-info.java index ff0f6f62b7..8af64c8a7d 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/package-info.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/package-info.java @@ -17,4 +17,3 @@ * Basic implementation of access control lists (ACLs) interfaces. */ package org.springframework.security.acls.domain; - diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/AclClassIdUtils.java b/acl/src/main/java/org/springframework/security/acls/jdbc/AclClassIdUtils.java index 65b5d80f54..27b132d1ad 100644 --- a/acl/src/main/java/org/springframework/security/acls/jdbc/AclClassIdUtils.java +++ b/acl/src/main/java/org/springframework/security/acls/jdbc/AclClassIdUtils.java @@ -31,12 +31,16 @@ import org.springframework.security.acls.model.ObjectIdentity; import org.springframework.util.Assert; /** - * Utility class for helping convert database representations of {@link ObjectIdentity#getIdentifier()} into - * the correct Java type as specified by acl_class.class_id_type. + * Utility class for helping convert database representations of + * {@link ObjectIdentity#getIdentifier()} into the correct Java type as specified by + * acl_class.class_id_type. + * * @author paulwheeler */ class AclClassIdUtils { + private static final String DEFAULT_CLASS_ID_TYPE_COLUMN_NAME = "class_id_type"; + private static final Log log = LogFactory.getLog(AclClassIdUtils.class); private ConversionService conversionService; @@ -54,19 +58,20 @@ class AclClassIdUtils { } /** - * Converts the raw type from the database into the right Java type. For most applications the 'raw type' will be Long, for some applications - * it could be String. + * Converts the raw type from the database into the right Java type. For most + * applications the 'raw type' will be Long, for some applications it could be String. * @param identifier The identifier from the database - * @param resultSet Result set of the query + * @param resultSet Result set of the query * @return The identifier in the appropriate target Java type. Typically Long or UUID. * @throws SQLException */ Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException { if (isString(identifier) && hasValidClassIdType(resultSet) - && canConvertFromStringTo(classIdTypeFrom(resultSet))) { + && canConvertFromStringTo(classIdTypeFrom(resultSet))) { identifier = convertFromStringTo((String) identifier, classIdTypeFrom(resultSet)); - } else { + } + else { // Assume it should be a Long type identifier = convertToLong(identifier); } @@ -78,13 +83,14 @@ class AclClassIdUtils { boolean hasClassIdType = false; try { hasClassIdType = classIdTypeFrom(resultSet) != null; - } catch (SQLException e) { + } + catch (SQLException e) { log.debug("Unable to obtain the class id type", e); } return hasClassIdType; } - private Class classIdTypeFrom(ResultSet resultSet) throws SQLException { + private Class classIdTypeFrom(ResultSet resultSet) throws SQLException { return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME)); } @@ -93,7 +99,8 @@ class AclClassIdUtils { if (className != null) { try { targetType = Class.forName(className); - } catch (ClassNotFoundException e) { + } + catch (ClassNotFoundException e) { log.debug("Unable to find class id type on classpath", e); } } @@ -109,18 +116,21 @@ class AclClassIdUtils { } /** - * Converts to a {@link Long}, attempting to use the {@link ConversionService} if available. - * @param identifier The identifier + * Converts to a {@link Long}, attempting to use the {@link ConversionService} if + * available. + * @param identifier The identifier * @return Long version of the identifier * @throws NumberFormatException if the string cannot be parsed to a long. - * @throws org.springframework.core.convert.ConversionException if a conversion exception occurred + * @throws org.springframework.core.convert.ConversionException if a conversion + * exception occurred * @throws IllegalArgumentException if targetType is null */ private Long convertToLong(Serializable identifier) { Long idAsLong; if (conversionService.canConvert(identifier.getClass(), Long.class)) { idAsLong = conversionService.convert(identifier, Long.class); - } else { + } + else { idAsLong = Long.valueOf(identifier.toString()); } return idAsLong; @@ -136,6 +146,7 @@ class AclClassIdUtils { } private static class StringToLongConverter implements Converter { + @Override public Long convert(String identifierAsString) { if (identifierAsString == null) { @@ -145,9 +156,11 @@ class AclClassIdUtils { } return Long.parseLong(identifierAsString); } + } private static class StringToUUIDConverter implements Converter { + @Override public UUID convert(String identifierAsString) { if (identifierAsString == null) { @@ -157,5 +170,7 @@ class AclClassIdUtils { } return UUID.fromString(identifierAsString); } + } + } diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java b/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java index ebd32632a7..6cad36f01a 100644 --- a/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java @@ -68,9 +68,9 @@ import org.springframework.util.Assert; * as it is likely to change in future releases and therefore subclassing is unsupported. *

* There are two SQL queries executed, one in the lookupPrimaryKeys method and - * one in lookupObjectIdentities. These are built from the same select and - * "order by" clause, using a different where clause in each case. In order to use custom - * schema or column names, each of these SQL clauses can be customized, but they must be + * one in lookupObjectIdentities. These are built from the same select and "order + * by" clause, using a different where clause in each case. In order to use custom schema + * or column names, each of these SQL clauses can be customized, but they must be * consistent with each other and with the expected result set generated by the the * default values. * @@ -79,21 +79,14 @@ import org.springframework.util.Assert; public class BasicLookupStrategy implements LookupStrategy { private final static String DEFAULT_SELECT_CLAUSE_COLUMNS = "select acl_object_identity.object_id_identity, " - + "acl_entry.ace_order, " - + "acl_object_identity.id as acl_id, " - + "acl_object_identity.parent_object, " - + "acl_object_identity.entries_inheriting, " - + "acl_entry.id as ace_id, " - + "acl_entry.mask, " - + "acl_entry.granting, " - + "acl_entry.audit_success, " - + "acl_entry.audit_failure, " - + "acl_sid.principal as ace_principal, " - + "acl_sid.sid as ace_sid, " - + "acli_sid.principal as acl_principal, " - + "acli_sid.sid as acl_sid, " - + "acl_class.class "; + + "acl_entry.ace_order, " + "acl_object_identity.id as acl_id, " + "acl_object_identity.parent_object, " + + "acl_object_identity.entries_inheriting, " + "acl_entry.id as ace_id, " + "acl_entry.mask, " + + "acl_entry.granting, " + "acl_entry.audit_success, " + "acl_entry.audit_failure, " + + "acl_sid.principal as ace_principal, " + "acl_sid.sid as ace_sid, " + + "acli_sid.principal as acl_principal, " + "acli_sid.sid as acl_sid, " + "acl_class.class "; + private final static String DEFAULT_SELECT_CLAUSE_ACL_CLASS_ID_TYPE_COLUMN = ", acl_class.class_id_type "; + private final static String DEFAULT_SELECT_CLAUSE_FROM = "from acl_object_identity " + "left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid " + "left join acl_class on acl_class.id = acl_object_identity.object_id_class " @@ -102,8 +95,8 @@ public class BasicLookupStrategy implements LookupStrategy { public final static String DEFAULT_SELECT_CLAUSE = DEFAULT_SELECT_CLAUSE_COLUMNS + DEFAULT_SELECT_CLAUSE_FROM; - public final static String DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE = DEFAULT_SELECT_CLAUSE_COLUMNS + - DEFAULT_SELECT_CLAUSE_ACL_CLASS_ID_TYPE_COLUMN + DEFAULT_SELECT_CLAUSE_FROM; + public final static String DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE = DEFAULT_SELECT_CLAUSE_COLUMNS + + DEFAULT_SELECT_CLAUSE_ACL_CLASS_ID_TYPE_COLUMN + DEFAULT_SELECT_CLAUSE_FROM; private final static String DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE = "(acl_object_identity.id = ?)"; @@ -116,20 +109,28 @@ public class BasicLookupStrategy implements LookupStrategy { // ================================================================================================ private final AclAuthorizationStrategy aclAuthorizationStrategy; + private PermissionFactory permissionFactory = new DefaultPermissionFactory(); + private final AclCache aclCache; + private final PermissionGrantingStrategy grantingStrategy; + private final JdbcTemplate jdbcTemplate; + private int batchSize = 50; private final Field fieldAces = FieldUtils.getField(AclImpl.class, "aces"); - private final Field fieldAcl = FieldUtils.getField(AccessControlEntryImpl.class, - "acl"); + + private final Field fieldAcl = FieldUtils.getField(AccessControlEntryImpl.class, "acl"); // SQL Customization fields private String selectClause = DEFAULT_SELECT_CLAUSE; + private String lookupPrimaryKeysWhereClause = DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE; + private String lookupObjectIdentitiesWhereClause = DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE; + private String orderByClause = DEFAULT_ORDER_BY_CLAUSE; private AclClassIdUtils aclClassIdUtils; @@ -139,28 +140,24 @@ public class BasicLookupStrategy implements LookupStrategy { /** * Constructor accepting mandatory arguments - * * @param dataSource to access the database * @param aclCache the cache where fully-loaded elements can be stored * @param aclAuthorizationStrategy authorization strategy (required) */ public BasicLookupStrategy(DataSource dataSource, AclCache aclCache, AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) { - this(dataSource, aclCache, aclAuthorizationStrategy, - new DefaultPermissionGrantingStrategy(auditLogger)); + this(dataSource, aclCache, aclAuthorizationStrategy, new DefaultPermissionGrantingStrategy(auditLogger)); } /** * Creates a new instance - * * @param dataSource to access the database * @param aclCache the cache where fully-loaded elements can be stored * @param aclAuthorizationStrategy authorization strategy (required) * @param grantingStrategy the PermissionGrantingStrategy */ public BasicLookupStrategy(DataSource dataSource, AclCache aclCache, - AclAuthorizationStrategy aclAuthorizationStrategy, - PermissionGrantingStrategy grantingStrategy) { + AclAuthorizationStrategy aclAuthorizationStrategy, PermissionGrantingStrategy grantingStrategy) { Assert.notNull(dataSource, "DataSource required"); Assert.notNull(aclCache, "AclCache required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); @@ -184,8 +181,8 @@ public class BasicLookupStrategy implements LookupStrategy { final String endSql = orderByClause; - StringBuilder sqlStringBldr = new StringBuilder(startSql.length() - + endSql.length() + requiredRepetitions * (repeatingSql.length() + 4)); + StringBuilder sqlStringBldr = new StringBuilder( + startSql.length() + endSql.length() + requiredRepetitions * (repeatingSql.length() + 4)); sqlStringBldr.append(startSql); for (int i = 1; i <= requiredRepetitions; i++) { @@ -216,8 +213,7 @@ public class BasicLookupStrategy implements LookupStrategy { fieldAcl.set(ace, acl); } catch (IllegalAccessException e) { - throw new IllegalStateException( - "Could not or set AclImpl on AccessControlEntryImpl fields", e); + throw new IllegalStateException("Could not or set AclImpl on AccessControlEntryImpl fields", e); } } @@ -233,27 +229,24 @@ public class BasicLookupStrategy implements LookupStrategy { /** * Locates the primary key IDs specified in "findNow", adding AclImpl instances with * StubAclParents to the "acls" Map. - * * @param acls the AclImpls (with StubAclParents) * @param findNow Long-based primary keys to retrieve * @param sids */ - private void lookupPrimaryKeys(final Map acls, - final Set findNow, final List sids) { + private void lookupPrimaryKeys(final Map acls, final Set findNow, final List sids) { Assert.notNull(acls, "ACLs are required"); Assert.notEmpty(findNow, "Items to find now required"); String sql = computeRepeatingSql(lookupPrimaryKeysWhereClause, findNow.size()); - Set parentsToLookup = jdbcTemplate.query(sql, - ps -> { - int i = 0; + Set parentsToLookup = jdbcTemplate.query(sql, ps -> { + int i = 0; - for (Long toFind : findNow) { - i++; - ps.setLong(i, toFind); - } - }, new ProcessResultSet(acls, sids)); + for (Long toFind : findNow) { + i++; + ps.setLong(i, toFind); + } + }, new ProcessResultSet(acls, sids)); // Lookup the parents, now that our JdbcTemplate has released the database // connection (SEC-547) @@ -271,28 +264,25 @@ public class BasicLookupStrategy implements LookupStrategy { * develop a custom {@link LookupStrategy} implementation instead. *

* The implementation works in batch sizes specified by {@link #batchSize}. - * * @param objects the identities to lookup (required) * @param sids the SIDs for which identities are required (ignored by this * implementation) - * * @return a Map where keys represent the {@link ObjectIdentity} of the * located {@link Acl} and values are the located {@link Acl} (never null * although some entries may be missing; this method should not throw * {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used to * automatically create entries if required) */ - public final Map readAclsById(List objects, - List sids) { + public final Map readAclsById(List objects, List sids) { Assert.isTrue(batchSize >= 1, "BatchSize must be >= 1"); Assert.notEmpty(objects, "Objects to lookup required"); // Map Map result = new HashMap<>(); // contains - // FULLY - // loaded - // Acl - // objects + // FULLY + // loaded + // Acl + // objects Set currentBatchToLoad = new HashSet<>(); @@ -330,11 +320,9 @@ public class BasicLookupStrategy implements LookupStrategy { } // Is it time to load from JDBC the currentBatchToLoad? - if ((currentBatchToLoad.size() == this.batchSize) - || ((i + 1) == objects.size())) { + if ((currentBatchToLoad.size() == this.batchSize) || ((i + 1) == objects.size())) { if (currentBatchToLoad.size() > 0) { - Map loadedBatch = lookupObjectIdentities( - currentBatchToLoad, sids); + Map loadedBatch = lookupObjectIdentities(currentBatchToLoad, sids); // Add loaded batch (all elements 100% initialized) to results result.putAll(loadedBatch); @@ -364,37 +352,35 @@ public class BasicLookupStrategy implements LookupStrategy { * properly-configured parent ACLs. * */ - private Map lookupObjectIdentities( - final Collection objectIdentities, List sids) { + private Map lookupObjectIdentities(final Collection objectIdentities, + List sids) { Assert.notEmpty(objectIdentities, "Must provide identities to lookup"); final Map acls = new HashMap<>(); // contains - // Acls - // with - // StubAclParents + // Acls + // with + // StubAclParents // Make the "acls" map contain all requested objectIdentities // (including markers to each parent in the hierarchy) - String sql = computeRepeatingSql(lookupObjectIdentitiesWhereClause, - objectIdentities.size()); + String sql = computeRepeatingSql(lookupObjectIdentitiesWhereClause, objectIdentities.size()); - Set parentsToLookup = jdbcTemplate.query(sql, - ps -> { - int i = 0; - for (ObjectIdentity oid : objectIdentities) { - // Determine prepared statement values for this iteration - String type = oid.getType(); + Set parentsToLookup = jdbcTemplate.query(sql, ps -> { + int i = 0; + for (ObjectIdentity oid : objectIdentities) { + // Determine prepared statement values for this iteration + String type = oid.getType(); - // No need to check for nulls, as guaranteed non-null by - // ObjectIdentity.getIdentifier() interface contract - String identifier = oid.getIdentifier().toString(); + // No need to check for nulls, as guaranteed non-null by + // ObjectIdentity.getIdentifier() interface contract + String identifier = oid.getIdentifier().toString(); - // Inject values - ps.setString((2 * i) + 1, identifier); - ps.setString((2 * i) + 2, type); - i++; - } - }, new ProcessResultSet(acls, sids)); + // Inject values + ps.setString((2 * i) + 1, identifier); + ps.setString((2 * i) + 2, type); + i++; + } + }, new ProcessResultSet(acls, sids)); // Lookup the parents, now that our JdbcTemplate has released the database // connection (SEC-547) @@ -406,10 +392,8 @@ public class BasicLookupStrategy implements LookupStrategy { Map resultMap = new HashMap<>(); for (Acl inputAcl : acls.values()) { - Assert.isInstanceOf(AclImpl.class, inputAcl, - "Map should have contained an AclImpl"); - Assert.isInstanceOf(Long.class, ((AclImpl) inputAcl).getId(), - "Acl.getId() must be Long"); + Assert.isInstanceOf(AclImpl.class, inputAcl, "Map should have contained an AclImpl"); + Assert.isInstanceOf(Long.class, ((AclImpl) inputAcl).getId(), "Acl.getId() must be Long"); Acl result = convert(acls, (Long) ((AclImpl) inputAcl).getId()); resultMap.put(result.getObjectIdentity(), result); @@ -422,7 +406,6 @@ public class BasicLookupStrategy implements LookupStrategy { * The final phase of converting the Map of AclImpl * instances which contain StubAclParents into proper, valid * AclImpls with correct ACL parents. - * * @param inputMap the unconverted AclImpls * @param currentIdentity the currentAcl that we wish to convert (this * may be @@ -434,8 +417,7 @@ public class BasicLookupStrategy implements LookupStrategy { // Retrieve this Acl from the InputMap Acl uncastAcl = inputMap.get(currentIdentity); - Assert.isInstanceOf(AclImpl.class, uncastAcl, - "The inputMap contained a non-AclImpl"); + Assert.isInstanceOf(AclImpl.class, uncastAcl, "The inputMap contained a non-AclImpl"); AclImpl inputAcl = (AclImpl) uncastAcl; @@ -448,9 +430,8 @@ public class BasicLookupStrategy implements LookupStrategy { } // Now we have the parent (if there is one), create the true AclImpl - AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), - inputAcl.getId(), aclAuthorizationStrategy, grantingStrategy, - parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner()); + AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), inputAcl.getId(), aclAuthorizationStrategy, + grantingStrategy, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner()); // Copy the "aces" from the input to the destination @@ -477,7 +458,6 @@ public class BasicLookupStrategy implements LookupStrategy { /** * Creates a particular implementation of {@link Sid} depending on the arguments. - * * @param sid the name of the sid representing its unique identifier. In typical ACL * database schema it's located in table {@code acl_sid} table, {@code sid} column. * @param isPrincipal whether it's a user or granted authority like role @@ -496,7 +476,6 @@ public class BasicLookupStrategy implements LookupStrategy { * Sets the {@code PermissionFactory} instance which will be used to convert loaded * permission data values to {@code Permission}s. A {@code DefaultPermissionFactory} * will be used by default. - * * @param permissionFactory */ public final void setPermissionFactory(PermissionFactory permissionFactory) { @@ -510,7 +489,6 @@ public class BasicLookupStrategy implements LookupStrategy { /** * The SQL for the select clause. If customizing in order to modify column names, * schema etc, the other SQL customization fields must also be set to match. - * * @param selectClause the select clause, which defaults to * {@link #DEFAULT_SELECT_CLAUSE}. */ @@ -528,8 +506,7 @@ public class BasicLookupStrategy implements LookupStrategy { /** * The SQL for the where clause used in the lookupObjectIdentities method. */ - public final void setLookupObjectIdentitiesWhereClause( - String lookupObjectIdentitiesWhereClause) { + public final void setLookupObjectIdentitiesWhereClause(String lookupObjectIdentitiesWhereClause) { this.lookupObjectIdentitiesWhereClause = lookupObjectIdentitiesWhereClause; } @@ -542,8 +519,9 @@ public class BasicLookupStrategy implements LookupStrategy { public final void setAclClassIdSupported(boolean aclClassIdSupported) { if (aclClassIdSupported) { - Assert.isTrue(this.selectClause.equals(DEFAULT_SELECT_CLAUSE), "Cannot set aclClassIdSupported and override the select clause; " - + "just override the select clause"); + Assert.isTrue(this.selectClause.equals(DEFAULT_SELECT_CLAUSE), + "Cannot set aclClassIdSupported and override the select clause; " + + "just override the select clause"); this.selectClause = DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE; } } @@ -556,7 +534,9 @@ public class BasicLookupStrategy implements LookupStrategy { // ================================================================================================== private class ProcessResultSet implements ResultSetExtractor> { + private final Map acls; + private final List sids; ProcessResultSet(Map acls, List sids) { @@ -612,15 +592,12 @@ public class BasicLookupStrategy implements LookupStrategy { /** * Accepts the current ResultSet row, and converts it into an * AclImpl that contains a StubAclParent - * * @param acls the Map we should add the converted Acl to * @param rs the ResultSet focused on a current row - * * @throws SQLException if something goes wrong converting values * @throws ConversionException if can't convert to the desired Java type */ - private void convertCurrentResultIntoObject(Map acls, - ResultSet rs) throws SQLException { + private void convertCurrentResultIntoObject(Map acls, ResultSet rs) throws SQLException { Long id = rs.getLong("acl_id"); // If we already have an ACL for this ID, just create the ACE @@ -629,11 +606,11 @@ public class BasicLookupStrategy implements LookupStrategy { if (acl == null) { // Make an AclImpl and pop it into the Map - // If the Java type is a String, check to see if we can convert it to the target id type, e.g. UUID. + // If the Java type is a String, check to see if we can convert it to the + // target id type, e.g. UUID. Serializable identifier = (Serializable) rs.getObject("object_id_identity"); identifier = aclClassIdUtils.identifierFrom(identifier, rs); - ObjectIdentity objectIdentity = new ObjectIdentityImpl( - rs.getString("class"), identifier); + ObjectIdentity objectIdentity = new ObjectIdentityImpl(rs.getString("class"), identifier); Acl parentAcl = null; long parentAclId = rs.getLong("parent_object"); @@ -643,11 +620,10 @@ public class BasicLookupStrategy implements LookupStrategy { } boolean entriesInheriting = rs.getBoolean("entries_inheriting"); - Sid owner = createSid(rs.getBoolean("acl_principal"), - rs.getString("acl_sid")); + Sid owner = createSid(rs.getBoolean("acl_principal"), rs.getString("acl_sid")); - acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, - grantingStrategy, parentAcl, null, entriesInheriting, owner); + acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, grantingStrategy, parentAcl, null, + entriesInheriting, owner); acls.put(id, acl); } @@ -657,8 +633,7 @@ public class BasicLookupStrategy implements LookupStrategy { // ACE_SID) if (rs.getString("ace_sid") != null) { Long aceId = rs.getLong("ace_id"); - Sid recipient = createSid(rs.getBoolean("ace_principal"), - rs.getString("ace_sid")); + Sid recipient = createSid(rs.getBoolean("ace_principal"), rs.getString("ace_sid")); int mask = rs.getInt("mask"); Permission permission = permissionFactory.buildFromMask(mask); @@ -666,8 +641,8 @@ public class BasicLookupStrategy implements LookupStrategy { boolean auditSuccess = rs.getBoolean("audit_success"); boolean auditFailure = rs.getBoolean("audit_failure"); - AccessControlEntryImpl ace = new AccessControlEntryImpl(aceId, acl, - recipient, permission, granting, auditSuccess, auditFailure); + AccessControlEntryImpl ace = new AccessControlEntryImpl(aceId, acl, recipient, permission, granting, + auditSuccess, auditFailure); // Field acesField = FieldUtils.getField(AclImpl.class, "aces"); List aces = readAces((AclImpl) acl); @@ -678,9 +653,11 @@ public class BasicLookupStrategy implements LookupStrategy { } } } + } private static class StubAclParent implements Acl { + private final Long id; StubAclParent(Long id) { @@ -711,14 +688,15 @@ public class BasicLookupStrategy implements LookupStrategy { throw new UnsupportedOperationException("Stub only"); } - public boolean isGranted(List permission, List sids, - boolean administrativeMode) throws NotFoundException, - UnloadedSidException { + public boolean isGranted(List permission, List sids, boolean administrativeMode) + throws NotFoundException, UnloadedSidException { throw new UnsupportedOperationException("Stub only"); } public boolean isSidLoaded(List sids) { throw new UnsupportedOperationException("Stub only"); } + } + } diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java index f2cb89f909..2286bac911 100644 --- a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java +++ b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java @@ -45,18 +45,26 @@ import org.springframework.util.Assert; * @author Ben Alex */ public class JdbcAclService implements AclService { + // ~ Static fields/initializers // ===================================================================================== protected static final Log log = LogFactory.getLog(JdbcAclService.class); + private static final String DEFAULT_SELECT_ACL_CLASS_COLUMNS = "class.class as class"; - private static final String DEFAULT_SELECT_ACL_CLASS_COLUMNS_WITH_ID_TYPE = DEFAULT_SELECT_ACL_CLASS_COLUMNS + ", class.class_id_type as class_id_type"; - private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL = "select obj.object_id_identity as obj_id, " + DEFAULT_SELECT_ACL_CLASS_COLUMNS + + private static final String DEFAULT_SELECT_ACL_CLASS_COLUMNS_WITH_ID_TYPE = DEFAULT_SELECT_ACL_CLASS_COLUMNS + + ", class.class_id_type as class_id_type"; + + private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL = "select obj.object_id_identity as obj_id, " + + DEFAULT_SELECT_ACL_CLASS_COLUMNS + " from acl_object_identity obj, acl_object_identity parent, acl_class class " + "where obj.parent_object = parent.id and obj.object_id_class = class.id " + "and parent.object_id_identity = ? and parent.object_id_class = (" + "select id FROM acl_class where acl_class.class = ?)"; - private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE = "select obj.object_id_identity as obj_id, " + DEFAULT_SELECT_ACL_CLASS_COLUMNS_WITH_ID_TYPE + + private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE = "select obj.object_id_identity as obj_id, " + + DEFAULT_SELECT_ACL_CLASS_COLUMNS_WITH_ID_TYPE + " from acl_object_identity obj, acl_object_identity parent, acl_class class " + "where obj.parent_object = parent.id and obj.object_id_class = class.id " + "and parent.object_id_identity = ? and parent.object_id_class = (" @@ -66,9 +74,13 @@ public class JdbcAclService implements AclService { // ================================================================================================ protected final JdbcOperations jdbcOperations; + private final LookupStrategy lookupStrategy; + private boolean aclClassIdSupported; + private String findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL; + private AclClassIdUtils aclClassIdUtils; // ~ Constructors @@ -91,13 +103,12 @@ public class JdbcAclService implements AclService { public List findChildren(ObjectIdentity parentIdentity) { Object[] args = { parentIdentity.getIdentifier().toString(), parentIdentity.getType() }; - List objects = jdbcOperations.query(findChildrenSql, args, - (rs, rowNum) -> { - String javaType = rs.getString("class"); - Serializable identifier = (Serializable) rs.getObject("obj_id"); - identifier = aclClassIdUtils.identifierFrom(identifier, rs); - return new ObjectIdentityImpl(javaType, identifier); - }); + List objects = jdbcOperations.query(findChildrenSql, args, (rs, rowNum) -> { + String javaType = rs.getString("class"); + Serializable identifier = (Serializable) rs.getObject("obj_id"); + identifier = aclClassIdUtils.identifierFrom(identifier, rs); + return new ObjectIdentityImpl(javaType, identifier); + }); if (objects.isEmpty()) { return null; @@ -106,8 +117,7 @@ public class JdbcAclService implements AclService { return objects; } - public Acl readAclById(ObjectIdentity object, List sids) - throws NotFoundException { + public Acl readAclById(ObjectIdentity object, List sids) throws NotFoundException { Map map = readAclsById(Collections.singletonList(object), sids); Assert.isTrue(map.containsKey(object), () -> "There should have been an Acl entry for ObjectIdentity " + object); @@ -119,22 +129,19 @@ public class JdbcAclService implements AclService { return readAclById(object, null); } - public Map readAclsById(List objects) - throws NotFoundException { + public Map readAclsById(List objects) throws NotFoundException { return readAclsById(objects, null); } - public Map readAclsById(List objects, - List sids) throws NotFoundException { + public Map readAclsById(List objects, List sids) + throws NotFoundException { Map result = lookupStrategy.readAclsById(objects, sids); // Check every requested object identity was found (throw NotFoundException if // needed) for (ObjectIdentity oid : objects) { if (!result.containsKey(oid)) { - throw new NotFoundException( - "Unable to find ACL information for object identity '" + oid - + "'"); + throw new NotFoundException("Unable to find ACL information for object identity '" + oid + "'"); } } @@ -143,7 +150,6 @@ public class JdbcAclService implements AclService { /** * Allows customization of the SQL query used to find child object identities. - * * @param findChildrenSql */ public void setFindChildrenQuery(String findChildrenSql) { @@ -156,7 +162,8 @@ public class JdbcAclService implements AclService { // Change the default children select if it hasn't been overridden if (this.findChildrenSql.equals(DEFAULT_SELECT_ACL_WITH_PARENT_SQL)) { this.findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE; - } else { + } + else { log.debug("Find children statement has already been overridden, so not overridding the default"); } } @@ -169,4 +176,5 @@ public class JdbcAclService implements AclService { protected boolean isAclClassIdSupported() { return aclClassIdSupported; } + } diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java index 6625abdc5d..3654dc7f3f 100644 --- a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java +++ b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java @@ -58,39 +58,52 @@ import org.springframework.util.Assert; * @author Johannes Zlattinger */ public class JdbcMutableAclService extends JdbcAclService implements MutableAclService { + private static final String DEFAULT_INSERT_INTO_ACL_CLASS = "insert into acl_class (class) values (?)"; + private static final String DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID = "insert into acl_class (class, class_id_type) values (?, ?)"; + // ~ Instance fields // ================================================================================================ private boolean foreignKeysInDatabase = true; + private final AclCache aclCache; + private String deleteEntryByObjectIdentityForeignKey = "delete from acl_entry where acl_object_identity=?"; + private String deleteObjectIdentityByPrimaryKey = "delete from acl_object_identity where id=?"; + private String classIdentityQuery = "call identity()"; + private String sidIdentityQuery = "call identity()"; + private String insertClass = DEFAULT_INSERT_INTO_ACL_CLASS; + private String insertEntry = "insert into acl_entry " + "(acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)" + "values (?, ?, ?, ?, ?, ?, ?)"; + private String insertObjectIdentity = "insert into acl_object_identity " - + "(object_id_class, object_id_identity, owner_sid, entries_inheriting) " - + "values (?, ?, ?, ?)"; + + "(object_id_class, object_id_identity, owner_sid, entries_inheriting) " + "values (?, ?, ?, ?)"; + private String insertSid = "insert into acl_sid (principal, sid) values (?, ?)"; + private String selectClassPrimaryKey = "select id from acl_class where class=?"; + private String selectObjectIdentityPrimaryKey = "select acl_object_identity.id from acl_object_identity, acl_class " + "where acl_object_identity.object_id_class = acl_class.id and acl_class.class=? " + "and acl_object_identity.object_id_identity = ?"; + private String selectSidPrimaryKey = "select id from acl_sid where principal=? and sid=?"; + private String updateObjectIdentity = "update acl_object_identity set " - + "parent_object = ?, owner_sid = ?, entries_inheriting = ?" - + " where id = ?"; + + "parent_object = ?, owner_sid = ?, entries_inheriting = ?" + " where id = ?"; // ~ Constructors // =================================================================================================== - public JdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, - AclCache aclCache) { + public JdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) { super(dataSource, lookupStrategy); Assert.notNull(aclCache, "AclCache required"); this.aclCache = aclCache; @@ -99,14 +112,12 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS // ~ Methods // ======================================================================================================== - public MutableAcl createAcl(ObjectIdentity objectIdentity) - throws AlreadyExistsException { + public MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException { Assert.notNull(objectIdentity, "Object Identity required"); // Check this object identity hasn't already been persisted if (retrieveObjectIdentityPrimaryKey(objectIdentity) != null) { - throw new AlreadyExistsException("Object identity '" + objectIdentity - + "' already exists"); + throw new AlreadyExistsException("Object identity '" + objectIdentity + "' already exists"); } // Need to retrieve the current principal, in order to know who "owns" this ACL @@ -128,7 +139,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS /** * Creates a new row in acl_entry for every ACE defined in the passed MutableAcl * object. - * * @param acl containing the ACEs to insert */ protected void createEntries(final MutableAcl acl) { @@ -142,8 +152,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS public void setValues(PreparedStatement stmt, int i) throws SQLException { AccessControlEntry entry_ = acl.getEntries().get(i); - Assert.isTrue(entry_ instanceof AccessControlEntryImpl, - "Unknown ACE class"); + Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class"); AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_; stmt.setLong(1, (Long) acl.getId()); @@ -161,7 +170,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS * Creates an entry in the acl_object_identity table for the passed ObjectIdentity. * The Sid is also necessary, as acl_object_identity has defined the sid column as * non-null. - * * @param object to represent an acl_object_identity for * @param owner for the SID column (will be created if there is no acl_sid entry for * this particular Sid already) @@ -169,22 +177,18 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS protected void createObjectIdentity(ObjectIdentity object, Sid owner) { Long sidId = createOrRetrieveSidPrimaryKey(owner, true); Long classId = createOrRetrieveClassPrimaryKey(object.getType(), true, object.getIdentifier().getClass()); - jdbcOperations.update(insertObjectIdentity, classId, object.getIdentifier().toString(), sidId, - Boolean.TRUE); + jdbcOperations.update(insertObjectIdentity, classId, object.getIdentifier().toString(), sidId, Boolean.TRUE); } /** * Retrieves the primary key from {@code acl_class}, creating a new row if needed and * the {@code allowCreate} property is {@code true}. - * * @param type to find or create an entry for (often the fully-qualified class name) * @param allowCreate true if creation is permitted if not found - * * @return the primary key or null if not found */ protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) { - List classIds = jdbcOperations.queryForList(selectClassPrimaryKey, - new Object[] { type }, Long.class); + List classIds = jdbcOperations.queryForList(selectClassPrimaryKey, new Object[] { type }, Long.class); if (!classIds.isEmpty()) { return classIds.get(0); @@ -193,11 +197,11 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS if (allowCreate) { if (!isAclClassIdSupported()) { jdbcOperations.update(insertClass, type); - } else { + } + else { jdbcOperations.update(insertClass, type, idType.getCanonicalName()); } - Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), - "Transaction must be running"); + Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running"); return jdbcOperations.queryForObject(classIdentityQuery, Long.class); } @@ -207,12 +211,9 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS /** * Retrieves the primary key from acl_sid, creating a new row if needed and the * allowCreate property is true. - * * @param sid to find or create * @param allowCreate true if creation is permitted if not found - * * @return the primary key or null if not found - * * @throws IllegalArgumentException if the Sid is not a recognized * implementation. */ @@ -244,11 +245,10 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS * @param allowCreate true if creation is permitted if not found * @return the primary key or null if not found */ - protected Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, - boolean allowCreate) { + protected Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, boolean allowCreate) { - List sidIds = jdbcOperations.queryForList(selectSidPrimaryKey, new Object[] { - sidIsPrincipal, sidName }, Long.class); + List sidIds = jdbcOperations.queryForList(selectSidPrimaryKey, new Object[] { sidIsPrincipal, sidName }, + Long.class); if (!sidIds.isEmpty()) { return sidIds.get(0); @@ -256,19 +256,16 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS if (allowCreate) { jdbcOperations.update(insertSid, sidIsPrincipal, sidName); - Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), - "Transaction must be running"); + Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running"); return jdbcOperations.queryForObject(sidIdentityQuery, Long.class); } return null; } - public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) - throws ChildrenExistException { + public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException { Assert.notNull(objectIdentity, "Object Identity required"); - Assert.notNull(objectIdentity.getIdentifier(), - "Object Identity doesn't provide an identifier"); + Assert.notNull(objectIdentity.getIdentifier(), "Object Identity doesn't provide an identifier"); if (deleteChildren) { List children = findChildren(objectIdentity); @@ -285,8 +282,8 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS // We generally don't do this, in the interests of deadlock management List children = findChildren(objectIdentity); if (children != null) { - throw new ChildrenExistException("Cannot delete '" + objectIdentity - + "' (has " + children.size() + " children)"); + throw new ChildrenExistException( + "Cannot delete '" + objectIdentity + "' (has " + children.size() + " children)"); } } } @@ -306,7 +303,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS /** * Deletes all ACEs defined in the acl_entry table belonging to the presented * ObjectIdentity primary key. - * * @param oidPrimaryKey the rows in acl_entry to delete */ protected void deleteEntries(Long oidPrimaryKey) { @@ -319,7 +315,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS *

* We do not delete any entries from acl_class, even if no classes are using that * class any longer. This is a deadlock avoidance approach. - * * @param oidPrimaryKey to delete the acl_object_identity */ protected void deleteObjectIdentity(Long oidPrimaryKey) { @@ -331,15 +326,13 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS * Retrieves the primary key from the acl_object_identity table for the passed * ObjectIdentity. Unlike some other methods in this implementation, this method will * NOT create a row (use {@link #createObjectIdentity(ObjectIdentity, Sid)} instead). - * * @param oid to find - * * @return the object identity or null if not found */ protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) { try { - return jdbcOperations.queryForObject(selectObjectIdentityPrimaryKey, Long.class, - oid.getType(), oid.getIdentifier().toString()); + return jdbcOperations.queryForObject(selectObjectIdentityPrimaryKey, Long.class, oid.getType(), + oid.getIdentifier().toString()); } catch (DataAccessException notFound) { return null; @@ -387,29 +380,25 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS * Updates an existing acl_object_identity row, with new information presented in the * passed MutableAcl object. Also will create an acl_sid entry if needed for the Sid * that owns the MutableAcl. - * * @param acl to modify (a row must already exist in acl_object_identity) - * * @throws NotFoundException if the ACL could not be found to update. */ protected void updateObjectIdentity(MutableAcl acl) { Long parentId = null; if (acl.getParentAcl() != null) { - Assert.isInstanceOf(ObjectIdentityImpl.class, acl.getParentAcl() - .getObjectIdentity(), + Assert.isInstanceOf(ObjectIdentityImpl.class, acl.getParentAcl().getObjectIdentity(), "Implementation only supports ObjectIdentityImpl"); - ObjectIdentityImpl oii = (ObjectIdentityImpl) acl.getParentAcl() - .getObjectIdentity(); + ObjectIdentityImpl oii = (ObjectIdentityImpl) acl.getParentAcl().getObjectIdentity(); parentId = retrieveObjectIdentityPrimaryKey(oii); } Assert.notNull(acl.getOwner(), "Owner is required in this implementation"); Long ownerSid = createOrRetrieveSidPrimaryKey(acl.getOwner(), true); - int count = jdbcOperations.update(updateObjectIdentity, parentId, ownerSid, - acl.isEntriesInheriting(), acl.getId()); + int count = jdbcOperations.update(updateObjectIdentity, parentId, ownerSid, acl.isEntriesInheriting(), + acl.getId()); if (count != 1) { throw new NotFoundException("Unable to locate ACL to update"); @@ -419,7 +408,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS /** * Sets the query that will be used to retrieve the identity of a newly created row in * the acl_class table. - * * @param classIdentityQuery the query, which should return the identifier. Defaults * to call identity() */ @@ -431,7 +419,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS /** * Sets the query that will be used to retrieve the identity of a newly created row in * the acl_sid table. - * * @param sidIdentityQuery the query, which should return the identifier. Defaults to * call identity() */ @@ -440,13 +427,11 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS this.sidIdentityQuery = sidIdentityQuery; } - public void setDeleteEntryByObjectIdentityForeignKeySql( - String deleteEntryByObjectIdentityForeignKey) { + public void setDeleteEntryByObjectIdentityForeignKeySql(String deleteEntryByObjectIdentityForeignKey) { this.deleteEntryByObjectIdentityForeignKey = deleteEntryByObjectIdentityForeignKey; } - public void setDeleteObjectIdentityByPrimaryKeySql( - String deleteObjectIdentityByPrimaryKey) { + public void setDeleteObjectIdentityByPrimaryKeySql(String deleteObjectIdentityByPrimaryKey) { this.deleteObjectIdentityByPrimaryKey = deleteObjectIdentityByPrimaryKey; } @@ -498,9 +483,11 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS // Change the default insert if it hasn't been overridden if (this.insertClass.equals(DEFAULT_INSERT_INTO_ACL_CLASS)) { this.insertClass = DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID; - } else { + } + else { log.debug("Insert class statement has already been overridden, so not overridding the default"); } } } + } diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/LookupStrategy.java b/acl/src/main/java/org/springframework/security/acls/jdbc/LookupStrategy.java index dc8a11d419..98243dda75 100644 --- a/acl/src/main/java/org/springframework/security/acls/jdbc/LookupStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/jdbc/LookupStrategy.java @@ -29,16 +29,15 @@ import java.util.Map; * @author Ben Alex */ public interface LookupStrategy { + // ~ Methods // ======================================================================================================== /** * Perform database-specific optimized lookup. - * * @param objects the identities to lookup (required) * @param sids the SIDs for which identities are required (may be null - * implementations may elect not to provide SID optimisations) - * * @return a Map where keys represent the {@link ObjectIdentity} of the * located {@link Acl} and values are the located {@link Acl} (never null * although some entries may be missing; this method should not throw @@ -46,4 +45,5 @@ public interface LookupStrategy { * automatically create entries if required) */ Map readAclsById(List objects, List sids); + } diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/package-info.java b/acl/src/main/java/org/springframework/security/acls/jdbc/package-info.java index 154bf41bfc..0293449a4b 100644 --- a/acl/src/main/java/org/springframework/security/acls/jdbc/package-info.java +++ b/acl/src/main/java/org/springframework/security/acls/jdbc/package-info.java @@ -17,4 +17,3 @@ * JDBC-based persistence of ACL information */ package org.springframework.security.acls.jdbc; - diff --git a/acl/src/main/java/org/springframework/security/acls/model/AccessControlEntry.java b/acl/src/main/java/org/springframework/security/acls/model/AccessControlEntry.java index a1bd103c9b..b0241f0b78 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/AccessControlEntry.java +++ b/acl/src/main/java/org/springframework/security/acls/model/AccessControlEntry.java @@ -29,6 +29,7 @@ import java.io.Serializable; * */ public interface AccessControlEntry extends Serializable { + // ~ Methods // ======================================================================================================== @@ -36,7 +37,6 @@ public interface AccessControlEntry extends Serializable { /** * Obtains an identifier that represents this ACE. - * * @return the identifier, or null if unsaved */ Serializable getId(); @@ -46,10 +46,10 @@ public interface AccessControlEntry extends Serializable { Sid getSid(); /** - * Indicates the permission is being granted to the relevant Sid. If false, - * indicates the permission is being revoked/blocked. - * + * Indicates the permission is being granted to the relevant Sid. If false, indicates + * the permission is being revoked/blocked. * @return true if being granted, false otherwise */ boolean isGranting(); + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/Acl.java b/acl/src/main/java/org/springframework/security/acls/model/Acl.java index de48e3a929..9174cd6b15 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/Acl.java +++ b/acl/src/main/java/org/springframework/security/acls/model/Acl.java @@ -63,7 +63,6 @@ public interface Acl extends Serializable { * subset of Sids. The caller is responsible for correctly handling the * result if only a subset of Sids is represented. *

- * * @return the list of entries represented by the Acl, or null if * there are no entries presently associated with this Acl. */ @@ -72,7 +71,6 @@ public interface Acl extends Serializable { /** * Obtains the domain object this Acl provides entries for. This is immutable * once an Acl is created. - * * @return the object identity (never null) */ ObjectIdentity getObjectIdentity(); @@ -80,7 +78,6 @@ public interface Acl extends Serializable { /** * Determines the owner of the Acl. The meaning of ownership varies by * implementation and is unspecified. - * * @return the owner (may be null if the implementation does not use * ownership concepts) */ @@ -102,7 +99,6 @@ public interface Acl extends Serializable { * subset of Sids. The caller is responsible for correctly handling the * result if only a subset of Sids is represented. *

- * * @return the parent Acl (may be null if this Acl does not * have a parent) */ @@ -118,7 +114,6 @@ public interface Acl extends Serializable { * parent for navigation purposes. Thus, this method denotes whether or not the * navigation relationship also extends to the actual inheritance of entries. *

- * * @return true if parent ACL entries inherit into the current Acl */ boolean isEntriesInheriting(); @@ -158,7 +153,6 @@ public interface Acl extends Serializable { * authorization decision for a {@link Sid} that was never loaded in this Acl * . *

- * * @param permission the permission or permissions required (at least one entry * required) * @param sids the security identities held by the principal (at least one entry @@ -166,17 +160,15 @@ public interface Acl extends Serializable { * @param administrativeMode if true denotes the query is for administrative * purposes and no logging or auditing (if supported by the implementation) should be * undertaken - * * @return true if authorization is granted - * * @throws NotFoundException MUST be thrown if an implementation cannot make an * authoritative authorization decision, usually because there is no ACL information * for this particular permission and/or SID * @throws UnloadedSidException thrown if the Acl does not have details for * one or more of the Sids passed as arguments */ - boolean isGranted(List permission, List sids, - boolean administrativeMode) throws NotFoundException, UnloadedSidException; + boolean isGranted(List permission, List sids, boolean administrativeMode) + throws NotFoundException, UnloadedSidException; /** * For efficiency reasons an Acl may be loaded and not contain @@ -191,12 +183,11 @@ public interface Acl extends Serializable { * all Sids. This method denotes whether or not the specified Sids * have been loaded or not. *

- * * @param sids one or more security identities the caller is interest in knowing * whether this Sid supports - * * @return true if every passed Sid is represented by this * Acl instance */ boolean isSidLoaded(List sids); + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/AclCache.java b/acl/src/main/java/org/springframework/security/acls/model/AclCache.java index 7c23e5f999..85df6e14ea 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/AclCache.java +++ b/acl/src/main/java/org/springframework/security/acls/model/AclCache.java @@ -26,6 +26,7 @@ import java.io.Serializable; * */ public interface AclCache { + // ~ Methods // ======================================================================================================== @@ -40,4 +41,5 @@ public interface AclCache { void putInCache(MutableAcl acl); void clearCache(); + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/AclDataAccessException.java b/acl/src/main/java/org/springframework/security/acls/model/AclDataAccessException.java index 090cecc49f..dc363d1318 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/AclDataAccessException.java +++ b/acl/src/main/java/org/springframework/security/acls/model/AclDataAccessException.java @@ -26,7 +26,6 @@ public abstract class AclDataAccessException extends RuntimeException { /** * Constructs an AclDataAccessException with the specified message and * root cause. - * * @param msg the detail message * @param cause the root cause */ @@ -37,10 +36,10 @@ public abstract class AclDataAccessException extends RuntimeException { /** * Constructs an AclDataAccessException with the specified message and no * root cause. - * * @param msg the detail message */ public AclDataAccessException(String msg) { super(msg); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/AclService.java b/acl/src/main/java/org/springframework/security/acls/model/AclService.java index 462d33d7f2..b0df3f0cd8 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/AclService.java +++ b/acl/src/main/java/org/springframework/security/acls/model/AclService.java @@ -24,15 +24,14 @@ import java.util.Map; * @author Ben Alex */ public interface AclService { + // ~ Methods // ======================================================================================================== /** * Locates all object identities that use the specified parent. This is useful for * administration tools. - * * @param parentIdentity to locate children of - * * @return the children (or null if none were found) */ List findChildren(ObjectIdentity parentIdentity); @@ -44,12 +43,9 @@ public interface AclService { * implementation's potential ability to filter Acl entries based on a * {@link Sid} parameter. *

- * * @param object to locate an {@link Acl} for - * * @return the {@link Acl} for the requested {@link ObjectIdentity} (never * null) - * * @throws NotFoundException if an {@link Acl} was not found for the requested * {@link ObjectIdentity} */ @@ -57,14 +53,11 @@ public interface AclService { /** * Same as {@link #readAclsById(List, List)} except it returns only a single Acl. - * * @param object to locate an {@link Acl} for * @param sids the security identities for which {@link Acl} information is required * (may be null to denote all entries) - * * @return the {@link Acl} for the requested {@link ObjectIdentity} (never * null) - * * @throws NotFoundException if an {@link Acl} was not found for the requested * {@link ObjectIdentity} */ @@ -76,17 +69,13 @@ public interface AclService { * The returned map is keyed on the passed objects, with the values being the * Acl instances. Any unknown objects will not have a map key. *

- * * @param objects the objects to find {@link Acl} information for - * * @return a map with exactly one element for each {@link ObjectIdentity} passed as an * argument (never null) - * * @throws NotFoundException if an {@link Acl} was not found for each requested * {@link ObjectIdentity} */ - Map readAclsById(List objects) - throws NotFoundException; + Map readAclsById(List objects) throws NotFoundException; /** * Obtains all the Acls that apply for the passed Objects, but only @@ -103,17 +92,14 @@ public interface AclService { * Acl instances. Any unknown objects (or objects for which the interested * Sids do not have entries) will not have a map key. *

- * * @param objects the objects to find {@link Acl} information for * @param sids the security identities for which {@link Acl} information is required * (may be null to denote all entries) - * * @return a map with exactly one element for each {@link ObjectIdentity} passed as an * argument (never null) - * * @throws NotFoundException if an {@link Acl} was not found for each requested * {@link ObjectIdentity} */ - Map readAclsById(List objects, List sids) - throws NotFoundException; + Map readAclsById(List objects, List sids) throws NotFoundException; + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/AlreadyExistsException.java b/acl/src/main/java/org/springframework/security/acls/model/AlreadyExistsException.java index d611ab11ee..d0d7818e60 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/AlreadyExistsException.java +++ b/acl/src/main/java/org/springframework/security/acls/model/AlreadyExistsException.java @@ -21,12 +21,12 @@ package org.springframework.security.acls.model; * @author Ben Alex */ public class AlreadyExistsException extends AclDataAccessException { + // ~ Constructors // =================================================================================================== /** * Constructs an AlreadyExistsException with the specified message. - * * @param msg the detail message */ public AlreadyExistsException(String msg) { @@ -36,11 +36,11 @@ public class AlreadyExistsException extends AclDataAccessException { /** * Constructs an AlreadyExistsException with the specified message and * root cause. - * * @param msg the detail message * @param t root cause */ public AlreadyExistsException(String msg, Throwable t) { super(msg, t); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/AuditableAccessControlEntry.java b/acl/src/main/java/org/springframework/security/acls/model/AuditableAccessControlEntry.java index 30ea235690..1790e38276 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/AuditableAccessControlEntry.java +++ b/acl/src/main/java/org/springframework/security/acls/model/AuditableAccessControlEntry.java @@ -22,10 +22,12 @@ package org.springframework.security.acls.model; * */ public interface AuditableAccessControlEntry extends AccessControlEntry { + // ~ Methods // ======================================================================================================== boolean isAuditFailure(); boolean isAuditSuccess(); + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/AuditableAcl.java b/acl/src/main/java/org/springframework/security/acls/model/AuditableAcl.java index ddf31a954d..9311aac46e 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/AuditableAcl.java +++ b/acl/src/main/java/org/springframework/security/acls/model/AuditableAcl.java @@ -22,8 +22,10 @@ package org.springframework.security.acls.model; * */ public interface AuditableAcl extends MutableAcl { + // ~ Methods // ======================================================================================================== void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure); + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/ChildrenExistException.java b/acl/src/main/java/org/springframework/security/acls/model/ChildrenExistException.java index 514258ec07..d127e8523f 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/ChildrenExistException.java +++ b/acl/src/main/java/org/springframework/security/acls/model/ChildrenExistException.java @@ -21,12 +21,12 @@ package org.springframework.security.acls.model; * @author Ben Alex */ public class ChildrenExistException extends AclDataAccessException { + // ~ Constructors // =================================================================================================== /** * Constructs an ChildrenExistException with the specified message. - * * @param msg the detail message */ public ChildrenExistException(String msg) { @@ -36,11 +36,11 @@ public class ChildrenExistException extends AclDataAccessException { /** * Constructs an ChildrenExistException with the specified message and * root cause. - * * @param msg the detail message * @param t root cause */ public ChildrenExistException(String msg, Throwable t) { super(msg, t); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/MutableAcl.java b/acl/src/main/java/org/springframework/security/acls/model/MutableAcl.java index 0e91c66e25..717824b513 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/MutableAcl.java +++ b/acl/src/main/java/org/springframework/security/acls/model/MutableAcl.java @@ -26,6 +26,7 @@ import java.io.Serializable; * @author Ben Alex */ public interface MutableAcl extends Acl { + // ~ Methods // ======================================================================================================== @@ -33,34 +34,30 @@ public interface MutableAcl extends Acl { /** * Obtains an identifier that represents this MutableAcl. - * * @return the identifier, or null if unsaved */ Serializable getId(); - void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting) - throws NotFoundException; + void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting) throws NotFoundException; /** * Changes the present owner to a different owner. - * * @param newOwner the new owner (mandatory; cannot be null) */ void setOwner(Sid newOwner); /** * Change the value returned by {@link Acl#isEntriesInheriting()}. - * * @param entriesInheriting the new value */ void setEntriesInheriting(boolean entriesInheriting); /** * Changes the parent of this ACL. - * * @param newParent the new parent */ void setParent(Acl newParent); void updateAce(int aceIndex, Permission permission) throws NotFoundException; + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/MutableAclService.java b/acl/src/main/java/org/springframework/security/acls/model/MutableAclService.java index 7b14f99e40..0c1536529a 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/MutableAclService.java +++ b/acl/src/main/java/org/springframework/security/acls/model/MutableAclService.java @@ -21,41 +21,35 @@ package org.springframework.security.acls.model; * @author Ben Alex */ public interface MutableAclService extends AclService { + // ~ Methods // ======================================================================================================== /** * Creates an empty Acl object in the database. It will have no entries. * The returned object will then be used to add entries. - * * @param objectIdentity the object identity to create - * * @return an ACL object with its ID set - * * @throws AlreadyExistsException if the passed object identity already has a record */ MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException; /** * Removes the specified entry from the database. - * * @param objectIdentity the object identity to remove * @param deleteChildren whether to cascade the delete to children - * * @throws ChildrenExistException if the deleteChildren argument was * false but children exist */ - void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) - throws ChildrenExistException; + void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException; /** * Changes an existing Acl in the database. - * * @param acl to modify - * * @throws NotFoundException if the relevant record could not be found (did you * remember to use {@link #createAcl(ObjectIdentity)} to create the object, rather * than creating it with the new keyword?) */ MutableAcl updateAcl(MutableAcl acl) throws NotFoundException; + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/NotFoundException.java b/acl/src/main/java/org/springframework/security/acls/model/NotFoundException.java index e470d61292..7e1450dedf 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/NotFoundException.java +++ b/acl/src/main/java/org/springframework/security/acls/model/NotFoundException.java @@ -21,12 +21,12 @@ package org.springframework.security.acls.model; * @author Ben Alex */ public class NotFoundException extends AclDataAccessException { + // ~ Constructors // =================================================================================================== /** * Constructs an NotFoundException with the specified message. - * * @param msg the detail message */ public NotFoundException(String msg) { @@ -36,11 +36,11 @@ public class NotFoundException extends AclDataAccessException { /** * Constructs an NotFoundException with the specified message and root * cause. - * * @param msg the detail message * @param t root cause */ public NotFoundException(String msg, Throwable t) { super(msg, t); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentity.java b/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentity.java index 2edf7cd2e1..5e5d9d8e37 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentity.java +++ b/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentity.java @@ -32,12 +32,12 @@ import java.io.Serializable; * @author Ben Alex */ public interface ObjectIdentity extends Serializable { + // ~ Methods // ======================================================================================================== /** * @param obj to be compared - * * @return true if the objects are equal, false otherwise * @see Object#equals(Object) */ @@ -53,7 +53,6 @@ public interface ObjectIdentity extends Serializable { * identifier with business meaning, as that business meaning may change in the future * such change will cascade to the ACL subsystem data. *

- * * @return the identifier (unique within this type; never null) */ Serializable getIdentifier(); @@ -62,7 +61,6 @@ public interface ObjectIdentity extends Serializable { * Obtains the "type" metadata for the domain object. This will often be a Java type * name (an interface or a class) – traditionally it is the name of the domain * object implementation class. - * * @return the "type" of the domain object (never null). */ String getType(); @@ -72,4 +70,5 @@ public interface ObjectIdentity extends Serializable { * @see Object#hashCode() */ int hashCode(); + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityGenerator.java b/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityGenerator.java index 1814295874..b78059c8f1 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityGenerator.java +++ b/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityGenerator.java @@ -30,7 +30,6 @@ import java.io.Serializable; public interface ObjectIdentityGenerator { /** - * * @param id the identifier of the domain object, not null * @param type the type of the object (often a class name), not null * @return the identity constructed using the supplied identifier and type diff --git a/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityRetrievalStrategy.java b/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityRetrievalStrategy.java index cd1b53031e..da817471b1 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityRetrievalStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentityRetrievalStrategy.java @@ -24,8 +24,10 @@ package org.springframework.security.acls.model; * */ public interface ObjectIdentityRetrievalStrategy { + // ~ Methods // ======================================================================================================== ObjectIdentity getObjectIdentity(Object domainObject); + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/OwnershipAcl.java b/acl/src/main/java/org/springframework/security/acls/model/OwnershipAcl.java index edda240b19..856bd2f3b4 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/OwnershipAcl.java +++ b/acl/src/main/java/org/springframework/security/acls/model/OwnershipAcl.java @@ -25,8 +25,10 @@ package org.springframework.security.acls.model; * @author Ben Alex */ public interface OwnershipAcl extends MutableAcl { + // ~ Methods // ======================================================================================================== void setOwner(Sid newOwner); + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/Permission.java b/acl/src/main/java/org/springframework/security/acls/model/Permission.java index 68beec8568..ea44686f29 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/Permission.java +++ b/acl/src/main/java/org/springframework/security/acls/model/Permission.java @@ -23,11 +23,14 @@ import java.io.Serializable; * @author Ben Alex */ public interface Permission extends Serializable { + // ~ Static fields/initializers // ===================================================================================== char RESERVED_ON = '~'; + char RESERVED_OFF = '.'; + String THIRTY_TWO_RESERVED_OFF = "................................"; // ~ Methods @@ -35,7 +38,6 @@ public interface Permission extends Serializable { /** * Returns the bits that represents the permission. - * * @return the bits that represent the permission */ int getMask(); @@ -56,8 +58,8 @@ public interface Permission extends Serializable { * This method is only used for user interface and logging purposes. It is not used in * any permission calculations. Therefore, duplication of characters within the output * is permitted. - * * @return a 32-character bit pattern */ String getPattern(); + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/PermissionGrantingStrategy.java b/acl/src/main/java/org/springframework/security/acls/model/PermissionGrantingStrategy.java index 14c8185c18..f9d5ffe351 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/PermissionGrantingStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/model/PermissionGrantingStrategy.java @@ -27,10 +27,9 @@ import java.util.List; public interface PermissionGrantingStrategy { /** - * Returns true if the supplied strategy decides that the supplied {@code Acl} - * grants access based on the supplied list of permissions and sids. + * Returns true if the supplied strategy decides that the supplied {@code Acl} grants + * access based on the supplied list of permissions and sids. */ - boolean isGranted(Acl acl, List permission, List sids, - boolean administrativeMode); + boolean isGranted(Acl acl, List permission, List sids, boolean administrativeMode); } diff --git a/acl/src/main/java/org/springframework/security/acls/model/Sid.java b/acl/src/main/java/org/springframework/security/acls/model/Sid.java index 134fc0ed7a..4ced8b26f7 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/Sid.java +++ b/acl/src/main/java/org/springframework/security/acls/model/Sid.java @@ -31,15 +31,14 @@ import java.io.Serializable; * @author Ben Alex */ public interface Sid extends Serializable { + // ~ Methods // ======================================================================================================== /** * Refer to the java.lang.Object documentation for the interface * contract. - * * @param obj to be compared - * * @return true if the objects are equal, false otherwise */ boolean equals(Object obj); @@ -47,8 +46,8 @@ public interface Sid extends Serializable { /** * Refer to the java.lang.Object documentation for the interface * contract. - * * @return a hash code representation of this object */ int hashCode(); + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/SidRetrievalStrategy.java b/acl/src/main/java/org/springframework/security/acls/model/SidRetrievalStrategy.java index 3f605440c0..24397ea1cc 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/SidRetrievalStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/model/SidRetrievalStrategy.java @@ -27,8 +27,10 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ public interface SidRetrievalStrategy { + // ~ Methods // ======================================================================================================== List getSids(Authentication authentication); + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/UnloadedSidException.java b/acl/src/main/java/org/springframework/security/acls/model/UnloadedSidException.java index b692ad79ca..f48b60e11b 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/UnloadedSidException.java +++ b/acl/src/main/java/org/springframework/security/acls/model/UnloadedSidException.java @@ -23,12 +23,12 @@ package org.springframework.security.acls.model; * @author Ben Alex */ public class UnloadedSidException extends AclDataAccessException { + // ~ Constructors // =================================================================================================== /** * Constructs an NotFoundException with the specified message. - * * @param msg the detail message */ public UnloadedSidException(String msg) { @@ -38,11 +38,11 @@ public class UnloadedSidException extends AclDataAccessException { /** * Constructs an NotFoundException with the specified message and root * cause. - * * @param msg the detail message * @param t root cause */ public UnloadedSidException(String msg, Throwable t) { super(msg, t); } + } diff --git a/acl/src/main/java/org/springframework/security/acls/model/package-info.java b/acl/src/main/java/org/springframework/security/acls/model/package-info.java index c6f8389ae9..7b06410450 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/package-info.java +++ b/acl/src/main/java/org/springframework/security/acls/model/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Interfaces and shared classes to manage access control lists (ACLs) for domain object instances. + * Interfaces and shared classes to manage access control lists (ACLs) for domain object + * instances. */ package org.springframework.security.acls.model; - diff --git a/acl/src/main/java/org/springframework/security/acls/package-info.java b/acl/src/main/java/org/springframework/security/acls/package-info.java index 75d4de804f..7b764596d5 100644 --- a/acl/src/main/java/org/springframework/security/acls/package-info.java +++ b/acl/src/main/java/org/springframework/security/acls/package-info.java @@ -14,11 +14,13 @@ * limitations under the License. */ /** - * The Spring Security ACL package which implements instance-based security for domain objects. + * The Spring Security ACL package which implements instance-based security for domain + * objects. *

- * Consider using the annotation based approach ({@code @PreAuthorize}, {@code @PostFilter} annotations) combined - * with a {@link org.springframework.security.acls.AclPermissionEvaluator} in preference to the older and more verbose - * attribute/voter/after-invocation approach from versions before Spring Security 3.0. + * Consider using the annotation based approach ({@code @PreAuthorize}, + * {@code @PostFilter} annotations) combined with a + * {@link org.springframework.security.acls.AclPermissionEvaluator} in preference to the + * older and more verbose attribute/voter/after-invocation approach from versions before + * Spring Security 3.0. */ package org.springframework.security.acls; - diff --git a/acl/src/test/java/org/springframework/security/acls/AclFormattingUtilsTests.java b/acl/src/test/java/org/springframework/security/acls/AclFormattingUtilsTests.java index acf951ef06..87fcd2e0e9 100644 --- a/acl/src/test/java/org/springframework/security/acls/AclFormattingUtilsTests.java +++ b/acl/src/test/java/org/springframework/security/acls/AclFormattingUtilsTests.java @@ -66,13 +66,11 @@ public class AclFormattingUtilsTests { public final void testDemergePatterns() { String original = "...........................A...R"; String removeBits = "...............................R"; - assertThat(AclFormattingUtils.demergePatterns(original, removeBits)).isEqualTo( - "...........................A...."); + assertThat(AclFormattingUtils.demergePatterns(original, removeBits)) + .isEqualTo("...........................A...."); - assertThat(AclFormattingUtils.demergePatterns("ABCDEF", "......")).isEqualTo( - "ABCDEF"); - assertThat(AclFormattingUtils.demergePatterns("ABCDEF", "GHIJKL")).isEqualTo( - "......"); + assertThat(AclFormattingUtils.demergePatterns("ABCDEF", "......")).isEqualTo("ABCDEF"); + assertThat(AclFormattingUtils.demergePatterns("ABCDEF", "GHIJKL")).isEqualTo("......"); } @Test @@ -109,19 +107,15 @@ public class AclFormattingUtilsTests { public final void testMergePatterns() { String original = "...............................R"; String extraBits = "...........................A...."; - assertThat(AclFormattingUtils.mergePatterns(original, extraBits)).isEqualTo( - "...........................A...R"); + assertThat(AclFormattingUtils.mergePatterns(original, extraBits)).isEqualTo("...........................A...R"); - assertThat(AclFormattingUtils.mergePatterns("ABCDEF", "......")).isEqualTo( - "ABCDEF"); - assertThat(AclFormattingUtils.mergePatterns("ABCDEF", "GHIJKL")).isEqualTo( - "GHIJKL"); + assertThat(AclFormattingUtils.mergePatterns("ABCDEF", "......")).isEqualTo("ABCDEF"); + assertThat(AclFormattingUtils.mergePatterns("ABCDEF", "GHIJKL")).isEqualTo("GHIJKL"); } @Test public final void testBinaryPrints() { - assertThat(AclFormattingUtils.printBinary(15)).isEqualTo( - "............................****"); + assertThat(AclFormattingUtils.printBinary(15)).isEqualTo("............................****"); try { AclFormattingUtils.printBinary(15, Permission.RESERVED_ON); @@ -137,19 +131,17 @@ public class AclFormattingUtilsTests { catch (IllegalArgumentException notExpected) { } - assertThat(AclFormattingUtils.printBinary(15, 'x')).isEqualTo( - "............................xxxx"); + assertThat(AclFormattingUtils.printBinary(15, 'x')).isEqualTo("............................xxxx"); } @Test public void testPrintBinaryNegative() { - assertThat(AclFormattingUtils.printBinary(0x80000000)).isEqualTo( - "*..............................."); + assertThat(AclFormattingUtils.printBinary(0x80000000)).isEqualTo("*..............................."); } @Test public void testPrintBinaryMinusOne() { - assertThat(AclFormattingUtils.printBinary(0xffffffff)).isEqualTo( - "********************************"); + assertThat(AclFormattingUtils.printBinary(0xffffffff)).isEqualTo("********************************"); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/AclPermissionCacheOptimizerTests.java b/acl/src/test/java/org/springframework/security/acls/AclPermissionCacheOptimizerTests.java index d499a79ca7..f922d20c9c 100644 --- a/acl/src/test/java/org/springframework/security/acls/AclPermissionCacheOptimizerTests.java +++ b/acl/src/test/java/org/springframework/security/acls/AclPermissionCacheOptimizerTests.java @@ -44,8 +44,7 @@ public class AclPermissionCacheOptimizerTests { pco.setObjectIdentityRetrievalStrategy(oidStrat); pco.setSidRetrievalStrategy(sidStrat); Object[] dos = { new Object(), null, new Object() }; - ObjectIdentity[] oids = { new ObjectIdentityImpl("A", "1"), - new ObjectIdentityImpl("A", "2") }; + ObjectIdentity[] oids = { new ObjectIdentityImpl("A", "1"), new ObjectIdentityImpl("A", "2") }; when(oidStrat.getObjectIdentity(dos[0])).thenReturn(oids[0]); when(oidStrat.getObjectIdentity(dos[2])).thenReturn(oids[1]); diff --git a/acl/src/test/java/org/springframework/security/acls/AclPermissionEvaluatorTests.java b/acl/src/test/java/org/springframework/security/acls/AclPermissionEvaluatorTests.java index 47df332908..148083b750 100644 --- a/acl/src/test/java/org/springframework/security/acls/AclPermissionEvaluatorTests.java +++ b/acl/src/test/java/org/springframework/security/acls/AclPermissionEvaluatorTests.java @@ -30,7 +30,6 @@ import org.springframework.security.acls.model.SidRetrievalStrategy; import org.springframework.security.core.Authentication; /** - * * @author Luke Taylor * @since 3.0 */ @@ -74,4 +73,5 @@ public class AclPermissionEvaluatorTests { Locale.setDefault(systemLocale); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/TargetObjectWithUUID.java b/acl/src/test/java/org/springframework/security/acls/TargetObjectWithUUID.java index 426956f7ea..11b297257d 100644 --- a/acl/src/test/java/org/springframework/security/acls/TargetObjectWithUUID.java +++ b/acl/src/test/java/org/springframework/security/acls/TargetObjectWithUUID.java @@ -33,4 +33,5 @@ public final class TargetObjectWithUUID { public void setId(UUID id) { this.id = id; } + } diff --git a/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProviderTests.java b/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProviderTests.java index b85b01d3dd..f9a1c8f4b6 100644 --- a/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProviderTests.java +++ b/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationCollectionFilteringProviderTests.java @@ -15,7 +15,6 @@ */ package org.springframework.security.acls.afterinvocation; - import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; @@ -36,14 +35,13 @@ import java.util.List; */ @SuppressWarnings({ "unchecked" }) public class AclEntryAfterInvocationCollectionFilteringProviderTests { + @Test public void objectsAreRemovedIfPermissionDenied() { AclService service = mock(AclService.class); Acl acl = mock(Acl.class); - when(acl.isGranted(any(), any(), anyBoolean())).thenReturn( - false); - when(service.readAclById(any(), any())).thenReturn( - acl); + when(acl.isGranted(any(), any(), anyBoolean())).thenReturn(false); + when(service.readAclById(any(), any())).thenReturn(acl); AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider( service, Arrays.asList(mock(Permission.class))); provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class)); @@ -51,8 +49,8 @@ public class AclEntryAfterInvocationCollectionFilteringProviderTests { provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class)); Object returned = provider.decide(mock(Authentication.class), new Object(), - SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), new ArrayList( - Arrays.asList(new Object(), new Object()))); + SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), + new ArrayList(Arrays.asList(new Object(), new Object()))); assertThat(returned).isInstanceOf(List.class); assertThat(((List) returned)).isEmpty(); returned = provider.decide(mock(Authentication.class), new Object(), @@ -68,10 +66,8 @@ public class AclEntryAfterInvocationCollectionFilteringProviderTests { mock(AclService.class), Arrays.asList(mock(Permission.class))); Object returned = new Object(); - assertThat(returned) - .isSameAs( - provider.decide(mock(Authentication.class), new Object(), - Collections. emptyList(), returned)); + assertThat(returned).isSameAs(provider.decide(mock(Authentication.class), new Object(), + Collections.emptyList(), returned)); } @Test @@ -81,8 +77,7 @@ public class AclEntryAfterInvocationCollectionFilteringProviderTests { service, Arrays.asList(mock(Permission.class))); assertThat(provider.decide(mock(Authentication.class), new Object(), - SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null)) - .isNull(); + SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null)).isNull(); verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class)); } diff --git a/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProviderTests.java b/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProviderTests.java index 322bb3d11f..a541f72215 100644 --- a/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProviderTests.java +++ b/acl/src/test/java/org/springframework/security/acls/afterinvocation/AclEntryAfterInvocationProviderTests.java @@ -44,74 +44,59 @@ public class AclEntryAfterInvocationProviderTests { } catch (IllegalArgumentException expected) { } - new AclEntryAfterInvocationProvider(mock(AclService.class), - Collections. emptyList()); + new AclEntryAfterInvocationProvider(mock(AclService.class), Collections.emptyList()); } @Test public void accessIsAllowedIfPermissionIsGranted() { AclService service = mock(AclService.class); Acl acl = mock(Acl.class); - when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn( - true); - when(service.readAclById(any(), any())).thenReturn( - acl); - AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider( - service, Arrays.asList(mock(Permission.class))); + when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(true); + when(service.readAclById(any(), any())).thenReturn(acl); + AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service, + Arrays.asList(mock(Permission.class))); provider.setMessageSource(new SpringSecurityMessageSource()); provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class)); provider.setProcessDomainObjectClass(Object.class); provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class)); Object returned = new Object(); - assertThat( - returned) - .isSameAs( - provider.decide(mock(Authentication.class), new Object(), - SecurityConfig.createList("AFTER_ACL_READ"), returned)); + assertThat(returned).isSameAs(provider.decide(mock(Authentication.class), new Object(), + SecurityConfig.createList("AFTER_ACL_READ"), returned)); } @Test public void accessIsGrantedIfNoAttributesDefined() { - AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider( - mock(AclService.class), Arrays.asList(mock(Permission.class))); + AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(mock(AclService.class), + Arrays.asList(mock(Permission.class))); Object returned = new Object(); - assertThat( - returned) - .isSameAs( - provider.decide(mock(Authentication.class), new Object(), - Collections. emptyList(), returned)); + assertThat(returned).isSameAs(provider.decide(mock(Authentication.class), new Object(), + Collections.emptyList(), returned)); } @Test public void accessIsGrantedIfObjectTypeNotSupported() { - AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider( - mock(AclService.class), Arrays.asList(mock(Permission.class))); + AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(mock(AclService.class), + Arrays.asList(mock(Permission.class))); provider.setProcessDomainObjectClass(String.class); // Not a String Object returned = new Object(); - assertThat( - returned) - .isSameAs( - provider.decide(mock(Authentication.class), new Object(), - SecurityConfig.createList("AFTER_ACL_READ"), returned)); + assertThat(returned).isSameAs(provider.decide(mock(Authentication.class), new Object(), + SecurityConfig.createList("AFTER_ACL_READ"), returned)); } @Test(expected = AccessDeniedException.class) public void accessIsDeniedIfPermissionIsNotGranted() { AclService service = mock(AclService.class); Acl acl = mock(Acl.class); - when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn( - false); + when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(false); // Try a second time with no permissions found - when(acl.isGranted(any(), any(List.class), anyBoolean())).thenThrow( - new NotFoundException("")); - when(service.readAclById(any(), any())).thenReturn( - acl); - AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider( - service, Arrays.asList(mock(Permission.class))); + when(acl.isGranted(any(), any(List.class), anyBoolean())).thenThrow(new NotFoundException("")); + when(service.readAclById(any(), any())).thenReturn(acl); + AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service, + Arrays.asList(mock(Permission.class))); provider.setProcessConfigAttribute("MY_ATTRIBUTE"); provider.setMessageSource(new SpringSecurityMessageSource()); provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class)); @@ -119,8 +104,7 @@ public class AclEntryAfterInvocationProviderTests { provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class)); try { provider.decide(mock(Authentication.class), new Object(), - SecurityConfig.createList("UNSUPPORTED", "MY_ATTRIBUTE"), - new Object()); + SecurityConfig.createList("UNSUPPORTED", "MY_ATTRIBUTE"), new Object()); fail("Expected Exception"); } catch (AccessDeniedException expected) { @@ -133,12 +117,12 @@ public class AclEntryAfterInvocationProviderTests { @Test public void nullReturnObjectIsIgnored() { AclService service = mock(AclService.class); - AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider( - service, Arrays.asList(mock(Permission.class))); + AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service, + Arrays.asList(mock(Permission.class))); assertThat(provider.decide(mock(Authentication.class), new Object(), - SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null)) - .isNull(); + SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null)).isNull(); verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class)); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/AccessControlImplEntryTests.java b/acl/src/test/java/org/springframework/security/acls/domain/AccessControlImplEntryTests.java index bbf33dfef4..0def085888 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/AccessControlImplEntryTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/AccessControlImplEntryTests.java @@ -39,8 +39,8 @@ public class AccessControlImplEntryTests { public void testConstructorRequiredFields() { // Check Acl field is present try { - new AccessControlEntryImpl(null, null, new PrincipalSid("johndoe"), - BasePermission.ADMINISTRATION, true, true, true); + new AccessControlEntryImpl(null, null, new PrincipalSid("johndoe"), BasePermission.ADMINISTRATION, true, + true, true); fail("It should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { @@ -48,8 +48,7 @@ public class AccessControlImplEntryTests { // Check Sid field is present try { - new AccessControlEntryImpl(null, mock(Acl.class), null, - BasePermission.ADMINISTRATION, true, true, true); + new AccessControlEntryImpl(null, mock(Acl.class), null, BasePermission.ADMINISTRATION, true, true, true); fail("It should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { @@ -57,8 +56,7 @@ public class AccessControlImplEntryTests { // Check Permission field is present try { - new AccessControlEntryImpl(null, mock(Acl.class), - new PrincipalSid("johndoe"), null, true, true, true); + new AccessControlEntryImpl(null, mock(Acl.class), new PrincipalSid("johndoe"), null, true, true, true); fail("It should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { @@ -71,8 +69,8 @@ public class AccessControlImplEntryTests { Sid sid = new PrincipalSid("johndoe"); // Create a sample entry - AccessControlEntry ace = new AccessControlEntryImpl(1L, mockAcl, - sid, BasePermission.ADMINISTRATION, true, true, true); + AccessControlEntry ace = new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true, + true); // and check every get() method assertThat(ace.getId()).isEqualTo(1L); @@ -92,26 +90,26 @@ public class AccessControlImplEntryTests { when(mockAcl.getObjectIdentity()).thenReturn(oid); Sid sid = new PrincipalSid("johndoe"); - AccessControlEntry ace = new AccessControlEntryImpl(1L, mockAcl, - sid, BasePermission.ADMINISTRATION, true, true, true); + AccessControlEntry ace = new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true, + true); assertThat(ace).isNotNull(); assertThat(ace).isNotEqualTo(100L); assertThat(ace).isEqualTo(ace); - assertThat(ace).isEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid, + assertThat(ace).isEqualTo( + new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true, true)); + assertThat(ace).isNotEqualTo( + new AccessControlEntryImpl(2L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true, true)); + assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, new PrincipalSid("scott"), BasePermission.ADMINISTRATION, true, true, true)); - assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(2L, mockAcl, sid, - BasePermission.ADMINISTRATION, true, true, true)); - assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, - new PrincipalSid("scott"), BasePermission.ADMINISTRATION, true, true, - true)); - assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid, - BasePermission.WRITE, true, true, true)); - assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid, - BasePermission.ADMINISTRATION, false, true, true)); - assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid, - BasePermission.ADMINISTRATION, true, false, true)); - assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid, - BasePermission.ADMINISTRATION, true, true, false)); + assertThat(ace) + .isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.WRITE, true, true, true)); + assertThat(ace).isNotEqualTo( + new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, false, true, true)); + assertThat(ace).isNotEqualTo( + new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, false, true)); + assertThat(ace).isNotEqualTo( + new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true, false)); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/AclAuthorizationStrategyImplTests.java b/acl/src/test/java/org/springframework/security/acls/domain/AclAuthorizationStrategyImplTests.java index 0e8d7c12ff..348122d0c4 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/AclAuthorizationStrategyImplTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/AclAuthorizationStrategyImplTests.java @@ -15,7 +15,6 @@ */ package org.springframework.security.acls.domain; - import java.util.Arrays; import org.junit.After; @@ -31,21 +30,24 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; /** - * * @author Rob Winch * */ @RunWith(MockitoJUnitRunner.class) public class AclAuthorizationStrategyImplTests { + @Mock Acl acl; + GrantedAuthority authority; + AclAuthorizationStrategyImpl strategy; @Before public void setup() { authority = new SimpleGrantedAuthority("ROLE_AUTH"); - TestingAuthenticationToken authentication = new TestingAuthenticationToken("foo", "bar", Arrays.asList(authority)); + TestingAuthenticationToken authentication = new TestingAuthenticationToken("foo", "bar", + Arrays.asList(authority)); authentication.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(authentication); } @@ -64,9 +66,12 @@ public class AclAuthorizationStrategyImplTests { @SuppressWarnings("serial") class CustomAuthority implements GrantedAuthority { + @Override public String getAuthority() { return authority.getAuthority(); } + } + } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/AclImplTests.java b/acl/src/test/java/org/springframework/security/acls/domain/AclImplTests.java index 7313048d20..fddbe66610 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/AclImplTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/AclImplTests.java @@ -35,20 +35,31 @@ import java.util.*; * @author Andrei Stefan */ public class AclImplTests { + private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; + private static final List READ = Arrays.asList(BasePermission.READ); + private static final List WRITE = Arrays.asList(BasePermission.WRITE); + private static final List CREATE = Arrays.asList(BasePermission.CREATE); + private static final List DELETE = Arrays.asList(BasePermission.DELETE); + private static final List SCOTT = Arrays.asList((Sid) new PrincipalSid("scott")); + private static final List BEN = Arrays.asList((Sid) new PrincipalSid("ben")); - Authentication auth = new TestingAuthenticationToken("joe", "ignored", - "ROLE_ADMINISTRATOR"); + Authentication auth = new TestingAuthenticationToken("joe", "ignored", "ROLE_ADMINISTRATOR"); + AclAuthorizationStrategy authzStrategy; + PermissionGrantingStrategy pgs; + AuditLogger mockAuditLogger; + ObjectIdentity objectIdentity = new ObjectIdentityImpl(TARGET_CLASS, 100); + private DefaultPermissionFactory permissionFactory; // ~ Methods @@ -72,8 +83,7 @@ public class AclImplTests { @Test(expected = IllegalArgumentException.class) public void constructorsRejectNullObjectIdentity() { try { - new AclImpl(null, 1, authzStrategy, pgs, null, null, true, new PrincipalSid( - "joe")); + new AclImpl(null, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { @@ -84,8 +94,7 @@ public class AclImplTests { @Test(expected = IllegalArgumentException.class) public void constructorsRejectNullId() { try { - new AclImpl(objectIdentity, null, authzStrategy, pgs, null, null, true, - new PrincipalSid("joe")); + new AclImpl(objectIdentity, null, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { @@ -97,8 +106,8 @@ public class AclImplTests { @Test(expected = IllegalArgumentException.class) public void constructorsRejectNullAclAuthzStrategy() { try { - new AclImpl(objectIdentity, 1, null, new DefaultPermissionGrantingStrategy( - mockAuditLogger), null, null, true, new PrincipalSid("joe")); + new AclImpl(objectIdentity, 1, null, new DefaultPermissionGrantingStrategy(mockAuditLogger), null, null, + true, new PrincipalSid("joe")); fail("It should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { @@ -108,8 +117,7 @@ public class AclImplTests { @Test public void insertAceRejectsNullParameters() { - MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, - true, new PrincipalSid("joe")); + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); try { acl.insertAce(0, null, new GrantedAuthoritySid("ROLE_IGNORED"), true); fail("It should have thrown IllegalArgumentException"); @@ -126,8 +134,7 @@ public class AclImplTests { @Test public void insertAceAddsElementAtCorrectIndex() { - MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, - true, new PrincipalSid("joe")); + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); MockAclService service = new MockAclService(); // Insert one permission @@ -137,8 +144,7 @@ public class AclImplTests { assertThat(acl.getEntries()).hasSize(1); assertThat(acl).isEqualTo(acl.getEntries().get(0).getAcl()); assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(0).getPermission()); - assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid( - "ROLE_TEST1")); + assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST1")); // Add a second permission acl.insertAce(1, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true); @@ -147,44 +153,36 @@ public class AclImplTests { assertThat(acl.getEntries()).hasSize(2); assertThat(acl).isEqualTo(acl.getEntries().get(1).getAcl()); assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(1).getPermission()); - assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid( - "ROLE_TEST2")); + assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST2")); // Add a third permission, after the first one - acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_TEST3"), - false); + acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_TEST3"), false); service.updateAcl(acl); assertThat(acl.getEntries()).hasSize(3); // Check the third entry was added between the two existent ones assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(0).getPermission()); - assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid( - "ROLE_TEST1")); + assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST1")); assertThat(BasePermission.WRITE).isEqualTo(acl.getEntries().get(1).getPermission()); - assertThat(acl.getEntries().get(1).getSid()).isEqualTo( new GrantedAuthoritySid( - "ROLE_TEST3")); + assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST3")); assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(2).getPermission()); - assertThat(acl.getEntries().get(2).getSid()).isEqualTo(new GrantedAuthoritySid( - "ROLE_TEST2")); + assertThat(acl.getEntries().get(2).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST2")); } @Test(expected = NotFoundException.class) public void insertAceFailsForNonExistentElement() { - MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, - true, new PrincipalSid("joe")); + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); MockAclService service = new MockAclService(); // Insert one permission acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true); service.updateAcl(acl); - acl.insertAce(55, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), - true); + acl.insertAce(55, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true); } @Test public void deleteAceKeepsInitialOrdering() { - MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, - true, new PrincipalSid("joe")); + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); MockAclService service = new MockAclService(); // Add several permissions @@ -197,20 +195,16 @@ public class AclImplTests { // kept acl.deleteAce(0); assertThat(acl.getEntries()).hasSize(2); - assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid( - "ROLE_TEST2")); - assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid( - "ROLE_TEST3")); + assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST2")); + assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST3")); // Add one more permission and remove the permission in the middle acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST4"), true); service.updateAcl(acl); acl.deleteAce(1); assertThat(acl.getEntries()).hasSize(2); - assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid( - "ROLE_TEST2")); - assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid( - "ROLE_TEST4")); + assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST2")); + assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST4")); // Remove remaining permissions acl.deleteAce(1); @@ -221,10 +215,9 @@ public class AclImplTests { @Test public void deleteAceFailsForNonExistentElement() { AclAuthorizationStrategyImpl strategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( - "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); - MutableAcl acl = new AclImpl(objectIdentity, (1), strategy, pgs, null, null, - true, new PrincipalSid("joe")); + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), + new SimpleGrantedAuthority("ROLE_GENERAL")); + MutableAcl acl = new AclImpl(objectIdentity, (1), strategy, pgs, null, null, true, new PrincipalSid("joe")); try { acl.deleteAce(99); fail("It should have thrown NotFoundException"); @@ -235,8 +228,7 @@ public class AclImplTests { @Test public void isGrantingRejectsEmptyParameters() { - MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, - true, new PrincipalSid("joe")); + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); Sid ben = new PrincipalSid("ben"); try { acl.isGranted(new ArrayList<>(0), Arrays.asList(ben), false); @@ -254,28 +246,23 @@ public class AclImplTests { @Test public void isGrantingGrantsAccessForAclWithNoParent() { - Authentication auth = new TestingAuthenticationToken("ben", "ignored", - "ROLE_GENERAL", "ROLE_GUEST"); + Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL", "ROLE_GUEST"); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); ObjectIdentity rootOid = new ObjectIdentityImpl(TARGET_CLASS, 100); // Create an ACL which owner is not the authenticated principal - MutableAcl rootAcl = new AclImpl(rootOid, 1, authzStrategy, pgs, null, null, - false, new PrincipalSid("joe")); + MutableAcl rootAcl = new AclImpl(rootOid, 1, authzStrategy, pgs, null, null, false, new PrincipalSid("joe")); // Grant some permissions rootAcl.insertAce(0, BasePermission.READ, new PrincipalSid("ben"), false); rootAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid("scott"), true); rootAcl.insertAce(2, BasePermission.WRITE, new PrincipalSid("rod"), false); - rootAcl.insertAce(3, BasePermission.WRITE, new GrantedAuthoritySid( - "WRITE_ACCESS_ROLE"), true); + rootAcl.insertAce(3, BasePermission.WRITE, new GrantedAuthoritySid("WRITE_ACCESS_ROLE"), true); // Check permissions granting - List permissions = Arrays.asList(BasePermission.READ, - BasePermission.CREATE); - List sids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid( - "ROLE_GUEST")); + List permissions = Arrays.asList(BasePermission.READ, BasePermission.CREATE); + List sids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid("ROLE_GUEST")); assertThat(rootAcl.isGranted(permissions, sids, false)).isFalse(); try { rootAcl.isGranted(permissions, SCOTT, false); @@ -284,14 +271,14 @@ public class AclImplTests { catch (NotFoundException expected) { } assertThat(rootAcl.isGranted(WRITE, SCOTT, false)).isTrue(); - assertThat(rootAcl.isGranted(WRITE, Arrays.asList(new PrincipalSid("rod"), - new GrantedAuthoritySid("WRITE_ACCESS_ROLE")), false)).isFalse(); - assertThat(rootAcl.isGranted(WRITE, Arrays.asList(new GrantedAuthoritySid( - "WRITE_ACCESS_ROLE"), new PrincipalSid("rod")), false)).isTrue(); + assertThat(rootAcl.isGranted(WRITE, + Arrays.asList(new PrincipalSid("rod"), new GrantedAuthoritySid("WRITE_ACCESS_ROLE")), false)).isFalse(); + assertThat(rootAcl.isGranted(WRITE, + Arrays.asList(new GrantedAuthoritySid("WRITE_ACCESS_ROLE"), new PrincipalSid("rod")), false)).isTrue(); try { // Change the type of the Sid and check the granting process - rootAcl.isGranted(WRITE, Arrays.asList(new GrantedAuthoritySid("rod"), - new PrincipalSid("WRITE_ACCESS_ROLE")), false); + rootAcl.isGranted(WRITE, + Arrays.asList(new GrantedAuthoritySid("rod"), new PrincipalSid("WRITE_ACCESS_ROLE")), false); fail("It should have thrown NotFoundException"); } catch (NotFoundException expected) { @@ -300,8 +287,7 @@ public class AclImplTests { @Test public void isGrantingGrantsAccessForInheritableAcls() { - Authentication auth = new TestingAuthenticationToken("ben", "ignored", - "ROLE_GENERAL"); + Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL"); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100); @@ -312,16 +298,11 @@ public class AclImplTests { // Create ACLs PrincipalSid joe = new PrincipalSid("joe"); - MutableAcl grandParentAcl = new AclImpl(grandParentOid, 1, authzStrategy, pgs, - null, null, false, joe); - MutableAcl parentAcl1 = new AclImpl(parentOid1, 2, authzStrategy, pgs, null, - null, true, joe); - MutableAcl parentAcl2 = new AclImpl(parentOid2, 3, authzStrategy, pgs, null, - null, true, joe); - MutableAcl childAcl1 = new AclImpl(childOid1, 4, authzStrategy, pgs, null, null, - true, joe); - MutableAcl childAcl2 = new AclImpl(childOid2, 4, authzStrategy, pgs, null, null, - false, joe); + MutableAcl grandParentAcl = new AclImpl(grandParentOid, 1, authzStrategy, pgs, null, null, false, joe); + MutableAcl parentAcl1 = new AclImpl(parentOid1, 2, authzStrategy, pgs, null, null, true, joe); + MutableAcl parentAcl2 = new AclImpl(parentOid2, 3, authzStrategy, pgs, null, null, true, joe); + MutableAcl childAcl1 = new AclImpl(childOid1, 4, authzStrategy, pgs, null, null, true, joe); + MutableAcl childAcl2 = new AclImpl(childOid2, 4, authzStrategy, pgs, null, null, false, joe); // Create hierarchies childAcl2.setParent(childAcl1); @@ -330,13 +311,10 @@ public class AclImplTests { parentAcl1.setParent(grandParentAcl); // Add some permissions - grandParentAcl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid( - "ROLE_USER_READ"), true); + grandParentAcl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true); grandParentAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid("ben"), true); - grandParentAcl - .insertAce(2, BasePermission.DELETE, new PrincipalSid("ben"), false); - grandParentAcl.insertAce(3, BasePermission.DELETE, new PrincipalSid("scott"), - true); + grandParentAcl.insertAce(2, BasePermission.DELETE, new PrincipalSid("ben"), false); + grandParentAcl.insertAce(3, BasePermission.DELETE, new PrincipalSid("scott"), true); parentAcl1.insertAce(0, BasePermission.READ, new PrincipalSid("scott"), true); parentAcl1.insertAce(1, BasePermission.DELETE, new PrincipalSid("scott"), false); parentAcl2.insertAce(0, BasePermission.CREATE, new PrincipalSid("ben"), true); @@ -344,8 +322,7 @@ public class AclImplTests { // Check granting process for parent1 assertThat(parentAcl1.isGranted(READ, SCOTT, false)).isTrue(); - assertThat(parentAcl1.isGranted(READ, - Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_USER_READ")), false)) + assertThat(parentAcl1.isGranted(READ, Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_USER_READ")), false)) .isTrue(); assertThat(parentAcl1.isGranted(WRITE, BEN, false)).isTrue(); assertThat(parentAcl1.isGranted(DELETE, BEN, false)).isFalse(); @@ -358,8 +335,7 @@ public class AclImplTests { // Check granting process for child1 assertThat(childAcl1.isGranted(CREATE, SCOTT, false)).isTrue(); - assertThat(childAcl1.isGranted(READ, - Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_USER_READ")), false)) + assertThat(childAcl1.isGranted(READ, Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_USER_READ")), false)) .isTrue(); assertThat(childAcl1.isGranted(DELETE, BEN, false)).isFalse(); @@ -372,8 +348,7 @@ public class AclImplTests { catch (NotFoundException expected) { } try { - childAcl2.isGranted(CREATE, - Arrays.asList((Sid) new PrincipalSid("joe")), false); + childAcl2.isGranted(CREATE, Arrays.asList((Sid) new PrincipalSid("joe")), false); fail("It should have thrown NotFoundException"); } catch (NotFoundException expected) { @@ -382,18 +357,14 @@ public class AclImplTests { @Test public void updatedAceValuesAreCorrectlyReflectedInAcl() { - Authentication auth = new TestingAuthenticationToken("ben", "ignored", - "ROLE_GENERAL"); + Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL"); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); - MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, - false, new PrincipalSid("joe")); + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, false, new PrincipalSid("joe")); MockAclService service = new MockAclService(); - acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), - true); - acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), - true); + acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true); + acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true); acl.insertAce(2, BasePermission.CREATE, new PrincipalSid("ben"), true); service.updateAcl(acl); @@ -414,32 +385,20 @@ public class AclImplTests { @Test public void auditableEntryFlagsAreUpdatedCorrectly() { - Authentication auth = new TestingAuthenticationToken("ben", "ignored", - "ROLE_AUDITING", "ROLE_GENERAL"); + Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_AUDITING", "ROLE_GENERAL"); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); - MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, - false, new PrincipalSid("joe")); + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, false, new PrincipalSid("joe")); MockAclService service = new MockAclService(); - acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), - true); - acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), - true); + acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true); + acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true); service.updateAcl(acl); - assertThat(((AuditableAccessControlEntry) acl.getEntries().get(0)) - .isAuditFailure()) - .isFalse(); - assertThat(((AuditableAccessControlEntry) acl.getEntries().get(1)) - .isAuditFailure()) - .isFalse(); - assertThat(((AuditableAccessControlEntry) acl.getEntries().get(0)) - .isAuditSuccess()) - .isFalse(); - assertThat(((AuditableAccessControlEntry) acl.getEntries().get(1)) - .isAuditSuccess()) - .isFalse(); + assertThat(((AuditableAccessControlEntry) acl.getEntries().get(0)).isAuditFailure()).isFalse(); + assertThat(((AuditableAccessControlEntry) acl.getEntries().get(1)).isAuditFailure()).isFalse(); + assertThat(((AuditableAccessControlEntry) acl.getEntries().get(0)).isAuditSuccess()).isFalse(); + assertThat(((AuditableAccessControlEntry) acl.getEntries().get(1)).isAuditSuccess()).isFalse(); // Change each permission ((AuditableAcl) acl).updateAuditing(0, true, true); @@ -452,21 +411,16 @@ public class AclImplTests { @Test public void gettersAndSettersAreConsistent() { - Authentication auth = new TestingAuthenticationToken("ben", "ignored", - "ROLE_GENERAL"); + Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL"); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, (100)); ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, (101)); - MutableAcl acl = new AclImpl(identity, 1, authzStrategy, pgs, null, null, true, - new PrincipalSid("joe")); - MutableAcl parentAcl = new AclImpl(identity2, 2, authzStrategy, pgs, null, null, - true, new PrincipalSid("joe")); + MutableAcl acl = new AclImpl(identity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); + MutableAcl parentAcl = new AclImpl(identity2, 2, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); MockAclService service = new MockAclService(); - acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), - true); - acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), - true); + acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true); + acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true); service.updateAcl(acl); assertThat(1).isEqualTo(acl.getId()); @@ -488,50 +442,43 @@ public class AclImplTests { @Test public void isSidLoadedBehavesAsExpected() { - List loadedSids = Arrays.asList(new PrincipalSid("ben"), - new GrantedAuthoritySid("ROLE_IGNORED")); - MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, - loadedSids, true, new PrincipalSid("joe")); + List loadedSids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid("ROLE_IGNORED")); + MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, loadedSids, true, + new PrincipalSid("joe")); assertThat(acl.isSidLoaded(loadedSids)).isTrue(); - assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"), - new PrincipalSid("ben")))) - .isTrue(); - assertThat(acl.isSidLoaded(Arrays.asList((Sid) new GrantedAuthoritySid( - "ROLE_IGNORED")))) - .isTrue(); + assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"), new PrincipalSid("ben")))) + .isTrue(); + assertThat(acl.isSidLoaded(Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_IGNORED")))).isTrue(); assertThat(acl.isSidLoaded(BEN)).isTrue(); assertThat(acl.isSidLoaded(null)).isTrue(); assertThat(acl.isSidLoaded(new ArrayList<>(0))).isTrue(); - assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid( - "ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_IGNORED")))) - .isTrue(); - assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid( - "ROLE_GENERAL"), new GrantedAuthoritySid("ROLE_IGNORED")))) - .isFalse(); - assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid( - "ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_GENERAL")))) - .isFalse(); + assertThat(acl.isSidLoaded( + Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_IGNORED")))) + .isTrue(); + assertThat(acl.isSidLoaded( + Arrays.asList(new GrantedAuthoritySid("ROLE_GENERAL"), new GrantedAuthoritySid("ROLE_IGNORED")))) + .isFalse(); + assertThat(acl.isSidLoaded( + Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_GENERAL")))) + .isFalse(); } @Test(expected = NotFoundException.class) public void insertAceRaisesNotFoundExceptionForIndexLessThanZero() { - AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, - true, new PrincipalSid("joe")); + AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); acl.insertAce(-1, mock(Permission.class), mock(Sid.class), true); } @Test(expected = NotFoundException.class) public void deleteAceRaisesNotFoundExceptionForIndexLessThanZero() { - AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, - true, new PrincipalSid("joe")); + AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); acl.deleteAce(-1); } @Test(expected = NotFoundException.class) public void insertAceRaisesNotFoundExceptionForIndexGreaterThanSize() { - AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, - true, new PrincipalSid("joe")); + AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); // Insert at zero, OK. acl.insertAce(0, mock(Permission.class), mock(Sid.class), true); // Size is now 1 @@ -541,8 +488,7 @@ public class AclImplTests { // SEC-1151 @Test(expected = NotFoundException.class) public void deleteAceRaisesNotFoundExceptionForIndexEqualToSize() { - AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, - true, new PrincipalSid("joe")); + AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe")); acl.insertAce(0, mock(Permission.class), mock(Sid.class), true); // Size is now 1 acl.deleteAce(1); @@ -551,11 +497,9 @@ public class AclImplTests { // SEC-1795 @Test public void changingParentIsSuccessful() { - AclImpl parentAcl = new AclImpl(objectIdentity, 1L, authzStrategy, - mockAuditLogger); + AclImpl parentAcl = new AclImpl(objectIdentity, 1L, authzStrategy, mockAuditLogger); AclImpl childAcl = new AclImpl(objectIdentity, 2L, authzStrategy, mockAuditLogger); - AclImpl changeParentAcl = new AclImpl(objectIdentity, 3L, authzStrategy, - mockAuditLogger); + AclImpl changeParentAcl = new AclImpl(objectIdentity, 3L, authzStrategy, mockAuditLogger); childAcl.setParent(parentAcl); childAcl.setParent(changeParentAcl); @@ -566,9 +510,9 @@ public class AclImplTests { public void maskPermissionGrantingStrategy() { DefaultPermissionGrantingStrategy maskPgs = new MaskPermissionGrantingStrategy(mockAuditLogger); MockAclService service = new MockAclService(); - AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, maskPgs, null, null, - true, new PrincipalSid("joe")); - Permission permission = permissionFactory.buildFromMask(BasePermission.READ.getMask() | BasePermission.WRITE.getMask()); + AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, maskPgs, null, null, true, new PrincipalSid("joe")); + Permission permission = permissionFactory + .buildFromMask(BasePermission.READ.getMask() | BasePermission.WRITE.getMask()); Sid sid = new PrincipalSid("ben"); acl.insertAce(0, permission, sid, true); service.updateAcl(acl); @@ -579,20 +523,20 @@ public class AclImplTests { @Test public void hashCodeWithoutStackOverFlow() throws Exception { - //given + // given Sid sid = new PrincipalSid("pSid"); ObjectIdentity oid = new ObjectIdentityImpl("type", 1); AclAuthorizationStrategy authStrategy = new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("role")); PermissionGrantingStrategy grantingStrategy = new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()); - AclImpl acl = new AclImpl(oid, 1L, authStrategy, grantingStrategy, null, null, false, sid); + AclImpl acl = new AclImpl(oid, 1L, authStrategy, grantingStrategy, null, null, false, sid); AccessControlEntryImpl ace = new AccessControlEntryImpl(1L, acl, sid, BasePermission.READ, true, true, true); - Field fieldAces = FieldUtils.getField(AclImpl.class, "aces"); + Field fieldAces = FieldUtils.getField(AclImpl.class, "aces"); fieldAces.setAccessible(true); List aces = (List) fieldAces.get(acl); aces.add(ace); - //when - then none StackOverFlowError been raised + // when - then none StackOverFlowError been raised ace.hashCode(); } @@ -600,6 +544,7 @@ public class AclImplTests { // ================================================================================================== private static class MaskPermissionGrantingStrategy extends DefaultPermissionGrantingStrategy { + MaskPermissionGrantingStrategy(AuditLogger auditLogger) { super(auditLogger); } @@ -611,25 +556,24 @@ public class AclImplTests { } return super.isGranted(ace, p); } + } private class MockAclService implements MutableAclService { - public MutableAcl createAcl(ObjectIdentity objectIdentity) - throws AlreadyExistsException { + + public MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException { return null; } - public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) - throws ChildrenExistException { + public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException { } /* * Mock implementation that populates the aces list with fully initialized * AccessControlEntries * - * @see - * org.springframework.security.acls.MutableAclService#updateAcl(org.springframework - * .security.acls.MutableAcl) + * @see org.springframework.security.acls.MutableAclService#updateAcl(org. + * springframework .security.acls.MutableAcl) */ @SuppressWarnings("unchecked") public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException { @@ -645,9 +589,8 @@ public class AclImplTests { AccessControlEntry ac = oldAces.get(i); // Just give an ID to all this acl's aces, rest of the fields are just // copied - newAces.add(new AccessControlEntryImpl((i + 1), ac.getAcl(), ac - .getSid(), ac.getPermission(), ac.isGranting(), - ((AuditableAccessControlEntry) ac).isAuditSuccess(), + newAces.add(new AccessControlEntryImpl((i + 1), ac.getAcl(), ac.getSid(), ac.getPermission(), + ac.isGranting(), ((AuditableAccessControlEntry) ac).isAuditSuccess(), ((AuditableAccessControlEntry) ac).isAuditFailure())); } } @@ -666,19 +609,19 @@ public class AclImplTests { return null; } - public Acl readAclById(ObjectIdentity object, List sids) + public Acl readAclById(ObjectIdentity object, List sids) throws NotFoundException { + return null; + } + + public Map readAclsById(List objects) throws NotFoundException { + return null; + } + + public Map readAclsById(List objects, List sids) throws NotFoundException { return null; } - public Map readAclsById(List objects) - throws NotFoundException { - return null; - } - - public Map readAclsById(List objects, - List sids) throws NotFoundException { - return null; - } } + } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/AclImplementationSecurityCheckTests.java b/acl/src/test/java/org/springframework/security/acls/domain/AclImplementationSecurityCheckTests.java index 0eab9940ac..a20536c691 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/AclImplementationSecurityCheckTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/AclImplementationSecurityCheckTests.java @@ -35,6 +35,7 @@ import org.springframework.security.core.context.SecurityContextHolder; * @author Andrei Stefan */ public class AclImplementationSecurityCheckTests { + private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; // ~ Methods @@ -52,50 +53,42 @@ public class AclImplementationSecurityCheckTests { @Test public void testSecurityCheckNoACEs() { - Authentication auth = new TestingAuthenticationToken("user", "password", - "ROLE_GENERAL", "ROLE_AUDITING", "ROLE_OWNERSHIP"); + Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL", "ROLE_AUDITING", + "ROLE_OWNERSHIP"); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L); AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( - "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), + new SimpleGrantedAuthority("ROLE_GENERAL")); - Acl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, - new ConsoleAuditLogger()); + Acl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger()); - aclAuthorizationStrategy.securityCheck(acl, - AclAuthorizationStrategy.CHANGE_GENERAL); - aclAuthorizationStrategy.securityCheck(acl, - AclAuthorizationStrategy.CHANGE_AUDITING); - aclAuthorizationStrategy.securityCheck(acl, - AclAuthorizationStrategy.CHANGE_OWNERSHIP); + aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_GENERAL); + aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_AUDITING); + aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_OWNERSHIP); // Create another authorization strategy AclAuthorizationStrategy aclAuthorizationStrategy2 = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority( - "ROLE_TWO"), new SimpleGrantedAuthority("ROLE_THREE")); - Acl acl2 = new AclImpl(identity, 1L, aclAuthorizationStrategy2, - new ConsoleAuditLogger()); + new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority("ROLE_TWO"), + new SimpleGrantedAuthority("ROLE_THREE")); + Acl acl2 = new AclImpl(identity, 1L, aclAuthorizationStrategy2, new ConsoleAuditLogger()); // Check access in case the principal has no authorization rights try { - aclAuthorizationStrategy2.securityCheck(acl2, - AclAuthorizationStrategy.CHANGE_GENERAL); + aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_GENERAL); fail("It should have thrown NotFoundException"); } catch (NotFoundException expected) { } try { - aclAuthorizationStrategy2.securityCheck(acl2, - AclAuthorizationStrategy.CHANGE_AUDITING); + aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_AUDITING); fail("It should have thrown NotFoundException"); } catch (NotFoundException expected) { } try { - aclAuthorizationStrategy2.securityCheck(acl2, - AclAuthorizationStrategy.CHANGE_OWNERSHIP); + aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_OWNERSHIP); fail("It should have thrown NotFoundException"); } catch (NotFoundException expected) { @@ -105,54 +98,46 @@ public class AclImplementationSecurityCheckTests { @Test public void testSecurityCheckWithMultipleACEs() { // Create a simple authentication with ROLE_GENERAL - Authentication auth = new TestingAuthenticationToken("user", "password", - "ROLE_GENERAL"); + Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL"); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L); // Authorization strategy will require a different role for each access AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( - "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), + new SimpleGrantedAuthority("ROLE_GENERAL")); // Let's give the principal the ADMINISTRATION permission, without // granting access - MutableAcl aclFirstDeny = new AclImpl(identity, 1L, - aclAuthorizationStrategy, new ConsoleAuditLogger()); - aclFirstDeny.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), - false); + MutableAcl aclFirstDeny = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger()); + aclFirstDeny.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), false); // The CHANGE_GENERAL test should pass as the principal has ROLE_GENERAL - aclAuthorizationStrategy.securityCheck(aclFirstDeny, - AclAuthorizationStrategy.CHANGE_GENERAL); + aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_GENERAL); // The CHANGE_AUDITING and CHANGE_OWNERSHIP should fail since the // principal doesn't have these authorities, // nor granting access try { - aclAuthorizationStrategy.securityCheck(aclFirstDeny, - AclAuthorizationStrategy.CHANGE_AUDITING); + aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_AUDITING); fail("It should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { } try { - aclAuthorizationStrategy.securityCheck(aclFirstDeny, - AclAuthorizationStrategy.CHANGE_OWNERSHIP); + aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_OWNERSHIP); fail("It should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { } // Add granting access to this principal - aclFirstDeny.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), - true); + aclFirstDeny.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true); // and try again for CHANGE_AUDITING - the first ACE's granting flag // (false) will deny this access try { - aclAuthorizationStrategy.securityCheck(aclFirstDeny, - AclAuthorizationStrategy.CHANGE_AUDITING); + aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_AUDITING); fail("It should have thrown AccessDeniedException"); } catch (AccessDeniedException expected) { @@ -160,23 +145,18 @@ public class AclImplementationSecurityCheckTests { // Create another ACL and give the principal the ADMINISTRATION // permission, with granting access - MutableAcl aclFirstAllow = new AclImpl(identity, 1L, - aclAuthorizationStrategy, new ConsoleAuditLogger()); - aclFirstAllow.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), - true); + MutableAcl aclFirstAllow = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger()); + aclFirstAllow.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true); // The CHANGE_AUDITING test should pass as there is one ACE with // granting access - aclAuthorizationStrategy.securityCheck(aclFirstAllow, - AclAuthorizationStrategy.CHANGE_AUDITING); + aclAuthorizationStrategy.securityCheck(aclFirstAllow, AclAuthorizationStrategy.CHANGE_AUDITING); // Add a deny ACE and test again for CHANGE_AUDITING - aclFirstAllow.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), - false); + aclFirstAllow.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), false); try { - aclAuthorizationStrategy.securityCheck(aclFirstAllow, - AclAuthorizationStrategy.CHANGE_AUDITING); + aclAuthorizationStrategy.securityCheck(aclFirstAllow, AclAuthorizationStrategy.CHANGE_AUDITING); } catch (AccessDeniedException notExpected) { @@ -184,11 +164,9 @@ public class AclImplementationSecurityCheckTests { } // Create an ACL with no ACE - MutableAcl aclNoACE = new AclImpl(identity, 1L, - aclAuthorizationStrategy, new ConsoleAuditLogger()); + MutableAcl aclNoACE = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger()); try { - aclAuthorizationStrategy.securityCheck(aclNoACE, - AclAuthorizationStrategy.CHANGE_AUDITING); + aclAuthorizationStrategy.securityCheck(aclNoACE, AclAuthorizationStrategy.CHANGE_AUDITING); fail("It should have thrown NotFoundException"); } catch (NotFoundException expected) { @@ -196,8 +174,7 @@ public class AclImplementationSecurityCheckTests { } // and still grant access for CHANGE_GENERAL try { - aclAuthorizationStrategy.securityCheck(aclNoACE, - AclAuthorizationStrategy.CHANGE_GENERAL); + aclAuthorizationStrategy.securityCheck(aclNoACE, AclAuthorizationStrategy.CHANGE_GENERAL); } catch (NotFoundException expected) { @@ -208,31 +185,26 @@ public class AclImplementationSecurityCheckTests { @Test public void testSecurityCheckWithInheritableACEs() { // Create a simple authentication with ROLE_GENERAL - Authentication auth = new TestingAuthenticationToken("user", "password", - "ROLE_GENERAL"); + Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL"); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100); // Authorization strategy will require a different role for each access AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority( - "ROLE_TWO"), new SimpleGrantedAuthority("ROLE_GENERAL")); + new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority("ROLE_TWO"), + new SimpleGrantedAuthority("ROLE_GENERAL")); // Let's give the principal an ADMINISTRATION permission, with granting // access - MutableAcl parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, - new ConsoleAuditLogger()); - parentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), - true); - MutableAcl childAcl = new AclImpl(identity, 2, aclAuthorizationStrategy, - new ConsoleAuditLogger()); + MutableAcl parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, new ConsoleAuditLogger()); + parentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true); + MutableAcl childAcl = new AclImpl(identity, 2, aclAuthorizationStrategy, new ConsoleAuditLogger()); // Check against the 'child' acl, which doesn't offer any authorization // rights on CHANGE_OWNERSHIP try { - aclAuthorizationStrategy.securityCheck(childAcl, - AclAuthorizationStrategy.CHANGE_OWNERSHIP); + aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP); fail("It should have thrown NotFoundException"); } catch (NotFoundException expected) { @@ -244,8 +216,7 @@ public class AclImplementationSecurityCheckTests { childAcl.setParent(parentAcl); childAcl.setEntriesInheriting(true); try { - aclAuthorizationStrategy.securityCheck(childAcl, - AclAuthorizationStrategy.CHANGE_OWNERSHIP); + aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP); } catch (NotFoundException expected) { @@ -253,18 +224,14 @@ public class AclImplementationSecurityCheckTests { } // Create a root parent and link it to the middle parent - MutableAcl rootParentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, - new ConsoleAuditLogger()); - parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, - new ConsoleAuditLogger()); - rootParentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), - true); + MutableAcl rootParentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, new ConsoleAuditLogger()); + parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, new ConsoleAuditLogger()); + rootParentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true); parentAcl.setEntriesInheriting(true); parentAcl.setParent(rootParentAcl); childAcl.setParent(parentAcl); try { - aclAuthorizationStrategy.securityCheck(childAcl, - AclAuthorizationStrategy.CHANGE_OWNERSHIP); + aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP); } catch (NotFoundException expected) { @@ -274,39 +241,36 @@ public class AclImplementationSecurityCheckTests { @Test public void testSecurityCheckPrincipalOwner() { - Authentication auth = new TestingAuthenticationToken("user", "password", - "ROLE_ONE"); + Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_ONE"); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100); AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( - "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), + new SimpleGrantedAuthority("ROLE_GENERAL")); Acl acl = new AclImpl(identity, 1, aclAuthorizationStrategy, - new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), null, - null, false, new PrincipalSid(auth)); + new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), null, null, false, + new PrincipalSid(auth)); try { - aclAuthorizationStrategy.securityCheck(acl, - AclAuthorizationStrategy.CHANGE_GENERAL); + aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_GENERAL); } catch (AccessDeniedException notExpected) { fail("It shouldn't have thrown AccessDeniedException"); } try { - aclAuthorizationStrategy.securityCheck(acl, - AclAuthorizationStrategy.CHANGE_AUDITING); + aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_AUDITING); fail("It shouldn't have thrown AccessDeniedException"); } catch (NotFoundException expected) { } try { - aclAuthorizationStrategy.securityCheck(acl, - AclAuthorizationStrategy.CHANGE_OWNERSHIP); + aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_OWNERSHIP); } catch (AccessDeniedException notExpected) { fail("It shouldn't have thrown AccessDeniedException"); } } + } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/AuditLoggerTests.java b/acl/src/test/java/org/springframework/security/acls/domain/AuditLoggerTests.java index 001e0450e3..3cd3daba23 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/AuditLoggerTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/AuditLoggerTests.java @@ -33,11 +33,15 @@ import org.springframework.security.acls.model.AuditableAccessControlEntry; * @author Andrei Stefan */ public class AuditLoggerTests { + // ~ Instance fields // ================================================================================================ private PrintStream console; + private ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + private ConsoleAuditLogger logger; + private AuditableAccessControlEntry ace; // ~ Methods @@ -92,4 +96,5 @@ public class AuditLoggerTests { logger.logIfNeeded(false, ace); assertThat(bytes.toString()).startsWith("DENIED due to ACE"); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityImplTests.java b/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityImplTests.java index 93adac3837..a66c933441 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityImplTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityImplTests.java @@ -141,8 +141,7 @@ public class ObjectIdentityImplTests { assertThat(obj).isNotEqualTo("DIFFERENT_OBJECT_TYPE"); assertThat(obj).isNotEqualTo(new ObjectIdentityImpl(DOMAIN_CLASS, 2L)); assertThat(obj).isNotEqualTo(new ObjectIdentityImpl( - "org.springframework.security.acls.domain.ObjectIdentityImplTests$MockOtherIdDomainObject", - 1L)); + "org.springframework.security.acls.domain.ObjectIdentityImplTests$MockOtherIdDomainObject", 1L)); assertThat(new ObjectIdentityImpl(DOMAIN_CLASS, 1L)).isEqualTo(obj); assertThat(new ObjectIdentityImpl(mockObj)).isEqualTo(obj); } @@ -182,6 +181,7 @@ public class ObjectIdentityImplTests { // ================================================================================================== private class MockIdDomainObject { + private Object id; public Object getId() { @@ -191,9 +191,11 @@ public class ObjectIdentityImplTests { public void setId(Object id) { this.id = id; } + } private class MockOtherIdDomainObject { + private Object id; public Object getId() { @@ -203,5 +205,7 @@ public class ObjectIdentityImplTests { public void setId(Object id) { this.id = id; } + } + } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImplTests.java b/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImplTests.java index 67e068c947..7164690017 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImplTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityRetrievalStrategyImplTests.java @@ -56,5 +56,7 @@ public class ObjectIdentityRetrievalStrategyImplTests { public void setId(Object id) { this.id = id; } + } + } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/PermissionTests.java b/acl/src/test/java/org/springframework/security/acls/domain/PermissionTests.java index f71c50755d..af6f1ed928 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/PermissionTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/PermissionTests.java @@ -45,14 +45,10 @@ public class PermissionTests { public void expectedIntegerValues() { assertThat(BasePermission.READ.getMask()).isEqualTo(1); assertThat(BasePermission.ADMINISTRATION.getMask()).isEqualTo(16); - assertThat( - new CumulativePermission().set(BasePermission.READ) - .set(BasePermission.WRITE).set(BasePermission.CREATE).getMask()) - .isEqualTo(7); - assertThat( - new CumulativePermission().set(BasePermission.READ) - .set(BasePermission.ADMINISTRATION).getMask()) - .isEqualTo(17); + assertThat(new CumulativePermission().set(BasePermission.READ).set(BasePermission.WRITE) + .set(BasePermission.CREATE).getMask()).isEqualTo(7); + assertThat(new CumulativePermission().set(BasePermission.READ).set(BasePermission.ADMINISTRATION).getMask()) + .isEqualTo(17); } @Test @@ -65,33 +61,28 @@ public class PermissionTests { public void stringConversion() { permissionFactory.registerPublicPermissions(SpecialPermission.class); - assertThat(BasePermission.READ.toString()) - .isEqualTo("BasePermission[...............................R=1]"); + assertThat(BasePermission.READ.toString()).isEqualTo("BasePermission[...............................R=1]"); + + assertThat(BasePermission.ADMINISTRATION.toString()) + .isEqualTo("BasePermission[...........................A....=16]"); + + assertThat(new CumulativePermission().set(BasePermission.READ).toString()) + .isEqualTo("CumulativePermission[...............................R=1]"); assertThat( - BasePermission.ADMINISTRATION.toString()) - .isEqualTo("BasePermission[...........................A....=16]"); + new CumulativePermission().set(SpecialPermission.ENTER).set(BasePermission.ADMINISTRATION).toString()) + .isEqualTo("CumulativePermission[..........................EA....=48]"); - assertThat( - new CumulativePermission().set(BasePermission.READ).toString()) - .isEqualTo("CumulativePermission[...............................R=1]"); + assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ).toString()) + .isEqualTo("CumulativePermission[...........................A...R=17]"); - assertThat(new CumulativePermission().set(SpecialPermission.ENTER) - .set(BasePermission.ADMINISTRATION).toString()) - .isEqualTo("CumulativePermission[..........................EA....=48]"); + assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ) + .clear(BasePermission.ADMINISTRATION).toString()) + .isEqualTo("CumulativePermission[...............................R=1]"); - assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION) - .set(BasePermission.READ).toString()) - .isEqualTo("CumulativePermission[...........................A...R=17]"); - - assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION) - .set(BasePermission.READ).clear(BasePermission.ADMINISTRATION) - .toString()) - .isEqualTo("CumulativePermission[...............................R=1]"); - - assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION) - .set(BasePermission.READ).clear(BasePermission.ADMINISTRATION) - .clear(BasePermission.READ).toString()) - .isEqualTo("CumulativePermission[................................=0]"); + assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ) + .clear(BasePermission.ADMINISTRATION).clear(BasePermission.READ).toString()) + .isEqualTo("CumulativePermission[................................=0]"); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/domain/SpecialPermission.java b/acl/src/test/java/org/springframework/security/acls/domain/SpecialPermission.java index 0aedb10afe..c6ebb59d02 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/SpecialPermission.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/SpecialPermission.java @@ -23,10 +23,13 @@ import org.springframework.security.acls.model.Permission; * @author Ben Alex */ public class SpecialPermission extends BasePermission { + public static final Permission ENTER = new SpecialPermission(1 << 5, 'E'); // 32 + public static final Permission LEAVE = new SpecialPermission(1 << 6, 'L'); protected SpecialPermission(int mask, char code) { super(mask, code); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/AbstractBasicLookupStrategyTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/AbstractBasicLookupStrategyTests.java index a2cefecab5..7c95c5dfbf 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/AbstractBasicLookupStrategyTests.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/AbstractBasicLookupStrategyTests.java @@ -47,15 +47,20 @@ import javax.sql.DataSource; public abstract class AbstractBasicLookupStrategyTests { protected static final Sid BEN_SID = new PrincipalSid("ben"); + protected static final String TARGET_CLASS = TargetObject.class.getName(); + protected static final String TARGET_CLASS_WITH_UUID = TargetObjectWithUUID.class.getName(); + protected static final UUID OBJECT_IDENTITY_UUID = UUID.randomUUID(); + protected static final Long OBJECT_IDENTITY_LONG_AS_UUID = 110L; // ~ Instance fields // ================================================================================================ private BasicLookupStrategy strategy; + private static CacheManager cacheManager; // ~ Methods @@ -80,44 +85,41 @@ public abstract class AbstractBasicLookupStrategyTests { @Before public void populateDatabase() { String query = "INSERT INTO acl_sid(ID,PRINCIPAL,SID) VALUES (1,1,'ben');" - + "INSERT INTO acl_class(ID,CLASS) VALUES (2,'" + TARGET_CLASS + "');" - + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (1,2,100,null,1,1);" - + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (2,2,101,1,1,1);" - + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (3,2,102,2,1,1);" - + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (1,1,0,1,1,1,0,0);" - + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (2,1,1,1,2,0,0,0);" - + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (3,2,0,1,8,1,0,0);" - + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (4,3,0,1,8,0,0,0);"; + + "INSERT INTO acl_class(ID,CLASS) VALUES (2,'" + TARGET_CLASS + "');" + + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (1,2,100,null,1,1);" + + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (2,2,101,1,1,1);" + + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (3,2,102,2,1,1);" + + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (1,1,0,1,1,1,0,0);" + + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (2,1,1,1,2,0,0,0);" + + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (3,2,0,1,8,1,0,0);" + + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (4,3,0,1,8,0,0,0);"; getJdbcTemplate().execute(query); } @Before public void initializeBeans() { strategy = new BasicLookupStrategy(getDataSource(), aclCache(), aclAuthStrategy(), - new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger())); + new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger())); strategy.setPermissionFactory(new DefaultPermissionFactory()); } protected AclAuthorizationStrategy aclAuthStrategy() { - return new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_ADMINISTRATOR")); + return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_ADMINISTRATOR")); } protected EhCacheBasedAclCache aclCache() { - return new EhCacheBasedAclCache(getCache(), - new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), - new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER"))); + return new EhCacheBasedAclCache(getCache(), new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), + new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER"))); } - @After public void emptyDatabase() { String query = "DELETE FROM acl_entry;" + "DELETE FROM acl_object_identity WHERE ID = 9;" - + "DELETE FROM acl_object_identity WHERE ID = 8;" + "DELETE FROM acl_object_identity WHERE ID = 7;" - + "DELETE FROM acl_object_identity WHERE ID = 6;" + "DELETE FROM acl_object_identity WHERE ID = 5;" - + "DELETE FROM acl_object_identity WHERE ID = 4;" + "DELETE FROM acl_object_identity WHERE ID = 3;" - + "DELETE FROM acl_object_identity WHERE ID = 2;" + "DELETE FROM acl_object_identity WHERE ID = 1;" - + "DELETE FROM acl_class;" + "DELETE FROM acl_sid;"; + + "DELETE FROM acl_object_identity WHERE ID = 8;" + "DELETE FROM acl_object_identity WHERE ID = 7;" + + "DELETE FROM acl_object_identity WHERE ID = 6;" + "DELETE FROM acl_object_identity WHERE ID = 5;" + + "DELETE FROM acl_object_identity WHERE ID = 4;" + "DELETE FROM acl_object_identity WHERE ID = 3;" + + "DELETE FROM acl_object_identity WHERE ID = 2;" + "DELETE FROM acl_object_identity WHERE ID = 1;" + + "DELETE FROM acl_class;" + "DELETE FROM acl_sid;"; getJdbcTemplate().execute(query); } @@ -135,7 +137,7 @@ public abstract class AbstractBasicLookupStrategyTests { ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 102); Map map = this.strategy - .readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); + .readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); checkEntries(topParentOid, middleParentOid, childOid, map); } @@ -151,7 +153,7 @@ public abstract class AbstractBasicLookupStrategyTests { // Let's empty the database to force acls retrieval from cache emptyDatabase(); Map map = this.strategy - .readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); + .readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); checkEntries(topParentOid, middleParentOid, childOid, map); } @@ -166,12 +168,12 @@ public abstract class AbstractBasicLookupStrategyTests { // acls this.strategy.setBatchSize(1); Map map = this.strategy - .readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); + .readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); checkEntries(topParentOid, middleParentOid, childOid, map); } private void checkEntries(ObjectIdentity topParentOid, ObjectIdentity middleParentOid, ObjectIdentity childOid, - Map map) { + Map map) { assertThat(map).hasSize(3); MutableAcl topParent = (MutableAcl) map.get(topParentOid); @@ -268,10 +270,10 @@ public abstract class AbstractBasicLookupStrategyTests { @Test public void testReadAllObjectIdentitiesWhenLastElementIsAlreadyCached() { String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,105,null,1,1);" - + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (7,2,106,6,1,1);" - + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (8,2,107,6,1,1);" - + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (9,2,108,7,1,1);" - + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (7,6,0,1,1,1,0,0)"; + + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (7,2,106,6,1,1);" + + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (8,2,107,6,1,1);" + + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (9,2,108,7,1,1);" + + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (7,6,0,1,1,1,0,0)"; getJdbcTemplate().execute(query); ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, 104L); @@ -302,7 +304,8 @@ public abstract class AbstractBasicLookupStrategyTests { try { foundAcls = strategy.readAclsById(allOids, sids); - } catch (NotFoundException notExpected) { + } + catch (NotFoundException notExpected) { fail("It shouldn't have thrown NotFoundException"); } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/AclClassIdUtilsTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/AclClassIdUtilsTests.java index d41341c466..ecc16ffa3d 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/AclClassIdUtilsTests.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/AclClassIdUtilsTests.java @@ -15,7 +15,6 @@ */ package org.springframework.security.acls.jdbc; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -34,17 +33,21 @@ import static org.mockito.BDDMockito.given; /** * Tests for {@link AclClassIdUtils}. + * * @author paulwheeler */ @RunWith(MockitoJUnitRunner.class) public class AclClassIdUtilsTests { private static final Long DEFAULT_IDENTIFIER = 999L; + private static final BigInteger BIGINT_IDENTIFIER = new BigInteger("999"); + private static final String DEFAULT_IDENTIFIER_AS_STRING = DEFAULT_IDENTIFIER.toString(); @Mock private ResultSet resultSet; + @Mock private ConversionService conversionService; @@ -172,4 +175,5 @@ public class AclClassIdUtilsTests { // when aclClassIdUtils.setConversionService(null); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTests.java index 4f5f7c13a7..2116fdb0bf 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTests.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTests.java @@ -28,8 +28,8 @@ import org.springframework.jdbc.core.JdbcTemplate; * @author Paul Wheeler */ public class BasicLookupStrategyTests extends AbstractBasicLookupStrategyTests { - private static final BasicLookupStrategyTestsDbHelper DATABASE_HELPER = new BasicLookupStrategyTestsDbHelper(); + private static final BasicLookupStrategyTestsDbHelper DATABASE_HELPER = new BasicLookupStrategyTestsDbHelper(); @BeforeClass public static void createDatabase() throws Exception { @@ -50,4 +50,5 @@ public class BasicLookupStrategyTests extends AbstractBasicLookupStrategyTests { public DataSource getDataSource() { return DATABASE_HELPER.getDataSource(); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTestsDbHelper.java b/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTestsDbHelper.java index 8c1f7042dc..c181522900 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTestsDbHelper.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyTestsDbHelper.java @@ -23,15 +23,20 @@ import org.springframework.util.FileCopyUtils; /** * Helper class to initialize the database for BasicLookupStrategyTests. + * * @author Andrei Stefan * @author Paul Wheeler */ public class BasicLookupStrategyTestsDbHelper { + private static final String ACL_SCHEMA_SQL_FILE = "createAclSchema.sql"; + private static final String ACL_SCHEMA_SQL_FILE_WITH_ACL_CLASS_ID = "createAclSchemaWithAclClassIdType.sql"; private SingleConnectionDataSource dataSource; + private JdbcTemplate jdbcTemplate; + private boolean withAclClassIdType; public BasicLookupStrategyTestsDbHelper() { @@ -48,7 +53,8 @@ public class BasicLookupStrategyTestsDbHelper { if (!withAclClassIdType) { connectionUrl = "jdbc:hsqldb:mem:lookupstrategytest"; sqlClassPathResource = ACL_SCHEMA_SQL_FILE; - } else { + } + else { connectionUrl = "jdbc:hsqldb:mem:lookupstrategytestWithAclClassIdType"; sqlClassPathResource = ACL_SCHEMA_SQL_FILE_WITH_ACL_CLASS_ID; @@ -69,4 +75,5 @@ public class BasicLookupStrategyTestsDbHelper { public SingleConnectionDataSource getDataSource() { return dataSource; } + } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyWithAclClassTypeTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyWithAclClassTypeTests.java index 60ca2508f7..9ac5360675 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyWithAclClassTypeTests.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/BasicLookupStrategyWithAclClassTypeTests.java @@ -71,7 +71,7 @@ public class BasicLookupStrategyWithAclClassTypeTests extends AbstractBasicLooku public void initializeBeans() { super.initializeBeans(); uuidEnabledStrategy = new BasicLookupStrategy(getDataSource(), aclCache(), aclAuthStrategy(), - new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger())); + new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger())); uuidEnabledStrategy.setPermissionFactory(new DefaultPermissionFactory()); uuidEnabledStrategy.setAclClassIdSupported(true); uuidEnabledStrategy.setConversionService(new DefaultConversionService()); @@ -79,22 +79,22 @@ public class BasicLookupStrategyWithAclClassTypeTests extends AbstractBasicLooku @Before public void populateDatabaseForAclClassTypeTests() { - String query = "INSERT INTO acl_class(ID,CLASS,CLASS_ID_TYPE) VALUES (3,'" - + TARGET_CLASS_WITH_UUID - + "', 'java.util.UUID');" - + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,3,'" - + OBJECT_IDENTITY_UUID.toString() + "',null,1,1);" - + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (5,3,'" - + OBJECT_IDENTITY_LONG_AS_UUID + "',null,1,1);" - + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (5,4,0,1,8,0,0,0);" - + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (6,5,0,1,8,0,0,0);"; + String query = "INSERT INTO acl_class(ID,CLASS,CLASS_ID_TYPE) VALUES (3,'" + TARGET_CLASS_WITH_UUID + + "', 'java.util.UUID');" + + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,3,'" + + OBJECT_IDENTITY_UUID.toString() + "',null,1,1);" + + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (5,3,'" + + OBJECT_IDENTITY_LONG_AS_UUID + "',null,1,1);" + + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (5,4,0,1,8,0,0,0);" + + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (6,5,0,1,8,0,0,0);"; DATABASE_HELPER.getJdbcTemplate().execute(query); } @Test public void testReadObjectIdentityUsingUuidType() { ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, OBJECT_IDENTITY_UUID); - Map foundAcls = uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID)); + Map foundAcls = uuidEnabledStrategy.readAclsById(Arrays.asList(oid), + Arrays.asList(BEN_SID)); Assert.assertEquals(1, foundAcls.size()); Assert.assertNotNull(foundAcls.get(oid)); } @@ -102,7 +102,8 @@ public class BasicLookupStrategyWithAclClassTypeTests extends AbstractBasicLooku @Test public void testReadObjectIdentityUsingLongTypeWithConversionServiceEnabled() { ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, 100L); - Map foundAcls = uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID)); + Map foundAcls = uuidEnabledStrategy.readAclsById(Arrays.asList(oid), + Arrays.asList(BEN_SID)); Assert.assertEquals(1, foundAcls.size()); Assert.assertNotNull(foundAcls.get(oid)); } @@ -112,4 +113,5 @@ public class BasicLookupStrategyWithAclClassTypeTests extends AbstractBasicLooku ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, OBJECT_IDENTITY_LONG_AS_UUID); uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID)); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/DatabaseSeeder.java b/acl/src/test/java/org/springframework/security/acls/jdbc/DatabaseSeeder.java index d8170b3081..4533e58966 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/DatabaseSeeder.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/DatabaseSeeder.java @@ -32,6 +32,7 @@ import javax.sql.DataSource; * @author Ben Alex */ public class DatabaseSeeder { + // ~ Constructors // =================================================================================================== @@ -43,4 +44,5 @@ public class DatabaseSeeder { String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream())); template.execute(sql); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/EhCacheBasedAclCacheTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/EhCacheBasedAclCacheTests.java index 1e90a4ddc0..7cec850f45 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/EhCacheBasedAclCacheTests.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/EhCacheBasedAclCacheTests.java @@ -54,10 +54,12 @@ import org.springframework.test.util.ReflectionTestUtils; */ @RunWith(MockitoJUnitRunner.class) public class EhCacheBasedAclCacheTests { + private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; @Mock private Ehcache cache; + @Captor private ArgumentCaptor element; @@ -67,17 +69,15 @@ public class EhCacheBasedAclCacheTests { @Before public void setup() { - myCache = new EhCacheBasedAclCache(cache, new DefaultPermissionGrantingStrategy( - new ConsoleAuditLogger()), new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_USER"))); + myCache = new EhCacheBasedAclCache(cache, new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), + new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER"))); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L); AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( - "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), + new SimpleGrantedAuthority("ROLE_GENERAL")); - acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, - new ConsoleAuditLogger()); + acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger()); } @After @@ -87,9 +87,8 @@ public class EhCacheBasedAclCacheTests { @Test(expected = IllegalArgumentException.class) public void constructorRejectsNullParameters() { - new EhCacheBasedAclCache(null, new DefaultPermissionGrantingStrategy( - new ConsoleAuditLogger()), new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_USER"))); + new EhCacheBasedAclCache(null, new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), + new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER"))); } @Test @@ -152,12 +151,10 @@ public class EhCacheBasedAclCacheTests { assertThat(retrieved).isEqualTo(acl); - Object retrieved1 = FieldUtils.getProtectedFieldValue("aclAuthorizationStrategy", - retrieved); + Object retrieved1 = FieldUtils.getProtectedFieldValue("aclAuthorizationStrategy", retrieved); assertThat(retrieved1).isNull(); - Object retrieved2 = FieldUtils.getProtectedFieldValue( - "permissionGrantingStrategy", retrieved); + Object retrieved2 = FieldUtils.getProtectedFieldValue("permissionGrantingStrategy", retrieved); assertThat(retrieved2).isNull(); } @@ -175,25 +172,21 @@ public class EhCacheBasedAclCacheTests { verify(cache, times(2)).put(element.capture()); assertThat(element.getValue().getKey()).isEqualTo(acl.getId()); assertThat(element.getValue().getObjectValue()).isEqualTo(acl); - assertThat(element.getAllValues().get(0).getKey()).isEqualTo( - acl.getObjectIdentity()); + assertThat(element.getAllValues().get(0).getKey()).isEqualTo(acl.getObjectIdentity()); assertThat(element.getAllValues().get(0).getObjectValue()).isEqualTo(acl); } @Test public void putInCacheAclWithParent() { - Authentication auth = new TestingAuthenticationToken("user", "password", - "ROLE_GENERAL"); + Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL"); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, - 2L); + ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, 2L); AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( - "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); - MutableAcl parentAcl = new AclImpl(identityParent, 2L, - aclAuthorizationStrategy, new ConsoleAuditLogger()); + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), + new SimpleGrantedAuthority("ROLE_GENERAL")); + MutableAcl parentAcl = new AclImpl(identityParent, 2L, aclAuthorizationStrategy, new ConsoleAuditLogger()); acl.setParent(parentAcl); myCache.putInCache(acl); @@ -233,10 +226,8 @@ public class EhCacheBasedAclCacheTests { MutableAcl fromCache = myCache.getFromCache(acl.getId()); - assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")) - .isNotNull(); - assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy")) - .isNotNull(); + assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")).isNotNull(); + assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy")).isNotNull(); } @Test @@ -248,8 +239,7 @@ public class EhCacheBasedAclCacheTests { @Test public void getFromCacheObjectIdentityPopulatesTransient() { - when(cache.get(acl.getObjectIdentity())) - .thenReturn(new Element(acl.getId(), acl)); + when(cache.get(acl.getObjectIdentity())).thenReturn(new Element(acl.getId(), acl)); myCache.putInCache(acl); @@ -258,16 +248,13 @@ public class EhCacheBasedAclCacheTests { MutableAcl fromCache = myCache.getFromCache(acl.getObjectIdentity()); - assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")) - .isNotNull(); - assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy")) - .isNotNull(); + assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")).isNotNull(); + assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy")).isNotNull(); } @Test public void evictCacheSerializable() { - when(cache.get(acl.getObjectIdentity())) - .thenReturn(new Element(acl.getId(), acl)); + when(cache.get(acl.getObjectIdentity())).thenReturn(new Element(acl.getId(), acl)); myCache.evictFromCache(acl.getObjectIdentity()); @@ -284,4 +271,5 @@ public class EhCacheBasedAclCacheTests { verify(cache).remove(acl.getId()); verify(cache).remove(acl.getObjectIdentity()); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcAclServiceTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcAclServiceTests.java index b039e4d656..2ce64f73c2 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcAclServiceTests.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcAclServiceTests.java @@ -41,8 +41,7 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.when; /** - * Unit and Integration tests the ACL JdbcAclService using an - * in-memory database. + * Unit and Integration tests the ACL JdbcAclService using an in-memory database. * * @author Nena Raab */ @@ -61,6 +60,7 @@ public class JdbcAclServiceTests { JdbcOperations jdbcOperations; private JdbcAclService aclServiceIntegration; + private JdbcAclService aclService; @Before @@ -72,9 +72,7 @@ public class JdbcAclServiceTests { @Before public void setUpEmbeddedDatabase() { embeddedDatabase = new EmbeddedDatabaseBuilder()// - .addScript("createAclSchemaWithAclClassIdType.sql") - .addScript("db/sql/test_data_hierarchy.sql") - .build(); + .addScript("createAclSchemaWithAclClassIdType.sql").addScript("db/sql/test_data_hierarchy.sql").build(); } @After @@ -86,9 +84,7 @@ public class JdbcAclServiceTests { @Test(expected = NotFoundException.class) public void readAclByIdMissingAcl() { Map result = new HashMap<>(); - when( - lookupStrategy.readAclsById(anyList(), - anyList())).thenReturn(result); + when(lookupStrategy.readAclsById(anyList(), anyList())).thenReturn(result); ObjectIdentity objectIdentity = new ObjectIdentityImpl(Object.class, 1); List sids = Arrays.asList(new PrincipalSid("user")); @@ -99,10 +95,8 @@ public class JdbcAclServiceTests { public void findOneChildren() { List result = new ArrayList<>(); result.add(new ObjectIdentityImpl(Object.class, "5577")); - Object[] args = {"1", "org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject"}; - when( - jdbcOperations.query(anyString(), - aryEq(args), any(RowMapper.class))).thenReturn(result); + Object[] args = { "1", "org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject" }; + when(jdbcOperations.query(anyString(), aryEq(args), any(RowMapper.class))).thenReturn(result); ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L); List objectIdentities = aclService.findChildren(objectIdentity); @@ -170,10 +164,12 @@ public class JdbcAclServiceTests { List objectIdentities = aclServiceIntegration.findChildren(objectIdentity); assertThat(objectIdentities.size()).isEqualTo(1); assertThat(objectIdentities.get(0).getType()).isEqualTo("costcenter"); - assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo(UUID.fromString("25d93b3f-c3aa-4814-9d5e-c7c96ced7762")); + assertThat(objectIdentities.get(0).getIdentifier()) + .isEqualTo(UUID.fromString("25d93b3f-c3aa-4814-9d5e-c7c96ced7762")); } private class MockLongIdDomainObject { + private Object id; public Object getId() { @@ -183,9 +179,11 @@ public class JdbcAclServiceTests { public void setId(Object id) { this.id = id; } + } private class MockUntypedIdDomainObject { + private Object id; public Object getId() { @@ -195,5 +193,7 @@ public class JdbcAclServiceTests { public void setId(Object id) { this.id = id; } + } + } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java index 0e54ed8f58..0d80c92051 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java @@ -62,36 +62,38 @@ import org.springframework.transaction.annotation.Transactional; * @author Andrei Stefan */ @ContextConfiguration(locations = { "/jdbcMutableAclServiceTests-context.xml" }) -public class JdbcMutableAclServiceTests extends - AbstractTransactionalJUnit4SpringContextTests { +public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4SpringContextTests { + // ~ Constant fields // ================================================================================================ private static final String TARGET_CLASS = TargetObject.class.getName(); - private final Authentication auth = new TestingAuthenticationToken("ben", "ignored", - "ROLE_ADMINISTRATOR"); + private final Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_ADMINISTRATOR"); public static final String SELECT_ALL_CLASSES = "SELECT * FROM acl_class WHERE class = ?"; // ~ Instance fields // ================================================================================================ - private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, - 100L); - private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, - 101L); - private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, - 102L); + private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100L); + + private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, 101L); + + private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 102L); @Autowired private JdbcMutableAclService jdbcMutableAclService; + @Autowired private AclCache aclCache; + @Autowired private LookupStrategy lookupStrategy; + @Autowired private DataSource dataSource; + @Autowired private JdbcTemplate jdbcTemplate; @@ -166,8 +168,8 @@ public class JdbcMutableAclServiceTests extends jdbcMutableAclService.updateAcl(child); // Let's check if we can read them back correctly - Map map = jdbcMutableAclService.readAclsById(Arrays.asList( - getTopParentOid(), getMiddleParentOid(), getChildOid())); + Map map = jdbcMutableAclService + .readAclsById(Arrays.asList(getTopParentOid(), getMiddleParentOid(), getChildOid())); assertThat(map).hasSize(3); // Replace our current objects with their retrieved versions @@ -257,8 +259,9 @@ public class JdbcMutableAclServiceTests extends } // Check the permissions are as they should be - assertThat(child.isGranted(delete, pSid, true)).isFalse(); // as earlier permission - // overrode + assertThat(child.isGranted(delete, pSid, true)).isFalse(); // as earlier + // permission + // overrode assertThat(child.isGranted(Arrays.asList(BasePermission.CREATE), pSid, true)).isTrue(); // Now check the first ACE (index 0) really is DELETE for our Sid and is @@ -360,8 +363,7 @@ public class JdbcMutableAclServiceTests extends @Transactional public void createAclForADuplicateDomainObject() { SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentity duplicateOid = new ObjectIdentityImpl(TARGET_CLASS, - 100L); + ObjectIdentity duplicateOid = new ObjectIdentityImpl(TARGET_CLASS, 100L); jdbcMutableAclService.createAcl(duplicateOid); // Try to add the same object second time try { @@ -419,11 +421,8 @@ public class JdbcMutableAclServiceTests extends // Remove the child and check all related database rows were removed accordingly jdbcMutableAclService.deleteAcl(getChildOid(), false); - assertThat( - jdbcTemplate.queryForList(SELECT_ALL_CLASSES, - new Object[] { getTargetClass() })).hasSize(1); - assertThat(jdbcTemplate.queryForList("select * from acl_object_identity") - ).isEmpty(); + assertThat(jdbcTemplate.queryForList(SELECT_ALL_CLASSES, new Object[] { getTargetClass() })).hasSize(1); + assertThat(jdbcTemplate.queryForList("select * from acl_object_identity")).isEmpty(); assertThat(jdbcTemplate.queryForList("select * from acl_entry")).isEmpty(); // Check the cache @@ -439,8 +438,7 @@ public class JdbcMutableAclServiceTests extends ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, 101); jdbcMutableAclService.createAcl(oid); - assertThat(jdbcMutableAclService.readAclById(new ObjectIdentityImpl( - TARGET_CLASS, 101L))).isNotNull(); + assertThat(jdbcMutableAclService.readAclById(new ObjectIdentityImpl(TARGET_CLASS, 101L))).isNotNull(); } /** @@ -449,8 +447,7 @@ public class JdbcMutableAclServiceTests extends @Test @Transactional public void childrenAreClearedFromCacheWhenParentIsUpdated() { - Authentication auth = new TestingAuthenticationToken("ben", "ignored", - "ROLE_ADMINISTRATOR"); + Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_ADMINISTRATOR"); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); @@ -474,7 +471,8 @@ public class JdbcMutableAclServiceTests extends child = (MutableAcl) jdbcMutableAclService.readAclById(childOid); parent = (MutableAcl) child.getParentAcl(); - assertThat(parent.getEntries()).hasSize(2).withFailMessage("Fails because child has a stale reference to its parent"); + assertThat(parent.getEntries()).hasSize(2) + .withFailMessage("Fails because child has a stale reference to its parent"); assertThat(parent.getEntries().get(0).getPermission().getMask()).isEqualTo(1); assertThat(parent.getEntries().get(0).getSid()).isEqualTo(new PrincipalSid("ben")); assertThat(parent.getEntries().get(1).getPermission().getMask()).isEqualTo(1); @@ -487,34 +485,28 @@ public class JdbcMutableAclServiceTests extends @Test @Transactional public void childrenAreClearedFromCacheWhenParentisUpdated2() { - Authentication auth = new TestingAuthenticationToken("system", "secret", - "ROLE_IGNORED"); + Authentication auth = new TestingAuthenticationToken("system", "secret", "ROLE_IGNORED"); SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentityImpl rootObject = new ObjectIdentityImpl(TARGET_CLASS, - 1L); + ObjectIdentityImpl rootObject = new ObjectIdentityImpl(TARGET_CLASS, 1L); MutableAcl parent = jdbcMutableAclService.createAcl(rootObject); - MutableAcl child = jdbcMutableAclService.createAcl(new ObjectIdentityImpl( - TARGET_CLASS, 2L)); + MutableAcl child = jdbcMutableAclService.createAcl(new ObjectIdentityImpl(TARGET_CLASS, 2L)); child.setParent(parent); jdbcMutableAclService.updateAcl(child); - parent.insertAce(0, BasePermission.ADMINISTRATION, new GrantedAuthoritySid( - "ROLE_ADMINISTRATOR"), true); + parent.insertAce(0, BasePermission.ADMINISTRATION, new GrantedAuthoritySid("ROLE_ADMINISTRATOR"), true); jdbcMutableAclService.updateAcl(parent); parent.insertAce(1, BasePermission.DELETE, new PrincipalSid("terry"), true); jdbcMutableAclService.updateAcl(parent); - child = (MutableAcl) jdbcMutableAclService.readAclById(new ObjectIdentityImpl( - TARGET_CLASS, 2L)); + child = (MutableAcl) jdbcMutableAclService.readAclById(new ObjectIdentityImpl(TARGET_CLASS, 2L)); parent = (MutableAcl) child.getParentAcl(); assertThat(parent.getEntries()).hasSize(2); assertThat(parent.getEntries().get(0).getPermission().getMask()).isEqualTo(16); - assertThat(parent.getEntries() - .get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_ADMINISTRATOR")); + assertThat(parent.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_ADMINISTRATOR")); assertThat(parent.getEntries().get(1).getPermission().getMask()).isEqualTo(8); assertThat(parent.getEntries().get(1).getSid()).isEqualTo(new PrincipalSid("terry")); } @@ -522,18 +514,15 @@ public class JdbcMutableAclServiceTests extends @Test @Transactional public void cumulativePermissions() { - Authentication auth = new TestingAuthenticationToken("ben", "ignored", - "ROLE_ADMINISTRATOR"); + Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_ADMINISTRATOR"); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); - ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, - 110L); + ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, 110L); MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid); // Add an ACE permission entry - Permission cm = new CumulativePermission().set(BasePermission.READ).set( - BasePermission.ADMINISTRATION); + Permission cm = new CumulativePermission().set(BasePermission.READ).set(BasePermission.ADMINISTRATION); assertThat(cm.getMask()).isEqualTo(17); Sid benSid = new PrincipalSid(auth); topParent.insertAce(0, cm, benSid, true); @@ -551,15 +540,12 @@ public class JdbcMutableAclServiceTests extends @Test public void testProcessingCustomSid() { - CustomJdbcMutableAclService customJdbcMutableAclService = spy(new CustomJdbcMutableAclService( - dataSource, lookupStrategy, aclCache)); + CustomJdbcMutableAclService customJdbcMutableAclService = spy( + new CustomJdbcMutableAclService(dataSource, lookupStrategy, aclCache)); CustomSid customSid = new CustomSid("Custom sid"); - when( - customJdbcMutableAclService.createOrRetrieveSidPrimaryKey("Custom sid", - false, false)).thenReturn(1L); + when(customJdbcMutableAclService.createOrRetrieveSidPrimaryKey("Custom sid", false, false)).thenReturn(1L); - Long result = customJdbcMutableAclService.createOrRetrieveSidPrimaryKey( - customSid, false); + Long result = customJdbcMutableAclService.createOrRetrieveSidPrimaryKey(customSid, false); assertThat(new Long(1L)).isEqualTo(result); } @@ -570,8 +556,7 @@ public class JdbcMutableAclServiceTests extends */ private class CustomJdbcMutableAclService extends JdbcMutableAclService { - private CustomJdbcMutableAclService(DataSource dataSource, - LookupStrategy lookupStrategy, AclCache aclCache) { + private CustomJdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) { super(dataSource, lookupStrategy, aclCache); } @@ -591,6 +576,7 @@ public class JdbcMutableAclServiceTests extends } return createOrRetrieveSidPrimaryKey(sidName, isPrincipal, allowCreate); } + } protected Authentication getAuth() { @@ -600,4 +586,5 @@ public class JdbcMutableAclServiceTests extends protected JdbcMutableAclService getJdbcMutableAclService() { return jdbcMutableAclService; } + } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTestsWithAclClassId.java b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTestsWithAclClassId.java index 1d45b033aa..397dfc4820 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTestsWithAclClassId.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTestsWithAclClassId.java @@ -28,20 +28,21 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.transaction.annotation.Transactional; /** - * Integration tests the ACL system using ACL class id type of UUID and using an in-memory database. + * Integration tests the ACL system using ACL class id type of UUID and using an in-memory + * database. + * * @author Paul Wheeler */ -@ContextConfiguration(locations = {"/jdbcMutableAclServiceTestsWithAclClass-context.xml"}) +@ContextConfiguration(locations = { "/jdbcMutableAclServiceTestsWithAclClass-context.xml" }) public class JdbcMutableAclServiceTestsWithAclClassId extends JdbcMutableAclServiceTests { private static final String TARGET_CLASS_WITH_UUID = TargetObjectWithUUID.class.getName(); - private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, - UUID.randomUUID()); - private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, - UUID.randomUUID()); - private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, - UUID.randomUUID()); + private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, UUID.randomUUID()); + + private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, UUID.randomUUID()); + + private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, UUID.randomUUID()); @Override protected String getSqlClassPathResource() { @@ -77,7 +78,8 @@ public class JdbcMutableAclServiceTestsWithAclClassId extends JdbcMutableAclServ ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, id); getJdbcMutableAclService().createAcl(oid); - assertThat(getJdbcMutableAclService().readAclById(new ObjectIdentityImpl( - TARGET_CLASS_WITH_UUID, id))).isNotNull(); + assertThat(getJdbcMutableAclService().readAclById(new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, id))) + .isNotNull(); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/SpringCacheBasedAclCacheTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/SpringCacheBasedAclCacheTests.java index 4d9de2f556..6b9368af6c 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/SpringCacheBasedAclCacheTests.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/SpringCacheBasedAclCacheTests.java @@ -41,6 +41,7 @@ import static org.assertj.core.api.Assertions.*; * @author Marten Deinum */ public class SpringCacheBasedAclCacheTests { + private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; private static CacheManager cacheManager; @@ -76,16 +77,14 @@ public class SpringCacheBasedAclCacheTests { Map realCache = (Map) cache.getNativeCache(); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L); AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( - "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), + new SimpleGrantedAuthority("ROLE_GENERAL")); AuditLogger auditLogger = new ConsoleAuditLogger(); - PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy( - auditLogger); - SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache, - permissionGrantingStrategy, aclAuthorizationStrategy); - MutableAcl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, - auditLogger); + PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(auditLogger); + SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache, permissionGrantingStrategy, + aclAuthorizationStrategy); + MutableAcl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, auditLogger); assertThat(realCache).isEmpty(); myCache.putInCache(acl); @@ -96,8 +95,7 @@ public class SpringCacheBasedAclCacheTests { // Put another object in cache ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, 101L); - MutableAcl acl2 = new AclImpl(identity2, 2L, - aclAuthorizationStrategy, new ConsoleAuditLogger()); + MutableAcl acl2 = new AclImpl(identity2, 2L, aclAuthorizationStrategy, new ConsoleAuditLogger()); myCache.putInCache(acl2); @@ -123,28 +121,23 @@ public class SpringCacheBasedAclCacheTests { Cache cache = getCache(); Map realCache = (Map) cache.getNativeCache(); - Authentication auth = new TestingAuthenticationToken("user", "password", - "ROLE_GENERAL"); + Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL"); auth.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(auth); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 1L); - ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, - 2L); + ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, 2L); AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( - new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( - "ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); + new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"), + new SimpleGrantedAuthority("ROLE_GENERAL")); AuditLogger auditLogger = new ConsoleAuditLogger(); - PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy( - auditLogger); - SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache, - permissionGrantingStrategy, aclAuthorizationStrategy); + PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(auditLogger); + SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache, permissionGrantingStrategy, + aclAuthorizationStrategy); - MutableAcl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, - auditLogger); - MutableAcl parentAcl = new AclImpl(identityParent, 2L, - aclAuthorizationStrategy, auditLogger); + MutableAcl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, auditLogger); + MutableAcl parentAcl = new AclImpl(identityParent, 2L, aclAuthorizationStrategy, auditLogger); acl.setParent(parentAcl); @@ -156,16 +149,14 @@ public class SpringCacheBasedAclCacheTests { AclImpl aclFromCache = (AclImpl) myCache.getFromCache(1L); assertThat(aclFromCache).isEqualTo(acl); // SEC-951 check transient fields are set on parent - assertThat(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), - "aclAuthorizationStrategy")).isNotNull(); - assertThat(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), - "permissionGrantingStrategy")).isNotNull(); + assertThat(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), "aclAuthorizationStrategy")).isNotNull(); + assertThat(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), "permissionGrantingStrategy")).isNotNull(); assertThat(myCache.getFromCache(identity)).isEqualTo(acl); assertThat(FieldUtils.getFieldValue(aclFromCache, "aclAuthorizationStrategy")).isNotNull(); AclImpl parentAclFromCache = (AclImpl) myCache.getFromCache(2L); assertThat(parentAclFromCache).isEqualTo(parentAcl); - assertThat(FieldUtils.getFieldValue(parentAclFromCache, - "aclAuthorizationStrategy")).isNotNull(); + assertThat(FieldUtils.getFieldValue(parentAclFromCache, "aclAuthorizationStrategy")).isNotNull(); assertThat(myCache.getFromCache(identityParent)).isEqualTo(parentAcl); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/sid/CustomSid.java b/acl/src/test/java/org/springframework/security/acls/sid/CustomSid.java index 21226f1888..c872258518 100644 --- a/acl/src/test/java/org/springframework/security/acls/sid/CustomSid.java +++ b/acl/src/test/java/org/springframework/security/acls/sid/CustomSid.java @@ -19,6 +19,7 @@ import org.springframework.security.acls.model.Sid; /** * This class is example of custom {@link Sid} implementation + * * @author Mikhail Stryzhonok */ public class CustomSid implements Sid { @@ -36,4 +37,5 @@ public class CustomSid implements Sid { public void setSid(String sid) { this.sid = sid; } + } diff --git a/acl/src/test/java/org/springframework/security/acls/sid/SidRetrievalStrategyTests.java b/acl/src/test/java/org/springframework/security/acls/sid/SidRetrievalStrategyTests.java index ba61b41d01..8972dfa378 100644 --- a/acl/src/test/java/org/springframework/security/acls/sid/SidRetrievalStrategyTests.java +++ b/acl/src/test/java/org/springframework/security/acls/sid/SidRetrievalStrategyTests.java @@ -39,8 +39,8 @@ import org.springframework.security.core.authority.AuthorityUtils; */ @SuppressWarnings("unchecked") public class SidRetrievalStrategyTests { - Authentication authentication = new TestingAuthenticationToken("scott", "password", - "A", "B", "C"); + + Authentication authentication = new TestingAuthenticationToken("scott", "password", "A", "B", "C"); // ~ Methods // ======================================================================================================== @@ -69,8 +69,7 @@ public class SidRetrievalStrategyTests { public void roleHierarchyIsUsedWhenSet() { RoleHierarchy rh = mock(RoleHierarchy.class); List rhAuthorities = AuthorityUtils.createAuthorityList("D"); - when(rh.getReachableGrantedAuthorities(anyCollection())) - .thenReturn(rhAuthorities); + when(rh.getReachableGrantedAuthorities(anyCollection())).thenReturn(rhAuthorities); SidRetrievalStrategy strat = new SidRetrievalStrategyImpl(rh); List sids = strat.getSids(authentication); @@ -79,4 +78,5 @@ public class SidRetrievalStrategyTests { assertThat(sids.get(0) instanceof PrincipalSid).isTrue(); assertThat(((GrantedAuthoritySid) sids.get(1)).getGrantedAuthority()).isEqualTo("D"); } + } diff --git a/acl/src/test/java/org/springframework/security/acls/sid/SidTests.java b/acl/src/test/java/org/springframework/security/acls/sid/SidTests.java index b65c1cb906..fe11171182 100644 --- a/acl/src/test/java/org/springframework/security/acls/sid/SidTests.java +++ b/acl/src/test/java/org/springframework/security/acls/sid/SidTests.java @@ -67,16 +67,14 @@ public class SidTests { } try { - Authentication authentication = new TestingAuthenticationToken(null, - "password"); + Authentication authentication = new TestingAuthenticationToken(null, "password"); new PrincipalSid(authentication); fail("It should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { } - Authentication authentication = new TestingAuthenticationToken("johndoe", - "password"); + Authentication authentication = new TestingAuthenticationToken("johndoe", "password"); new PrincipalSid(authentication); // throws no exception } @@ -140,18 +138,15 @@ public class SidTests { @Test public void testPrincipalSidEquals() { - Authentication authentication = new TestingAuthenticationToken("johndoe", - "password"); + Authentication authentication = new TestingAuthenticationToken("johndoe", "password"); Sid principalSid = new PrincipalSid(authentication); assertThat(principalSid.equals(null)).isFalse(); assertThat(principalSid.equals("DIFFERENT_TYPE_OBJECT")).isFalse(); assertThat(principalSid.equals(principalSid)).isTrue(); assertThat(principalSid.equals(new PrincipalSid(authentication))).isTrue(); - assertThat(principalSid.equals(new PrincipalSid( - new TestingAuthenticationToken("johndoe", null)))).isTrue(); - assertThat(principalSid.equals(new PrincipalSid( - new TestingAuthenticationToken("scott", null)))).isFalse(); + assertThat(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("johndoe", null)))).isTrue(); + assertThat(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("scott", null)))).isFalse(); assertThat(principalSid.equals(new PrincipalSid("johndoe"))).isTrue(); assertThat(principalSid.equals(new PrincipalSid("scott"))).isFalse(); } @@ -165,27 +160,22 @@ public class SidTests { assertThat(gaSid.equals("DIFFERENT_TYPE_OBJECT")).isFalse(); assertThat(gaSid.equals(gaSid)).isTrue(); assertThat(gaSid.equals(new GrantedAuthoritySid(ga))).isTrue(); - assertThat(gaSid.equals(new GrantedAuthoritySid( - new SimpleGrantedAuthority("ROLE_TEST")))).isTrue(); - assertThat(gaSid.equals(new GrantedAuthoritySid( - new SimpleGrantedAuthority("ROLE_NOT_EQUAL")))).isFalse(); + assertThat(gaSid.equals(new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_TEST")))).isTrue(); + assertThat(gaSid.equals(new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_NOT_EQUAL")))).isFalse(); assertThat(gaSid.equals(new GrantedAuthoritySid("ROLE_TEST"))).isTrue(); assertThat(gaSid.equals(new GrantedAuthoritySid("ROLE_NOT_EQUAL"))).isFalse(); } @Test public void testPrincipalSidHashCode() { - Authentication authentication = new TestingAuthenticationToken("johndoe", - "password"); + Authentication authentication = new TestingAuthenticationToken("johndoe", "password"); Sid principalSid = new PrincipalSid(authentication); assertThat(principalSid.hashCode()).isEqualTo("johndoe".hashCode()); - assertThat(principalSid.hashCode()).isEqualTo( - new PrincipalSid("johndoe").hashCode()); - assertThat(principalSid.hashCode()).isNotEqualTo( - new PrincipalSid("scott").hashCode()); - assertThat(principalSid.hashCode()).isNotEqualTo(new PrincipalSid( - new TestingAuthenticationToken("scott", "password")).hashCode()); + assertThat(principalSid.hashCode()).isEqualTo(new PrincipalSid("johndoe").hashCode()); + assertThat(principalSid.hashCode()).isNotEqualTo(new PrincipalSid("scott").hashCode()); + assertThat(principalSid.hashCode()) + .isNotEqualTo(new PrincipalSid(new TestingAuthenticationToken("scott", "password")).hashCode()); } @Test @@ -194,18 +184,15 @@ public class SidTests { Sid gaSid = new GrantedAuthoritySid(ga); assertThat(gaSid.hashCode()).isEqualTo("ROLE_TEST".hashCode()); - assertThat(gaSid.hashCode()).isEqualTo( - new GrantedAuthoritySid("ROLE_TEST").hashCode()); - assertThat(gaSid.hashCode()).isNotEqualTo( - new GrantedAuthoritySid("ROLE_TEST_2").hashCode()); - assertThat(gaSid.hashCode()).isNotEqualTo(new GrantedAuthoritySid( - new SimpleGrantedAuthority("ROLE_TEST_2")).hashCode()); + assertThat(gaSid.hashCode()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST").hashCode()); + assertThat(gaSid.hashCode()).isNotEqualTo(new GrantedAuthoritySid("ROLE_TEST_2").hashCode()); + assertThat(gaSid.hashCode()) + .isNotEqualTo(new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_TEST_2")).hashCode()); } @Test public void testGetters() { - Authentication authentication = new TestingAuthenticationToken("johndoe", - "password"); + Authentication authentication = new TestingAuthenticationToken("johndoe", "password"); PrincipalSid principalSid = new PrincipalSid(authentication); GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST"); GrantedAuthoritySid gaSid = new GrantedAuthoritySid(ga); @@ -243,6 +230,7 @@ public class SidTests { } static class CustomAuthenticationToken extends AbstractAuthenticationToken { + private CustomToken principal; CustomAuthenticationToken(CustomToken principal, Collection authorities) { @@ -264,9 +252,11 @@ public class SidTests { public String getName() { return principal.getName(); } + } static class CustomToken { + private String name; CustomToken(String name) { @@ -276,5 +266,7 @@ public class SidTests { String getName() { return name; } + } + } diff --git a/aspects/src/test/java/org/springframework/security/access/intercept/aspectj/aspect/AnnotationSecurityAspectTests.java b/aspects/src/test/java/org/springframework/security/access/intercept/aspectj/aspect/AnnotationSecurityAspectTests.java index f0d7570722..90ff2b7db6 100644 --- a/aspects/src/test/java/org/springframework/security/access/intercept/aspectj/aspect/AnnotationSecurityAspectTests.java +++ b/aspects/src/test/java/org/springframework/security/access/intercept/aspectj/aspect/AnnotationSecurityAspectTests.java @@ -50,36 +50,37 @@ import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; /** - * * @author Luke Taylor * @since 3.0.3 */ public class AnnotationSecurityAspectTests { + private AffirmativeBased adm; + private @Mock AuthenticationManager authman; - private TestingAuthenticationToken anne = new TestingAuthenticationToken("anne", "", - "ROLE_A"); + + private TestingAuthenticationToken anne = new TestingAuthenticationToken("anne", "", "ROLE_A"); + // private TestingAuthenticationToken bob = new TestingAuthenticationToken("bob", "", // "ROLE_B"); private AspectJMethodSecurityInterceptor interceptor; + private SecuredImpl secured = new SecuredImpl(); + private SecuredImplSubclass securedSub = new SecuredImplSubclass(); + private PrePostSecured prePostSecured = new PrePostSecured(); @Before public final void setUp() { MockitoAnnotations.initMocks(this); interceptor = new AspectJMethodSecurityInterceptor(); - AccessDecisionVoter[] voters = new AccessDecisionVoter[] { - new RoleVoter(), - new PreInvocationAuthorizationAdviceVoter( - new ExpressionBasedPreInvocationAdvice()) }; - adm = new AffirmativeBased( - Arrays.> asList(voters)); + AccessDecisionVoter[] voters = new AccessDecisionVoter[] { new RoleVoter(), + new PreInvocationAuthorizationAdviceVoter(new ExpressionBasedPreInvocationAdvice()) }; + adm = new AffirmativeBased(Arrays.>asList(voters)); interceptor.setAccessDecisionManager(adm); interceptor.setAuthenticationManager(authman); - interceptor - .setSecurityMetadataSource(new SecuredAnnotationSecurityMetadataSource()); + interceptor.setSecurityMetadataSource(new SecuredAnnotationSecurityMetadataSource()); AnnotationSecurityAspect secAspect = AnnotationSecurityAspect.aspectOf(); secAspect.setSecurityInterceptor(interceptor); } @@ -151,23 +152,25 @@ public class AnnotationSecurityAspectTests { private void configureForElAnnotations() { DefaultMethodSecurityExpressionHandler eh = new DefaultMethodSecurityExpressionHandler(); - interceptor - .setSecurityMetadataSource(new PrePostAnnotationSecurityMetadataSource( - new ExpressionBasedAnnotationAttributeFactory(eh))); + interceptor.setSecurityMetadataSource( + new PrePostAnnotationSecurityMetadataSource(new ExpressionBasedAnnotationAttributeFactory(eh))); interceptor.setAccessDecisionManager(adm); AfterInvocationProviderManager aim = new AfterInvocationProviderManager(); - aim.setProviders(Arrays.asList(new PostInvocationAdviceProvider( - new ExpressionBasedPostInvocationAdvice(eh)))); + aim.setProviders(Arrays.asList(new PostInvocationAdviceProvider(new ExpressionBasedPostInvocationAdvice(eh)))); interceptor.setAfterInvocationManager(aim); } + } interface SecuredInterface { + @Secured("ROLE_X") void securedMethod(); + } class SecuredImpl implements SecuredInterface { + // Not really secured because AspectJ doesn't inherit annotations from interfaces public void securedMethod() { } @@ -188,18 +191,22 @@ class SecuredImpl implements SecuredInterface { public void publicCallsPrivate() { privateMethod(); } + } class SecuredImplSubclass extends SecuredImpl { + protected void protectedMethod() { } public void publicCallsPrivate() { super.publicCallsPrivate(); } + } class PrePostSecured { + @PreAuthorize("denyAll") public void denyAllMethod() { } @@ -207,8 +214,8 @@ class PrePostSecured { @PostFilter("filterObject.startsWith('a')") public List postFilterMethod() { ArrayList objects = new ArrayList<>(); - objects.addAll(Arrays.asList(new String[] { "apple", "banana", "aubergine", - "orange" })); + objects.addAll(Arrays.asList(new String[] { "apple", "banana", "aubergine", "orange" })); return objects; } + } diff --git a/cas/src/main/java/org/springframework/security/cas/SamlServiceProperties.java b/cas/src/main/java/org/springframework/security/cas/SamlServiceProperties.java index 6be415859e..c20e352e73 100644 --- a/cas/src/main/java/org/springframework/security/cas/SamlServiceProperties.java +++ b/cas/src/main/java/org/springframework/security/cas/SamlServiceProperties.java @@ -32,4 +32,5 @@ public final class SamlServiceProperties extends ServiceProperties { super.setArtifactParameter(DEFAULT_SAML_ARTIFACT_PARAMETER); super.setServiceParameter(DEFAULT_SAML_SERVICE_PARAMETER); } + } diff --git a/cas/src/main/java/org/springframework/security/cas/ServiceProperties.java b/cas/src/main/java/org/springframework/security/cas/ServiceProperties.java index e63742222c..85bab3cc0e 100644 --- a/cas/src/main/java/org/springframework/security/cas/ServiceProperties.java +++ b/cas/src/main/java/org/springframework/security/cas/ServiceProperties.java @@ -65,7 +65,6 @@ public class ServiceProperties implements InitializingBean { *

 	 * https://www.mycompany.com/application/login/cas
 	 * 
- * * @return the URL of the service the user is authenticating to */ public final String getService() { @@ -81,7 +80,6 @@ public class ServiceProperties implements InitializingBean { * ticket was generated as a consequence of an explicit login. High security * applications would probably set this to true. Defaults to * false, providing automated single sign on. - * * @return whether to send the renew parameter to CAS */ public final boolean isSendRenew() { @@ -103,7 +101,6 @@ public class ServiceProperties implements InitializingBean { /** * Configures the Request Parameter to look for when attempting to see if a CAS ticket * was sent from the server. - * * @param artifactParameter the id to use. Default is "ticket". */ public final void setArtifactParameter(final String artifactParameter) { @@ -113,7 +110,6 @@ public class ServiceProperties implements InitializingBean { /** * Configures the Request parameter to look for when attempting to send a request to * CAS. - * * @return the service parameter to use. Default is "service". */ public final String getServiceParameter() { @@ -132,11 +128,10 @@ public class ServiceProperties implements InitializingBean { * If true, then any non-null artifact (ticket) should be authenticated. Additionally, * the service will be determined dynamically in order to ensure the service matches * the expected value for this artifact. - * * @param authenticateAllArtifacts */ - public final void setAuthenticateAllArtifacts( - final boolean authenticateAllArtifacts) { + public final void setAuthenticateAllArtifacts(final boolean authenticateAllArtifacts) { this.authenticateAllArtifacts = authenticateAllArtifacts; } + } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/CasAssertionAuthenticationToken.java b/cas/src/main/java/org/springframework/security/cas/authentication/CasAssertionAuthenticationToken.java index af82fa1183..ffc2ad4703 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/CasAssertionAuthenticationToken.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/CasAssertionAuthenticationToken.java @@ -53,4 +53,5 @@ public final class CasAssertionAuthenticationToken extends AbstractAuthenticatio public Assertion getAssertion() { return this.assertion; } + } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java index 226a786d6b..e40696fb94 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java @@ -54,8 +54,8 @@ import org.springframework.util.Assert; * @author Ben Alex * @author Scott Battaglia */ -public class CasAuthenticationProvider implements AuthenticationProvider, - InitializingBean, MessageSourceAware { +public class CasAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { + // ~ Static fields/initializers // ===================================================================================== @@ -67,67 +67,65 @@ public class CasAuthenticationProvider implements AuthenticationProvider, private AuthenticationUserDetailsService authenticationUserDetailsService; private final UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker(); + protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); + private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache(); + private String key; + private TicketValidator ticketValidator; + private ServiceProperties serviceProperties; + private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper(); // ~ Methods // ======================================================================================================== public void afterPropertiesSet() { - Assert.notNull(this.authenticationUserDetailsService, - "An authenticationUserDetailsService must be set"); + Assert.notNull(this.authenticationUserDetailsService, "An authenticationUserDetailsService must be set"); Assert.notNull(this.ticketValidator, "A ticketValidator must be set"); Assert.notNull(this.statelessTicketCache, "A statelessTicketCache must be set"); - Assert.hasText( - this.key, + Assert.hasText(this.key, "A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated"); Assert.notNull(this.messages, "A message source must be set"); } - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } if (authentication instanceof UsernamePasswordAuthenticationToken - && (!CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER - .equals(authentication.getPrincipal().toString()) && !CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER - .equals(authentication.getPrincipal().toString()))) { + && (!CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER.equals(authentication.getPrincipal().toString()) + && !CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER + .equals(authentication.getPrincipal().toString()))) { // UsernamePasswordAuthenticationToken not CAS related return null; } // If an existing CasAuthenticationToken, just check we created it if (authentication instanceof CasAuthenticationToken) { - if (this.key.hashCode() == ((CasAuthenticationToken) authentication) - .getKeyHash()) { + if (this.key.hashCode() == ((CasAuthenticationToken) authentication).getKeyHash()) { return authentication; } else { - throw new BadCredentialsException( - messages.getMessage("CasAuthenticationProvider.incorrectKey", - "The presented CasAuthenticationToken does not contain the expected key")); + throw new BadCredentialsException(messages.getMessage("CasAuthenticationProvider.incorrectKey", + "The presented CasAuthenticationToken does not contain the expected key")); } } // Ensure credentials are presented - if ((authentication.getCredentials() == null) - || "".equals(authentication.getCredentials())) { - throw new BadCredentialsException(messages.getMessage( - "CasAuthenticationProvider.noServiceTicket", + if ((authentication.getCredentials() == null) || "".equals(authentication.getCredentials())) { + throw new BadCredentialsException(messages.getMessage("CasAuthenticationProvider.noServiceTicket", "Failed to provide a CAS service ticket to validate")); } boolean stateless = false; if (authentication instanceof UsernamePasswordAuthenticationToken - && CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER.equals(authentication - .getPrincipal())) { + && CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER.equals(authentication.getPrincipal())) { stateless = true; } @@ -135,8 +133,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, if (stateless) { // Try to obtain from cache - result = statelessTicketCache.getByTicketId(authentication.getCredentials() - .toString()); + result = statelessTicketCache.getByTicketId(authentication.getCredentials().toString()); } if (result == null) { @@ -152,17 +149,14 @@ public class CasAuthenticationProvider implements AuthenticationProvider, return result; } - private CasAuthenticationToken authenticateNow(final Authentication authentication) - throws AuthenticationException { + private CasAuthenticationToken authenticateNow(final Authentication authentication) throws AuthenticationException { try { - final Assertion assertion = this.ticketValidator.validate(authentication - .getCredentials().toString(), getServiceUrl(authentication)); + final Assertion assertion = this.ticketValidator.validate(authentication.getCredentials().toString(), + getServiceUrl(authentication)); final UserDetails userDetails = loadUserByAssertion(assertion); userDetailsChecker.check(userDetails); - return new CasAuthenticationToken(this.key, userDetails, - authentication.getCredentials(), - authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), - userDetails, assertion); + return new CasAuthenticationToken(this.key, userDetails, authentication.getCredentials(), + authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), userDetails, assertion); } catch (final TicketValidationException e) { throw new BadCredentialsException(e.getMessage(), e); @@ -174,15 +168,13 @@ public class CasAuthenticationProvider implements AuthenticationProvider, * {@link ServiceAuthenticationDetails}, then * {@link ServiceAuthenticationDetails#getServiceUrl()} is used. Otherwise, the * {@link ServiceProperties#getService()} is used. - * * @param authentication * @return */ private String getServiceUrl(Authentication authentication) { String serviceUrl; if (authentication.getDetails() instanceof ServiceAuthenticationDetails) { - serviceUrl = ((ServiceAuthenticationDetails) authentication.getDetails()) - .getServiceUrl(); + serviceUrl = ((ServiceAuthenticationDetails) authentication.getDetails()).getServiceUrl(); } else if (serviceProperties == null) { throw new IllegalStateException( @@ -205,13 +197,11 @@ public class CasAuthenticationProvider implements AuthenticationProvider, * Template method for retrieving the UserDetails based on the assertion. Default is * to call configured userDetailsService and pass the username. Deployers can override * this method and retrieve the user based on any criteria they desire. - * * @param assertion The CAS Assertion. * @return the UserDetails. */ protected UserDetails loadUserByAssertion(final Assertion assertion) { - final CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken( - assertion, ""); + final CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken(assertion, ""); return this.authenticationUserDetailsService.loadUserDetails(token); } @@ -220,8 +210,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, * Sets the UserDetailsService to use. This is a convenience method to invoke */ public void setUserDetailsService(final UserDetailsService userDetailsService) { - this.authenticationUserDetailsService = new UserDetailsByNameServiceWrapper( - userDetailsService); + this.authenticationUserDetailsService = new UserDetailsByNameServiceWrapper(userDetailsService); } public void setAuthenticationUserDetailsService( @@ -266,10 +255,9 @@ public class CasAuthenticationProvider implements AuthenticationProvider, } public boolean supports(final Class authentication) { - return (UsernamePasswordAuthenticationToken.class - .isAssignableFrom(authentication)) + return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)) || (CasAuthenticationToken.class.isAssignableFrom(authentication)) - || (CasAssertionAuthenticationToken.class - .isAssignableFrom(authentication)); + || (CasAssertionAuthenticationToken.class.isAssignableFrom(authentication)); } + } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java index d3d0827133..3483b640cc 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java @@ -32,17 +32,20 @@ import org.springframework.util.Assert; * @author Ben Alex * @author Scott Battaglia */ -public class CasAuthenticationToken extends AbstractAuthenticationToken implements - Serializable { +public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; // ~ Instance fields // ================================================================================================ private final Object credentials; + private final Object principal; + private final UserDetails userDetails; + private final int keyHash; + private final Assertion assertion; // ~ Constructors @@ -50,60 +53,53 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen /** * Constructor. - * - * @param key to identify if this object made by a given - * {@link CasAuthenticationProvider} - * @param principal typically the UserDetails object (cannot be null) + * @param key to identify if this object made by a given + * {@link CasAuthenticationProvider} + * @param principal typically the UserDetails object (cannot be null) * @param credentials the service/proxy ticket ID from CAS (cannot be - * null) + * null) * @param authorities the authorities granted to the user (from the - * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot - * be null) + * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot + * be null) * @param userDetails the user details (from the - * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot - * be null) - * @param assertion the assertion returned from the CAS servers. It contains the - * principal and how to obtain a proxy ticket for the user. + * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot + * be null) + * @param assertion the assertion returned from the CAS servers. It contains the + * principal and how to obtain a proxy ticket for the user. * @throws IllegalArgumentException if a null was passed */ - public CasAuthenticationToken(final String key, final Object principal, - final Object credentials, - final Collection authorities, - final UserDetails userDetails, final Assertion assertion) { + public CasAuthenticationToken(final String key, final Object principal, final Object credentials, + final Collection authorities, final UserDetails userDetails, + final Assertion assertion) { this(extractKeyHash(key), principal, credentials, authorities, userDetails, assertion); } /** * Private constructor for Jackson Deserialization support - * - * @param keyHash hashCode of provided key to identify if this object made by a given - * {@link CasAuthenticationProvider} - * @param principal typically the UserDetails object (cannot be null) + * @param keyHash hashCode of provided key to identify if this object made by a given + * {@link CasAuthenticationProvider} + * @param principal typically the UserDetails object (cannot be null) * @param credentials the service/proxy ticket ID from CAS (cannot be - * null) + * null) * @param authorities the authorities granted to the user (from the - * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot - * be null) + * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot + * be null) * @param userDetails the user details (from the - * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot - * be null) - * @param assertion the assertion returned from the CAS servers. It contains the - * principal and how to obtain a proxy ticket for the user. + * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot + * be null) + * @param assertion the assertion returned from the CAS servers. It contains the + * principal and how to obtain a proxy ticket for the user. * @throws IllegalArgumentException if a null was passed * @since 4.2 */ - private CasAuthenticationToken(final Integer keyHash, final Object principal, - final Object credentials, - final Collection authorities, - final UserDetails userDetails, final Assertion assertion) { + private CasAuthenticationToken(final Integer keyHash, final Object principal, final Object credentials, + final Collection authorities, final UserDetails userDetails, + final Assertion assertion) { super(authorities); - if ((principal == null) - || "".equals(principal) || (credentials == null) - || "".equals(credentials) || (authorities == null) - || (userDetails == null) || (assertion == null)) { - throw new IllegalArgumentException( - "Cannot pass null or empty values to constructor"); + if ((principal == null) || "".equals(principal) || (credentials == null) || "".equals(credentials) + || (authorities == null) || (userDetails == null) || (assertion == null)) { + throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); } this.keyHash = keyHash; @@ -187,4 +183,5 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen return (sb.toString()); } + } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCache.java b/cas/src/main/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCache.java index e424d512de..7840387422 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCache.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCache.java @@ -25,12 +25,13 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** - * Caches tickets using a Spring IoC defined EHCACHE. + * Caches tickets using a Spring IoC defined + * EHCACHE. * * @author Ben Alex */ public class EhCacheBasedTicketCache implements StatelessTicketCache, InitializingBean { + // ~ Static fields/initializers // ===================================================================================== @@ -52,8 +53,7 @@ public class EhCacheBasedTicketCache implements StatelessTicketCache, Initializi final Element element = cache.get(serviceTicket); if (logger.isDebugEnabled()) { - logger.debug("Cache hit: " + (element != null) + "; service ticket: " - + serviceTicket); + logger.debug("Cache hit: " + (element != null) + "; service ticket: " + serviceTicket); } return element == null ? null : (CasAuthenticationToken) element.getValue(); @@ -88,4 +88,5 @@ public class EhCacheBasedTicketCache implements StatelessTicketCache, Initializi public void setCache(final Ehcache cache) { this.cache = cache; } + } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/NullStatelessTicketCache.java b/cas/src/main/java/org/springframework/security/cas/authentication/NullStatelessTicketCache.java index b33518114b..e5aafe8235 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/NullStatelessTicketCache.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/NullStatelessTicketCache.java @@ -24,7 +24,6 @@ package org.springframework.security.cas.authentication; * are not using the stateless session management. * * @author Scott Battaglia - * * @see CasAuthenticationProvider */ public final class NullStatelessTicketCache implements StatelessTicketCache { @@ -56,4 +55,5 @@ public final class NullStatelessTicketCache implements StatelessTicketCache { public void removeTicketFromCache(final String serviceTicket) { // nothing to do } + } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCache.java b/cas/src/main/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCache.java index 171792448d..01549d55bd 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCache.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCache.java @@ -28,11 +28,11 @@ import org.springframework.util.Assert; * */ public class SpringCacheBasedTicketCache implements StatelessTicketCache { + // ~ Static fields/initializers // ===================================================================================== - private static final Log logger = LogFactory - .getLog(SpringCacheBasedTicketCache.class); + private static final Log logger = LogFactory.getLog(SpringCacheBasedTicketCache.class); // ~ Instance fields // ================================================================================================ @@ -51,12 +51,10 @@ public class SpringCacheBasedTicketCache implements StatelessTicketCache { // ======================================================================================================== public CasAuthenticationToken getByTicketId(final String serviceTicket) { - final Cache.ValueWrapper element = serviceTicket != null ? cache - .get(serviceTicket) : null; + final Cache.ValueWrapper element = serviceTicket != null ? cache.get(serviceTicket) : null; if (logger.isDebugEnabled()) { - logger.debug("Cache hit: " + (element != null) + "; service ticket: " - + serviceTicket); + logger.debug("Cache hit: " + (element != null) + "; service ticket: " + serviceTicket); } return element == null ? null : (CasAuthenticationToken) element.get(); @@ -83,4 +81,5 @@ public class SpringCacheBasedTicketCache implements StatelessTicketCache { public void removeTicketFromCache(final String serviceTicket) { cache.evict(serviceTicket); } + } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/StatelessTicketCache.java b/cas/src/main/java/org/springframework/security/cas/authentication/StatelessTicketCache.java index 7c848f19a4..b17fd05ae0 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/StatelessTicketCache.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/StatelessTicketCache.java @@ -59,6 +59,7 @@ package org.springframework.security.cas.authentication; * @author Ben Alex */ public interface StatelessTicketCache { + // ~ Methods ================================================================ /** @@ -68,7 +69,6 @@ public interface StatelessTicketCache { *

* If not found, returns a nullCasAuthenticationToken. *

- * * @return the fully populated authentication token */ CasAuthenticationToken getByTicketId(String serviceTicket); @@ -80,7 +80,6 @@ public interface StatelessTicketCache { * The {@link CasAuthenticationToken#getCredentials()} method is used to retrieve the * service ticket number. *

- * * @param token to be added to the cache */ void putTicketInCache(CasAuthenticationToken token); @@ -91,10 +90,9 @@ public interface StatelessTicketCache { * *

* Implementations should use {@link CasAuthenticationToken#getCredentials()} to - * obtain the ticket and then delegate to the - * {@link #removeTicketFromCache(String)} method. + * obtain the ticket and then delegate to the {@link #removeTicketFromCache(String)} + * method. *

- * * @param token to be removed */ void removeTicketFromCache(CasAuthenticationToken token); @@ -107,8 +105,8 @@ public interface StatelessTicketCache { * This is in case applications wish to provide a session termination capability for * their stateless clients. *

- * * @param serviceTicket to be removed */ void removeTicketFromCache(String serviceTicket); + } diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/package-info.java b/cas/src/main/java/org/springframework/security/cas/authentication/package-info.java index 240f124bb9..c951b0f08b 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/package-info.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * An {@code AuthenticationProvider} that can process CAS service tickets and proxy tickets. + * An {@code AuthenticationProvider} that can process CAS service tickets and proxy + * tickets. */ package org.springframework.security.cas.authentication; - diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java index 3085f92d95..ae16b228c0 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AssertionImplMixin.java @@ -23,31 +23,32 @@ import java.util.Date; import java.util.Map; /** - * Helps in jackson deserialization of class {@link org.jasig.cas.client.validation.AssertionImpl}, which is - * used with {@link org.springframework.security.cas.authentication.CasAuthenticationToken}. - * To use this class we need to register with {@link com.fasterxml.jackson.databind.ObjectMapper}. Type information - * will be stored in @class property. + * Helps in jackson deserialization of class + * {@link org.jasig.cas.client.validation.AssertionImpl}, which is used with + * {@link org.springframework.security.cas.authentication.CasAuthenticationToken}. To use + * this class we need to register with + * {@link com.fasterxml.jackson.databind.ObjectMapper}. Type information will be stored + * in @class property. *

*

  *     ObjectMapper mapper = new ObjectMapper();
  *     mapper.registerModule(new CasJackson2Module());
  * 
* - * * @author Jitendra Singh * @see CasJackson2Module * @see org.springframework.security.jackson2.SecurityJackson2Modules * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) -@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, - getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE) +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, + isGetterVisibility = JsonAutoDetect.Visibility.NONE) @JsonIgnoreProperties(ignoreUnknown = true) class AssertionImplMixin { /** - * Mixin Constructor helps in deserialize {@link org.jasig.cas.client.validation.AssertionImpl} - * + * Mixin Constructor helps in deserialize + * {@link org.jasig.cas.client.validation.AssertionImpl} * @param principal the Principal to associate with the Assertion. * @param validFromDate when the assertion is valid from. * @param validUntilDate when the assertion is valid to. @@ -56,7 +57,9 @@ class AssertionImplMixin { */ @JsonCreator AssertionImplMixin(@JsonProperty("principal") AttributePrincipal principal, - @JsonProperty("validFromDate") Date validFromDate, @JsonProperty("validUntilDate") Date validUntilDate, - @JsonProperty("authenticationDate") Date authenticationDate, @JsonProperty("attributes") Map attributes){ + @JsonProperty("validFromDate") Date validFromDate, @JsonProperty("validUntilDate") Date validUntilDate, + @JsonProperty("authenticationDate") Date authenticationDate, + @JsonProperty("attributes") Map attributes) { } + } diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java index ddc326704f..ca4e28d805 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/AttributePrincipalImplMixin.java @@ -22,9 +22,10 @@ import org.jasig.cas.client.proxy.ProxyRetriever; import java.util.Map; /** - * Helps in deserialize {@link org.jasig.cas.client.authentication.AttributePrincipalImpl} which is used with - * {@link org.springframework.security.cas.authentication.CasAuthenticationToken}. Type information will be stored - * in property named @class. + * Helps in deserialize {@link org.jasig.cas.client.authentication.AttributePrincipalImpl} + * which is used with + * {@link org.springframework.security.cas.authentication.CasAuthenticationToken}. Type + * information will be stored in property named @class. *

*

  *     ObjectMapper mapper = new ObjectMapper();
@@ -43,16 +44,19 @@ import java.util.Map;
 class AttributePrincipalImplMixin {
 
 	/**
-	 * Mixin Constructor helps in deserialize {@link org.jasig.cas.client.authentication.AttributePrincipalImpl}
-	 *
+	 * Mixin Constructor helps in deserialize
+	 * {@link org.jasig.cas.client.authentication.AttributePrincipalImpl}
 	 * @param name the unique identifier for the principal.
 	 * @param attributes the key/value pairs for this principal.
 	 * @param proxyGrantingTicket the ticket associated with this principal.
-	 * @param proxyRetriever the ProxyRetriever implementation to call back to the CAS server.
+	 * @param proxyRetriever the ProxyRetriever implementation to call back to the CAS
+	 * server.
 	 */
 	@JsonCreator
-	AttributePrincipalImplMixin(@JsonProperty("name") String name, @JsonProperty("attributes") Map attributes,
-										@JsonProperty("proxyGrantingTicket") String proxyGrantingTicket,
-										@JsonProperty("proxyRetriever") ProxyRetriever proxyRetriever) {
+	AttributePrincipalImplMixin(@JsonProperty("name") String name,
+			@JsonProperty("attributes") Map attributes,
+			@JsonProperty("proxyGrantingTicket") String proxyGrantingTicket,
+			@JsonProperty("proxyRetriever") ProxyRetriever proxyRetriever) {
 	}
+
 }
diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java b/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java
index dba9e0521e..bf7dacde49 100644
--- a/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java
+++ b/cas/src/main/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixin.java
@@ -26,11 +26,12 @@ import org.springframework.security.core.userdetails.UserDetails;
 import java.util.Collection;
 
 /**
- * Mixin class which helps in deserialize {@link org.springframework.security.cas.authentication.CasAuthenticationToken}
- * using jackson. Two more dependent classes needs to register along with this mixin class.
+ * Mixin class which helps in deserialize
+ * {@link org.springframework.security.cas.authentication.CasAuthenticationToken} using
+ * jackson. Two more dependent classes needs to register along with this mixin class.
  * 
    - *
  1. {@link org.springframework.security.cas.jackson2.AssertionImplMixin}
  2. - *
  3. {@link org.springframework.security.cas.jackson2.AttributePrincipalImplMixin}
  4. + *
  5. {@link org.springframework.security.cas.jackson2.AssertionImplMixin}
  6. + *
  7. {@link org.springframework.security.cas.jackson2.AttributePrincipalImplMixin}
  8. *
* *

@@ -53,7 +54,6 @@ class CasAuthenticationTokenMixin { /** * Mixin Constructor helps in deserialize {@link CasAuthenticationToken} - * * @param keyHash hashCode of provided key to identify if this object made by a given * {@link CasAuthenticationProvider} * @param principal typically the UserDetails object (cannot be null) @@ -70,8 +70,9 @@ class CasAuthenticationTokenMixin { */ @JsonCreator CasAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, - @JsonProperty("credentials") Object credentials, - @JsonProperty("authorities") Collection authorities, - @JsonProperty("userDetails") UserDetails userDetails, @JsonProperty("assertion") Assertion assertion) { + @JsonProperty("credentials") Object credentials, + @JsonProperty("authorities") Collection authorities, + @JsonProperty("userDetails") UserDetails userDetails, @JsonProperty("assertion") Assertion assertion) { } + } diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java b/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java index 5d2e99370d..2042e967fa 100644 --- a/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java +++ b/cas/src/main/java/org/springframework/security/cas/jackson2/CasJackson2Module.java @@ -24,16 +24,17 @@ import org.springframework.security.cas.authentication.CasAuthenticationToken; import org.springframework.security.jackson2.SecurityJackson2Modules; /** - * Jackson module for spring-security-cas. This module register {@link AssertionImplMixin}, - * {@link AttributePrincipalImplMixin} and {@link CasAuthenticationTokenMixin}. If no default typing enabled by default then - * it'll enable it because typing info is needed to properly serialize/deserialize objects. In order to use this module just - * add this module into your ObjectMapper configuration. + * Jackson module for spring-security-cas. This module register + * {@link AssertionImplMixin}, {@link AttributePrincipalImplMixin} and + * {@link CasAuthenticationTokenMixin}. If no default typing enabled by default then it'll + * enable it because typing info is needed to properly serialize/deserialize objects. In + * order to use this module just add this module into your ObjectMapper configuration. * *

  *     ObjectMapper mapper = new ObjectMapper();
  *     mapper.registerModule(new CasJackson2Module());
- * 
- * Note: use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get list of all security modules on the classpath. + *
Note: use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get list + * of all security modules on the classpath. * * @author Jitendra Singh. * @see org.springframework.security.jackson2.SecurityJackson2Modules @@ -52,4 +53,5 @@ public class CasJackson2Module extends SimpleModule { context.setMixInAnnotations(AttributePrincipalImpl.class, AttributePrincipalImplMixin.class); context.setMixInAnnotations(CasAuthenticationToken.class, CasAuthenticationTokenMixin.class); } + } diff --git a/cas/src/main/java/org/springframework/security/cas/package-info.java b/cas/src/main/java/org/springframework/security/cas/package-info.java index 8ce8a88b5a..87b0b093f8 100644 --- a/cas/src/main/java/org/springframework/security/cas/package-info.java +++ b/cas/src/main/java/org/springframework/security/cas/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Spring Security support for Jasig's Central Authentication Service (CAS). + * Spring Security support for Jasig's Central Authentication Service + * (CAS). */ package org.springframework.security.cas; - diff --git a/cas/src/main/java/org/springframework/security/cas/userdetails/AbstractCasAssertionUserDetailsService.java b/cas/src/main/java/org/springframework/security/cas/userdetails/AbstractCasAssertionUserDetailsService.java index bb4770eb05..235c5fadfd 100644 --- a/cas/src/main/java/org/springframework/security/cas/userdetails/AbstractCasAssertionUserDetailsService.java +++ b/cas/src/main/java/org/springframework/security/cas/userdetails/AbstractCasAssertionUserDetailsService.java @@ -28,8 +28,8 @@ import org.springframework.security.core.userdetails.UserDetails; * @author Scott Battaglia * @since 3.0 */ -public abstract class AbstractCasAssertionUserDetailsService implements - AuthenticationUserDetailsService { +public abstract class AbstractCasAssertionUserDetailsService + implements AuthenticationUserDetailsService { public final UserDetails loadUserDetails(final CasAssertionAuthenticationToken token) { return loadUserDetails(token.getAssertion()); @@ -39,10 +39,10 @@ public abstract class AbstractCasAssertionUserDetailsService implements * Protected template method for construct a * {@link org.springframework.security.core.userdetails.UserDetails} via the supplied * CAS assertion. - * * @param assertion the assertion to use to construct the new UserDetails. CANNOT be * NULL. * @return the newly constructed UserDetails. */ protected abstract UserDetails loadUserDetails(Assertion assertion); + } diff --git a/cas/src/main/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsService.java b/cas/src/main/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsService.java index 93f03eeabe..d160a6c091 100644 --- a/cas/src/main/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsService.java +++ b/cas/src/main/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsService.java @@ -34,8 +34,8 @@ import java.util.ArrayList; * @author Scott Battaglia * @since 3.0 */ -public final class GrantedAuthorityFromAssertionAttributesUserDetailsService extends - AbstractCasAssertionUserDetailsService { +public final class GrantedAuthorityFromAssertionAttributesUserDetailsService + extends AbstractCasAssertionUserDetailsService { private static final String NON_EXISTENT_PASSWORD_VALUE = "NO_PASSWORD"; @@ -43,11 +43,9 @@ public final class GrantedAuthorityFromAssertionAttributesUserDetailsService ext private boolean convertToUpperCase = true; - public GrantedAuthorityFromAssertionAttributesUserDetailsService( - final String[] attributes) { + public GrantedAuthorityFromAssertionAttributesUserDetailsService(final String[] attributes) { Assert.notNull(attributes, "attributes cannot be null."); - Assert.isTrue(attributes.length > 0, - "At least one attribute is required to retrieve roles from."); + Assert.isTrue(attributes.length > 0, "At least one attribute is required to retrieve roles from."); this.attributes = attributes; } @@ -68,29 +66,27 @@ public final class GrantedAuthorityFromAssertionAttributesUserDetailsService ext for (final Object o : list) { grantedAuthorities.add(new SimpleGrantedAuthority( - this.convertToUpperCase ? o.toString().toUpperCase() : o - .toString())); + this.convertToUpperCase ? o.toString().toUpperCase() : o.toString())); } } else { grantedAuthorities.add(new SimpleGrantedAuthority( - this.convertToUpperCase ? value.toString().toUpperCase() : value - .toString())); + this.convertToUpperCase ? value.toString().toUpperCase() : value.toString())); } } - return new User(assertion.getPrincipal().getName(), NON_EXISTENT_PASSWORD_VALUE, - true, true, true, true, grantedAuthorities); + return new User(assertion.getPrincipal().getName(), NON_EXISTENT_PASSWORD_VALUE, true, true, true, true, + grantedAuthorities); } /** * Converts the returned attribute values to uppercase values. - * * @param convertToUpperCase true if it should convert, false otherwise. */ public void setConvertToUpperCase(final boolean convertToUpperCase) { this.convertToUpperCase = convertToUpperCase; } + } diff --git a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java index 9742fde7d5..4e8d8a63f3 100644 --- a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java +++ b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java @@ -42,8 +42,8 @@ import org.springframework.util.Assert; * @author Ben Alex * @author Scott Battaglia */ -public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, - InitializingBean { +public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, InitializingBean { + // ~ Instance fields // ================================================================================================ private ServiceProperties serviceProperties; @@ -67,12 +67,10 @@ public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, public void afterPropertiesSet() { Assert.hasLength(this.loginUrl, "loginUrl must be specified"); Assert.notNull(this.serviceProperties, "serviceProperties must be specified"); - Assert.notNull(this.serviceProperties.getService(), - "serviceProperties.getService() cannot be null."); + Assert.notNull(this.serviceProperties.getService(), "serviceProperties.getService() cannot be null."); } - public final void commence(final HttpServletRequest servletRequest, - final HttpServletResponse response, + public final void commence(final HttpServletRequest servletRequest, final HttpServletResponse response, final AuthenticationException authenticationException) throws IOException { final String urlEncodedService = createServiceUrl(servletRequest, response); @@ -90,42 +88,34 @@ public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, * @param response the HttpServlet Response * @return the constructed service url. CANNOT be NULL. */ - protected String createServiceUrl(final HttpServletRequest request, - final HttpServletResponse response) { - return CommonUtils.constructServiceUrl(null, response, - this.serviceProperties.getService(), null, - this.serviceProperties.getArtifactParameter(), - this.encodeServiceUrlWithSessionId); + protected String createServiceUrl(final HttpServletRequest request, final HttpServletResponse response) { + return CommonUtils.constructServiceUrl(null, response, this.serviceProperties.getService(), null, + this.serviceProperties.getArtifactParameter(), this.encodeServiceUrlWithSessionId); } /** * Constructs the Url for Redirection to the CAS server. Default implementation relies * on the CAS client to do the bulk of the work. - * * @param serviceUrl the service url that should be included. * @return the redirect url. CANNOT be NULL. */ protected String createRedirectUrl(final String serviceUrl) { - return CommonUtils.constructRedirectUrl(this.loginUrl, - this.serviceProperties.getServiceParameter(), serviceUrl, + return CommonUtils.constructRedirectUrl(this.loginUrl, this.serviceProperties.getServiceParameter(), serviceUrl, this.serviceProperties.isSendRenew(), false); } /** * Template method for you to do your own pre-processing before the redirect occurs. - * * @param request the HttpServletRequest * @param response the HttpServletResponse */ - protected void preCommence(final HttpServletRequest request, - final HttpServletResponse response) { + protected void preCommence(final HttpServletRequest request, final HttpServletResponse response) { } /** * The enterprise-wide CAS login URL. Usually something like * https://www.mycompany.com/cas/login. - * * @return the enterprise-wide CAS login URL */ public final String getLoginUrl() { @@ -146,12 +136,10 @@ public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, /** * Sets whether to encode the service url with the session id or not. - * * @param encodeServiceUrlWithSessionId whether to encode the service url with the * session id or not. */ - public final void setEncodeServiceUrlWithSessionId( - final boolean encodeServiceUrlWithSessionId) { + public final void setEncodeServiceUrlWithSessionId(final boolean encodeServiceUrlWithSessionId) { this.encodeServiceUrlWithSessionId = encodeServiceUrlWithSessionId; } @@ -163,4 +151,5 @@ public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, protected boolean getEncodeServiceUrlWithSessionId() { return this.encodeServiceUrlWithSessionId; } + } diff --git a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java index 7ff21e2480..e88e85b0cb 100644 --- a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java +++ b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java @@ -45,7 +45,8 @@ import org.springframework.util.Assert; /** * Processes a CAS service ticket, obtains proxy granting tickets, and processes proxy - * tickets.

Service Tickets

+ * tickets. + *

Service Tickets

*

* A service ticket consists of an opaque ticket string. It arrives at this filter by the * user's browser successfully authenticating using CAS, and then receiving a HTTP @@ -171,10 +172,13 @@ import org.springframework.util.Assert; * @author Rob Winch */ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFilter { + // ~ Static fields/initializers // ===================================================================================== - /** Used to identify a CAS request for a stateful user agent, such as a web browser. */ + /** + * Used to identify a CAS request for a stateful user agent, such as a web browser. + */ public static final String CAS_STATEFUL_IDENTIFIER = "_cas_stateful_"; /** @@ -213,48 +217,41 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil // ======================================================================================================== @Override - protected final void successfulAuthentication(HttpServletRequest request, - HttpServletResponse response, FilterChain chain, Authentication authResult) - throws IOException, ServletException { - boolean continueFilterChain = proxyTicketRequest( - serviceTicketRequest(request, response), request); + protected final void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, + FilterChain chain, Authentication authResult) throws IOException, ServletException { + boolean continueFilterChain = proxyTicketRequest(serviceTicketRequest(request, response), request); if (!continueFilterChain) { super.successfulAuthentication(request, response, chain, authResult); return; } if (logger.isDebugEnabled()) { - logger.debug("Authentication success. Updating SecurityContextHolder to contain: " - + authResult); + logger.debug("Authentication success. Updating SecurityContextHolder to contain: " + authResult); } SecurityContextHolder.getContext().setAuthentication(authResult); // Fire event if (this.eventPublisher != null) { - eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent( - authResult, this.getClass())); + eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass())); } chain.doFilter(request, response); } @Override - public Authentication attemptAuthentication(final HttpServletRequest request, - final HttpServletResponse response) throws AuthenticationException, - IOException { + public Authentication attemptAuthentication(final HttpServletRequest request, final HttpServletResponse response) + throws AuthenticationException, IOException { // if the request is a proxy request process it and return null to indicate the // request has been processed if (proxyReceptorRequest(request)) { logger.debug("Responding to proxy receptor request"); - CommonUtils.readAndRespondToProxyReceptorRequest(request, response, - this.proxyGrantingTicketStorage); + CommonUtils.readAndRespondToProxyReceptorRequest(request, response, this.proxyGrantingTicketStorage); return null; } final boolean serviceTicketRequest = serviceTicketRequest(request, response); - final String username = serviceTicketRequest ? CAS_STATEFUL_IDENTIFIER - : CAS_STATELESS_IDENTIFIER; + final String username = serviceTicketRequest ? CAS_STATEFUL_IDENTIFIER : CAS_STATELESS_IDENTIFIER; String password = obtainArtifact(request); if (password == null) { @@ -262,8 +259,8 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil password = ""; } - final UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( - username, password); + final UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, + password); authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); @@ -282,8 +279,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil /** * Overridden to provide proxying capabilities. */ - protected boolean requiresAuthentication(final HttpServletRequest request, - final HttpServletResponse response) { + protected boolean requiresAuthentication(final HttpServletRequest request, final HttpServletResponse response) { final boolean serviceTicketRequest = serviceTicketRequest(request, response); final boolean result = serviceTicketRequest || proxyReceptorRequest(request) || (proxyTicketRequest(serviceTicketRequest, request)); @@ -297,8 +293,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil * Sets the {@link AuthenticationFailureHandler} for proxy requests. * @param proxyFailureHandler */ - public final void setProxyAuthenticationFailureHandler( - AuthenticationFailureHandler proxyFailureHandler) { + public final void setProxyAuthenticationFailureHandler(AuthenticationFailureHandler proxyFailureHandler) { Assert.notNull(proxyFailureHandler, "proxyFailureHandler cannot be null"); this.proxyFailureHandler = proxyFailureHandler; } @@ -308,18 +303,15 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil * proxy ticket authentication failures and service ticket failures. */ @Override - public final void setAuthenticationFailureHandler( - AuthenticationFailureHandler failureHandler) { - super.setAuthenticationFailureHandler(new CasAuthenticationFailureHandler( - failureHandler)); + public final void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) { + super.setAuthenticationFailureHandler(new CasAuthenticationFailureHandler(failureHandler)); } public final void setProxyReceptorUrl(final String proxyReceptorUrl) { this.proxyReceptorMatcher = new AntPathRequestMatcher("/**" + proxyReceptorUrl); } - public final void setProxyGrantingTicketStorage( - final ProxyGrantingTicketStorage proxyGrantingTicketStorage) { + public final void setProxyGrantingTicketStorage(final ProxyGrantingTicketStorage proxyGrantingTicketStorage) { this.proxyGrantingTicketStorage = proxyGrantingTicketStorage; } @@ -335,8 +327,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil * @param response * @return */ - private boolean serviceTicketRequest(final HttpServletRequest request, - final HttpServletResponse response) { + private boolean serviceTicketRequest(final HttpServletRequest request, final HttpServletResponse response) { boolean result = super.requiresAuthentication(request, response); if (logger.isDebugEnabled()) { logger.debug("serviceTicketRequest = " + result); @@ -349,13 +340,11 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil * @param request * @return */ - private boolean proxyTicketRequest(final boolean serviceTicketRequest, - final HttpServletRequest request) { + private boolean proxyTicketRequest(final boolean serviceTicketRequest, final HttpServletRequest request) { if (serviceTicketRequest) { return false; } - final boolean result = authenticateAllArtifacts - && obtainArtifact(request) != null && !authenticated(); + final boolean result = authenticateAllArtifacts && obtainArtifact(request) != null && !authenticated(); if (logger.isDebugEnabled()) { logger.debug("proxyTicketRequest = " + result); } @@ -367,8 +356,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil * @return */ private boolean authenticated() { - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); return authentication != null && authentication.isAuthenticated() && !(authentication instanceof AnonymousAuthenticationToken); } @@ -379,8 +367,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil * @return */ private boolean proxyReceptorRequest(final HttpServletRequest request) { - final boolean result = proxyReceptorConfigured() - && proxyReceptorMatcher.matches(request); + final boolean result = proxyReceptorConfigured() && proxyReceptorMatcher.matches(request); if (logger.isDebugEnabled()) { logger.debug("proxyReceptorRequest = " + result); } @@ -390,12 +377,10 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil /** * Determines if the {@link CasAuthenticationFilter} is configured to handle the proxy * receptor requests. - * * @return */ private boolean proxyReceptorConfigured() { - final boolean result = this.proxyGrantingTicketStorage != null - && proxyReceptorMatcher != null; + final boolean result = this.proxyGrantingTicketStorage != null && proxyReceptorMatcher != null; if (logger.isDebugEnabled()) { logger.debug("proxyReceptorConfigured = " + result); } @@ -413,6 +398,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil * @author Rob Winch */ private class CasAuthenticationFailureHandler implements AuthenticationFailureHandler { + private final AuthenticationFailureHandler serviceTicketFailureHandler; CasAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) { @@ -420,16 +406,16 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil this.serviceTicketFailureHandler = failureHandler; } - public void onAuthenticationFailure(HttpServletRequest request, - HttpServletResponse response, AuthenticationException exception) - throws IOException, ServletException { + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, + AuthenticationException exception) throws IOException, ServletException { if (serviceTicketRequest(request, response)) { - serviceTicketFailureHandler.onAuthenticationFailure(request, response, - exception); + serviceTicketFailureHandler.onAuthenticationFailure(request, response, exception); } else { proxyFailureHandler.onAuthenticationFailure(request, response, exception); } } + } + } diff --git a/cas/src/main/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetails.java b/cas/src/main/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetails.java index cac9cd1643..271359abc1 100644 --- a/cas/src/main/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetails.java +++ b/cas/src/main/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetails.java @@ -34,6 +34,7 @@ import org.springframework.util.Assert; */ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails implements ServiceAuthenticationDetails { + private static final long serialVersionUID = 6192409090610517700L; // ~ Instance fields @@ -52,14 +53,14 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails * string from containing the artifact name and value. This can be created using * {@link #createArtifactPattern(String)}. */ - DefaultServiceAuthenticationDetails(String casService, HttpServletRequest request, - Pattern artifactPattern) throws MalformedURLException { + DefaultServiceAuthenticationDetails(String casService, HttpServletRequest request, Pattern artifactPattern) + throws MalformedURLException { super(request); URL casServiceUrl = new URL(casService); int port = getServicePort(casServiceUrl); final String query = getQueryString(request, artifactPattern); - this.serviceUrl = UrlUtils.buildFullRequestUrl(casServiceUrl.getProtocol(), - casServiceUrl.getHost(), port, request.getRequestURI(), query); + this.serviceUrl = UrlUtils.buildFullRequestUrl(casServiceUrl.getProtocol(), casServiceUrl.getHost(), port, + request.getRequestURI(), query); } // ~ Methods @@ -109,8 +110,7 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails * @return the query String minus the artifactParameterName and the corresponding * value. */ - private String getQueryString(final HttpServletRequest request, - final Pattern artifactPattern) { + private String getQueryString(final HttpServletRequest request, final Pattern artifactPattern) { final String query = request.getQueryString(); if (query == null) { return null; @@ -127,7 +127,6 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails * Creates a {@link Pattern} that can be passed into the constructor. This allows the * {@link Pattern} to be reused for every instance of * {@link DefaultServiceAuthenticationDetails}. - * * @param artifactParameterName * @return */ @@ -150,4 +149,5 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails } return port; } + } \ No newline at end of file diff --git a/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetails.java b/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetails.java index 80f9e23803..5bf790dcc1 100644 --- a/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetails.java +++ b/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetails.java @@ -28,15 +28,14 @@ import org.springframework.security.core.Authentication; * {@link ServiceProperties#getService()}. * * @author Rob Winch - * * @see ServiceAuthenticationDetailsSource */ public interface ServiceAuthenticationDetails extends Serializable { /** * Gets the absolute service url (i.e. https://example.com/service/). - * * @return the service url. Cannot be null. */ String getServiceUrl(); + } \ No newline at end of file diff --git a/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetailsSource.java b/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetailsSource.java index c323bb491b..1e3c0ecbcc 100644 --- a/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetailsSource.java +++ b/cas/src/main/java/org/springframework/security/cas/web/authentication/ServiceAuthenticationDetailsSource.java @@ -34,8 +34,9 @@ import org.springframework.util.Assert; * * @author Rob Winch */ -public class ServiceAuthenticationDetailsSource implements - AuthenticationDetailsSource { +public class ServiceAuthenticationDetailsSource + implements AuthenticationDetailsSource { + // ~ Instance fields // ================================================================================================ @@ -49,7 +50,6 @@ public class ServiceAuthenticationDetailsSource implements /** * Creates an implementation that uses the specified ServiceProperties and the default * CAS artifactParameterName. - * * @param serviceProperties The ServiceProperties to use to construct the serviceUrl. */ public ServiceAuthenticationDetailsSource(ServiceProperties serviceProperties) { @@ -58,18 +58,15 @@ public class ServiceAuthenticationDetailsSource implements /** * Creates an implementation that uses the specified artifactParameterName - * * @param serviceProperties The ServiceProperties to use to construct the serviceUrl. * @param artifactParameterName the artifactParameterName that is removed from the * current URL. The result becomes the service url. Cannot be null and cannot be an * empty String. */ - public ServiceAuthenticationDetailsSource(ServiceProperties serviceProperties, - String artifactParameterName) { + public ServiceAuthenticationDetailsSource(ServiceProperties serviceProperties, String artifactParameterName) { Assert.notNull(serviceProperties, "serviceProperties cannot be null"); this.serviceProperties = serviceProperties; - this.artifactPattern = DefaultServiceAuthenticationDetails - .createArtifactPattern(artifactParameterName); + this.artifactPattern = DefaultServiceAuthenticationDetails.createArtifactPattern(artifactParameterName); } // ~ Methods @@ -82,11 +79,11 @@ public class ServiceAuthenticationDetailsSource implements */ public ServiceAuthenticationDetails buildDetails(HttpServletRequest context) { try { - return new DefaultServiceAuthenticationDetails( - serviceProperties.getService(), context, artifactPattern); + return new DefaultServiceAuthenticationDetails(serviceProperties.getService(), context, artifactPattern); } catch (MalformedURLException e) { throw new RuntimeException(e); } } + } \ No newline at end of file diff --git a/cas/src/main/java/org/springframework/security/cas/web/authentication/package-info.java b/cas/src/main/java/org/springframework/security/cas/web/authentication/package-info.java index b7be180138..f774c00ef9 100644 --- a/cas/src/main/java/org/springframework/security/cas/web/authentication/package-info.java +++ b/cas/src/main/java/org/springframework/security/cas/web/authentication/package-info.java @@ -18,4 +18,3 @@ * credentials using CAS. */ package org.springframework.security.cas.web.authentication; - diff --git a/cas/src/main/java/org/springframework/security/cas/web/package-info.java b/cas/src/main/java/org/springframework/security/cas/web/package-info.java index 21781af725..b37f7e89f2 100644 --- a/cas/src/main/java/org/springframework/security/cas/web/package-info.java +++ b/cas/src/main/java/org/springframework/security/cas/web/package-info.java @@ -17,4 +17,3 @@ * Authenticates standard web browser users via CAS. */ package org.springframework.security.cas.web; - diff --git a/cas/src/test/java/org/springframework/security/cas/authentication/AbstractStatelessTicketCacheTests.java b/cas/src/test/java/org/springframework/security/cas/authentication/AbstractStatelessTicketCacheTests.java index ec009058a7..c31b9f9aa3 100644 --- a/cas/src/test/java/org/springframework/security/cas/authentication/AbstractStatelessTicketCacheTests.java +++ b/cas/src/test/java/org/springframework/security/cas/authentication/AbstractStatelessTicketCacheTests.java @@ -25,7 +25,6 @@ import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.User; /** - * * @author Scott Battaglia * @since 2.0 * @@ -41,8 +40,7 @@ public abstract class AbstractStatelessTicketCacheTests { final Assertion assertion = new AssertionImpl("rod"); return new CasAuthenticationToken("key", user, "ST-0-ER94xMJmn6pha35CQRoZ", - AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), user, - assertion); + AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), user, assertion); } } diff --git a/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationProviderTests.java b/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationProviderTests.java index c39fdf8cfd..dca51ceddf 100644 --- a/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationProviderTests.java +++ b/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationProviderTests.java @@ -49,6 +49,7 @@ import java.util.*; */ @SuppressWarnings("unchecked") public class CasAuthenticationProviderTests { + // ~ Methods // ======================================================================================================== @@ -99,10 +100,8 @@ public class CasAuthenticationProviderTests { CasAuthenticationToken casResult = (CasAuthenticationToken) result; assertThat(casResult.getPrincipal()).isEqualTo(makeUserDetailsFromAuthoritiesPopulator()); assertThat(casResult.getCredentials()).isEqualTo("ST-123"); - assertThat(casResult.getAuthorities()).contains( - new SimpleGrantedAuthority("ROLE_A")); - assertThat(casResult.getAuthorities()).contains( - new SimpleGrantedAuthority("ROLE_B")); + assertThat(casResult.getAuthorities()).contains(new SimpleGrantedAuthority("ROLE_A")); + assertThat(casResult.getAuthorities()).contains(new SimpleGrantedAuthority("ROLE_B")); assertThat(casResult.getKeyHash()).isEqualTo(cap.getKey().hashCode()); assertThat(casResult.getDetails()).isEqualTo("details"); @@ -159,8 +158,7 @@ public class CasAuthenticationProviderTests { ServiceAuthenticationDetails details = mock(ServiceAuthenticationDetails.class); when(details.getServiceUrl()).thenReturn(serviceUrl); TicketValidator validator = mock(TicketValidator.class); - when(validator.validate(any(String.class), any(String.class))).thenReturn( - new AssertionImpl("rod")); + when(validator.validate(any(String.class), any(String.class))).thenReturn(new AssertionImpl("rod")); ServiceProperties serviceProperties = makeServiceProperties(); serviceProperties.setAuthenticateAllArtifacts(true); @@ -186,8 +184,7 @@ public class CasAuthenticationProviderTests { ServiceAuthenticationDetails details = mock(ServiceAuthenticationDetails.class); when(details.getServiceUrl()).thenReturn(serviceUrl); TicketValidator validator = mock(TicketValidator.class); - when(validator.validate(any(String.class), any(String.class))).thenReturn( - new AssertionImpl("rod")); + when(validator.validate(any(String.class), any(String.class))).thenReturn(new AssertionImpl("rod")); ServiceProperties serviceProperties = makeServiceProperties(); serviceProperties.setAuthenticateAllArtifacts(true); @@ -271,8 +268,7 @@ public class CasAuthenticationProviderTests { cap.setServiceProperties(makeServiceProperties()); cap.afterPropertiesSet(); - CasAuthenticationToken token = new CasAuthenticationToken("WRONG_KEY", - makeUserDetails(), "credentials", + CasAuthenticationToken token = new CasAuthenticationToken("WRONG_KEY", makeUserDetails(), "credentials", AuthorityUtils.createAuthorityList("XX"), makeUserDetails(), assertion); cap.authenticate(token); @@ -347,8 +343,7 @@ public class CasAuthenticationProviderTests { cap.setServiceProperties(makeServiceProperties()); cap.afterPropertiesSet(); - TestingAuthenticationToken token = new TestingAuthenticationToken("user", - "password", "ROLE_A"); + TestingAuthenticationToken token = new TestingAuthenticationToken("user", "password", "ROLE_A"); assertThat(cap.supports(TestingAuthenticationToken.class)).isFalse(); // Try it anyway @@ -356,8 +351,7 @@ public class CasAuthenticationProviderTests { } @Test - public void ignoresUsernamePasswordAuthenticationTokensWithoutCasIdentifiersAsPrincipal() - throws Exception { + public void ignoresUsernamePasswordAuthenticationTokensWithoutCasIdentifiersAsPrincipal() throws Exception { CasAuthenticationProvider cap = new CasAuthenticationProvider(); cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator()); cap.setKey("qwerty"); @@ -366,9 +360,8 @@ public class CasAuthenticationProviderTests { cap.setServiceProperties(makeServiceProperties()); cap.afterPropertiesSet(); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "some_normal_user", "password", - AuthorityUtils.createAuthorityList("ROLE_A")); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("some_normal_user", + "password", AuthorityUtils.createAuthorityList("ROLE_A")); assertThat(cap.authenticate(token)).isNull(); } @@ -384,13 +377,14 @@ public class CasAuthenticationProviderTests { private class MockAuthoritiesPopulator implements AuthenticationUserDetailsService { - public UserDetails loadUserDetails(final Authentication token) - throws UsernameNotFoundException { + public UserDetails loadUserDetails(final Authentication token) throws UsernameNotFoundException { return makeUserDetailsFromAuthoritiesPopulator(); } + } private class MockStatelessTicketCache implements StatelessTicketCache { + private Map cache = new HashMap<>(); public CasAuthenticationToken getByTicketId(String serviceTicket) { @@ -408,9 +402,11 @@ public class CasAuthenticationProviderTests { public void removeTicketFromCache(String serviceTicket) { throw new UnsupportedOperationException("mock method not implemented"); } + } private class MockTicketValidator implements TicketValidator { + private boolean returnTicket; MockTicketValidator(boolean returnTicket) { @@ -423,5 +419,7 @@ public class CasAuthenticationProviderTests { } throw new BadCredentialsException("As requested from mock"); } + } + } diff --git a/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationTokenTests.java b/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationTokenTests.java index 920b8d9c18..c9a9e0c526 100644 --- a/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationTokenTests.java +++ b/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationTokenTests.java @@ -39,8 +39,7 @@ import org.springframework.security.core.userdetails.UserDetails; */ public class CasAuthenticationTokenTests { - private final List ROLES = AuthorityUtils.createAuthorityList( - "ROLE_ONE", "ROLE_TWO"); + private final List ROLES = AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"); private UserDetails makeUserDetails() { return makeUserDetails("user"); @@ -54,40 +53,35 @@ public class CasAuthenticationTokenTests { public void testConstructorRejectsNulls() { final Assertion assertion = new AssertionImpl("test"); try { - new CasAuthenticationToken(null, makeUserDetails(), "Password", ROLES, - makeUserDetails(), assertion); + new CasAuthenticationToken(null, makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { } try { - new CasAuthenticationToken("key", null, "Password", ROLES, makeUserDetails(), - assertion); + new CasAuthenticationToken("key", null, "Password", ROLES, makeUserDetails(), assertion); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { } try { - new CasAuthenticationToken("key", makeUserDetails(), null, ROLES, - makeUserDetails(), assertion); + new CasAuthenticationToken("key", makeUserDetails(), null, ROLES, makeUserDetails(), assertion); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { } try { - new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, - makeUserDetails(), null); + new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, makeUserDetails(), null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { } try { - new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, null, - assertion); + new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, null, assertion); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { @@ -95,8 +89,7 @@ public class CasAuthenticationTokenTests { try { new CasAuthenticationToken("key", makeUserDetails(), "Password", - AuthorityUtils.createAuthorityList("ROLE_1", null), makeUserDetails(), - assertion); + AuthorityUtils.createAuthorityList("ROLE_1", null), makeUserDetails(), assertion); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { @@ -113,11 +106,11 @@ public class CasAuthenticationTokenTests { public void testEqualsWhenEqual() { final Assertion assertion = new AssertionImpl("test"); - CasAuthenticationToken token1 = new CasAuthenticationToken("key", - makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion); + CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, + makeUserDetails(), assertion); - CasAuthenticationToken token2 = new CasAuthenticationToken("key", - makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion); + CasAuthenticationToken token2 = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, + makeUserDetails(), assertion); assertThat(token2).isEqualTo(token1); } @@ -126,18 +119,15 @@ public class CasAuthenticationTokenTests { public void testGetters() { // Build the proxy list returned in the ticket from CAS final Assertion assertion = new AssertionImpl("test"); - CasAuthenticationToken token = new CasAuthenticationToken("key", - makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion); + CasAuthenticationToken token = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, + makeUserDetails(), assertion); assertThat(token.getKeyHash()).isEqualTo("key".hashCode()); assertThat(token.getPrincipal()).isEqualTo(makeUserDetails()); assertThat(token.getCredentials()).isEqualTo("Password"); - assertThat(token.getAuthorities()).contains( - new SimpleGrantedAuthority("ROLE_ONE")); - assertThat(token.getAuthorities()).contains( - new SimpleGrantedAuthority("ROLE_TWO")); + assertThat(token.getAuthorities()).contains(new SimpleGrantedAuthority("ROLE_ONE")); + assertThat(token.getAuthorities()).contains(new SimpleGrantedAuthority("ROLE_TWO")); assertThat(token.getAssertion()).isEqualTo(assertion); - assertThat(token.getUserDetails().getUsername()).isEqualTo( - makeUserDetails().getUsername()); + assertThat(token.getUserDetails().getUsername()).isEqualTo(makeUserDetails().getUsername()); } @Test @@ -155,12 +145,11 @@ public class CasAuthenticationTokenTests { public void testNotEqualsDueToAbstractParentEqualsCheck() { final Assertion assertion = new AssertionImpl("test"); - CasAuthenticationToken token1 = new CasAuthenticationToken("key", - makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion); + CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, + makeUserDetails(), assertion); - CasAuthenticationToken token2 = new CasAuthenticationToken("key", - makeUserDetails("OTHER_NAME"), "Password", ROLES, makeUserDetails(), - assertion); + CasAuthenticationToken token2 = new CasAuthenticationToken("key", makeUserDetails("OTHER_NAME"), "Password", + ROLES, makeUserDetails(), assertion); assertThat(!token1.equals(token2)).isTrue(); } @@ -169,11 +158,10 @@ public class CasAuthenticationTokenTests { public void testNotEqualsDueToDifferentAuthenticationClass() { final Assertion assertion = new AssertionImpl("test"); - CasAuthenticationToken token1 = new CasAuthenticationToken("key", - makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion); + CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, + makeUserDetails(), assertion); - UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken( - "Test", "Password", ROLES); + UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken("Test", "Password", ROLES); assertThat(!token1.equals(token2)).isTrue(); } @@ -181,11 +169,11 @@ public class CasAuthenticationTokenTests { public void testNotEqualsDueToKey() { final Assertion assertion = new AssertionImpl("test"); - CasAuthenticationToken token1 = new CasAuthenticationToken("key", - makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion); + CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, + makeUserDetails(), assertion); - CasAuthenticationToken token2 = new CasAuthenticationToken("DIFFERENT_KEY", - makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion); + CasAuthenticationToken token2 = new CasAuthenticationToken("DIFFERENT_KEY", makeUserDetails(), "Password", + ROLES, makeUserDetails(), assertion); assertThat(!token1.equals(token2)).isTrue(); } @@ -195,11 +183,11 @@ public class CasAuthenticationTokenTests { final Assertion assertion = new AssertionImpl("test"); final Assertion assertion2 = new AssertionImpl("test"); - CasAuthenticationToken token1 = new CasAuthenticationToken("key", - makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion); + CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, + makeUserDetails(), assertion); - CasAuthenticationToken token2 = new CasAuthenticationToken("key", - makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion2); + CasAuthenticationToken token2 = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, + makeUserDetails(), assertion2); assertThat(!token1.equals(token2)).isTrue(); } @@ -207,8 +195,8 @@ public class CasAuthenticationTokenTests { @Test public void testSetAuthenticated() { final Assertion assertion = new AssertionImpl("test"); - CasAuthenticationToken token = new CasAuthenticationToken("key", - makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion); + CasAuthenticationToken token = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, + makeUserDetails(), assertion); assertThat(token.isAuthenticated()).isTrue(); token.setAuthenticated(false); assertThat(!token.isAuthenticated()).isTrue(); @@ -217,10 +205,10 @@ public class CasAuthenticationTokenTests { @Test public void testToString() { final Assertion assertion = new AssertionImpl("test"); - CasAuthenticationToken token = new CasAuthenticationToken("key", - makeUserDetails(), "Password", ROLES, makeUserDetails(), assertion); + CasAuthenticationToken token = new CasAuthenticationToken("key", makeUserDetails(), "Password", ROLES, + makeUserDetails(), assertion); String result = token.toString(); - assertThat( - result.lastIndexOf("Credentials (Service/Proxy Ticket):") != -1).isTrue(); + assertThat(result.lastIndexOf("Credentials (Service/Proxy Ticket):") != -1).isTrue(); } + } diff --git a/cas/src/test/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCacheTests.java b/cas/src/test/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCacheTests.java index d50013caed..05885f146c 100644 --- a/cas/src/test/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCacheTests.java +++ b/cas/src/test/java/org/springframework/security/cas/authentication/EhCacheBasedTicketCacheTests.java @@ -34,6 +34,7 @@ import static org.assertj.core.api.Assertions.*; * @author Ben Alex */ public class EhCacheBasedTicketCacheTests extends AbstractStatelessTicketCacheTests { + private static CacheManager cacheManager; // ~ Methods @@ -87,4 +88,5 @@ public class EhCacheBasedTicketCacheTests extends AbstractStatelessTicketCacheTe cache.setCache(myCache); assertThat(cache.getCache()).isEqualTo(myCache); } + } diff --git a/cas/src/test/java/org/springframework/security/cas/authentication/NullStatelessTicketCacheTests.java b/cas/src/test/java/org/springframework/security/cas/authentication/NullStatelessTicketCacheTests.java index 1643bb0394..a1d84cd1dd 100644 --- a/cas/src/test/java/org/springframework/security/cas/authentication/NullStatelessTicketCacheTests.java +++ b/cas/src/test/java/org/springframework/security/cas/authentication/NullStatelessTicketCacheTests.java @@ -44,4 +44,5 @@ public class NullStatelessTicketCacheTests extends AbstractStatelessTicketCacheT cache.putTicketInCache(token); assertThat(cache.getByTicketId((String) token.getCredentials())).isNull(); } + } diff --git a/cas/src/test/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCacheTests.java b/cas/src/test/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCacheTests.java index 57ccf6136c..51b703617d 100644 --- a/cas/src/test/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCacheTests.java +++ b/cas/src/test/java/org/springframework/security/cas/authentication/SpringCacheBasedTicketCacheTests.java @@ -31,6 +31,7 @@ import static org.assertj.core.api.Assertions.*; * @since 3.2 */ public class SpringCacheBasedTicketCacheTests extends AbstractStatelessTicketCacheTests { + private static CacheManager cacheManager; // ~ Methods @@ -44,8 +45,7 @@ public class SpringCacheBasedTicketCacheTests extends AbstractStatelessTicketCac @Test public void testCacheOperation() throws Exception { - SpringCacheBasedTicketCache cache = new SpringCacheBasedTicketCache( - cacheManager.getCache("castickets")); + SpringCacheBasedTicketCache cache = new SpringCacheBasedTicketCache(cacheManager.getCache("castickets")); final CasAuthenticationToken token = getToken(); @@ -66,4 +66,5 @@ public class SpringCacheBasedTicketCacheTests extends AbstractStatelessTicketCac public void testStartupDetectsMissingCache() throws Exception { new SpringCacheBasedTicketCache(null); } + } diff --git a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java index 933be2cf14..45956f171e 100644 --- a/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java +++ b/cas/src/test/java/org/springframework/security/cas/jackson2/CasAuthenticationTokenMixinTests.java @@ -47,15 +47,20 @@ import static org.assertj.core.api.Assertions.assertThat; public class CasAuthenticationTokenMixinTests { private static final String KEY = "casKey"; + private static final String PASSWORD = "\"1234\""; + private static final Date START_DATE = new Date(); + private static final Date END_DATE = new Date(); public static final String AUTHORITY_JSON = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"authority\": \"ROLE_USER\"}"; - public static final String AUTHORITIES_SET_JSON = "[\"java.util.Collections$UnmodifiableSet\", [" + AUTHORITY_JSON + "]]"; + public static final String AUTHORITIES_SET_JSON = "[\"java.util.Collections$UnmodifiableSet\", [" + AUTHORITY_JSON + + "]]"; - public static final String AUTHORITIES_ARRAYLIST_JSON = "[\"java.util.Collections$UnmodifiableRandomAccessList\", [" + AUTHORITY_JSON + "]]"; + public static final String AUTHORITIES_ARRAYLIST_JSON = "[\"java.util.Collections$UnmodifiableRandomAccessList\", [" + + AUTHORITY_JSON + "]]"; // @formatter:off public static final String USER_JSON = "{" @@ -71,29 +76,18 @@ public class CasAuthenticationTokenMixinTests { // @formatter:on private static final String CAS_TOKEN_JSON = "{" - + "\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", " - + "\"keyHash\": " + KEY.hashCode() + "," - + "\"principal\": " + USER_JSON + ", " - + "\"credentials\": " + PASSWORD + ", " - + "\"authorities\": " + AUTHORITIES_ARRAYLIST_JSON + "," - + "\"userDetails\": " + USER_JSON +"," - + "\"authenticated\": true, " - + "\"details\": null," - + "\"assertion\": {" - + "\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", " - + "\"principal\": {" - + "\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", " - + "\"name\": \"assertName\", " - + "\"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, " - + "\"proxyGrantingTicket\": null, " - + "\"proxyRetriever\": null" - + "}, " + + "\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", " + + "\"keyHash\": " + KEY.hashCode() + "," + "\"principal\": " + USER_JSON + ", " + "\"credentials\": " + + PASSWORD + ", " + "\"authorities\": " + AUTHORITIES_ARRAYLIST_JSON + "," + "\"userDetails\": " + USER_JSON + + "," + "\"authenticated\": true, " + "\"details\": null," + "\"assertion\": {" + + "\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", " + "\"principal\": {" + + "\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", " + + "\"name\": \"assertName\", " + "\"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, " + + "\"proxyGrantingTicket\": null, " + "\"proxyRetriever\": null" + "}, " + "\"validFromDate\": [\"java.util.Date\", " + START_DATE.getTime() + "], " + "\"validUntilDate\": [\"java.util.Date\", " + END_DATE.getTime() + "]," + "\"authenticationDate\": [\"java.util.Date\", " + START_DATE.getTime() + "], " - + "\"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" + - "}" - + "}"; + + "\"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" + "}" + "}"; private static final String CAS_TOKEN_CLEARED_JSON = CAS_TOKEN_JSON.replaceFirst(PASSWORD, "null"); @@ -114,7 +108,8 @@ public class CasAuthenticationTokenMixinTests { } @Test - public void serializeCasAuthenticationTestAfterEraseCredentialInvoked() throws JsonProcessingException, JSONException { + public void serializeCasAuthenticationTestAfterEraseCredentialInvoked() + throws JsonProcessingException, JSONException { CasAuthenticationToken token = createCasAuthenticationToken(); token.eraseCredentials(); String actualJson = mapper.writeValueAsString(token); @@ -137,9 +132,8 @@ public class CasAuthenticationTokenMixinTests { assertThat(token.getUserDetails()).isNotNull().isInstanceOf(User.class); assertThat(token.getAssertion()).isNotNull().isInstanceOf(AssertionImpl.class); assertThat(token.getKeyHash()).isEqualTo(KEY.hashCode()); - assertThat(token.getUserDetails().getAuthorities()) - .extracting(GrantedAuthority::getAuthority) - .containsOnly("ROLE_USER"); + assertThat(token.getUserDetails().getAuthorities()).extracting(GrantedAuthority::getAuthority) + .containsOnly("ROLE_USER"); assertThat(token.getAssertion().getAuthenticationDate()).isEqualTo(START_DATE); assertThat(token.getAssertion().getValidFromDate()).isEqualTo(START_DATE); assertThat(token.getAssertion().getValidUntilDate()).isEqualTo(END_DATE); @@ -149,9 +143,12 @@ public class CasAuthenticationTokenMixinTests { private CasAuthenticationToken createCasAuthenticationToken() { User principal = new User("admin", "1234", Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"))); - Collection authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); - Assertion assertion = new AssertionImpl(new AttributePrincipalImpl("assertName"), START_DATE, END_DATE, START_DATE, Collections.emptyMap()); + Collection authorities = Collections + .singletonList(new SimpleGrantedAuthority("ROLE_USER")); + Assertion assertion = new AssertionImpl(new AttributePrincipalImpl("assertName"), START_DATE, END_DATE, + START_DATE, Collections.emptyMap()); return new CasAuthenticationToken(KEY, principal, principal.getPassword(), authorities, new User("admin", "1234", authorities), assertion); } + } diff --git a/cas/src/test/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsServiceTests.java b/cas/src/test/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsServiceTests.java index b4cbad40cf..071863d884 100644 --- a/cas/src/test/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsServiceTests.java +++ b/cas/src/test/java/org/springframework/security/cas/userdetails/GrantedAuthorityFromAssertionAttributesUserDetailsServiceTests.java @@ -53,11 +53,10 @@ public class GrantedAuthorityFromAssertionAttributesUserDetailsServiceTests { when(assertion.getPrincipal()).thenReturn(principal); when(principal.getAttributes()).thenReturn(attributes); when(principal.getName()).thenReturn("somebody"); - CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken( - assertion, "ticket"); + CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken(assertion, "ticket"); UserDetails user = uds.loadUserDetails(token); Set roles = AuthorityUtils.authorityListToSet(user.getAuthorities()); - assertThat(roles).containsExactlyInAnyOrder( - "role_a1", "role_a2", "role_b", "role_c"); + assertThat(roles).containsExactlyInAnyOrder("role_a1", "role_a2", "role_b", "role_c"); } + } diff --git a/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationEntryPointTests.java b/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationEntryPointTests.java index 35d3f7fdc6..05da9f1fef 100644 --- a/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationEntryPointTests.java +++ b/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationEntryPointTests.java @@ -59,8 +59,7 @@ public class CasAuthenticationEntryPointTests { fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { - assertThat(expected.getMessage()).isEqualTo( - "serviceProperties must be specified"); + assertThat(expected.getMessage()).isEqualTo("serviceProperties must be specified"); } } @@ -92,9 +91,9 @@ public class CasAuthenticationEntryPointTests { ep.afterPropertiesSet(); ep.commence(request, response, null); - assertThat("https://cas/login?service=" + URLEncoder.encode( - "https://mycompany.com/bigWebApp/login/cas", "UTF-8")).isEqualTo( - response.getRedirectedUrl()); + assertThat( + "https://cas/login?service=" + URLEncoder.encode("https://mycompany.com/bigWebApp/login/cas", "UTF-8")) + .isEqualTo(response.getRedirectedUrl()); } @Test @@ -115,7 +114,8 @@ public class CasAuthenticationEntryPointTests { ep.afterPropertiesSet(); ep.commence(request, response, null); assertThat("https://cas/login?service=" - + URLEncoder.encode("https://mycompany.com/bigWebApp/login/cas", "UTF-8") - + "&renew=true").isEqualTo(response.getRedirectedUrl()); + + URLEncoder.encode("https://mycompany.com/bigWebApp/login/cas", "UTF-8") + "&renew=true") + .isEqualTo(response.getRedirectedUrl()); } + } diff --git a/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java b/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java index 700e24240f..848ba5d36b 100644 --- a/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java +++ b/cas/src/test/java/org/springframework/security/cas/web/CasAuthenticationFilterTests.java @@ -44,6 +44,7 @@ import static org.mockito.Mockito.*; * @author Rob Winch */ public class CasAuthenticationFilterTests { + // ~ Methods // ======================================================================================================== @@ -71,8 +72,7 @@ public class CasAuthenticationFilterTests { assertThat(filter.requiresAuthentication(request, new MockHttpServletResponse())).isTrue(); - Authentication result = filter.attemptAuthentication(request, - new MockHttpServletResponse()); + Authentication result = filter.attemptAuthentication(request, new MockHttpServletResponse()); assertThat(result != null).isTrue(); } @@ -83,8 +83,7 @@ public class CasAuthenticationFilterTests { throw new BadCredentialsException("Rejected"); }); - filter.attemptAuthentication(new MockHttpServletRequest(), - new MockHttpServletResponse()); + filter.attemptAuthentication(new MockHttpServletRequest(), new MockHttpServletResponse()); } @Test @@ -134,15 +133,13 @@ public class CasAuthenticationFilterTests { assertThat(filter.requiresAuthentication(request, response)).isFalse(); request.setParameter(properties.getArtifactParameter(), "value"); assertThat(filter.requiresAuthentication(request, response)).isTrue(); - SecurityContextHolder.getContext().setAuthentication( - new AnonymousAuthenticationToken("key", "principal", AuthorityUtils - .createAuthorityList("ROLE_ANONYMOUS"))); + SecurityContextHolder.getContext().setAuthentication(new AnonymousAuthenticationToken("key", "principal", + AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))); assertThat(filter.requiresAuthentication(request, response)).isTrue(); - SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken("un", "principal")); + SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("un", "principal")); assertThat(filter.requiresAuthentication(request, response)).isTrue(); - SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken("un", "principal", "ROLE_ANONYMOUS")); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("un", "principal", "ROLE_ANONYMOUS")); assertThat(filter.requiresAuthentication(request, response)).isFalse(); } @@ -162,8 +159,7 @@ public class CasAuthenticationFilterTests { public void testDoFilterAuthenticateAll() throws Exception { AuthenticationSuccessHandler successHandler = mock(AuthenticationSuccessHandler.class); AuthenticationManager manager = mock(AuthenticationManager.class); - Authentication authentication = new TestingAuthenticationToken("un", "pwd", - "ROLE_USER"); + Authentication authentication = new TestingAuthenticationToken("un", "pwd", "ROLE_USER"); when(manager.authenticate(any(Authentication.class))).thenReturn(authentication); ServiceProperties serviceProperties = new ServiceProperties(); serviceProperties.setAuthenticateAllArtifacts(true); @@ -181,8 +177,8 @@ public class CasAuthenticationFilterTests { filter.afterPropertiesSet(); filter.doFilter(request, response, chain); - assertThat(SecurityContextHolder - .getContext().getAuthentication()).isNotNull().withFailMessage("Authentication should not be null"); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isNotNull() + .withFailMessage("Authentication should not be null"); verify(chain).doFilter(request, response); verifyZeroInteractions(successHandler); @@ -209,4 +205,5 @@ public class CasAuthenticationFilterTests { filter.doFilter(request, response, chain); verifyZeroInteractions(chain); } + } diff --git a/cas/src/test/java/org/springframework/security/cas/web/ServicePropertiesTests.java b/cas/src/test/java/org/springframework/security/cas/web/ServicePropertiesTests.java index b9ddcf1942..e19ea137b6 100644 --- a/cas/src/test/java/org/springframework/security/cas/web/ServicePropertiesTests.java +++ b/cas/src/test/java/org/springframework/security/cas/web/ServicePropertiesTests.java @@ -28,6 +28,7 @@ import org.springframework.security.cas.ServiceProperties; * @author Ben Alex */ public class ServicePropertiesTests { + // ~ Methods // ======================================================================================================== @@ -75,4 +76,5 @@ public class ServicePropertiesTests { sp.afterPropertiesSet(); } } + } diff --git a/cas/src/test/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetailsTests.java b/cas/src/test/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetailsTests.java index 3343a2bbb2..f96d4ace8a 100644 --- a/cas/src/test/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetailsTests.java +++ b/cas/src/test/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetailsTests.java @@ -30,13 +30,16 @@ import org.springframework.security.web.util.UrlUtils; import static org.assertj.core.api.Assertions.assertThat; /** - * * @author Rob Winch */ public class DefaultServiceAuthenticationDetailsTests { + private DefaultServiceAuthenticationDetails details; + private MockHttpServletRequest request; + private Pattern artifactPattern; + private String casServiceUrl; private ConfigurableApplicationContext context; @@ -63,17 +66,14 @@ public class DefaultServiceAuthenticationDetailsTests { @Test public void getServiceUrlNullQuery() throws Exception { - this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, - this.request, this.artifactPattern); - assertThat(this.details.getServiceUrl()) - .isEqualTo(UrlUtils.buildFullRequestUrl(this.request)); + this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, this.request, this.artifactPattern); + assertThat(this.details.getServiceUrl()).isEqualTo(UrlUtils.buildFullRequestUrl(this.request)); } @Test public void getServiceUrlTicketOnlyParam() throws Exception { this.request.setQueryString("ticket=123"); - this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, - this.request, this.artifactPattern); + this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, this.request, this.artifactPattern); String serviceUrl = this.details.getServiceUrl(); this.request.setQueryString(null); assertThat(serviceUrl).isEqualTo(UrlUtils.buildFullRequestUrl(this.request)); @@ -82,8 +82,7 @@ public class DefaultServiceAuthenticationDetailsTests { @Test public void getServiceUrlTicketFirstMultiParam() throws Exception { this.request.setQueryString("ticket=123&other=value"); - this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, - this.request, this.artifactPattern); + this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, this.request, this.artifactPattern); String serviceUrl = this.details.getServiceUrl(); this.request.setQueryString("other=value"); assertThat(serviceUrl).isEqualTo(UrlUtils.buildFullRequestUrl(this.request)); @@ -92,8 +91,7 @@ public class DefaultServiceAuthenticationDetailsTests { @Test public void getServiceUrlTicketLastMultiParam() throws Exception { this.request.setQueryString("other=value&ticket=123"); - this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, - this.request, this.artifactPattern); + this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, this.request, this.artifactPattern); String serviceUrl = this.details.getServiceUrl(); this.request.setQueryString("other=value"); assertThat(serviceUrl).isEqualTo(UrlUtils.buildFullRequestUrl(this.request)); @@ -102,8 +100,7 @@ public class DefaultServiceAuthenticationDetailsTests { @Test public void getServiceUrlTicketMiddleMultiParam() throws Exception { this.request.setQueryString("other=value&ticket=123&last=this"); - this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, - this.request, this.artifactPattern); + this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, this.request, this.artifactPattern); String serviceUrl = this.details.getServiceUrl(); this.request.setQueryString("other=value&last=this"); assertThat(serviceUrl).isEqualTo(UrlUtils.buildFullRequestUrl(this.request)); @@ -113,10 +110,8 @@ public class DefaultServiceAuthenticationDetailsTests { public void getServiceUrlDoesNotUseHostHeader() throws Exception { this.casServiceUrl = "https://example.com/j_spring_security_cas"; this.request.setServerName("evil.com"); - this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, - this.request, this.artifactPattern); - assertThat(this.details.getServiceUrl()) - .isEqualTo("https://example.com/cas-sample/secure/"); + this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, this.request, this.artifactPattern); + assertThat(this.details.getServiceUrl()).isEqualTo("https://example.com/cas-sample/secure/"); } @Test @@ -125,15 +120,13 @@ public class DefaultServiceAuthenticationDetailsTests { this.request.setServerName("evil.com"); ServiceAuthenticationDetails details = loadServiceAuthenticationDetails( "defaultserviceauthenticationdetails-explicit.xml"); - assertThat(details.getServiceUrl()) - .isEqualTo("https://example.com/cas-sample/secure/"); + assertThat(details.getServiceUrl()).isEqualTo("https://example.com/cas-sample/secure/"); } - private ServiceAuthenticationDetails loadServiceAuthenticationDetails( - String resourceName) { + private ServiceAuthenticationDetails loadServiceAuthenticationDetails(String resourceName) { this.context = new GenericXmlApplicationContext(getClass(), resourceName); - ServiceAuthenticationDetailsSource source = this.context - .getBean(ServiceAuthenticationDetailsSource.class); + ServiceAuthenticationDetailsSource source = this.context.getBean(ServiceAuthenticationDetailsSource.class); return source.buildDetails(this.request); } + } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java index 42736b22e4..330d52a351 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java @@ -49,6 +49,7 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; public class LdapAuthenticationProviderBuilderSecurityBuilderTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -74,6 +75,7 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { @EnableWebSecurity static class DefaultLdapConfig extends BaseLdapProviderConfig { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -82,6 +84,7 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { .userDnPatterns("uid={0},ou=people"); // @formatter:on } + } @Test @@ -89,11 +92,13 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { this.spring.register(GroupRolesConfig.class).autowire(); LdapAuthenticationProvider provider = ldapProvider(); - assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "groupRoleAttribute")).isEqualTo("group"); + assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "groupRoleAttribute")) + .isEqualTo("group"); } @EnableWebSecurity static class GroupRolesConfig extends BaseLdapProviderConfig { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -103,6 +108,7 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { .groupRoleAttribute("group"); // @formatter:on } + } @Test @@ -110,11 +116,13 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { this.spring.register(GroupSearchConfig.class).autowire(); LdapAuthenticationProvider provider = ldapProvider(); - assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "groupSearchFilter")).isEqualTo("ou=groupName"); + assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "groupSearchFilter")) + .isEqualTo("ou=groupName"); } @EnableWebSecurity static class GroupSearchConfig extends BaseLdapProviderConfig { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -124,6 +132,7 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { .groupSearchFilter("ou=groupName"); // @formatter:on } + } @Test @@ -137,6 +146,7 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { @EnableWebSecurity static class GroupSubtreeSearchConfig extends BaseLdapProviderConfig { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -147,6 +157,7 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { .groupSearchSubtree(true); // @formatter:on } + } @Test @@ -159,6 +170,7 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { @EnableWebSecurity static class RolePrefixConfig extends BaseLdapProviderConfig { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -168,18 +180,20 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { .rolePrefix("role_"); // @formatter:on } + } @Test public void bindAuthentication() throws Exception { this.spring.register(BindAuthenticationConfig.class).autowire(); - this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) - .andExpect(authenticated().withUsername("bob").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")))); + this.mockMvc.perform(formLogin().user("bob").password("bobspassword")).andExpect(authenticated() + .withUsername("bob").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")))); } @EnableWebSecurity static class BindAuthenticationConfig extends BaseLdapServerConfig { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -190,6 +204,7 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { .userDnPatterns("uid={0},ou=people"); // @formatter:on } + } // SEC-2472 @@ -197,12 +212,13 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { public void canUseCryptoPasswordEncoder() throws Exception { this.spring.register(PasswordEncoderConfig.class).autowire(); - this.mockMvc.perform(formLogin().user("bcrypt").password("password")) - .andExpect(authenticated().withUsername("bcrypt").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")))); + this.mockMvc.perform(formLogin().user("bcrypt").password("password")).andExpect(authenticated() + .withUsername("bcrypt").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")))); } @EnableWebSecurity static class PasswordEncoderConfig extends BaseLdapServerConfig { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -214,10 +230,12 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { .userDnPatterns("uid={0},ou=people"); // @formatter:on } + } private LdapAuthenticationProvider ldapProvider() { - return ((List) ReflectionTestUtils.getField(authenticationManager, "providers")).get(0); + return ((List) ReflectionTestUtils.getField(authenticationManager, "providers")) + .get(0); } private LdapAuthoritiesPopulator getAuthoritiesPopulator(LdapAuthenticationProvider provider) { @@ -230,12 +248,15 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { @EnableWebSecurity static abstract class BaseLdapServerConfig extends BaseLdapProviderConfig { + @Bean public ApacheDSContainer ldapServer() throws Exception { - ApacheDSContainer apacheDSContainer = new ApacheDSContainer("dc=springframework,dc=org", "classpath:/test-server.ldif"); + ApacheDSContainer apacheDSContainer = new ApacheDSContainer("dc=springframework,dc=org", + "classpath:/test-server.ldif"); apacheDSContainer.setPort(getPort()); return apacheDSContainer; } + } @EnableWebSecurity @@ -260,6 +281,7 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { } abstract protected void configure(AuthenticationManagerBuilder auth) throws Exception; + } static Integer port; @@ -272,4 +294,5 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { } return port; } + } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.java index ab5960f1c4..d634ac6f85 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.java @@ -34,6 +34,7 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; public class LdapAuthenticationProviderConfigurerTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -41,7 +42,8 @@ public class LdapAuthenticationProviderConfigurerTests { private MockMvc mockMvc; @Test - public void authenticationManagerSupportMultipleDefaultLdapContextsWithPortsDynamicallyAllocated() throws Exception { + public void authenticationManagerSupportMultipleDefaultLdapContextsWithPortsDynamicallyAllocated() + throws Exception { this.spring.register(MultiLdapAuthenticationProvidersConfig.class).autowire(); this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) @@ -52,16 +54,16 @@ public class LdapAuthenticationProviderConfigurerTests { public void authenticationManagerSupportMultipleLdapContextWithDefaultRolePrefix() throws Exception { this.spring.register(MultiLdapAuthenticationProvidersConfig.class).autowire(); - this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) - .andExpect(authenticated().withUsername("bob").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")))); + this.mockMvc.perform(formLogin().user("bob").password("bobspassword")).andExpect(authenticated() + .withUsername("bob").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")))); } @Test public void authenticationManagerSupportMultipleLdapContextWithCustomRolePrefix() throws Exception { this.spring.register(MultiLdapWithCustomRolePrefixAuthenticationProvidersConfig.class).autowire(); - this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) - .andExpect(authenticated().withUsername("bob").withAuthorities(singleton(new SimpleGrantedAuthority("ROL_DEVELOPERS")))); + this.mockMvc.perform(formLogin().user("bob").password("bobspassword")).andExpect(authenticated() + .withUsername("bob").withAuthorities(singleton(new SimpleGrantedAuthority("ROL_DEVELOPERS")))); } @Test @@ -83,6 +85,7 @@ public class LdapAuthenticationProviderConfigurerTests { @EnableWebSecurity static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -97,10 +100,12 @@ public class LdapAuthenticationProviderConfigurerTests { .userDnPatterns("uid={0},ou=people"); // @formatter:on } + } @EnableWebSecurity static class MultiLdapWithCustomRolePrefixAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -117,10 +122,12 @@ public class LdapAuthenticationProviderConfigurerTests { .rolePrefix("RUOLO_"); // @formatter:on } + } @EnableWebSecurity static class LdapWithRandomPortConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -133,10 +140,12 @@ public class LdapAuthenticationProviderConfigurerTests { .port(0); // @formatter:on } + } @EnableWebSecurity static class GroupSubtreeSearchConfig extends BaseLdapProviderConfig { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -147,5 +156,7 @@ public class LdapAuthenticationProviderConfigurerTests { .userDnPatterns("uid={0},ou=people"); // @formatter:on } + } + } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTests.java index 527d0f0462..da053c6e12 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTests.java @@ -64,14 +64,15 @@ public class NamespaceLdapAuthenticationProviderTests { public void ldapAuthenticationProviderCustom() throws Exception { this.spring.register(CustomLdapAuthenticationProviderConfig.class).autowire(); - this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) - .andExpect(authenticated().withAuthorities(Collections.singleton(new SimpleGrantedAuthority("PREFIX_DEVELOPERS")))); + this.mockMvc.perform(formLogin().user("bob").password("bobspassword")).andExpect(authenticated() + .withAuthorities(Collections.singleton(new SimpleGrantedAuthority("PREFIX_DEVELOPERS")))); } // SEC-2490 @Test public void ldapAuthenticationProviderCustomLdapAuthoritiesPopulator() throws Exception { - LdapContextSource contextSource = new DefaultSpringSecurityContextSource("ldap://blah.example.com:789/dc=springframework,dc=org"); + LdapContextSource contextSource = new DefaultSpringSecurityContextSource( + "ldap://blah.example.com:789/dc=springframework,dc=org"); CustomAuthoritiesPopulatorConfig.LAP = new DefaultLdapAuthoritiesPopulator(contextSource, null) { @Override protected Set getAdditionalRoles(DirContextOperations user, String username) { @@ -81,8 +82,8 @@ public class NamespaceLdapAuthenticationProviderTests { this.spring.register(CustomAuthoritiesPopulatorConfig.class).autowire(); - this.mockMvc.perform(formLogin().user("bob").password("bobspassword")) - .andExpect(authenticated().withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_EXTRA")))); + this.mockMvc.perform(formLogin().user("bob").password("bobspassword")).andExpect( + authenticated().withAuthorities(Collections.singleton(new SimpleGrantedAuthority("ROLE_EXTRA")))); } @Test @@ -92,4 +93,5 @@ public class NamespaceLdapAuthenticationProviderTests { this.mockMvc.perform(formLogin().user("bcrypt").password("password")) .andExpect(authenticated().withUsername("bcrypt")); } + } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java index d73fb3a801..7a1959f23e 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTestsConfigs.java @@ -27,8 +27,10 @@ import org.springframework.security.ldap.userdetails.PersonContextMapper; * */ public class NamespaceLdapAuthenticationProviderTestsConfigs { + @EnableWebSecurity static class LdapAuthenticationProviderConfig extends WebSecurityConfigurerAdapter { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -37,11 +39,12 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs { .userDnPatterns("uid={0},ou=people"); // ldap-server@user-dn-pattern // @formatter:on } + } @EnableWebSecurity - static class CustomLdapAuthenticationProviderConfig extends - WebSecurityConfigurerAdapter { + static class CustomLdapAuthenticationProviderConfig extends WebSecurityConfigurerAdapter { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -65,10 +68,12 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs { ; // @formatter:on } + } @EnableWebSecurity static class CustomAuthoritiesPopulatorConfig extends WebSecurityConfigurerAdapter { + static LdapAuthoritiesPopulator LAP; protected void configure(AuthenticationManagerBuilder auth) throws Exception { @@ -79,10 +84,12 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs { .ldapAuthoritiesPopulator(LAP); // @formatter:on } + } @EnableWebSecurity static class PasswordCompareLdapConfig extends WebSecurityConfigurerAdapter { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -94,5 +101,7 @@ public class NamespaceLdapAuthenticationProviderTestsConfigs { .passwordAttribute("userPassword"); // ldap-authentication-provider/password-compare@password-attribute // @formatter:on } + } + } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/HelloHandler.java b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/HelloHandler.java index 501822a65c..b5b6b28347 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/HelloHandler.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/HelloHandler.java @@ -27,15 +27,15 @@ public class HelloHandler implements SocketAcceptor { @Override public Mono accept(ConnectionSetupPayload setup, RSocket sendingSocket) { - return Mono.just( - new AbstractRSocket() { - @Override - public Mono requestResponse(Payload payload) { - String data = payload.getDataUtf8(); - payload.release(); - System.out.println("Got " + data); - return Mono.just(ByteBufPayload.create("Hello " + data)); - } - }); + return Mono.just(new AbstractRSocket() { + @Override + public Mono requestResponse(Payload payload) { + String data = payload.getDataUtf8(); + payload.release(); + System.out.println("Got " + data); + return Mono.just(ByteBufPayload.create("Hello " + data)); + } + }); } + } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/HelloRSocketITests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/HelloRSocketITests.java index 624332b308..44e7c9199f 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/HelloRSocketITests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/HelloRSocketITests.java @@ -53,6 +53,7 @@ import static org.assertj.core.api.Assertions.assertThatCode; @ContextConfiguration @RunWith(SpringRunner.class) public class HelloRSocketITests { + @Autowired RSocketMessageHandler handler; @@ -68,13 +69,9 @@ public class HelloRSocketITests { @Before public void setup() { - this.server = RSocketFactory.receive() - .frameDecoder(PayloadDecoder.ZERO_COPY) - .addSocketAcceptorPlugin(this.interceptor) - .acceptor(this.handler.responder()) - .transport(TcpServerTransport.create("localhost", 0)) - .start() - .block(); + this.server = RSocketFactory.receive().frameDecoder(PayloadDecoder.ZERO_COPY) + .addSocketAcceptorPlugin(this.interceptor).acceptor(this.handler.responder()) + .transport(TcpServerTransport.create("localhost", 0)).start().block(); } @After @@ -86,20 +83,14 @@ public class HelloRSocketITests { @Test public void retrieveMonoWhenSecureThenDenied() throws Exception { - this.requester = RSocketRequester.builder() - .rsocketStrategies(this.handler.getRSocketStrategies()) - .connectTcp("localhost", this.server.address().getPort()) - .block(); + this.requester = RSocketRequester.builder().rsocketStrategies(this.handler.getRSocketStrategies()) + .connectTcp("localhost", this.server.address().getPort()).block(); String data = "rob"; - assertThatCode(() -> this.requester.route("secure.retrieve-mono") - .data(data) - .retrieveMono(String.class) - .block() - ) - .isNotNull(); + assertThatCode(() -> this.requester.route("secure.retrieve-mono").data(data).retrieveMono(String.class).block()) + .isNotNull(); // FIXME: https://github.com/rsocket/rsocket-java/issues/686 - // .isInstanceOf(RejectedSetupException.class); + // .isInstanceOf(RejectedSetupException.class); assertThat(this.controller.payloads).isEmpty(); } @@ -109,14 +100,11 @@ public class HelloRSocketITests { this.requester = RSocketRequester.builder() .setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) .rsocketStrategies(this.handler.getRSocketStrategies()) - .connectTcp("localhost", this.server.address().getPort()) - .block(); + .connectTcp("localhost", this.server.address().getPort()).block(); String data = "rob"; String hiRob = this.requester.route("secure.retrieve-mono") - .metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) - .data(data) - .retrieveMono(String.class) - .block(); + .metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE).data(data) + .retrieveMono(String.class).block(); assertThat(hiRob).isEqualTo("Hi rob"); assertThat(this.controller.payloads).containsOnly(data); @@ -140,9 +128,7 @@ public class HelloRSocketITests { @Bean public RSocketStrategies rsocketStrategies() { - return RSocketStrategies.builder() - .encoder(new BasicAuthenticationEncoder()) - .build(); + return RSocketStrategies.builder().encoder(new BasicAuthenticationEncoder()).build(); } @Bean @@ -156,10 +142,12 @@ public class HelloRSocketITests { // @formatter:on return new MapReactiveUserDetailsService(rob); } + } @Controller static class ServerController { + private List payloads = new ArrayList<>(); @MessageMapping("**") @@ -171,6 +159,7 @@ public class HelloRSocketITests { private void add(String p) { this.payloads.add(p); } + } } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/JwtITests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/JwtITests.java index 6b08f11ffd..4a836e737b 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/JwtITests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/JwtITests.java @@ -62,6 +62,7 @@ import static org.mockito.Mockito.when; @ContextConfiguration @RunWith(SpringRunner.class) public class JwtITests { + @Autowired RSocketMessageHandler handler; @@ -80,13 +81,9 @@ public class JwtITests { @Before public void setup() { - this.server = RSocketFactory.receive() - .frameDecoder(PayloadDecoder.ZERO_COPY) - .addSocketAcceptorPlugin(this.interceptor) - .acceptor(this.handler.responder()) - .transport(TcpServerTransport.create("localhost", 0)) - .start() - .block(); + this.server = RSocketFactory.receive().frameDecoder(PayloadDecoder.ZERO_COPY) + .addSocketAcceptorPlugin(this.interceptor).acceptor(this.handler.responder()) + .transport(TcpServerTransport.create("localhost", 0)).start().block(); } @After @@ -98,18 +95,13 @@ public class JwtITests { @Test public void routeWhenBearerThenAuthorized() { - BearerTokenMetadata credentials = - new BearerTokenMetadata("token"); + BearerTokenMetadata credentials = new BearerTokenMetadata("token"); when(this.decoder.decode(any())).thenReturn(Mono.just(jwt())); this.requester = requester() .setupMetadata(credentials.getToken(), BearerTokenMetadata.BEARER_AUTHENTICATION_MIME_TYPE) - .connectTcp(this.server.address().getHostName(), this.server.address().getPort()) - .block(); + .connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block(); - String hiRob = this.requester.route("secure.retrieve-mono") - .data("rob") - .retrieveMono(String.class) - .block(); + String hiRob = this.requester.route("secure.retrieve-mono").data("rob").retrieveMono(String.class).block(); assertThat(hiRob).isEqualTo("Hi rob"); } @@ -118,36 +110,25 @@ public class JwtITests { public void routeWhenAuthenticationBearerThenAuthorized() { MimeType authenticationMimeType = MimeTypeUtils.parseMimeType(MESSAGE_RSOCKET_AUTHENTICATION.getString()); - BearerTokenMetadata credentials = - new BearerTokenMetadata("token"); + BearerTokenMetadata credentials = new BearerTokenMetadata("token"); when(this.decoder.decode(any())).thenReturn(Mono.just(jwt())); - this.requester = requester() - .setupMetadata(credentials, authenticationMimeType) - .connectTcp(this.server.address().getHostName(), this.server.address().getPort()) - .block(); + this.requester = requester().setupMetadata(credentials, authenticationMimeType) + .connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block(); - String hiRob = this.requester.route("secure.retrieve-mono") - .data("rob") - .retrieveMono(String.class) - .block(); + String hiRob = this.requester.route("secure.retrieve-mono").data("rob").retrieveMono(String.class).block(); assertThat(hiRob).isEqualTo("Hi rob"); } private Jwt jwt() { - return TestJwts.jwt() - .claim(IdTokenClaimNames.ISS, "https://issuer.example.com") - .claim(IdTokenClaimNames.SUB, "rob") - .claim(IdTokenClaimNames.AUD, Arrays.asList("client-id")) - .build(); + return TestJwts.jwt().claim(IdTokenClaimNames.ISS, "https://issuer.example.com") + .claim(IdTokenClaimNames.SUB, "rob").claim(IdTokenClaimNames.AUD, Arrays.asList("client-id")).build(); } private RSocketRequester.Builder requester() { - return RSocketRequester.builder() - .rsocketStrategies(this.handler.getRSocketStrategies()); + return RSocketRequester.builder().rsocketStrategies(this.handler.getRSocketStrategies()); } - @Configuration @EnableRSocketSecurity static class Config { @@ -166,20 +147,13 @@ public class JwtITests { @Bean public RSocketStrategies rsocketStrategies() { - return RSocketStrategies.builder() - .encoder(new BearerTokenAuthenticationEncoder()) - .build(); + return RSocketStrategies.builder().encoder(new BearerTokenAuthenticationEncoder()).build(); } @Bean PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) { - rsocket - .authorizePayload(authorize -> - authorize - .anyRequest().authenticated() - .anyExchange().permitAll() - ) - .jwt(Customizer.withDefaults()); + rsocket.authorizePayload(authorize -> authorize.anyRequest().authenticated().anyExchange().permitAll()) + .jwt(Customizer.withDefaults()); return rsocket.build(); } @@ -187,16 +161,19 @@ public class JwtITests { ReactiveJwtDecoder jwtDecoder() { return mock(ReactiveJwtDecoder.class); } + } @Controller static class ServerController { + private List payloads = new ArrayList<>(); @MessageMapping("**") String connect(String payload) { return "Hi " + payload; } + } } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerConnectionITests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerConnectionITests.java index 66cafbebef..6c852eb6f5 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerConnectionITests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerConnectionITests.java @@ -59,6 +59,7 @@ import static org.assertj.core.api.Assertions.assertThatCode; @ContextConfiguration @RunWith(SpringRunner.class) public class RSocketMessageHandlerConnectionITests { + @Autowired RSocketMessageHandler handler; @@ -74,13 +75,9 @@ public class RSocketMessageHandlerConnectionITests { @Before public void setup() { - this.server = RSocketFactory.receive() - .frameDecoder(PayloadDecoder.ZERO_COPY) - .addSocketAcceptorPlugin(this.interceptor) - .acceptor(this.handler.responder()) - .transport(TcpServerTransport.create("localhost", 0)) - .start() - .block(); + this.server = RSocketFactory.receive().frameDecoder(PayloadDecoder.ZERO_COPY) + .addSocketAcceptorPlugin(this.interceptor).acceptor(this.handler.responder()) + .transport(TcpServerTransport.create("localhost", 0)).start().block(); } @After @@ -92,17 +89,11 @@ public class RSocketMessageHandlerConnectionITests { @Test public void routeWhenAuthorized() { - UsernamePasswordMetadata credentials = - new UsernamePasswordMetadata("user", "password"); - this.requester = requester() - .setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) - .connectTcp(this.server.address().getHostName(), this.server.address().getPort()) - .block(); + UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password"); + this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) + .connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block(); - String hiRob = this.requester.route("secure.retrieve-mono") - .data("rob") - .retrieveMono(String.class) - .block(); + String hiRob = this.requester.route("secure.retrieve-mono").data("rob").retrieveMono(String.class).block(); assertThat(hiRob).isEqualTo("Hi rob"); } @@ -110,16 +101,11 @@ public class RSocketMessageHandlerConnectionITests { @Test public void routeWhenNotAuthorized() { UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password"); - this.requester = requester() - .setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) - .connectTcp(this.server.address().getHostName(), this.server.address().getPort()) - .block(); + this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) + .connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block(); - assertThatCode(() -> this.requester.route("secure.admin.retrieve-mono") - .data("data") - .retrieveMono(String.class) - .block()) - .isInstanceOf(ApplicationErrorException.class); + assertThatCode(() -> this.requester.route("secure.admin.retrieve-mono").data("data").retrieveMono(String.class) + .block()).isInstanceOf(ApplicationErrorException.class); } @Test @@ -127,14 +113,12 @@ public class RSocketMessageHandlerConnectionITests { UsernamePasswordMetadata connectCredentials = new UsernamePasswordMetadata("user", "password"); this.requester = requester() .setupMetadata(connectCredentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) - .connectTcp(this.server.address().getHostName(), this.server.address().getPort()) - .block(); + .connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block(); String hiRob = this.requester.route("secure.admin.retrieve-mono") - .metadata(new UsernamePasswordMetadata("admin", "password"), UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) - .data("rob") - .retrieveMono(String.class) - .block(); + .metadata(new UsernamePasswordMetadata("admin", "password"), + UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) + .data("rob").retrieveMono(String.class).block(); assertThat(hiRob).isEqualTo("Hi rob"); } @@ -144,105 +128,75 @@ public class RSocketMessageHandlerConnectionITests { UsernamePasswordMetadata connectCredentials = new UsernamePasswordMetadata("user", "password"); this.requester = requester() .setupMetadata(connectCredentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) - .connectTcp(this.server.address().getHostName(), this.server.address().getPort()) - .block(); + .connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block(); String hiUser = this.requester.route("secure.authority.retrieve-mono") - .metadata(new UsernamePasswordMetadata("admin", "password"), UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) - .data("Felipe") - .retrieveMono(String.class) - .block(); + .metadata(new UsernamePasswordMetadata("admin", "password"), + UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) + .data("Felipe").retrieveMono(String.class).block(); assertThat(hiUser).isEqualTo("Hi Felipe"); } @Test public void connectWhenNotAuthenticated() { - this.requester = requester() - .connectTcp(this.server.address().getHostName(), this.server.address().getPort()) + this.requester = requester().connectTcp(this.server.address().getHostName(), this.server.address().getPort()) .block(); - assertThatCode(() -> this.requester.route("retrieve-mono") - .data("data") - .retrieveMono(String.class) - .block()) + assertThatCode(() -> this.requester.route("retrieve-mono").data("data").retrieveMono(String.class).block()) .isNotNull(); // FIXME: https://github.com/rsocket/rsocket-java/issues/686 - // .isInstanceOf(RejectedSetupException.class); + // .isInstanceOf(RejectedSetupException.class); } @Test public void connectWhenNotAuthorized() { UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("evil", "password"); - this.requester = requester() - .setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) - .connectTcp(this.server.address().getHostName(), this.server.address().getPort()) - .block(); + this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) + .connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block(); - assertThatCode(() -> this.requester.route("retrieve-mono") - .data("data") - .retrieveMono(String.class) - .block()) - .isNotNull(); -// FIXME: https://github.com/rsocket/rsocket-java/issues/686 -// .isInstanceOf(RejectedSetupException.class); + assertThatCode(() -> this.requester.route("retrieve-mono").data("data").retrieveMono(String.class).block()) + .isNotNull(); + // FIXME: https://github.com/rsocket/rsocket-java/issues/686 + // .isInstanceOf(RejectedSetupException.class); } @Test public void connectionDenied() { UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password"); - this.requester = requester() - .setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) - .connectTcp(this.server.address().getHostName(), this.server.address().getPort()) - .block(); + this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) + .connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block(); - assertThatCode(() -> this.requester.route("prohibit") - .data("data") - .retrieveMono(String.class) - .block()) + assertThatCode(() -> this.requester.route("prohibit").data("data").retrieveMono(String.class).block()) .isInstanceOf(ApplicationErrorException.class); } @Test public void connectWithAnyRole() { - UsernamePasswordMetadata credentials = - new UsernamePasswordMetadata("user", "password"); - this.requester = requester() - .setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) - .connectTcp(this.server.address().getHostName(), this.server.address().getPort()) - .block(); + UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password"); + this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) + .connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block(); - String hiRob = this.requester.route("anyroute") - .data("rob") - .retrieveMono(String.class) - .block(); + String hiRob = this.requester.route("anyroute").data("rob").retrieveMono(String.class).block(); assertThat(hiRob).isEqualTo("Hi rob"); } @Test public void connectWithAnyAuthority() { - UsernamePasswordMetadata credentials = - new UsernamePasswordMetadata("admin", "password"); - this.requester = requester() - .setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) - .connectTcp(this.server.address().getHostName(), this.server.address().getPort()) - .block(); + UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("admin", "password"); + this.requester = requester().setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) + .connectTcp(this.server.address().getHostName(), this.server.address().getPort()).block(); - String hiEbert = this.requester.route("management.users") - .data("admin") - .retrieveMono(String.class) - .block(); + String hiEbert = this.requester.route("management.users").data("admin").retrieveMono(String.class).block(); assertThat(hiEbert).isEqualTo("Hi admin"); } private RSocketRequester.Builder requester() { - return RSocketRequester.builder() - .rsocketStrategies(this.handler.getRSocketStrategies()); + return RSocketRequester.builder().rsocketStrategies(this.handler.getRSocketStrategies()); } - @Configuration @EnableRSocketSecurity static class Config { @@ -261,9 +215,7 @@ public class RSocketMessageHandlerConnectionITests { @Bean public RSocketStrategies rsocketStrategies() { - return RSocketStrategies.builder() - .encoder(new BasicAuthenticationEncoder()) - .build(); + return RSocketStrategies.builder().encoder(new BasicAuthenticationEncoder()).build(); } @Bean @@ -290,30 +242,25 @@ public class RSocketMessageHandlerConnectionITests { @Bean PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) { - rsocket - .authorizePayload(authorize -> - authorize - .setup().hasRole("SETUP") - .route("secure.admin.*").hasRole("ADMIN") - .route("secure.**").hasRole("USER") - .route("secure.authority.*").hasAuthority("ROLE_USER") - .route("management.*").hasAnyAuthority("ROLE_ADMIN") - .route("prohibit").denyAll() - .anyRequest().permitAll() - ) - .basicAuthentication(Customizer.withDefaults()); + rsocket.authorizePayload(authorize -> authorize.setup().hasRole("SETUP").route("secure.admin.*") + .hasRole("ADMIN").route("secure.**").hasRole("USER").route("secure.authority.*") + .hasAuthority("ROLE_USER").route("management.*").hasAnyAuthority("ROLE_ADMIN").route("prohibit") + .denyAll().anyRequest().permitAll()).basicAuthentication(Customizer.withDefaults()); return rsocket.build(); } + } @Controller static class ServerController { + private List payloads = new ArrayList<>(); @MessageMapping("**") String connect(String payload) { return "Hi " + payload; } + } } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerITests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerITests.java index 0256651580..fcb8202a58 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerITests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerITests.java @@ -59,6 +59,7 @@ import static org.assertj.core.api.Assertions.assertThatCode; @ContextConfiguration @RunWith(SpringRunner.class) public class RSocketMessageHandlerITests { + @Autowired RSocketMessageHandler handler; @@ -74,19 +75,15 @@ public class RSocketMessageHandlerITests { @Before public void setup() { - this.server = RSocketFactory.receive() - .frameDecoder(PayloadDecoder.ZERO_COPY) - .addSocketAcceptorPlugin(this.interceptor) - .acceptor(this.handler.responder()) - .transport(TcpServerTransport.create("localhost", 0)) - .start() - .block(); + this.server = RSocketFactory.receive().frameDecoder(PayloadDecoder.ZERO_COPY) + .addSocketAcceptorPlugin(this.interceptor).acceptor(this.handler.responder()) + .transport(TcpServerTransport.create("localhost", 0)).start().block(); this.requester = RSocketRequester.builder() - // .rsocketFactory(factory -> factory.addRequesterPlugin(payloadInterceptor)) + // .rsocketFactory(factory -> + // factory.addRequesterPlugin(payloadInterceptor)) .rsocketStrategies(this.handler.getRSocketStrategies()) - .connectTcp("localhost", this.server.address().getPort()) - .block(); + .connectTcp("localhost", this.server.address().getPort()).block(); } @After @@ -99,12 +96,8 @@ public class RSocketMessageHandlerITests { @Test public void retrieveMonoWhenSecureThenDenied() throws Exception { String data = "rob"; - assertThatCode(() -> this.requester.route("secure.retrieve-mono") - .data(data) - .retrieveMono(String.class) - .block() - ).isInstanceOf(ApplicationErrorException.class) - .hasMessageContaining("Access Denied"); + assertThatCode(() -> this.requester.route("secure.retrieve-mono").data(data).retrieveMono(String.class).block()) + .isInstanceOf(ApplicationErrorException.class).hasMessageContaining("Access Denied"); assertThat(this.controller.payloads).isEmpty(); } @@ -114,12 +107,9 @@ public class RSocketMessageHandlerITests { String data = "rob"; UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("invalid", "password"); assertThatCode(() -> this.requester.route("secure.retrieve-mono") - .metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) - .data(data) - .retrieveMono(String.class) - .block() - ).isInstanceOf(ApplicationErrorException.class) - .hasMessageContaining("Invalid Credentials"); + .metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE).data(data) + .retrieveMono(String.class).block()).isInstanceOf(ApplicationErrorException.class) + .hasMessageContaining("Invalid Credentials"); assertThat(this.controller.payloads).isEmpty(); } @@ -129,10 +119,8 @@ public class RSocketMessageHandlerITests { String data = "rob"; UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("rob", "password"); String hiRob = this.requester.route("secure.retrieve-mono") - .metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) - .data(data) - .retrieveMono(String.class) - .block(); + .metadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE).data(data) + .retrieveMono(String.class).block(); assertThat(hiRob).isEqualTo("Hi rob"); assertThat(this.controller.payloads).containsOnly(data); @@ -141,10 +129,7 @@ public class RSocketMessageHandlerITests { @Test public void retrieveMonoWhenPublicThenGranted() throws Exception { String data = "rob"; - String hiRob = this.requester.route("retrieve-mono") - .data(data) - .retrieveMono(String.class) - .block(); + String hiRob = this.requester.route("retrieve-mono").data(data).retrieveMono(String.class).block(); assertThat(hiRob).isEqualTo("Hi rob"); assertThat(this.controller.payloads).containsOnly(data); @@ -153,13 +138,9 @@ public class RSocketMessageHandlerITests { @Test public void retrieveFluxWhenDataFluxAndSecureThenDenied() throws Exception { Flux data = Flux.just("a", "b", "c"); - assertThatCode(() -> this.requester.route("secure.retrieve-flux") - .data(data, String.class) - .retrieveFlux(String.class) - .collectList() - .block() - ).isInstanceOf(ApplicationErrorException.class) - .hasMessageContaining("Access Denied"); + assertThatCode(() -> this.requester.route("secure.retrieve-flux").data(data, String.class) + .retrieveFlux(String.class).collectList().block()).isInstanceOf(ApplicationErrorException.class) + .hasMessageContaining("Access Denied"); assertThat(this.controller.payloads).isEmpty(); } @@ -167,11 +148,8 @@ public class RSocketMessageHandlerITests { @Test public void retrieveFluxWhenDataFluxAndPublicThenGranted() throws Exception { Flux data = Flux.just("a", "b", "c"); - List hi = this.requester.route("retrieve-flux") - .data(data, String.class) - .retrieveFlux(String.class) - .collectList() - .block(); + List hi = this.requester.route("retrieve-flux").data(data, String.class).retrieveFlux(String.class) + .collectList().block(); assertThat(hi).containsOnly("hello a", "hello b", "hello c"); assertThat(this.controller.payloads).containsOnlyElementsOf(data.collectList().block()); @@ -180,13 +158,9 @@ public class RSocketMessageHandlerITests { @Test public void retrieveFluxWhenDataStringAndSecureThenDenied() throws Exception { String data = "a"; - assertThatCode(() -> this.requester.route("secure.hello") - .data(data) - .retrieveFlux(String.class) - .collectList() - .block() - ).isInstanceOf(ApplicationErrorException.class) - .hasMessageContaining("Access Denied"); + assertThatCode( + () -> this.requester.route("secure.hello").data(data).retrieveFlux(String.class).collectList().block()) + .isInstanceOf(ApplicationErrorException.class).hasMessageContaining("Access Denied"); assertThat(this.controller.payloads).isEmpty(); } @@ -194,10 +168,7 @@ public class RSocketMessageHandlerITests { @Test public void sendWhenSecureThenDenied() throws Exception { String data = "hi"; - this.requester.route("secure.send") - .data(data) - .send() - .block(); + this.requester.route("secure.send").data(data).send().block(); assertThat(this.controller.payloads).isEmpty(); } @@ -205,10 +176,7 @@ public class RSocketMessageHandlerITests { @Test public void sendWhenPublicThenGranted() throws Exception { String data = "hi"; - this.requester.route("send") - .data(data) - .send() - .block(); + this.requester.route("send").data(data).send().block(); assertThat(this.controller.awaitPayloads()).containsOnly("hi"); } @@ -230,9 +198,7 @@ public class RSocketMessageHandlerITests { @Bean public RSocketStrategies rsocketStrategies() { - return RSocketStrategies.builder() - .encoder(new BasicAuthenticationEncoder()) - .build(); + return RSocketStrategies.builder().encoder(new BasicAuthenticationEncoder()).build(); } @Bean @@ -254,40 +220,35 @@ public class RSocketMessageHandlerITests { @Bean PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) { - rsocket - .authorizePayload(authorize -> { - authorize - .route("secure.*").authenticated() - .anyExchange().permitAll(); - }) - .basicAuthentication(Customizer.withDefaults()); + rsocket.authorizePayload(authorize -> { + authorize.route("secure.*").authenticated().anyExchange().permitAll(); + }).basicAuthentication(Customizer.withDefaults()); return rsocket.build(); } + } @Controller static class ServerController { + private List payloads = new ArrayList<>(); - @MessageMapping({"secure.retrieve-mono", "retrieve-mono"}) + @MessageMapping({ "secure.retrieve-mono", "retrieve-mono" }) String retrieveMono(String payload) { add(payload); return "Hi " + payload; } - @MessageMapping({"secure.retrieve-flux", "retrieve-flux"}) + @MessageMapping({ "secure.retrieve-flux", "retrieve-flux" }) Flux retrieveFlux(Flux payload) { - return payload.doOnNext(this::add) - .map(p -> "hello " + p); + return payload.doOnNext(this::add).map(p -> "hello " + p); } - @MessageMapping({"secure.send", "send"}) + @MessageMapping({ "secure.send", "send" }) Mono send(Mono payload) { - return payload - .doOnNext(this::add) - .then(Mono.fromRunnable(() -> { - doNotifyAll(); - })); + return payload.doOnNext(this::add).then(Mono.fromRunnable(() -> { + doNotifyAll(); + })); } private synchronized void doNotifyAll() { @@ -302,6 +263,7 @@ public class RSocketMessageHandlerITests { private void add(String p) { this.payloads.add(p); } + } } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/SimpleAuthenticationITests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/SimpleAuthenticationITests.java index 1e01b26cd8..0600efbc1b 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/SimpleAuthenticationITests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/rsocket/SimpleAuthenticationITests.java @@ -59,6 +59,7 @@ import static org.assertj.core.api.Assertions.assertThatCode; @ContextConfiguration @RunWith(SpringRunner.class) public class SimpleAuthenticationITests { + @Autowired RSocketMessageHandler handler; @@ -74,13 +75,9 @@ public class SimpleAuthenticationITests { @Before public void setup() { - this.server = RSocketFactory.receive() - .frameDecoder(PayloadDecoder.ZERO_COPY) - .addSocketAcceptorPlugin(this.interceptor) - .acceptor(this.handler.responder()) - .transport(TcpServerTransport.create("localhost", 0)) - .start() - .block(); + this.server = RSocketFactory.receive().frameDecoder(PayloadDecoder.ZERO_COPY) + .addSocketAcceptorPlugin(this.interceptor).acceptor(this.handler.responder()) + .transport(TcpServerTransport.create("localhost", 0)).start().block(); } @After @@ -92,18 +89,12 @@ public class SimpleAuthenticationITests { @Test public void retrieveMonoWhenSecureThenDenied() throws Exception { - this.requester = RSocketRequester.builder() - .rsocketStrategies(this.handler.getRSocketStrategies()) - .connectTcp("localhost", this.server.address().getPort()) - .block(); + this.requester = RSocketRequester.builder().rsocketStrategies(this.handler.getRSocketStrategies()) + .connectTcp("localhost", this.server.address().getPort()).block(); String data = "rob"; - assertThatCode(() -> this.requester.route("secure.retrieve-mono") - .data(data) - .retrieveMono(String.class) - .block() - ) - .isInstanceOf(ApplicationErrorException.class); + assertThatCode(() -> this.requester.route("secure.retrieve-mono").data(data).retrieveMono(String.class).block()) + .isInstanceOf(ApplicationErrorException.class); assertThat(this.controller.payloads).isEmpty(); } @@ -112,17 +103,12 @@ public class SimpleAuthenticationITests { MimeType authenticationMimeType = MimeTypeUtils.parseMimeType(MESSAGE_RSOCKET_AUTHENTICATION.getString()); UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("rob", "password"); - this.requester = RSocketRequester.builder() - .setupMetadata(credentials, authenticationMimeType) + this.requester = RSocketRequester.builder().setupMetadata(credentials, authenticationMimeType) .rsocketStrategies(this.handler.getRSocketStrategies()) - .connectTcp("localhost", this.server.address().getPort()) - .block(); + .connectTcp("localhost", this.server.address().getPort()).block(); String data = "rob"; - String hiRob = this.requester.route("secure.retrieve-mono") - .metadata(credentials, authenticationMimeType) - .data(data) - .retrieveMono(String.class) - .block(); + String hiRob = this.requester.route("secure.retrieve-mono").metadata(credentials, authenticationMimeType) + .data(data).retrieveMono(String.class).block(); assertThat(hiRob).isEqualTo("Hi rob"); assertThat(this.controller.payloads).containsOnly(data); @@ -146,19 +132,12 @@ public class SimpleAuthenticationITests { @Bean public RSocketStrategies rsocketStrategies() { - return RSocketStrategies.builder() - .encoder(new SimpleAuthenticationEncoder()) - .build(); + return RSocketStrategies.builder().encoder(new SimpleAuthenticationEncoder()).build(); } @Bean PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) { - rsocket - .authorizePayload(authorize -> - authorize - .anyRequest().authenticated() - .anyExchange().permitAll() - ) + rsocket.authorizePayload(authorize -> authorize.anyRequest().authenticated().anyExchange().permitAll()) .simpleAuthentication(Customizer.withDefaults()); return rsocket.build(); } @@ -174,10 +153,12 @@ public class SimpleAuthenticationITests { // @formatter:on return new MapReactiveUserDetailsService(rob); } + } @Controller static class ServerController { + private List payloads = new ArrayList<>(); @MessageMapping("**") @@ -189,6 +170,7 @@ public class SimpleAuthenticationITests { private void add(String p) { this.payloads.add(p); } + } } diff --git a/config/src/integration-test/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.java b/config/src/integration-test/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.java index f2a954fed1..d2ae81bdc7 100644 --- a/config/src/integration-test/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.java +++ b/config/src/integration-test/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.java @@ -35,6 +35,7 @@ import org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper; import static org.assertj.core.api.Assertions.assertThat; public class LdapProviderBeanDefinitionParserTests { + InMemoryXmlApplicationContext appCtx; @After @@ -48,13 +49,13 @@ public class LdapProviderBeanDefinitionParserTests { @Test public void simpleProviderAuthenticatesCorrectly() { appCtx = new InMemoryXmlApplicationContext("" - + "" - + " " - + "" - ); + + "" + " " + + ""); - AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, AuthenticationManager.class); - Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword")); + AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, + AuthenticationManager.class); + Authentication auth = authenticationManager + .authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword")); UserDetails ben = (UserDetails) auth.getPrincipal(); assertThat(ben.getAuthorities()).hasSize(3); } @@ -62,39 +63,32 @@ public class LdapProviderBeanDefinitionParserTests { @Test public void multipleProvidersAreSupported() { appCtx = new InMemoryXmlApplicationContext("" - + "" - + " " + + "" + " " + " " - + "" - ); + + ""); ProviderManager providerManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class); assertThat(providerManager.getProviders()).hasSize(2); - assertThat(providerManager.getProviders()) - .extracting("authoritiesPopulator.groupSearchFilter") + assertThat(providerManager.getProviders()).extracting("authoritiesPopulator.groupSearchFilter") .containsExactly("member={0}", "uniqueMember={0}"); } @Test(expected = ApplicationContextException.class) public void missingServerEltCausesConfigException() { - new InMemoryXmlApplicationContext("" - + " " - + "" - ); + new InMemoryXmlApplicationContext( + "" + " " + ""); } @Test public void supportsPasswordComparisonAuthentication() { appCtx = new InMemoryXmlApplicationContext("" - + "" - + " " - + " " - + " " - + "" - ); + + "" + " " + + " " + " " + ""); - AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, AuthenticationManager.class); - Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword")); + AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, + AuthenticationManager.class); + Authentication auth = authenticationManager + .authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword")); assertThat(auth).isNotNull(); } @@ -102,17 +96,13 @@ public class LdapProviderBeanDefinitionParserTests { @Test public void supportsPasswordComparisonAuthenticationWithPasswordEncoder() { appCtx = new InMemoryXmlApplicationContext("" - + "" - + " " - + " " - + " " - + " " - + " " - + "" - + "" - ); + + "" + " " + + " " + " " + + " " + " " + "" + + ""); - AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, AuthenticationManager.class); + AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, + AuthenticationManager.class); Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben")); assertThat(auth).isNotNull(); @@ -122,34 +112,30 @@ public class LdapProviderBeanDefinitionParserTests { @Test public void supportsCryptoPasswordEncoder() { appCtx = new InMemoryXmlApplicationContext("" - + "" - + " " - + " " - + " " - + " " - + " " - + "" - + "" - ); + + "" + " " + + " " + " " + " " + + " " + "" + + ""); - AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, AuthenticationManager.class); - Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bcrypt", "password")); + AuthenticationManager authenticationManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, + AuthenticationManager.class); + Authentication auth = authenticationManager + .authenticate(new UsernamePasswordAuthenticationToken("bcrypt", "password")); assertThat(auth).isNotNull(); } @Test public void inetOrgContextMapperIsSupported() { - appCtx = new InMemoryXmlApplicationContext("" - + "" - + " " - + "" - ); + appCtx = new InMemoryXmlApplicationContext( + "" + + "" + + " " + + ""); ProviderManager providerManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class); assertThat(providerManager.getProviders()).hasSize(1); - assertThat(providerManager.getProviders()) - .extracting("userDetailsContextMapper") + assertThat(providerManager.getProviders()).extracting("userDetailsContextMapper") .allSatisfy(contextMapper -> assertThat(contextMapper).isInstanceOf(InetOrgPersonContextMapper.class)); } @@ -157,22 +143,20 @@ public class LdapProviderBeanDefinitionParserTests { public void ldapAuthenticationProviderWorksWithPlaceholders() { System.setProperty("udp", "people"); System.setProperty("gsf", "member"); - appCtx = new InMemoryXmlApplicationContext("" - + "" + appCtx = new InMemoryXmlApplicationContext("" + "" + " " + "" - + "" - ); + + ""); ProviderManager providerManager = appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER, ProviderManager.class); assertThat(providerManager.getProviders()).hasSize(1); AuthenticationProvider authenticationProvider = providerManager.getProviders().get(0); - assertThat(authenticationProvider) - .extracting("authenticator.userDnFormat") - .satisfies(messageFormats -> assertThat(messageFormats).isEqualTo(new MessageFormat[]{new MessageFormat("uid={0},ou=people")})); - assertThat(authenticationProvider) - .extracting("authoritiesPopulator.groupSearchFilter") + assertThat(authenticationProvider).extracting("authenticator.userDnFormat") + .satisfies(messageFormats -> assertThat(messageFormats) + .isEqualTo(new MessageFormat[] { new MessageFormat("uid={0},ou=people") })); + assertThat(authenticationProvider).extracting("authoritiesPopulator.groupSearchFilter") .satisfies(searchFilter -> assertThat(searchFilter).isEqualTo("member={0}")); } + } diff --git a/config/src/integration-test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTests.java b/config/src/integration-test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTests.java index 564352400b..5eaa5a9a9e 100644 --- a/config/src/integration-test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTests.java +++ b/config/src/integration-test/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParserTests.java @@ -35,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Rob Winch */ public class LdapServerBeanDefinitionParserTests { + InMemoryXmlApplicationContext appCtx; @After @@ -47,8 +48,7 @@ public class LdapServerBeanDefinitionParserTests { @Test public void embeddedServerCreationContainsExpectedContextSourceAndData() { - appCtx = new InMemoryXmlApplicationContext( - ""); + appCtx = new InMemoryXmlApplicationContext(""); DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx .getBean(BeanIds.CONTEXT_SOURCE); @@ -62,18 +62,14 @@ public class LdapServerBeanDefinitionParserTests { public void useOfUrlAttributeCreatesCorrectContextSource() throws Exception { int port = getDefaultPort(); // Create second "server" with a url pointing at embedded one - appCtx = new InMemoryXmlApplicationContext( - "" - + ""); + appCtx = new InMemoryXmlApplicationContext("" + ""); // Check the default context source is still there. appCtx.getBean(BeanIds.CONTEXT_SOURCE); - DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx - .getBean("blah"); + DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx.getBean("blah"); // Check data is loaded as before LdapTemplate template = new LdapTemplate(contextSource); @@ -104,4 +100,5 @@ public class LdapServerBeanDefinitionParserTests { return server.getLocalPort(); } } + } diff --git a/config/src/integration-test/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParserTests.java b/config/src/integration-test/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParserTests.java index caff4c8757..36b8921c69 100644 --- a/config/src/integration-test/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParserTests.java +++ b/config/src/integration-test/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParserTests.java @@ -48,6 +48,7 @@ import static org.springframework.security.config.ldap.LdapUserServiceBeanDefini * @author Eddú Meléndez */ public class LdapUserServiceBeanDefinitionParserTests { + private InMemoryXmlApplicationContext appCtx; @After @@ -65,17 +66,20 @@ public class LdapUserServiceBeanDefinitionParserTests { assertThat(InetOrgPersonContextMapper.class.getName()).isEqualTo(INET_ORG_PERSON_MAPPER_CLASS); assertThat(LdapUserDetailsMapper.class.getName()).isEqualTo(LDAP_USER_MAPPER_CLASS); assertThat(DefaultLdapAuthoritiesPopulator.class.getName()).isEqualTo(LDAP_AUTHORITIES_POPULATOR_CLASS); - assertThat(new LdapUserServiceBeanDefinitionParser().getBeanClassName(mock(Element.class))).isEqualTo(LdapUserDetailsService.class.getName()); + assertThat(new LdapUserServiceBeanDefinitionParser().getBeanClassName(mock(Element.class))) + .isEqualTo(LdapUserDetailsService.class.getName()); } @Test public void minimalConfigurationIsParsedOk() { - setContext(""); + setContext( + ""); } @Test public void userServiceReturnsExpectedData() { - setContext(""); + setContext( + ""); UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS"); UserDetails ben = uds.loadUserByUsername("ben"); @@ -87,8 +91,7 @@ public class LdapUserServiceBeanDefinitionParserTests { @Test public void differentUserSearchBaseWorksAsExpected() { - setContext(""); @@ -100,11 +103,9 @@ public class LdapUserServiceBeanDefinitionParserTests { @Test public void rolePrefixIsSupported() { - setContext("" - + ""); UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS"); @@ -118,7 +119,8 @@ public class LdapUserServiceBeanDefinitionParserTests { @Test public void differentGroupRoleAttributeWorksAsExpected() { - setContext(""); + setContext( + ""); UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS"); UserDetails ben = uds.loadUserByUsername("ben"); @@ -131,11 +133,11 @@ public class LdapUserServiceBeanDefinitionParserTests { @Test public void isSupportedByAuthenticationProviderElement() { - setContext("" - + "" - + " " - + " " - + " " + ""); + setContext( + "" + + "" + " " + + " " + " " + + ""); } @Test @@ -160,8 +162,7 @@ public class LdapUserServiceBeanDefinitionParserTests { public void externalContextMapperIsSupported() { setContext("" + "" - + ""); + + ""); UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS"); UserDetails ben = uds.loadUserByUsername("ben"); @@ -171,4 +172,5 @@ public class LdapUserServiceBeanDefinitionParserTests { private void setContext(String context) { appCtx = new InMemoryXmlApplicationContext(context); } + } diff --git a/config/src/main/java/org/springframework/security/config/BeanIds.java b/config/src/main/java/org/springframework/security/config/BeanIds.java index 85027d2c73..4cdeddcd7f 100644 --- a/config/src/main/java/org/springframework/security/config/BeanIds.java +++ b/config/src/main/java/org/springframework/security/config/BeanIds.java @@ -25,6 +25,7 @@ package org.springframework.security.config; * @author Luke Taylor */ public abstract class BeanIds { + private static final String PREFIX = "org.springframework.security."; /** @@ -36,26 +37,26 @@ public abstract class BeanIds { /** External alias for FilterChainProxy bean, for use in web.xml files */ public static final String SPRING_SECURITY_FILTER_CHAIN = "springSecurityFilterChain"; - public static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = PREFIX - + "contextSettingPostProcessor"; + public static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = PREFIX + "contextSettingPostProcessor"; public static final String USER_DETAILS_SERVICE = PREFIX + "userDetailsService"; - public static final String USER_DETAILS_SERVICE_FACTORY = PREFIX - + "userDetailsServiceFactory"; - public static final String METHOD_ACCESS_MANAGER = PREFIX - + "defaultMethodAccessManager"; + public static final String USER_DETAILS_SERVICE_FACTORY = PREFIX + "userDetailsServiceFactory"; + + public static final String METHOD_ACCESS_MANAGER = PREFIX + "defaultMethodAccessManager"; public static final String FILTER_CHAIN_PROXY = PREFIX + "filterChainProxy"; + public static final String FILTER_CHAINS = PREFIX + "filterChains"; - public static final String METHOD_SECURITY_METADATA_SOURCE_ADVISOR = PREFIX - + "methodSecurityMetadataSourceAdvisor"; - public static final String EMBEDDED_APACHE_DS = PREFIX - + "apacheDirectoryServerContainer"; - public static final String EMBEDDED_UNBOUNDID = PREFIX - + "unboundidServerContainer"; + public static final String METHOD_SECURITY_METADATA_SOURCE_ADVISOR = PREFIX + "methodSecurityMetadataSourceAdvisor"; + + public static final String EMBEDDED_APACHE_DS = PREFIX + "apacheDirectoryServerContainer"; + + public static final String EMBEDDED_UNBOUNDID = PREFIX + "unboundidServerContainer"; + public static final String CONTEXT_SOURCE = PREFIX + "securityContextSource"; public static final String DEBUG_FILTER = PREFIX + "debugFilter"; + } diff --git a/config/src/main/java/org/springframework/security/config/Customizer.java b/config/src/main/java/org/springframework/security/config/Customizer.java index 048ec1f3e0..8433a3c7de 100644 --- a/config/src/main/java/org/springframework/security/config/Customizer.java +++ b/config/src/main/java/org/springframework/security/config/Customizer.java @@ -28,17 +28,17 @@ public interface Customizer { /** * Performs the customizations on the input argument. - * * @param t the input argument */ void customize(T t); /** * Returns a {@link Customizer} that does not alter the input argument. - * * @return a {@link Customizer} that does not alter the input argument. */ static Customizer withDefaults() { - return t -> {}; + return t -> { + }; } + } diff --git a/config/src/main/java/org/springframework/security/config/DebugBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/DebugBeanDefinitionParser.java index e7327e5ab0..bbbf44a87d 100644 --- a/config/src/main/java/org/springframework/security/config/DebugBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/DebugBeanDefinitionParser.java @@ -26,11 +26,12 @@ import org.w3c.dom.Element; * @author Luke Taylor */ public class DebugBeanDefinitionParser implements BeanDefinitionParser { + public BeanDefinition parse(Element element, ParserContext parserContext) { - RootBeanDefinition debugPP = new RootBeanDefinition( - SecurityDebugBeanFactoryPostProcessor.class); + RootBeanDefinition debugPP = new RootBeanDefinition(SecurityDebugBeanFactoryPostProcessor.class); parserContext.getReaderContext().registerWithGeneratedName(debugPP); return null; } + } diff --git a/config/src/main/java/org/springframework/security/config/Elements.java b/config/src/main/java/org/springframework/security/config/Elements.java index 35a4d0fa17..9f7cee5862 100644 --- a/config/src/main/java/org/springframework/security/config/Elements.java +++ b/config/src/main/java/org/springframework/security/config/Elements.java @@ -23,61 +23,113 @@ package org.springframework.security.config; public abstract class Elements { public static final String ACCESS_DENIED_HANDLER = "access-denied-handler"; + public static final String AUTHENTICATION_MANAGER = "authentication-manager"; + public static final String AFTER_INVOCATION_PROVIDER = "after-invocation-provider"; + public static final String USER_SERVICE = "user-service"; + public static final String JDBC_USER_SERVICE = "jdbc-user-service"; + public static final String FILTER_CHAIN_MAP = "filter-chain-map"; + public static final String INTERCEPT_METHODS = "intercept-methods"; + public static final String INTERCEPT_URL = "intercept-url"; + public static final String AUTHENTICATION_PROVIDER = "authentication-provider"; + public static final String HTTP = "http"; + public static final String LDAP_PROVIDER = "ldap-authentication-provider"; + public static final String LDAP_SERVER = "ldap-server"; + public static final String LDAP_USER_SERVICE = "ldap-user-service"; + public static final String PROTECT_POINTCUT = "protect-pointcut"; + public static final String EXPRESSION_HANDLER = "expression-handler"; + public static final String INVOCATION_HANDLING = "pre-post-annotation-handling"; + public static final String INVOCATION_ATTRIBUTE_FACTORY = "invocation-attribute-factory"; + public static final String PRE_INVOCATION_ADVICE = "pre-invocation-advice"; + public static final String POST_INVOCATION_ADVICE = "post-invocation-advice"; + public static final String PROTECT = "protect"; + public static final String SESSION_MANAGEMENT = "session-management"; + public static final String CONCURRENT_SESSIONS = "concurrency-control"; + public static final String LOGOUT = "logout"; + public static final String FORM_LOGIN = "form-login"; + public static final String OPENID_LOGIN = "openid-login"; + public static final String OPENID_ATTRIBUTE_EXCHANGE = "attribute-exchange"; + public static final String OPENID_ATTRIBUTE = "openid-attribute"; + public static final String BASIC_AUTH = "http-basic"; + public static final String REMEMBER_ME = "remember-me"; + public static final String ANONYMOUS = "anonymous"; + public static final String FILTER_CHAIN = "filter-chain"; + public static final String GLOBAL_METHOD_SECURITY = "global-method-security"; + public static final String PASSWORD_ENCODER = "password-encoder"; + public static final String PORT_MAPPINGS = "port-mappings"; + public static final String PORT_MAPPING = "port-mapping"; + public static final String CUSTOM_FILTER = "custom-filter"; + public static final String REQUEST_CACHE = "request-cache"; + public static final String X509 = "x509"; + public static final String JEE = "jee"; + public static final String FILTER_SECURITY_METADATA_SOURCE = "filter-security-metadata-source"; + public static final String METHOD_SECURITY_METADATA_SOURCE = "method-security-metadata-source"; + public static final String LDAP_PASSWORD_COMPARE = "password-compare"; + public static final String DEBUG = "debug"; + public static final String HTTP_FIREWALL = "http-firewall"; + public static final String HEADERS = "headers"; + public static final String CORS = "cors"; + public static final String CSRF = "csrf"; public static final String OAUTH2_RESOURCE_SERVER = "oauth2-resource-server"; + public static final String JWT = "jwt"; + public static final String OPAQUE_TOKEN = "opaque-token"; public static final String WEBSOCKET_MESSAGE_BROKER = "websocket-message-broker"; + public static final String INTERCEPT_MESSAGE = "intercept-message"; public static final String OAUTH2_LOGIN = "oauth2-login"; + public static final String OAUTH2_CLIENT = "oauth2-client"; + public static final String CLIENT_REGISTRATIONS = "client-registrations"; + } diff --git a/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java b/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java index fc044e24e2..b92ff3f560 100644 --- a/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java +++ b/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java @@ -59,11 +59,17 @@ import org.springframework.util.ClassUtils; * @since 2.0 */ public final class SecurityNamespaceHandler implements NamespaceHandler { + private static final String FILTER_CHAIN_PROXY_CLASSNAME = "org.springframework.security.web.FilterChainProxy"; + private static final String MESSAGE_CLASSNAME = "org.springframework.messaging.Message"; + private final Log logger = LogFactory.getLog(getClass()); + private final Map parsers = new HashMap<>(); + private final BeanDefinitionDecorator interceptMethodsBDD = new InterceptMethodsBeanDefinitionDecorator(); + private BeanDefinitionDecorator filterChainMapBDD; public SecurityNamespaceHandler() { @@ -86,10 +92,10 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { public BeanDefinition parse(Element element, ParserContext pc) { if (!namespaceMatchesVersion(element)) { - pc.getReaderContext() - .fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or spring-security-3.1.xsd schema or spring-security-3.2.xsd schema or spring-security-4.0.xsd schema " + pc.getReaderContext().fatal( + "You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or spring-security-3.1.xsd schema or spring-security-3.2.xsd schema or spring-security-4.0.xsd schema " + "with Spring Security 5.4. Please update your schema declarations to the 5.4 schema.", - element); + element); } String name = pc.getDelegate().getLocalName(element); BeanDefinitionParser parser = parsers.get(name); @@ -100,10 +106,8 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { } if (parser == null) { - if (Elements.HTTP.equals(name) - || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name) - || Elements.FILTER_CHAIN_MAP.equals(name) - || Elements.FILTER_CHAIN.equals(name)) { + if (Elements.HTTP.equals(name) || Elements.FILTER_SECURITY_METADATA_SOURCE.equals(name) + || Elements.FILTER_CHAIN_MAP.equals(name) || Elements.FILTER_CHAIN.equals(name)) { reportMissingWebClasses(name, pc, element); } else { @@ -116,8 +120,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { return parser.parse(element, pc); } - public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, - ParserContext pc) { + public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext pc) { String name = pc.getDelegate().getLocalName(node); // We only handle elements @@ -143,16 +146,13 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { } private void reportUnsupportedNodeType(String name, ParserContext pc, Node node) { - pc.getReaderContext().fatal( - "Security namespace does not support decoration of " - + (node instanceof Element ? "element" : "attribute") + " [" - + name + "]", node); + pc.getReaderContext().fatal("Security namespace does not support decoration of " + + (node instanceof Element ? "element" : "attribute") + " [" + name + "]", node); } private void reportMissingWebClasses(String nodeName, ParserContext pc, Node node) { String errorMessage = "The classes from the spring-security-web jar " - + "(or one of its dependencies) are not available. You need these to use <" - + nodeName + ">"; + + "(or one of its dependencies) are not available. You need these to use <" + nodeName + ">"; try { ClassUtils.forName(FILTER_CHAIN_PROXY_CLASSNAME, getClass().getClassLoader()); // no details available @@ -175,31 +175,24 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { parsers.put(Elements.LDAP_USER_SERVICE, new LdapUserServiceBeanDefinitionParser()); parsers.put(Elements.USER_SERVICE, new UserServiceBeanDefinitionParser()); parsers.put(Elements.JDBC_USER_SERVICE, new JdbcUserServiceBeanDefinitionParser()); - parsers.put(Elements.AUTHENTICATION_PROVIDER, - new AuthenticationProviderBeanDefinitionParser()); - parsers.put(Elements.GLOBAL_METHOD_SECURITY, - new GlobalMethodSecurityBeanDefinitionParser()); - parsers.put(Elements.AUTHENTICATION_MANAGER, - new AuthenticationManagerBeanDefinitionParser()); - parsers.put(Elements.METHOD_SECURITY_METADATA_SOURCE, - new MethodSecurityMetadataSourceBeanDefinitionParser()); + parsers.put(Elements.AUTHENTICATION_PROVIDER, new AuthenticationProviderBeanDefinitionParser()); + parsers.put(Elements.GLOBAL_METHOD_SECURITY, new GlobalMethodSecurityBeanDefinitionParser()); + parsers.put(Elements.AUTHENTICATION_MANAGER, new AuthenticationManagerBeanDefinitionParser()); + parsers.put(Elements.METHOD_SECURITY_METADATA_SOURCE, new MethodSecurityMetadataSourceBeanDefinitionParser()); // Only load the web-namespace parsers if the web classes are available - if (ClassUtils.isPresent(FILTER_CHAIN_PROXY_CLASSNAME, getClass() - .getClassLoader())) { + if (ClassUtils.isPresent(FILTER_CHAIN_PROXY_CLASSNAME, getClass().getClassLoader())) { parsers.put(Elements.DEBUG, new DebugBeanDefinitionParser()); parsers.put(Elements.HTTP, new HttpSecurityBeanDefinitionParser()); parsers.put(Elements.HTTP_FIREWALL, new HttpFirewallBeanDefinitionParser()); - parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, - new FilterInvocationSecurityMetadataSourceParser()); + parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceParser()); parsers.put(Elements.FILTER_CHAIN, new FilterChainBeanDefinitionParser()); filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator(); parsers.put(Elements.CLIENT_REGISTRATIONS, new ClientRegistrationsBeanDefinitionParser()); } if (ClassUtils.isPresent(MESSAGE_CLASSNAME, getClass().getClassLoader())) { - parsers.put(Elements.WEBSOCKET_MESSAGE_BROKER, - new WebSocketMessageBrokerSecurityBeanDefinitionParser()); + parsers.put(Elements.WEBSOCKET_MESSAGE_BROKER, new WebSocketMessageBrokerSecurityBeanDefinitionParser()); } } @@ -212,7 +205,6 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { * using 3.0 as an error too. It might be an error to declare spring-security.xsd as * an alias, but you are only going to find that out when one of the sub parsers * breaks. - * * @param element the element that is to be parsed next * @return true if we find a schema declaration that matches */ @@ -222,8 +214,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { } private boolean matchesVersionInternal(Element element) { - String schemaLocation = element.getAttributeNS( - "http://www.w3.org/2001/XMLSchema-instance", "schemaLocation"); + String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation"); return schemaLocation.matches("(?m).*spring-security-5\\.4.*.xsd.*") || schemaLocation.matches("(?m).*spring-security.xsd.*") || !schemaLocation.matches("(?m).*spring-security.*"); diff --git a/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java b/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java index 34fe85cb2c..5e9b198ffc 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java @@ -45,17 +45,17 @@ import org.springframework.web.filter.DelegatingFilterProxy; *

* * @see WebSecurity - * * @author Rob Winch - * * @param The object that this builder returns * @param The type of this builder (that is returned by the base class) */ public abstract class AbstractConfiguredSecurityBuilder> extends AbstractSecurityBuilder { + private final Log logger = LogFactory.getLog(getClass()); private final LinkedHashMap>, List>> configurers = new LinkedHashMap<>(); + private final List> configurersAddedInInitializing = new ArrayList<>(); private final Map, Object> sharedObjects = new HashMap<>(); @@ -70,11 +70,9 @@ public abstract class AbstractConfiguredSecurityBuilder objectPostProcessor) { + protected AbstractConfiguredSecurityBuilder(ObjectPostProcessor objectPostProcessor) { this(objectPostProcessor, false); } @@ -82,13 +80,11 @@ public abstract class AbstractConfiguredSecurityBuilder objectPostProcessor, + protected AbstractConfiguredSecurityBuilder(ObjectPostProcessor objectPostProcessor, boolean allowConfigurersOfSameType) { Assert.notNull(objectPostProcessor, "objectPostProcessor cannot be null"); this.objectPostProcessor = objectPostProcessor; @@ -98,7 +94,6 @@ public abstract class AbstractConfiguredSecurityBuilder> C apply(C configurer) - throws Exception { + public > C apply(C configurer) throws Exception { configurer.addObjectPostProcessor(objectPostProcessor); configurer.setBuilder((B) this); add(configurer); @@ -138,7 +131,6 @@ public abstract class AbstractConfiguredSecurityBuilder> configs = allowConfigurersOfSameType ? this.configurers - .get(clazz) : null; + List> configs = allowConfigurersOfSameType ? this.configurers.get(clazz) : null; if (configs == null) { configs = new ArrayList<>(1); } @@ -211,7 +198,6 @@ public abstract class AbstractConfiguredSecurityBuildernull if not * found. Note that object hierarchies are not considered. - * * @param clazz * @return the {@link SecurityConfigurer} for further customizations */ @@ -254,8 +238,7 @@ public abstract class AbstractConfiguredSecurityBuildernull if not found. Note that object hierarchies are not considered. - * * @param clazz * @return */ @@ -274,8 +256,7 @@ public abstract class AbstractConfiguredSecurityBuilder= CONFIGURING.order; } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/AbstractSecurityBuilder.java b/config/src/main/java/org/springframework/security/config/annotation/AbstractSecurityBuilder.java index 2f4c4022fe..afaeebd92a 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/AbstractSecurityBuilder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/AbstractSecurityBuilder.java @@ -22,11 +22,11 @@ import java.util.concurrent.atomic.AtomicBoolean; * time. * * @param the type of Object that is being built - * * @author Rob Winch * */ public abstract class AbstractSecurityBuilder implements SecurityBuilder { + private AtomicBoolean building = new AtomicBoolean(); private O object; @@ -47,7 +47,6 @@ public abstract class AbstractSecurityBuilder implements SecurityBuilder { /** * Gets the object that was built. If it has not been built yet an Exception is * thrown. - * * @return the Object that was built */ public final O getObject() { @@ -59,10 +58,9 @@ public abstract class AbstractSecurityBuilder implements SecurityBuilder { /** * Subclasses should implement this to perform the build. - * * @return the object that should be returned by {@link #build()}. - * * @throws Exception if an error occurs */ protected abstract O doBuild() throws Exception; + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/AlreadyBuiltException.java b/config/src/main/java/org/springframework/security/config/annotation/AlreadyBuiltException.java index b84bbff45e..b50484c4ea 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/AlreadyBuiltException.java +++ b/config/src/main/java/org/springframework/security/config/annotation/AlreadyBuiltException.java @@ -28,4 +28,5 @@ public class AlreadyBuiltException extends IllegalStateException { } private static final long serialVersionUID = -5891004752785553015L; + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/ObjectPostProcessor.java b/config/src/main/java/org/springframework/security/config/annotation/ObjectPostProcessor.java index ca07992749..4218081cdb 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/ObjectPostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/annotation/ObjectPostProcessor.java @@ -25,7 +25,6 @@ import org.springframework.beans.factory.InitializingBean; * {@link DisposableBean#destroy()} has been invoked. * * @param the bound of the types of Objects this {@link ObjectPostProcessor} supports. - * * @author Rob Winch * @since 3.2 */ @@ -34,9 +33,9 @@ public interface ObjectPostProcessor { /** * Initialize the object possibly returning a modified instance that should be used * instead. - * * @param object the object to initialize * @return the initialized version of the object */ O postProcess(O object); + } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/SecurityBuilder.java b/config/src/main/java/org/springframework/security/config/annotation/SecurityBuilder.java index 1f097537c0..3340250675 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/SecurityBuilder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/SecurityBuilder.java @@ -20,16 +20,15 @@ package org.springframework.security.config.annotation; * * @author Rob Winch * @since 3.2 - * * @param The type of the Object being built */ public interface SecurityBuilder { /** * Builds the object and returns it or null. - * * @return the Object to be built or null if the implementation allows it. * @throws Exception if an error occurred when building the Object */ O build() throws Exception; + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurer.java index 4ddba28274..13564216ea 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurer.java @@ -22,20 +22,18 @@ package org.springframework.security.config.annotation; * {@link #configure(SecurityBuilder)} method is invoked. * * @see AbstractConfiguredSecurityBuilder - * * @author Rob Winch - * * @param The object being built by the {@link SecurityBuilder} B * @param The {@link SecurityBuilder} that builds objects of type O. This is also the * {@link SecurityBuilder} that is being configured. */ public interface SecurityConfigurer> { + /** * Initialize the {@link SecurityBuilder}. Here only shared state should be created * and modified, but not properties on the {@link SecurityBuilder} used for building * the object. This ensures that the {@link #configure(SecurityBuilder)} method uses * the correct shared objects when building. Configurers should be applied here. - * * @param builder * @throws Exception */ @@ -44,9 +42,9 @@ public interface SecurityConfigurer> { /** * Configure the {@link SecurityBuilder} by setting the necessary properties on the * {@link SecurityBuilder}. - * * @param builder * @throws Exception */ void configure(B builder) throws Exception; + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurerAdapter.java b/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurerAdapter.java index d5ca809c64..87e0876002 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurerAdapter.java +++ b/config/src/main/java/org/springframework/security/config/annotation/SecurityConfigurerAdapter.java @@ -29,13 +29,12 @@ import org.springframework.core.annotation.AnnotationAwareOrderComparator; * * @author Rob Winch * @author Wallace Wadge - * * @param The Object being built by B * @param The Builder that is building O and is configured by * {@link SecurityConfigurerAdapter} */ -public abstract class SecurityConfigurerAdapter> - implements SecurityConfigurer { +public abstract class SecurityConfigurerAdapter> implements SecurityConfigurer { + private B securityBuilder; private CompositeObjectPostProcessor objectPostProcessor = new CompositeObjectPostProcessor(); @@ -49,7 +48,6 @@ public abstract class SecurityConfigurerAdapter> /** * Return the {@link SecurityBuilder} when done using the {@link SecurityConfigurer}. * This is useful for method chaining. - * * @return the {@link SecurityBuilder} for further customizations */ public B and() { @@ -58,7 +56,6 @@ public abstract class SecurityConfigurerAdapter> /** * Gets the {@link SecurityBuilder}. Cannot be null. - * * @return the {@link SecurityBuilder} * @throws IllegalStateException if {@link SecurityBuilder} is null */ @@ -72,7 +69,6 @@ public abstract class SecurityConfigurerAdapter> /** * Performs post processing of an object. The default is to delegate to the * {@link ObjectPostProcessor}. - * * @param object the Object to post process * @return the possibly modified Object to use */ @@ -85,7 +81,6 @@ public abstract class SecurityConfigurerAdapter> * Adds an {@link ObjectPostProcessor} to be used for this * {@link SecurityConfigurerAdapter}. The default implementation does nothing to the * object. - * * @param objectPostProcessor the {@link ObjectPostProcessor} to use */ public void addObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { @@ -95,7 +90,6 @@ public abstract class SecurityConfigurerAdapter> /** * Sets the {@link SecurityBuilder} to be used. This is automatically set when using * {@link AbstractConfiguredSecurityBuilder#apply(SecurityConfigurerAdapter)} - * * @param builder the {@link SecurityBuilder} to set */ public void setBuilder(B builder) { @@ -108,16 +102,15 @@ public abstract class SecurityConfigurerAdapter> * * @author Rob Winch */ - private static final class CompositeObjectPostProcessor implements - ObjectPostProcessor { + private static final class CompositeObjectPostProcessor implements ObjectPostProcessor { + private List> postProcessors = new ArrayList<>(); @SuppressWarnings({ "rawtypes", "unchecked" }) public Object postProcess(Object object) { for (ObjectPostProcessor opp : postProcessors) { Class oppClass = opp.getClass(); - Class oppType = GenericTypeResolver.resolveTypeArgument(oppClass, - ObjectPostProcessor.class); + Class oppType = GenericTypeResolver.resolveTypeArgument(oppClass, ObjectPostProcessor.class); if (oppType == null || oppType.isAssignableFrom(object.getClass())) { object = opp.postProcess(object); } @@ -130,11 +123,12 @@ public abstract class SecurityConfigurerAdapter> * @param objectPostProcessor the {@link ObjectPostProcessor} to add * @return true if the {@link ObjectPostProcessor} was added, else false */ - private boolean addObjectPostProcessor( - ObjectPostProcessor objectPostProcessor) { + private boolean addObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { boolean result = this.postProcessors.add(objectPostProcessor); postProcessors.sort(AnnotationAwareOrderComparator.INSTANCE); return result; } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/ProviderManagerBuilder.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/ProviderManagerBuilder.java index aab2e9eab6..6240d764c0 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/ProviderManagerBuilder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/ProviderManagerBuilder.java @@ -24,11 +24,10 @@ import org.springframework.security.config.annotation.SecurityBuilder; * Interface for operating on a SecurityBuilder that creates a {@link ProviderManager} * * @author Rob Winch - * * @param the type of the {@link SecurityBuilder} */ -public interface ProviderManagerBuilder> extends - SecurityBuilder { +public interface ProviderManagerBuilder> + extends SecurityBuilder { /** * Add authentication based upon the custom {@link AuthenticationProvider} that is @@ -36,10 +35,11 @@ public interface ProviderManagerBuilder> ext * customizations must be done externally and the {@link ProviderManagerBuilder} is * returned immediately. * - * Note that an Exception is thrown if an error occurs when adding the {@link AuthenticationProvider}. - * + * Note that an Exception is thrown if an error occurs when adding the + * {@link AuthenticationProvider}. * @return a {@link ProviderManagerBuilder} to allow further authentication to be * provided to the {@link ProviderManagerBuilder} */ B authenticationProvider(AuthenticationProvider authenticationProvider); + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/builders/AuthenticationManagerBuilder.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/builders/AuthenticationManagerBuilder.java index 36b4a97a28..3052cfa2c7 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/builders/AuthenticationManagerBuilder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/builders/AuthenticationManagerBuilder.java @@ -48,15 +48,19 @@ import org.springframework.util.Assert; * @since 3.2 */ public class AuthenticationManagerBuilder - extends - AbstractConfiguredSecurityBuilder + extends AbstractConfiguredSecurityBuilder implements ProviderManagerBuilder { + private final Log logger = LogFactory.getLog(getClass()); private AuthenticationManager parentAuthenticationManager; + private List authenticationProviders = new ArrayList<>(); + private UserDetailsService defaultUserDetailsService; + private Boolean eraseCredentials; + private AuthenticationEventPublisher eventPublisher; /** @@ -71,18 +75,15 @@ public class AuthenticationManagerBuilder * Allows providing a parent {@link AuthenticationManager} that will be tried if this * {@link AuthenticationManager} was unable to attempt to authenticate the provided * {@link Authentication}. - * * @param authenticationManager the {@link AuthenticationManager} that should be used * if the current {@link AuthenticationManager} was unable to attempt to authenticate * the provided {@link Authentication}. * @return the {@link AuthenticationManagerBuilder} for further adding types of * authentication */ - public AuthenticationManagerBuilder parentAuthenticationManager( - AuthenticationManager authenticationManager) { + public AuthenticationManagerBuilder parentAuthenticationManager(AuthenticationManager authenticationManager) { if (authenticationManager instanceof ProviderManager) { - eraseCredentials(((ProviderManager) authenticationManager) - .isEraseCredentialsAfterAuthentication()); + eraseCredentials(((ProviderManager) authenticationManager).isEraseCredentialsAfterAuthentication()); } this.parentAuthenticationManager = authenticationManager; return this; @@ -90,20 +91,16 @@ public class AuthenticationManagerBuilder /** * Sets the {@link AuthenticationEventPublisher} - * * @param eventPublisher the {@link AuthenticationEventPublisher} to use * @return the {@link AuthenticationManagerBuilder} for further customizations */ - public AuthenticationManagerBuilder authenticationEventPublisher( - AuthenticationEventPublisher eventPublisher) { + public AuthenticationManagerBuilder authenticationEventPublisher(AuthenticationEventPublisher eventPublisher) { Assert.notNull(eventPublisher, "AuthenticationEventPublisher cannot be null"); this.eventPublisher = eventPublisher; return this; } /** - * - * * @param eraseCredentials true if {@link AuthenticationManager} should clear the * credentials from the {@link Authentication} object after authenticating * @return the {@link AuthenticationManagerBuilder} for further customizations @@ -124,7 +121,6 @@ public class AuthenticationManagerBuilder * {@link UserDetailsService}'s may override this {@link UserDetailsService} as the * default. *

- * * @return a {@link InMemoryUserDetailsManagerConfigurer} to allow customization of * the in memory authentication * @throws Exception if an error occurs when adding the in memory authentication @@ -141,8 +137,8 @@ public class AuthenticationManagerBuilder * *

* When using with a persistent data store, it is best to add users external of - * configuration using something like Flyway or Liquibase to create the schema and adding + * configuration using something like Flyway or + * Liquibase to create the schema and adding * users to ensure these steps are only done once and that the optimal SQL is used. *

* @@ -154,13 +150,11 @@ public class AuthenticationManagerBuilder * "https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#user-schema" * >User Schema section of the reference for the default schema. *

- * * @return a {@link JdbcUserDetailsManagerConfigurer} to allow customization of the * JDBC authentication * @throws Exception if an error occurs when adding the JDBC authentication */ - public JdbcUserDetailsManagerConfigurer jdbcAuthentication() - throws Exception { + public JdbcUserDetailsManagerConfigurer jdbcAuthentication() throws Exception { return apply(new JdbcUserDetailsManagerConfigurer<>()); } @@ -175,7 +169,6 @@ public class AuthenticationManagerBuilder * {@link UserDetailsService}'s may override this {@link UserDetailsService} as the * default. *

- * * @return a {@link DaoAuthenticationConfigurer} to allow customization of the DAO * authentication * @throws Exception if an error occurs when adding the {@link UserDetailsService} @@ -184,8 +177,7 @@ public class AuthenticationManagerBuilder public DaoAuthenticationConfigurer userDetailsService( T userDetailsService) throws Exception { this.defaultUserDetailsService = userDetailsService; - return apply(new DaoAuthenticationConfigurer<>( - userDetailsService)); + return apply(new DaoAuthenticationConfigurer<>(userDetailsService)); } /** @@ -196,13 +188,11 @@ public class AuthenticationManagerBuilder *

* This method does NOT ensure that a {@link UserDetailsService} is available * for the {@link #getDefaultUserDetailsService()} method. - * * @return a {@link LdapAuthenticationProviderConfigurer} to allow customization of * the LDAP authentication * @throws Exception if an error occurs when adding the LDAP authentication */ - public LdapAuthenticationProviderConfigurer ldapAuthentication() - throws Exception { + public LdapAuthenticationProviderConfigurer ldapAuthentication() throws Exception { return apply(new LdapAuthenticationProviderConfigurer<>()); } @@ -216,13 +206,12 @@ public class AuthenticationManagerBuilder * This method does NOT ensure that the {@link UserDetailsService} is available * for the {@link #getDefaultUserDetailsService()} method. * - * Note that an {@link Exception} might be thrown if an error occurs when adding the {@link AuthenticationProvider}. - * + * Note that an {@link Exception} might be thrown if an error occurs when adding the + * {@link AuthenticationProvider}. * @return a {@link AuthenticationManagerBuilder} to allow further authentication to * be provided to the {@link AuthenticationManagerBuilder} */ - public AuthenticationManagerBuilder authenticationProvider( - AuthenticationProvider authenticationProvider) { + public AuthenticationManagerBuilder authenticationProvider(AuthenticationProvider authenticationProvider) { this.authenticationProviders.add(authenticationProvider); return this; } @@ -233,8 +222,7 @@ public class AuthenticationManagerBuilder logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null."); return null; } - ProviderManager providerManager = new ProviderManager(authenticationProviders, - parentAuthenticationManager); + ProviderManager providerManager = new ProviderManager(authenticationProviders, parentAuthenticationManager); if (eraseCredentials != null) { providerManager.setEraseCredentialsAfterAuthentication(eraseCredentials); } @@ -257,8 +245,8 @@ public class AuthenticationManagerBuilder * {@link SecurityConfigurer} that is last could check this method and provide a * default configuration in the {@link SecurityConfigurer#configure(SecurityBuilder)} * method. - * - * @return true, if {@link AuthenticationManagerBuilder} is configured, otherwise false + * @return true, if {@link AuthenticationManagerBuilder} is configured, otherwise + * false */ public boolean isConfigured() { return !authenticationProviders.isEmpty() || parentAuthenticationManager != null; @@ -267,7 +255,6 @@ public class AuthenticationManagerBuilder /** * Gets the default {@link UserDetailsService} for the * {@link AuthenticationManagerBuilder}. The result may be null in some circumstances. - * * @return the default {@link UserDetailsService} for the * {@link AuthenticationManagerBuilder} */ @@ -278,7 +265,6 @@ public class AuthenticationManagerBuilder /** * Captures the {@link UserDetailsService} from any {@link UserDetailsAwareConfigurer} * . - * * @param configurer the {@link UserDetailsAwareConfigurer} to capture the * {@link UserDetailsService} from. * @return the {@link UserDetailsAwareConfigurer} for further customizations @@ -289,4 +275,5 @@ public class AuthenticationManagerBuilder this.defaultUserDetailsService = configurer.getUserDetailsService(); return super.apply(configurer); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java index a9a7b088af..26232408cc 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java @@ -68,18 +68,19 @@ public class AuthenticationConfiguration { private boolean authenticationManagerInitialized; - private List globalAuthConfigurers = Collections - .emptyList(); + private List globalAuthConfigurers = Collections.emptyList(); private ObjectPostProcessor objectPostProcessor; @Bean - public AuthenticationManagerBuilder authenticationManagerBuilder( - ObjectPostProcessor objectPostProcessor, ApplicationContext context) { + public AuthenticationManagerBuilder authenticationManagerBuilder(ObjectPostProcessor objectPostProcessor, + ApplicationContext context) { LazyPasswordEncoder defaultPasswordEncoder = new LazyPasswordEncoder(context); - AuthenticationEventPublisher authenticationEventPublisher = getBeanOrNull(context, AuthenticationEventPublisher.class); + AuthenticationEventPublisher authenticationEventPublisher = getBeanOrNull(context, + AuthenticationEventPublisher.class); - DefaultPasswordEncoderAuthenticationManagerBuilder result = new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, defaultPasswordEncoder); + DefaultPasswordEncoderAuthenticationManagerBuilder result = new DefaultPasswordEncoderAuthenticationManagerBuilder( + objectPostProcessor, defaultPasswordEncoder); if (authenticationEventPublisher != null) { result.authenticationEventPublisher(authenticationEventPublisher); } @@ -93,12 +94,14 @@ public class AuthenticationConfiguration { } @Bean - public static InitializeUserDetailsBeanManagerConfigurer initializeUserDetailsBeanManagerConfigurer(ApplicationContext context) { + public static InitializeUserDetailsBeanManagerConfigurer initializeUserDetailsBeanManagerConfigurer( + ApplicationContext context) { return new InitializeUserDetailsBeanManagerConfigurer(context); } @Bean - public static InitializeAuthenticationProviderBeanManagerConfigurer initializeAuthenticationProviderBeanManagerConfigurer(ApplicationContext context) { + public static InitializeAuthenticationProviderBeanManagerConfigurer initializeAuthenticationProviderBeanManagerConfigurer( + ApplicationContext context) { return new InitializeAuthenticationProviderBeanManagerConfigurer(context); } @@ -126,8 +129,7 @@ public class AuthenticationConfiguration { } @Autowired(required = false) - public void setGlobalAuthenticationConfigurers( - List configurers) { + public void setGlobalAuthenticationConfigurers(List configurers) { configurers.sort(AnnotationAwareOrderComparator.INSTANCE); this.globalAuthConfigurers = configurers; } @@ -145,8 +147,8 @@ public class AuthenticationConfiguration { @SuppressWarnings("unchecked") private T lazyBean(Class interfaceName) { LazyInitTargetSource lazyTargetSource = new LazyInitTargetSource(); - String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( - applicationContext, interfaceName); + String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, + interfaceName); if (beanNamesForType.length == 0) { return null; } @@ -154,12 +156,13 @@ public class AuthenticationConfiguration { if (beanNamesForType.length > 1) { List primaryBeanNames = getPrimaryBeanNames(beanNamesForType); - Assert.isTrue(primaryBeanNames.size() != 0, () -> "Found " + beanNamesForType.length - + " beans for type " + interfaceName + ", but none marked as primary"); - Assert.isTrue(primaryBeanNames.size() == 1, () -> "Found " + primaryBeanNames.size() - + " beans for type " + interfaceName + " marked as primary"); + Assert.isTrue(primaryBeanNames.size() != 0, () -> "Found " + beanNamesForType.length + " beans for type " + + interfaceName + ", but none marked as primary"); + Assert.isTrue(primaryBeanNames.size() == 1, () -> "Found " + primaryBeanNames.size() + " beans for type " + + interfaceName + " marked as primary"); beanName = primaryBeanNames.get(0); - } else { + } + else { beanName = beanNamesForType[0]; } @@ -177,8 +180,8 @@ public class AuthenticationConfiguration { return Collections.emptyList(); } for (String beanName : beanNamesForType) { - if (((ConfigurableApplicationContext) applicationContext).getBeanFactory() - .getBeanDefinition(beanName).isPrimary()) { + if (((ConfigurableApplicationContext) applicationContext).getBeanFactory().getBeanDefinition(beanName) + .isPrimary()) { list.add(beanName); } } @@ -192,16 +195,17 @@ public class AuthenticationConfiguration { private static T getBeanOrNull(ApplicationContext applicationContext, Class type) { try { return applicationContext.getBean(type); - } catch(NoSuchBeanDefinitionException notFound) { + } + catch (NoSuchBeanDefinitionException notFound) { return null; } } - private static class EnableGlobalAuthenticationAutowiredConfigurer extends - GlobalAuthenticationConfigurerAdapter { + private static class EnableGlobalAuthenticationAutowiredConfigurer extends GlobalAuthenticationConfigurerAdapter { + private final ApplicationContext context; - private static final Log logger = LogFactory - .getLog(EnableGlobalAuthenticationAutowiredConfigurer.class); + + private static final Log logger = LogFactory.getLog(EnableGlobalAuthenticationAutowiredConfigurer.class); EnableGlobalAuthenticationAutowiredConfigurer(ApplicationContext context) { this.context = context; @@ -209,12 +213,12 @@ public class AuthenticationConfiguration { @Override public void init(AuthenticationManagerBuilder auth) { - Map beansWithAnnotation = context - .getBeansWithAnnotation(EnableGlobalAuthentication.class); + Map beansWithAnnotation = context.getBeansWithAnnotation(EnableGlobalAuthentication.class); if (logger.isDebugEnabled()) { logger.debug("Eagerly initializing " + beansWithAnnotation); } } + } /** @@ -225,8 +229,11 @@ public class AuthenticationConfiguration { * @since 4.1.1 */ static final class AuthenticationManagerDelegator implements AuthenticationManager { + private AuthenticationManagerBuilder delegateBuilder; + private AuthenticationManager delegate; + private final Object delegateMonitor = new Object(); AuthenticationManagerDelegator(AuthenticationManagerBuilder delegateBuilder) { @@ -235,8 +242,7 @@ public class AuthenticationConfiguration { } @Override - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (this.delegate != null) { return this.delegate.authenticate(authentication); } @@ -255,46 +261,46 @@ public class AuthenticationConfiguration { public String toString() { return "AuthenticationManagerDelegator [delegate=" + this.delegate + "]"; } + } static class DefaultPasswordEncoderAuthenticationManagerBuilder extends AuthenticationManagerBuilder { + private PasswordEncoder defaultPasswordEncoder; /** * Creates a new instance - * * @param objectPostProcessor the {@link ObjectPostProcessor} instance to use. */ - DefaultPasswordEncoderAuthenticationManagerBuilder( - ObjectPostProcessor objectPostProcessor, PasswordEncoder defaultPasswordEncoder) { + DefaultPasswordEncoderAuthenticationManagerBuilder(ObjectPostProcessor objectPostProcessor, + PasswordEncoder defaultPasswordEncoder) { super(objectPostProcessor); this.defaultPasswordEncoder = defaultPasswordEncoder; } @Override public InMemoryUserDetailsManagerConfigurer inMemoryAuthentication() - throws Exception { - return super.inMemoryAuthentication() - .passwordEncoder(this.defaultPasswordEncoder); + throws Exception { + return super.inMemoryAuthentication().passwordEncoder(this.defaultPasswordEncoder); } @Override - public JdbcUserDetailsManagerConfigurer jdbcAuthentication() - throws Exception { - return super.jdbcAuthentication() - .passwordEncoder(this.defaultPasswordEncoder); + public JdbcUserDetailsManagerConfigurer jdbcAuthentication() throws Exception { + return super.jdbcAuthentication().passwordEncoder(this.defaultPasswordEncoder); } @Override public DaoAuthenticationConfigurer userDetailsService( - T userDetailsService) throws Exception { - return super.userDetailsService(userDetailsService) - .passwordEncoder(this.defaultPasswordEncoder); + T userDetailsService) throws Exception { + return super.userDetailsService(userDetailsService).passwordEncoder(this.defaultPasswordEncoder); } + } static class LazyPasswordEncoder implements PasswordEncoder { + private ApplicationContext applicationContext; + private PasswordEncoder passwordEncoder; LazyPasswordEncoder(ApplicationContext applicationContext) { @@ -307,8 +313,7 @@ public class AuthenticationConfiguration { } @Override - public boolean matches(CharSequence rawPassword, - String encodedPassword) { + public boolean matches(CharSequence rawPassword, String encodedPassword) { return getPasswordEncoder().matches(rawPassword, encodedPassword); } @@ -333,5 +338,7 @@ public class AuthenticationConfiguration { public String toString() { return getPasswordEncoder().toString(); } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthentication.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthentication.java index 4a41eb75bf..78f8b11757 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthentication.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthentication.java @@ -87,4 +87,5 @@ import org.springframework.security.config.annotation.web.servlet.configuration. @Import(AuthenticationConfiguration.class) @Configuration public @interface EnableGlobalAuthentication { + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/GlobalAuthenticationConfigurerAdapter.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/GlobalAuthenticationConfigurerAdapter.java index c3d6e253d4..cf349a0bf0 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/GlobalAuthenticationConfigurerAdapter.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/GlobalAuthenticationConfigurerAdapter.java @@ -31,12 +31,13 @@ import org.springframework.security.config.annotation.authentication.configurati * @author Rob Winch */ @Order(100) -public abstract class GlobalAuthenticationConfigurerAdapter implements - SecurityConfigurer { +public abstract class GlobalAuthenticationConfigurerAdapter + implements SecurityConfigurer { public void init(AuthenticationManagerBuilder auth) throws Exception { } public void configure(AuthenticationManagerBuilder auth) throws Exception { } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeAuthenticationProviderBeanManagerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeAuthenticationProviderBeanManagerConfigurer.java index 6aa64b8dfa..499ad2b748 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeAuthenticationProviderBeanManagerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeAuthenticationProviderBeanManagerConfigurer.java @@ -21,26 +21,23 @@ import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; /** - * Lazily initializes the global authentication with an {@link AuthenticationProvider} if it is - * not yet configured and there is only a single Bean of that type. + * Lazily initializes the global authentication with an {@link AuthenticationProvider} if + * it is not yet configured and there is only a single Bean of that type. * * @author Rob Winch * @since 4.1 */ @Order(InitializeAuthenticationProviderBeanManagerConfigurer.DEFAULT_ORDER) -class InitializeAuthenticationProviderBeanManagerConfigurer - extends GlobalAuthenticationConfigurerAdapter { +class InitializeAuthenticationProviderBeanManagerConfigurer extends GlobalAuthenticationConfigurerAdapter { - static final int DEFAULT_ORDER = InitializeUserDetailsBeanManagerConfigurer.DEFAULT_ORDER - - 100; + static final int DEFAULT_ORDER = InitializeUserDetailsBeanManagerConfigurer.DEFAULT_ORDER - 100; private final ApplicationContext context; /** * @param context the ApplicationContext to look up beans. */ - InitializeAuthenticationProviderBeanManagerConfigurer( - ApplicationContext context) { + InitializeAuthenticationProviderBeanManagerConfigurer(ApplicationContext context) { this.context = context; } @@ -49,25 +46,24 @@ class InitializeAuthenticationProviderBeanManagerConfigurer auth.apply(new InitializeAuthenticationProviderManagerConfigurer()); } - class InitializeAuthenticationProviderManagerConfigurer - extends GlobalAuthenticationConfigurerAdapter { + class InitializeAuthenticationProviderManagerConfigurer extends GlobalAuthenticationConfigurerAdapter { + @Override public void configure(AuthenticationManagerBuilder auth) { if (auth.isConfigured()) { return; } - AuthenticationProvider authenticationProvider = getBeanOrNull( - AuthenticationProvider.class); + AuthenticationProvider authenticationProvider = getBeanOrNull(AuthenticationProvider.class); if (authenticationProvider == null) { return; } - auth.authenticationProvider(authenticationProvider); } /** - * @return a bean of the requested class if there's just a single registered component, null otherwise. + * @return a bean of the requested class if there's just a single registered + * component, null otherwise. */ private T getBeanOrNull(Class type) { String[] beanNames = InitializeAuthenticationProviderBeanManagerConfigurer.this.context @@ -76,8 +72,9 @@ class InitializeAuthenticationProviderBeanManagerConfigurer return null; } - return InitializeAuthenticationProviderBeanManagerConfigurer.this.context - .getBean(beanNames[0], type); + return InitializeAuthenticationProviderBeanManagerConfigurer.this.context.getBean(beanNames[0], type); } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeUserDetailsBeanManagerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeUserDetailsBeanManagerConfigurer.java index 14013dbf0d..b1aa40b345 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeUserDetailsBeanManagerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/InitializeUserDetailsBeanManagerConfigurer.java @@ -33,8 +33,7 @@ import org.springframework.security.core.userdetails.UserDetailsPasswordService; * @since 4.1 */ @Order(InitializeUserDetailsBeanManagerConfigurer.DEFAULT_ORDER) -class InitializeUserDetailsBeanManagerConfigurer - extends GlobalAuthenticationConfigurerAdapter { +class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationConfigurerAdapter { static final int DEFAULT_ORDER = Ordered.LOWEST_PRECEDENCE - 5000; @@ -52,15 +51,14 @@ class InitializeUserDetailsBeanManagerConfigurer auth.apply(new InitializeUserDetailsManagerConfigurer()); } - class InitializeUserDetailsManagerConfigurer - extends GlobalAuthenticationConfigurerAdapter { + class InitializeUserDetailsManagerConfigurer extends GlobalAuthenticationConfigurerAdapter { + @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { if (auth.isConfigured()) { return; } - UserDetailsService userDetailsService = getBeanOrNull( - UserDetailsService.class); + UserDetailsService userDetailsService = getBeanOrNull(UserDetailsService.class); if (userDetailsService == null) { return; } @@ -82,17 +80,18 @@ class InitializeUserDetailsBeanManagerConfigurer } /** - * @return a bean of the requested class if there's just a single registered component, null otherwise. + * @return a bean of the requested class if there's just a single registered + * component, null otherwise. */ private T getBeanOrNull(Class type) { - String[] beanNames = InitializeUserDetailsBeanManagerConfigurer.this.context - .getBeanNamesForType(type); + String[] beanNames = InitializeUserDetailsBeanManagerConfigurer.this.context.getBeanNamesForType(type); if (beanNames.length != 1) { return null; } - return InitializeUserDetailsBeanManagerConfigurer.this.context - .getBean(beanNames[0], type); + return InitializeUserDetailsBeanManagerConfigurer.this.context.getBean(beanNames[0], type); } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java index 9c6e2bae85..2e3514057c 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java @@ -52,27 +52,41 @@ import org.springframework.util.ClassUtils; * Configures LDAP {@link AuthenticationProvider} in the {@link ProviderManagerBuilder}. * * @param the {@link ProviderManagerBuilder} type that this is configuring. - * * @author Rob Winch * @author Eddú Meléndez * @since 3.2 */ public class LdapAuthenticationProviderConfigurer> extends SecurityConfigurerAdapter { + private String groupRoleAttribute = "cn"; + private String groupSearchBase = ""; + private boolean groupSearchSubtree = false; + private String groupSearchFilter = "(uniqueMember={0})"; + private String rolePrefix = "ROLE_"; + private String userSearchBase = ""; // only for search + private String userSearchFilter = null; // "uid={0}"; // only for search + private String[] userDnPatterns; + private BaseLdapPathContextSource contextSource; + private ContextSourceBuilder contextSourceBuilder = new ContextSourceBuilder(); + private UserDetailsContextMapper userDetailsContextMapper; + private PasswordEncoder passwordEncoder; + private String passwordAttribute; + private LdapAuthoritiesPopulator ldapAuthoritiesPopulator; + private GrantedAuthoritiesMapper authoritiesMapper; private LdapAuthenticationProvider build() throws Exception { @@ -81,19 +95,17 @@ public class LdapAuthenticationProviderConfigurer withObjectPostProcessor( - ObjectPostProcessor objectPostProcessor) { + public LdapAuthenticationProviderConfigurer withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { addObjectPostProcessor(objectPostProcessor); return this; } @@ -119,7 +129,6 @@ public class LdapAuthenticationProviderConfigurer authoritiesMapper(GrantedAuthoritiesMapper grantedAuthoritiesMapper) { + public LdapAuthenticationProviderConfigurer authoritiesMapper( + GrantedAuthoritiesMapper grantedAuthoritiesMapper) { this.authoritiesMapper = grantedAuthoritiesMapper; return this; } /** - * Gets the {@link GrantedAuthoritiesMapper} and defaults to {@link SimpleAuthorityMapper}. - * + * Gets the {@link GrantedAuthoritiesMapper} and defaults to + * {@link SimpleAuthorityMapper}. * @return the {@link GrantedAuthoritiesMapper} * @throws Exception if errors in {@link SimpleAuthorityMapper#afterPropertiesSet()} */ @@ -173,12 +182,10 @@ public class LdapAuthenticationProviderConfigurer contextSource( - BaseLdapPathContextSource contextSource) { + public LdapAuthenticationProviderConfigurer contextSource(BaseLdapPathContextSource contextSource) { this.contextSource = contextSource; return this; } @@ -244,7 +244,6 @@ public class LdapAuthenticationProviderConfigurer userDnPatterns( - String... userDnPatterns) { + public LdapAuthenticationProviderConfigurer userDnPatterns(String... userDnPatterns) { this.userDnPatterns = userDnPatterns; return this; } @@ -287,7 +283,6 @@ public class LdapAuthenticationProviderConfigurer groupRoleAttribute( - String groupRoleAttribute) { + public LdapAuthenticationProviderConfigurer groupRoleAttribute(String groupRoleAttribute) { this.groupRoleAttribute = groupRoleAttribute; return this; } @@ -323,11 +317,10 @@ public class LdapAuthenticationProviderConfigurergroupSearchBase. + * groupSearchBase. * @return the {@link LdapAuthenticationProviderConfigurer} for further customizations */ public LdapAuthenticationProviderConfigurer groupSearchSubtree(boolean groupSearchSubtree) { @@ -338,12 +331,10 @@ public class LdapAuthenticationProviderConfigurer groupSearchFilter( - String groupSearchFilter) { + public LdapAuthenticationProviderConfigurer groupSearchFilter(String groupSearchFilter) { this.groupSearchFilter = groupSearchFilter; return this; } @@ -351,7 +342,6 @@ public class LdapAuthenticationProviderConfigurer userSearchFilter( - String userSearchFilter) { + public LdapAuthenticationProviderConfigurer userSearchFilter(String userSearchFilter) { this.userSearchFilter = userSearchFilter; return this; } @@ -413,7 +400,6 @@ public class LdapAuthenticationProviderConfigurer and() { @@ -435,6 +420,7 @@ public class LdapAuthenticationProviderConfigurer the type of the {@link ProviderManagerBuilder} that is being configured - * * @author Rob Winch * @since 3.2 */ @@ -40,4 +39,5 @@ public class InMemoryUserDetailsManagerConfigurer())); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/JdbcUserDetailsManagerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/JdbcUserDetailsManagerConfigurer.java index 035bd7877f..89928fb6e6 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/JdbcUserDetailsManagerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/JdbcUserDetailsManagerConfigurer.java @@ -40,7 +40,6 @@ import org.springframework.security.provisioning.JdbcUserDetailsManager; * methods have reasonable defaults. * * @param the type of the {@link ProviderManagerBuilder} that is being configured - * * @author Rob Winch * @since 3.2 */ @@ -61,9 +60,9 @@ public class JdbcUserDetailsManagerConfigurer dataSource(DataSource dataSource) { this.dataSource = dataSource; @@ -94,7 +93,6 @@ public class JdbcUserDetailsManagerConfigurer * select username,authority from authorities where username = ? * - * * @param query The query to use for selecting the username, authority by username. * Must contain a single parameter for the username. * @return The {@link JdbcUserDetailsManagerConfigurer} used for additional @@ -116,7 +114,6 @@ public class JdbcUserDetailsManagerConfigurer - * * @param query The query to use for selecting the authorities by group. Must contain * a single parameter for the username. * @return The {@link JdbcUserDetailsManagerConfigurer} used for additional @@ -132,9 +129,9 @@ public class JdbcUserDetailsManagerConfigurer rolePrefix(String rolePrefix) { getUserDetailsService().setRolePrefix(rolePrefix); @@ -143,7 +140,6 @@ public class JdbcUserDetailsManagerConfigurer withDefaultSchema() { - this.initScripts.add(new ClassPathResource( - "org/springframework/security/core/userdetails/jdbc/users.ddl")); + this.initScripts.add(new ClassPathResource("org/springframework/security/core/userdetails/jdbc/users.ddl")); return this; } @@ -189,4 +183,5 @@ public class JdbcUserDetailsManagerConfigurer the type of the {@link SecurityBuilder} that is being configured * @param the type of {@link UserDetailsManagerConfigurer} - * * @author Rob Winch * @since 3.2 */ @@ -51,7 +50,6 @@ public class UserDetailsManagerConfigurer, C /** * Populates the users that have been added. - * * @throws Exception */ @Override @@ -67,7 +65,6 @@ public class UserDetailsManagerConfigurer, C /** * Allows adding a user to the {@link UserDetailsManager} that is being created. This * method can be invoked multiple times to add multiple users. - * * @param userDetails the user to add. Cannot be null. * @return the {@link UserDetailsBuilder} for further customizations */ @@ -80,7 +77,6 @@ public class UserDetailsManagerConfigurer, C /** * Allows adding a user to the {@link UserDetailsManager} that is being created. This * method can be invoked multiple times to add multiple users. - * * @param userBuilder the user to add. Cannot be null. * @return the {@link UserDetailsBuilder} for further customizations */ @@ -93,7 +89,6 @@ public class UserDetailsManagerConfigurer, C /** * Allows adding a user to the {@link UserDetailsManager} that is being created. This * method can be invoked multiple times to add multiple users. - * * @param username the username for the user being added. Cannot be null. * @return the {@link UserDetailsBuilder} for further customizations */ @@ -110,7 +105,9 @@ public class UserDetailsManagerConfigurer, C * should provided. The remaining attributes have reasonable defaults. */ public class UserDetailsBuilder { + private UserBuilder user; + private final C builder; /** @@ -122,9 +119,8 @@ public class UserDetailsManagerConfigurer, C } /** - * Returns the {@link UserDetailsManagerConfigurer} for method chaining (i.e. to add - * another user) - * + * Returns the {@link UserDetailsManagerConfigurer} for method chaining (i.e. to + * add another user) * @return the {@link UserDetailsManagerConfigurer} for method chaining */ public C and() { @@ -133,7 +129,6 @@ public class UserDetailsManagerConfigurer, C /** * Populates the username. This attribute is required. - * * @param username the username. Cannot be null. * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate * additional attributes for this user) @@ -145,7 +140,6 @@ public class UserDetailsManagerConfigurer, C /** * Populates the password. This attribute is required. - * * @param password the password. Cannot be null. * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate * additional attributes for this user) @@ -174,7 +168,6 @@ public class UserDetailsManagerConfigurer, C * This attribute is required, but can also be populated with * {@link #authorities(String...)}. *

- * * @param roles the roles for this user (i.e. USER, ADMIN, etc). Cannot be null, * contain null values or start with "ROLE_" * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate @@ -187,7 +180,6 @@ public class UserDetailsManagerConfigurer, C /** * Populates the authorities. This attribute is required. - * * @param authorities the authorities for this user. Cannot be null, or contain * null values * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate @@ -201,7 +193,6 @@ public class UserDetailsManagerConfigurer, C /** * Populates the authorities. This attribute is required. - * * @param authorities the authorities for this user. Cannot be null, or contain * null values * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate @@ -215,7 +206,6 @@ public class UserDetailsManagerConfigurer, C /** * Populates the authorities. This attribute is required. - * * @param authorities the authorities for this user (i.e. ROLE_USER, ROLE_ADMIN, * etc). Cannot be null, or contain null values * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate @@ -229,7 +219,6 @@ public class UserDetailsManagerConfigurer, C /** * Defines if the account is expired or not. Default is false. - * * @param accountExpired true if the account is expired, false otherwise * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate * additional attributes for this user) @@ -241,7 +230,6 @@ public class UserDetailsManagerConfigurer, C /** * Defines if the account is locked or not. Default is false. - * * @param accountLocked true if the account is locked, false otherwise * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate * additional attributes for this user) @@ -253,7 +241,6 @@ public class UserDetailsManagerConfigurer, C /** * Defines if the credentials are expired or not. Default is false. - * * @param credentialsExpired true if the credentials are expired, false otherwise * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate * additional attributes for this user) @@ -265,7 +252,6 @@ public class UserDetailsManagerConfigurer, C /** * Defines if the account is disabled or not. Default is false. - * * @param disabled true if the account is disabled, false otherwise * @return the {@link UserDetailsBuilder} for method chaining (i.e. to populate * additional attributes for this user) @@ -278,5 +264,7 @@ public class UserDetailsManagerConfigurer, C UserDetails build() { return this.user.build(); } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/AbstractDaoAuthenticationConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/AbstractDaoAuthenticationConfigurer.java index 0cf004160f..ebc2fa8e36 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/AbstractDaoAuthenticationConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/AbstractDaoAuthenticationConfigurer.java @@ -28,7 +28,6 @@ import org.springframework.security.core.userdetails.UserDetailsPasswordService; * * @author Rob Winch * @since 3.2 - * * @param the type of the {@link SecurityBuilder} * @param the type of {@link AbstractDaoAuthenticationConfigurer} this is * @param The type of {@link UserDetailsService} that is being used @@ -36,12 +35,13 @@ import org.springframework.security.core.userdetails.UserDetailsPasswordService; */ abstract class AbstractDaoAuthenticationConfigurer, C extends AbstractDaoAuthenticationConfigurer, U extends UserDetailsService> extends UserDetailsAwareConfigurer { + private DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); + private final U userDetailsService; /** * Creates a new instance - * * @param userDetailsService */ protected AbstractDaoAuthenticationConfigurer(U userDetailsService) { @@ -54,7 +54,6 @@ abstract class AbstractDaoAuthenticationConfigurer The type of {@link ProviderManagerBuilder} this is * @param The type of {@link UserDetailsService} that is being used * */ public class DaoAuthenticationConfigurer, U extends UserDetailsService> - extends - AbstractDaoAuthenticationConfigurer, U> { + extends AbstractDaoAuthenticationConfigurer, U> { /** * Creates a new instance @@ -40,4 +38,5 @@ public class DaoAuthenticationConfigurer, U public DaoAuthenticationConfigurer(U userDetailsService) { super(userDetailsService); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/UserDetailsAwareConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/UserDetailsAwareConfigurer.java index 7ba27523ec..ee2dc6eac4 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/UserDetailsAwareConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/userdetails/UserDetailsAwareConfigurer.java @@ -26,7 +26,6 @@ import org.springframework.security.core.userdetails.UserDetailsService; * value with {@link AuthenticationManagerBuilder}. * * @author Rob Winch - * * @param the type of the {@link ProviderManagerBuilder} * @param the type of {@link UserDetailsService} */ @@ -38,4 +37,5 @@ public abstract class UserDetailsAwareConfigurer the type of the {@link ProviderManagerBuilder} * @param the {@link UserDetailsServiceConfigurer} (or this) * @param the type of UserDetailsService being used to allow for returning the @@ -55,4 +54,5 @@ public class UserDetailsServiceConfigurer, C */ protected void initUserDetailsService() throws Exception { } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessor.java b/config/src/main/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessor.java index 813e05684c..5844af0506 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessor.java @@ -39,13 +39,16 @@ import org.springframework.util.Assert; */ final class AutowireBeanFactoryObjectPostProcessor implements ObjectPostProcessor, DisposableBean, SmartInitializingSingleton { + private final Log logger = LogFactory.getLog(getClass()); + private final AutowireCapableBeanFactory autowireBeanFactory; + private final List disposableBeans = new ArrayList<>(); + private final List smartSingletons = new ArrayList<>(); - AutowireBeanFactoryObjectPostProcessor( - AutowireCapableBeanFactory autowireBeanFactory) { + AutowireBeanFactoryObjectPostProcessor(AutowireCapableBeanFactory autowireBeanFactory) { Assert.notNull(autowireBeanFactory, "autowireBeanFactory cannot be null"); this.autowireBeanFactory = autowireBeanFactory; } @@ -64,13 +67,11 @@ final class AutowireBeanFactoryObjectPostProcessor } T result = null; try { - result = (T) this.autowireBeanFactory.initializeBean(object, - object.toString()); + result = (T) this.autowireBeanFactory.initializeBean(object, object.toString()); } catch (RuntimeException e) { Class type = object.getClass(); - throw new RuntimeException( - "Could not postProcess " + object + " of type " + type, e); + throw new RuntimeException("Could not postProcess " + object + " of type " + type, e); } this.autowireBeanFactory.autowireBean(object); if (result instanceof DisposableBean) { @@ -82,8 +83,11 @@ final class AutowireBeanFactoryObjectPostProcessor return result; } - /* (non-Javadoc) - * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated() + /* + * (non-Javadoc) + * + * @see org.springframework.beans.factory.SmartInitializingSingleton# + * afterSingletonsInstantiated() */ @Override public void afterSingletonsInstantiated() { diff --git a/config/src/main/java/org/springframework/security/config/annotation/configuration/ObjectPostProcessorConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/configuration/ObjectPostProcessorConfiguration.java index 3c61557c4c..3dcaa846b4 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/configuration/ObjectPostProcessorConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/configuration/ObjectPostProcessorConfiguration.java @@ -31,7 +31,6 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe * * @see EnableWebSecurity * @see EnableGlobalMethodSecurity - * * @author Rob Winch * @since 3.2 */ @@ -41,8 +40,8 @@ public class ObjectPostProcessorConfiguration { @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) - public ObjectPostProcessor objectPostProcessor( - AutowireCapableBeanFactory beanFactory) { + public ObjectPostProcessor objectPostProcessor(AutowireCapableBeanFactory beanFactory) { return new AutowireBeanFactoryObjectPostProcessor(beanFactory); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableGlobalMethodSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableGlobalMethodSecurity.java index 7c1fbc49d0..61d4f33609 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableGlobalMethodSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableGlobalMethodSecurity.java @@ -28,8 +28,8 @@ import org.springframework.security.config.annotation.authentication.configurati /** *

- * Enables Spring Security global method security similar to the <global-method-security> - * xml support. + * Enables Spring Security global method security similar to the + * <global-method-security> xml support. * *

* More advanced configurations may wish to extend @@ -82,7 +82,6 @@ public @interface EnableGlobalMethodSecurity { * annotation will be upgraded to subclass proxying at the same time. This approach * has no negative impact in practice unless one is explicitly expecting one type of * proxy vs another, e.g. in tests. - * * @return true if CGILIB proxies should be created instead of interface based * proxies, else false */ @@ -92,7 +91,6 @@ public @interface EnableGlobalMethodSecurity { * Indicate how security advice should be applied. The default is * {@link AdviceMode#PROXY}. * @see AdviceMode - * * @return the {@link AdviceMode} to use */ AdviceMode mode() default AdviceMode.PROXY; @@ -101,8 +99,8 @@ public @interface EnableGlobalMethodSecurity { * Indicate the ordering of the execution of the security advisor when multiple * advices are applied at a specific joinpoint. The default is * {@link Ordered#LOWEST_PRECEDENCE}. - * * @return the order the security advisor should be applied */ int order() default Ordered.LOWEST_PRECEDENCE; + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableReactiveMethodSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableReactiveMethodSecurity.java index 3d659bc4eb..11fcf66e80 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableReactiveMethodSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/EnableReactiveMethodSecurity.java @@ -36,16 +36,18 @@ import java.lang.annotation.Target; @Import({ ReactiveMethodSecuritySelector.class }) @Configuration public @interface EnableReactiveMethodSecurity { + /** - * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed - * to standard Java interface-based proxies. The default is {@code false}. + * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed to + * standard Java interface-based proxies. The default is {@code false}. * Applicable only if {@link #mode()} is set to {@link AdviceMode#PROXY}. - *

Note that setting this attribute to {@code true} will affect all - * Spring-managed beans requiring proxying, not just those marked with {@code @Cacheable}. - * For example, other beans marked with Spring's {@code @Transactional} annotation will - * be upgraded to subclass proxying at the same time. This approach has no negative - * impact in practice unless one is explicitly expecting one type of proxy vs another, - * e.g. in tests. + *

+ * Note that setting this attribute to {@code true} will affect all + * Spring-managed beans requiring proxying, not just those marked with + * {@code @Cacheable}. For example, other beans marked with Spring's + * {@code @Transactional} annotation will be upgraded to subclass proxying at the same + * time. This approach has no negative impact in practice unless one is explicitly + * expecting one type of proxy vs another, e.g. in tests. */ boolean proxyTargetClass() default false; @@ -53,7 +55,6 @@ public @interface EnableReactiveMethodSecurity { * Indicate how security advice should be applied. The default is * {@link AdviceMode#PROXY}. * @see AdviceMode - * * @return the {@link AdviceMode} to use */ AdviceMode mode() default AdviceMode.PROXY; @@ -62,8 +63,8 @@ public @interface EnableReactiveMethodSecurity { * Indicate the ordering of the execution of the security advisor when multiple * advices are applied at a specific joinpoint. The default is * {@link Ordered#LOWEST_PRECEDENCE}. - * * @return the order the security advisor should be applied */ int order() default Ordered.LOWEST_PRECEDENCE; + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityAspectJAutoProxyRegistrar.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityAspectJAutoProxyRegistrar.java index 392c58f3d8..0d2705d6f5 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityAspectJAutoProxyRegistrar.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityAspectJAutoProxyRegistrar.java @@ -36,28 +36,24 @@ import org.springframework.core.type.AnnotationMetadata; * @author Rob Winch * @since 3.2 */ -class GlobalMethodSecurityAspectJAutoProxyRegistrar implements - ImportBeanDefinitionRegistrar { +class GlobalMethodSecurityAspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { /** * Register, escalate, and configure the AspectJ auto proxy creator based on the value * of the @{@link EnableGlobalMethodSecurity#proxyTargetClass()} attribute on the * importing {@code @Configuration} class. */ - public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, - BeanDefinitionRegistry registry) { + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { - BeanDefinition interceptor = registry - .getBeanDefinition("methodSecurityInterceptor"); + BeanDefinition interceptor = registry.getBeanDefinition("methodSecurityInterceptor"); - BeanDefinitionBuilder aspect = BeanDefinitionBuilder - .rootBeanDefinition("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"); + BeanDefinitionBuilder aspect = BeanDefinitionBuilder.rootBeanDefinition( + "org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"); aspect.setFactoryMethod("aspectOf"); aspect.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); aspect.addPropertyValue("securityInterceptor", interceptor); - registry.registerBeanDefinition("annotationSecurityAspect$0", - aspect.getBeanDefinition()); + registry.registerBeanDefinition("annotationSecurityAspect$0", aspect.getBeanDefinition()); } } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java index eb3207f823..244cac59b2 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java @@ -82,24 +82,31 @@ import org.springframework.util.Assert; */ @Configuration(proxyBeanMethods = false) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) -public class GlobalMethodSecurityConfiguration - implements ImportAware, SmartInitializingSingleton, BeanFactoryAware { - private static final Log logger = LogFactory - .getLog(GlobalMethodSecurityConfiguration.class); +public class GlobalMethodSecurityConfiguration implements ImportAware, SmartInitializingSingleton, BeanFactoryAware { + + private static final Log logger = LogFactory.getLog(GlobalMethodSecurityConfiguration.class); + private ObjectPostProcessor objectPostProcessor = new ObjectPostProcessor() { public T postProcess(T object) { throw new IllegalStateException(ObjectPostProcessor.class.getName() - + " is a required bean. Ensure you have used @" - + EnableGlobalMethodSecurity.class.getName()); + + " is a required bean. Ensure you have used @" + EnableGlobalMethodSecurity.class.getName()); } }; + private DefaultMethodSecurityExpressionHandler defaultMethodExpressionHandler = new DefaultMethodSecurityExpressionHandler(); + private AuthenticationManager authenticationManager; + private AuthenticationManagerBuilder auth; + private boolean disableAuthenticationRegistry; + private AnnotationAttributes enableMethodSecurity; + private BeanFactory context; + private MethodSecurityExpressionHandler expressionHandler; + private MethodSecurityInterceptor methodSecurityInterceptor; /** @@ -117,19 +124,17 @@ public class GlobalMethodSecurityConfiguration * Subclasses can override this method to provide a different * {@link MethodInterceptor}. *

- * @param methodSecurityMetadataSource the default {@link MethodSecurityMetadataSource}. - * + * @param methodSecurityMetadataSource the default + * {@link MethodSecurityMetadataSource}. * @return the {@link MethodInterceptor}. */ @Bean public MethodInterceptor methodSecurityInterceptor(MethodSecurityMetadataSource methodSecurityMetadataSource) { - this.methodSecurityInterceptor = isAspectJ() - ? new AspectJMethodSecurityInterceptor() + this.methodSecurityInterceptor = isAspectJ() ? new AspectJMethodSecurityInterceptor() : new MethodSecurityInterceptor(); methodSecurityInterceptor.setAccessDecisionManager(accessDecisionManager()); methodSecurityInterceptor.setAfterInvocationManager(afterInvocationManager()); - methodSecurityInterceptor - .setSecurityMetadataSource(methodSecurityMetadataSource); + methodSecurityInterceptor.setSecurityMetadataSource(methodSecurityMetadataSource); RunAsManager runAsManager = runAsManager(); if (runAsManager != null) { methodSecurityInterceptor.setRunAsManager(runAsManager); @@ -153,11 +158,9 @@ public class GlobalMethodSecurityConfiguration throw new RuntimeException(e); } - PermissionEvaluator permissionEvaluator = getSingleBeanOrNull( - PermissionEvaluator.class); + PermissionEvaluator permissionEvaluator = getSingleBeanOrNull(PermissionEvaluator.class); if (permissionEvaluator != null) { - this.defaultMethodExpressionHandler - .setPermissionEvaluator(permissionEvaluator); + this.defaultMethodExpressionHandler.setPermissionEvaluator(permissionEvaluator); } RoleHierarchy roleHierarchy = getSingleBeanOrNull(RoleHierarchy.class); @@ -165,24 +168,23 @@ public class GlobalMethodSecurityConfiguration this.defaultMethodExpressionHandler.setRoleHierarchy(roleHierarchy); } - AuthenticationTrustResolver trustResolver = getSingleBeanOrNull( - AuthenticationTrustResolver.class); + AuthenticationTrustResolver trustResolver = getSingleBeanOrNull(AuthenticationTrustResolver.class); if (trustResolver != null) { this.defaultMethodExpressionHandler.setTrustResolver(trustResolver); } - GrantedAuthorityDefaults grantedAuthorityDefaults = getSingleBeanOrNull( - GrantedAuthorityDefaults.class); + GrantedAuthorityDefaults grantedAuthorityDefaults = getSingleBeanOrNull(GrantedAuthorityDefaults.class); if (grantedAuthorityDefaults != null) { - this.defaultMethodExpressionHandler.setDefaultRolePrefix( - grantedAuthorityDefaults.getRolePrefix()); + this.defaultMethodExpressionHandler.setDefaultRolePrefix(grantedAuthorityDefaults.getRolePrefix()); } } private T getSingleBeanOrNull(Class type) { try { return context.getBean(type); - } catch (NoSuchBeanDefinitionException e) {} + } + catch (NoSuchBeanDefinitionException e) { + } return null; } @@ -195,14 +197,14 @@ public class GlobalMethodSecurityConfiguration /** * Provide a custom {@link AfterInvocationManager} for the default implementation of - * {@link #methodSecurityInterceptor(MethodSecurityMetadataSource)}. The default is null - * if pre post is not enabled. Otherwise, it returns a {@link AfterInvocationProviderManager}. + * {@link #methodSecurityInterceptor(MethodSecurityMetadataSource)}. The default is + * null if pre post is not enabled. Otherwise, it returns a + * {@link AfterInvocationProviderManager}. * *

* Subclasses should override this method to provide a custom * {@link AfterInvocationManager} *

- * * @return the {@link AfterInvocationManager} to use */ protected AfterInvocationManager afterInvocationManager() { @@ -210,8 +212,7 @@ public class GlobalMethodSecurityConfiguration AfterInvocationProviderManager invocationProviderManager = new AfterInvocationProviderManager(); ExpressionBasedPostInvocationAdvice postAdvice = new ExpressionBasedPostInvocationAdvice( getExpressionHandler()); - PostInvocationAdviceProvider postInvocationAdviceProvider = new PostInvocationAdviceProvider( - postAdvice); + PostInvocationAdviceProvider postInvocationAdviceProvider = new PostInvocationAdviceProvider(postAdvice); List afterInvocationProviders = new ArrayList<>(); afterInvocationProviders.add(postInvocationAdviceProvider); invocationProviderManager.setProviders(afterInvocationProviders); @@ -222,8 +223,8 @@ public class GlobalMethodSecurityConfiguration /** * Provide a custom {@link RunAsManager} for the default implementation of - * {@link #methodSecurityInterceptor(MethodSecurityMetadataSource)}. The default is null. - * + * {@link #methodSecurityInterceptor(MethodSecurityMetadataSource)}. The default is + * null. * @return the {@link RunAsManager} to use */ protected RunAsManager runAsManager() { @@ -239,24 +240,20 @@ public class GlobalMethodSecurityConfiguration *
  • {@link RoleVoter}
  • *
  • {@link AuthenticatedVoter}
  • * - * * @return the {@link AccessDecisionManager} to use */ protected AccessDecisionManager accessDecisionManager() { List> decisionVoters = new ArrayList<>(); if (prePostEnabled()) { - ExpressionBasedPreInvocationAdvice expressionAdvice = - new ExpressionBasedPreInvocationAdvice(); + ExpressionBasedPreInvocationAdvice expressionAdvice = new ExpressionBasedPreInvocationAdvice(); expressionAdvice.setExpressionHandler(getExpressionHandler()); - decisionVoters - .add(new PreInvocationAuthorizationAdviceVoter(expressionAdvice)); + decisionVoters.add(new PreInvocationAuthorizationAdviceVoter(expressionAdvice)); } if (jsr250Enabled()) { decisionVoters.add(new Jsr250Voter()); } RoleVoter roleVoter = new RoleVoter(); - GrantedAuthorityDefaults grantedAuthorityDefaults = - getSingleBeanOrNull(GrantedAuthorityDefaults.class); + GrantedAuthorityDefaults grantedAuthorityDefaults = getSingleBeanOrNull(GrantedAuthorityDefaults.class); if (grantedAuthorityDefaults != null) { roleVoter.setRolePrefix(grantedAuthorityDefaults.getRolePrefix()); } @@ -275,7 +272,6 @@ public class GlobalMethodSecurityConfiguration * Subclasses may override this method to provide a custom * {@link MethodSecurityExpressionHandler} *

    - * * @return the {@link MethodSecurityExpressionHandler} to use */ protected MethodSecurityExpressionHandler createExpressionHandler() { @@ -285,7 +281,6 @@ public class GlobalMethodSecurityConfiguration /** * Gets the {@link MethodSecurityExpressionHandler} or creates it using * {@link #expressionHandler}. - * * @return a non {@code null} {@link MethodSecurityExpressionHandler} */ protected final MethodSecurityExpressionHandler getExpressionHandler() { @@ -298,7 +293,6 @@ public class GlobalMethodSecurityConfiguration /** * Provides a custom {@link MethodSecurityMetadataSource} that is registered with the * {@link #methodSecurityMetadataSource()}. Default is null. - * * @return a custom {@link MethodSecurityMetadataSource} that is registered with the * {@link #methodSecurityMetadataSource()} */ @@ -312,7 +306,6 @@ public class GlobalMethodSecurityConfiguration * {@link #configure(AuthenticationManagerBuilder)}. If * {@link #configure(AuthenticationManagerBuilder)} was not overridden, then an * {@link AuthenticationManager} is attempted to be autowired by type. - * * @return the {@link AuthenticationManager} to use */ protected AuthenticationManager authenticationManager() throws Exception { @@ -323,8 +316,7 @@ public class GlobalMethodSecurityConfiguration auth.authenticationEventPublisher(eventPublisher); configure(auth); if (disableAuthenticationRegistry) { - authenticationManager = getAuthenticationConfiguration() - .getAuthenticationManager(); + authenticationManager = getAuthenticationConfiguration().getAuthenticationManager(); } else { authenticationManager = auth.build(); @@ -337,7 +329,6 @@ public class GlobalMethodSecurityConfiguration * Sub classes can override this method to register different types of authentication. * If not overridden, {@link #configure(AuthenticationManagerBuilder)} will attempt to * autowire by type. - * * @param auth the {@link AuthenticationManagerBuilder} used to register different * authentication mechanisms for the global method security. * @throws Exception @@ -351,7 +342,6 @@ public class GlobalMethodSecurityConfiguration * creates a {@link DelegatingMethodSecurityMetadataSource} based upon * {@link #customMethodSecurityMetadataSource()} and the attributes on * {@link EnableGlobalMethodSecurity}. - * * @return the {@link MethodSecurityMetadataSource} */ @Bean @@ -370,8 +360,8 @@ public class GlobalMethodSecurityConfiguration boolean isJsr250Enabled = jsr250Enabled(); if (!isPrePostEnabled && !isSecuredEnabled && !isJsr250Enabled && !hasCustom) { - throw new IllegalStateException("In the composition of all global method configuration, " + - "no annotation support was actually activated"); + throw new IllegalStateException("In the composition of all global method configuration, " + + "no annotation support was actually activated"); } if (isPrePostEnabled) { @@ -381,12 +371,11 @@ public class GlobalMethodSecurityConfiguration sources.add(new SecuredAnnotationSecurityMetadataSource()); } if (isJsr250Enabled) { - GrantedAuthorityDefaults grantedAuthorityDefaults = - getSingleBeanOrNull(GrantedAuthorityDefaults.class); - Jsr250MethodSecurityMetadataSource jsr250MethodSecurityMetadataSource = this.context.getBean(Jsr250MethodSecurityMetadataSource.class); + GrantedAuthorityDefaults grantedAuthorityDefaults = getSingleBeanOrNull(GrantedAuthorityDefaults.class); + Jsr250MethodSecurityMetadataSource jsr250MethodSecurityMetadataSource = this.context + .getBean(Jsr250MethodSecurityMetadataSource.class); if (grantedAuthorityDefaults != null) { - jsr250MethodSecurityMetadataSource.setDefaultRolePrefix( - grantedAuthorityDefaults.getRolePrefix()); + jsr250MethodSecurityMetadataSource.setDefaultRolePrefix(grantedAuthorityDefaults.getRolePrefix()); } sources.add(jsr250MethodSecurityMetadataSource); } @@ -396,7 +385,6 @@ public class GlobalMethodSecurityConfiguration /** * Creates the {@link PreInvocationAuthorizationAdvice} to be used. The default is * {@link ExpressionBasedPreInvocationAdvice}. - * * @return the {@link PreInvocationAuthorizationAdvice} */ @Bean @@ -419,16 +407,13 @@ public class GlobalMethodSecurityConfiguration @Autowired(required = false) public void setObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { this.objectPostProcessor = objectPostProcessor; - this.defaultMethodExpressionHandler = objectPostProcessor - .postProcess(defaultMethodExpressionHandler); + this.defaultMethodExpressionHandler = objectPostProcessor.postProcess(defaultMethodExpressionHandler); } @Autowired(required = false) - public void setMethodSecurityExpressionHandler( - List handlers) { + public void setMethodSecurityExpressionHandler(List handlers) { if (handlers.size() != 1) { - logger.debug("Not autowiring MethodSecurityExpressionHandler since size != 1. Got " - + handlers); + logger.debug("Not autowiring MethodSecurityExpressionHandler since size != 1. Got " + handlers); return; } this.expressionHandler = handlers.get(0); @@ -466,14 +451,13 @@ public class GlobalMethodSecurityConfiguration private AnnotationAttributes enableMethodSecurity() { if (enableMethodSecurity == null) { // if it is null look at this instance (i.e. a subclass was used) - EnableGlobalMethodSecurity methodSecurityAnnotation = AnnotationUtils - .findAnnotation(getClass(), EnableGlobalMethodSecurity.class); - Assert.notNull(methodSecurityAnnotation, - () -> EnableGlobalMethodSecurity.class.getName() + " is required"); - Map methodSecurityAttrs = AnnotationUtils - .getAnnotationAttributes(methodSecurityAnnotation); + EnableGlobalMethodSecurity methodSecurityAnnotation = AnnotationUtils.findAnnotation(getClass(), + EnableGlobalMethodSecurity.class); + Assert.notNull(methodSecurityAnnotation, () -> EnableGlobalMethodSecurity.class.getName() + " is required"); + Map methodSecurityAttrs = AnnotationUtils.getAnnotationAttributes(methodSecurityAnnotation); this.enableMethodSecurity = AnnotationAttributes.fromMap(methodSecurityAttrs); } return this.enableMethodSecurity; } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java index 1ffa8256a2..da6bf1537f 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java @@ -38,26 +38,22 @@ final class GlobalMethodSecuritySelector implements ImportSelector { public String[] selectImports(AnnotationMetadata importingClassMetadata) { Class annoType = EnableGlobalMethodSecurity.class; - Map annotationAttributes = importingClassMetadata - .getAnnotationAttributes(annoType.getName(), false); - AnnotationAttributes attributes = AnnotationAttributes - .fromMap(annotationAttributes); - Assert.notNull(attributes, () -> String.format( - "@%s is not present on importing class '%s' as expected", + Map annotationAttributes = importingClassMetadata.getAnnotationAttributes(annoType.getName(), + false); + AnnotationAttributes attributes = AnnotationAttributes.fromMap(annotationAttributes); + Assert.notNull(attributes, () -> String.format("@%s is not present on importing class '%s' as expected", annoType.getSimpleName(), importingClassMetadata.getClassName())); // TODO would be nice if could use BeanClassLoaderAware (does not work) - Class importingClass = ClassUtils - .resolveClassName(importingClassMetadata.getClassName(), - ClassUtils.getDefaultClassLoader()); + Class importingClass = ClassUtils.resolveClassName(importingClassMetadata.getClassName(), + ClassUtils.getDefaultClassLoader()); boolean skipMethodSecurityConfiguration = GlobalMethodSecurityConfiguration.class .isAssignableFrom(importingClass); AdviceMode mode = attributes.getEnum("mode"); boolean isProxy = AdviceMode.PROXY == mode; - String autoProxyClassName = isProxy ? AutoProxyRegistrar.class - .getName() : GlobalMethodSecurityAspectJAutoProxyRegistrar.class - .getName(); + String autoProxyClassName = isProxy ? AutoProxyRegistrar.class.getName() + : GlobalMethodSecurityAspectJAutoProxyRegistrar.class.getName(); boolean jsr250Enabled = attributes.getBoolean("jsr250Enabled"); @@ -78,4 +74,5 @@ final class GlobalMethodSecuritySelector implements ImportSelector { return classNames.toArray(new String[0]); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MetadataSourceConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MetadataSourceConfiguration.java index 5c98bf48fe..b2b534d0aa 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MetadataSourceConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MetadataSourceConfiguration.java @@ -30,4 +30,5 @@ class Jsr250MetadataSourceConfiguration { public Jsr250MethodSecurityMetadataSource jsr250MethodSecurityMetadataSource() { return new Jsr250MethodSecurityMetadataSource(); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityMetadataSourceAdvisorRegistrar.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityMetadataSourceAdvisorRegistrar.java index 8ef8f1e4af..a000487b95 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityMetadataSourceAdvisorRegistrar.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityMetadataSourceAdvisorRegistrar.java @@ -24,24 +24,22 @@ import org.springframework.security.access.intercept.aopalliance.MethodSecurityM import org.springframework.util.MultiValueMap; /** - * Creates Spring Security's MethodSecurityMetadataSourceAdvisor only when - * using proxy based method security (i.e. do not do it when using ASPECTJ). - * The conditional logic is controlled through {@link GlobalMethodSecuritySelector}. + * Creates Spring Security's MethodSecurityMetadataSourceAdvisor only when using proxy + * based method security (i.e. do not do it when using ASPECTJ). The conditional logic is + * controlled through {@link GlobalMethodSecuritySelector}. * * @author Rob Winch * @since 4.0.2 * @see GlobalMethodSecuritySelector */ -class MethodSecurityMetadataSourceAdvisorRegistrar implements - ImportBeanDefinitionRegistrar { +class MethodSecurityMetadataSourceAdvisorRegistrar implements ImportBeanDefinitionRegistrar { /** * Register, escalate, and configure the AspectJ auto proxy creator based on the value * of the @{@link EnableGlobalMethodSecurity#proxyTargetClass()} attribute on the * importing {@code @Configuration} class. */ - public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, - BeanDefinitionRegistry registry) { + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { BeanDefinitionBuilder advisor = BeanDefinitionBuilder .rootBeanDefinition(MethodSecurityMetadataSourceAdvisor.class); @@ -50,13 +48,14 @@ class MethodSecurityMetadataSourceAdvisorRegistrar implements advisor.addConstructorArgReference("methodSecurityMetadataSource"); advisor.addConstructorArgValue("methodSecurityMetadataSource"); - MultiValueMap attributes = importingClassMetadata.getAllAnnotationAttributes(EnableGlobalMethodSecurity.class.getName()); + MultiValueMap attributes = importingClassMetadata + .getAllAnnotationAttributes(EnableGlobalMethodSecurity.class.getName()); Integer order = (Integer) attributes.getFirst("order"); if (order != null) { advisor.addPropertyValue("order", order); } - registry.registerBeanDefinition("metaDataSourceAdvisor", - advisor.getBeanDefinition()); + registry.registerBeanDefinition("metaDataSourceAdvisor", advisor.getBeanDefinition()); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfiguration.java index b1ba9ae5d8..ab77dab8af 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfiguration.java @@ -40,6 +40,7 @@ import java.util.Arrays; */ @Configuration(proxyBeanMethods = false) class ReactiveMethodSecurityConfiguration implements ImportAware { + private int advisorOrder; private GrantedAuthorityDefaults grantedAuthorityDefaults; @@ -48,26 +49,27 @@ class ReactiveMethodSecurityConfiguration implements ImportAware { @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public MethodSecurityMetadataSourceAdvisor methodSecurityInterceptor(AbstractMethodSecurityMetadataSource source) { MethodSecurityMetadataSourceAdvisor advisor = new MethodSecurityMetadataSourceAdvisor( - "securityMethodInterceptor", source, "methodMetadataSource"); + "securityMethodInterceptor", source, "methodMetadataSource"); advisor.setOrder(advisorOrder); return advisor; } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) - public DelegatingMethodSecurityMetadataSource methodMetadataSource(MethodSecurityExpressionHandler methodSecurityExpressionHandler) { + public DelegatingMethodSecurityMetadataSource methodMetadataSource( + MethodSecurityExpressionHandler methodSecurityExpressionHandler) { ExpressionBasedAnnotationAttributeFactory attributeFactory = new ExpressionBasedAnnotationAttributeFactory( methodSecurityExpressionHandler); PrePostAnnotationSecurityMetadataSource prePostSource = new PrePostAnnotationSecurityMetadataSource( - attributeFactory); + attributeFactory); return new DelegatingMethodSecurityMetadataSource(Arrays.asList(prePostSource)); } @Bean - public PrePostAdviceReactiveMethodInterceptor securityMethodInterceptor(AbstractMethodSecurityMetadataSource source, MethodSecurityExpressionHandler handler) { + public PrePostAdviceReactiveMethodInterceptor securityMethodInterceptor(AbstractMethodSecurityMetadataSource source, + MethodSecurityExpressionHandler handler) { - ExpressionBasedPostInvocationAdvice postAdvice = new ExpressionBasedPostInvocationAdvice( - handler); + ExpressionBasedPostInvocationAdvice postAdvice = new ExpressionBasedPostInvocationAdvice(handler); ExpressionBasedPreInvocationAdvice preAdvice = new ExpressionBasedPreInvocationAdvice(); preAdvice.setExpressionHandler(handler); @@ -86,7 +88,8 @@ class ReactiveMethodSecurityConfiguration implements ImportAware { @Override public void setImportMetadata(AnnotationMetadata importMetadata) { - this.advisorOrder = (int) importMetadata.getAnnotationAttributes(EnableReactiveMethodSecurity.class.getName()).get("order"); + this.advisorOrder = (int) importMetadata.getAnnotationAttributes(EnableReactiveMethodSecurity.class.getName()) + .get("order"); } @Autowired(required = false) diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecuritySelector.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecuritySelector.java index 612432215e..43b7fd85a8 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecuritySelector.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecuritySelector.java @@ -27,22 +27,23 @@ import java.util.List; * @author Rob Winch * @since 5.0 */ -class ReactiveMethodSecuritySelector extends - AdviceModeImportSelector { +class ReactiveMethodSecuritySelector extends AdviceModeImportSelector { @Override protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { - case PROXY: - return getProxyImports(); - default: - throw new IllegalStateException("AdviceMode " + adviceMode + " is not supported"); + case PROXY: + return getProxyImports(); + default: + throw new IllegalStateException("AdviceMode " + adviceMode + " is not supported"); } } /** - * Return the imports to use if the {@link AdviceMode} is set to {@link AdviceMode#PROXY}. - *

    Take care of adding the necessary JSR-107 import if it is available. + * Return the imports to use if the {@link AdviceMode} is set to + * {@link AdviceMode#PROXY}. + *

    + * Take care of adding the necessary JSR-107 import if it is available. */ private String[] getProxyImports() { List result = new ArrayList<>(); @@ -50,4 +51,5 @@ class ReactiveMethodSecuritySelector extends result.add(ReactiveMethodSecurityConfiguration.class.getName()); return result.toArray(new String[0]); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/rsocket/EnableRSocketSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/rsocket/EnableRSocketSecurity.java index 440186090f..a44636e121 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/rsocket/EnableRSocketSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/rsocket/EnableRSocketSecurity.java @@ -36,4 +36,6 @@ import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Import({ RSocketSecurityConfiguration.class, SecuritySocketAcceptorInterceptorConfiguration.class }) -public @interface EnableRSocketSecurity { } +public @interface EnableRSocketSecurity { + +} diff --git a/config/src/main/java/org/springframework/security/config/annotation/rsocket/PayloadInterceptorOrder.java b/config/src/main/java/org/springframework/security/config/annotation/rsocket/PayloadInterceptorOrder.java index eba69bd9c5..f21d5b71eb 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/rsocket/PayloadInterceptorOrder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/rsocket/PayloadInterceptorOrder.java @@ -21,14 +21,15 @@ import org.springframework.security.config.Customizer; import org.springframework.security.rsocket.api.PayloadInterceptor; /** - * The standard order for {@link PayloadInterceptor} to be - * sorted. The actual values might change, so users should use the {@link #getOrder()} method to - * calculate the position dynamically rather than copy values. + * The standard order for {@link PayloadInterceptor} to be sorted. The actual values might + * change, so users should use the {@link #getOrder()} method to calculate the position + * dynamically rather than copy values. * * @author Rob Winch * @since 5.2 */ public enum PayloadInterceptorOrder implements Ordered { + /** * Where basic authentication is placed. * @see RSocketSecurity#basicAuthentication(Customizer) @@ -65,4 +66,5 @@ public enum PayloadInterceptorOrder implements Ordered { public int getOrder() { return this.order; } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurity.java index d36acdbc44..1428f0015a 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurity.java @@ -99,6 +99,7 @@ import java.util.List; * } * } * + * * @author Rob Winch * @author Jesús Ascama Arias * @author Luis Felipe Vega @@ -123,12 +124,12 @@ public class RSocketSecurity { private ReactiveAuthenticationManager authenticationManager; /** - * Adds a {@link PayloadInterceptor} to be used. This is typically only used - * when using the DSL does not meet a users needs. In order to ensure the - * {@link PayloadInterceptor} is done in the proper order the {@link PayloadInterceptor} should - * either implement {@link org.springframework.core.Ordered} or be annotated with + * Adds a {@link PayloadInterceptor} to be used. This is typically only used when + * using the DSL does not meet a users needs. In order to ensure the + * {@link PayloadInterceptor} is done in the proper order the + * {@link PayloadInterceptor} should either implement + * {@link org.springframework.core.Ordered} or be annotated with * {@link org.springframework.core.annotation.Order}. - * * @param interceptor * @return the builder for additional customizations * @see PayloadInterceptorOrder @@ -144,8 +145,9 @@ public class RSocketSecurity { } /** - * Adds support for validating a username and password using - * Simple Authentication + * Adds support for validating a username and password using Simple + * Authentication * @param simple a customizer * @return RSocketSecurity for additional configuration * @since 5.3 @@ -162,6 +164,7 @@ public class RSocketSecurity { * @since 5.3 */ public class SimpleAuthenticationSpec { + private ReactiveAuthenticationManager authenticationManager; public SimpleAuthenticationSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { @@ -184,12 +187,13 @@ public class RSocketSecurity { return result; } - private SimpleAuthenticationSpec() {} + private SimpleAuthenticationSpec() { + } + } /** * Adds authentication with BasicAuthenticationPayloadExchangeConverter. - * * @param basic * @return * @deprecated Use {@link #simpleAuthentication(Customizer)} @@ -204,6 +208,7 @@ public class RSocketSecurity { } public class BasicAuthenticationSpec { + private ReactiveAuthenticationManager authenticationManager; public BasicAuthenticationSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { @@ -225,7 +230,9 @@ public class RSocketSecurity { return result; } - private BasicAuthenticationSpec() {} + private BasicAuthenticationSpec() { + } + } public RSocketSecurity jwt(Customizer jwt) { @@ -237,6 +244,7 @@ public class RSocketSecurity { } public class JwtSpec { + private ReactiveAuthenticationManager authenticationManager; public JwtSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { @@ -269,7 +277,9 @@ public class RSocketSecurity { return Arrays.asList(standard, legacy); } - private JwtSpec() {} + private JwtSpec() { + } + } public RSocketSecurity authorizePayload(Customizer authorize) { @@ -281,8 +291,7 @@ public class RSocketSecurity { } public PayloadSocketAcceptorInterceptor build() { - PayloadSocketAcceptorInterceptor interceptor = new PayloadSocketAcceptorInterceptor( - payloadInterceptors()); + PayloadSocketAcceptorInterceptor interceptor = new PayloadSocketAcceptorInterceptor(payloadInterceptors()); RSocketMessageHandler handler = getBean(RSocketMessageHandler.class); interceptor.setDefaultDataMimeType(handler.getDefaultDataMimeType()); interceptor.setDefaultMetadataMimeType(handler.getDefaultMetadataMimeType()); @@ -318,16 +327,17 @@ public class RSocketSecurity { public class AuthorizePayloadsSpec { - private PayloadExchangeMatcherReactiveAuthorizationManager.Builder authzBuilder = - PayloadExchangeMatcherReactiveAuthorizationManager.builder(); + private PayloadExchangeMatcherReactiveAuthorizationManager.Builder authzBuilder = PayloadExchangeMatcherReactiveAuthorizationManager + .builder(); public Access setup() { return matcher(PayloadExchangeMatchers.setup()); } /** - * Matches if {@link org.springframework.security.rsocket.api.PayloadExchangeType#isRequest()} is true, else - * not a match + * Matches if + * {@link org.springframework.security.rsocket.api.PayloadExchangeType#isRequest()} + * is true, else not a match * @return the Access to set up the authorization rule. */ public Access anyRequest() { @@ -350,10 +360,8 @@ public class RSocketSecurity { public Access route(String pattern) { RSocketMessageHandler handler = getBean(RSocketMessageHandler.class); - PayloadExchangeMatcher matcher = new RoutePayloadExchangeMatcher( - handler.getMetadataExtractor(), - handler.getRouteMatcher(), - pattern); + PayloadExchangeMatcher matcher = new RoutePayloadExchangeMatcher(handler.getMetadataExtractor(), + handler.getRouteMatcher(), pattern); return matcher(matcher); } @@ -386,8 +394,7 @@ public class RSocketSecurity { } public AuthorizePayloadsSpec permitAll() { - return access((a, ctx) -> Mono - .just(new AuthorizationDecision(true))); + return access((a, ctx) -> Mono.just(new AuthorizationDecision(true))); } public AuthorizePayloadsSpec hasAnyAuthority(String... authorities) { @@ -396,15 +403,17 @@ public class RSocketSecurity { public AuthorizePayloadsSpec access( ReactiveAuthorizationManager authorization) { - AuthorizePayloadsSpec.this.authzBuilder.add(new PayloadExchangeMatcherEntry<>(this.matcher, authorization)); + AuthorizePayloadsSpec.this.authzBuilder + .add(new PayloadExchangeMatcherEntry<>(this.matcher, authorization)); return AuthorizePayloadsSpec.this; } public AuthorizePayloadsSpec denyAll() { - return access((a, ctx) -> Mono - .just(new AuthorizationDecision(false))); + return access((a, ctx) -> Mono.just(new AuthorizationDecision(false))); } + } + } private T getBean(Class beanClass) { @@ -422,15 +431,15 @@ public class RSocketSecurity { if (this.context == null) { return null; } - String[] names = this.context.getBeanNamesForType(type); + String[] names = this.context.getBeanNamesForType(type); if (names.length == 1) { return (T) this.context.getBean(names[0]); } return null; } - protected void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { + protected void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = applicationContext; } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurityConfiguration.java index fdf9bd31bc..9e6cfcb73d 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurityConfiguration.java @@ -34,6 +34,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; class RSocketSecurityConfiguration { private static final String BEAN_NAME_PREFIX = "org.springframework.security.config.annotation.rsocket.RSocketSecurityConfiguration."; + private static final String RSOCKET_SECURITY_BEAN_NAME = BEAN_NAME_PREFIX + "rsocketSecurity"; private ReactiveAuthenticationManager authenticationManager; @@ -43,8 +44,7 @@ class RSocketSecurityConfiguration { private PasswordEncoder passwordEncoder; @Autowired(required = false) - void setAuthenticationManager( - ReactiveAuthenticationManager authenticationManager) { + void setAuthenticationManager(ReactiveAuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } @@ -61,8 +61,7 @@ class RSocketSecurityConfiguration { @Bean(name = RSOCKET_SECURITY_BEAN_NAME) @Scope("prototype") public RSocketSecurity rsocketSecurity(ApplicationContext context) { - RSocketSecurity security = new RSocketSecurity() - .authenticationManager(authenticationManager()); + RSocketSecurity security = new RSocketSecurity().authenticationManager(authenticationManager()); security.setApplicationContext(context); return security; } @@ -72,8 +71,8 @@ class RSocketSecurityConfiguration { return this.authenticationManager; } if (this.reactiveUserDetailsService != null) { - UserDetailsRepositoryReactiveAuthenticationManager manager = - new UserDetailsRepositoryReactiveAuthenticationManager(this.reactiveUserDetailsService); + UserDetailsRepositoryReactiveAuthenticationManager manager = new UserDetailsRepositoryReactiveAuthenticationManager( + this.reactiveUserDetailsService); if (this.passwordEncoder != null) { manager.setPasswordEncoder(this.passwordEncoder); } @@ -81,4 +80,5 @@ class RSocketSecurityConfiguration { } return null; } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/rsocket/SecuritySocketAcceptorInterceptorConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/rsocket/SecuritySocketAcceptorInterceptorConfiguration.java index cdd007d61e..57804f171f 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/rsocket/SecuritySocketAcceptorInterceptorConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/rsocket/SecuritySocketAcceptorInterceptorConfiguration.java @@ -31,29 +31,25 @@ import org.springframework.security.rsocket.util.matcher.PayloadExchangeMatcher. */ @Configuration(proxyBeanMethods = false) class SecuritySocketAcceptorInterceptorConfiguration { + @Bean SecuritySocketAcceptorInterceptor securitySocketAcceptorInterceptor( - ObjectProvider rsocketInterceptor, ObjectProvider rsocketSecurity) { + ObjectProvider rsocketInterceptor, + ObjectProvider rsocketSecurity) { PayloadSocketAcceptorInterceptor delegate = rsocketInterceptor .getIfAvailable(() -> defaultInterceptor(rsocketSecurity)); return new SecuritySocketAcceptorInterceptor(delegate); } - private PayloadSocketAcceptorInterceptor defaultInterceptor( - ObjectProvider rsocketSecurity) { + private PayloadSocketAcceptorInterceptor defaultInterceptor(ObjectProvider rsocketSecurity) { RSocketSecurity rsocket = rsocketSecurity.getIfAvailable(); if (rsocket == null) { throw new NoSuchBeanDefinitionException("No RSocketSecurity defined"); } - rsocket - .basicAuthentication(Customizer.withDefaults()) - .simpleAuthentication(Customizer.withDefaults()) - .authorizePayload(authz -> - authz - .setup().authenticated() - .anyRequest().authenticated() - .matcher(e -> MatchResult.match()).permitAll() - ); + rsocket.basicAuthentication(Customizer.withDefaults()).simpleAuthentication(Customizer.withDefaults()) + .authorizePayload(authz -> authz.setup().authenticated().anyRequest().authenticated() + .matcher(e -> MatchResult.match()).permitAll()); return rsocket.build(); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java b/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java index 268c0e4a54..01956cfe07 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java @@ -36,14 +36,13 @@ import java.util.List; * A base class for registering {@link RequestMatcher}'s. For example, it might allow for * specifying which {@link RequestMatcher} require a certain level of authorization. * - * * @param The object that is returned or Chained after creating the RequestMatcher - * * @author Rob Winch * @author Ankur Pathak * @since 3.2 */ public abstract class AbstractRequestMatcherRegistry { + private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"; private static final RequestMatcher ANY_REQUEST = AnyRequestMatcher.INSTANCE; @@ -58,7 +57,6 @@ public abstract class AbstractRequestMatcherRegistry { /** * Gets the {@link ApplicationContext} - * * @return the {@link ApplicationContext} */ protected final ApplicationContext getApplicationContext() { @@ -67,7 +65,6 @@ public abstract class AbstractRequestMatcherRegistry { /** * Maps any request. - * * @return the object that is chained after creating the {@link RequestMatcher} */ public C anyRequest() { @@ -81,10 +78,7 @@ public abstract class AbstractRequestMatcherRegistry { * Maps a {@link List} of * {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} * instances. - * - * @param method the {@link HttpMethod} to use for any - * {@link HttpMethod}. - * + * @param method the {@link HttpMethod} to use for any {@link HttpMethod}. * @return the object that is chained after creating the {@link RequestMatcher} */ public C antMatchers(HttpMethod method) { @@ -95,12 +89,11 @@ public abstract class AbstractRequestMatcherRegistry { * Maps a {@link List} of * {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} * instances. - * * @param method the {@link HttpMethod} to use or {@code null} for any * {@link HttpMethod}. - * @param antPatterns the ant patterns to create. If {@code null} or empty, then matches on nothing. + * @param antPatterns the ant patterns to create. If {@code null} or empty, then + * matches on nothing. * {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} from - * * @return the object that is chained after creating the {@link RequestMatcher} */ public C antMatchers(HttpMethod method, String... antPatterns) { @@ -112,10 +105,8 @@ public abstract class AbstractRequestMatcherRegistry { * Maps a {@link List} of * {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} * instances that do not care which {@link HttpMethod} is used. - * * @param antPatterns the ant patterns to create * {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} from - * * @return the object that is chained after creating the {@link RequestMatcher} */ public C antMatchers(String... antPatterns) { @@ -134,7 +125,6 @@ public abstract class AbstractRequestMatcherRegistry { * If the current request will not be processed by Spring MVC, a reasonable default * using the pattern as a ant pattern will be used. *

    - * * @param mvcPatterns the patterns to match on. The rules for matching are defined by * Spring MVC * @return the object that is chained after creating the {@link RequestMatcher}. @@ -152,7 +142,6 @@ public abstract class AbstractRequestMatcherRegistry { * If the current request will not be processed by Spring MVC, a reasonable default * using the pattern as a ant pattern will be used. *

    - * * @param method the HTTP method to match on * @param mvcPatterns the patterns to match on. The rules for matching are defined by * Spring MVC @@ -162,23 +151,21 @@ public abstract class AbstractRequestMatcherRegistry { /** * Creates {@link MvcRequestMatcher} instances for the method and patterns passed in - * * @param method the HTTP method to use or null if any should be used * @param mvcPatterns the Spring MVC patterns to match on * @return a List of {@link MvcRequestMatcher} instances */ - protected final List createMvcMatchers(HttpMethod method, - String... mvcPatterns) { + protected final List createMvcMatchers(HttpMethod method, String... mvcPatterns) { Assert.state(!this.anyRequestConfigured, "Can't configure mvcMatchers after anyRequest"); ObjectPostProcessor opp = this.context.getBean(ObjectPostProcessor.class); if (!this.context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) { - throw new NoSuchBeanDefinitionException("A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME +" of type " + HandlerMappingIntrospector.class.getName() - + " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext."); + throw new NoSuchBeanDefinitionException("A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + + " of type " + HandlerMappingIntrospector.class.getName() + + " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext."); } HandlerMappingIntrospector introspector = this.context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, - HandlerMappingIntrospector.class); - List matchers = new ArrayList<>( - mvcPatterns.length); + HandlerMappingIntrospector.class); + List matchers = new ArrayList<>(mvcPatterns.length); for (String mvcPattern : mvcPatterns) { MvcRequestMatcher matcher = new MvcRequestMatcher(introspector, mvcPattern); opp.postProcess(matcher); @@ -195,12 +182,10 @@ public abstract class AbstractRequestMatcherRegistry { * Maps a {@link List} of * {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} * instances. - * * @param method the {@link HttpMethod} to use or {@code null} for any * {@link HttpMethod}. * @param regexPatterns the regular expressions to create * {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} from - * * @return the object that is chained after creating the {@link RequestMatcher} */ public C regexMatchers(HttpMethod method, String... regexPatterns) { @@ -212,10 +197,8 @@ public abstract class AbstractRequestMatcherRegistry { * Create a {@link List} of * {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} instances * that do not specify an {@link HttpMethod}. - * * @param regexPatterns the regular expressions to create * {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} from - * * @return the object that is chained after creating the {@link RequestMatcher} */ public C regexMatchers(String... regexPatterns) { @@ -226,9 +209,7 @@ public abstract class AbstractRequestMatcherRegistry { /** * Associates a list of {@link RequestMatcher} instances with the * {@link AbstractConfigAttributeRequestMatcherRegistry} - * * @param requestMatchers the {@link RequestMatcher} instances - * * @return the object that is chained after creating the {@link RequestMatcher} */ public C requestMatchers(RequestMatcher... requestMatchers) { @@ -239,7 +220,6 @@ public abstract class AbstractRequestMatcherRegistry { /** * Subclasses should implement this method for returning the object that is chained to * the creation of the {@link RequestMatcher} instances. - * * @param requestMatchers the {@link RequestMatcher} instances that were created * @return the chained Object for the subclass which allows association of something * else to the {@link RequestMatcher} @@ -256,16 +236,13 @@ public abstract class AbstractRequestMatcherRegistry { /** * Create a {@link List} of {@link AntPathRequestMatcher} instances. - * * @param httpMethod the {@link HttpMethod} to use or {@code null} for any * {@link HttpMethod}. * @param antPatterns the ant patterns to create {@link AntPathRequestMatcher} * from - * * @return a {@link List} of {@link AntPathRequestMatcher} instances */ - public static List antMatchers(HttpMethod httpMethod, - String... antPatterns) { + public static List antMatchers(HttpMethod httpMethod, String... antPatterns) { String method = httpMethod == null ? null : httpMethod.toString(); List matchers = new ArrayList<>(); for (String pattern : antPatterns) { @@ -277,10 +254,8 @@ public abstract class AbstractRequestMatcherRegistry { /** * Create a {@link List} of {@link AntPathRequestMatcher} instances that do not * specify an {@link HttpMethod}. - * * @param antPatterns the ant patterns to create {@link AntPathRequestMatcher} * from - * * @return a {@link List} of {@link AntPathRequestMatcher} instances */ public static List antMatchers(String... antPatterns) { @@ -289,16 +264,13 @@ public abstract class AbstractRequestMatcherRegistry { /** * Create a {@link List} of {@link RegexRequestMatcher} instances. - * * @param httpMethod the {@link HttpMethod} to use or {@code null} for any * {@link HttpMethod}. * @param regexPatterns the regular expressions to create * {@link RegexRequestMatcher} from - * * @return a {@link List} of {@link RegexRequestMatcher} instances */ - public static List regexMatchers(HttpMethod httpMethod, - String... regexPatterns) { + public static List regexMatchers(HttpMethod httpMethod, String... regexPatterns) { String method = httpMethod == null ? null : httpMethod.toString(); List matchers = new ArrayList<>(); for (String pattern : regexPatterns) { @@ -310,10 +282,8 @@ public abstract class AbstractRequestMatcherRegistry { /** * Create a {@link List} of {@link RegexRequestMatcher} instances that do not * specify an {@link HttpMethod}. - * * @param regexPatterns the regular expressions to create * {@link RegexRequestMatcher} from - * * @return a {@link List} of {@link RegexRequestMatcher} instances */ public static List regexMatchers(String... regexPatterns) { @@ -322,6 +292,7 @@ public abstract class AbstractRequestMatcherRegistry { private RequestMatchers() { } + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/HttpSecurityBuilder.java b/config/src/main/java/org/springframework/security/config/annotation/web/HttpSecurityBuilder.java index 510f40cba6..61d69ad820 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/HttpSecurityBuilder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/HttpSecurityBuilder.java @@ -44,36 +44,29 @@ import org.springframework.security.web.session.ConcurrentSessionFilter; import org.springframework.security.web.session.SessionManagementFilter; /** - * * @author Rob Winch - * * @param */ -public interface HttpSecurityBuilder> extends - SecurityBuilder { +public interface HttpSecurityBuilder> + extends SecurityBuilder { /** * Gets the {@link SecurityConfigurer} by its class name or null if not * found. Note that object hierarchies are not considered. - * * @param clazz the Class of the {@link SecurityConfigurer} to attempt to get. */ - > C getConfigurer( - Class clazz); + > C getConfigurer(Class clazz); /** * Removes the {@link SecurityConfigurer} by its class name or null if * not found. Note that object hierarchies are not considered. - * * @param clazz the Class of the {@link SecurityConfigurer} to attempt to remove. * @return the {@link SecurityConfigurer} that was removed or null if not found */ - > C removeConfigurer( - Class clazz); + > C removeConfigurer(Class clazz); /** * Sets an object that is shared by multiple {@link SecurityConfigurer}. - * * @param sharedType the Class to key the shared object by. * @param object the Object to store */ @@ -81,7 +74,6 @@ public interface HttpSecurityBuilder> extends /** * Gets a shared Object. Note that object heirarchies are not considered. - * * @param sharedType the type of the shared Object * @return the shared Object or null if it is not found */ @@ -89,7 +81,6 @@ public interface HttpSecurityBuilder> extends /** * Allows adding an additional {@link AuthenticationProvider} to be used - * * @param authenticationProvider the {@link AuthenticationProvider} to be added * @return the {@link HttpSecurity} for further customizations */ @@ -97,7 +88,6 @@ public interface HttpSecurityBuilder> extends /** * Allows adding an additional {@link UserDetailsService} to be used - * * @param userDetailsService the {@link UserDetailsService} to be added * @return the {@link HttpSecurity} for further customizations */ @@ -108,7 +98,6 @@ public interface HttpSecurityBuilder> extends * known {@link Filter} instances are either a {@link Filter} listed in * {@link #addFilter(Filter)} or a {@link Filter} that has already been added using * {@link #addFilterAfter(Filter, Class)} or {@link #addFilterBefore(Filter, Class)}. - * * @param filter the {@link Filter} to register after the type {@code afterFilter} * @param afterFilter the Class of the known {@link Filter}. * @return the {@link HttpSecurity} for further customizations @@ -120,7 +109,6 @@ public interface HttpSecurityBuilder> extends * known {@link Filter} instances are either a {@link Filter} listed in * {@link #addFilter(Filter)} or a {@link Filter} that has already been added using * {@link #addFilterAfter(Filter, Class)} or {@link #addFilterBefore(Filter, Class)}. - * * @param filter the {@link Filter} to register before the type {@code beforeFilter} * @param beforeFilter the Class of the known {@link Filter}. * @return the {@link HttpSecurity} for further customizations @@ -140,7 +128,8 @@ public interface HttpSecurityBuilder> extends *
  • {@link LogoutFilter}
  • *
  • {@link X509AuthenticationFilter}
  • *
  • {@link AbstractPreAuthenticatedProcessingFilter}
  • - *
  • CasAuthenticationFilter
  • + *
  • CasAuthenticationFilter
  • *
  • {@link UsernamePasswordAuthenticationFilter}
  • *
  • {@link OpenIDAuthenticationFilter}
  • *
  • {@link org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter}
  • @@ -159,9 +148,9 @@ public interface HttpSecurityBuilder> extends *
  • {@link FilterSecurityInterceptor}
  • *
  • {@link SwitchUserFilter}
  • * - * * @param filter the {@link Filter} to add * @return the {@link HttpSecurity} for further customizations */ H addFilter(Filter filter); + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/WebSecurityConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/WebSecurityConfigurer.java index e97f2cf4da..68da8c63e9 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/WebSecurityConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/WebSecurityConfigurer.java @@ -28,17 +28,15 @@ import org.springframework.security.web.SecurityFilterChain; /** * Allows customization to the {@link WebSecurity}. In most instances users will use * {@link EnableWebSecurity} and either create a {@link Configuration} that extends - * {@link WebSecurityConfigurerAdapter} or expose a {@link SecurityFilterChain} bean. - * Both will automatically be applied to the {@link WebSecurity} by the + * {@link WebSecurityConfigurerAdapter} or expose a {@link SecurityFilterChain} bean. Both + * will automatically be applied to the {@link WebSecurity} by the * {@link EnableWebSecurity} annotation. * * @see WebSecurityConfigurerAdapter * @see SecurityFilterChain - * * @author Rob Winch * @since 3.2 */ -public interface WebSecurityConfigurer> extends - SecurityConfigurer { +public interface WebSecurityConfigurer> extends SecurityConfigurer { } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterComparator.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterComparator.java index 4b96267a59..f62ce4bafc 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterComparator.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterComparator.java @@ -56,8 +56,11 @@ import org.springframework.web.filter.CorsFilter; @SuppressWarnings("serial") final class FilterComparator implements Comparator, Serializable { + private static final int INITIAL_ORDER = 100; + private static final int ORDER_STEP = 100; + private final Map filterToOrder = new HashMap<>(); FilterComparator() { @@ -70,40 +73,35 @@ final class FilterComparator implements Comparator, Serializable { put(CorsFilter.class, order.next()); put(CsrfFilter.class, order.next()); put(LogoutFilter.class, order.next()); - filterToOrder.put( - "org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter", + filterToOrder.put("org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter", order.next()); filterToOrder.put( "org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationRequestFilter", order.next()); put(X509AuthenticationFilter.class, order.next()); put(AbstractPreAuthenticatedProcessingFilter.class, order.next()); - filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter", - order.next()); - filterToOrder.put( - "org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter", + filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter", order.next()); + filterToOrder.put("org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter", order.next()); filterToOrder.put( "org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter", order.next()); put(UsernamePasswordAuthenticationFilter.class, order.next()); order.next(); // gh-8105 - filterToOrder.put( - "org.springframework.security.openid.OpenIDAuthenticationFilter", order.next()); + filterToOrder.put("org.springframework.security.openid.OpenIDAuthenticationFilter", order.next()); put(DefaultLoginPageGeneratingFilter.class, order.next()); put(DefaultLogoutPageGeneratingFilter.class, order.next()); put(ConcurrentSessionFilter.class, order.next()); put(DigestAuthenticationFilter.class, order.next()); - filterToOrder.put( - "org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter", order.next()); + filterToOrder.put("org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter", + order.next()); put(BasicAuthenticationFilter.class, order.next()); put(RequestCacheAwareFilter.class, order.next()); put(SecurityContextHolderAwareRequestFilter.class, order.next()); put(JaasApiIntegrationFilter.class, order.next()); put(RememberMeAuthenticationFilter.class, order.next()); put(AnonymousAuthenticationFilter.class, order.next()); - filterToOrder.put( - "org.springframework.security.oauth2.client.web.OAuth2AuthorizationCodeGrantFilter", + filterToOrder.put("org.springframework.security.oauth2.client.web.OAuth2AuthorizationCodeGrantFilter", order.next()); put(SessionManagementFilter.class, order.next()); put(ExceptionTranslationFilter.class, order.next()); @@ -119,7 +117,6 @@ final class FilterComparator implements Comparator, Serializable { /** * Determines if a particular {@link Filter} is registered to be sorted - * * @param filter * @return */ @@ -134,12 +131,10 @@ final class FilterComparator implements Comparator, Serializable { * @param afterFilter the {@link Filter} that is already registered and that * {@code filter} should be placed after. */ - public void registerAfter(Class filter, - Class afterFilter) { + public void registerAfter(Class filter, Class afterFilter) { Integer position = getOrder(afterFilter); if (position == null) { - throw new IllegalArgumentException( - "Cannot register after unregistered Filter " + afterFilter); + throw new IllegalArgumentException("Cannot register after unregistered Filter " + afterFilter); } put(filter, position + 1); @@ -151,12 +146,10 @@ final class FilterComparator implements Comparator, Serializable { * @param atFilter the {@link Filter} that is already registered and that * {@code filter} should be placed at. */ - public void registerAt(Class filter, - Class atFilter) { + public void registerAt(Class filter, Class atFilter) { Integer position = getOrder(atFilter); if (position == null) { - throw new IllegalArgumentException( - "Cannot register after unregistered Filter " + atFilter); + throw new IllegalArgumentException("Cannot register after unregistered Filter " + atFilter); } put(filter, position); @@ -169,12 +162,10 @@ final class FilterComparator implements Comparator, Serializable { * @param beforeFilter the {@link Filter} that is already registered and that * {@code filter} should be placed before. */ - public void registerBefore(Class filter, - Class beforeFilter) { + public void registerBefore(Class filter, Class beforeFilter) { Integer position = getOrder(beforeFilter); if (position == null) { - throw new IllegalArgumentException( - "Cannot register after unregistered Filter " + beforeFilter); + throw new IllegalArgumentException("Cannot register after unregistered Filter " + beforeFilter); } put(filter, position - 1); @@ -188,7 +179,6 @@ final class FilterComparator implements Comparator, Serializable { /** * Gets the order of a particular {@link Filter} class taking into consideration * superclasses. - * * @param clazz the {@link Filter} class to determine the sort order * @return the sort order or null if not defined */ @@ -206,6 +196,7 @@ final class FilterComparator implements Comparator, Serializable { private static class Step { private int value; + private final int stepSize; Step(int initialValue, int stepSize) { diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java index b056bdc898..e082f1fb57 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java @@ -120,13 +120,15 @@ import javax.servlet.http.HttpServletRequest; * @since 3.2 * @see EnableWebSecurity */ -public final class HttpSecurity extends - AbstractConfiguredSecurityBuilder - implements SecurityBuilder, - HttpSecurityBuilder { +public final class HttpSecurity extends AbstractConfiguredSecurityBuilder + implements SecurityBuilder, HttpSecurityBuilder { + private final RequestMatcherConfigurer requestMatcherConfigurer; + private List filters = new ArrayList<>(); + private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE; + private FilterComparator comparator = new FilterComparator(); /** @@ -139,17 +141,14 @@ public final class HttpSecurity extends */ @SuppressWarnings("unchecked") public HttpSecurity(ObjectPostProcessor objectPostProcessor, - AuthenticationManagerBuilder authenticationBuilder, - Map, Object> sharedObjects) { + AuthenticationManagerBuilder authenticationBuilder, Map, Object> sharedObjects) { super(objectPostProcessor); Assert.notNull(authenticationBuilder, "authenticationBuilder cannot be null"); setSharedObject(AuthenticationManagerBuilder.class, authenticationBuilder); - for (Map.Entry, Object> entry : sharedObjects - .entrySet()) { + for (Map.Entry, Object> entry : sharedObjects.entrySet()) { setSharedObject((Class) entry.getKey(), entry.getValue()); } - ApplicationContext context = (ApplicationContext) sharedObjects - .get(ApplicationContext.class); + ApplicationContext context = (ApplicationContext) sharedObjects.get(ApplicationContext.class); this.requestMatcherConfigurer = new RequestMatcherConfigurer(context); } @@ -231,11 +230,11 @@ public final class HttpSecurity extends * } * } * - * * @return the {@link OpenIDLoginConfigurer} for further customizations. * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @throws Exception * @see OpenIDLoginConfigurer */ @@ -354,24 +353,25 @@ public final class HttpSecurity extends * * * @see OpenIDLoginConfigurer - * - * @param openidLoginCustomizer the {@link Customizer} to provide more options for - * the {@link OpenIDLoginConfigurer} + * @param openidLoginCustomizer the {@link Customizer} to provide more options for the + * {@link OpenIDLoginConfigurer} * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @return the {@link HttpSecurity} for further customizations * @throws Exception */ - public HttpSecurity openidLogin(Customizer> openidLoginCustomizer) throws Exception { + public HttpSecurity openidLogin(Customizer> openidLoginCustomizer) + throws Exception { openidLoginCustomizer.customize(getOrApply(new OpenIDLoginConfigurer<>())); return HttpSecurity.this; } /** * Adds the Security headers to the response. This is activated by default when using - * {@link WebSecurityConfigurerAdapter}'s default constructor. Accepting the - * default provided by {@link WebSecurityConfigurerAdapter} or only invoking + * {@link WebSecurityConfigurerAdapter}'s default constructor. Accepting the default + * provided by {@link WebSecurityConfigurerAdapter} or only invoking * {@link #headers()} without invoking additional methods on it, is the equivalent of: * *
    @@ -415,9 +415,9 @@ public final class HttpSecurity extends
     	 * 
    * * You can enable only a few of the headers by first invoking - * {@link HeadersConfigurer#defaultsDisabled()} - * and then invoking the appropriate methods on the {@link #headers()} result. - * For example, the following will enable {@link HeadersConfigurer#cacheControl()} and + * {@link HeadersConfigurer#defaultsDisabled()} and then invoking the appropriate + * methods on the {@link #headers()} result. For example, the following will enable + * {@link HeadersConfigurer#cacheControl()} and * {@link HeadersConfigurer#frameOptions()} only. * *
    @@ -439,8 +439,8 @@ public final class HttpSecurity extends
     	 * }
     	 * 
    * - * You can also choose to keep the defaults but explicitly disable a subset of headers. - * For example, the following will enable all the default headers except + * You can also choose to keep the defaults but explicitly disable a subset of + * headers. For example, the following will enable all the default headers except * {@link HeadersConfigurer#frameOptions()}. * *
    @@ -459,7 +459,6 @@ public final class HttpSecurity extends
     	 *     }
     	 * }
     	 * 
    - * * @return the {@link HeadersConfigurer} for further customizations * @throws Exception * @see HeadersConfigurer @@ -474,8 +473,9 @@ public final class HttpSecurity extends * *

    Example Configurations

    * - * Accepting the default provided by {@link WebSecurityConfigurerAdapter} or only invoking - * {@link #headers()} without invoking additional methods on it, is the equivalent of: + * Accepting the default provided by {@link WebSecurityConfigurerAdapter} or only + * invoking {@link #headers()} without invoking additional methods on it, is the + * equivalent of: * *
     	 * @Configuration
    @@ -513,9 +513,9 @@ public final class HttpSecurity extends
     	 * 
    * * You can enable only a few of the headers by first invoking - * {@link HeadersConfigurer#defaultsDisabled()} - * and then invoking the appropriate methods on the {@link #headers()} result. - * For example, the following will enable {@link HeadersConfigurer#cacheControl()} and + * {@link HeadersConfigurer#defaultsDisabled()} and then invoking the appropriate + * methods on the {@link #headers()} result. For example, the following will enable + * {@link HeadersConfigurer#cacheControl()} and * {@link HeadersConfigurer#frameOptions()} only. * *
    @@ -536,8 +536,8 @@ public final class HttpSecurity extends
     	 * }
     	 * 
    * - * You can also choose to keep the defaults but explicitly disable a subset of headers. - * For example, the following will enable all the default headers except + * You can also choose to keep the defaults but explicitly disable a subset of + * headers. For example, the following will enable all the default headers except * {@link HeadersConfigurer#frameOptions()}. * *
    @@ -554,9 +554,8 @@ public final class HttpSecurity extends
     	 *  		);
     	 * }
     	 * 
    - * - * @param headersCustomizer the {@link Customizer} to provide more options for - * the {@link HeadersConfigurer} + * @param headersCustomizer the {@link Customizer} to provide more options for the + * {@link HeadersConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ @@ -570,7 +569,6 @@ public final class HttpSecurity extends * provided, that {@link CorsFilter} is used. Else if corsConfigurationSource is * defined, then that {@link CorsConfiguration} is used. Otherwise, if Spring MVC is * on the classpath a {@link HandlerMappingIntrospector} is used. - * * @return the {@link CorsConfigurer} for customizations * @throws Exception */ @@ -582,8 +580,8 @@ public final class HttpSecurity extends * Adds a {@link CorsFilter} to be used. If a bean by the name of corsFilter is * provided, that {@link CorsFilter} is used. Else if corsConfigurationSource is * defined, then that {@link CorsConfiguration} is used. Otherwise, if Spring MVC is - * on the classpath a {@link HandlerMappingIntrospector} is used. - * You can enable CORS using: + * on the classpath a {@link HandlerMappingIntrospector} is used. You can enable CORS + * using: * *
     	 * @Configuration
    @@ -597,9 +595,8 @@ public final class HttpSecurity extends
     	 *     }
     	 * }
     	 * 
    - * - * @param corsCustomizer the {@link Customizer} to provide more options for - * the {@link CorsConfigurer} + * @param corsCustomizer the {@link Customizer} to provide more options for the + * {@link CorsConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ @@ -652,7 +649,6 @@ public final class HttpSecurity extends * Alternatively, * {@link AbstractSecurityWebApplicationInitializer#enableHttpSessionEventPublisher()} * could return true. - * * @return the {@link SessionManagementConfigurer} for further customizations * @throws Exception */ @@ -713,13 +709,13 @@ public final class HttpSecurity extends * Alternatively, * {@link AbstractSecurityWebApplicationInitializer#enableHttpSessionEventPublisher()} * could return true. - * - * @param sessionManagementCustomizer the {@link Customizer} to provide more options for - * the {@link SessionManagementConfigurer} + * @param sessionManagementCustomizer the {@link Customizer} to provide more options + * for the {@link SessionManagementConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ - public HttpSecurity sessionManagement(Customizer> sessionManagementCustomizer) throws Exception { + public HttpSecurity sessionManagement( + Customizer> sessionManagementCustomizer) throws Exception { sessionManagementCustomizer.customize(getOrApply(new SessionManagementConfigurer<>())); return HttpSecurity.this; } @@ -758,7 +754,6 @@ public final class HttpSecurity extends * } * } * - * * @return the {@link PortMapperConfigurer} for further customizations * @throws Exception * @see #requiresChannel() @@ -804,19 +799,20 @@ public final class HttpSecurity extends * * * @see #requiresChannel() - * @param portMapperCustomizer the {@link Customizer} to provide more options for - * the {@link PortMapperConfigurer} + * @param portMapperCustomizer the {@link Customizer} to provide more options for the + * {@link PortMapperConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ - public HttpSecurity portMapper(Customizer> portMapperCustomizer) throws Exception { + public HttpSecurity portMapper(Customizer> portMapperCustomizer) + throws Exception { portMapperCustomizer.customize(getOrApply(new PortMapperConfigurer<>())); return HttpSecurity.this; } /** - * Configures container based pre authentication. In this case, authentication - * is managed by the Servlet Container. + * Configures container based pre authentication. In this case, authentication is + * managed by the Servlet Container. * *

    Example Configuration

    * @@ -878,7 +874,6 @@ public final class HttpSecurity extends * Last you will need to configure your container to contain the user with the correct * roles. This configuration is specific to the Servlet Container, so consult your * Servlet Container's documentation. - * * @return the {@link JeeConfigurer} for further customizations * @throws Exception */ @@ -887,8 +882,8 @@ public final class HttpSecurity extends } /** - * Configures container based pre authentication. In this case, authentication - * is managed by the Servlet Container. + * Configures container based pre authentication. In this case, authentication is + * managed by the Servlet Container. * *

    Example Configuration

    * @@ -956,9 +951,8 @@ public final class HttpSecurity extends * Last you will need to configure your container to contain the user with the correct * roles. This configuration is specific to the Servlet Container, so consult your * Servlet Container's documentation. - * - * @param jeeCustomizer the {@link Customizer} to provide more options for - * the {@link JeeConfigurer} + * @param jeeCustomizer the {@link Customizer} to provide more options for the + * {@link JeeConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ @@ -989,7 +983,6 @@ public final class HttpSecurity extends * } * } * - * * @return the {@link X509Configurer} for further customizations * @throws Exception */ @@ -1022,9 +1015,8 @@ public final class HttpSecurity extends * } * } * - * - * @param x509Customizer the {@link Customizer} to provide more options for - * the {@link X509Configurer} + * @param x509Customizer the {@link Customizer} to provide more options for the + * {@link X509Configurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ @@ -1062,7 +1054,6 @@ public final class HttpSecurity extends * } * } * - * * @return the {@link RememberMeConfigurer} for further customizations * @throws Exception */ @@ -1097,13 +1088,13 @@ public final class HttpSecurity extends * } * } * - * - * @param rememberMeCustomizer the {@link Customizer} to provide more options for - * the {@link RememberMeConfigurer} + * @param rememberMeCustomizer the {@link Customizer} to provide more options for the + * {@link RememberMeConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ - public HttpSecurity rememberMe(Customizer> rememberMeCustomizer) throws Exception { + public HttpSecurity rememberMe(Customizer> rememberMeCustomizer) + throws Exception { rememberMeCustomizer.customize(getOrApply(new RememberMeConfigurer<>())); return HttpSecurity.this; } @@ -1169,15 +1160,13 @@ public final class HttpSecurity extends * * * @see #requestMatcher(RequestMatcher) - * * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customizations * @throws Exception */ public ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry authorizeRequests() throws Exception { ApplicationContext context = getContext(); - return getOrApply(new ExpressionUrlAuthorizationConfigurer<>(context)) - .getRegistry(); + return getOrApply(new ExpressionUrlAuthorizationConfigurer<>(context)).getRegistry(); } /** @@ -1251,17 +1240,17 @@ public final class HttpSecurity extends * * * @see #requestMatcher(RequestMatcher) - * - * @param authorizeRequestsCustomizer the {@link Customizer} to provide more options for - * the {@link ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry} + * @param authorizeRequestsCustomizer the {@link Customizer} to provide more options + * for the {@link ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ - public HttpSecurity authorizeRequests(Customizer.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer) + public HttpSecurity authorizeRequests( + Customizer.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer) throws Exception { ApplicationContext context = getContext(); - authorizeRequestsCustomizer.customize(getOrApply(new ExpressionUrlAuthorizationConfigurer<>(context)) - .getRegistry()); + authorizeRequestsCustomizer + .customize(getOrApply(new ExpressionUrlAuthorizationConfigurer<>(context)).getRegistry()); return HttpSecurity.this; } @@ -1271,7 +1260,6 @@ public final class HttpSecurity extends * a login page. After authentication, Spring Security will redirect the user to the * originally requested protected page (/protected). This is automatically applied * when using {@link WebSecurityConfigurerAdapter}. - * * @return the {@link RequestCacheConfigurer} for further customizations * @throws Exception */ @@ -1308,7 +1296,6 @@ public final class HttpSecurity extends * } * } * - * * @param requestCacheCustomizer the {@link Customizer} to provide more options for * the {@link RequestCacheConfigurer} * @return the {@link HttpSecurity} for further customizations @@ -1323,7 +1310,6 @@ public final class HttpSecurity extends /** * Allows configuring exception handling. This is automatically applied when using * {@link WebSecurityConfigurerAdapter}. - * * @return the {@link ExceptionHandlingConfigurer} for further customizations * @throws Exception */ @@ -1337,8 +1323,8 @@ public final class HttpSecurity extends * *

    Example Custom Configuration

    * - * The following customization will ensure that users who are denied access are forwarded - * to the page "/errors/access-denied". + * The following customization will ensure that users who are denied access are + * forwarded to the page "/errors/access-denied". * *
     	 * @Configuration
    @@ -1360,13 +1346,13 @@ public final class HttpSecurity extends
     	 * 	}
     	 * }
     	 * 
    - * - * @param exceptionHandlingCustomizer the {@link Customizer} to provide more options for - * the {@link ExceptionHandlingConfigurer} + * @param exceptionHandlingCustomizer the {@link Customizer} to provide more options + * for the {@link ExceptionHandlingConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ - public HttpSecurity exceptionHandling(Customizer> exceptionHandlingCustomizer) throws Exception { + public HttpSecurity exceptionHandling( + Customizer> exceptionHandlingCustomizer) throws Exception { exceptionHandlingCustomizer.customize(getOrApply(new ExceptionHandlingConfigurer<>())); return HttpSecurity.this; } @@ -1375,7 +1361,6 @@ public final class HttpSecurity extends * Sets up management of the {@link SecurityContext} on the * {@link SecurityContextHolder} between {@link HttpServletRequest}'s. This is * automatically applied when using {@link WebSecurityConfigurerAdapter}. - * * @return the {@link SecurityContextConfigurer} for further customizations * @throws Exception */ @@ -1405,13 +1390,13 @@ public final class HttpSecurity extends * } * } * - * * @param securityContextCustomizer the {@link Customizer} to provide more options for * the {@link SecurityContextConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ - public HttpSecurity securityContext(Customizer> securityContextCustomizer) throws Exception { + public HttpSecurity securityContext(Customizer> securityContextCustomizer) + throws Exception { securityContextCustomizer.customize(getOrApply(new SecurityContextConfigurer<>())); return HttpSecurity.this; } @@ -1420,7 +1405,6 @@ public final class HttpSecurity extends * Integrates the {@link HttpServletRequest} methods with the values found on the * {@link SecurityContext}. This is automatically applied when using * {@link WebSecurityConfigurerAdapter}. - * * @return the {@link ServletApiConfigurer} for further customizations * @throws Exception */ @@ -1447,13 +1431,13 @@ public final class HttpSecurity extends * } * } * - * - * @param servletApiCustomizer the {@link Customizer} to provide more options for - * the {@link ServletApiConfigurer} + * @param servletApiCustomizer the {@link Customizer} to provide more options for the + * {@link ServletApiConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ - public HttpSecurity servletApi(Customizer> servletApiCustomizer) throws Exception { + public HttpSecurity servletApi(Customizer> servletApiCustomizer) + throws Exception { servletApiCustomizer.customize(getOrApply(new ServletApiConfigurer<>())); return HttpSecurity.this; } @@ -1476,7 +1460,6 @@ public final class HttpSecurity extends * } * } * - * * @return the {@link CsrfConfigurer} for further customizations * @throws Exception */ @@ -1502,9 +1485,8 @@ public final class HttpSecurity extends * } * } * - * - * @param csrfCustomizer the {@link Customizer} to provide more options for - * the {@link CsrfConfigurer} + * @param csrfCustomizer the {@link Customizer} to provide more options for the + * {@link CsrfConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ @@ -1547,7 +1529,6 @@ public final class HttpSecurity extends * } * } * - * * @return the {@link LogoutConfigurer} for further customizations * @throws Exception */ @@ -1591,9 +1572,8 @@ public final class HttpSecurity extends * } * } * - * - * @param logoutCustomizer the {@link Customizer} to provide more options for - * the {@link LogoutConfigurer} + * @param logoutCustomizer the {@link Customizer} to provide more options for the + * {@link LogoutConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ @@ -1665,7 +1645,6 @@ public final class HttpSecurity extends * } * } * - * * @return the {@link AnonymousConfigurer} for further customizations * @throws Exception */ @@ -1736,9 +1715,8 @@ public final class HttpSecurity extends * } * } * - * - * @param anonymousCustomizer the {@link Customizer} to provide more options for - * the {@link AnonymousConfigurer} + * @param anonymousCustomizer the {@link Customizer} to provide more options for the + * {@link AnonymousConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ @@ -1747,7 +1725,6 @@ public final class HttpSecurity extends return HttpSecurity.this; } - /** * Specifies to support form based authentication. If * {@link FormLoginConfigurer#loginPage(String)} is not specified a default login page @@ -1804,7 +1781,6 @@ public final class HttpSecurity extends * * * @see FormLoginConfigurer#loginPage(String) - * * @return the {@link FormLoginConfigurer} for further customizations * @throws Exception */ @@ -1868,9 +1844,8 @@ public final class HttpSecurity extends * * * @see FormLoginConfigurer#loginPage(String) - * - * @param formLoginCustomizer the {@link Customizer} to provide more options for - * the {@link FormLoginConfigurer} + * @param formLoginCustomizer the {@link Customizer} to provide more options for the + * {@link FormLoginConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ @@ -1880,40 +1855,39 @@ public final class HttpSecurity extends } /** - * Configures authentication support using an SAML 2.0 Service Provider. - *
    + * Configures authentication support using an SAML 2.0 Service Provider.
    *
    * - * The "authentication flow" is implemented using the Web Browser SSO Profile, using POST and REDIRECT bindings, - * as documented in the SAML V2.0 Core,Profiles and Bindings - * specifications. - *
    + * The "authentication flow" is implemented using the Web Browser SSO + * Profile, using POST and REDIRECT bindings, as documented in the + * SAML V2.0 + * Core,Profiles and Bindings specifications.
    *
    * - * As a prerequisite to using this feature, is that you have a SAML v2.0 Identity Provider to provide an assertion. - * The representation of the Service Provider, the relying party, and the remote Identity Provider, the asserting party - * is contained within {@link RelyingPartyRegistration}. - *
    + * As a prerequisite to using this feature, is that you have a SAML v2.0 Identity + * Provider to provide an assertion. The representation of the Service Provider, the + * relying party, and the remote Identity Provider, the asserting party is contained + * within {@link RelyingPartyRegistration}.
    *
    * * {@link RelyingPartyRegistration}(s) are composed within a - * {@link RelyingPartyRegistrationRepository}, - * which is required and must be registered with the {@link ApplicationContext} or - * configured via saml2Login().relyingPartyRegistrationRepository(..). - *
    + * {@link RelyingPartyRegistrationRepository}, which is required and must be + * registered with the {@link ApplicationContext} or configured via + * saml2Login().relyingPartyRegistrationRepository(..).
    *
    * - * The default configuration provides an auto-generated login page at "/login" and - * redirects to "/login?error" when an authentication error occurs. - * The login page will display each of the identity providers with a link - * that is capable of initiating the "authentication flow". - *
    + * The default configuration provides an auto-generated login page at + * "/login" and redirects to + * "/login?error" when an authentication error occurs. The + * login page will display each of the identity providers with a link that is capable + * of initiating the "authentication flow".
    *
    * *

    *

    Example Configuration

    * - * The following example shows the minimal configuration required, using SimpleSamlPhp as the Authentication Provider. + * The following example shows the minimal configuration required, using SimpleSamlPhp + * as the Authentication Provider. * *
     	 * @Configuration
    @@ -1971,40 +1945,39 @@ public final class HttpSecurity extends
     	}
     
     	/**
    -	 * Configures authentication support using an SAML 2.0 Service Provider.
    -	 * 
    + * Configures authentication support using an SAML 2.0 Service Provider.
    *
    * - * The "authentication flow" is implemented using the Web Browser SSO Profile, using POST and REDIRECT bindings, - * as documented in the SAML V2.0 Core,Profiles and Bindings - * specifications. - *
    + * The "authentication flow" is implemented using the Web Browser SSO + * Profile, using POST and REDIRECT bindings, as documented in the + * SAML V2.0 + * Core,Profiles and Bindings specifications.
    *
    * - * As a prerequisite to using this feature, is that you have a SAML v2.0 Identity Provider to provide an assertion. - * The representation of the Service Provider, the relying party, and the remote Identity Provider, the asserting party - * is contained within {@link RelyingPartyRegistration}. - *
    + * As a prerequisite to using this feature, is that you have a SAML v2.0 Identity + * Provider to provide an assertion. The representation of the Service Provider, the + * relying party, and the remote Identity Provider, the asserting party is contained + * within {@link RelyingPartyRegistration}.
    *
    * * {@link RelyingPartyRegistration}(s) are composed within a - * {@link RelyingPartyRegistrationRepository}, - * which is required and must be registered with the {@link ApplicationContext} or - * configured via saml2Login().relyingPartyRegistrationRepository(..). - *
    + * {@link RelyingPartyRegistrationRepository}, which is required and must be + * registered with the {@link ApplicationContext} or configured via + * saml2Login().relyingPartyRegistrationRepository(..).
    *
    * - * The default configuration provides an auto-generated login page at "/login" and - * redirects to "/login?error" when an authentication error occurs. - * The login page will display each of the identity providers with a link - * that is capable of initiating the "authentication flow". - *
    + * The default configuration provides an auto-generated login page at + * "/login" and redirects to + * "/login?error" when an authentication error occurs. The + * login page will display each of the identity providers with a link that is capable + * of initiating the "authentication flow".
    *
    * *

    *

    Example Configuration

    * - * The following example shows the minimal configuration required, using SimpleSamlPhp as the Authentication Provider. + * The following example shows the minimal configuration required, using SimpleSamlPhp + * as the Authentication Provider. * *
     	 * @Configuration
    @@ -2054,53 +2027,57 @@ public final class HttpSecurity extends
     	 * 

    * * @since 5.2 - * @param saml2LoginCustomizer the {@link Customizer} to provide more options for - * the {@link Saml2LoginConfigurer} + * @param saml2LoginCustomizer the {@link Customizer} to provide more options for the + * {@link Saml2LoginConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ - public HttpSecurity saml2Login(Customizer> saml2LoginCustomizer) throws Exception { + public HttpSecurity saml2Login(Customizer> saml2LoginCustomizer) + throws Exception { saml2LoginCustomizer.customize(getOrApply(new Saml2LoginConfigurer<>())); return HttpSecurity.this; } /** - * Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 Provider. - *
    + * Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 + * Provider.
    *
    * - * The "authentication flow" is implemented using the Authorization Code Grant, as specified in the - * OAuth 2.0 Authorization Framework - * and OpenID Connect Core 1.0 - * specification. - *
    + * The "authentication flow" is implemented using the Authorization Code + * Grant, as specified in the + * OAuth 2.0 + * Authorization Framework and OpenID Connect + * Core 1.0 specification.
    *
    * - * As a prerequisite to using this feature, you must register a client with a provider. - * The client registration information may than be used for configuring - * a {@link org.springframework.security.oauth2.client.registration.ClientRegistration} using a + * As a prerequisite to using this feature, you must register a client with a + * provider. The client registration information may than be used for configuring a + * {@link org.springframework.security.oauth2.client.registration.ClientRegistration} + * using a * {@link org.springframework.security.oauth2.client.registration.ClientRegistration.Builder}. *
    *
    * - * {@link org.springframework.security.oauth2.client.registration.ClientRegistration}(s) are composed within a + * {@link org.springframework.security.oauth2.client.registration.ClientRegistration}(s) + * are composed within a * {@link org.springframework.security.oauth2.client.registration.ClientRegistrationRepository}, - * which is required and must be registered with the {@link ApplicationContext} or - * configured via oauth2Login().clientRegistrationRepository(..). - *
    + * which is required and must be registered with the {@link ApplicationContext} + * or configured via oauth2Login().clientRegistrationRepository(..).
    *
    * - * The default configuration provides an auto-generated login page at "/login" and - * redirects to "/login?error" when an authentication error occurs. - * The login page will display each of the clients with a link - * that is capable of initiating the "authentication flow". - *
    + * The default configuration provides an auto-generated login page at + * "/login" and redirects to + * "/login?error" when an authentication error occurs. The + * login page will display each of the clients with a link that is capable of + * initiating the "authentication flow".
    *
    * *

    *

    Example Configuration

    * - * The following example shows the minimal configuration required, using Google as the Authentication Provider. + * The following example shows the minimal configuration required, using Google as the + * Authentication Provider. * *
     	 * @Configuration
    @@ -2143,11 +2120,16 @@ public final class HttpSecurity extends
     	 * 
    * *

    - * For more advanced configuration, see {@link OAuth2LoginConfigurer} for available options to customize the defaults. + * For more advanced configuration, see {@link OAuth2LoginConfigurer} for available + * options to customize the defaults. * * @since 5.0 - * @see Section 4.1 Authorization Code Grant - * @see Section 3.1 Authorization Code Flow + * @see Section 4.1 Authorization Code + * Grant + * @see Section 3.1 + * Authorization Code Flow * @see org.springframework.security.oauth2.client.registration.ClientRegistration * @see org.springframework.security.oauth2.client.registration.ClientRegistrationRepository * @return the {@link OAuth2LoginConfigurer} for further customizations @@ -2158,42 +2140,45 @@ public final class HttpSecurity extends } /** - * Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 Provider. - *
    + * Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 + * Provider.
    *
    * - * The "authentication flow" is implemented using the Authorization Code Grant, as specified in the - * OAuth 2.0 Authorization Framework - * and OpenID Connect Core 1.0 - * specification. - *
    + * The "authentication flow" is implemented using the Authorization Code + * Grant, as specified in the + * OAuth 2.0 + * Authorization Framework and OpenID Connect + * Core 1.0 specification.
    *
    * - * As a prerequisite to using this feature, you must register a client with a provider. - * The client registration information may than be used for configuring - * a {@link org.springframework.security.oauth2.client.registration.ClientRegistration} using a + * As a prerequisite to using this feature, you must register a client with a + * provider. The client registration information may than be used for configuring a + * {@link org.springframework.security.oauth2.client.registration.ClientRegistration} + * using a * {@link org.springframework.security.oauth2.client.registration.ClientRegistration.Builder}. *
    *
    * - * {@link org.springframework.security.oauth2.client.registration.ClientRegistration}(s) are composed within a + * {@link org.springframework.security.oauth2.client.registration.ClientRegistration}(s) + * are composed within a * {@link org.springframework.security.oauth2.client.registration.ClientRegistrationRepository}, - * which is required and must be registered with the {@link ApplicationContext} or - * configured via oauth2Login().clientRegistrationRepository(..). - *
    + * which is required and must be registered with the {@link ApplicationContext} + * or configured via oauth2Login().clientRegistrationRepository(..).
    *
    * - * The default configuration provides an auto-generated login page at "/login" and - * redirects to "/login?error" when an authentication error occurs. - * The login page will display each of the clients with a link - * that is capable of initiating the "authentication flow". - *
    + * The default configuration provides an auto-generated login page at + * "/login" and redirects to + * "/login?error" when an authentication error occurs. The + * login page will display each of the clients with a link that is capable of + * initiating the "authentication flow".
    *
    * *

    *

    Example Configuration

    * - * The following example shows the minimal configuration required, using Google as the Authentication Provider. + * The following example shows the minimal configuration required, using Google as the + * Authentication Provider. * *
     	 * @Configuration
    @@ -2237,19 +2222,24 @@ public final class HttpSecurity extends
     	 * 
    * *

    - * For more advanced configuration, see {@link OAuth2LoginConfigurer} for available options to customize the defaults. + * For more advanced configuration, see {@link OAuth2LoginConfigurer} for available + * options to customize the defaults. * - * @see Section 4.1 Authorization Code Grant - * @see Section 3.1 Authorization Code Flow + * @see Section 4.1 Authorization Code + * Grant + * @see Section 3.1 + * Authorization Code Flow * @see org.springframework.security.oauth2.client.registration.ClientRegistration * @see org.springframework.security.oauth2.client.registration.ClientRegistrationRepository - * - * @param oauth2LoginCustomizer the {@link Customizer} to provide more options for - * the {@link OAuth2LoginConfigurer} + * @param oauth2LoginCustomizer the {@link Customizer} to provide more options for the + * {@link OAuth2LoginConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ - public HttpSecurity oauth2Login(Customizer> oauth2LoginCustomizer) throws Exception { + public HttpSecurity oauth2Login(Customizer> oauth2LoginCustomizer) + throws Exception { oauth2LoginCustomizer.customize(getOrApply(new OAuth2LoginConfigurer<>())); return HttpSecurity.this; } @@ -2258,7 +2248,9 @@ public final class HttpSecurity extends * Configures OAuth 2.0 Client support. * * @since 5.1 - * @see OAuth 2.0 Authorization Framework + * @see OAuth 2.0 Authorization + * Framework * @return the {@link OAuth2ClientConfigurer} for further customizations * @throws Exception */ @@ -2273,7 +2265,8 @@ public final class HttpSecurity extends * *

    Example Configuration

    * - * The following example demonstrates how to enable OAuth 2.0 Client support for all endpoints. + * The following example demonstrates how to enable OAuth 2.0 Client support for all + * endpoints. * *
     	 * @Configuration
    @@ -2291,14 +2284,16 @@ public final class HttpSecurity extends
     	 * }
     	 * 
    * - * @see OAuth 2.0 Authorization Framework - * + * @see OAuth 2.0 Authorization + * Framework * @param oauth2ClientCustomizer the {@link Customizer} to provide more options for * the {@link OAuth2ClientConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ - public HttpSecurity oauth2Client(Customizer> oauth2ClientCustomizer) throws Exception { + public HttpSecurity oauth2Client(Customizer> oauth2ClientCustomizer) + throws Exception { oauth2ClientCustomizer.customize(getOrApply(new OAuth2ClientConfigurer<>())); return HttpSecurity.this; } @@ -2307,12 +2302,15 @@ public final class HttpSecurity extends * Configures OAuth 2.0 Resource Server support. * * @since 5.1 - * @see OAuth 2.0 Authorization Framework + * @see OAuth 2.0 Authorization + * Framework * @return the {@link OAuth2ResourceServerConfigurer} for further customizations * @throws Exception */ public OAuth2ResourceServerConfigurer oauth2ResourceServer() throws Exception { - OAuth2ResourceServerConfigurer configurer = getOrApply(new OAuth2ResourceServerConfigurer<>(getContext())); + OAuth2ResourceServerConfigurer configurer = getOrApply( + new OAuth2ResourceServerConfigurer<>(getContext())); this.postProcess(configurer); return configurer; } @@ -2322,7 +2320,8 @@ public final class HttpSecurity extends * *

    Example Configuration

    * - * The following example demonstrates how to configure a custom JWT authentication converter. + * The following example demonstrates how to configure a custom JWT authentication + * converter. * *
     	 * @Configuration
    @@ -2355,16 +2354,18 @@ public final class HttpSecurity extends
     	 * }
     	 * 
    * - * @see OAuth 2.0 Authorization Framework - * - * @param oauth2ResourceServerCustomizer the {@link Customizer} to provide more options for - * the {@link OAuth2ResourceServerConfigurer} + * @see OAuth 2.0 Authorization + * Framework + * @param oauth2ResourceServerCustomizer the {@link Customizer} to provide more + * options for the {@link OAuth2ResourceServerConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ - public HttpSecurity oauth2ResourceServer(Customizer> oauth2ResourceServerCustomizer) - throws Exception { - OAuth2ResourceServerConfigurer configurer = getOrApply(new OAuth2ResourceServerConfigurer<>(getContext())); + public HttpSecurity oauth2ResourceServer( + Customizer> oauth2ResourceServerCustomizer) throws Exception { + OAuth2ResourceServerConfigurer configurer = getOrApply( + new OAuth2ResourceServerConfigurer<>(getContext())); this.postProcess(configurer); oauth2ResourceServerCustomizer.customize(configurer); return HttpSecurity.this; @@ -2379,8 +2380,8 @@ public final class HttpSecurity extends * The example below demonstrates how to require HTTPs for every request. Only * requiring HTTPS for some requests is supported, but not recommended since an * application that allows for HTTP introduces many security vulnerabilities. For one - * such example, read about Firesheep. + * such example, read about + * Firesheep. * *
     	 * @Configuration
    @@ -2399,16 +2400,12 @@ public final class HttpSecurity extends
     	 * 	}
     	 * }
     	 * 
    - * - * * @return the {@link ChannelSecurityConfigurer} for further customizations * @throws Exception */ - public ChannelSecurityConfigurer.ChannelRequestMatcherRegistry requiresChannel() - throws Exception { + public ChannelSecurityConfigurer.ChannelRequestMatcherRegistry requiresChannel() throws Exception { ApplicationContext context = getContext(); - return getOrApply(new ChannelSecurityConfigurer<>(context)) - .getRegistry(); + return getOrApply(new ChannelSecurityConfigurer<>(context)).getRegistry(); } /** @@ -2420,8 +2417,8 @@ public final class HttpSecurity extends * The example below demonstrates how to require HTTPs for every request. Only * requiring HTTPS for some requests is supported, but not recommended since an * application that allows for HTTP introduces many security vulnerabilities. For one - * such example, read about Firesheep. + * such example, read about + * Firesheep. * *
     	 * @Configuration
    @@ -2443,17 +2440,16 @@ public final class HttpSecurity extends
     	 * 	}
     	 * }
     	 * 
    - * * @param requiresChannelCustomizer the {@link Customizer} to provide more options for * the {@link ChannelSecurityConfigurer.ChannelRequestMatcherRegistry} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ - public HttpSecurity requiresChannel(Customizer.ChannelRequestMatcherRegistry> requiresChannelCustomizer) + public HttpSecurity requiresChannel( + Customizer.ChannelRequestMatcherRegistry> requiresChannelCustomizer) throws Exception { ApplicationContext context = getContext(); - requiresChannelCustomizer.customize(getOrApply(new ChannelSecurityConfigurer<>(context)) - .getRegistry()); + requiresChannelCustomizer.customize(getOrApply(new ChannelSecurityConfigurer<>(context)).getRegistry()); return HttpSecurity.this; } @@ -2463,8 +2459,8 @@ public final class HttpSecurity extends *

    Example Configuration

    * * The example below demonstrates how to configure HTTP Basic authentication for an - * application. The default realm is "Realm", but can be - * customized using {@link HttpBasicConfigurer#realmName(String)}. + * application. The default realm is "Realm", but can be customized using + * {@link HttpBasicConfigurer#realmName(String)}. * *
     	 * @Configuration
    @@ -2482,7 +2478,6 @@ public final class HttpSecurity extends
     	 * 	}
     	 * }
     	 * 
    - * * @return the {@link HttpBasicConfigurer} for further customizations * @throws Exception */ @@ -2496,8 +2491,8 @@ public final class HttpSecurity extends *

    Example Configuration

    * * The example below demonstrates how to configure HTTP Basic authentication for an - * application. The default realm is "Realm", but can be - * customized using {@link HttpBasicConfigurer#realmName(String)}. + * application. The default realm is "Realm", but can be customized using + * {@link HttpBasicConfigurer#realmName(String)}. * *
     	 * @Configuration
    @@ -2515,9 +2510,8 @@ public final class HttpSecurity extends
     	 * 	}
     	 * }
     	 * 
    - * - * @param httpBasicCustomizer the {@link Customizer} to provide more options for - * the {@link HttpBasicConfigurer} + * @param httpBasicCustomizer the {@link Customizer} to provide more options for the + * {@link HttpBasicConfigurer} * @return the {@link HttpSecurity} for further customizations * @throws Exception */ @@ -2544,12 +2538,11 @@ public final class HttpSecurity extends /* * (non-Javadoc) * - * @see - * org.springframework.security.config.annotation.web.HttpSecurityBuilder#authenticationProvider + * @see org.springframework.security.config.annotation.web.HttpSecurityBuilder# + * authenticationProvider * (org.springframework.security.authentication.AuthenticationProvider) */ - public HttpSecurity authenticationProvider( - AuthenticationProvider authenticationProvider) { + public HttpSecurity authenticationProvider(AuthenticationProvider authenticationProvider) { getAuthenticationRegistry().authenticationProvider(authenticationProvider); return this; } @@ -2557,12 +2550,11 @@ public final class HttpSecurity extends /* * (non-Javadoc) * - * @see - * org.springframework.security.config.annotation.web.HttpSecurityBuilder#userDetailsService + * @see org.springframework.security.config.annotation.web.HttpSecurityBuilder# + * userDetailsService * (org.springframework.security.core.userdetails.UserDetailsService) */ - public HttpSecurity userDetailsService(UserDetailsService userDetailsService) - throws Exception { + public HttpSecurity userDetailsService(UserDetailsService userDetailsService) throws Exception { getAuthenticationRegistry().userDetailsService(userDetailsService); return this; } @@ -2574,9 +2566,8 @@ public final class HttpSecurity extends /* * (non-Javadoc) * - * @see - * org.springframework.security.config.annotation.web.HttpSecurityBuilder#addFilterAfter(javax - * .servlet.Filter, java.lang.Class) + * @see org.springframework.security.config.annotation.web.HttpSecurityBuilder# + * addFilterAfter(javax .servlet.Filter, java.lang.Class) */ public HttpSecurity addFilterAfter(Filter filter, Class afterFilter) { comparator.registerAfter(filter.getClass(), afterFilter); @@ -2586,12 +2577,10 @@ public final class HttpSecurity extends /* * (non-Javadoc) * - * @see - * org.springframework.security.config.annotation.web.HttpSecurityBuilder#addFilterBefore( - * javax.servlet.Filter, java.lang.Class) + * @see org.springframework.security.config.annotation.web.HttpSecurityBuilder# + * addFilterBefore( javax.servlet.Filter, java.lang.Class) */ - public HttpSecurity addFilterBefore(Filter filter, - Class beforeFilter) { + public HttpSecurity addFilterBefore(Filter filter, Class beforeFilter) { comparator.registerBefore(filter.getClass(), beforeFilter); return addFilter(filter); } @@ -2600,16 +2589,14 @@ public final class HttpSecurity extends * (non-Javadoc) * * @see - * org.springframework.security.config.annotation.web.HttpSecurityBuilder#addFilter(javax. - * servlet.Filter) + * org.springframework.security.config.annotation.web.HttpSecurityBuilder#addFilter( + * javax. servlet.Filter) */ public HttpSecurity addFilter(Filter filter) { Class filterClass = filter.getClass(); if (!comparator.isRegistered(filterClass)) { - throw new IllegalArgumentException( - "The Filter class " - + filterClass.getName() - + " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead."); + throw new IllegalArgumentException("The Filter class " + filterClass.getName() + + " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead."); } this.filters.add(filter); return this; @@ -2628,7 +2615,6 @@ public final class HttpSecurity extends * deterministic. More concretely, registering multiple Filters in the same location * does not override existing Filters. Instead, do not register Filters you do not * want to use. - * * @param filter the Filter to register * @param atFilter the location of another {@link Filter} that is already registered * (i.e. known) with Spring Security. @@ -2643,14 +2629,15 @@ public final class HttpSecurity extends * Allows specifying which {@link HttpServletRequest} instances this * {@link HttpSecurity} will be invoked on. This method allows for easily invoking the * {@link HttpSecurity} for multiple different {@link RequestMatcher} instances. If - * only a single {@link RequestMatcher} is necessary consider using {@link #mvcMatcher(String)}, - * {@link #antMatcher(String)}, {@link #regexMatcher(String)}, or - * {@link #requestMatcher(RequestMatcher)}. + * only a single {@link RequestMatcher} is necessary consider using + * {@link #mvcMatcher(String)}, {@link #antMatcher(String)}, + * {@link #regexMatcher(String)}, or {@link #requestMatcher(RequestMatcher)}. * *

    - * Invoking {@link #requestMatchers()} will not override previous invocations of {@link #mvcMatcher(String)}}, - * {@link #requestMatchers()}, {@link #antMatcher(String)}, - * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. + * Invoking {@link #requestMatchers()} will not override previous invocations of + * {@link #mvcMatcher(String)}}, {@link #requestMatchers()}, + * {@link #antMatcher(String)}, {@link #regexMatcher(String)}, and + * {@link #requestMatcher(RequestMatcher)}. *

    * *

    Example Configurations

    @@ -2743,7 +2730,6 @@ public final class HttpSecurity extends * } * } *
    - * * @return the {@link RequestMatcherConfigurer} for further customizations */ public RequestMatcherConfigurer requestMatchers() { @@ -2754,14 +2740,15 @@ public final class HttpSecurity extends * Allows specifying which {@link HttpServletRequest} instances this * {@link HttpSecurity} will be invoked on. This method allows for easily invoking the * {@link HttpSecurity} for multiple different {@link RequestMatcher} instances. If - * only a single {@link RequestMatcher} is necessary consider using {@link #mvcMatcher(String)}, - * {@link #antMatcher(String)}, {@link #regexMatcher(String)}, or - * {@link #requestMatcher(RequestMatcher)}. + * only a single {@link RequestMatcher} is necessary consider using + * {@link #mvcMatcher(String)}, {@link #antMatcher(String)}, + * {@link #regexMatcher(String)}, or {@link #requestMatcher(RequestMatcher)}. * *

    - * Invoking {@link #requestMatchers()} will not override previous invocations of {@link #mvcMatcher(String)}}, - * {@link #requestMatchers()}, {@link #antMatcher(String)}, - * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. + * Invoking {@link #requestMatchers()} will not override previous invocations of + * {@link #mvcMatcher(String)}}, {@link #requestMatchers()}, + * {@link #antMatcher(String)}, {@link #regexMatcher(String)}, and + * {@link #requestMatcher(RequestMatcher)}. *

    * *

    Example Configurations

    @@ -2840,7 +2827,6 @@ public final class HttpSecurity extends * } * } *
    - * * @param requestMatcherCustomizer the {@link Customizer} to provide more options for * the {@link RequestMatcherConfigurer} * @return the {@link HttpSecurity} for further customizations @@ -2857,10 +2843,10 @@ public final class HttpSecurity extends * *

    * Invoking {@link #requestMatcher(RequestMatcher)} will override previous invocations - * of {@link #requestMatchers()}, {@link #mvcMatcher(String)}, {@link #antMatcher(String)}, - * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. + * of {@link #requestMatchers()}, {@link #mvcMatcher(String)}, + * {@link #antMatcher(String)}, {@link #regexMatcher(String)}, and + * {@link #requestMatcher(RequestMatcher)}. *

    - * * @param requestMatcher the {@link RequestMatcher} to use (i.e. new * AntPathRequestMatcher("/admin/**","GET") ) * @return the {@link HttpSecurity} for further customizations @@ -2879,11 +2865,11 @@ public final class HttpSecurity extends * {@link #requestMatchers()} or {@link #requestMatcher(RequestMatcher)}. * *

    - * Invoking {@link #antMatcher(String)} will override previous invocations of {@link #mvcMatcher(String)}}, - * {@link #requestMatchers()}, {@link #antMatcher(String)}, - * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. + * Invoking {@link #antMatcher(String)} will override previous invocations of + * {@link #mvcMatcher(String)}}, {@link #requestMatchers()}, + * {@link #antMatcher(String)}, {@link #regexMatcher(String)}, and + * {@link #requestMatcher(RequestMatcher)}. *

    - * * @param antPattern the Ant Pattern to match on (i.e. "/admin/**") * @return the {@link HttpSecurity} for further customizations * @see AntPathRequestMatcher @@ -2894,15 +2880,15 @@ public final class HttpSecurity extends /** * Allows configuring the {@link HttpSecurity} to only be invoked when matching the - * provided Spring MVC pattern. If more advanced configuration is necessary, consider using - * {@link #requestMatchers()} or {@link #requestMatcher(RequestMatcher)}. + * provided Spring MVC pattern. If more advanced configuration is necessary, consider + * using {@link #requestMatchers()} or {@link #requestMatcher(RequestMatcher)}. * *

    - * Invoking {@link #mvcMatcher(String)} will override previous invocations of {@link #mvcMatcher(String)}}, - * {@link #requestMatchers()}, {@link #antMatcher(String)}, - * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. + * Invoking {@link #mvcMatcher(String)} will override previous invocations of + * {@link #mvcMatcher(String)}}, {@link #requestMatchers()}, + * {@link #antMatcher(String)}, {@link #regexMatcher(String)}, and + * {@link #requestMatcher(RequestMatcher)}. *

    - * * @param mvcPattern the Spring MVC Pattern to match on (i.e. "/admin/**") * @return the {@link HttpSecurity} for further customizations * @see MvcRequestMatcher @@ -2918,11 +2904,11 @@ public final class HttpSecurity extends * {@link #requestMatchers()} or {@link #requestMatcher(RequestMatcher)}. * *

    - * Invoking {@link #regexMatcher(String)} will override previous invocations of {@link #mvcMatcher(String)}}, - * {@link #requestMatchers()}, {@link #antMatcher(String)}, - * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. + * Invoking {@link #regexMatcher(String)} will override previous invocations of + * {@link #mvcMatcher(String)}}, {@link #requestMatchers()}, + * {@link #antMatcher(String)}, {@link #regexMatcher(String)}, and + * {@link #requestMatcher(RequestMatcher)}. *

    - * * @param pattern the Regular Expression to match on (i.e. "/admin/.+") * @return the {@link HttpSecurity} for further customizations * @see RegexRequestMatcher @@ -2945,8 +2931,7 @@ public final class HttpSecurity extends * @param matchers the {@link MvcRequestMatcher} instances to set the servlet path * on if {@link #servletPath(String)} is set. */ - private MvcMatchersRequestMatcherConfigurer(ApplicationContext context, - List matchers) { + private MvcMatchersRequestMatcherConfigurer(ApplicationContext context, List matchers) { super(context); this.matchers = new ArrayList<>(matchers); } @@ -2966,8 +2951,7 @@ public final class HttpSecurity extends * @author Rob Winch * @since 3.2 */ - public class RequestMatcherConfigurer - extends AbstractRequestMatcherRegistry { + public class RequestMatcherConfigurer extends AbstractRequestMatcherRegistry { protected List matchers = new ArrayList<>(); @@ -2979,8 +2963,7 @@ public final class HttpSecurity extends } @Override - public MvcMatchersRequestMatcherConfigurer mvcMatchers(HttpMethod method, - String... mvcPatterns) { + public MvcMatchersRequestMatcherConfigurer mvcMatchers(HttpMethod method, String... mvcPatterns) { List mvcMatchers = createMvcMatchers(method, mvcPatterns); setMatchers(mvcMatchers); return new MvcMatchersRequestMatcherConfigurer(getContext(), mvcMatchers); @@ -2992,8 +2975,7 @@ public final class HttpSecurity extends } @Override - protected RequestMatcherConfigurer chainRequestMatchers( - List requestMatchers) { + protected RequestMatcherConfigurer chainRequestMatchers(List requestMatchers) { setMatchers(requestMatchers); return this; } @@ -3005,7 +2987,6 @@ public final class HttpSecurity extends /** * Return the {@link HttpSecurity} for further customizations - * * @return the {@link HttpSecurity} for further customizations */ public HttpSecurity and() { @@ -3017,19 +2998,19 @@ public final class HttpSecurity extends /** * If the {@link SecurityConfigurer} has already been specified get the original, * otherwise apply the new {@link SecurityConfigurerAdapter}. - * * @param configurer the {@link SecurityConfigurer} to apply if one is not found for * this {@link SecurityConfigurer} class. * @return the current {@link SecurityConfigurer} for the configurer passed in * @throws Exception */ @SuppressWarnings("unchecked") - private > C getOrApply( - C configurer) throws Exception { + private > C getOrApply(C configurer) + throws Exception { C existingConfig = (C) getConfigurer(configurer.getClass()); if (existingConfig != null) { return existingConfig; } return apply(configurer); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java index 251556fcaf..1adc9465ec 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java @@ -74,14 +74,13 @@ import org.springframework.web.filter.DelegatingFilterProxy; * * @see EnableWebSecurity * @see WebSecurityConfiguration - * * @author Rob Winch * @author Evgeniy Cheban * @since 3.2 */ -public final class WebSecurity extends - AbstractConfiguredSecurityBuilder implements - SecurityBuilder, ApplicationContextAware { +public final class WebSecurity extends AbstractConfiguredSecurityBuilder + implements SecurityBuilder, ApplicationContextAware { + private final Log logger = LogFactory.getLog(getClass()); private final List ignoredRequests = new ArrayList<>(); @@ -118,12 +117,11 @@ public final class WebSecurity extends /** *

    - * Allows adding {@link RequestMatcher} instances that Spring Security - * should ignore. Web Security provided by Spring Security (including the - * {@link SecurityContext}) will not be available on {@link HttpServletRequest} that - * match. Typically the requests that are registered should be that of only static - * resources. For requests that are dynamic, consider mapping the request to allow all - * users instead. + * Allows adding {@link RequestMatcher} instances that Spring Security should ignore. + * Web Security provided by Spring Security (including the {@link SecurityContext}) + * will not be available on {@link HttpServletRequest} that match. Typically the + * requests that are registered should be that of only static resources. For requests + * that are dynamic, consider mapping the request to allow all users instead. *

    * * Example Usage: @@ -154,7 +152,6 @@ public final class WebSecurity extends * .antMatchers("/static/**"); * // now both URLs that start with /resources/ and /static/ will be ignored * - * * @return the {@link IgnoredRequestConfigurer} to use for registering request that * should be ignored */ @@ -165,7 +162,6 @@ public final class WebSecurity extends /** * Allows customizing the {@link HttpFirewall}. The default is * {@link StrictHttpFirewall}. - * * @param httpFirewall the custom {@link HttpFirewall} * @return the {@link WebSecurity} for further customizations */ @@ -176,10 +172,8 @@ public final class WebSecurity extends /** * Controls debugging support for Spring Security. - * * @param debugEnabled if true, enables debug support with Spring Security. Default is * false. - * * @return the {@link WebSecurity} for further customization. * @see EnableWebSecurity#debug() */ @@ -197,7 +191,6 @@ public final class WebSecurity extends * Typically this method is invoked automatically within the framework from * {@link WebSecurityConfigurerAdapter#init(WebSecurity)} *

    - * * @param securityFilterChainBuilder the builder to use to create the * {@link SecurityFilterChain} instances * @return the {@link WebSecurity} for further customizations @@ -209,15 +202,13 @@ public final class WebSecurity extends } /** - * Set the {@link WebInvocationPrivilegeEvaluator} to be used. If this is not specified, - * then a {@link DefaultWebInvocationPrivilegeEvaluator} will be created when - * {@link #securityInterceptor(FilterSecurityInterceptor)} is non null. - * + * Set the {@link WebInvocationPrivilegeEvaluator} to be used. If this is not + * specified, then a {@link DefaultWebInvocationPrivilegeEvaluator} will be created + * when {@link #securityInterceptor(FilterSecurityInterceptor)} is non null. * @param privilegeEvaluator the {@link WebInvocationPrivilegeEvaluator} to use * @return the {@link WebSecurity} for further customizations */ - public WebSecurity privilegeEvaluator( - WebInvocationPrivilegeEvaluator privilegeEvaluator) { + public WebSecurity privilegeEvaluator(WebInvocationPrivilegeEvaluator privilegeEvaluator) { this.privilegeEvaluator = privilegeEvaluator; return this; } @@ -225,12 +216,10 @@ public final class WebSecurity extends /** * Set the {@link SecurityExpressionHandler} to be used. If this is not specified, * then a {@link DefaultWebSecurityExpressionHandler} will be used. - * * @param expressionHandler the {@link SecurityExpressionHandler} to use * @return the {@link WebSecurity} for further customizations */ - public WebSecurity expressionHandler( - SecurityExpressionHandler expressionHandler) { + public WebSecurity expressionHandler(SecurityExpressionHandler expressionHandler) { Assert.notNull(expressionHandler, "expressionHandler cannot be null"); this.expressionHandler = expressionHandler; return this; @@ -269,7 +258,6 @@ public final class WebSecurity extends /** * Executes the Runnable immediately after the build takes place - * * @param postBuildAction * @return the {@link WebSecurity} for further customizations */ @@ -280,17 +268,14 @@ public final class WebSecurity extends @Override protected Filter performBuild() throws Exception { - Assert.state( - !securityFilterChainBuilders.isEmpty(), + Assert.state(!securityFilterChainBuilders.isEmpty(), () -> "At least one SecurityBuilder needs to be specified. " + "Typically this is done by exposing a SecurityFilterChain bean " + "or by adding a @Configuration that extends WebSecurityConfigurerAdapter. " - + "More advanced users can invoke " - + WebSecurity.class.getSimpleName() + + "More advanced users can invoke " + WebSecurity.class.getSimpleName() + ".addSecurityFilterChainBuilder directly"); int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size(); - List securityFilterChains = new ArrayList<>( - chainSize); + List securityFilterChains = new ArrayList<>(chainSize); for (RequestMatcher ignoredRequest : ignoredRequests) { securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest)); } @@ -308,8 +293,7 @@ public final class WebSecurity extends Filter result = filterChainProxy; if (debugEnabled) { - logger.warn("\n\n" - + "********************************************************************\n" + logger.warn("\n\n" + "********************************************************************\n" + "********** Security debugging is enabled. *************\n" + "********** This may include sensitive information. *************\n" + "********** Do not use in a production system! *************\n" @@ -326,12 +310,11 @@ public final class WebSecurity extends * * @author Rob Winch */ - public final class MvcMatchersIgnoredRequestConfigurer - extends IgnoredRequestConfigurer { + public final class MvcMatchersIgnoredRequestConfigurer extends IgnoredRequestConfigurer { + private final List mvcMatchers; - private MvcMatchersIgnoredRequestConfigurer(ApplicationContext context, - List mvcMatchers) { + private MvcMatchersIgnoredRequestConfigurer(ApplicationContext context, List mvcMatchers) { super(context); this.mvcMatchers = mvcMatchers; } @@ -342,6 +325,7 @@ public final class WebSecurity extends } return this; } + } /** @@ -351,20 +335,17 @@ public final class WebSecurity extends * @author Rob Winch * @since 3.2 */ - public class IgnoredRequestConfigurer - extends AbstractRequestMatcherRegistry { + public class IgnoredRequestConfigurer extends AbstractRequestMatcherRegistry { private IgnoredRequestConfigurer(ApplicationContext context) { setApplicationContext(context); } @Override - public MvcMatchersIgnoredRequestConfigurer mvcMatchers(HttpMethod method, - String... mvcPatterns) { + public MvcMatchersIgnoredRequestConfigurer mvcMatchers(HttpMethod method, String... mvcPatterns) { List mvcMatchers = createMvcMatchers(method, mvcPatterns); WebSecurity.this.ignoredRequests.addAll(mvcMatchers); - return new MvcMatchersIgnoredRequestConfigurer(getApplicationContext(), - mvcMatchers); + return new MvcMatchersIgnoredRequestConfigurer(getApplicationContext(), mvcMatchers); } @Override @@ -373,8 +354,7 @@ public final class WebSecurity extends } @Override - protected IgnoredRequestConfigurer chainRequestMatchers( - List requestMatchers) { + protected IgnoredRequestConfigurer chainRequestMatchers(List requestMatchers) { WebSecurity.this.ignoredRequests.addAll(requestMatchers); return this; } @@ -385,29 +365,37 @@ public final class WebSecurity extends public WebSecurity and() { return WebSecurity.this; } + } @Override - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.defaultWebSecurityExpressionHandler - .setApplicationContext(applicationContext); + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.defaultWebSecurityExpressionHandler.setApplicationContext(applicationContext); try { this.defaultWebSecurityExpressionHandler.setRoleHierarchy(applicationContext.getBean(RoleHierarchy.class)); - } catch (NoSuchBeanDefinitionException e) {} + } + catch (NoSuchBeanDefinitionException e) { + } try { - this.defaultWebSecurityExpressionHandler.setPermissionEvaluator(applicationContext.getBean( - PermissionEvaluator.class)); - } catch(NoSuchBeanDefinitionException e) {} + this.defaultWebSecurityExpressionHandler + .setPermissionEvaluator(applicationContext.getBean(PermissionEvaluator.class)); + } + catch (NoSuchBeanDefinitionException e) { + } this.ignoredRequestRegistry = new IgnoredRequestConfigurer(applicationContext); try { this.httpFirewall = applicationContext.getBean(HttpFirewall.class); - } catch(NoSuchBeanDefinitionException e) {} + } + catch (NoSuchBeanDefinitionException e) { + } try { this.requestRejectedHandler = applicationContext.getBean(RequestRejectedHandler.class); - } catch(NoSuchBeanDefinitionException e) {} + } + catch (NoSuchBeanDefinitionException e) { + } } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/AutowiredWebSecurityConfigurersIgnoreParents.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/AutowiredWebSecurityConfigurersIgnoreParents.java index 9195060ef1..012c0fec66 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/AutowiredWebSecurityConfigurersIgnoreParents.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/AutowiredWebSecurityConfigurersIgnoreParents.java @@ -40,8 +40,7 @@ final class AutowiredWebSecurityConfigurersIgnoreParents { private final ConfigurableListableBeanFactory beanFactory; - AutowiredWebSecurityConfigurersIgnoreParents( - ConfigurableListableBeanFactory beanFactory) { + AutowiredWebSecurityConfigurersIgnoreParents(ConfigurableListableBeanFactory beanFactory) { Assert.notNull(beanFactory, "beanFactory cannot be null"); this.beanFactory = beanFactory; } @@ -49,11 +48,11 @@ final class AutowiredWebSecurityConfigurersIgnoreParents { @SuppressWarnings({ "rawtypes", "unchecked" }) public List> getWebSecurityConfigurers() { List> webSecurityConfigurers = new ArrayList<>(); - Map beansOfType = beanFactory - .getBeansOfType(WebSecurityConfigurer.class); + Map beansOfType = beanFactory.getBeansOfType(WebSecurityConfigurer.class); for (Entry entry : beansOfType.entrySet()) { webSecurityConfigurers.add(entry.getValue()); } return webSecurityConfigurers; } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurity.java index 9b6ccdbfa5..217ae581a3 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurity.java @@ -72,10 +72,8 @@ import org.springframework.security.config.annotation.web.WebSecurityConfigurer; @Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) @Target(value = { java.lang.annotation.ElementType.TYPE }) @Documented -@Import({ WebSecurityConfiguration.class, - SpringWebMvcImportSelector.class, - OAuth2ImportSelector.class, - HttpSecurityConfiguration.class}) +@Import({ WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class, + HttpSecurityConfiguration.class }) @EnableGlobalAuthentication @Configuration public @interface EnableWebSecurity { @@ -85,4 +83,5 @@ public @interface EnableWebSecurity { * @return if true, enables debug support with Spring Security */ boolean debug() default false; + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java index 0b4ea90061..456f436ce1 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java @@ -42,7 +42,9 @@ import static org.springframework.security.config.Customizer.withDefaults; */ @Configuration(proxyBeanMethods = false) class HttpSecurityConfiguration { + private static final String BEAN_NAME_PREFIX = "org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration."; + private static final String HTTPSECURITY_BEAN_NAME = BEAN_NAME_PREFIX + "httpSecurity"; private ObjectPostProcessor objectPostProcessor; @@ -64,8 +66,7 @@ class HttpSecurityConfiguration { } @Autowired - public void setAuthenticationConfiguration( - AuthenticationConfiguration authenticationConfiguration) { + public void setAuthenticationConfiguration(AuthenticationConfiguration authenticationConfiguration) { this.authenticationConfiguration = authenticationConfiguration; } @@ -77,26 +78,18 @@ class HttpSecurityConfiguration { @Bean(HTTPSECURITY_BEAN_NAME) @Scope("prototype") public HttpSecurity httpSecurity() throws Exception { - WebSecurityConfigurerAdapter.LazyPasswordEncoder passwordEncoder = - new WebSecurityConfigurerAdapter.LazyPasswordEncoder(this.context); + WebSecurityConfigurerAdapter.LazyPasswordEncoder passwordEncoder = new WebSecurityConfigurerAdapter.LazyPasswordEncoder( + this.context); - AuthenticationManagerBuilder authenticationBuilder = - new WebSecurityConfigurerAdapter.DefaultPasswordEncoderAuthenticationManagerBuilder(this.objectPostProcessor, passwordEncoder); + AuthenticationManagerBuilder authenticationBuilder = new WebSecurityConfigurerAdapter.DefaultPasswordEncoderAuthenticationManagerBuilder( + this.objectPostProcessor, passwordEncoder); authenticationBuilder.parentAuthenticationManager(authenticationManager()); HttpSecurity http = new HttpSecurity(objectPostProcessor, authenticationBuilder, createSharedObjects()); - http - .csrf(withDefaults()) - .addFilter(new WebAsyncManagerIntegrationFilter()) - .exceptionHandling(withDefaults()) - .headers(withDefaults()) - .sessionManagement(withDefaults()) - .securityContext(withDefaults()) - .requestCache(withDefaults()) - .anonymous(withDefaults()) - .servletApi(withDefaults()) - .logout(withDefaults()) - .apply(new DefaultLoginPageConfigurer<>()); + http.csrf(withDefaults()).addFilter(new WebAsyncManagerIntegrationFilter()).exceptionHandling(withDefaults()) + .headers(withDefaults()).sessionManagement(withDefaults()).securityContext(withDefaults()) + .requestCache(withDefaults()).anonymous(withDefaults()).servletApi(withDefaults()) + .logout(withDefaults()).apply(new DefaultLoginPageConfigurer<>()); return http; } @@ -104,7 +97,8 @@ class HttpSecurityConfiguration { private AuthenticationManager authenticationManager() throws Exception { if (this.authenticationManager != null) { return this.authenticationManager; - } else { + } + else { return this.authenticationConfiguration.getAuthenticationManager(); } } @@ -114,4 +108,5 @@ class HttpSecurityConfiguration { sharedObjects.put(ApplicationContext.class, context); return sharedObjects; } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfiguration.java index 892fb394f0..09d5681d9d 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfiguration.java @@ -53,20 +53,25 @@ final class OAuth2ClientConfiguration { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { - boolean webmvcPresent = ClassUtils.isPresent( - "org.springframework.web.servlet.DispatcherServlet", getClass().getClassLoader()); + boolean webmvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", + getClass().getClassLoader()); - return webmvcPresent ? - new String[] { "org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration.OAuth2ClientWebMvcSecurityConfiguration" } : - new String[] {}; + return webmvcPresent ? new String[] { + "org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration.OAuth2ClientWebMvcSecurityConfiguration" } + : new String[] {}; } + } @Configuration(proxyBeanMethods = false) static class OAuth2ClientWebMvcSecurityConfiguration implements WebMvcConfigurer { + private ClientRegistrationRepository clientRegistrationRepository; + private OAuth2AuthorizedClientRepository authorizedClientRepository; + private OAuth2AccessTokenResponseClient accessTokenResponseClient; + private OAuth2AuthorizedClientManager authorizedClientManager; @Override @@ -92,7 +97,8 @@ final class OAuth2ClientConfiguration { } @Autowired(required = false) - void setAccessTokenResponseClient(OAuth2AccessTokenResponseClient accessTokenResponseClient) { + void setAccessTokenResponseClient( + OAuth2AccessTokenResponseClient accessTokenResponseClient) { this.accessTokenResponseClient = accessTokenResponseClient; } @@ -111,25 +117,24 @@ final class OAuth2ClientConfiguration { OAuth2AuthorizedClientManager authorizedClientManager = null; if (this.clientRegistrationRepository != null && this.authorizedClientRepository != null) { if (this.accessTokenResponseClient != null) { - OAuth2AuthorizedClientProvider authorizedClientProvider = - OAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .refreshToken() - .clientCredentials(configurer -> - configurer.accessTokenResponseClient(this.accessTokenResponseClient)) - .password() - .build(); - DefaultOAuth2AuthorizedClientManager defaultAuthorizedClientManager = - new DefaultOAuth2AuthorizedClientManager( - this.clientRegistrationRepository, this.authorizedClientRepository); + OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder + .builder().authorizationCode().refreshToken() + .clientCredentials( + configurer -> configurer.accessTokenResponseClient(this.accessTokenResponseClient)) + .password().build(); + DefaultOAuth2AuthorizedClientManager defaultAuthorizedClientManager = new DefaultOAuth2AuthorizedClientManager( + this.clientRegistrationRepository, this.authorizedClientRepository); defaultAuthorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); authorizedClientManager = defaultAuthorizedClientManager; - } else { + } + else { authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( this.clientRegistrationRepository, this.authorizedClientRepository); } } return authorizedClientManager; } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ImportSelector.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ImportSelector.java index a999d5c7f8..863cf03dca 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ImportSelector.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2ImportSelector.java @@ -26,10 +26,11 @@ import org.springframework.util.ClassUtils; * Used by {@link EnableWebSecurity} to conditionally import: * *
      - *
    • {@link OAuth2ClientConfiguration} when the {@code spring-security-oauth2-client} module is present on the classpath
    • - *
    • {@link SecurityReactorContextConfiguration} when either the {@code spring-security-oauth2-client} or - * {@code spring-security-oauth2-resource-server} module as well as the {@code spring-webflux} module - * are present on the classpath
    • + *
    • {@link OAuth2ClientConfiguration} when the {@code spring-security-oauth2-client} + * module is present on the classpath
    • + *
    • {@link SecurityReactorContextConfiguration} when either the + * {@code spring-security-oauth2-client} or {@code spring-security-oauth2-resource-server} + * module as well as the {@code spring-webflux} module are present on the classpath
    • *
    * * @author Joe Grandja @@ -45,7 +46,8 @@ final class OAuth2ImportSelector implements ImportSelector { Set imports = new LinkedHashSet<>(); boolean oauth2ClientPresent = ClassUtils.isPresent( - "org.springframework.security.oauth2.client.registration.ClientRegistration", getClass().getClassLoader()); + "org.springframework.security.oauth2.client.registration.ClientRegistration", + getClass().getClassLoader()); if (oauth2ClientPresent) { imports.add("org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration"); } @@ -53,15 +55,18 @@ final class OAuth2ImportSelector implements ImportSelector { boolean webfluxPresent = ClassUtils.isPresent( "org.springframework.web.reactive.function.client.ExchangeFilterFunction", getClass().getClassLoader()); if (webfluxPresent && oauth2ClientPresent) { - imports.add("org.springframework.security.config.annotation.web.configuration.SecurityReactorContextConfiguration"); + imports.add( + "org.springframework.security.config.annotation.web.configuration.SecurityReactorContextConfiguration"); } boolean oauth2ResourceServerPresent = ClassUtils.isPresent( "org.springframework.security.oauth2.server.resource.BearerTokenError", getClass().getClassLoader()); if (webfluxPresent && oauth2ResourceServerPresent) { - imports.add("org.springframework.security.config.annotation.web.configuration.SecurityReactorContextConfiguration"); + imports.add( + "org.springframework.security.config.annotation.web.configuration.SecurityReactorContextConfiguration"); } return imports.toArray(new String[0]); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfiguration.java index 8d76982c80..667ca07881 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfiguration.java @@ -41,13 +41,13 @@ import java.util.function.Function; import static org.springframework.security.config.annotation.web.configuration.SecurityReactorContextConfiguration.SecurityReactorContextSubscriber.SECURITY_CONTEXT_ATTRIBUTES; /** - * {@link Configuration} that (potentially) adds a "decorating" {@code Publisher} - * for the last operator created in every {@code Mono} or {@code Flux}. + * {@link Configuration} that (potentially) adds a "decorating" {@code Publisher} for the + * last operator created in every {@code Mono} or {@code Flux}. * *

    - * The {@code Publisher} is solely responsible for adding - * the current {@code HttpServletRequest}, {@code HttpServletResponse} and {@code Authentication} - * to the Reactor {@code Context} so that it's accessible in every flow, if required. + * The {@code Publisher} is solely responsible for adding the current + * {@code HttpServletRequest}, {@code HttpServletResponse} and {@code Authentication} to + * the Reactor {@code Context} so that it's accessible in every flow, if required. * * @author Joe Grandja * @author Roman Matiushchenko @@ -63,12 +63,13 @@ class SecurityReactorContextConfiguration { } static class SecurityReactorContextSubscriberRegistrar implements InitializingBean, DisposableBean { + private static final String SECURITY_REACTOR_CONTEXT_OPERATOR_KEY = "org.springframework.security.SECURITY_REACTOR_CONTEXT_OPERATOR"; @Override public void afterPropertiesSet() throws Exception { - Function, ? extends Publisher> lifter = - Operators.liftPublisher((pub, sub) -> createSubscriberIfNecessary(sub)); + Function, ? extends Publisher> lifter = Operators + .liftPublisher((pub, sub) -> createSubscriberIfNecessary(sub)); Hooks.onLastOperator(SECURITY_REACTOR_CONTEXT_OPERATOR_KEY, pub -> { if (!contextAttributesAvailable()) { @@ -93,8 +94,8 @@ class SecurityReactorContextConfiguration { } private static boolean contextAttributesAvailable() { - return SecurityContextHolder.getContext().getAuthentication() != null || - RequestContextHolder.getRequestAttributes() instanceof ServletRequestAttributes; + return SecurityContextHolder.getContext().getAuthentication() != null + || RequestContextHolder.getRequestAttributes() instanceof ServletRequestAttributes; } private static Map getContextAttributes() { @@ -104,7 +105,7 @@ class SecurityReactorContextConfiguration { if (requestAttributes instanceof ServletRequestAttributes) { ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes; servletRequest = servletRequestAttributes.getRequest(); - servletResponse = servletRequestAttributes.getResponse(); // possible null + servletResponse = servletRequestAttributes.getResponse(); // possible null } Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null && servletRequest == null) { @@ -124,11 +125,15 @@ class SecurityReactorContextConfiguration { return contextAttributes; } + } static class SecurityReactorContextSubscriber implements CoreSubscriber { + static final String SECURITY_CONTEXT_ATTRIBUTES = "org.springframework.security.SECURITY_CONTEXT_ATTRIBUTES"; + private final CoreSubscriber delegate; + private final Context context; SecurityReactorContextSubscriber(CoreSubscriber delegate, Map attributes) { @@ -137,7 +142,8 @@ class SecurityReactorContextConfiguration { Context context; if (currentContext.hasKey(SECURITY_CONTEXT_ATTRIBUTES)) { context = currentContext; - } else { + } + else { context = currentContext.put(SECURITY_CONTEXT_ATTRIBUTES, attributes); } this.context = context; @@ -167,5 +173,7 @@ class SecurityReactorContextConfiguration { public void onComplete() { this.delegate.onComplete(); } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.java index 1516a3e3f0..93aa8279c5 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.java @@ -36,12 +36,12 @@ class SpringWebMvcImportSelector implements ImportSelector { * springframework .core.type.AnnotationMetadata) */ public String[] selectImports(AnnotationMetadata importingClassMetadata) { - boolean webmvcPresent = ClassUtils.isPresent( - "org.springframework.web.servlet.DispatcherServlet", + boolean webmvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", getClass().getClassLoader()); return webmvcPresent ? new String[] { "org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration" } : new String[] {}; } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java index 312a1b170e..10751a034a 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java @@ -35,8 +35,10 @@ import java.util.List; /** * Used to add a {@link RequestDataValueProcessor} for Spring MVC and Spring Security CSRF * integration. This configuration is added whenever {@link EnableWebMvc} is added by - * SpringWebMvcImportSelector and the DispatcherServlet is present on the - * classpath. It also adds the {@link AuthenticationPrincipalArgumentResolver} as a + * SpringWebMvcImportSelector + * and the DispatcherServlet is present on the classpath. It also adds the + * {@link AuthenticationPrincipalArgumentResolver} as a * {@link HandlerMethodArgumentResolver}. * * @author Rob Winch @@ -44,6 +46,7 @@ import java.util.List; * @since 3.2 */ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContextAware { + private BeanResolver beanResolver; @Override @@ -70,4 +73,5 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.beanResolver = new BeanFactoryResolver(applicationContext.getAutowireCapableBeanFactory()); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java index 31e5e9f6ea..dc854bc4d7 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java @@ -49,7 +49,6 @@ import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; - /** * Uses a {@link WebSecurity} to create the {@link FilterChainProxy} that performs the web * based security for Spring Security. It then exports the necessary beans. Customizations @@ -60,13 +59,13 @@ import org.springframework.security.web.context.AbstractSecurityWebApplicationIn * * @see EnableWebSecurity * @see WebSecurity - * * @author Rob Winch * @author Keesun Baik * @since 3.2 */ @Configuration(proxyBeanMethods = false) public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware { + private WebSecurity webSecurity; private Boolean debugEnabled; @@ -98,13 +97,11 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa */ @Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) public Filter springSecurityFilterChain() throws Exception { - boolean hasConfigurers = webSecurityConfigurers != null - && !webSecurityConfigurers.isEmpty(); + boolean hasConfigurers = webSecurityConfigurers != null && !webSecurityConfigurers.isEmpty(); boolean hasFilterChain = !securityFilterChains.isEmpty(); if (hasConfigurers && hasFilterChain) { throw new IllegalStateException( - "Found WebSecurityConfigurerAdapter as well as SecurityFilterChain." + - "Please select just one."); + "Found WebSecurityConfigurerAdapter as well as SecurityFilterChain." + "Please select just one."); } if (!hasConfigurers && !hasFilterChain) { WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor @@ -138,7 +135,6 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa /** * Sets the {@code } * instances used to create the web configuration. - * * @param objectPostProcessor the {@link ObjectPostProcessor} used to create a * {@link WebSecurity} instance * @param webSecurityConfigurers the @@ -147,12 +143,10 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa * @throws Exception */ @Autowired(required = false) - public void setFilterChainProxySecurityConfigurer( - ObjectPostProcessor objectPostProcessor, + public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor objectPostProcessor, @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List> webSecurityConfigurers) throws Exception { - webSecurity = objectPostProcessor - .postProcess(new WebSecurity(objectPostProcessor)); + webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor)); if (debugEnabled != null) { webSecurity.debug(debugEnabled); } @@ -164,10 +158,8 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa for (SecurityConfigurer config : webSecurityConfigurers) { Integer order = AnnotationAwareOrderComparator.lookupOrder(config); if (previousOrder != null && previousOrder.equals(order)) { - throw new IllegalStateException( - "@Order on WebSecurityConfigurers must be unique. Order of " - + order + " was already used on " + previousConfig + ", so it cannot be used on " - + config + " too."); + throw new IllegalStateException("@Order on WebSecurityConfigurers must be unique. Order of " + order + + " was already used on " + previousConfig + ", so it cannot be used on " + config + " too."); } previousOrder = order; previousConfig = config; @@ -204,6 +196,7 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa * @since 3.2 */ private static class AnnotationAwareOrderComparator extends OrderComparator { + private static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator(); @Override @@ -224,6 +217,7 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa } return Ordered.LOWEST_PRECEDENCE; } + } /* @@ -235,8 +229,7 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa public void setImportMetadata(AnnotationMetadata importMetadata) { Map enableWebSecurityAttrMap = importMetadata .getAnnotationAttributes(EnableWebSecurity.class.getName()); - AnnotationAttributes enableWebSecurityAttrs = AnnotationAttributes - .fromMap(enableWebSecurityAttrMap); + AnnotationAttributes enableWebSecurityAttrs = AnnotationAttributes.fromMap(enableWebSecurityAttrMap); debugEnabled = enableWebSecurityAttrs.getBoolean("debug"); if (webSecurity != null) { webSecurity.debug(debugEnabled); @@ -253,4 +246,5 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa public void setBeanClassLoader(ClassLoader classLoader) { this.beanClassLoader = classLoader; } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java index 6f3819549f..1125884f2f 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java @@ -69,31 +69,30 @@ import org.springframework.web.accept.ContentNegotiationStrategy; import org.springframework.web.accept.HeaderContentNegotiationStrategy; /** - * Provides a convenient base class for creating a {@link WebSecurityConfigurer} - * instance. The implementation allows customization by overriding methods. + * Provides a convenient base class for creating a {@link WebSecurityConfigurer} instance. + * The implementation allows customization by overriding methods. * *

    - * Will automatically apply the result of looking up - * {@link AbstractHttpConfigurer} from {@link SpringFactoriesLoader} to allow - * developers to extend the defaults. - * To do this, you must create a class that extends AbstractHttpConfigurer and then create a file in the classpath at "META-INF/spring.factories" that looks something like: + * Will automatically apply the result of looking up {@link AbstractHttpConfigurer} from + * {@link SpringFactoriesLoader} to allow developers to extend the defaults. To do this, + * you must create a class that extends AbstractHttpConfigurer and then create a file in + * the classpath at "META-INF/spring.factories" that looks something like: *

    *
      * org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyClassThatExtendsAbstractHttpConfigurer
    - * 
    - * If you have multiple classes that should be added you can use "," to separate the values. For example: + * If you have multiple classes that should be added you can use "," to separate + * the values. For example: * *
      * org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyClassThatExtendsAbstractHttpConfigurer, sample.OtherThatExtendsAbstractHttpConfigurer
      * 
    * * @see EnableWebSecurity - * * @author Rob Winch */ @Order(100) -public abstract class WebSecurityConfigurerAdapter implements - WebSecurityConfigurer { +public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigurer { + private final Log logger = LogFactory.getLog(WebSecurityConfigurerAdapter.class); private ApplicationContext context; @@ -102,20 +101,27 @@ public abstract class WebSecurityConfigurerAdapter implements private ObjectPostProcessor objectPostProcessor = new ObjectPostProcessor() { public T postProcess(T object) { - throw new IllegalStateException( - ObjectPostProcessor.class.getName() - + " is a required bean. Ensure you have used @EnableWebSecurity and @Configuration"); + throw new IllegalStateException(ObjectPostProcessor.class.getName() + + " is a required bean. Ensure you have used @EnableWebSecurity and @Configuration"); } }; private AuthenticationConfiguration authenticationConfiguration; + private AuthenticationManagerBuilder authenticationBuilder; + private AuthenticationManagerBuilder localConfigureAuthenticationBldr; + private boolean disableLocalConfigureAuthenticationBldr; + private boolean authenticationManagerInitialized; + private AuthenticationManager authenticationManager; + private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); + private HttpSecurity http; + private boolean disableDefaults; /** @@ -129,7 +135,6 @@ public abstract class WebSecurityConfigurerAdapter implements * Creates an instance which allows specifying if the default configuration should be * enabled. Disabling the default configuration should be considered more advanced * usage as it requires more understanding of how the framework is implemented. - * * @param disableDefaults true if the default configuration should be disabled, else * false */ @@ -176,7 +181,6 @@ public abstract class WebSecurityConfigurerAdapter implements * } * * - * * @param auth the {@link AuthenticationManagerBuilder} to use * @throws Exception */ @@ -186,7 +190,6 @@ public abstract class WebSecurityConfigurerAdapter implements /** * Creates the {@link HttpSecurity} or returns the current instance - * * @return the {@link HttpSecurity} * @throws Exception */ @@ -203,8 +206,7 @@ public abstract class WebSecurityConfigurerAdapter implements authenticationBuilder.parentAuthenticationManager(authenticationManager); Map, Object> sharedObjects = createSharedObjects(); - http = new HttpSecurity(objectPostProcessor, authenticationBuilder, - sharedObjects); + http = new HttpSecurity(objectPostProcessor, authenticationBuilder, sharedObjects); if (!disableDefaults) { // @formatter:off http @@ -221,8 +223,8 @@ public abstract class WebSecurityConfigurerAdapter implements .logout(); // @formatter:on ClassLoader classLoader = this.context.getClassLoader(); - List defaultHttpConfigurers = - SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader); + List defaultHttpConfigurers = SpringFactoriesLoader + .loadFactories(AbstractHttpConfigurer.class, classLoader); for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) { http.apply(configurer); @@ -244,7 +246,6 @@ public abstract class WebSecurityConfigurerAdapter implements * return super.authenticationManagerBean(); * } * - * * @return the {@link AuthenticationManager} * @throws Exception */ @@ -257,7 +258,6 @@ public abstract class WebSecurityConfigurerAdapter implements * {@link #configure(AuthenticationManagerBuilder)} method is overridden to use the * {@link AuthenticationManagerBuilder} that was passed in. Otherwise, autowire the * {@link AuthenticationManager} by type. - * * @return the {@link AuthenticationManager} to use * @throws Exception */ @@ -265,8 +265,7 @@ public abstract class WebSecurityConfigurerAdapter implements if (!authenticationManagerInitialized) { configure(localConfigureAuthenticationBldr); if (disableLocalConfigureAuthenticationBldr) { - authenticationManager = authenticationConfiguration - .getAuthenticationManager(); + authenticationManager = authenticationConfiguration.getAuthenticationManager(); } else { authenticationManager = localConfigureAuthenticationBldr.build(); @@ -297,10 +296,8 @@ public abstract class WebSecurityConfigurerAdapter implements * @see #userDetailsService() */ public UserDetailsService userDetailsServiceBean() throws Exception { - AuthenticationManagerBuilder globalAuthBuilder = context - .getBean(AuthenticationManagerBuilder.class); - return new UserDetailsServiceDelegator(Arrays.asList( - localConfigureAuthenticationBldr, globalAuthBuilder)); + AuthenticationManagerBuilder globalAuthBuilder = context.getBean(AuthenticationManagerBuilder.class); + return new UserDetailsServiceDelegator(Arrays.asList(localConfigureAuthenticationBldr, globalAuthBuilder)); } /** @@ -308,21 +305,17 @@ public abstract class WebSecurityConfigurerAdapter implements * {@link #userDetailsServiceBean()} without interacting with the * {@link ApplicationContext}. Developers should override this method when changing * the instance of {@link #userDetailsServiceBean()}. - * * @return the {@link UserDetailsService} to use */ protected UserDetailsService userDetailsService() { - AuthenticationManagerBuilder globalAuthBuilder = context - .getBean(AuthenticationManagerBuilder.class); - return new UserDetailsServiceDelegator(Arrays.asList( - localConfigureAuthenticationBldr, globalAuthBuilder)); + AuthenticationManagerBuilder globalAuthBuilder = context.getBean(AuthenticationManagerBuilder.class); + return new UserDetailsServiceDelegator(Arrays.asList(localConfigureAuthenticationBldr, globalAuthBuilder)); } public void init(final WebSecurity web) throws Exception { final HttpSecurity http = getHttp(); web.addSecurityFilterChainBuilder(http).postBuildAction(() -> { - FilterSecurityInterceptor securityInterceptor = http - .getSharedObject(FilterSecurityInterceptor.class); + FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class); web.securityInterceptor(securityInterceptor); }); } @@ -350,15 +343,15 @@ public abstract class WebSecurityConfigurerAdapter implements * http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic(); * * - * Any endpoint that requires defense against common vulnerabilities can be specified here, including public ones. - * See {@link HttpSecurity#authorizeRequests} and the `permitAll()` authorization rule - * for more details on public endpoints. - * + * Any endpoint that requires defense against common vulnerabilities can be specified + * here, including public ones. See {@link HttpSecurity#authorizeRequests} and the + * `permitAll()` authorization rule for more details on public endpoints. * @param http the {@link HttpSecurity} to modify * @throws Exception if an error occurs */ protected void configure(HttpSecurity http) throws Exception { - logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity)."); + logger.debug( + "Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity)."); // @formatter:off http @@ -385,8 +378,10 @@ public abstract class WebSecurityConfigurerAdapter implements ObjectPostProcessor objectPostProcessor = context.getBean(ObjectPostProcessor.class); LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(context); - authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, passwordEncoder); - localConfigureAuthenticationBldr = new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, passwordEncoder) { + authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, + passwordEncoder); + localConfigureAuthenticationBldr = new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, + passwordEncoder) { @Override public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) { authenticationBuilder.eraseCredentials(eraseCredentials); @@ -394,7 +389,8 @@ public abstract class WebSecurityConfigurerAdapter implements } @Override - public AuthenticationManagerBuilder authenticationEventPublisher(AuthenticationEventPublisher eventPublisher) { + public AuthenticationManagerBuilder authenticationEventPublisher( + AuthenticationEventPublisher eventPublisher) { authenticationBuilder.authenticationEventPublisher(eventPublisher); return super.authenticationEventPublisher(eventPublisher); } @@ -407,8 +403,7 @@ public abstract class WebSecurityConfigurerAdapter implements } @Autowired(required = false) - public void setContentNegotationStrategy( - ContentNegotiationStrategy contentNegotiationStrategy) { + public void setContentNegotationStrategy(ContentNegotiationStrategy contentNegotiationStrategy) { this.contentNegotiationStrategy = contentNegotiationStrategy; } @@ -418,8 +413,7 @@ public abstract class WebSecurityConfigurerAdapter implements } @Autowired - public void setAuthenticationConfiguration( - AuthenticationConfiguration authenticationConfiguration) { + public void setAuthenticationConfiguration(AuthenticationConfiguration authenticationConfiguration) { this.authenticationConfiguration = authenticationConfiguration; } @@ -432,7 +426,6 @@ public abstract class WebSecurityConfigurerAdapter implements /** * Creates the shared objects - * * @return the shared Objects */ private Map, Object> createSharedObjects() { @@ -453,21 +446,22 @@ public abstract class WebSecurityConfigurerAdapter implements * @since 3.2 */ static final class UserDetailsServiceDelegator implements UserDetailsService { + private List delegateBuilders; + private UserDetailsService delegate; + private final Object delegateMonitor = new Object(); UserDetailsServiceDelegator(List delegateBuilders) { if (delegateBuilders.contains(null)) { throw new IllegalArgumentException( - "delegateBuilders cannot contain null values. Got " - + delegateBuilders); + "delegateBuilders cannot contain null values. Got " + delegateBuilders); } this.delegateBuilders = delegateBuilders; } - public UserDetails loadUserByUsername(String username) - throws UsernameNotFoundException { + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { if (delegate != null) { return delegate.loadUserByUsername(username); } @@ -490,6 +484,7 @@ public abstract class WebSecurityConfigurerAdapter implements return delegate.loadUserByUsername(username); } + } /** @@ -500,26 +495,26 @@ public abstract class WebSecurityConfigurerAdapter implements * @since 3.2 */ static final class AuthenticationManagerDelegator implements AuthenticationManager { + private AuthenticationManagerBuilder delegateBuilder; + private AuthenticationManager delegate; + private final Object delegateMonitor = new Object(); + private Set beanNames; - AuthenticationManagerDelegator(AuthenticationManagerBuilder delegateBuilder, - ApplicationContext context) { + AuthenticationManagerDelegator(AuthenticationManagerBuilder delegateBuilder, ApplicationContext context) { Assert.notNull(delegateBuilder, "delegateBuilder cannot be null"); - Field parentAuthMgrField = ReflectionUtils.findField( - AuthenticationManagerBuilder.class, "parentAuthenticationManager"); + Field parentAuthMgrField = ReflectionUtils.findField(AuthenticationManagerBuilder.class, + "parentAuthenticationManager"); ReflectionUtils.makeAccessible(parentAuthMgrField); beanNames = getAuthenticationManagerBeanNames(context); - validateBeanCycle( - ReflectionUtils.getField(parentAuthMgrField, delegateBuilder), - beanNames); + validateBeanCycle(ReflectionUtils.getField(parentAuthMgrField, delegateBuilder), beanNames); this.delegateBuilder = delegateBuilder; } - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (delegate != null) { return delegate.authenticate(authentication); } @@ -534,11 +529,9 @@ public abstract class WebSecurityConfigurerAdapter implements return delegate.authenticate(authentication); } - private static Set getAuthenticationManagerBeanNames( - ApplicationContext applicationContext) { - String[] beanNamesForType = BeanFactoryUtils - .beanNamesForTypeIncludingAncestors(applicationContext, - AuthenticationManager.class); + private static Set getAuthenticationManagerBeanNames(ApplicationContext applicationContext) { + String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, + AuthenticationManager.class); return new HashSet<>(Arrays.asList(beanNamesForType)); } @@ -558,46 +551,46 @@ public abstract class WebSecurityConfigurerAdapter implements beanNames = Collections.emptySet(); } } + } static class DefaultPasswordEncoderAuthenticationManagerBuilder extends AuthenticationManagerBuilder { + private PasswordEncoder defaultPasswordEncoder; /** * Creates a new instance - * * @param objectPostProcessor the {@link ObjectPostProcessor} instance to use. */ - DefaultPasswordEncoderAuthenticationManagerBuilder( - ObjectPostProcessor objectPostProcessor, PasswordEncoder defaultPasswordEncoder) { + DefaultPasswordEncoderAuthenticationManagerBuilder(ObjectPostProcessor objectPostProcessor, + PasswordEncoder defaultPasswordEncoder) { super(objectPostProcessor); this.defaultPasswordEncoder = defaultPasswordEncoder; } @Override public InMemoryUserDetailsManagerConfigurer inMemoryAuthentication() - throws Exception { - return super.inMemoryAuthentication() - .passwordEncoder(this.defaultPasswordEncoder); + throws Exception { + return super.inMemoryAuthentication().passwordEncoder(this.defaultPasswordEncoder); } @Override - public JdbcUserDetailsManagerConfigurer jdbcAuthentication() - throws Exception { - return super.jdbcAuthentication() - .passwordEncoder(this.defaultPasswordEncoder); + public JdbcUserDetailsManagerConfigurer jdbcAuthentication() throws Exception { + return super.jdbcAuthentication().passwordEncoder(this.defaultPasswordEncoder); } @Override public DaoAuthenticationConfigurer userDetailsService( - T userDetailsService) throws Exception { - return super.userDetailsService(userDetailsService) - .passwordEncoder(this.defaultPasswordEncoder); + T userDetailsService) throws Exception { + return super.userDetailsService(userDetailsService).passwordEncoder(this.defaultPasswordEncoder); } + } static class LazyPasswordEncoder implements PasswordEncoder { + private ApplicationContext applicationContext; + private PasswordEncoder passwordEncoder; LazyPasswordEncoder(ApplicationContext applicationContext) { @@ -610,8 +603,7 @@ public abstract class WebSecurityConfigurerAdapter implements } @Override - public boolean matches(CharSequence rawPassword, - String encodedPassword) { + public boolean matches(CharSequence rawPassword, String encodedPassword) { return getPasswordEncoder().matches(rawPassword, encodedPassword); } @@ -635,7 +627,8 @@ public abstract class WebSecurityConfigurerAdapter implements private T getBeanOrNull(Class type) { try { return this.applicationContext.getBean(type); - } catch(NoSuchBeanDefinitionException notFound) { + } + catch (NoSuchBeanDefinitionException notFound) { return null; } } @@ -644,5 +637,7 @@ public abstract class WebSecurityConfigurerAdapter implements public String toString() { return getPasswordEncoder().toString(); } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractAuthenticationFilterConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractAuthenticationFilterConfigurer.java index 0dfd232009..d9180e5c86 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractAuthenticationFilterConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractAuthenticationFilterConfigurer.java @@ -51,11 +51,9 @@ import java.util.Collections; * * @see FormLoginConfigurer * @see OpenIDLoginConfigurer - * * @param T refers to "this" for returning the current configurer * @param F refers to the {@link AbstractAuthenticationProcessingFilter} that is being * built - * * @author Rob Winch * @since 3.2 */ @@ -67,12 +65,15 @@ public abstract class AbstractAuthenticationFilterConfigurer authenticationDetailsSource; private SavedRequestAwareAuthenticationSuccessHandler defaultSuccessHandler = new SavedRequestAwareAuthenticationSuccessHandler(); + private AuthenticationSuccessHandler successHandler = this.defaultSuccessHandler; private LoginUrlAuthenticationEntryPoint authenticationEntryPoint; private boolean customLoginPage; + private String loginPage; + private String loginProcessingUrl; private AuthenticationFailureHandler failureHandler; @@ -95,8 +96,7 @@ public abstract class AbstractAuthenticationFilterConfigurer exceptionHandling = http - .getConfigurer(ExceptionHandlingConfigurer.class); + ExceptionHandlingConfigurer exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class); if (exceptionHandling == null) { return; } - exceptionHandling.defaultAuthenticationEntryPointFor( - postProcess(authenticationEntryPoint), getAuthenticationEntryPointMatcher(http)); + exceptionHandling.defaultAuthenticationEntryPointFor(postProcess(authenticationEntryPoint), + getAuthenticationEntryPointMatcher(http)); } protected final RequestMatcher getAuthenticationEntryPointMatcher(B http) { - ContentNegotiationStrategy contentNegotiationStrategy = http - .getSharedObject(ContentNegotiationStrategy.class); + ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class); if (contentNegotiationStrategy == null) { contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); } - MediaTypeRequestMatcher mediaMatcher = new MediaTypeRequestMatcher( - contentNegotiationStrategy, MediaType.APPLICATION_XHTML_XML, - new MediaType("image", "*"), MediaType.TEXT_HTML, MediaType.TEXT_PLAIN); + MediaTypeRequestMatcher mediaMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, + MediaType.APPLICATION_XHTML_XML, new MediaType("image", "*"), MediaType.TEXT_HTML, + MediaType.TEXT_PLAIN); mediaMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); RequestMatcher notXRequestedWith = new NegatedRequestMatcher( @@ -288,8 +275,7 @@ public abstract class AbstractAuthenticationFilterConfigurer logoutConfigurer = getBuilder().getConfigurer( - LogoutConfigurer.class); + final LogoutConfigurer logoutConfigurer = getBuilder().getConfigurer(LogoutConfigurer.class); if (logoutConfigurer != null && !logoutConfigurer.isCustomLogoutSuccess()) { logoutConfigurer.logoutSuccessUrl(loginPage + "?logout"); } @@ -434,4 +410,5 @@ public abstract class AbstractAuthenticationFilterConfigurer The object that is returned or Chained after creating the RequestMatcher - * * @see ChannelSecurityConfigurer * @see UrlAuthorizationConfigurer * @see ExpressionUrlAuthorizationConfigurer */ -public abstract class AbstractConfigAttributeRequestMatcherRegistry extends - AbstractRequestMatcherRegistry { +public abstract class AbstractConfigAttributeRequestMatcherRegistry extends AbstractRequestMatcherRegistry { + private List urlMappings = new ArrayList<>(); + private List unmappedMatchers; /** * Gets the {@link UrlMapping} added by subclasses in * {@link #chainRequestMatchers(java.util.List)}. May be empty. - * * @return the {@link UrlMapping} added by subclasses in * {@link #chainRequestMatchers(java.util.List)} */ @@ -57,7 +55,6 @@ public abstract class AbstractConfigAttributeRequestMatcherRegistry extends * Adds a {@link UrlMapping} added by subclasses in * {@link #chainRequestMatchers(java.util.List)} and resets the unmapped * {@link RequestMatcher}'s. - * * @param urlMapping {@link UrlMapping} the mapping to add */ final void addMapping(UrlMapping urlMapping) { @@ -68,7 +65,6 @@ public abstract class AbstractConfigAttributeRequestMatcherRegistry extends /** * Marks the {@link RequestMatcher}'s as unmapped and then calls * {@link #chainRequestMatchersInternal(List)}. - * * @param requestMatchers the {@link RequestMatcher} instances that were created * @return the chained Object for the subclass which allows association of something * else to the {@link RequestMatcher} @@ -81,7 +77,6 @@ public abstract class AbstractConfigAttributeRequestMatcherRegistry extends /** * Subclasses should implement this method for returning the object that is chained to * the creation of the {@link RequestMatcher} instances. - * * @param requestMatchers the {@link RequestMatcher} instances that were created * @return the chained Object for the subclass which allows association of something * else to the {@link RequestMatcher} @@ -91,7 +86,6 @@ public abstract class AbstractConfigAttributeRequestMatcherRegistry extends /** * Adds a {@link UrlMapping} added by subclasses in * {@link #chainRequestMatchers(java.util.List)} at a particular index. - * * @param index the index to add a {@link UrlMapping} * @param urlMapping {@link UrlMapping} the mapping to add */ @@ -102,16 +96,13 @@ public abstract class AbstractConfigAttributeRequestMatcherRegistry extends /** * Creates the mapping of {@link RequestMatcher} to {@link Collection} of * {@link ConfigAttribute} instances - * * @return the mapping of {@link RequestMatcher} to {@link Collection} of * {@link ConfigAttribute} instances. Cannot be null. */ final LinkedHashMap> createRequestMap() { if (unmappedMatchers != null) { - throw new IllegalStateException( - "An incomplete mapping was found for " - + unmappedMatchers - + ". Try completing it with something like requestUrls()..hasRole('USER')"); + throw new IllegalStateException("An incomplete mapping was found for " + unmappedMatchers + + ". Try completing it with something like requestUrls()..hasRole('USER')"); } LinkedHashMap> requestMap = new LinkedHashMap<>(); @@ -128,7 +119,9 @@ public abstract class AbstractConfigAttributeRequestMatcherRegistry extends * {@link ConfigAttribute} instances */ static final class UrlMapping { + private RequestMatcher requestMatcher; + private Collection configAttrs; UrlMapping(RequestMatcher requestMatcher, Collection configAttrs) { @@ -143,5 +136,7 @@ public abstract class AbstractConfigAttributeRequestMatcherRegistry extends public Collection getConfigAttrs() { return configAttrs; } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java index 18c26b4236..7becadfb84 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractHttpConfigurer.java @@ -35,7 +35,6 @@ public abstract class AbstractHttpConfigurer - *
  • - * {@link AuthenticationManager} - *
  • + *
  • {@link AuthenticationManager}
  • * * - * * @param the AbstractInterceptUrlConfigurer * @param the type of {@link HttpSecurityBuilder} that is being configured - * * @author Rob Winch * @since 3.2 * @see ExpressionUrlAuthorizationConfigurer @@ -66,6 +62,7 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept */ abstract class AbstractInterceptUrlConfigurer, H extends HttpSecurityBuilder> extends AbstractHttpConfigurer { + private Boolean filterSecurityInterceptorOncePerRequest; private AccessDecisionManager accessDecisionManager; @@ -76,11 +73,10 @@ abstract class AbstractInterceptUrlConfigurer> extends - AbstractHttpConfigurer, H> { +public final class AnonymousConfigurer> + extends AbstractHttpConfigurer, H> { + private String key; + private AuthenticationProvider authenticationProvider; + private AnonymousAuthenticationFilter authenticationFilter; + private Object principal = "anonymousUser"; - private List authorities = AuthorityUtils - .createAuthorityList("ROLE_ANONYMOUS"); + + private List authorities = AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"); /** * Creates a new instance @@ -58,7 +62,6 @@ public final class AnonymousConfigurer> extends /** * Sets the key to identify tokens created for anonymous authentication. Default is a * secure randomly generated key. - * * @param key the key to identify tokens created for anonymous authentication. Default * is a secure randomly generated key. * @return the {@link AnonymousConfigurer} for further customization of anonymous @@ -71,7 +74,6 @@ public final class AnonymousConfigurer> extends /** * Sets the principal for {@link Authentication} objects of anonymous users - * * @param principal used for the {@link Authentication} object of anonymous users * @return the {@link AnonymousConfigurer} for further customization of anonymous * authentication @@ -84,7 +86,6 @@ public final class AnonymousConfigurer> extends /** * Sets the {@link org.springframework.security.core.Authentication#getAuthorities()} * for anonymous users - * * @param authorities Sets the * {@link org.springframework.security.core.Authentication#getAuthorities()} for * anonymous users @@ -99,7 +100,6 @@ public final class AnonymousConfigurer> extends /** * Sets the {@link org.springframework.security.core.Authentication#getAuthorities()} * for anonymous users - * * @param authorities Sets the * {@link org.springframework.security.core.Authentication#getAuthorities()} for * anonymous users (i.e. "ROLE_ANONYMOUS") @@ -114,15 +114,12 @@ public final class AnonymousConfigurer> extends * Sets the {@link AuthenticationProvider} used to validate an anonymous user. If this * is set, no attributes on the {@link AnonymousConfigurer} will be set on the * {@link AuthenticationProvider}. - * * @param authenticationProvider the {@link AuthenticationProvider} used to validate * an anonymous user. Default is {@link AnonymousAuthenticationProvider} - * * @return the {@link AnonymousConfigurer} for further customization of anonymous * authentication */ - public AnonymousConfigurer authenticationProvider( - AuthenticationProvider authenticationProvider) { + public AnonymousConfigurer authenticationProvider(AuthenticationProvider authenticationProvider) { this.authenticationProvider = authenticationProvider; return this; } @@ -131,15 +128,12 @@ public final class AnonymousConfigurer> extends * Sets the {@link AnonymousAuthenticationFilter} used to populate an anonymous user. * If this is set, no attributes on the {@link AnonymousConfigurer} will be set on the * {@link AnonymousAuthenticationFilter}. - * * @param authenticationFilter the {@link AnonymousAuthenticationFilter} used to * populate an anonymous user. - * * @return the {@link AnonymousConfigurer} for further customization of anonymous * authentication */ - public AnonymousConfigurer authenticationFilter( - AnonymousAuthenticationFilter authenticationFilter) { + public AnonymousConfigurer authenticationFilter(AnonymousAuthenticationFilter authenticationFilter) { this.authenticationFilter = authenticationFilter; return this; } @@ -150,8 +144,7 @@ public final class AnonymousConfigurer> extends authenticationProvider = new AnonymousAuthenticationProvider(getKey()); } if (authenticationFilter == null) { - authenticationFilter = new AnonymousAuthenticationFilter(getKey(), principal, - authorities); + authenticationFilter = new AnonymousAuthenticationFilter(getKey(), principal, authorities); } authenticationProvider = postProcess(authenticationProvider); http.authenticationProvider(authenticationProvider); @@ -169,4 +162,5 @@ public final class AnonymousConfigurer> extends } return key; } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java index 1d3b99b5ef..6e32cbec24 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java @@ -73,14 +73,16 @@ import org.springframework.security.web.util.matcher.RequestMatcher; * * * @param the type of {@link HttpSecurityBuilder} that is being configured - * * @author Rob Winch * @since 3.2 */ -public final class ChannelSecurityConfigurer> extends - AbstractHttpConfigurer, H> { +public final class ChannelSecurityConfigurer> + extends AbstractHttpConfigurer, H> { + private ChannelProcessingFilter channelFilter = new ChannelProcessingFilter(); + private LinkedHashMap> requestMap = new LinkedHashMap<>(); + private List channelProcessors; private final ChannelRequestMatcherRegistry REGISTRY; @@ -133,15 +135,12 @@ public final class ChannelSecurityConfigurer> e } insecureChannelProcessor = postProcess(insecureChannelProcessor); secureChannelProcessor = postProcess(secureChannelProcessor); - return Arrays. asList(insecureChannelProcessor, - secureChannelProcessor); + return Arrays.asList(insecureChannelProcessor, secureChannelProcessor); } - private ChannelRequestMatcherRegistry addAttribute(String attribute, - List matchers) { + private ChannelRequestMatcherRegistry addAttribute(String attribute, List matchers) { for (RequestMatcher matcher : matchers) { - Collection attrs = Arrays - . asList(new SecurityConfig(attribute)); + Collection attrs = Arrays.asList(new SecurityConfig(attribute)); requestMap.put(matcher, attrs); } return REGISTRY; @@ -155,8 +154,7 @@ public final class ChannelSecurityConfigurer> e } @Override - public MvcMatchersRequiresChannelUrl mvcMatchers(HttpMethod method, - String... mvcPatterns) { + public MvcMatchersRequiresChannelUrl mvcMatchers(HttpMethod method, String... mvcPatterns) { List mvcMatchers = createMvcMatchers(method, mvcPatterns); return new MvcMatchersRequiresChannelUrl(mvcMatchers); } @@ -167,19 +165,16 @@ public final class ChannelSecurityConfigurer> e } @Override - protected RequiresChannelUrl chainRequestMatchersInternal( - List requestMatchers) { + protected RequiresChannelUrl chainRequestMatchersInternal(List requestMatchers) { return new RequiresChannelUrl(requestMatchers); } /** * Adds an {@link ObjectPostProcessor} for this class. - * * @param objectPostProcessor * @return the {@link ChannelSecurityConfigurer} for further customizations */ - public ChannelRequestMatcherRegistry withObjectPostProcessor( - ObjectPostProcessor objectPostProcessor) { + public ChannelRequestMatcherRegistry withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { addObjectPostProcessor(objectPostProcessor); return this; } @@ -190,8 +185,7 @@ public final class ChannelSecurityConfigurer> e * @param channelProcessors * @return the {@link ChannelSecurityConfigurer} for further customizations */ - public ChannelRequestMatcherRegistry channelProcessors( - List channelProcessors) { + public ChannelRequestMatcherRegistry channelProcessors(List channelProcessors) { ChannelSecurityConfigurer.this.channelProcessors = channelProcessors; return this; } @@ -199,12 +193,12 @@ public final class ChannelSecurityConfigurer> e /** * Return the {@link SecurityBuilder} when done using the * {@link SecurityConfigurer}. This is useful for method chaining. - * * @return the type of {@link HttpSecurityBuilder} that is being configured */ public H and() { return ChannelSecurityConfigurer.this.and(); } + } public final class MvcMatchersRequiresChannelUrl extends RequiresChannelUrl { @@ -219,9 +213,11 @@ public final class ChannelSecurityConfigurer> e } return this; } + } public class RequiresChannelUrl { + protected List requestMatchers; private RequiresChannelUrl(List requestMatchers) { @@ -239,5 +235,7 @@ public final class ChannelSecurityConfigurer> e public ChannelRequestMatcherRegistry requires(String attribute) { return addAttribute(attribute, requestMatchers); } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurer.java index 449061d49f..ccf9aa26ee 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurer.java @@ -36,11 +36,12 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector; * @author Rob Winch * @since 4.1.1 */ -public class CorsConfigurer> - extends AbstractHttpConfigurer, H> { +public class CorsConfigurer> extends AbstractHttpConfigurer, H> { private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"; + private static final String CORS_CONFIGURATION_SOURCE_BEAN_NAME = "corsConfigurationSource"; + private static final String CORS_FILTER_BEAN_NAME = "corsFilter"; private CorsConfigurationSource configurationSource; @@ -53,8 +54,7 @@ public class CorsConfigurer> public CorsConfigurer() { } - public CorsConfigurer configurationSource( - CorsConfigurationSource configurationSource) { + public CorsConfigurer configurationSource(CorsConfigurationSource configurationSource) { this.configurationSource = configurationSource; return this; } @@ -65,9 +65,8 @@ public class CorsConfigurer> CorsFilter corsFilter = getCorsFilter(context); if (corsFilter == null) { - throw new IllegalStateException( - "Please configure either a " + CORS_FILTER_BEAN_NAME + " bean or a " - + CORS_CONFIGURATION_SOURCE_BEAN_NAME + "bean."); + throw new IllegalStateException("Please configure either a " + CORS_FILTER_BEAN_NAME + " bean or a " + + CORS_CONFIGURATION_SOURCE_BEAN_NAME + "bean."); } http.addFilter(corsFilter); } @@ -77,31 +76,29 @@ public class CorsConfigurer> return new CorsFilter(this.configurationSource); } - boolean containsCorsFilter = context - .containsBeanDefinition(CORS_FILTER_BEAN_NAME); + boolean containsCorsFilter = context.containsBeanDefinition(CORS_FILTER_BEAN_NAME); if (containsCorsFilter) { return context.getBean(CORS_FILTER_BEAN_NAME, CorsFilter.class); } - boolean containsCorsSource = context - .containsBean(CORS_CONFIGURATION_SOURCE_BEAN_NAME); + boolean containsCorsSource = context.containsBean(CORS_CONFIGURATION_SOURCE_BEAN_NAME); if (containsCorsSource) { - CorsConfigurationSource configurationSource = context.getBean( - CORS_CONFIGURATION_SOURCE_BEAN_NAME, CorsConfigurationSource.class); + CorsConfigurationSource configurationSource = context.getBean(CORS_CONFIGURATION_SOURCE_BEAN_NAME, + CorsConfigurationSource.class); return new CorsFilter(configurationSource); } - boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, - context.getClassLoader()); + boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, context.getClassLoader()); if (mvcPresent) { return MvcCorsFilter.getMvcCorsFilter(context); } return null; } - static class MvcCorsFilter { + private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"; + /** * This needs to be isolated into a separate class as Spring MVC is an optional * dependency and will potentially cause ClassLoading issues @@ -110,11 +107,16 @@ public class CorsConfigurer> */ private static CorsFilter getMvcCorsFilter(ApplicationContext context) { if (!context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) { - throw new NoSuchBeanDefinitionException(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, "A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME +" of type " + HandlerMappingIntrospector.class.getName() + throw new NoSuchBeanDefinitionException(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, "A Bean named " + + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + " of type " + + HandlerMappingIntrospector.class.getName() + " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext."); } - HandlerMappingIntrospector mappingIntrospector = context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector.class); + HandlerMappingIntrospector mappingIntrospector = context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, + HandlerMappingIntrospector.class); return new CorsFilter(mappingIntrospector); } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java index 33b34bcef5..5c2e4be582 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java @@ -78,11 +78,15 @@ import org.springframework.util.Assert; */ public final class CsrfConfigurer> extends AbstractHttpConfigurer, H> { - private CsrfTokenRepository csrfTokenRepository = new LazyCsrfTokenRepository( - new HttpSessionCsrfTokenRepository()); + + private CsrfTokenRepository csrfTokenRepository = new LazyCsrfTokenRepository(new HttpSessionCsrfTokenRepository()); + private RequestMatcher requireCsrfProtectionMatcher = CsrfFilter.DEFAULT_CSRF_MATCHER; + private List ignoredCsrfProtectionMatchers = new ArrayList<>(); + private SessionAuthenticationStrategy sessionAuthenticationStrategy; + private final ApplicationContext context; /** @@ -96,12 +100,10 @@ public final class CsrfConfigurer> /** * Specify the {@link CsrfTokenRepository} to use. The default is an * {@link HttpSessionCsrfTokenRepository} wrapped by {@link LazyCsrfTokenRepository}. - * * @param csrfTokenRepository the {@link CsrfTokenRepository} to use * @return the {@link CsrfConfigurer} for further customizations */ - public CsrfConfigurer csrfTokenRepository( - CsrfTokenRepository csrfTokenRepository) { + public CsrfConfigurer csrfTokenRepository(CsrfTokenRepository csrfTokenRepository) { Assert.notNull(csrfTokenRepository, "csrfTokenRepository cannot be null"); this.csrfTokenRepository = csrfTokenRepository; return this; @@ -111,14 +113,11 @@ public final class CsrfConfigurer> * Specify the {@link RequestMatcher} to use for determining when CSRF should be * applied. The default is to ignore GET, HEAD, TRACE, OPTIONS and process all other * requests. - * * @param requireCsrfProtectionMatcher the {@link RequestMatcher} to use * @return the {@link CsrfConfigurer} for further customizations */ - public CsrfConfigurer requireCsrfProtectionMatcher( - RequestMatcher requireCsrfProtectionMatcher) { - Assert.notNull(requireCsrfProtectionMatcher, - "requireCsrfProtectionMatcher cannot be null"); + public CsrfConfigurer requireCsrfProtectionMatcher(RequestMatcher requireCsrfProtectionMatcher) { + Assert.notNull(requireCsrfProtectionMatcher, "requireCsrfProtectionMatcher cannot be null"); this.requireCsrfProtectionMatcher = requireCsrfProtectionMatcher; return this; } @@ -148,8 +147,7 @@ public final class CsrfConfigurer> * @since 4.0 */ public CsrfConfigurer ignoringAntMatchers(String... antPatterns) { - return new IgnoreCsrfProtectionRegistry(this.context).antMatchers(antPatterns) - .and(); + return new IgnoreCsrfProtectionRegistry(this.context).antMatchers(antPatterns).and(); } /** @@ -163,7 +161,8 @@ public final class CsrfConfigurer> *

    *
      *
    • Any GET, HEAD, TRACE, OPTIONS (this is the default)
    • - *
    • We also explicitly state to ignore any request that has a "X-Requested-With: XMLHttpRequest" header
    • + *
    • We also explicitly state to ignore any request that has a "X-Requested-With: + * XMLHttpRequest" header
    • *
    * *
    @@ -177,8 +176,7 @@ public final class CsrfConfigurer>
     	 * @since 5.1
     	 */
     	public CsrfConfigurer ignoringRequestMatchers(RequestMatcher... requestMatchers) {
    -		return new IgnoreCsrfProtectionRegistry(this.context).requestMatchers(requestMatchers)
    -				.and();
    +		return new IgnoreCsrfProtectionRegistry(this.context).requestMatchers(requestMatchers).and();
     	}
     
     	/**
    @@ -189,14 +187,13 @@ public final class CsrfConfigurer>
     	 *
     	 * @author Michael Vitz
     	 * @since 5.2
    -	 *
    -	 * @param sessionAuthenticationStrategy the {@link SessionAuthenticationStrategy} to use
    +	 * @param sessionAuthenticationStrategy the {@link SessionAuthenticationStrategy} to
    +	 * use
     	 * @return the {@link CsrfConfigurer} for further customizations
     	 */
     	public CsrfConfigurer sessionAuthenticationStrategy(
     			SessionAuthenticationStrategy sessionAuthenticationStrategy) {
    -		Assert.notNull(sessionAuthenticationStrategy,
    -				"sessionAuthenticationStrategy cannot be null");
    +		Assert.notNull(sessionAuthenticationStrategy, "sessionAuthenticationStrategy cannot be null");
     		this.sessionAuthenticationStrategy = sessionAuthenticationStrategy;
     		return this;
     	}
    @@ -215,14 +212,11 @@ public final class CsrfConfigurer>
     		}
     		LogoutConfigurer logoutConfigurer = http.getConfigurer(LogoutConfigurer.class);
     		if (logoutConfigurer != null) {
    -			logoutConfigurer
    -					.addLogoutHandler(new CsrfLogoutHandler(this.csrfTokenRepository));
    +			logoutConfigurer.addLogoutHandler(new CsrfLogoutHandler(this.csrfTokenRepository));
     		}
    -		SessionManagementConfigurer sessionConfigurer = http
    -				.getConfigurer(SessionManagementConfigurer.class);
    +		SessionManagementConfigurer sessionConfigurer = http.getConfigurer(SessionManagementConfigurer.class);
     		if (sessionConfigurer != null) {
    -			sessionConfigurer.addSessionAuthenticationStrategy(
    -					getSessionAuthenticationStrategy());
    +			sessionConfigurer.addSessionAuthenticationStrategy(getSessionAuthenticationStrategy());
     		}
     		filter = postProcess(filter);
     		http.addFilter(filter);
    @@ -231,7 +225,6 @@ public final class CsrfConfigurer>
     	/**
     	 * Gets the final {@link RequestMatcher} to use by combining the
     	 * {@link #requireCsrfProtectionMatcher(RequestMatcher)} and any {@link #ignore()}.
    -	 *
     	 * @return the {@link RequestMatcher} to use
     	 */
     	private RequestMatcher getRequireCsrfProtectionMatcher() {
    @@ -239,22 +232,19 @@ public final class CsrfConfigurer>
     			return this.requireCsrfProtectionMatcher;
     		}
     		return new AndRequestMatcher(this.requireCsrfProtectionMatcher,
    -				new NegatedRequestMatcher(
    -						new OrRequestMatcher(this.ignoredCsrfProtectionMatchers)));
    +				new NegatedRequestMatcher(new OrRequestMatcher(this.ignoredCsrfProtectionMatchers)));
     	}
     
     	/**
     	 * Gets the default {@link AccessDeniedHandler} from the
     	 * {@link ExceptionHandlingConfigurer#getAccessDeniedHandler()} or create a
     	 * {@link AccessDeniedHandlerImpl} if not available.
    -	 *
     	 * @param http the {@link HttpSecurityBuilder}
     	 * @return the {@link AccessDeniedHandler}
     	 */
     	@SuppressWarnings("unchecked")
     	private AccessDeniedHandler getDefaultAccessDeniedHandler(H http) {
    -		ExceptionHandlingConfigurer exceptionConfig = http
    -				.getConfigurer(ExceptionHandlingConfigurer.class);
    +		ExceptionHandlingConfigurer exceptionConfig = http.getConfigurer(ExceptionHandlingConfigurer.class);
     		AccessDeniedHandler handler = null;
     		if (exceptionConfig != null) {
     			handler = exceptionConfig.getAccessDeniedHandler();
    @@ -269,14 +259,12 @@ public final class CsrfConfigurer>
     	 * Gets the default {@link InvalidSessionStrategy} from the
     	 * {@link SessionManagementConfigurer#getInvalidSessionStrategy()} or null if not
     	 * available.
    -	 *
     	 * @param http the {@link HttpSecurityBuilder}
     	 * @return the {@link InvalidSessionStrategy}
     	 */
     	@SuppressWarnings("unchecked")
     	private InvalidSessionStrategy getInvalidSessionStrategy(H http) {
    -		SessionManagementConfigurer sessionManagement = http
    -				.getConfigurer(SessionManagementConfigurer.class);
    +		SessionManagementConfigurer sessionManagement = http.getConfigurer(SessionManagementConfigurer.class);
     		if (sessionManagement == null) {
     			return null;
     		}
    @@ -292,14 +280,12 @@ public final class CsrfConfigurer>
     	 * {@link InvalidSessionAccessDeniedHandler} and the
     	 * {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)}. Otherwise, only
     	 * {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)} is used.
    -	 *
     	 * @param http the {@link HttpSecurityBuilder}
     	 * @return the {@link AccessDeniedHandler}
     	 */
     	private AccessDeniedHandler createAccessDeniedHandler(H http) {
     		InvalidSessionStrategy invalidSessionStrategy = getInvalidSessionStrategy(http);
    -		AccessDeniedHandler defaultAccessDeniedHandler = getDefaultAccessDeniedHandler(
    -				http);
    +		AccessDeniedHandler defaultAccessDeniedHandler = getDefaultAccessDeniedHandler(http);
     		if (invalidSessionStrategy == null) {
     			return defaultAccessDeniedHandler;
     		}
    @@ -312,18 +298,18 @@ public final class CsrfConfigurer>
     	}
     
     	/**
    -	 * Gets the {@link SessionAuthenticationStrategy} to use. If none was set by the user a
    -	 * {@link CsrfAuthenticationStrategy} is created.
    +	 * Gets the {@link SessionAuthenticationStrategy} to use. If none was set by the user
    +	 * a {@link CsrfAuthenticationStrategy} is created.
     	 *
     	 * @author Michael Vitz
     	 * @since 5.2
    -	 *
     	 * @return the {@link SessionAuthenticationStrategy}
     	 */
     	private SessionAuthenticationStrategy getSessionAuthenticationStrategy() {
     		if (sessionAuthenticationStrategy != null) {
     			return sessionAuthenticationStrategy;
    -		} else {
    +		}
    +		else {
     			return new CsrfAuthenticationStrategy(this.csrfTokenRepository);
     		}
     	}
    @@ -336,8 +322,7 @@ public final class CsrfConfigurer>
     	 * @author Rob Winch
     	 * @since 4.0
     	 */
    -	private class IgnoreCsrfProtectionRegistry
    -			extends AbstractRequestMatcherRegistry {
    +	private class IgnoreCsrfProtectionRegistry extends AbstractRequestMatcherRegistry {
     
     		/**
     		 * @param context
    @@ -347,12 +332,10 @@ public final class CsrfConfigurer>
     		}
     
     		@Override
    -		public MvcMatchersIgnoreCsrfProtectionRegistry mvcMatchers(HttpMethod method,
    -				String... mvcPatterns) {
    +		public MvcMatchersIgnoreCsrfProtectionRegistry mvcMatchers(HttpMethod method, String... mvcPatterns) {
     			List mvcMatchers = createMvcMatchers(method, mvcPatterns);
     			CsrfConfigurer.this.ignoredCsrfProtectionMatchers.addAll(mvcMatchers);
    -			return new MvcMatchersIgnoreCsrfProtectionRegistry(getApplicationContext(),
    -					mvcMatchers);
    +			return new MvcMatchersIgnoreCsrfProtectionRegistry(getApplicationContext(), mvcMatchers);
     		}
     
     		@Override
    @@ -365,11 +348,11 @@ public final class CsrfConfigurer>
     		}
     
     		@Override
    -		protected IgnoreCsrfProtectionRegistry chainRequestMatchers(
    -				List requestMatchers) {
    +		protected IgnoreCsrfProtectionRegistry chainRequestMatchers(List requestMatchers) {
     			CsrfConfigurer.this.ignoredCsrfProtectionMatchers.addAll(requestMatchers);
     			return this;
     		}
    +
     	}
     
     	/**
    @@ -378,8 +361,8 @@ public final class CsrfConfigurer>
     	 *
     	 * @author Rob Winch
     	 */
    -	private final class MvcMatchersIgnoreCsrfProtectionRegistry
    -			extends IgnoreCsrfProtectionRegistry {
    +	private final class MvcMatchersIgnoreCsrfProtectionRegistry extends IgnoreCsrfProtectionRegistry {
    +
     		private final List mvcMatchers;
     
     		private MvcMatchersIgnoreCsrfProtectionRegistry(ApplicationContext context,
    @@ -394,5 +377,7 @@ public final class CsrfConfigurer>
     			}
     			return this;
     		}
    +
     	}
    +
     }
    diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurer.java
    index 251c586f3e..92c09d6192 100644
    --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurer.java
    +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurer.java
    @@ -49,7 +49,8 @@ import java.util.function.Function;
      *
      * 

    Shared Objects Created

    * - * No shared objects are created. isLogoutRequest

    Shared Objects Used

    + * No shared objects are created. isLogoutRequest + *

    Shared Objects Used

    * * The following shared objects are used: * @@ -61,12 +62,11 @@ import java.util.function.Function; * * * @see WebSecurityConfigurerAdapter - * * @author Rob Winch * @since 3.2 */ -public final class DefaultLoginPageConfigurer> extends - AbstractHttpConfigurer, H> { +public final class DefaultLoginPageConfigurer> + extends AbstractHttpConfigurer, H> { private DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = new DefaultLoginPageGeneratingFilter(); @@ -83,16 +83,14 @@ public final class DefaultLoginPageConfigurer> }; this.loginPageGeneratingFilter.setResolveHiddenInputs(hiddenInputs); this.logoutPageGeneratingFilter.setResolveHiddenInputs(hiddenInputs); - http.setSharedObject(DefaultLoginPageGeneratingFilter.class, - loginPageGeneratingFilter); + http.setSharedObject(DefaultLoginPageGeneratingFilter.class, loginPageGeneratingFilter); } @Override @SuppressWarnings("unchecked") public void configure(H http) { AuthenticationEntryPoint authenticationEntryPoint = null; - ExceptionHandlingConfigurer exceptionConf = http - .getConfigurer(ExceptionHandlingConfigurer.class); + ExceptionHandlingConfigurer exceptionConf = http.getConfigurer(ExceptionHandlingConfigurer.class); if (exceptionConf != null) { authenticationEntryPoint = exceptionConf.getAuthenticationEntryPoint(); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurer.java index d1741cf898..43b1a09ec3 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurer.java @@ -62,8 +62,8 @@ import org.springframework.security.web.util.matcher.RequestMatcher; * @author Rob Winch * @since 3.2 */ -public final class ExceptionHandlingConfigurer> extends - AbstractHttpConfigurer, H> { +public final class ExceptionHandlingConfigurer> + extends AbstractHttpConfigurer, H> { private AuthenticationEntryPoint authenticationEntryPoint; @@ -83,7 +83,6 @@ public final class ExceptionHandlingConfigurer> /** * Shortcut to specify the {@link AccessDeniedHandler} to be used is a specific error * page - * * @param accessDeniedUrl the URL to the access denied page (i.e. /errors/401) * @return the {@link ExceptionHandlingConfigurer} for further customization * @see AccessDeniedHandlerImpl @@ -97,32 +96,29 @@ public final class ExceptionHandlingConfigurer> /** * Specifies the {@link AccessDeniedHandler} to be used - * * @param accessDeniedHandler the {@link AccessDeniedHandler} to be used * @return the {@link ExceptionHandlingConfigurer} for further customization */ - public ExceptionHandlingConfigurer accessDeniedHandler( - AccessDeniedHandler accessDeniedHandler) { + public ExceptionHandlingConfigurer accessDeniedHandler(AccessDeniedHandler accessDeniedHandler) { this.accessDeniedHandler = accessDeniedHandler; return this; } /** - * Sets a default {@link AccessDeniedHandler} to be used which prefers being - * invoked for the provided {@link RequestMatcher}. If only a single default - * {@link AccessDeniedHandler} is specified, it will be what is used for the - * default {@link AccessDeniedHandler}. If multiple default - * {@link AccessDeniedHandler} instances are configured, then a + * Sets a default {@link AccessDeniedHandler} to be used which prefers being invoked + * for the provided {@link RequestMatcher}. If only a single default + * {@link AccessDeniedHandler} is specified, it will be what is used for the default + * {@link AccessDeniedHandler}. If multiple default {@link AccessDeniedHandler} + * instances are configured, then a * {@link RequestMatcherDelegatingAccessDeniedHandler} will be used. - * * @param deniedHandler the {@link AccessDeniedHandler} to use * @param preferredMatcher the {@link RequestMatcher} for this default * {@link AccessDeniedHandler} * @return the {@link ExceptionHandlingConfigurer} for further customizations * @since 5.1 */ - public ExceptionHandlingConfigurer defaultAccessDeniedHandlerFor( - AccessDeniedHandler deniedHandler, RequestMatcher preferredMatcher) { + public ExceptionHandlingConfigurer defaultAccessDeniedHandlerFor(AccessDeniedHandler deniedHandler, + RequestMatcher preferredMatcher) { this.defaultDeniedHandlerMappings.put(preferredMatcher, deniedHandler); return this; } @@ -141,12 +137,10 @@ public final class ExceptionHandlingConfigurer> *

    * If that is not provided defaults to {@link Http403ForbiddenEntryPoint}. *

    - * * @param authenticationEntryPoint the {@link AuthenticationEntryPoint} to use * @return the {@link ExceptionHandlingConfigurer} for further customizations */ - public ExceptionHandlingConfigurer authenticationEntryPoint( - AuthenticationEntryPoint authenticationEntryPoint) { + public ExceptionHandlingConfigurer authenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; return this; } @@ -158,14 +152,13 @@ public final class ExceptionHandlingConfigurer> * default {@link AuthenticationEntryPoint}. If multiple default * {@link AuthenticationEntryPoint} instances are configured, then a * {@link DelegatingAuthenticationEntryPoint} will be used. - * * @param entryPoint the {@link AuthenticationEntryPoint} to use * @param preferredMatcher the {@link RequestMatcher} for this default * {@link AuthenticationEntryPoint} * @return the {@link ExceptionHandlingConfigurer} for further customizations */ - public ExceptionHandlingConfigurer defaultAuthenticationEntryPointFor( - AuthenticationEntryPoint entryPoint, RequestMatcher preferredMatcher) { + public ExceptionHandlingConfigurer defaultAuthenticationEntryPointFor(AuthenticationEntryPoint entryPoint, + RequestMatcher preferredMatcher) { this.defaultEntryPointMappings.put(preferredMatcher, entryPoint); return this; } @@ -180,7 +173,6 @@ public final class ExceptionHandlingConfigurer> /** * Gets the {@link AccessDeniedHandler} that is configured. - * * @return the {@link AccessDeniedHandler} */ AccessDeniedHandler getAccessDeniedHandler() { @@ -190,8 +182,8 @@ public final class ExceptionHandlingConfigurer> @Override public void configure(H http) { AuthenticationEntryPoint entryPoint = getAuthenticationEntryPoint(http); - ExceptionTranslationFilter exceptionTranslationFilter = new ExceptionTranslationFilter( - entryPoint, getRequestCache(http)); + ExceptionTranslationFilter exceptionTranslationFilter = new ExceptionTranslationFilter(entryPoint, + getRequestCache(http)); AccessDeniedHandler deniedHandler = getAccessDeniedHandler(http); exceptionTranslationFilter.setAccessDeniedHandler(deniedHandler); exceptionTranslationFilter = postProcess(exceptionTranslationFilter); @@ -235,8 +227,7 @@ public final class ExceptionHandlingConfigurer> if (this.defaultDeniedHandlerMappings.size() == 1) { return this.defaultDeniedHandlerMappings.values().iterator().next(); } - return new RequestMatcherDelegatingAccessDeniedHandler( - this.defaultDeniedHandlerMappings, + return new RequestMatcherDelegatingAccessDeniedHandler(this.defaultDeniedHandlerMappings, new AccessDeniedHandlerImpl()); } @@ -249,8 +240,7 @@ public final class ExceptionHandlingConfigurer> } DelegatingAuthenticationEntryPoint entryPoint = new DelegatingAuthenticationEntryPoint( this.defaultEntryPointMappings); - entryPoint.setDefaultEntryPoint(this.defaultEntryPointMappings.values().iterator() - .next()); + entryPoint.setDefaultEntryPoint(this.defaultEntryPointMappings.values().iterator().next()); return entryPoint; } @@ -259,7 +249,6 @@ public final class ExceptionHandlingConfigurer> * {@link #requestCache(org.springframework.security.web.savedrequest.RequestCache)}, * then it is used. Otherwise, an attempt to find a {@link RequestCache} shared object * is made. If that fails, an {@link HttpSessionRequestCache} is used - * * @param http the {@link HttpSecurity} to attempt to fined the shared object * @return the {@link RequestCache} to use */ @@ -270,4 +259,5 @@ public final class ExceptionHandlingConfigurer> } return new HttpSessionRequestCache(); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java index d1df31e7f5..1a6bdf8acb 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java @@ -46,7 +46,8 @@ import org.springframework.util.StringUtils; * Adds URL based authorization based upon SpEL expressions to an application. At least * one {@link org.springframework.web.bind.annotation.RequestMapping} needs to be mapped * to {@link ConfigAttribute}'s for this {@link SecurityContextConfigurer} to have - * meaning.

    Security Filters

    + * meaning. + *

    Security Filters

    * * The following Filters are populated * @@ -73,19 +74,23 @@ import org.springframework.util.StringUtils; * * * @param the type of {@link HttpSecurityBuilder} that is being configured - * * @author Rob Winch * @since 3.2 * @see org.springframework.security.config.annotation.web.builders.HttpSecurity#authorizeRequests() */ public final class ExpressionUrlAuthorizationConfigurer> - extends - AbstractInterceptUrlConfigurer, H> { + extends AbstractInterceptUrlConfigurer, H> { + static final String permitAll = "permitAll"; + private static final String denyAll = "denyAll"; + private static final String anonymous = "anonymous"; + private static final String authenticated = "authenticated"; + private static final String fullyAuthenticated = "fullyAuthenticated"; + private static final String rememberMe = "rememberMe"; private final ExpressionInterceptUrlRegistry REGISTRY; @@ -104,8 +109,7 @@ public final class ExpressionUrlAuthorizationConfigurer.AbstractInterceptUrlRegistry { /** @@ -126,15 +130,13 @@ public final class ExpressionUrlAuthorizationConfigurer requestMatchers) { + protected final AuthorizedUrl chainRequestMatchersInternal(List requestMatchers) { return new AuthorizedUrl(requestMatchers); } /** * Allows customization of the {@link SecurityExpressionHandler} to be used. The * default is {@link DefaultWebSecurityExpressionHandler} - * * @param expressionHandler the {@link SecurityExpressionHandler} to be used * @return the {@link ExpressionUrlAuthorizationConfigurer} for further * customization. @@ -147,13 +149,11 @@ public final class ExpressionUrlAuthorizationConfigurer objectPostProcessor) { + public ExpressionInterceptUrlRegistry withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { addObjectPostProcessor(objectPostProcessor); return this; } @@ -167,7 +167,6 @@ public final class ExpressionUrlAuthorizationConfigurer requestMatchers, Collection configAttributes) { for (RequestMatcher requestMatcher : requestMatchers) { - REGISTRY.addMapping(new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping( - requestMatcher, configAttributes)); + REGISTRY.addMapping( + new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping(requestMatcher, configAttributes)); } } @@ -192,23 +191,19 @@ public final class ExpressionUrlAuthorizationConfigurer> requestMap = REGISTRY - .createRequestMap(); + ExpressionBasedFilterInvocationSecurityMetadataSource createMetadataSource(H http) { + LinkedHashMap> requestMap = REGISTRY.createRequestMap(); if (requestMap.isEmpty()) { throw new IllegalStateException( "At least one mapping is required (i.e. authorizeRequests().anyRequest().authenticated())"); } - return new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, - getExpressionHandler(http)); + return new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, getExpressionHandler(http)); } private SecurityExpressionHandler getExpressionHandler(H http) { if (expressionHandler == null) { DefaultWebSecurityExpressionHandler defaultHandler = new DefaultWebSecurityExpressionHandler(); - AuthenticationTrustResolver trustResolver = http - .getSharedObject(AuthenticationTrustResolver.class); + AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class); if (trustResolver != null) { defaultHandler.setTrustResolver(trustResolver); } @@ -218,14 +213,17 @@ public final class ExpressionUrlAuthorizationConfigurer requestMatchers) { @@ -287,15 +283,17 @@ public final class ExpressionUrlAuthorizationConfigurer requestMatchers; + private boolean not; /** * Creates a new instance - * * @param requestMatchers the {@link RequestMatcher} instances to map */ private AuthorizedUrl(List requestMatchers) { @@ -308,7 +306,6 @@ public final class ExpressionUrlAuthorizationConfigurersubnet. - * * @param ipaddressExpression the ipaddress (i.e. 192.168.1.79) or local subnet * (i.e. 192.168.0/24) * @return the {@link ExpressionUrlAuthorizationConfigurer} for further * customization */ public ExpressionInterceptUrlRegistry hasIpAddress(String ipaddressExpression) { - return access(ExpressionUrlAuthorizationConfigurer - .hasIpAddress(ipaddressExpression)); + return access(ExpressionUrlAuthorizationConfigurer.hasIpAddress(ipaddressExpression)); } /** * Specify that URLs are allowed by anyone. - * * @return the {@link ExpressionUrlAuthorizationConfigurer} for further * customization */ @@ -396,7 +385,6 @@ public final class ExpressionUrlAuthorizationConfigurer> extends *
  • /authenticate?error GET - redirect here for failed authentication attempts
  • *
  • /authenticate?logout GET - redirect here after successfully logging out
  • * - * - * * @param loginPage the login page to redirect to if authentication is required (i.e. * "/login") * @return the {@link FormLoginConfigurer} for additional customization @@ -186,7 +184,6 @@ public final class FormLoginConfigurer> extends /** * The HTTP parameter to look for the username when performing authentication. Default * is "username". - * * @param usernameParameter the HTTP parameter to look for the username when * performing authentication * @return the {@link FormLoginConfigurer} for additional customization @@ -199,7 +196,6 @@ public final class FormLoginConfigurer> extends /** * The HTTP parameter to look for the password when performing authentication. Default * is "password". - * * @param passwordParameter the HTTP parameter to look for the password when * performing authentication * @return the {@link FormLoginConfigurer} for additional customization @@ -211,7 +207,6 @@ public final class FormLoginConfigurer> extends /** * Forward Authentication Failure Handler - * * @param forwardUrl the target URL in case of failure * @return the {@link FormLoginConfigurer} for additional customization */ @@ -222,7 +217,6 @@ public final class FormLoginConfigurer> extends /** * Forward Authentication Success Handler - * * @param forwardUrl the target URL in case of success * @return the {@link FormLoginConfigurer} for additional customization */ @@ -251,7 +245,6 @@ public final class FormLoginConfigurer> extends /** * Gets the HTTP parameter that is used to submit the username. - * * @return the HTTP parameter that is used to submit the username */ private String getUsernameParameter() { @@ -260,7 +253,6 @@ public final class FormLoginConfigurer> extends /** * Gets the HTTP parameter that is used to submit the password. - * * @return the HTTP parameter that is used to submit the password */ private String getPasswordParameter() { @@ -270,7 +262,6 @@ public final class FormLoginConfigurer> extends /** * If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared * object. - * * @param http the {@link HttpSecurityBuilder} to use */ private void initDefaultLoginFilter(H http) { @@ -285,4 +276,5 @@ public final class FormLoginConfigurer> extends loginPageGeneratingFilter.setAuthenticationUrl(getLoginProcessingUrl()); } } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java index adcffa0648..0f6758a5c8 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java @@ -63,8 +63,9 @@ import org.springframework.util.Assert; * @author Vedran Pavic * @since 3.2 */ -public class HeadersConfigurer> extends - AbstractHttpConfigurer, H> { +public class HeadersConfigurer> + extends AbstractHttpConfigurer, H> { + private List headerWriters = new ArrayList<>(); // --- default header writers --- @@ -97,7 +98,6 @@ public class HeadersConfigurer> extends /** * Adds a {@link HeaderWriter} instance - * * @param headerWriter the {@link HeaderWriter} instance to add * @return the {@link HeadersConfigurer} for additional customizations */ @@ -108,14 +108,13 @@ public class HeadersConfigurer> extends } /** - * Configures the {@link XContentTypeOptionsHeaderWriter} which inserts the X-Content-Type-Options: * *
     	 * X-Content-Type-Options: nosniff
     	 * 
    - * * @return the {@link ContentTypeOptionsConfig} for additional customizations */ public ContentTypeOptionsConfig contentTypeOptions() { @@ -123,16 +122,15 @@ public class HeadersConfigurer> extends } /** - * Configures the {@link XContentTypeOptionsHeaderWriter} which inserts the X-Content-Type-Options: * *
     	 * X-Content-Type-Options: nosniff
     	 * 
    - * - * @param contentTypeOptionsCustomizer the {@link Customizer} to provide more options for - * the {@link ContentTypeOptionsConfig} + * @param contentTypeOptionsCustomizer the {@link Customizer} to provide more options + * for the {@link ContentTypeOptionsConfig} * @return the {@link HeadersConfigurer} for additional customizations */ public HeadersConfigurer contentTypeOptions(Customizer contentTypeOptionsCustomizer) { @@ -141,6 +139,7 @@ public class HeadersConfigurer> extends } public final class ContentTypeOptionsConfig { + private XContentTypeOptionsHeaderWriter writer; private ContentTypeOptionsConfig() { @@ -149,7 +148,6 @@ public class HeadersConfigurer> extends /** * Removes the X-XSS-Protection header. - * * @return {@link HeadersConfigurer} for additional customization. */ public HeadersConfigurer disable() { @@ -167,7 +165,6 @@ public class HeadersConfigurer> extends /** * Ensures that Content Type Options is enabled - * * @return the {@link ContentTypeOptionsConfig} for additional customization */ private ContentTypeOptionsConfig enable() { @@ -176,6 +173,7 @@ public class HeadersConfigurer> extends } return this; } + } /** @@ -186,7 +184,6 @@ public class HeadersConfigurer> extends * "https://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx" * >X-XSS-Protection header *

    - * * @return the {@link XXssConfig} for additional customizations */ public XXssConfig xssProtection() { @@ -201,9 +198,8 @@ public class HeadersConfigurer> extends * "https://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx" * >X-XSS-Protection header *

    - * - * @param xssCustomizer the {@link Customizer} to provide more options for - * the {@link XXssConfig} + * @param xssCustomizer the {@link Customizer} to provide more options for the + * {@link XXssConfig} * @return the {@link HeadersConfigurer} for additional customizations */ public HeadersConfigurer xssProtection(Customizer xssCustomizer) { @@ -212,6 +208,7 @@ public class HeadersConfigurer> extends } public final class XXssConfig { + private XXssProtectionHeaderWriter writer; private XXssConfig() { @@ -221,7 +218,6 @@ public class HeadersConfigurer> extends /** * If false, will not specify the mode as blocked. In this instance, any content * will be attempted to be fixed. If true, the content will be replaced with "#". - * * @param enabled the new value */ public XXssConfig block(boolean enabled) { @@ -236,7 +232,8 @@ public class HeadersConfigurer> extends * X-XSS-Protection: 1 *
    * - * or if {@link XXssProtectionHeaderWriter#setBlock(boolean)} of the given {@link XXssProtectionHeaderWriter} is true + * or if {@link XXssProtectionHeaderWriter#setBlock(boolean)} of the given + * {@link XXssProtectionHeaderWriter} is true * * *
    @@ -249,7 +246,6 @@ public class HeadersConfigurer> extends
     		 * 
     		 * X-XSS-Protection: 0
     		 * 
    - * * @param enabled the new value */ public XXssConfig xssProtectionEnabled(boolean enabled) { @@ -259,7 +255,6 @@ public class HeadersConfigurer> extends /** * Disables X-XSS-Protection header (does not include it) - * * @return the {@link HeadersConfigurer} for additional configuration */ public HeadersConfigurer disable() { @@ -270,7 +265,6 @@ public class HeadersConfigurer> extends /** * Allows completing configuration of X-XSS-Protection and continuing * configuration of headers. - * * @return the {@link HeadersConfigurer} for additional configuration */ public HeadersConfigurer and() { @@ -279,7 +273,6 @@ public class HeadersConfigurer> extends /** * Ensures the X-XSS-Protection header is enabled if it is not already. - * * @return the {@link XXssConfig} for additional customization */ private XXssConfig enable() { @@ -288,6 +281,7 @@ public class HeadersConfigurer> extends } return this; } + } /** @@ -298,7 +292,6 @@ public class HeadersConfigurer> extends *
  • Pragma: no-cache
  • *
  • Expires: 0
  • * - * * @return the {@link CacheControlConfig} for additional customizations */ public CacheControlConfig cacheControl() { @@ -313,7 +306,6 @@ public class HeadersConfigurer> extends *
  • Pragma: no-cache
  • *
  • Expires: 0
  • * - * * @param cacheControlCustomizer the {@link Customizer} to provide more options for * the {@link CacheControlConfig} * @return the {@link HeadersConfigurer} for additional customizations @@ -324,6 +316,7 @@ public class HeadersConfigurer> extends } public final class CacheControlConfig { + private CacheControlHeadersWriter writer; private CacheControlConfig() { @@ -332,7 +325,6 @@ public class HeadersConfigurer> extends /** * Disables Cache Control - * * @return the {@link HeadersConfigurer} for additional configuration */ public HeadersConfigurer disable() { @@ -341,9 +333,8 @@ public class HeadersConfigurer> extends } /** - * Allows completing configuration of Cache Control and continuing - * configuration of headers. - * + * Allows completing configuration of Cache Control and continuing configuration + * of headers. * @return the {@link HeadersConfigurer} for additional configuration */ public HeadersConfigurer and() { @@ -352,7 +343,6 @@ public class HeadersConfigurer> extends /** * Ensures the Cache Control headers are enabled if they are not already. - * * @return the {@link CacheControlConfig} for additional customization */ private CacheControlConfig enable() { @@ -361,13 +351,13 @@ public class HeadersConfigurer> extends } return this; } + } /** - * Allows customizing the {@link HstsHeaderWriter} which provides support for HTTP Strict Transport Security + * Allows customizing the {@link HstsHeaderWriter} which provides support for + * HTTP Strict Transport Security * (HSTS). - * * @return the {@link HstsConfig} for additional customizations */ public HstsConfig httpStrictTransportSecurity() { @@ -375,12 +365,11 @@ public class HeadersConfigurer> extends } /** - * Allows customizing the {@link HstsHeaderWriter} which provides support for HTTP Strict Transport Security + * Allows customizing the {@link HstsHeaderWriter} which provides support for + * HTTP Strict Transport Security * (HSTS). - * - * @param hstsCustomizer the {@link Customizer} to provide more options for - * the {@link HstsConfig} + * @param hstsCustomizer the {@link Customizer} to provide more options for the + * {@link HstsConfig} * @return the {@link HeadersConfigurer} for additional customizations */ public HeadersConfigurer httpStrictTransportSecurity(Customizer hstsCustomizer) { @@ -389,6 +378,7 @@ public class HeadersConfigurer> extends } public final class HstsConfig { + private HstsHeaderWriter writer; private HstsConfig() { @@ -403,11 +393,10 @@ public class HeadersConfigurer> extends * *

    * This instructs browsers how long to remember to keep this domain as a known - * HSTS Host. See Section 6.1.1 for - * additional details. + * HSTS Host. See + * Section 6.1.1 + * for additional details. *

    - * * @param maxAgeInSeconds the maximum amount of time (in seconds) to consider this * domain as a known HSTS Host. * @throws IllegalArgumentException if maxAgeInSeconds is negative @@ -422,7 +411,6 @@ public class HeadersConfigurer> extends * "Strict-Transport-Security" should be added. If true the header is added, else * the header is not added. By default the header is added when * {@link HttpServletRequest#isSecure()} returns true. - * * @param requestMatcher the {@link RequestMatcher} to use. * @throws IllegalArgumentException if {@link RequestMatcher} is null */ @@ -440,7 +428,6 @@ public class HeadersConfigurer> extends * See Section * 6.1.2 for additional details. *

    - * * @param includeSubDomains true to include subdomains, else false */ public HstsConfig includeSubDomains(boolean includeSubDomains) { @@ -454,10 +441,9 @@ public class HeadersConfigurer> extends *

    * *

    - * See Website hstspreload.org - * for additional details. + * See Website hstspreload.org for + * additional details. *

    - * * @param preload true to include preload, else false * @since 5.2.0 * @author Ankur Pathak @@ -469,7 +455,6 @@ public class HeadersConfigurer> extends /** * Disables Strict Transport Security - * * @return the {@link HeadersConfigurer} for additional configuration */ public HeadersConfigurer disable() { @@ -480,7 +465,6 @@ public class HeadersConfigurer> extends /** * Allows completing configuration of Strict Transport Security and continuing * configuration of headers. - * * @return the {@link HeadersConfigurer} for additional configuration */ public HeadersConfigurer and() { @@ -489,7 +473,6 @@ public class HeadersConfigurer> extends /** * Ensures that Strict-Transport-Security is enabled if it is not already - * * @return the {@link HstsConfig} for additional customization */ private HstsConfig enable() { @@ -498,11 +481,11 @@ public class HeadersConfigurer> extends } return this; } + } /** * Allows customizing the {@link XFrameOptionsHeaderWriter}. - * * @return the {@link FrameOptionsConfig} for additional customizations */ public FrameOptionsConfig frameOptions() { @@ -511,7 +494,6 @@ public class HeadersConfigurer> extends /** * Allows customizing the {@link XFrameOptionsHeaderWriter}. - * * @param frameOptionsCustomizer the {@link Customizer} to provide more options for * the {@link FrameOptionsConfig} * @return the {@link HeadersConfigurer} for additional customizations @@ -522,6 +504,7 @@ public class HeadersConfigurer> extends } public final class FrameOptionsConfig { + private XFrameOptionsHeaderWriter writer; private FrameOptionsConfig() { @@ -530,7 +513,6 @@ public class HeadersConfigurer> extends /** * Specify to DENY framing any content from this application. - * * @return the {@link HeadersConfigurer} for additional customization. */ public HeadersConfigurer deny() { @@ -545,7 +527,6 @@ public class HeadersConfigurer> extends * example.com could frame the application, but evil.com could not frame the * application. *

    - * * @return the {@link HeadersConfigurer} for additional customization. */ public HeadersConfigurer sameOrigin() { @@ -555,7 +536,6 @@ public class HeadersConfigurer> extends /** * Prevents the header from being added to the response. - * * @return the {@link HeadersConfigurer} for additional configuration. */ public HeadersConfigurer disable() { @@ -565,7 +545,6 @@ public class HeadersConfigurer> extends /** * Allows continuing customizing the headers configuration. - * * @return the {@link HeadersConfigurer} for additional configuration */ public HeadersConfigurer and() { @@ -574,7 +553,6 @@ public class HeadersConfigurer> extends /** * Enables FrameOptionsConfig if it is not already enabled. - * * @return the FrameOptionsConfig for additional customization. */ private FrameOptionsConfig enable() { @@ -583,12 +561,12 @@ public class HeadersConfigurer> extends } return this; } + } /** - * Allows customizing the {@link HpkpHeaderWriter} which provides support for HTTP Public Key Pinning (HPKP). - * + * Allows customizing the {@link HpkpHeaderWriter} which provides support for + * HTTP Public Key Pinning (HPKP). * @return the {@link HpkpConfig} for additional customizations * * @since 4.1 @@ -598,11 +576,10 @@ public class HeadersConfigurer> extends } /** - * Allows customizing the {@link HpkpHeaderWriter} which provides support for HTTP Public Key Pinning (HPKP). - * - * @param hpkpCustomizer the {@link Customizer} to provide more options for - * the {@link HpkpConfig} + * Allows customizing the {@link HpkpHeaderWriter} which provides support for + * HTTP Public Key Pinning (HPKP). + * @param hpkpCustomizer the {@link Customizer} to provide more options for the + * {@link HpkpConfig} * @return the {@link HeadersConfigurer} for additional customizations */ public HeadersConfigurer httpPublicKeyPinning(Customizer hpkpCustomizer) { @@ -611,9 +588,11 @@ public class HeadersConfigurer> extends } public final class HpkpConfig { + private HpkpHeaderWriter writer; - private HpkpConfig() {} + private HpkpConfig() { + } /** *

    @@ -621,12 +600,13 @@ public class HeadersConfigurer> extends *

    * *

    - * The pin directive specifies a way for web host operators to indicate - * a cryptographic identity that should be bound to a given web host. - * See Section 2.1.1 for additional details. + * The pin directive specifies a way for web host operators to indicate a + * cryptographic identity that should be bound to a given web host. See + * Section 2.1.1 + * for additional details. *

    - * - * @param pins the map of base64-encoded SPKI fingerprint & cryptographic hash algorithm pairs. + * @param pins the map of base64-encoded SPKI fingerprint & cryptographic hash + * algorithm pairs. * @throws IllegalArgumentException if pins is null */ public HpkpConfig withPins(Map pins) { @@ -636,37 +616,38 @@ public class HeadersConfigurer> extends /** *

    - * Adds a list of SHA256 hashed pins for the pin- directive of the Public-Key-Pins header. + * Adds a list of SHA256 hashed pins for the pin- directive of the Public-Key-Pins + * header. *

    * *

    - * The pin directive specifies a way for web host operators to indicate - * a cryptographic identity that should be bound to a given web host. - * See Section 2.1.1 for additional details. + * The pin directive specifies a way for web host operators to indicate a + * cryptographic identity that should be bound to a given web host. See + * Section 2.1.1 + * for additional details. *

    - * * @param pins a list of base64-encoded SPKI fingerprints. * @throws IllegalArgumentException if a pin is null */ - public HpkpConfig addSha256Pins(String ... pins) { + public HpkpConfig addSha256Pins(String... pins) { writer.addSha256Pins(pins); return this; } /** *

    - * Sets the value (in seconds) for the max-age directive of the Public-Key-Pins header. - * The default is 60 days. + * Sets the value (in seconds) for the max-age directive of the Public-Key-Pins + * header. The default is 60 days. *

    * *

    - * This instructs browsers how long they should regard the host (from whom the message was received) - * as a known pinned host. See Section - * 2.1.2 for additional details. + * This instructs browsers how long they should regard the host (from whom the + * message was received) as a known pinned host. See + * Section 2.1.2 + * for additional details. *

    - * - * @param maxAgeInSeconds the maximum amount of time (in seconds) to regard the host - * as a known pinned host. + * @param maxAgeInSeconds the maximum amount of time (in seconds) to regard the + * host as a known pinned host. * @throws IllegalArgumentException if maxAgeInSeconds is negative */ public HpkpConfig maxAgeInSeconds(long maxAgeInSeconds) { @@ -676,15 +657,14 @@ public class HeadersConfigurer> extends /** *

    - * If true, the pinning policy applies to this pinned host as well as any subdomains - * of the host's domain name. The default is false. + * If true, the pinning policy applies to this pinned host as well as any + * subdomains of the host's domain name. The default is false. *

    * *

    - * See Section 2.1.3 - * for additional details. + * See Section + * 2.1.3 for additional details. *

    - * * @param includeSubDomains true to include subdomains, else false */ public HpkpConfig includeSubDomains(boolean includeSubDomains) { @@ -694,14 +674,14 @@ public class HeadersConfigurer> extends /** *

    - * If true, the browser should not terminate the connection with the server. The default is true. + * If true, the browser should not terminate the connection with the server. The + * default is true. *

    * *

    * See Section 2.1 * for additional details. *

    - * * @param reportOnly true to report only, else false */ public HpkpConfig reportOnly(boolean reportOnly) { @@ -715,10 +695,9 @@ public class HeadersConfigurer> extends *

    * *

    - * See Section 2.1.4 - * for additional details. + * See Section + * 2.1.4 for additional details. *

    - * * @param reportUri the URI where the browser should send the report to. */ public HpkpConfig reportUri(URI reportUri) { @@ -732,10 +711,9 @@ public class HeadersConfigurer> extends *

    * *

    - * See Section 2.1.4 - * for additional details. + * See Section + * 2.1.4 for additional details. *

    - * * @param reportUri the URI where the browser should send the report to. * @throws IllegalArgumentException if the reportUri is not a valid URI */ @@ -746,7 +724,6 @@ public class HeadersConfigurer> extends /** * Prevents the header from being added to the response. - * * @return the {@link HeadersConfigurer} for additional configuration. */ public HeadersConfigurer disable() { @@ -757,7 +734,6 @@ public class HeadersConfigurer> extends /** * Allows completing configuration of Public Key Pinning and continuing * configuration of headers. - * * @return the {@link HeadersConfigurer} for additional configuration */ public HeadersConfigurer and() { @@ -765,8 +741,8 @@ public class HeadersConfigurer> extends } /** - * Ensures that Public-Key-Pins or Public-Key-Pins-Report-Only is enabled if it is not already - * + * Ensures that Public-Key-Pins or Public-Key-Pins-Report-Only is enabled if it is + * not already * @return the {@link HstsConfig} for additional customization */ private HpkpConfig enable() { @@ -775,25 +751,28 @@ public class HeadersConfigurer> extends } return this; } + } /** *

    - * Allows configuration for Content Security Policy (CSP) Level 2. + * Allows configuration for Content Security + * Policy (CSP) Level 2. *

    * *

    - * Calling this method automatically enables (includes) the Content-Security-Policy header in the response - * using the supplied security policy directive(s). + * Calling this method automatically enables (includes) the Content-Security-Policy + * header in the response using the supplied security policy directive(s). *

    * *

    - * Configuration is provided to the {@link ContentSecurityPolicyHeaderWriter} which supports the writing - * of the two headers as detailed in the W3C Candidate Recommendation: + * Configuration is provided to the {@link ContentSecurityPolicyHeaderWriter} which + * supports the writing of the two headers as detailed in the W3C Candidate + * Recommendation: *

    *
      - *
    • Content-Security-Policy
    • - *
    • Content-Security-Policy-Report-Only
    • + *
    • Content-Security-Policy
    • + *
    • Content-Security-Policy-Report-Only
    • *
    * * @see ContentSecurityPolicyHeaderWriter @@ -802,28 +781,29 @@ public class HeadersConfigurer> extends * @throws IllegalArgumentException if policyDirectives is null or empty */ public ContentSecurityPolicyConfig contentSecurityPolicy(String policyDirectives) { - this.contentSecurityPolicy.writer = - new ContentSecurityPolicyHeaderWriter(policyDirectives); + this.contentSecurityPolicy.writer = new ContentSecurityPolicyHeaderWriter(policyDirectives); return contentSecurityPolicy; } /** *

    - * Allows configuration for Content Security Policy (CSP) Level 2. + * Allows configuration for Content Security + * Policy (CSP) Level 2. *

    * *

    - * Calling this method automatically enables (includes) the Content-Security-Policy header in the response - * using the supplied security policy directive(s). + * Calling this method automatically enables (includes) the Content-Security-Policy + * header in the response using the supplied security policy directive(s). *

    * *

    - * Configuration is provided to the {@link ContentSecurityPolicyHeaderWriter} which supports the writing - * of the two headers as detailed in the W3C Candidate Recommendation: + * Configuration is provided to the {@link ContentSecurityPolicyHeaderWriter} which + * supports the writing of the two headers as detailed in the W3C Candidate + * Recommendation: *

    *
      - *
    • Content-Security-Policy
    • - *
    • Content-Security-Policy-Report-Only
    • + *
    • Content-Security-Policy
    • + *
    • Content-Security-Policy-Report-Only
    • *
    * * @see ContentSecurityPolicyHeaderWriter @@ -831,7 +811,8 @@ public class HeadersConfigurer> extends * the {@link ContentSecurityPolicyConfig} * @return the {@link HeadersConfigurer} for additional customizations */ - public HeadersConfigurer contentSecurityPolicy(Customizer contentSecurityCustomizer) { + public HeadersConfigurer contentSecurityPolicy( + Customizer contentSecurityCustomizer) { this.contentSecurityPolicy.writer = new ContentSecurityPolicyHeaderWriter(); contentSecurityCustomizer.customize(this.contentSecurityPolicy); @@ -839,6 +820,7 @@ public class HeadersConfigurer> extends } public final class ContentSecurityPolicyConfig { + private ContentSecurityPolicyHeaderWriter writer; private ContentSecurityPolicyConfig() { @@ -846,7 +828,6 @@ public class HeadersConfigurer> extends /** * Sets the security policy directive(s) to be used in the response header. - * * @param policyDirectives the security policy directive(s) * @return the {@link ContentSecurityPolicyConfig} for additional configuration * @throws IllegalArgumentException if policyDirectives is null or empty @@ -857,8 +838,8 @@ public class HeadersConfigurer> extends } /** - * Enables (includes) the Content-Security-Policy-Report-Only header in the response. - * + * Enables (includes) the Content-Security-Policy-Report-Only header in the + * response. * @return the {@link ContentSecurityPolicyConfig} for additional configuration */ public ContentSecurityPolicyConfig reportOnly() { @@ -869,7 +850,6 @@ public class HeadersConfigurer> extends /** * Allows completing configuration of Content Security Policy and continuing * configuration of headers. - * * @return the {@link HeadersConfigurer} for additional configuration */ public HeadersConfigurer and() { @@ -886,7 +866,6 @@ public class HeadersConfigurer> extends *
     	 * http.headers().defaultsDisabled().cacheControl();
     	 * 
    - * * @return the {@link HeadersConfigurer} for additional customization */ public HeadersConfigurer defaultsDisabled() { @@ -906,7 +885,6 @@ public class HeadersConfigurer> extends /** * Creates the {@link HeaderWriter} - * * @return the {@link HeaderWriter} */ private HeaderWriterFilter createHeaderWriterFilter() { @@ -922,7 +900,6 @@ public class HeadersConfigurer> extends /** * Gets the {@link HeaderWriter} instances and possibly initializes with the defaults. - * * @return */ private List getHeaderWriters() { @@ -948,18 +925,21 @@ public class HeadersConfigurer> extends /** *

    - * Allows configuration for Referrer Policy. + * Allows configuration for Referrer + * Policy. *

    * *

    - * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support the writing - * of the header as detailed in the W3C Technical Report: + * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support + * the writing of the header as detailed in the W3C Technical Report: *

    *
      - *
    • Referrer-Policy
    • + *
    • Referrer-Policy
    • *
    * - *

    Default value is:

    + *

    + * Default value is: + *

    * *
     	 * Referrer-Policy: no-referrer
    @@ -976,15 +956,16 @@ public class HeadersConfigurer> extends
     
     	/**
     	 * 

    - * Allows configuration for Referrer Policy. + * Allows configuration for Referrer + * Policy. *

    * *

    - * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support the writing - * of the header as detailed in the W3C Technical Report: + * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support + * the writing of the header as detailed in the W3C Technical Report: *

    *
      - *
    • Referrer-Policy
    • + *
    • Referrer-Policy
    • *
    * * @see ReferrerPolicyHeaderWriter @@ -999,15 +980,16 @@ public class HeadersConfigurer> extends /** *

    - * Allows configuration for Referrer Policy. + * Allows configuration for Referrer + * Policy. *

    * *

    - * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support the writing - * of the header as detailed in the W3C Technical Report: + * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support + * the writing of the header as detailed in the W3C Technical Report: *

    *
      - *
    • Referrer-Policy
    • + *
    • Referrer-Policy
    • *
    * * @see ReferrerPolicyHeaderWriter @@ -1030,7 +1012,6 @@ public class HeadersConfigurer> extends /** * Sets the policy to be used in the response header. - * * @param policy a referrer policy * @return the {@link ReferrerPolicyConfig} for additional configuration * @throws IllegalArgumentException if policy is null @@ -1076,7 +1057,6 @@ public class HeadersConfigurer> extends /** * Allows completing configuration of Feature Policy and continuing configuration * of headers. - * * @return the {@link HeadersConfigurer} for additional configuration */ public HeadersConfigurer and() { diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurer.java index e4defae601..6bddc681af 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurer.java @@ -53,8 +53,7 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy; * The following Filters are populated * *
      - *
    • - * {@link BasicAuthenticationFilter}
    • + *
    • {@link BasicAuthenticationFilter}
    • *
    * *

    Shared Objects Created

    @@ -77,16 +76,18 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy; * @author Rob Winch * @since 3.2 */ -public final class HttpBasicConfigurer> extends - AbstractHttpConfigurer, B> { +public final class HttpBasicConfigurer> + extends AbstractHttpConfigurer, B> { - private static final RequestHeaderRequestMatcher X_REQUESTED_WITH = new RequestHeaderRequestMatcher("X-Requested-With", - "XMLHttpRequest"); + private static final RequestHeaderRequestMatcher X_REQUESTED_WITH = new RequestHeaderRequestMatcher( + "X-Requested-With", "XMLHttpRequest"); private static final String DEFAULT_REALM = "Realm"; private AuthenticationEntryPoint authenticationEntryPoint; + private AuthenticationDetailsSource authenticationDetailsSource; + private BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint(); /** @@ -99,8 +100,7 @@ public final class HttpBasicConfigurer> extends LinkedHashMap entryPoints = new LinkedHashMap<>(); entryPoints.put(X_REQUESTED_WITH, new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)); - DelegatingAuthenticationEntryPoint defaultEntryPoint = new DelegatingAuthenticationEntryPoint( - entryPoints); + DelegatingAuthenticationEntryPoint defaultEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints); defaultEntryPoint.setDefaultEntryPoint(this.basicAuthEntryPoint); this.authenticationEntryPoint = defaultEntryPoint; } @@ -109,7 +109,6 @@ public final class HttpBasicConfigurer> extends * Allows easily changing the realm, but leaving the remaining defaults in place. If * {@link #authenticationEntryPoint(AuthenticationEntryPoint)} has been invoked, * invoking this method will result in an error. - * * @param realmName the HTTP Basic realm to use * @return {@link HttpBasicConfigurer} for additional customization */ @@ -122,14 +121,11 @@ public final class HttpBasicConfigurer> extends /** * The {@link AuthenticationEntryPoint} to be populated on * {@link BasicAuthenticationFilter} in the event that authentication fails. The - * default to use {@link BasicAuthenticationEntryPoint} with the realm - * "Realm". - * + * default to use {@link BasicAuthenticationEntryPoint} with the realm "Realm". * @param authenticationEntryPoint the {@link AuthenticationEntryPoint} to use * @return {@link HttpBasicConfigurer} for additional customization */ - public HttpBasicConfigurer authenticationEntryPoint( - AuthenticationEntryPoint authenticationEntryPoint) { + public HttpBasicConfigurer authenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) { this.authenticationEntryPoint = authenticationEntryPoint; return this; } @@ -137,7 +133,6 @@ public final class HttpBasicConfigurer> extends /** * Specifies a custom {@link AuthenticationDetailsSource} to use for basic * authentication. The default is {@link WebAuthenticationDetailsSource}. - * * @param authenticationDetailsSource the custom {@link AuthenticationDetailsSource} * to use * @return {@link HttpBasicConfigurer} for additional customization @@ -154,47 +149,43 @@ public final class HttpBasicConfigurer> extends } private void registerDefaults(B http) { - ContentNegotiationStrategy contentNegotiationStrategy = http - .getSharedObject(ContentNegotiationStrategy.class); + ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class); if (contentNegotiationStrategy == null) { contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); } - MediaTypeRequestMatcher restMatcher = new MediaTypeRequestMatcher( - contentNegotiationStrategy, MediaType.APPLICATION_ATOM_XML, - MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, - MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_XML, - MediaType.MULTIPART_FORM_DATA, MediaType.TEXT_XML); + MediaTypeRequestMatcher restMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, + MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, + MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_XML, MediaType.MULTIPART_FORM_DATA, + MediaType.TEXT_XML); restMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); MediaTypeRequestMatcher allMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.ALL); allMatcher.setUseEquals(true); RequestMatcher notHtmlMatcher = new NegatedRequestMatcher( - new MediaTypeRequestMatcher(contentNegotiationStrategy, - MediaType.TEXT_HTML)); + new MediaTypeRequestMatcher(contentNegotiationStrategy, MediaType.TEXT_HTML)); RequestMatcher restNotHtmlMatcher = new AndRequestMatcher( Arrays.asList(notHtmlMatcher, restMatcher)); - RequestMatcher preferredMatcher = new OrRequestMatcher(Arrays.asList(X_REQUESTED_WITH, restNotHtmlMatcher, allMatcher)); + RequestMatcher preferredMatcher = new OrRequestMatcher( + Arrays.asList(X_REQUESTED_WITH, restNotHtmlMatcher, allMatcher)); registerDefaultEntryPoint(http, preferredMatcher); registerDefaultLogoutSuccessHandler(http, preferredMatcher); } private void registerDefaultEntryPoint(B http, RequestMatcher preferredMatcher) { - ExceptionHandlingConfigurer exceptionHandling = http - .getConfigurer(ExceptionHandlingConfigurer.class); + ExceptionHandlingConfigurer exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class); if (exceptionHandling == null) { return; } - exceptionHandling.defaultAuthenticationEntryPointFor( - postProcess(this.authenticationEntryPoint), preferredMatcher); + exceptionHandling.defaultAuthenticationEntryPointFor(postProcess(this.authenticationEntryPoint), + preferredMatcher); } private void registerDefaultLogoutSuccessHandler(B http, RequestMatcher preferredMatcher) { - LogoutConfigurer logout = http - .getConfigurer(LogoutConfigurer.class); + LogoutConfigurer logout = http.getConfigurer(LogoutConfigurer.class); if (logout == null) { return; } @@ -204,13 +195,11 @@ public final class HttpBasicConfigurer> extends @Override public void configure(B http) { - AuthenticationManager authenticationManager = http - .getSharedObject(AuthenticationManager.class); - BasicAuthenticationFilter basicAuthenticationFilter = new BasicAuthenticationFilter( - authenticationManager, this.authenticationEntryPoint); + AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); + BasicAuthenticationFilter basicAuthenticationFilter = new BasicAuthenticationFilter(authenticationManager, + this.authenticationEntryPoint); if (this.authenticationDetailsSource != null) { - basicAuthenticationFilter - .setAuthenticationDetailsSource(this.authenticationDetailsSource); + basicAuthenticationFilter.setAuthenticationDetailsSource(this.authenticationDetailsSource); } RememberMeServices rememberMeServices = http.getSharedObject(RememberMeServices.class); if (rememberMeServices != null) { @@ -219,4 +208,5 @@ public final class HttpBasicConfigurer> extends basicAuthenticationFilter = postProcess(basicAuthenticationFilter); http.addFilter(basicAuthenticationFilter); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurer.java index 45abc6b156..67151567e6 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurer.java @@ -42,15 +42,13 @@ import org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthe * The following Filters are populated * *
      - *
    • - * {@link J2eePreAuthenticatedProcessingFilter}
    • + *
    • {@link J2eePreAuthenticatedProcessingFilter}
    • *
    * *

    Shared Objects Created

    * *
      - *
    • - * {@link AuthenticationEntryPoint} is populated with an + *
    • {@link AuthenticationEntryPoint} is populated with an * {@link Http403ForbiddenEntryPoint}
    • *
    • A {@link PreAuthenticatedAuthenticationProvider} is populated into * {@link HttpSecurity#authenticationProvider(org.springframework.security.authentication.AuthenticationProvider)} @@ -68,10 +66,12 @@ import org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthe * @author Rob Winch * @since 3.2 */ -public final class JeeConfigurer> extends - AbstractHttpConfigurer, H> { +public final class JeeConfigurer> extends AbstractHttpConfigurer, H> { + private J2eePreAuthenticatedProcessingFilter j2eePreAuthenticatedProcessingFilter; + private AuthenticationUserDetailsService authenticationUserDetailsService; + private Set mappableRoles = new HashSet<>(); /** @@ -91,7 +91,6 @@ public final class JeeConfigurer> extends *

      * There are no default roles that are mapped. *

      - * * @param mappableRoles the roles to attempt to map to the {@link UserDetails} (i.e. * "ROLE_USER", "ROLE_ADMIN", etc). * @return the {@link JeeConfigurer} for further customizations @@ -117,7 +116,6 @@ public final class JeeConfigurer> extends *

      * There are no default roles that are mapped. *

      - * * @param mappableRoles the roles to attempt to map to the {@link UserDetails} (i.e. * "USER", "ADMIN", etc). * @return the {@link JeeConfigurer} for further customizations @@ -142,7 +140,6 @@ public final class JeeConfigurer> extends *

      * There are no default roles that are mapped. *

      - * * @param mappableRoles the roles to attempt to map to the {@link UserDetails}. * @return the {@link JeeConfigurer} for further customizations * @see SimpleMappableAttributesRetriever @@ -156,7 +153,6 @@ public final class JeeConfigurer> extends * Specifies the {@link AuthenticationUserDetailsService} that is used with the * {@link PreAuthenticatedAuthenticationProvider}. The default is a * {@link PreAuthenticatedGrantedAuthoritiesUserDetailsService}. - * * @param authenticatedUserDetailsService the {@link AuthenticationUserDetailsService} * to use. * @return the {@link JeeConfigurer} for further configuration @@ -172,7 +168,6 @@ public final class JeeConfigurer> extends * {@link J2eePreAuthenticatedProcessingFilter} is provided, all of its attributes * must also be configured manually (i.e. all attributes populated in the * {@link JeeConfigurer} are not used). - * * @param j2eePreAuthenticatedProcessingFilter the * {@link J2eePreAuthenticatedProcessingFilter} to use. * @return the {@link JeeConfigurer} for further configuration @@ -194,8 +189,7 @@ public final class JeeConfigurer> extends @Override public void init(H http) { PreAuthenticatedAuthenticationProvider authenticationProvider = new PreAuthenticatedAuthenticationProvider(); - authenticationProvider - .setPreAuthenticatedUserDetailsService(getUserDetailsService()); + authenticationProvider.setPreAuthenticatedUserDetailsService(getUserDetailsService()); authenticationProvider = postProcess(authenticationProvider); // @formatter:off @@ -207,8 +201,7 @@ public final class JeeConfigurer> extends @Override public void configure(H http) { - J2eePreAuthenticatedProcessingFilter filter = getFilter(http - .getSharedObject(AuthenticationManager.class)); + J2eePreAuthenticatedProcessingFilter filter = getFilter(http.getSharedObject(AuthenticationManager.class)); http.addFilter(filter); } @@ -218,14 +211,11 @@ public final class JeeConfigurer> extends * @param authenticationManager the {@link AuthenticationManager} to use. * @return the {@link J2eePreAuthenticatedProcessingFilter} to use. */ - private J2eePreAuthenticatedProcessingFilter getFilter( - AuthenticationManager authenticationManager) { + private J2eePreAuthenticatedProcessingFilter getFilter(AuthenticationManager authenticationManager) { if (j2eePreAuthenticatedProcessingFilter == null) { j2eePreAuthenticatedProcessingFilter = new J2eePreAuthenticatedProcessingFilter(); - j2eePreAuthenticatedProcessingFilter - .setAuthenticationManager(authenticationManager); - j2eePreAuthenticatedProcessingFilter - .setAuthenticationDetailsSource(createWebAuthenticationDetailsSource()); + j2eePreAuthenticatedProcessingFilter.setAuthenticationManager(authenticationManager); + j2eePreAuthenticatedProcessingFilter.setAuthenticationDetailsSource(createWebAuthenticationDetailsSource()); j2eePreAuthenticatedProcessingFilter = postProcess(j2eePreAuthenticatedProcessingFilter); } @@ -235,7 +225,6 @@ public final class JeeConfigurer> extends /** * Gets the {@link AuthenticationUserDetailsService} that was specified or defaults to * {@link PreAuthenticatedGrantedAuthoritiesUserDetailsService}. - * * @return the {@link AuthenticationUserDetailsService} to use */ private AuthenticationUserDetailsService getUserDetailsService() { @@ -247,7 +236,6 @@ public final class JeeConfigurer> extends * Creates the {@link J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource} to set * on the {@link J2eePreAuthenticatedProcessingFilter}. It is populated with a * {@link SimpleMappableAttributesRetriever}. - * * @return the {@link J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource} to use. */ private J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource createWebAuthenticationDetailsSource() { @@ -259,4 +247,5 @@ public final class JeeConfigurer> extends detailsSource = postProcess(detailsSource); return detailsSource; } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java index 4f5d09833f..da0028a54f 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java @@ -41,15 +41,15 @@ import org.springframework.util.Assert; /** * Adds logout support. Other {@link SecurityConfigurer} instances may invoke - * {@link #addLogoutHandler(LogoutHandler)} in the {@link #init(HttpSecurityBuilder)} phase. + * {@link #addLogoutHandler(LogoutHandler)} in the {@link #init(HttpSecurityBuilder)} + * phase. * *

      Security Filters

      * * The following Filters are populated * *
        - *
      • - * {@link LogoutFilter}
      • + *
      • {@link LogoutFilter}
      • *
      * *

      Shared Objects Created

      @@ -65,19 +65,26 @@ import org.springframework.util.Assert; * @since 3.2 * @see RememberMeConfigurer */ -public final class LogoutConfigurer> extends - AbstractHttpConfigurer, H> { +public final class LogoutConfigurer> + extends AbstractHttpConfigurer, H> { + private List logoutHandlers = new ArrayList<>(); + private SecurityContextLogoutHandler contextLogoutHandler = new SecurityContextLogoutHandler(); + private String logoutSuccessUrl = "/login?logout"; + private LogoutSuccessHandler logoutSuccessHandler; + private String logoutUrl = "/logout"; + private RequestMatcher logoutRequestMatcher; + private boolean permitAll; + private boolean customLogoutSuccess; - private LinkedHashMap defaultLogoutSuccessHandlerMappings = - new LinkedHashMap<>(); + private LinkedHashMap defaultLogoutSuccessHandlerMappings = new LinkedHashMap<>(); /** * Creates a new instance @@ -87,10 +94,9 @@ public final class LogoutConfigurer> extends } /** - * Adds a {@link LogoutHandler}. - * {@link SecurityContextLogoutHandler} and {@link LogoutSuccessEventPublishingLogoutHandler} are added as - * last {@link LogoutHandler} instances by default. - * + * Adds a {@link LogoutHandler}. {@link SecurityContextLogoutHandler} and + * {@link LogoutSuccessEventPublishingLogoutHandler} are added as last + * {@link LogoutHandler} instances by default. * @param logoutHandler the {@link LogoutHandler} to add * @return the {@link LogoutConfigurer} for further customization */ @@ -101,8 +107,10 @@ public final class LogoutConfigurer> extends } /** - * Specifies if {@link SecurityContextLogoutHandler} should clear the {@link Authentication} at the time of logout. - * @param clearAuthentication true {@link SecurityContextLogoutHandler} should clear the {@link Authentication} (default), or false otherwise. + * Specifies if {@link SecurityContextLogoutHandler} should clear the + * {@link Authentication} at the time of logout. + * @param clearAuthentication true {@link SecurityContextLogoutHandler} should clear + * the {@link Authentication} (default), or false otherwise. * @return the {@link LogoutConfigurer} for further customization */ public LogoutConfigurer clearAuthentication(boolean clearAuthentication) { @@ -110,7 +118,6 @@ public final class LogoutConfigurer> extends return this; } - /** * Configures {@link SecurityContextLogoutHandler} to invalidate the * {@link HttpSession} at the time of logout. @@ -131,15 +138,14 @@ public final class LogoutConfigurer> extends * *

      * It is considered best practice to use an HTTP POST on any action that changes state - * (i.e. log out) to protect against CSRF attacks. If - * you really want to use an HTTP GET, you can use + * (i.e. log out) to protect against + * CSRF + * attacks. If you really want to use an HTTP GET, you can use * logoutRequestMatcher(new AntPathRequestMatcher(logoutUrl, "GET")); *

      * * @see #logoutRequestMatcher(RequestMatcher) * @see HttpSecurity#csrf() - * * @param logoutUrl the URL that will invoke logout. * @return the {@link LogoutConfigurer} for further customization */ @@ -154,7 +160,6 @@ public final class LogoutConfigurer> extends * use {@link #logoutUrl(String)} which helps enforce good practices. * * @see #logoutUrl(String) - * * @param logoutRequestMatcher the RequestMatcher used to determine if logout should * occur. * @return the {@link LogoutConfigurer} for further customization @@ -168,7 +173,6 @@ public final class LogoutConfigurer> extends * The URL to redirect to after logout has occurred. The default is "/login?logout". * This is a shortcut for invoking {@link #logoutSuccessHandler(LogoutSuccessHandler)} * with a {@link SimpleUrlLogoutSuccessHandler}. - * * @param logoutSuccessUrl the URL to redirect to after logout occurred * @return the {@link LogoutConfigurer} for further customization */ @@ -190,7 +194,6 @@ public final class LogoutConfigurer> extends * Allows specifying the names of cookies to be removed on logout success. This is a * shortcut to easily invoke {@link #addLogoutHandler(LogoutHandler)} with a * {@link CookieClearingLogoutHandler}. - * * @param cookieNamesToClear the names of cookies to be removed on logout success. * @return the {@link LogoutConfigurer} for further customization */ @@ -201,13 +204,11 @@ public final class LogoutConfigurer> extends /** * Sets the {@link LogoutSuccessHandler} to use. If this is specified, * {@link #logoutSuccessUrl(String)} is ignored. - * * @param logoutSuccessHandler the {@link LogoutSuccessHandler} to use after a user * has been logged out. * @return the {@link LogoutConfigurer} for further customizations */ - public LogoutConfigurer logoutSuccessHandler( - LogoutSuccessHandler logoutSuccessHandler) { + public LogoutConfigurer logoutSuccessHandler(LogoutSuccessHandler logoutSuccessHandler) { this.logoutSuccessUrl = null; this.customLogoutSuccess = true; this.logoutSuccessHandler = logoutSuccessHandler; @@ -217,18 +218,17 @@ public final class LogoutConfigurer> extends /** * Sets a default {@link LogoutSuccessHandler} to be used which prefers being invoked * for the provided {@link RequestMatcher}. If no {@link LogoutSuccessHandler} is - * specified a {@link SimpleUrlLogoutSuccessHandler} will be used. - * If any default {@link LogoutSuccessHandler} instances are configured, then a + * specified a {@link SimpleUrlLogoutSuccessHandler} will be used. If any default + * {@link LogoutSuccessHandler} instances are configured, then a * {@link DelegatingLogoutSuccessHandler} will be used that defaults to a * {@link SimpleUrlLogoutSuccessHandler}. - * * @param handler the {@link LogoutSuccessHandler} to use * @param preferredMatcher the {@link RequestMatcher} for this default * {@link LogoutSuccessHandler} * @return the {@link LogoutConfigurer} for further customizations */ - public LogoutConfigurer defaultLogoutSuccessHandlerFor( - LogoutSuccessHandler handler, RequestMatcher preferredMatcher) { + public LogoutConfigurer defaultLogoutSuccessHandlerFor(LogoutSuccessHandler handler, + RequestMatcher preferredMatcher) { Assert.notNull(handler, "handler cannot be null"); Assert.notNull(preferredMatcher, "preferredMatcher cannot be null"); this.defaultLogoutSuccessHandlerMappings.put(preferredMatcher, handler); @@ -238,7 +238,6 @@ public final class LogoutConfigurer> extends /** * Grants access to the {@link #logoutSuccessUrl(String)} and the * {@link #logoutUrl(String)} for every user. - * * @param permitAll if true grants access, else nothing is done * @return the {@link LogoutConfigurer} for further customization. */ @@ -250,7 +249,6 @@ public final class LogoutConfigurer> extends /** * Gets the {@link LogoutSuccessHandler} if not null, otherwise creates a new * {@link SimpleUrlLogoutSuccessHandler} using the {@link #logoutSuccessUrl(String)}. - * * @return the {@link LogoutSuccessHandler} to use */ private LogoutSuccessHandler getLogoutSuccessHandler() { @@ -267,7 +265,8 @@ public final class LogoutConfigurer> extends if (defaultLogoutSuccessHandlerMappings.isEmpty()) { return urlLogoutHandler; } - DelegatingLogoutSuccessHandler successHandler = new DelegatingLogoutSuccessHandler(defaultLogoutSuccessHandlerMappings); + DelegatingLogoutSuccessHandler successHandler = new DelegatingLogoutSuccessHandler( + defaultLogoutSuccessHandlerMappings); successHandler.setDefaultLogoutSuccessHandler(urlLogoutHandler); return successHandler; } @@ -296,7 +295,6 @@ public final class LogoutConfigurer> extends * Returns true if the logout success has been customized via * {@link #logoutSuccessUrl(String)} or * {@link #logoutSuccessHandler(LogoutSuccessHandler)}. - * * @return true if logout success handling has been customized, else false */ boolean isCustomLogoutSuccess() { @@ -306,7 +304,6 @@ public final class LogoutConfigurer> extends /** * Gets the logoutSuccesUrl or null if a * {@link #logoutSuccessHandler(LogoutSuccessHandler)} was configured. - * * @return the logoutSuccessUrl */ private String getLogoutSuccessUrl() { @@ -325,15 +322,13 @@ public final class LogoutConfigurer> extends * Creates the {@link LogoutFilter} using the {@link LogoutHandler} instances, the * {@link #logoutSuccessHandler(LogoutSuccessHandler)} and the * {@link #logoutUrl(String)}. - * * @param http the builder to use * @return the {@link LogoutFilter} to use. */ private LogoutFilter createLogoutFilter(H http) { logoutHandlers.add(contextLogoutHandler); logoutHandlers.add(postProcess(new LogoutSuccessEventPublishingLogoutHandler())); - LogoutHandler[] handlers = logoutHandlers - .toArray(new LogoutHandler[0]); + LogoutHandler[] handlers = logoutHandlers.toArray(new LogoutHandler[0]); LogoutFilter result = new LogoutFilter(getLogoutSuccessHandler(), handlers); result.setLogoutRequestMatcher(getLogoutRequestMatcher(http)); result = postProcess(result); @@ -349,13 +344,11 @@ public final class LogoutConfigurer> extends this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST"); } else { - this.logoutRequestMatcher = new OrRequestMatcher( - new AntPathRequestMatcher(this.logoutUrl, "GET"), - new AntPathRequestMatcher(this.logoutUrl, "POST"), - new AntPathRequestMatcher(this.logoutUrl, "PUT"), - new AntPathRequestMatcher(this.logoutUrl, "DELETE") - ); + this.logoutRequestMatcher = new OrRequestMatcher(new AntPathRequestMatcher(this.logoutUrl, "GET"), + new AntPathRequestMatcher(this.logoutUrl, "POST"), new AntPathRequestMatcher(this.logoutUrl, "PUT"), + new AntPathRequestMatcher(this.logoutUrl, "DELETE")); } return this.logoutRequestMatcher; } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupport.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupport.java index c500e9e283..78ebe6417d 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupport.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupport.java @@ -24,13 +24,13 @@ import org.springframework.security.web.util.matcher.RequestMatcher; /** * Configures non-null URL's to grant access to every URL + * * @author Rob Winch * @since 3.2 */ final class PermitAllSupport { - public static void permitAll( - HttpSecurityBuilder> http, String... urls) { + public static void permitAll(HttpSecurityBuilder> http, String... urls) { for (String url : urls) { if (url != null) { permitAll(http, new ExactUrlRequestMatcher(url)); @@ -39,32 +39,25 @@ final class PermitAllSupport { } @SuppressWarnings("unchecked") - public static void permitAll( - HttpSecurityBuilder> http, + public static void permitAll(HttpSecurityBuilder> http, RequestMatcher... requestMatchers) { ExpressionUrlAuthorizationConfigurer configurer = http .getConfigurer(ExpressionUrlAuthorizationConfigurer.class); if (configurer == null) { - throw new IllegalStateException( - "permitAll only works with HttpSecurity.authorizeRequests()"); + throw new IllegalStateException("permitAll only works with HttpSecurity.authorizeRequests()"); } for (RequestMatcher matcher : requestMatchers) { if (matcher != null) { - configurer - .getRegistry() - .addMapping( - 0, - new UrlMapping( - matcher, - SecurityConfig - .createList(ExpressionUrlAuthorizationConfigurer.permitAll))); + configurer.getRegistry().addMapping(0, new UrlMapping(matcher, + SecurityConfig.createList(ExpressionUrlAuthorizationConfigurer.permitAll))); } } } private final static class ExactUrlRequestMatcher implements RequestMatcher { + private String processUrl; private ExactUrlRequestMatcher(String processUrl) { @@ -92,8 +85,10 @@ final class PermitAllSupport { sb.append("ExactUrl [processUrl='").append(processUrl).append("']"); return sb.toString(); } + } private PermitAllSupport() { } + } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurer.java index 74f77c1b57..983cc726b2 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurer.java @@ -31,9 +31,11 @@ import org.springframework.security.web.PortMapperImpl; * @author Rob Winch * @since 3.2 */ -public final class PortMapperConfigurer> extends - AbstractHttpConfigurer, H> { +public final class PortMapperConfigurer> + extends AbstractHttpConfigurer, H> { + private PortMapper portMapper; + private Map httpsPortMappings = new HashMap<>(); /** @@ -70,7 +72,6 @@ public final class PortMapperConfigurer> extend * Gets the {@link PortMapper} to use. If {@link #portMapper(PortMapper)} was not * invoked, builds a {@link PortMapperImpl} using the port mappings specified with * {@link #http(int)}. - * * @return the {@link PortMapper} to use */ private PortMapper getPortMapper() { @@ -90,6 +91,7 @@ public final class PortMapperConfigurer> extend * @since 3.2 */ public final class HttpPortMapping { + private final int httpPort; /** @@ -110,5 +112,7 @@ public final class PortMapperConfigurer> extend httpsPortMappings.put(String.valueOf(httpPort), String.valueOf(httpsPort)); return PortMapperConfigurer.this; } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurer.java index 16e1cdfe51..878f11ed6c 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurer.java @@ -79,21 +79,34 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageGenera */ public final class RememberMeConfigurer> extends AbstractHttpConfigurer, H> { + /** * The default name for remember me parameter name and remember me cookie name */ private static final String DEFAULT_REMEMBER_ME_NAME = "remember-me"; + private AuthenticationSuccessHandler authenticationSuccessHandler; + private String key; + private RememberMeServices rememberMeServices; + private LogoutHandler logoutHandler; + private String rememberMeParameter = DEFAULT_REMEMBER_ME_NAME; + private String rememberMeCookieName = DEFAULT_REMEMBER_ME_NAME; + private String rememberMeCookieDomain; + private PersistentTokenRepository tokenRepository; + private UserDetailsService userDetailsService; + private Integer tokenValiditySeconds; + private Boolean useSecureCookie; + private Boolean alwaysRemember; /** @@ -104,7 +117,6 @@ public final class RememberMeConfigurer> /** * Allows specifying how long (in seconds) a token is valid for - * * @param tokenValiditySeconds * @return {@link RememberMeConfigurer} for further customization * @see AbstractRememberMeServices#setTokenValiditySeconds(int) @@ -122,7 +134,6 @@ public final class RememberMeConfigurer> * By default the cookie will be secure if the request is secure. If you only want to * use remember-me over HTTPS (recommended) you should set this property to * {@code true}. - * * @param useSecureCookie set to {@code true} to always user secure cookies, * {@code false} to disable their use. * @return the {@link RememberMeConfigurer} for further customization @@ -140,13 +151,11 @@ public final class RememberMeConfigurer> * {@link HttpSecurity#getSharedObject(Class)} which is set when using * {@link WebSecurityConfigurerAdapter#configure(AuthenticationManagerBuilder)}. * Alternatively, one can populate {@link #rememberMeServices(RememberMeServices)}. - * * @param userDetailsService the {@link UserDetailsService} to configure * @return the {@link RememberMeConfigurer} for further customization * @see AbstractRememberMeServices */ - public RememberMeConfigurer userDetailsService( - UserDetailsService userDetailsService) { + public RememberMeConfigurer userDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; return this; } @@ -154,23 +163,19 @@ public final class RememberMeConfigurer> /** * Specifies the {@link PersistentTokenRepository} to use. The default is to use * {@link TokenBasedRememberMeServices} instead. - * * @param tokenRepository the {@link PersistentTokenRepository} to use * @return the {@link RememberMeConfigurer} for further customization */ - public RememberMeConfigurer tokenRepository( - PersistentTokenRepository tokenRepository) { + public RememberMeConfigurer tokenRepository(PersistentTokenRepository tokenRepository) { this.tokenRepository = tokenRepository; return this; } /** * Sets the key to identify tokens created for remember me authentication. Default is - * a secure randomly generated key. - * If {@link #rememberMeServices(RememberMeServices)} is specified and is of type - * {@link AbstractRememberMeServices}, then the default is the key set in - * {@link AbstractRememberMeServices}. - * + * a secure randomly generated key. If {@link #rememberMeServices(RememberMeServices)} + * is specified and is of type {@link AbstractRememberMeServices}, then the default is + * the key set in {@link AbstractRememberMeServices}. * @param key the key to identify tokens created for remember me authentication * @return the {@link RememberMeConfigurer} for further customization */ @@ -181,7 +186,6 @@ public final class RememberMeConfigurer> /** * The HTTP parameter used to indicate to remember the user at time of login. - * * @param rememberMeParameter the HTTP parameter used to indicate to remember the user * @return the {@link RememberMeConfigurer} for further customization */ @@ -193,7 +197,6 @@ public final class RememberMeConfigurer> /** * The name of cookie which store the token for remember me authentication. Defaults * to 'remember-me'. - * * @param rememberMeCookieName the name of cookie which store the token for remember * me authentication * @return the {@link RememberMeConfigurer} for further customization @@ -206,7 +209,6 @@ public final class RememberMeConfigurer> /** * The domain name within which the remember me cookie is visible. - * * @param rememberMeCookieDomain the domain name within which the remember me cookie * is visible. * @return the {@link RememberMeConfigurer} for further customization @@ -224,7 +226,6 @@ public final class RememberMeConfigurer> * be invoked and the {@code doFilter()} method will return immediately, thus allowing * the application to redirect the user to a specific URL, regardless of what the * original request was for. - * * @param authenticationSuccessHandler the strategy to invoke immediately before * returning from {@code doFilter()}. * @return {@link RememberMeConfigurer} for further customization @@ -242,8 +243,7 @@ public final class RememberMeConfigurer> * @return the {@link RememberMeConfigurer} for further customizations * @see RememberMeServices */ - public RememberMeConfigurer rememberMeServices( - RememberMeServices rememberMeServices) { + public RememberMeConfigurer rememberMeServices(RememberMeServices rememberMeServices) { this.rememberMeServices = rememberMeServices; return this; } @@ -253,7 +253,6 @@ public final class RememberMeConfigurer> * not set. *

      * By default this will be set to {@code false}. - * * @param alwaysRemember set to {@code true} to always trigger remember me, * {@code false} to use the remember-me parameter. * @return the {@link RememberMeConfigurer} for further customization @@ -276,8 +275,7 @@ public final class RememberMeConfigurer> logoutConfigurer.addLogoutHandler(this.logoutHandler); } - RememberMeAuthenticationProvider authenticationProvider = new RememberMeAuthenticationProvider( - key); + RememberMeAuthenticationProvider authenticationProvider = new RememberMeAuthenticationProvider(key); authenticationProvider = postProcess(authenticationProvider); http.authenticationProvider(authenticationProvider); @@ -287,24 +285,21 @@ public final class RememberMeConfigurer> @Override public void configure(H http) { RememberMeAuthenticationFilter rememberMeFilter = new RememberMeAuthenticationFilter( - http.getSharedObject(AuthenticationManager.class), - this.rememberMeServices); + http.getSharedObject(AuthenticationManager.class), this.rememberMeServices); if (this.authenticationSuccessHandler != null) { - rememberMeFilter - .setAuthenticationSuccessHandler(this.authenticationSuccessHandler); + rememberMeFilter.setAuthenticationSuccessHandler(this.authenticationSuccessHandler); } rememberMeFilter = postProcess(rememberMeFilter); http.addFilter(rememberMeFilter); } /** - * Validate rememberMeServices and rememberMeCookieName have not been set at - * the same time. + * Validate rememberMeServices and rememberMeCookieName have not been set at the same + * time. */ private void validateInput() { if (this.rememberMeServices != null && this.rememberMeCookieName != DEFAULT_REMEMBER_ME_NAME) { - throw new IllegalArgumentException("Can not set rememberMeCookieName " + - "and custom rememberMeServices."); + throw new IllegalArgumentException("Can not set rememberMeCookieName " + "and custom rememberMeServices."); } } @@ -319,7 +314,6 @@ public final class RememberMeConfigurer> /** * If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared * object. - * * @param http the {@link HttpSecurityBuilder} to use */ private void initDefaultLoginFilter(H http) { @@ -337,17 +331,14 @@ public final class RememberMeConfigurer> * @return the {@link RememberMeServices} to use * @throws Exception */ - private RememberMeServices getRememberMeServices(H http, String key) - throws Exception { + private RememberMeServices getRememberMeServices(H http, String key) throws Exception { if (this.rememberMeServices != null) { - if (this.rememberMeServices instanceof LogoutHandler - && this.logoutHandler == null) { + if (this.rememberMeServices instanceof LogoutHandler && this.logoutHandler == null) { this.logoutHandler = (LogoutHandler) this.rememberMeServices; } return this.rememberMeServices; } - AbstractRememberMeServices tokenRememberMeServices = createRememberMeServices( - http, key); + AbstractRememberMeServices tokenRememberMeServices = createRememberMeServices(http, key); tokenRememberMeServices.setParameter(this.rememberMeParameter); tokenRememberMeServices.setCookieName(this.rememberMeCookieName); if (this.rememberMeCookieDomain != null) { @@ -372,49 +363,41 @@ public final class RememberMeConfigurer> * Creates the {@link RememberMeServices} to use when none is provided. The result is * either {@link PersistentTokenRepository} (if a {@link PersistentTokenRepository} is * specified, else {@link TokenBasedRememberMeServices}. - * * @param http the {@link HttpSecurity} to lookup shared objects * @param key the {@link #key(String)} * @return the {@link RememberMeServices} to use */ private AbstractRememberMeServices createRememberMeServices(H http, String key) { - return this.tokenRepository == null - ? createTokenBasedRememberMeServices(http, key) + return this.tokenRepository == null ? createTokenBasedRememberMeServices(http, key) : createPersistentRememberMeServices(http, key); } /** * Creates {@link TokenBasedRememberMeServices} - * * @param http the {@link HttpSecurity} to lookup shared objects * @param key the {@link #key(String)} * @return the {@link TokenBasedRememberMeServices} */ - private AbstractRememberMeServices createTokenBasedRememberMeServices(H http, - String key) { + private AbstractRememberMeServices createTokenBasedRememberMeServices(H http, String key) { UserDetailsService userDetailsService = getUserDetailsService(http); return new TokenBasedRememberMeServices(key, userDetailsService); } /** * Creates {@link PersistentTokenBasedRememberMeServices} - * * @param http the {@link HttpSecurity} to lookup shared objects * @param key the {@link #key(String)} * @return the {@link PersistentTokenBasedRememberMeServices} */ - private AbstractRememberMeServices createPersistentRememberMeServices(H http, - String key) { + private AbstractRememberMeServices createPersistentRememberMeServices(H http, String key) { UserDetailsService userDetailsService = getUserDetailsService(http); - return new PersistentTokenBasedRememberMeServices(key, userDetailsService, - this.tokenRepository); + return new PersistentTokenBasedRememberMeServices(key, userDetailsService, this.tokenRepository); } /** * Gets the {@link UserDetailsService} to use. Either the explicitly configure * {@link UserDetailsService} from {@link #userDetailsService(UserDetailsService)} or * a shared object from {@link HttpSecurity#getSharedObject(Class)}. - * * @param http {@link HttpSecurity} to get the shared {@link UserDetailsService} * @return the {@link UserDetailsService} to use */ @@ -423,31 +406,31 @@ public final class RememberMeConfigurer> this.userDetailsService = http.getSharedObject(UserDetailsService.class); } if (this.userDetailsService == null) { - throw new IllegalStateException("userDetailsService cannot be null. Invoke " - + RememberMeConfigurer.class.getSimpleName() - + "#userDetailsService(UserDetailsService) or see its javadoc for alternative approaches."); + throw new IllegalStateException( + "userDetailsService cannot be null. Invoke " + RememberMeConfigurer.class.getSimpleName() + + "#userDetailsService(UserDetailsService) or see its javadoc for alternative approaches."); } return this.userDetailsService; } /** * Gets the key to use for validating remember me tokens. If a value was passed into - * {@link #key(String)}, then that is returned. - * Alternatively, if a key was specified in the - * {@link #rememberMeServices(RememberMeServices)}}, then that is returned. - * If no key was specified in either of those cases, then a secure random string is + * {@link #key(String)}, then that is returned. Alternatively, if a key was specified + * in the {@link #rememberMeServices(RememberMeServices)}}, then that is returned. If + * no key was specified in either of those cases, then a secure random string is * generated. - * * @return the remember me key to use */ private String getKey() { if (this.key == null) { if (this.rememberMeServices instanceof AbstractRememberMeServices) { this.key = ((AbstractRememberMeServices) rememberMeServices).getKey(); - } else { + } + else { this.key = UUID.randomUUID().toString(); } } return this.key; } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java index 3ac5d73e89..b74c57c3ba 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java @@ -69,8 +69,8 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy; * @since 3.2 * @see RequestCache */ -public final class RequestCacheConfigurer> extends - AbstractHttpConfigurer, H> { +public final class RequestCacheConfigurer> + extends AbstractHttpConfigurer, H> { public RequestCacheConfigurer() { } @@ -79,7 +79,6 @@ public final class RequestCacheConfigurer> exte * Allows explicit configuration of the {@link RequestCache} to be used. Defaults to * try finding a {@link RequestCache} as a shared object. Then falls back to a * {@link HttpSessionRequestCache}. - * * @param requestCache the explicit {@link RequestCache} to use * @return the {@link RequestCacheConfigurer} for further customization */ @@ -102,8 +101,7 @@ public final class RequestCacheConfigurer> exte @Override public void configure(H http) { RequestCache requestCache = getRequestCache(http); - RequestCacheAwareFilter requestCacheFilter = new RequestCacheAwareFilter( - requestCache); + RequestCacheAwareFilter requestCacheFilter = new RequestCacheAwareFilter(requestCache); requestCacheFilter = postProcess(requestCacheFilter); http.addFilter(requestCacheFilter); } @@ -113,7 +111,6 @@ public final class RequestCacheConfigurer> exte * {@link #requestCache(org.springframework.security.web.savedrequest.RequestCache)}, * then it is used. Otherwise, an attempt to find a {@link RequestCache} shared object * is made. If that fails, an {@link HttpSessionRequestCache} is used - * * @param http the {@link HttpSecurity} to attempt to fined the shared object * @return the {@link RequestCache} to use */ @@ -138,15 +135,15 @@ public final class RequestCacheConfigurer> exte } try { return context.getBean(type); - } catch (NoSuchBeanDefinitionException e) { + } + catch (NoSuchBeanDefinitionException e) { return null; } } @SuppressWarnings("unchecked") private RequestMatcher createDefaultSavedRequestMatcher(H http) { - RequestMatcher notFavIcon = new NegatedRequestMatcher(new AntPathRequestMatcher( - "/**/favicon.*")); + RequestMatcher notFavIcon = new NegatedRequestMatcher(new AntPathRequestMatcher("/**/favicon.*")); RequestMatcher notXRequestedWith = new NegatedRequestMatcher( new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest")); @@ -177,4 +174,5 @@ public final class RequestCacheConfigurer> exte mediaRequest.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); return new NegatedRequestMatcher(mediaRequest); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurer.java index c514989fe9..0c5f9df8f1 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurer.java @@ -58,8 +58,8 @@ import org.springframework.security.web.context.SecurityContextRepository; * @author Rob Winch * @since 3.2 */ -public final class SecurityContextConfigurer> extends - AbstractHttpConfigurer, H> { +public final class SecurityContextConfigurer> + extends AbstractHttpConfigurer, H> { /** * Creates a new instance @@ -73,10 +73,8 @@ public final class SecurityContextConfigurer> e * @param securityContextRepository the {@link SecurityContextRepository} to use * @return the {@link HttpSecurity} for further customizations */ - public SecurityContextConfigurer securityContextRepository( - SecurityContextRepository securityContextRepository) { - getBuilder().setSharedObject(SecurityContextRepository.class, - securityContextRepository); + public SecurityContextConfigurer securityContextRepository(SecurityContextRepository securityContextRepository) { + getBuilder().setSharedObject(SecurityContextRepository.class, securityContextRepository); return this; } @@ -84,15 +82,13 @@ public final class SecurityContextConfigurer> e @SuppressWarnings("unchecked") public void configure(H http) { - SecurityContextRepository securityContextRepository = http - .getSharedObject(SecurityContextRepository.class); + SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class); if (securityContextRepository == null) { securityContextRepository = new HttpSessionSecurityContextRepository(); } SecurityContextPersistenceFilter securityContextFilter = new SecurityContextPersistenceFilter( securityContextRepository); - SessionManagementConfigurer sessionManagement = http - .getConfigurer(SessionManagementConfigurer.class); + SessionManagementConfigurer sessionManagement = http.getConfigurer(SessionManagementConfigurer.class); SessionCreationPolicy sessionCreationPolicy = sessionManagement == null ? null : sessionManagement.getSessionCreationPolicy(); if (SessionCreationPolicy.ALWAYS == sessionCreationPolicy) { @@ -101,4 +97,5 @@ public final class SecurityContextConfigurer> e securityContextFilter = postProcess(securityContextFilter); http.addFilter(securityContextFilter); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurer.java index 73dccbfea2..3175ac3f30 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurer.java @@ -57,8 +57,9 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq * @author Rob Winch * @since 3.2 */ -public final class ServletApiConfigurer> extends - AbstractHttpConfigurer, H> { +public final class ServletApiConfigurer> + extends AbstractHttpConfigurer, H> { + private SecurityContextHolderAwareRequestFilter securityContextRequestFilter = new SecurityContextHolderAwareRequestFilter(); /** @@ -76,20 +77,15 @@ public final class ServletApiConfigurer> extend @Override @SuppressWarnings("unchecked") public void configure(H http) { - securityContextRequestFilter.setAuthenticationManager(http - .getSharedObject(AuthenticationManager.class)); - ExceptionHandlingConfigurer exceptionConf = http - .getConfigurer(ExceptionHandlingConfigurer.class); + securityContextRequestFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class)); + ExceptionHandlingConfigurer exceptionConf = http.getConfigurer(ExceptionHandlingConfigurer.class); AuthenticationEntryPoint authenticationEntryPoint = exceptionConf == null ? null : exceptionConf.getAuthenticationEntryPoint(http); - securityContextRequestFilter - .setAuthenticationEntryPoint(authenticationEntryPoint); + securityContextRequestFilter.setAuthenticationEntryPoint(authenticationEntryPoint); LogoutConfigurer logoutConf = http.getConfigurer(LogoutConfigurer.class); - List logoutHandlers = logoutConf == null ? null : logoutConf - .getLogoutHandlers(); + List logoutHandlers = logoutConf == null ? null : logoutConf.getLogoutHandlers(); securityContextRequestFilter.setLogoutHandlers(logoutHandlers); - AuthenticationTrustResolver trustResolver = http - .getSharedObject(AuthenticationTrustResolver.class); + AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class); if (trustResolver != null) { securityContextRequestFilter.setTrustResolver(trustResolver); } @@ -97,11 +93,13 @@ public final class ServletApiConfigurer> extend if (context != null) { String[] grantedAuthorityDefaultsBeanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class); if (grantedAuthorityDefaultsBeanNames.length == 1) { - GrantedAuthorityDefaults grantedAuthorityDefaults = context.getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class); + GrantedAuthorityDefaults grantedAuthorityDefaults = context + .getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class); securityContextRequestFilter.setRolePrefix(grantedAuthorityDefaults.getRolePrefix()); } } securityContextRequestFilter = postProcess(securityContextRequestFilter); http.addFilter(securityContextRequestFilter); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java index 5d6d2c22f0..acc55108bd 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java @@ -98,21 +98,37 @@ import org.springframework.util.CollectionUtils; */ public final class SessionManagementConfigurer> extends AbstractHttpConfigurer, H> { + private final SessionAuthenticationStrategy DEFAULT_SESSION_FIXATION_STRATEGY = createDefaultSessionFixationProtectionStrategy(); + private SessionAuthenticationStrategy sessionFixationAuthenticationStrategy = this.DEFAULT_SESSION_FIXATION_STRATEGY; + private SessionAuthenticationStrategy sessionAuthenticationStrategy; + private SessionAuthenticationStrategy providedSessionAuthenticationStrategy; + private InvalidSessionStrategy invalidSessionStrategy; + private SessionInformationExpiredStrategy expiredSessionStrategy; + private List sessionAuthenticationStrategies = new ArrayList<>(); + private SessionRegistry sessionRegistry; + private Integer maximumSessions; + private String expiredUrl; + private boolean maxSessionsPreventsLogin; + private SessionCreationPolicy sessionPolicy; + private boolean enableSessionUrlRewriting; + private String invalidSessionUrl; + private String sessionAuthenticationErrorUrl; + private AuthenticationFailureHandler sessionAuthenticationFailureHandler; /** @@ -127,7 +143,6 @@ public final class SessionManagementConfigurer> * {@link SimpleRedirectInvalidSessionStrategy} configured with the attribute value. * When an invalid session ID is submitted, the strategy will be invoked, redirecting * to the configured URL. - * * @param invalidSessionUrl the URL to redirect to when an invalid session is detected * @return the {@link SessionManagementConfigurer} for further customization */ @@ -144,8 +159,7 @@ public final class SessionManagementConfigurer> * submitted. * @return the {@link SessionManagementConfigurer} for further customization */ - public SessionManagementConfigurer invalidSessionStrategy( - InvalidSessionStrategy invalidSessionStrategy) { + public SessionManagementConfigurer invalidSessionStrategy(InvalidSessionStrategy invalidSessionStrategy) { Assert.notNull(invalidSessionStrategy, "invalidSessionStrategy"); this.invalidSessionStrategy = invalidSessionStrategy; return this; @@ -157,12 +171,10 @@ public final class SessionManagementConfigurer> * (402) error code will be returned to the client. Note that this attribute doesn't * apply if the error occurs during a form-based login, where the URL for * authentication failure will take precedence. - * * @param sessionAuthenticationErrorUrl the URL to redirect to * @return the {@link SessionManagementConfigurer} for further customization */ - public SessionManagementConfigurer sessionAuthenticationErrorUrl( - String sessionAuthenticationErrorUrl) { + public SessionManagementConfigurer sessionAuthenticationErrorUrl(String sessionAuthenticationErrorUrl) { this.sessionAuthenticationErrorUrl = sessionAuthenticationErrorUrl; return this; } @@ -173,7 +185,6 @@ public final class SessionManagementConfigurer> * (402) error code will be returned to the client. Note that this attribute doesn't * apply if the error occurs during a form-based login, where the URL for * authentication failure will take precedence. - * * @param sessionAuthenticationFailureHandler the handler to use * @return the {@link SessionManagementConfigurer} for further customization */ @@ -188,14 +199,12 @@ public final class SessionManagementConfigurer> * {@link HttpServletResponse#encodeRedirectURL(String)} or * {@link HttpServletResponse#encodeURL(String)}, otherwise disallows HTTP sessions to * be included in the URL. This prevents leaking information to external domains. - * * @param enableSessionUrlRewriting true if should allow the JSESSIONID to be * rewritten into the URLs, else false (default) * @return the {@link SessionManagementConfigurer} for further customization * @see HttpSessionSecurityContextRepository#setDisableUrlRewriting(boolean) */ - public SessionManagementConfigurer enableSessionUrlRewriting( - boolean enableSessionUrlRewriting) { + public SessionManagementConfigurer enableSessionUrlRewriting(boolean enableSessionUrlRewriting) { this.enableSessionUrlRewriting = enableSessionUrlRewriting; return this; } @@ -208,26 +217,24 @@ public final class SessionManagementConfigurer> * @see SessionCreationPolicy * @throws IllegalArgumentException if {@link SessionCreationPolicy} is null. */ - public SessionManagementConfigurer sessionCreationPolicy( - SessionCreationPolicy sessionCreationPolicy) { + public SessionManagementConfigurer sessionCreationPolicy(SessionCreationPolicy sessionCreationPolicy) { Assert.notNull(sessionCreationPolicy, "sessionCreationPolicy cannot be null"); this.sessionPolicy = sessionCreationPolicy; return this; } /** - * Allows explicitly specifying the {@link SessionAuthenticationStrategy}. - * The default is to use {@link ChangeSessionIdAuthenticationStrategy}. - * If restricting the maximum number of sessions is configured, then + * Allows explicitly specifying the {@link SessionAuthenticationStrategy}. The default + * is to use {@link ChangeSessionIdAuthenticationStrategy}. If restricting the maximum + * number of sessions is configured, then * {@link CompositeSessionAuthenticationStrategy} delegating to - * {@link ConcurrentSessionControlAuthenticationStrategy}, - * the default OR supplied {@code SessionAuthenticationStrategy} and + * {@link ConcurrentSessionControlAuthenticationStrategy}, the default OR supplied + * {@code SessionAuthenticationStrategy} and * {@link RegisterSessionAuthenticationStrategy}. * *

      * NOTE: Supplying a custom {@link SessionAuthenticationStrategy} will override the * default session fixation strategy. - * * @param sessionAuthenticationStrategy * @return the {@link SessionManagementConfigurer} for further customizations */ @@ -240,7 +247,6 @@ public final class SessionManagementConfigurer> /** * Adds an additional {@link SessionAuthenticationStrategy} to be used within the * {@link CompositeSessionAuthenticationStrategy}. - * * @param sessionAuthenticationStrategy * @return the {@link SessionManagementConfigurer} for further customizations */ @@ -252,7 +258,6 @@ public final class SessionManagementConfigurer> /** * Allows changing the default {@link SessionFixationProtectionStrategy}. - * * @return the {@link SessionFixationConfigurer} for further customizations */ public SessionFixationConfigurer sessionFixation() { @@ -261,12 +266,12 @@ public final class SessionManagementConfigurer> /** * Allows configuring session fixation protection. - * * @param sessionFixationCustomizer the {@link Customizer} to provide more options for * the {@link SessionFixationConfigurer} * @return the {@link SessionManagementConfigurer} for further customizations */ - public SessionManagementConfigurer sessionFixation(Customizer sessionFixationCustomizer) { + public SessionManagementConfigurer sessionFixation( + Customizer sessionFixationCustomizer) { sessionFixationCustomizer.customize(new SessionFixationConfigurer()); return this; } @@ -285,12 +290,12 @@ public final class SessionManagementConfigurer> /** * Controls the maximum number of sessions for a user. The default is to allow any * number of users. - * - * @param sessionConcurrencyCustomizer the {@link Customizer} to provide more options for - * the {@link ConcurrencyControlConfigurer} + * @param sessionConcurrencyCustomizer the {@link Customizer} to provide more options + * for the {@link ConcurrencyControlConfigurer} * @return the {@link SessionManagementConfigurer} for further customizations */ - public SessionManagementConfigurer sessionConcurrency(Customizer sessionConcurrencyCustomizer) { + public SessionManagementConfigurer sessionConcurrency( + Customizer sessionConcurrencyCustomizer) { sessionConcurrencyCustomizer.customize(new ConcurrencyControlConfigurer()); return this; } @@ -302,8 +307,7 @@ public final class SessionManagementConfigurer> */ private void setSessionFixationAuthenticationStrategy( SessionAuthenticationStrategy sessionFixationAuthenticationStrategy) { - this.sessionFixationAuthenticationStrategy = postProcess( - sessionFixationAuthenticationStrategy); + this.sessionFixationAuthenticationStrategy = postProcess(sessionFixationAuthenticationStrategy); } /** @@ -312,10 +316,10 @@ public final class SessionManagementConfigurer> * @author Rob Winch */ public final class SessionFixationConfigurer { + /** * Specifies that a new session should be created, but the session attributes from * the original {@link HttpSession} should not be retained. - * * @return the {@link SessionManagementConfigurer} for further customizations */ public SessionManagementConfigurer newSession() { @@ -328,12 +332,10 @@ public final class SessionManagementConfigurer> /** * Specifies that a new session should be created and the session attributes from * the original {@link HttpSession} should be retained. - * * @return the {@link SessionManagementConfigurer} for further customizations */ public SessionManagementConfigurer migrateSession() { - setSessionFixationAuthenticationStrategy( - new SessionFixationProtectionStrategy()); + setSessionFixationAuthenticationStrategy(new SessionFixationProtectionStrategy()); return SessionManagementConfigurer.this; } @@ -342,12 +344,10 @@ public final class SessionManagementConfigurer> * should be used. When a session authenticates, the Servlet method * {@code HttpServletRequest#changeSessionId()} is called to change the session ID * and retain all session attributes. - * * @return the {@link SessionManagementConfigurer} for further customizations */ public SessionManagementConfigurer changeSessionId() { - setSessionFixationAuthenticationStrategy( - new ChangeSessionIdAuthenticationStrategy()); + setSessionFixationAuthenticationStrategy(new ChangeSessionIdAuthenticationStrategy()); return SessionManagementConfigurer.this; } @@ -356,14 +356,13 @@ public final class SessionManagementConfigurer> * useful when utilizing other mechanisms for protecting against session fixation. * For example, if application container session fixation protection is already in * use. Otherwise, this option is not recommended. - * * @return the {@link SessionManagementConfigurer} for further customizations */ public SessionManagementConfigurer none() { - setSessionFixationAuthenticationStrategy( - new NullAuthenticatedSessionStrategy()); + setSessionFixationAuthenticationStrategy(new NullAuthenticatedSessionStrategy()); return SessionManagementConfigurer.this; } + } /** @@ -376,7 +375,6 @@ public final class SessionManagementConfigurer> /** * Controls the maximum number of sessions for a user. The default is to allow any * number of users. - * * @param maximumSessions the maximum number of sessions for a user * @return the {@link ConcurrencyControlConfigurer} for further customizations */ @@ -389,7 +387,6 @@ public final class SessionManagementConfigurer> * The URL to redirect to if a user tries to access a resource and their session * has been expired due to too many sessions for the current user. The default is * to write a simple error message to the response. - * * @param expiredUrl the URL to redirect to * @return the {@link ConcurrencyControlConfigurer} for further customizations */ @@ -400,7 +397,6 @@ public final class SessionManagementConfigurer> /** * Determines the behaviour when an expired session is detected. - * * @param expiredSessionStrategy the {@link SessionInformationExpiredStrategy} to * use when an expired session is detected. * @return the {@link ConcurrencyControlConfigurer} for further customizations @@ -419,13 +415,11 @@ public final class SessionManagementConfigurer> * {@link #expiredUrl(String)}. The advantage of this approach is if a user * accidentally does not log out, there is no need for an administrator to * intervene or wait till their session expires. - * * @param maxSessionsPreventsLogin true to have an error at time of * authentication, else false (default) * @return the {@link ConcurrencyControlConfigurer} for further customizations */ - public ConcurrencyControlConfigurer maxSessionsPreventsLogin( - boolean maxSessionsPreventsLogin) { + public ConcurrencyControlConfigurer maxSessionsPreventsLogin(boolean maxSessionsPreventsLogin) { SessionManagementConfigurer.this.maxSessionsPreventsLogin = maxSessionsPreventsLogin; return this; } @@ -433,19 +427,16 @@ public final class SessionManagementConfigurer> /** * Controls the {@link SessionRegistry} implementation used. The default is * {@link SessionRegistryImpl} which is an in memory implementation. - * * @param sessionRegistry the {@link SessionRegistry} to use * @return the {@link ConcurrencyControlConfigurer} for further customizations */ - public ConcurrencyControlConfigurer sessionRegistry( - SessionRegistry sessionRegistry) { + public ConcurrencyControlConfigurer sessionRegistry(SessionRegistry sessionRegistry) { SessionManagementConfigurer.this.sessionRegistry = sessionRegistry; return this; } /** * Used to chain back to the {@link SessionManagementConfigurer} - * * @return the {@link SessionManagementConfigurer} for further customizations */ public SessionManagementConfigurer and() { @@ -454,31 +445,27 @@ public final class SessionManagementConfigurer> private ConcurrencyControlConfigurer() { } + } @Override public void init(H http) { - SecurityContextRepository securityContextRepository = http - .getSharedObject(SecurityContextRepository.class); + SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class); boolean stateless = isStateless(); if (securityContextRepository == null) { if (stateless) { - http.setSharedObject(SecurityContextRepository.class, - new NullSecurityContextRepository()); + http.setSharedObject(SecurityContextRepository.class, new NullSecurityContextRepository()); } else { HttpSessionSecurityContextRepository httpSecurityRepository = new HttpSessionSecurityContextRepository(); - httpSecurityRepository - .setDisableUrlRewriting(!this.enableSessionUrlRewriting); + httpSecurityRepository.setDisableUrlRewriting(!this.enableSessionUrlRewriting); httpSecurityRepository.setAllowSessionCreation(isAllowSessionCreation()); - AuthenticationTrustResolver trustResolver = http - .getSharedObject(AuthenticationTrustResolver.class); + AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class); if (trustResolver != null) { httpSecurityRepository.setTrustResolver(trustResolver); } - http.setSharedObject(SecurityContextRepository.class, - httpSecurityRepository); + http.setSharedObject(SecurityContextRepository.class, httpSecurityRepository); } } @@ -488,21 +475,18 @@ public final class SessionManagementConfigurer> http.setSharedObject(RequestCache.class, new NullRequestCache()); } } - http.setSharedObject(SessionAuthenticationStrategy.class, - getSessionAuthenticationStrategy(http)); + http.setSharedObject(SessionAuthenticationStrategy.class, getSessionAuthenticationStrategy(http)); http.setSharedObject(InvalidSessionStrategy.class, getInvalidSessionStrategy()); } @Override public void configure(H http) { - SecurityContextRepository securityContextRepository = http - .getSharedObject(SecurityContextRepository.class); - SessionManagementFilter sessionManagementFilter = new SessionManagementFilter( - securityContextRepository, getSessionAuthenticationStrategy(http)); + SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class); + SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(securityContextRepository, + getSessionAuthenticationStrategy(http)); if (this.sessionAuthenticationErrorUrl != null) { sessionManagementFilter.setAuthenticationFailureHandler( - new SimpleUrlAuthenticationFailureHandler( - this.sessionAuthenticationErrorUrl)); + new SimpleUrlAuthenticationFailureHandler(this.sessionAuthenticationErrorUrl)); } InvalidSessionStrategy strategy = getInvalidSessionStrategy(); if (strategy != null) { @@ -512,8 +496,7 @@ public final class SessionManagementConfigurer> if (failureHandler != null) { sessionManagementFilter.setAuthenticationFailureHandler(failureHandler); } - AuthenticationTrustResolver trustResolver = http - .getSharedObject(AuthenticationTrustResolver.class); + AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class); if (trustResolver != null) { sessionManagementFilter.setTrustResolver(trustResolver); } @@ -534,7 +517,8 @@ public final class SessionManagementConfigurer> ConcurrentSessionFilter concurrentSessionFilter; if (expireStrategy == null) { concurrentSessionFilter = new ConcurrentSessionFilter(sessionRegistry); - } else { + } + else { concurrentSessionFilter = new ConcurrentSessionFilter(sessionRegistry, expireStrategy); } LogoutConfigurer logoutConfigurer = http.getConfigurer(LogoutConfigurer.class); @@ -551,7 +535,6 @@ public final class SessionManagementConfigurer> * Gets the {@link InvalidSessionStrategy} to use. If null and * {@link #invalidSessionUrl} is not null defaults to * {@link SimpleRedirectInvalidSessionStrategy}. - * * @return the {@link InvalidSessionStrategy} to use */ InvalidSessionStrategy getInvalidSessionStrategy() { @@ -563,8 +546,7 @@ public final class SessionManagementConfigurer> return null; } - this.invalidSessionStrategy = new SimpleRedirectInvalidSessionStrategy( - this.invalidSessionUrl); + this.invalidSessionStrategy = new SimpleRedirectInvalidSessionStrategy(this.invalidSessionUrl); return this.invalidSessionStrategy; } @@ -577,8 +559,7 @@ public final class SessionManagementConfigurer> return null; } - this.expiredSessionStrategy = new SimpleRedirectSessionInformationExpiredStrategy( - this.expiredUrl); + this.expiredSessionStrategy = new SimpleRedirectSessionInformationExpiredStrategy(this.expiredUrl); return this.expiredSessionStrategy; } @@ -605,10 +586,8 @@ public final class SessionManagementConfigurer> return this.sessionPolicy; } - SessionCreationPolicy sessionPolicy = - getBuilder().getSharedObject(SessionCreationPolicy.class); - return sessionPolicy == null ? - SessionCreationPolicy.IF_REQUIRED : sessionPolicy; + SessionCreationPolicy sessionPolicy = getBuilder().getSharedObject(SessionCreationPolicy.class); + return sessionPolicy == null ? SessionCreationPolicy.IF_REQUIRED : sessionPolicy; } /** @@ -618,8 +597,7 @@ public final class SessionManagementConfigurer> */ private boolean isAllowSessionCreation() { SessionCreationPolicy sessionPolicy = getSessionCreationPolicy(); - return SessionCreationPolicy.ALWAYS == sessionPolicy - || SessionCreationPolicy.IF_REQUIRED == sessionPolicy; + return SessionCreationPolicy.ALWAYS == sessionPolicy || SessionCreationPolicy.IF_REQUIRED == sessionPolicy; } /** @@ -635,7 +613,6 @@ public final class SessionManagementConfigurer> * Gets the customized {@link SessionAuthenticationStrategy} if * {@link #sessionAuthenticationStrategy(SessionAuthenticationStrategy)} was * specified. Otherwise creates a default {@link SessionAuthenticationStrategy}. - * * @return the {@link SessionAuthenticationStrategy} to use */ private SessionAuthenticationStrategy getSessionAuthenticationStrategy(H http) { @@ -647,8 +624,7 @@ public final class SessionManagementConfigurer> if (this.providedSessionAuthenticationStrategy == null) { // If the user did not provide a SessionAuthenticationStrategy // then default to sessionFixationAuthenticationStrategy - defaultSessionAuthenticationStrategy = postProcess( - this.sessionFixationAuthenticationStrategy); + defaultSessionAuthenticationStrategy = postProcess(this.sessionFixationAuthenticationStrategy); } else { defaultSessionAuthenticationStrategy = this.providedSessionAuthenticationStrategy; @@ -658,10 +634,8 @@ public final class SessionManagementConfigurer> ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlStrategy = new ConcurrentSessionControlAuthenticationStrategy( sessionRegistry); concurrentSessionControlStrategy.setMaximumSessions(this.maximumSessions); - concurrentSessionControlStrategy - .setExceptionIfMaximumExceeded(this.maxSessionsPreventsLogin); - concurrentSessionControlStrategy = postProcess( - concurrentSessionControlStrategy); + concurrentSessionControlStrategy.setExceptionIfMaximumExceeded(this.maxSessionsPreventsLogin); + concurrentSessionControlStrategy = postProcess(concurrentSessionControlStrategy); RegisterSessionAuthenticationStrategy registerSessionStrategy = new RegisterSessionAuthenticationStrategy( sessionRegistry); @@ -690,14 +664,12 @@ public final class SessionManagementConfigurer> return this.sessionRegistry; } - private void registerDelegateApplicationListener(H http, - ApplicationListener delegate) { + private void registerDelegateApplicationListener(H http, ApplicationListener delegate) { DelegatingApplicationListener delegating = getBeanOrNull(DelegatingApplicationListener.class); if (delegating == null) { return; } - SmartApplicationListener smartListener = new GenericApplicationListenerAdapter( - delegate); + SmartApplicationListener smartListener = new GenericApplicationListenerAdapter(delegate); delegating.addListener(smartListener); } @@ -714,7 +686,7 @@ public final class SessionManagementConfigurer> * @return the default {@link SessionAuthenticationStrategy} for session fixation */ private static SessionAuthenticationStrategy createDefaultSessionFixationProtectionStrategy() { - return new ChangeSessionIdAuthenticationStrategy(); + return new ChangeSessionIdAuthenticationStrategy(); } private T getBeanOrNull(Class type) { @@ -729,4 +701,5 @@ public final class SessionManagementConfigurer> return null; } } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java index ec653cb5fb..7eb350a744 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java @@ -77,18 +77,17 @@ import org.springframework.util.Assert; * The following shared objects are used: * *

        - *
      • - * AuthenticationManager
      • + *
      • AuthenticationManager
      • *
      * * @param the type of {@link HttpSecurityBuilder} that is being configured - * * @author Rob Winch * @since 3.2 * @see ExpressionUrlAuthorizationConfigurer */ -public final class UrlAuthorizationConfigurer> extends - AbstractInterceptUrlConfigurer, H> { +public final class UrlAuthorizationConfigurer> + extends AbstractInterceptUrlConfigurer, H> { + private final StandardInterceptUrlRegistry REGISTRY; public UrlAuthorizationConfigurer(ApplicationContext context) { @@ -98,7 +97,6 @@ public final class UrlAuthorizationConfigurer> /** * The StandardInterceptUrlRegistry is what users will interact with after applying * the {@link UrlAuthorizationConfigurer}. - * * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customizations */ public StandardInterceptUrlRegistry getRegistry() { @@ -107,18 +105,15 @@ public final class UrlAuthorizationConfigurer> /** * Adds an {@link ObjectPostProcessor} for this class. - * * @param objectPostProcessor * @return the {@link UrlAuthorizationConfigurer} for further customizations */ - public UrlAuthorizationConfigurer withObjectPostProcessor( - ObjectPostProcessor objectPostProcessor) { + public UrlAuthorizationConfigurer withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { addObjectPostProcessor(objectPostProcessor); return this; } - public class StandardInterceptUrlRegistry - extends + public class StandardInterceptUrlRegistry extends ExpressionUrlAuthorizationConfigurer.AbstractInterceptUrlRegistry { /** @@ -129,8 +124,7 @@ public final class UrlAuthorizationConfigurer> } @Override - public MvcMatchersAuthorizedUrl mvcMatchers(HttpMethod method, - String... mvcPatterns) { + public MvcMatchersAuthorizedUrl mvcMatchers(HttpMethod method, String... mvcPatterns) { return new MvcMatchersAuthorizedUrl(createMvcMatchers(method, mvcPatterns)); } @@ -140,20 +134,17 @@ public final class UrlAuthorizationConfigurer> } @Override - protected final AuthorizedUrl chainRequestMatchersInternal( - List requestMatchers) { + protected final AuthorizedUrl chainRequestMatchersInternal(List requestMatchers) { return new AuthorizedUrl(requestMatchers); } /** * Adds an {@link ObjectPostProcessor} for this class. - * * @param objectPostProcessor * @return the {@link ExpressionUrlAuthorizationConfigurer} for further * customizations */ - public StandardInterceptUrlRegistry withObjectPostProcessor( - ObjectPostProcessor objectPostProcessor) { + public StandardInterceptUrlRegistry withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { addObjectPostProcessor(objectPostProcessor); return this; } @@ -167,7 +158,6 @@ public final class UrlAuthorizationConfigurer> /** * Creates the default {@link AccessDecisionVoter} instances used if an * {@link AccessDecisionManager} was not specified. - * * @param http the builder to use */ @Override @@ -182,13 +172,11 @@ public final class UrlAuthorizationConfigurer> /** * Creates the {@link FilterInvocationSecurityMetadataSource} to use. The * implementation is a {@link DefaultFilterInvocationSecurityMetadataSource}. - * * @param http the builder to use */ @Override FilterInvocationSecurityMetadataSource createMetadataSource(H http) { - return new DefaultFilterInvocationSecurityMetadataSource( - REGISTRY.createRequestMap()); + return new DefaultFilterInvocationSecurityMetadataSource(REGISTRY.createRequestMap()); } /** @@ -200,34 +188,29 @@ public final class UrlAuthorizationConfigurer> * by the {@link RequestMatcher} instances * @return the {@link ExpressionUrlAuthorizationConfigurer} for further customizations */ - private StandardInterceptUrlRegistry addMapping( - Iterable requestMatchers, + private StandardInterceptUrlRegistry addMapping(Iterable requestMatchers, Collection configAttributes) { for (RequestMatcher requestMatcher : requestMatchers) { - REGISTRY.addMapping(new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping( - requestMatcher, configAttributes)); + REGISTRY.addMapping( + new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping(requestMatcher, configAttributes)); } return REGISTRY; } /** * Creates a String for specifying a user requires a role. - * * @param role the role that should be required which is prepended with ROLE_ * automatically (i.e. USER, ADMIN, etc). It should not start with ROLE_ * @return the {@link ConfigAttribute} expressed as a String */ private static String hasRole(String role) { - Assert.isTrue( - !role.startsWith("ROLE_"), - () -> role - + " should not start with ROLE_ since ROLE_ is automatically prepended when using hasRole. Consider using hasAuthority or access instead."); + Assert.isTrue(!role.startsWith("ROLE_"), () -> role + + " should not start with ROLE_ since ROLE_ is automatically prepended when using hasRole. Consider using hasAuthority or access instead."); return "ROLE_" + role; } /** * Creates a String for specifying that a user requires one of many roles. - * * @param roles the roles that the user should have at least one of (i.e. ADMIN, USER, * etc). Each role should not start with ROLE_ since it is automatically prepended * already. @@ -257,9 +240,9 @@ public final class UrlAuthorizationConfigurer> * @author Rob Winch */ public final class MvcMatchersAuthorizedUrl extends AuthorizedUrl { + /** * Creates a new instance - * * @param requestMatchers the {@link RequestMatcher} instances to map */ private MvcMatchersAuthorizedUrl(List requestMatchers) { @@ -273,6 +256,7 @@ public final class UrlAuthorizationConfigurer> } return this; } + } /** @@ -283,6 +267,7 @@ public final class UrlAuthorizationConfigurer> * @since 3.2 */ public class AuthorizedUrl { + private final List requestMatchers; /** @@ -291,14 +276,12 @@ public final class UrlAuthorizationConfigurer> * {@link ConfigAttribute} instances. */ private AuthorizedUrl(List requestMatchers) { - Assert.notEmpty(requestMatchers, - "requestMatchers must contain at least one value"); + Assert.notEmpty(requestMatchers, "requestMatchers must contain at least one value"); this.requestMatchers = requestMatchers; } /** * Specifies a user requires a role. - * * @param role the role that should be required which is prepended with ROLE_ * automatically (i.e. USER, ADMIN, etc). It should not start with ROLE_ the * {@link UrlAuthorizationConfigurer} for further customization @@ -309,7 +292,6 @@ public final class UrlAuthorizationConfigurer> /** * Specifies that a user requires one of many roles. - * * @param roles the roles that the user should have at least one of (i.e. ADMIN, * USER, etc). Each role should not start with ROLE_ since it is automatically * prepended already. @@ -321,7 +303,6 @@ public final class UrlAuthorizationConfigurer> /** * Specifies a user requires an authority. - * * @param authority the authority that should be required * @return the {@link UrlAuthorizationConfigurer} for further customization */ @@ -360,5 +341,7 @@ public final class UrlAuthorizationConfigurer> protected List getMatchers() { return this.requestMatchers; } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java index 55d56086ed..6faa1649f3 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java @@ -53,8 +53,7 @@ import javax.servlet.http.HttpServletRequest; * The following shared objects are created * *
        - *
      • - * {@link AuthenticationEntryPoint} is populated with an + *
      • {@link AuthenticationEntryPoint} is populated with an * {@link Http403ForbiddenEntryPoint}
      • *
      • A {@link PreAuthenticatedAuthenticationProvider} is populated into * {@link HttpSecurity#authenticationProvider(org.springframework.security.authentication.AuthenticationProvider)} @@ -73,11 +72,15 @@ import javax.servlet.http.HttpServletRequest; * @author Rob Winch * @since 3.2 */ -public final class X509Configurer> extends - AbstractHttpConfigurer, H> { +public final class X509Configurer> + extends AbstractHttpConfigurer, H> { + private X509AuthenticationFilter x509AuthenticationFilter; + private X509PrincipalExtractor x509PrincipalExtractor; + private AuthenticationUserDetailsService authenticationUserDetailsService; + private AuthenticationDetailsSource authenticationDetailsSource; /** @@ -92,19 +95,16 @@ public final class X509Configurer> extends * Allows specifying the entire {@link X509AuthenticationFilter}. If this is * specified, the properties on {@link X509Configurer} will not be populated on the * {@link X509AuthenticationFilter}. - * * @param x509AuthenticationFilter the {@link X509AuthenticationFilter} to use * @return the {@link X509Configurer} for further customizations */ - public X509Configurer x509AuthenticationFilter( - X509AuthenticationFilter x509AuthenticationFilter) { + public X509Configurer x509AuthenticationFilter(X509AuthenticationFilter x509AuthenticationFilter) { this.x509AuthenticationFilter = x509AuthenticationFilter; return this; } /** * Specifies the {@link X509PrincipalExtractor} - * * @param x509PrincipalExtractor the {@link X509PrincipalExtractor} to use * @return the {@link X509Configurer} to use */ @@ -115,7 +115,6 @@ public final class X509Configurer> extends /** * Specifies the {@link AuthenticationDetailsSource} - * * @param authenticationDetailsSource the {@link AuthenticationDetailsSource} to use * @return the {@link X509Configurer} to use */ @@ -129,7 +128,6 @@ public final class X509Configurer> extends * Shortcut for invoking * {@link #authenticationUserDetailsService(AuthenticationUserDetailsService)} with a * {@link UserDetailsByNameServiceWrapper}. - * * @param userDetailsService the {@link UserDetailsService} to use * @return the {@link X509Configurer} for further customizations */ @@ -143,8 +141,8 @@ public final class X509Configurer> extends * Specifies the {@link AuthenticationUserDetailsService} to use. If not specified, * the shared {@link UserDetailsService} will be used to create a * {@link UserDetailsByNameServiceWrapper}. - * - * @param authenticationUserDetailsService the {@link AuthenticationUserDetailsService} to use + * @param authenticationUserDetailsService the + * {@link AuthenticationUserDetailsService} to use * @return the {@link X509Configurer} for further customizations */ public X509Configurer authenticationUserDetailsService( @@ -157,9 +155,8 @@ public final class X509Configurer> extends * Specifies the regex to extract the principal from the certificate. If not * specified, the default expression from {@link SubjectDnX509PrincipalExtractor} is * used. - * * @param subjectPrincipalRegex the regex to extract the user principal from the - * certificate (i.e. "CN=(.*?)(?:,|$)"). + * certificate (i.e. "CN=(.*?)(?:,|$)"). * @return the {@link X509Configurer} for further customizations */ public X509Configurer subjectPrincipalRegex(String subjectPrincipalRegex) { @@ -183,8 +180,7 @@ public final class X509Configurer> extends @Override public void configure(H http) { - X509AuthenticationFilter filter = getFilter(http - .getSharedObject(AuthenticationManager.class)); + X509AuthenticationFilter filter = getFilter(http.getSharedObject(AuthenticationManager.class)); http.addFilter(filter); } @@ -196,8 +192,7 @@ public final class X509Configurer> extends x509AuthenticationFilter.setPrincipalExtractor(x509PrincipalExtractor); } if (authenticationDetailsSource != null) { - x509AuthenticationFilter - .setAuthenticationDetailsSource(authenticationDetailsSource); + x509AuthenticationFilter.setAuthenticationDetailsSource(authenticationDetailsSource); } x509AuthenticationFilter = postProcess(x509AuthenticationFilter); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/ImplicitGrantConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/ImplicitGrantConfigurer.java index ccfff084db..30d96b3b88 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/ImplicitGrantConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/ImplicitGrantConfigurer.java @@ -48,26 +48,26 @@ import org.springframework.util.Assert; *
      • {@link ClientRegistrationRepository}
      • *
      * - * @deprecated It is not recommended to use the implicit flow - * due to the inherent risks of returning access tokens in an HTTP redirect - * without any confirmation that it has been received by the client. - * See reference OAuth 2.0 Implicit Grant. - * + * @deprecated It is not recommended to use the implicit flow due to the inherent risks of + * returning access tokens in an HTTP redirect without any confirmation that it has been + * received by the client. See reference + * OAuth 2.0 Implicit + * Grant. * @author Joe Grandja * @since 5.0 * @see OAuth2AuthorizationRequestRedirectFilter * @see ClientRegistrationRepository */ @Deprecated -public final class ImplicitGrantConfigurer> extends - AbstractHttpConfigurer, B> { +public final class ImplicitGrantConfigurer> + extends AbstractHttpConfigurer, B> { private String authorizationRequestBaseUri; /** * Sets the base {@code URI} used for authorization requests. - * - * @param authorizationRequestBaseUri the base {@code URI} used for authorization requests + * @param authorizationRequestBaseUri the base {@code URI} used for authorization + * requests * @return the {@link ImplicitGrantConfigurer} for further configuration */ public ImplicitGrantConfigurer authorizationRequestBaseUri(String authorizationRequestBaseUri) { @@ -78,11 +78,11 @@ public final class ImplicitGrantConfigurer> ext /** * Sets the repository of client registrations. - * * @param clientRegistrationRepository the repository of client registrations * @return the {@link ImplicitGrantConfigurer} for further configuration */ - public ImplicitGrantConfigurer clientRegistrationRepository(ClientRegistrationRepository clientRegistrationRepository) { + public ImplicitGrantConfigurer clientRegistrationRepository( + ClientRegistrationRepository clientRegistrationRepository) { Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null"); this.getBuilder().setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository); return this; @@ -91,13 +91,14 @@ public final class ImplicitGrantConfigurer> ext @Override public void configure(B http) { OAuth2AuthorizationRequestRedirectFilter authorizationRequestFilter = new OAuth2AuthorizationRequestRedirectFilter( - OAuth2ClientConfigurerUtils.getClientRegistrationRepository(this.getBuilder()), this.getAuthorizationRequestBaseUri()); + OAuth2ClientConfigurerUtils.getClientRegistrationRepository(this.getBuilder()), + this.getAuthorizationRequestBaseUri()); http.addFilter(this.postProcess(authorizationRequestFilter)); } private String getAuthorizationRequestBaseUri() { - return this.authorizationRequestBaseUri != null ? - this.authorizationRequestBaseUri : - OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI; + return this.authorizationRequestBaseUri != null ? this.authorizationRequestBaseUri + : OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI; } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java index af2f56e0cd..b504c8d6f8 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java @@ -43,13 +43,15 @@ import org.springframework.util.Assert; * The following configuration options are available: * *
        - *
      • {@link #authorizationCodeGrant()} - support for the OAuth 2.0 Authorization Code Grant
      • + *
      • {@link #authorizationCodeGrant()} - support for the OAuth 2.0 Authorization Code + * Grant
      • *
      * *

      - * Defaults are provided for all configuration options with the only required configuration - * being {@link #clientRegistrationRepository(ClientRegistrationRepository)}. - * Alternatively, a {@link ClientRegistrationRepository} {@code @Bean} may be registered instead. + * Defaults are provided for all configuration options with the only required + * configuration being + * {@link #clientRegistrationRepository(ClientRegistrationRepository)}. Alternatively, a + * {@link ClientRegistrationRepository} {@code @Bean} may be registered instead. * *

      Security Filters

      * @@ -87,18 +89,18 @@ import org.springframework.util.Assert; * @see OAuth2AuthorizedClientRepository * @see AbstractHttpConfigurer */ -public final class OAuth2ClientConfigurer> extends - AbstractHttpConfigurer, B> { +public final class OAuth2ClientConfigurer> + extends AbstractHttpConfigurer, B> { private AuthorizationCodeGrantConfigurer authorizationCodeGrantConfigurer = new AuthorizationCodeGrantConfigurer(); /** * Sets the repository of client registrations. - * * @param clientRegistrationRepository the repository of client registrations * @return the {@link OAuth2ClientConfigurer} for further configuration */ - public OAuth2ClientConfigurer clientRegistrationRepository(ClientRegistrationRepository clientRegistrationRepository) { + public OAuth2ClientConfigurer clientRegistrationRepository( + ClientRegistrationRepository clientRegistrationRepository) { Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null"); this.getBuilder().setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository); return this; @@ -106,11 +108,11 @@ public final class OAuth2ClientConfigurer> exte /** * Sets the repository for authorized client(s). - * * @param authorizedClientRepository the authorized client repository * @return the {@link OAuth2ClientConfigurer} for further configuration */ - public OAuth2ClientConfigurer authorizedClientRepository(OAuth2AuthorizedClientRepository authorizedClientRepository) { + public OAuth2ClientConfigurer authorizedClientRepository( + OAuth2AuthorizedClientRepository authorizedClientRepository) { Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null"); this.getBuilder().setSharedObject(OAuth2AuthorizedClientRepository.class, authorizedClientRepository); return this; @@ -118,19 +120,19 @@ public final class OAuth2ClientConfigurer> exte /** * Sets the service for authorized client(s). - * * @param authorizedClientService the authorized client service * @return the {@link OAuth2ClientConfigurer} for further configuration */ public OAuth2ClientConfigurer authorizedClientService(OAuth2AuthorizedClientService authorizedClientService) { Assert.notNull(authorizedClientService, "authorizedClientService cannot be null"); - this.authorizedClientRepository(new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService)); + this.authorizedClientRepository( + new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService)); return this; } /** - * Returns the {@link AuthorizationCodeGrantConfigurer} for configuring the OAuth 2.0 Authorization Code Grant. - * + * Returns the {@link AuthorizationCodeGrantConfigurer} for configuring the OAuth 2.0 + * Authorization Code Grant. * @return the {@link AuthorizationCodeGrantConfigurer} */ public AuthorizationCodeGrantConfigurer authorizationCodeGrant() { @@ -139,12 +141,12 @@ public final class OAuth2ClientConfigurer> exte /** * Configures the OAuth 2.0 Authorization Code Grant. - * - * @param authorizationCodeGrantCustomizer the {@link Customizer} to provide more options for - * the {@link AuthorizationCodeGrantConfigurer} + * @param authorizationCodeGrantCustomizer the {@link Customizer} to provide more + * options for the {@link AuthorizationCodeGrantConfigurer} * @return the {@link OAuth2ClientConfigurer} for further customizations */ - public OAuth2ClientConfigurer authorizationCodeGrant(Customizer authorizationCodeGrantCustomizer) { + public OAuth2ClientConfigurer authorizationCodeGrant( + Customizer authorizationCodeGrantCustomizer) { authorizationCodeGrantCustomizer.customize(this.authorizationCodeGrantConfigurer); return this; } @@ -153,8 +155,11 @@ public final class OAuth2ClientConfigurer> exte * Configuration options for the OAuth 2.0 Authorization Code Grant. */ public class AuthorizationCodeGrantConfigurer { + private OAuth2AuthorizationRequestResolver authorizationRequestResolver; + private AuthorizationRequestRepository authorizationRequestRepository; + private OAuth2AccessTokenResponseClient accessTokenResponseClient; private AuthorizationCodeGrantConfigurer() { @@ -162,11 +167,12 @@ public final class OAuth2ClientConfigurer> exte /** * Sets the resolver used for resolving {@link OAuth2AuthorizationRequest}'s. - * - * @param authorizationRequestResolver the resolver used for resolving {@link OAuth2AuthorizationRequest}'s + * @param authorizationRequestResolver the resolver used for resolving + * {@link OAuth2AuthorizationRequest}'s * @return the {@link AuthorizationCodeGrantConfigurer} for further configuration */ - public AuthorizationCodeGrantConfigurer authorizationRequestResolver(OAuth2AuthorizationRequestResolver authorizationRequestResolver) { + public AuthorizationCodeGrantConfigurer authorizationRequestResolver( + OAuth2AuthorizationRequestResolver authorizationRequestResolver) { Assert.notNull(authorizationRequestResolver, "authorizationRequestResolver cannot be null"); this.authorizationRequestResolver = authorizationRequestResolver; return this; @@ -174,8 +180,8 @@ public final class OAuth2ClientConfigurer> exte /** * Sets the repository used for storing {@link OAuth2AuthorizationRequest}'s. - * - * @param authorizationRequestRepository the repository used for storing {@link OAuth2AuthorizationRequest}'s + * @param authorizationRequestRepository the repository used for storing + * {@link OAuth2AuthorizationRequest}'s * @return the {@link AuthorizationCodeGrantConfigurer} for further configuration */ public AuthorizationCodeGrantConfigurer authorizationRequestRepository( @@ -187,9 +193,10 @@ public final class OAuth2ClientConfigurer> exte } /** - * Sets the client used for requesting the access token credential from the Token Endpoint. - * - * @param accessTokenResponseClient the client used for requesting the access token credential from the Token Endpoint + * Sets the client used for requesting the access token credential from the Token + * Endpoint. + * @param accessTokenResponseClient the client used for requesting the access + * token credential from the Token Endpoint * @return the {@link AuthorizationCodeGrantConfigurer} for further configuration */ public AuthorizationCodeGrantConfigurer accessTokenResponseClient( @@ -202,7 +209,6 @@ public final class OAuth2ClientConfigurer> exte /** * Returns the {@link OAuth2ClientConfigurer} for further configuration. - * * @return the {@link OAuth2ClientConfigurer} */ public OAuth2ClientConfigurer and() { @@ -210,25 +216,28 @@ public final class OAuth2ClientConfigurer> exte } private void init(B builder) { - OAuth2AuthorizationCodeAuthenticationProvider authorizationCodeAuthenticationProvider = - new OAuth2AuthorizationCodeAuthenticationProvider(getAccessTokenResponseClient()); + OAuth2AuthorizationCodeAuthenticationProvider authorizationCodeAuthenticationProvider = new OAuth2AuthorizationCodeAuthenticationProvider( + getAccessTokenResponseClient()); builder.authenticationProvider(postProcess(authorizationCodeAuthenticationProvider)); } private void configure(B builder) { - OAuth2AuthorizationRequestRedirectFilter authorizationRequestRedirectFilter = createAuthorizationRequestRedirectFilter(builder); + OAuth2AuthorizationRequestRedirectFilter authorizationRequestRedirectFilter = createAuthorizationRequestRedirectFilter( + builder); builder.addFilter(postProcess(authorizationRequestRedirectFilter)); - OAuth2AuthorizationCodeGrantFilter authorizationCodeGrantFilter = createAuthorizationCodeGrantFilter(builder); + OAuth2AuthorizationCodeGrantFilter authorizationCodeGrantFilter = createAuthorizationCodeGrantFilter( + builder); builder.addFilter(postProcess(authorizationCodeGrantFilter)); } private OAuth2AuthorizationRequestRedirectFilter createAuthorizationRequestRedirectFilter(B builder) { OAuth2AuthorizationRequestResolver resolver = getAuthorizationRequestResolver(); - OAuth2AuthorizationRequestRedirectFilter authorizationRequestRedirectFilter = - new OAuth2AuthorizationRequestRedirectFilter(resolver); + OAuth2AuthorizationRequestRedirectFilter authorizationRequestRedirectFilter = new OAuth2AuthorizationRequestRedirectFilter( + resolver); if (this.authorizationRequestRepository != null) { - authorizationRequestRedirectFilter.setAuthorizationRequestRepository(this.authorizationRequestRepository); + authorizationRequestRedirectFilter + .setAuthorizationRequestRepository(this.authorizationRequestRepository); } RequestCache requestCache = builder.getSharedObject(RequestCache.class); if (requestCache != null) { @@ -251,8 +260,7 @@ public final class OAuth2ClientConfigurer> exte AuthenticationManager authenticationManager = builder.getSharedObject(AuthenticationManager.class); OAuth2AuthorizationCodeGrantFilter authorizationCodeGrantFilter = new OAuth2AuthorizationCodeGrantFilter( OAuth2ClientConfigurerUtils.getClientRegistrationRepository(builder), - OAuth2ClientConfigurerUtils.getAuthorizedClientRepository(builder), - authenticationManager); + OAuth2ClientConfigurerUtils.getAuthorizedClientRepository(builder), authenticationManager); if (this.authorizationRequestRepository != null) { authorizationCodeGrantFilter.setAuthorizationRequestRepository(this.authorizationRequestRepository); @@ -270,6 +278,7 @@ public final class OAuth2ClientConfigurer> exte } return new DefaultAuthorizationCodeTokenResponseClient(); } + } @Override @@ -281,4 +290,5 @@ public final class OAuth2ClientConfigurer> exte public void configure(B builder) { this.authorizationCodeGrantConfigurer.configure(builder); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerUtils.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerUtils.java index 046c607739..2c34dca9bf 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerUtils.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerUtils.java @@ -41,7 +41,8 @@ final class OAuth2ClientConfigurerUtils { } static > ClientRegistrationRepository getClientRegistrationRepository(B builder) { - ClientRegistrationRepository clientRegistrationRepository = builder.getSharedObject(ClientRegistrationRepository.class); + ClientRegistrationRepository clientRegistrationRepository = builder + .getSharedObject(ClientRegistrationRepository.class); if (clientRegistrationRepository == null) { clientRegistrationRepository = getClientRegistrationRepositoryBean(builder); builder.setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository); @@ -49,12 +50,15 @@ final class OAuth2ClientConfigurerUtils { return clientRegistrationRepository; } - private static > ClientRegistrationRepository getClientRegistrationRepositoryBean(B builder) { + private static > ClientRegistrationRepository getClientRegistrationRepositoryBean( + B builder) { return builder.getSharedObject(ApplicationContext.class).getBean(ClientRegistrationRepository.class); } - static > OAuth2AuthorizedClientRepository getAuthorizedClientRepository(B builder) { - OAuth2AuthorizedClientRepository authorizedClientRepository = builder.getSharedObject(OAuth2AuthorizedClientRepository.class); + static > OAuth2AuthorizedClientRepository getAuthorizedClientRepository( + B builder) { + OAuth2AuthorizedClientRepository authorizedClientRepository = builder + .getSharedObject(OAuth2AuthorizedClientRepository.class); if (authorizedClientRepository == null) { authorizedClientRepository = getAuthorizedClientRepositoryBean(builder); if (authorizedClientRepository == null) { @@ -66,34 +70,45 @@ final class OAuth2ClientConfigurerUtils { return authorizedClientRepository; } - private static > OAuth2AuthorizedClientRepository getAuthorizedClientRepositoryBean(B builder) { - Map authorizedClientRepositoryMap = BeanFactoryUtils.beansOfTypeIncludingAncestors( - builder.getSharedObject(ApplicationContext.class), OAuth2AuthorizedClientRepository.class); + private static > OAuth2AuthorizedClientRepository getAuthorizedClientRepositoryBean( + B builder) { + Map authorizedClientRepositoryMap = BeanFactoryUtils + .beansOfTypeIncludingAncestors(builder.getSharedObject(ApplicationContext.class), + OAuth2AuthorizedClientRepository.class); if (authorizedClientRepositoryMap.size() > 1) { - throw new NoUniqueBeanDefinitionException(OAuth2AuthorizedClientRepository.class, authorizedClientRepositoryMap.size(), - "Expected single matching bean of type '" + OAuth2AuthorizedClientRepository.class.getName() + "' but found " + - authorizedClientRepositoryMap.size() + ": " + StringUtils.collectionToCommaDelimitedString(authorizedClientRepositoryMap.keySet())); + throw new NoUniqueBeanDefinitionException(OAuth2AuthorizedClientRepository.class, + authorizedClientRepositoryMap.size(), + "Expected single matching bean of type '" + OAuth2AuthorizedClientRepository.class.getName() + + "' but found " + authorizedClientRepositoryMap.size() + ": " + + StringUtils.collectionToCommaDelimitedString(authorizedClientRepositoryMap.keySet())); } - return (!authorizedClientRepositoryMap.isEmpty() ? authorizedClientRepositoryMap.values().iterator().next() : null); + return (!authorizedClientRepositoryMap.isEmpty() ? authorizedClientRepositoryMap.values().iterator().next() + : null); } - - private static > OAuth2AuthorizedClientService getAuthorizedClientService(B builder) { + private static > OAuth2AuthorizedClientService getAuthorizedClientService( + B builder) { OAuth2AuthorizedClientService authorizedClientService = getAuthorizedClientServiceBean(builder); if (authorizedClientService == null) { - authorizedClientService = new InMemoryOAuth2AuthorizedClientService(getClientRegistrationRepository(builder)); + authorizedClientService = new InMemoryOAuth2AuthorizedClientService( + getClientRegistrationRepository(builder)); } return authorizedClientService; } - private static > OAuth2AuthorizedClientService getAuthorizedClientServiceBean(B builder) { - Map authorizedClientServiceMap = BeanFactoryUtils.beansOfTypeIncludingAncestors( - builder.getSharedObject(ApplicationContext.class), OAuth2AuthorizedClientService.class); + private static > OAuth2AuthorizedClientService getAuthorizedClientServiceBean( + B builder) { + Map authorizedClientServiceMap = BeanFactoryUtils + .beansOfTypeIncludingAncestors(builder.getSharedObject(ApplicationContext.class), + OAuth2AuthorizedClientService.class); if (authorizedClientServiceMap.size() > 1) { - throw new NoUniqueBeanDefinitionException(OAuth2AuthorizedClientService.class, authorizedClientServiceMap.size(), - "Expected single matching bean of type '" + OAuth2AuthorizedClientService.class.getName() + "' but found " + - authorizedClientServiceMap.size() + ": " + StringUtils.collectionToCommaDelimitedString(authorizedClientServiceMap.keySet())); + throw new NoUniqueBeanDefinitionException(OAuth2AuthorizedClientService.class, + authorizedClientServiceMap.size(), + "Expected single matching bean of type '" + OAuth2AuthorizedClientService.class.getName() + + "' but found " + authorizedClientServiceMap.size() + ": " + + StringUtils.collectionToCommaDelimitedString(authorizedClientServiceMap.keySet())); } return (!authorizedClientServiceMap.isEmpty() ? authorizedClientServiceMap.values().iterator().next() : null); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java index 91c8f7f128..f30b3f0428 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java @@ -79,17 +79,18 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * An {@link AbstractHttpConfigurer} for OAuth 2.0 Login, - * which leverages the OAuth 2.0 Authorization Code Grant Flow. + * An {@link AbstractHttpConfigurer} for OAuth 2.0 Login, which leverages the OAuth 2.0 + * Authorization Code Grant Flow. * *

      - * OAuth 2.0 Login provides an application with the capability to have users log in - * by using their existing account at an OAuth 2.0 or OpenID Connect 1.0 Provider. + * OAuth 2.0 Login provides an application with the capability to have users log in by + * using their existing account at an OAuth 2.0 or OpenID Connect 1.0 Provider. * *

      - * Defaults are provided for all configuration options with the only required configuration - * being {@link #clientRegistrationRepository(ClientRegistrationRepository)}. - * Alternatively, a {@link ClientRegistrationRepository} {@code @Bean} may be registered instead. + * Defaults are provided for all configuration options with the only required + * configuration being + * {@link #clientRegistrationRepository(ClientRegistrationRepository)}. Alternatively, a + * {@link ClientRegistrationRepository} {@code @Bean} may be registered instead. * *

      Security Filters

      * @@ -118,8 +119,9 @@ import org.springframework.util.ClassUtils; *
    • {@link ClientRegistrationRepository}
    • *
    • {@link OAuth2AuthorizedClientRepository}
    • *
    • {@link GrantedAuthoritiesMapper}
    • - *
    • {@link DefaultLoginPageGeneratingFilter} - if {@link #loginPage(String)} is not configured - * and {@code DefaultLoginPageGeneratingFilter} is available, then a default login page will be made available
    • + *
    • {@link DefaultLoginPageGeneratingFilter} - if {@link #loginPage(String)} is not + * configured and {@code DefaultLoginPageGeneratingFilter} is available, then a default + * login page will be made available
    • *
    * * @author Joe Grandja @@ -132,23 +134,28 @@ import org.springframework.util.ClassUtils; * @see OAuth2AuthorizedClientRepository * @see AbstractAuthenticationFilterConfigurer */ -public final class OAuth2LoginConfigurer> extends - AbstractAuthenticationFilterConfigurer, OAuth2LoginAuthenticationFilter> { +public final class OAuth2LoginConfigurer> + extends AbstractAuthenticationFilterConfigurer, OAuth2LoginAuthenticationFilter> { private final AuthorizationEndpointConfig authorizationEndpointConfig = new AuthorizationEndpointConfig(); + private final TokenEndpointConfig tokenEndpointConfig = new TokenEndpointConfig(); + private final RedirectionEndpointConfig redirectionEndpointConfig = new RedirectionEndpointConfig(); + private final UserInfoEndpointConfig userInfoEndpointConfig = new UserInfoEndpointConfig(); + private String loginPage; + private String loginProcessingUrl = OAuth2LoginAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI; /** * Sets the repository of client registrations. - * * @param clientRegistrationRepository the repository of client registrations * @return the {@link OAuth2LoginConfigurer} for further configuration */ - public OAuth2LoginConfigurer clientRegistrationRepository(ClientRegistrationRepository clientRegistrationRepository) { + public OAuth2LoginConfigurer clientRegistrationRepository( + ClientRegistrationRepository clientRegistrationRepository) { Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null"); this.getBuilder().setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository); return this; @@ -161,7 +168,8 @@ public final class OAuth2LoginConfigurer> exten * @param authorizedClientRepository the authorized client repository * @return the {@link OAuth2LoginConfigurer} for further configuration */ - public OAuth2LoginConfigurer authorizedClientRepository(OAuth2AuthorizedClientRepository authorizedClientRepository) { + public OAuth2LoginConfigurer authorizedClientRepository( + OAuth2AuthorizedClientRepository authorizedClientRepository) { Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null"); this.getBuilder().setSharedObject(OAuth2AuthorizedClientRepository.class, authorizedClientRepository); return this; @@ -169,13 +177,13 @@ public final class OAuth2LoginConfigurer> exten /** * Sets the service for authorized client(s). - * * @param authorizedClientService the authorized client service * @return the {@link OAuth2LoginConfigurer} for further configuration */ public OAuth2LoginConfigurer authorizedClientService(OAuth2AuthorizedClientService authorizedClientService) { Assert.notNull(authorizedClientService, "authorizedClientService cannot be null"); - this.authorizedClientRepository(new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService)); + this.authorizedClientRepository( + new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService)); return this; } @@ -194,8 +202,8 @@ public final class OAuth2LoginConfigurer> exten } /** - * Returns the {@link AuthorizationEndpointConfig} for configuring the Authorization Server's Authorization Endpoint. - * + * Returns the {@link AuthorizationEndpointConfig} for configuring the Authorization + * Server's Authorization Endpoint. * @return the {@link AuthorizationEndpointConfig} */ public AuthorizationEndpointConfig authorizationEndpoint() { @@ -204,12 +212,12 @@ public final class OAuth2LoginConfigurer> exten /** * Configures the Authorization Server's Authorization Endpoint. - * - * @param authorizationEndpointCustomizer the {@link Customizer} to provide more options for - * the {@link AuthorizationEndpointConfig} + * @param authorizationEndpointCustomizer the {@link Customizer} to provide more + * options for the {@link AuthorizationEndpointConfig} * @return the {@link OAuth2LoginConfigurer} for further customizations */ - public OAuth2LoginConfigurer authorizationEndpoint(Customizer authorizationEndpointCustomizer) { + public OAuth2LoginConfigurer authorizationEndpoint( + Customizer authorizationEndpointCustomizer) { authorizationEndpointCustomizer.customize(this.authorizationEndpointConfig); return this; } @@ -218,8 +226,11 @@ public final class OAuth2LoginConfigurer> exten * Configuration options for the Authorization Server's Authorization Endpoint. */ public class AuthorizationEndpointConfig { + private String authorizationRequestBaseUri; + private OAuth2AuthorizationRequestResolver authorizationRequestResolver; + private AuthorizationRequestRepository authorizationRequestRepository; private AuthorizationEndpointConfig() { @@ -227,8 +238,8 @@ public final class OAuth2LoginConfigurer> exten /** * Sets the base {@code URI} used for authorization requests. - * - * @param authorizationRequestBaseUri the base {@code URI} used for authorization requests + * @param authorizationRequestBaseUri the base {@code URI} used for authorization + * requests * @return the {@link AuthorizationEndpointConfig} for further configuration */ public AuthorizationEndpointConfig baseUri(String authorizationRequestBaseUri) { @@ -241,10 +252,12 @@ public final class OAuth2LoginConfigurer> exten * Sets the resolver used for resolving {@link OAuth2AuthorizationRequest}'s. * * @since 5.1 - * @param authorizationRequestResolver the resolver used for resolving {@link OAuth2AuthorizationRequest}'s + * @param authorizationRequestResolver the resolver used for resolving + * {@link OAuth2AuthorizationRequest}'s * @return the {@link AuthorizationEndpointConfig} for further configuration */ - public AuthorizationEndpointConfig authorizationRequestResolver(OAuth2AuthorizationRequestResolver authorizationRequestResolver) { + public AuthorizationEndpointConfig authorizationRequestResolver( + OAuth2AuthorizationRequestResolver authorizationRequestResolver) { Assert.notNull(authorizationRequestResolver, "authorizationRequestResolver cannot be null"); this.authorizationRequestResolver = authorizationRequestResolver; return this; @@ -252,11 +265,12 @@ public final class OAuth2LoginConfigurer> exten /** * Sets the repository used for storing {@link OAuth2AuthorizationRequest}'s. - * - * @param authorizationRequestRepository the repository used for storing {@link OAuth2AuthorizationRequest}'s + * @param authorizationRequestRepository the repository used for storing + * {@link OAuth2AuthorizationRequest}'s * @return the {@link AuthorizationEndpointConfig} for further configuration */ - public AuthorizationEndpointConfig authorizationRequestRepository(AuthorizationRequestRepository authorizationRequestRepository) { + public AuthorizationEndpointConfig authorizationRequestRepository( + AuthorizationRequestRepository authorizationRequestRepository) { Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null"); this.authorizationRequestRepository = authorizationRequestRepository; return this; @@ -264,17 +278,17 @@ public final class OAuth2LoginConfigurer> exten /** * Returns the {@link OAuth2LoginConfigurer} for further configuration. - * * @return the {@link OAuth2LoginConfigurer} */ public OAuth2LoginConfigurer and() { return OAuth2LoginConfigurer.this; } + } /** - * Returns the {@link TokenEndpointConfig} for configuring the Authorization Server's Token Endpoint. - * + * Returns the {@link TokenEndpointConfig} for configuring the Authorization Server's + * Token Endpoint. * @return the {@link TokenEndpointConfig} */ public TokenEndpointConfig tokenEndpoint() { @@ -283,7 +297,6 @@ public final class OAuth2LoginConfigurer> exten /** * Configures the Authorization Server's Token Endpoint. - * * @param tokenEndpointCustomizer the {@link Customizer} to provide more options for * the {@link TokenEndpointConfig} * @return the {@link OAuth2LoginConfigurer} for further customizations @@ -298,19 +311,21 @@ public final class OAuth2LoginConfigurer> exten * Configuration options for the Authorization Server's Token Endpoint. */ public class TokenEndpointConfig { + private OAuth2AccessTokenResponseClient accessTokenResponseClient; private TokenEndpointConfig() { } /** - * Sets the client used for requesting the access token credential from the Token Endpoint. - * - * @param accessTokenResponseClient the client used for requesting the access token credential from the Token Endpoint + * Sets the client used for requesting the access token credential from the Token + * Endpoint. + * @param accessTokenResponseClient the client used for requesting the access + * token credential from the Token Endpoint * @return the {@link TokenEndpointConfig} for further configuration */ public TokenEndpointConfig accessTokenResponseClient( - OAuth2AccessTokenResponseClient accessTokenResponseClient) { + OAuth2AccessTokenResponseClient accessTokenResponseClient) { Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null"); this.accessTokenResponseClient = accessTokenResponseClient; @@ -319,17 +334,17 @@ public final class OAuth2LoginConfigurer> exten /** * Returns the {@link OAuth2LoginConfigurer} for further configuration. - * * @return the {@link OAuth2LoginConfigurer} */ public OAuth2LoginConfigurer and() { return OAuth2LoginConfigurer.this; } + } /** - * Returns the {@link RedirectionEndpointConfig} for configuring the Client's Redirection Endpoint. - * + * Returns the {@link RedirectionEndpointConfig} for configuring the Client's + * Redirection Endpoint. * @return the {@link RedirectionEndpointConfig} */ public RedirectionEndpointConfig redirectionEndpoint() { @@ -338,12 +353,12 @@ public final class OAuth2LoginConfigurer> exten /** * Configures the Client's Redirection Endpoint. - * - * @param redirectionEndpointCustomizer the {@link Customizer} to provide more options for - * the {@link RedirectionEndpointConfig} + * @param redirectionEndpointCustomizer the {@link Customizer} to provide more options + * for the {@link RedirectionEndpointConfig} * @return the {@link OAuth2LoginConfigurer} for further customizations */ - public OAuth2LoginConfigurer redirectionEndpoint(Customizer redirectionEndpointCustomizer) { + public OAuth2LoginConfigurer redirectionEndpoint( + Customizer redirectionEndpointCustomizer) { redirectionEndpointCustomizer.customize(this.redirectionEndpointConfig); return this; } @@ -352,6 +367,7 @@ public final class OAuth2LoginConfigurer> exten * Configuration options for the Client's Redirection Endpoint. */ public class RedirectionEndpointConfig { + private String authorizationResponseBaseUri; private RedirectionEndpointConfig() { @@ -359,8 +375,8 @@ public final class OAuth2LoginConfigurer> exten /** * Sets the {@code URI} where the authorization response will be processed. - * - * @param authorizationResponseBaseUri the {@code URI} where the authorization response will be processed + * @param authorizationResponseBaseUri the {@code URI} where the authorization + * response will be processed * @return the {@link RedirectionEndpointConfig} for further configuration */ public RedirectionEndpointConfig baseUri(String authorizationResponseBaseUri) { @@ -371,17 +387,17 @@ public final class OAuth2LoginConfigurer> exten /** * Returns the {@link OAuth2LoginConfigurer} for further configuration. - * * @return the {@link OAuth2LoginConfigurer} */ public OAuth2LoginConfigurer and() { return OAuth2LoginConfigurer.this; } + } /** - * Returns the {@link UserInfoEndpointConfig} for configuring the Authorization Server's UserInfo Endpoint. - * + * Returns the {@link UserInfoEndpointConfig} for configuring the Authorization + * Server's UserInfo Endpoint. * @return the {@link UserInfoEndpointConfig} */ public UserInfoEndpointConfig userInfoEndpoint() { @@ -390,9 +406,8 @@ public final class OAuth2LoginConfigurer> exten /** * Configures the Authorization Server's UserInfo Endpoint. - * - * @param userInfoEndpointCustomizer the {@link Customizer} to provide more options for - * the {@link UserInfoEndpointConfig} + * @param userInfoEndpointCustomizer the {@link Customizer} to provide more options + * for the {@link UserInfoEndpointConfig} * @return the {@link OAuth2LoginConfigurer} for further customizations */ public OAuth2LoginConfigurer userInfoEndpoint(Customizer userInfoEndpointCustomizer) { @@ -404,17 +419,21 @@ public final class OAuth2LoginConfigurer> exten * Configuration options for the Authorization Server's UserInfo Endpoint. */ public class UserInfoEndpointConfig { + private OAuth2UserService userService; + private OAuth2UserService oidcUserService; + private Map> customUserTypes = new HashMap<>(); private UserInfoEndpointConfig() { } /** - * Sets the OAuth 2.0 service used for obtaining the user attributes of the End-User from the UserInfo Endpoint. - * - * @param userService the OAuth 2.0 service used for obtaining the user attributes of the End-User from the UserInfo Endpoint + * Sets the OAuth 2.0 service used for obtaining the user attributes of the + * End-User from the UserInfo Endpoint. + * @param userService the OAuth 2.0 service used for obtaining the user attributes + * of the End-User from the UserInfo Endpoint * @return the {@link UserInfoEndpointConfig} for further configuration */ public UserInfoEndpointConfig userService(OAuth2UserService userService) { @@ -424,9 +443,10 @@ public final class OAuth2LoginConfigurer> exten } /** - * Sets the OpenID Connect 1.0 service used for obtaining the user attributes of the End-User from the UserInfo Endpoint. - * - * @param oidcUserService the OpenID Connect 1.0 service used for obtaining the user attributes of the End-User from the UserInfo Endpoint + * Sets the OpenID Connect 1.0 service used for obtaining the user attributes of + * the End-User from the UserInfo Endpoint. + * @param oidcUserService the OpenID Connect 1.0 service used for obtaining the + * user attributes of the End-User from the UserInfo Endpoint * @return the {@link UserInfoEndpointConfig} for further configuration */ public UserInfoEndpointConfig oidcUserService(OAuth2UserService oidcUserService) { @@ -436,17 +456,16 @@ public final class OAuth2LoginConfigurer> exten } /** - * Sets a custom {@link OAuth2User} type and associates it to the provided - * client {@link ClientRegistration#getRegistrationId() registration identifier}. - * + * Sets a custom {@link OAuth2User} type and associates it to the provided client + * {@link ClientRegistration#getRegistrationId() registration identifier}. * @deprecated See {@link CustomUserTypesOAuth2UserService} for alternative usage. - * * @param customUserType a custom {@link OAuth2User} type * @param clientRegistrationId the client registration identifier * @return the {@link UserInfoEndpointConfig} for further configuration */ @Deprecated - public UserInfoEndpointConfig customUserType(Class customUserType, String clientRegistrationId) { + public UserInfoEndpointConfig customUserType(Class customUserType, + String clientRegistrationId) { Assert.notNull(customUserType, "customUserType cannot be null"); Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty"); this.customUserTypes.put(clientRegistrationId, customUserType); @@ -454,34 +473,34 @@ public final class OAuth2LoginConfigurer> exten } /** - * Sets the {@link GrantedAuthoritiesMapper} used for mapping {@link OAuth2User#getAuthorities()}. - * - * @param userAuthoritiesMapper the {@link GrantedAuthoritiesMapper} used for mapping the user's authorities + * Sets the {@link GrantedAuthoritiesMapper} used for mapping + * {@link OAuth2User#getAuthorities()}. + * @param userAuthoritiesMapper the {@link GrantedAuthoritiesMapper} used for + * mapping the user's authorities * @return the {@link UserInfoEndpointConfig} for further configuration */ public UserInfoEndpointConfig userAuthoritiesMapper(GrantedAuthoritiesMapper userAuthoritiesMapper) { Assert.notNull(userAuthoritiesMapper, "userAuthoritiesMapper cannot be null"); - OAuth2LoginConfigurer.this.getBuilder().setSharedObject(GrantedAuthoritiesMapper.class, userAuthoritiesMapper); + OAuth2LoginConfigurer.this.getBuilder().setSharedObject(GrantedAuthoritiesMapper.class, + userAuthoritiesMapper); return this; } /** * Returns the {@link OAuth2LoginConfigurer} for further configuration. - * * @return the {@link OAuth2LoginConfigurer} */ public OAuth2LoginConfigurer and() { return OAuth2LoginConfigurer.this; } + } @Override public void init(B http) throws Exception { - OAuth2LoginAuthenticationFilter authenticationFilter = - new OAuth2LoginAuthenticationFilter( + OAuth2LoginAuthenticationFilter authenticationFilter = new OAuth2LoginAuthenticationFilter( OAuth2ClientConfigurerUtils.getClientRegistrationRepository(this.getBuilder()), - OAuth2ClientConfigurerUtils.getAuthorizedClientRepository(this.getBuilder()), - this.loginProcessingUrl); + OAuth2ClientConfigurerUtils.getAuthorizedClientRepository(this.getBuilder()), this.loginProcessingUrl); this.setAuthenticationFilter(authenticationFilter); super.loginProcessingUrl(this.loginProcessingUrl); @@ -489,7 +508,8 @@ public final class OAuth2LoginConfigurer> exten // Set custom login page super.loginPage(this.loginPage); super.init(http); - } else { + } + else { Map loginUrlToClientName = this.getLoginLinks(); if (loginUrlToClientName.size() == 1) { // Setup auto-redirect to provider login page @@ -498,33 +518,33 @@ public final class OAuth2LoginConfigurer> exten this.updateAccessDefaults(http); String providerLoginPage = loginUrlToClientName.keySet().iterator().next(); this.registerAuthenticationEntryPoint(http, this.getLoginEntryPoint(http, providerLoginPage)); - } else { + } + else { super.init(http); } } - OAuth2AccessTokenResponseClient accessTokenResponseClient = - this.tokenEndpointConfig.accessTokenResponseClient; + OAuth2AccessTokenResponseClient accessTokenResponseClient = this.tokenEndpointConfig.accessTokenResponseClient; if (accessTokenResponseClient == null) { accessTokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient(); } OAuth2UserService oauth2UserService = getOAuth2UserService(); - OAuth2LoginAuthenticationProvider oauth2LoginAuthenticationProvider = - new OAuth2LoginAuthenticationProvider(accessTokenResponseClient, oauth2UserService); + OAuth2LoginAuthenticationProvider oauth2LoginAuthenticationProvider = new OAuth2LoginAuthenticationProvider( + accessTokenResponseClient, oauth2UserService); GrantedAuthoritiesMapper userAuthoritiesMapper = this.getGrantedAuthoritiesMapper(); if (userAuthoritiesMapper != null) { oauth2LoginAuthenticationProvider.setAuthoritiesMapper(userAuthoritiesMapper); } http.authenticationProvider(this.postProcess(oauth2LoginAuthenticationProvider)); - boolean oidcAuthenticationProviderEnabled = ClassUtils.isPresent( - "org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader()); + boolean oidcAuthenticationProviderEnabled = ClassUtils + .isPresent("org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader()); if (oidcAuthenticationProviderEnabled) { OAuth2UserService oidcUserService = getOidcUserService(); - OidcAuthorizationCodeAuthenticationProvider oidcAuthorizationCodeAuthenticationProvider = - new OidcAuthorizationCodeAuthenticationProvider(accessTokenResponseClient, oidcUserService); + OidcAuthorizationCodeAuthenticationProvider oidcAuthorizationCodeAuthenticationProvider = new OidcAuthorizationCodeAuthenticationProvider( + accessTokenResponseClient, oidcUserService); JwtDecoderFactory jwtDecoderFactory = this.getJwtDecoderFactoryBean(); if (jwtDecoderFactory != null) { oidcAuthorizationCodeAuthenticationProvider.setJwtDecoderFactory(jwtDecoderFactory); @@ -533,7 +553,8 @@ public final class OAuth2LoginConfigurer> exten oidcAuthorizationCodeAuthenticationProvider.setAuthoritiesMapper(userAuthoritiesMapper); } http.authenticationProvider(this.postProcess(oidcAuthorizationCodeAuthenticationProvider)); - } else { + } + else { http.authenticationProvider(new OidcAuthenticationRequestChecker()); } @@ -547,18 +568,20 @@ public final class OAuth2LoginConfigurer> exten if (this.authorizationEndpointConfig.authorizationRequestResolver != null) { authorizationRequestFilter = new OAuth2AuthorizationRequestRedirectFilter( this.authorizationEndpointConfig.authorizationRequestResolver); - } else { + } + else { String authorizationRequestBaseUri = this.authorizationEndpointConfig.authorizationRequestBaseUri; if (authorizationRequestBaseUri == null) { authorizationRequestBaseUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI; } authorizationRequestFilter = new OAuth2AuthorizationRequestRedirectFilter( - OAuth2ClientConfigurerUtils.getClientRegistrationRepository(this.getBuilder()), authorizationRequestBaseUri); + OAuth2ClientConfigurerUtils.getClientRegistrationRepository(this.getBuilder()), + authorizationRequestBaseUri); } if (this.authorizationEndpointConfig.authorizationRequestRepository != null) { - authorizationRequestFilter.setAuthorizationRequestRepository( - this.authorizationEndpointConfig.authorizationRequestRepository); + authorizationRequestFilter + .setAuthorizationRequestRepository(this.authorizationEndpointConfig.authorizationRequestRepository); } RequestCache requestCache = http.getSharedObject(RequestCache.class); if (requestCache != null) { @@ -571,8 +594,8 @@ public final class OAuth2LoginConfigurer> exten authenticationFilter.setFilterProcessesUrl(this.redirectionEndpointConfig.authorizationResponseBaseUri); } if (this.authorizationEndpointConfig.authorizationRequestRepository != null) { - authenticationFilter.setAuthorizationRequestRepository( - this.authorizationEndpointConfig.authorizationRequestRepository); + authenticationFilter + .setAuthorizationRequestRepository(this.authorizationEndpointConfig.authorizationRequestRepository); } super.configure(http); } @@ -590,14 +613,15 @@ public final class OAuth2LoginConfigurer> exten throw new NoUniqueBeanDefinitionException(type, names); } if (names.length == 1) { - return (JwtDecoderFactory) this.getBuilder().getSharedObject(ApplicationContext.class).getBean(names[0]); + return (JwtDecoderFactory) this.getBuilder().getSharedObject(ApplicationContext.class) + .getBean(names[0]); } return null; } private GrantedAuthoritiesMapper getGrantedAuthoritiesMapper() { - GrantedAuthoritiesMapper grantedAuthoritiesMapper = - this.getBuilder().getSharedObject(GrantedAuthoritiesMapper.class); + GrantedAuthoritiesMapper grantedAuthoritiesMapper = this.getBuilder() + .getSharedObject(GrantedAuthoritiesMapper.class); if (grantedAuthoritiesMapper == null) { grantedAuthoritiesMapper = this.getGrantedAuthoritiesMapperBean(); if (grantedAuthoritiesMapper != null) { @@ -608,9 +632,8 @@ public final class OAuth2LoginConfigurer> exten } private GrantedAuthoritiesMapper getGrantedAuthoritiesMapperBean() { - Map grantedAuthoritiesMapperMap = - BeanFactoryUtils.beansOfTypeIncludingAncestors( - this.getBuilder().getSharedObject(ApplicationContext.class), + Map grantedAuthoritiesMapperMap = BeanFactoryUtils + .beansOfTypeIncludingAncestors(this.getBuilder().getSharedObject(ApplicationContext.class), GrantedAuthoritiesMapper.class); return (!grantedAuthoritiesMapperMap.isEmpty() ? grantedAuthoritiesMapperMap.values().iterator().next() : null); } @@ -619,7 +642,8 @@ public final class OAuth2LoginConfigurer> exten if (this.userInfoEndpointConfig.oidcUserService != null) { return this.userInfoEndpointConfig.oidcUserService; } - ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2UserService.class, OidcUserRequest.class, OidcUser.class); + ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2UserService.class, OidcUserRequest.class, + OidcUser.class); OAuth2UserService bean = getBeanOrNull(type); if (bean == null) { return new OidcUserService(); @@ -632,7 +656,8 @@ public final class OAuth2LoginConfigurer> exten if (this.userInfoEndpointConfig.userService != null) { return this.userInfoEndpointConfig.userService; } - ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2UserService.class, OAuth2UserRequest.class, OAuth2User.class); + ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2UserService.class, OAuth2UserRequest.class, + OAuth2User.class); OAuth2UserService bean = getBeanOrNull(type); if (bean == null) { if (!this.userInfoEndpointConfig.customUserTypes.isEmpty()) { @@ -640,7 +665,8 @@ public final class OAuth2LoginConfigurer> exten userServices.add(new CustomUserTypesOAuth2UserService(this.userInfoEndpointConfig.customUserTypes)); userServices.add(new DefaultOAuth2UserService()); return new DelegatingOAuth2UserService<>(userServices); - } else { + } + else { return new DefaultOAuth2UserService(); } } @@ -653,7 +679,7 @@ public final class OAuth2LoginConfigurer> exten if (context == null) { return null; } - String[] names = context.getBeanNamesForType(type); + String[] names = context.getBeanNamesForType(type); if (names.length == 1) { return (T) context.getBean(names[0]); } @@ -661,7 +687,8 @@ public final class OAuth2LoginConfigurer> exten } private void initDefaultLoginFilter(B http) { - DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class); + DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http + .getSharedObject(DefaultLoginPageGeneratingFilter.class); if (loginPageGeneratingFilter == null || this.isCustomLoginPage()) { return; } @@ -675,8 +702,8 @@ public final class OAuth2LoginConfigurer> exten @SuppressWarnings("unchecked") private Map getLoginLinks() { Iterable clientRegistrations = null; - ClientRegistrationRepository clientRegistrationRepository = - OAuth2ClientConfigurerUtils.getClientRegistrationRepository(this.getBuilder()); + ClientRegistrationRepository clientRegistrationRepository = OAuth2ClientConfigurerUtils + .getClientRegistrationRepository(this.getBuilder()); ResolvableType type = ResolvableType.forInstance(clientRegistrationRepository).as(Iterable.class); if (type != ResolvableType.NONE && ClientRegistration.class.isAssignableFrom(type.resolveGenerics()[0])) { clientRegistrations = (Iterable) clientRegistrationRepository; @@ -685,13 +712,12 @@ public final class OAuth2LoginConfigurer> exten return Collections.emptyMap(); } - String authorizationRequestBaseUri = this.authorizationEndpointConfig.authorizationRequestBaseUri != null ? - this.authorizationEndpointConfig.authorizationRequestBaseUri : - OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI; + String authorizationRequestBaseUri = this.authorizationEndpointConfig.authorizationRequestBaseUri != null + ? this.authorizationEndpointConfig.authorizationRequestBaseUri + : OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI; Map loginUrlToClientName = new HashMap<>(); clientRegistrations.forEach(registration -> loginUrlToClientName.put( - authorizationRequestBaseUri + "/" + registration.getRegistrationId(), - registration.getClientName())); + authorizationRequestBaseUri + "/" + registration.getRegistrationId(), registration.getClientName())); return loginUrlToClientName; } @@ -720,20 +746,19 @@ public final class OAuth2LoginConfigurer> exten @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { - OAuth2LoginAuthenticationToken authorizationCodeAuthentication = - (OAuth2LoginAuthenticationToken) authentication; + OAuth2LoginAuthenticationToken authorizationCodeAuthentication = (OAuth2LoginAuthenticationToken) authentication; - // Section 3.1.2.1 Authentication Request - https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest + // Section 3.1.2.1 Authentication Request - + // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest // scope - // REQUIRED. OpenID Connect requests MUST contain the "openid" scope value. - if (authorizationCodeAuthentication.getAuthorizationExchange() - .getAuthorizationRequest().getScopes().contains(OidcScopes.OPENID)) { + // REQUIRED. OpenID Connect requests MUST contain the "openid" scope value. + if (authorizationCodeAuthentication.getAuthorizationExchange().getAuthorizationRequest().getScopes() + .contains(OidcScopes.OPENID)) { - OAuth2Error oauth2Error = new OAuth2Error( - "oidc_provider_not_configured", - "An OpenID Connect Authentication Provider has not been configured. " + - "Check to ensure you include the dependency 'spring-security-oauth2-jose'.", - null); + OAuth2Error oauth2Error = new OAuth2Error("oidc_provider_not_configured", + "An OpenID Connect Authentication Provider has not been configured. " + + "Check to ensure you include the dependency 'spring-security-oauth2-jose'.", + null); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } @@ -744,5 +769,7 @@ public final class OAuth2LoginConfigurer> exten public boolean supports(Class authentication) { return OAuth2LoginAuthenticationToken.class.isAssignableFrom(authentication); } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java index e28f27e2f7..b37b21ee57 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java @@ -56,16 +56,19 @@ import static org.springframework.security.oauth2.jwt.NimbusJwtDecoder.withJwkSe * * An {@link AbstractHttpConfigurer} for OAuth 2.0 Resource Server Support. * - * By default, this wires a {@link BearerTokenAuthenticationFilter}, which can be used to parse the request - * for bearer tokens and make an authentication attempt. + * By default, this wires a {@link BearerTokenAuthenticationFilter}, which can be used to + * parse the request for bearer tokens and make an authentication attempt. * *

    * The following configuration options are available: * *

      - *
    • {@link #accessDeniedHandler(AccessDeniedHandler)}
    • - customizes how access denied errors are handled - *
    • {@link #authenticationEntryPoint(AuthenticationEntryPoint)}
    • - customizes how authentication failures are handled - *
    • {@link #bearerTokenResolver(BearerTokenResolver)} - customizes how to resolve a bearer token from the request
    • + *
    • {@link #accessDeniedHandler(AccessDeniedHandler)}
    • - customizes how access + * denied errors are handled + *
    • {@link #authenticationEntryPoint(AuthenticationEntryPoint)}
    • - customizes how + * authentication failures are handled + *
    • {@link #bearerTokenResolver(BearerTokenResolver)} - customizes how to resolve a + * bearer token from the request
    • *
    • {@link #jwt(Customizer)} - enables Jwt-encoded bearer token support
    • *
    • {@link #opaqueToken(Customizer)} - enables opaque bearer token support
    • *
    @@ -74,33 +77,28 @@ import static org.springframework.security.oauth2.jwt.NimbusJwtDecoder.withJwkSe * When using {@link #jwt(Customizer)}, either * *
      - *
    • - * supply a Jwk Set Uri via {@link JwtConfigurer#jwkSetUri}, or - *
    • - *
    • - * supply a {@link JwtDecoder} instance via {@link JwtConfigurer#decoder}, or - *
    • - *
    • - * expose a {@link JwtDecoder} bean - *
    • + *
    • supply a Jwk Set Uri via {@link JwtConfigurer#jwkSetUri}, or
    • + *
    • supply a {@link JwtDecoder} instance via {@link JwtConfigurer#decoder}, or
    • + *
    • expose a {@link JwtDecoder} bean
    • *
    * * Also with {@link #jwt(Customizer)} consider * *
      - *
    • - * customizing the conversion from a {@link Jwt} to an {@link org.springframework.security.core.Authentication} with - * {@link JwtConfigurer#jwtAuthenticationConverter(Converter)} - *
    • + *
    • customizing the conversion from a {@link Jwt} to an + * {@link org.springframework.security.core.Authentication} with + * {@link JwtConfigurer#jwtAuthenticationConverter(Converter)}
    • *
    * *

    - * When using {@link #opaqueToken(Customizer)}, supply an introspection endpoint and its authentication configuration + * When using {@link #opaqueToken(Customizer)}, supply an introspection endpoint and its + * authentication configuration *

    * *

    Security Filters

    * - * The following {@code Filter}s are populated when {@link #jwt(Customizer)} is configured: + * The following {@code Filter}s are populated when {@link #jwt(Customizer)} is + * configured: * *
      *
    • {@link BearerTokenAuthenticationFilter}
    • @@ -130,19 +128,23 @@ import static org.springframework.security.oauth2.jwt.NimbusJwtDecoder.withJwkSe * @see NimbusJwtDecoder * @see AbstractHttpConfigurer */ -public final class OAuth2ResourceServerConfigurer> extends - AbstractHttpConfigurer, H> { +public final class OAuth2ResourceServerConfigurer> + extends AbstractHttpConfigurer, H> { private final ApplicationContext context; private AuthenticationManagerResolver authenticationManagerResolver; + private BearerTokenResolver bearerTokenResolver; private JwtConfigurer jwtConfigurer; + private OpaqueTokenConfigurer opaqueTokenConfigurer; private AccessDeniedHandler accessDeniedHandler = new BearerTokenAccessDeniedHandler(); + private AuthenticationEntryPoint authenticationEntryPoint = new BearerTokenAuthenticationEntryPoint(); + private BearerTokenRequestMatcher requestMatcher = new BearerTokenRequestMatcher(); public OAuth2ResourceServerConfigurer(ApplicationContext context) { @@ -162,8 +164,8 @@ public final class OAuth2ResourceServerConfigurer authenticationManagerResolver - (AuthenticationManagerResolver authenticationManagerResolver) { + public OAuth2ResourceServerConfigurer authenticationManagerResolver( + AuthenticationManagerResolver authenticationManagerResolver) { Assert.notNull(authenticationManagerResolver, "authenticationManagerResolver cannot be null"); this.authenticationManagerResolver = authenticationManagerResolver; return this; @@ -176,7 +178,7 @@ public final class OAuth2ResourceServerConfigurer jwt(Customizer jwtCustomizer) { - if ( this.jwtConfigurer == null ) { + if (this.jwtConfigurer == null) { this.jwtConfigurer = new JwtConfigurer(this.context); } jwtCustomizer.customize(this.jwtConfigurer); @@ -208,9 +209,8 @@ public final class OAuth2ResourceServerConfigurer opaqueToken(Customizer opaqueTokenCustomizer) { @@ -257,28 +257,31 @@ public final class OAuth2ResourceServerConfigurer jwtAuthenticationConverter; @@ -303,8 +306,8 @@ public final class OAuth2ResourceServerConfigurer jwtAuthenticationConverter) { + public JwtConfigurer jwtAuthenticationConverter( + Converter jwtAuthenticationConverter) { this.jwtAuthenticationConverter = jwtAuthenticationConverter; return this; @@ -318,7 +321,8 @@ public final class OAuth2ResourceServerConfigurer 0) { this.jwtAuthenticationConverter = this.context.getBean(JwtAuthenticationConverter.class); - } else { + } + else { this.jwtAuthenticationConverter = new JwtAuthenticationConverter(); } } @@ -327,7 +331,7 @@ public final class OAuth2ResourceServerConfigurer jwtAuthenticationConverter = - getJwtAuthenticationConverter(); + Converter jwtAuthenticationConverter = getJwtAuthenticationConverter(); - JwtAuthenticationProvider provider = - new JwtAuthenticationProvider(decoder); + JwtAuthenticationProvider provider = new JwtAuthenticationProvider(decoder); provider.setJwtAuthenticationConverter(jwtAuthenticationConverter); return postProcess(provider); } @@ -356,15 +358,21 @@ public final class OAuth2ResourceServerConfigurer introspector; OpaqueTokenConfigurer(ApplicationContext context) { @@ -380,8 +388,8 @@ public final class OAuth2ResourceServerConfigurer - new NimbusOpaqueTokenIntrospector(this.introspectionUri, this.clientId, this.clientSecret); + this.introspector = () -> new NimbusOpaqueTokenIntrospector(this.introspectionUri, this.clientId, + this.clientSecret); return this; } @@ -390,8 +398,8 @@ public final class OAuth2ResourceServerConfigurer - new NimbusOpaqueTokenIntrospector(this.introspectionUri, this.clientId, this.clientSecret); + this.introspector = () -> new NimbusOpaqueTokenIntrospector(this.introspectionUri, this.clientId, + this.clientSecret); return this; } @@ -423,35 +431,29 @@ public final class OAuth2ResourceServerConfigurer exceptionHandling = http - .getConfigurer(ExceptionHandlingConfigurer.class); + ExceptionHandlingConfigurer exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class); if (exceptionHandling == null) { return; } - exceptionHandling.defaultAccessDeniedHandlerFor( - this.accessDeniedHandler, - this.requestMatcher); + exceptionHandling.defaultAccessDeniedHandlerFor(this.accessDeniedHandler, this.requestMatcher); } private void registerDefaultEntryPoint(H http) { - ExceptionHandlingConfigurer exceptionHandling = http - .getConfigurer(ExceptionHandlingConfigurer.class); + ExceptionHandlingConfigurer exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class); if (exceptionHandling == null) { return; } - exceptionHandling.defaultAuthenticationEntryPointFor( - this.authenticationEntryPoint, - this.requestMatcher); + exceptionHandling.defaultAuthenticationEntryPointFor(this.authenticationEntryPoint, this.requestMatcher); } private void registerDefaultCsrfOverride(H http) { - CsrfConfigurer csrf = http - .getConfigurer(CsrfConfigurer.class); + CsrfConfigurer csrf = http.getConfigurer(CsrfConfigurer.class); if (csrf == null) { return; } @@ -484,10 +486,11 @@ public final class OAuth2ResourceServerConfigurer 0 ) { + if (this.bearerTokenResolver == null) { + if (this.context.getBeanNamesForType(BearerTokenResolver.class).length > 0) { this.bearerTokenResolver = this.context.getBean(BearerTokenResolver.class); - } else { + } + else { this.bearerTokenResolver = new DefaultBearerTokenResolver(); } } @@ -496,13 +499,15 @@ public final class OAuth2ResourceServerConfigurerencouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @since 3.2 */ -public final class OpenIDLoginConfigurer> extends - AbstractAuthenticationFilterConfigurer, OpenIDAuthenticationFilter> { +public final class OpenIDLoginConfigurer> + extends AbstractAuthenticationFilterConfigurer, OpenIDAuthenticationFilter> { + private OpenIDConsumer openIDConsumer; + private ConsumerManager consumerManager; + private AuthenticationUserDetailsService authenticationUserDetailsService; + private List attributeExchangeConfigurers = new ArrayList<>(); /** @@ -139,29 +144,27 @@ public final class OpenIDLoginConfigurer> exten /** * Sets up OpenID attribute exchange for OpenID's matching the specified pattern. - * * @param identifierPattern the regular expression for matching on OpenID's (i.e. * "https://www.google.com/.*", ".*yahoo.com.*", etc) * @return a {@link AttributeExchangeConfigurer} for further customizations of the * attribute exchange */ public AttributeExchangeConfigurer attributeExchange(String identifierPattern) { - AttributeExchangeConfigurer attributeExchangeConfigurer = new AttributeExchangeConfigurer( - identifierPattern); + AttributeExchangeConfigurer attributeExchangeConfigurer = new AttributeExchangeConfigurer(identifierPattern); this.attributeExchangeConfigurers.add(attributeExchangeConfigurer); return attributeExchangeConfigurer; } /** - * Sets up OpenID attribute exchange for OpenIDs matching the specified pattern. - * The default pattern is ".*", it can be specified using + * Sets up OpenID attribute exchange for OpenIDs matching the specified pattern. The + * default pattern is ".*", it can be specified using * {@link AttributeExchangeConfigurer#identifierPattern(String)} - * - * @param attributeExchangeCustomizer the {@link Customizer} to provide more options for - * the {@link AttributeExchangeConfigurer} + * @param attributeExchangeCustomizer the {@link Customizer} to provide more options + * for the {@link AttributeExchangeConfigurer} * @return a {@link OpenIDLoginConfigurer} for further customizations */ - public OpenIDLoginConfigurer attributeExchange(Customizer attributeExchangeCustomizer) { + public OpenIDLoginConfigurer attributeExchange( + Customizer attributeExchangeCustomizer) { AttributeExchangeConfigurer attributeExchangeConfigurer = new AttributeExchangeConfigurer(".*"); attributeExchangeCustomizer.customize(attributeExchangeConfigurer); this.attributeExchangeConfigurers.add(attributeExchangeConfigurer); @@ -171,7 +174,6 @@ public final class OpenIDLoginConfigurer> exten /** * Allows specifying the {@link OpenIDConsumer} to be used. The default is using an * {@link OpenID4JavaConsumer}. - * * @param consumer the {@link OpenIDConsumer} to be used * @return the {@link OpenIDLoginConfigurer} for further customizations */ @@ -188,7 +190,6 @@ public final class OpenIDLoginConfigurer> exten * This is a shortcut for specifying the {@link OpenID4JavaConsumer} with a specific * {@link ConsumerManager} on {@link #consumer(OpenIDConsumer)}. *

      - * * @param consumerManager the {@link ConsumerManager} to use. Cannot be null. * @return the {@link OpenIDLoginConfigurer} for further customizations */ @@ -201,7 +202,6 @@ public final class OpenIDLoginConfigurer> exten * The {@link AuthenticationUserDetailsService} to use. By default a * {@link UserDetailsByNameServiceWrapper} is used with the {@link UserDetailsService} * shared object found with {@link HttpSecurity#getSharedObject(Class)}. - * * @param authenticationUserDetailsService the {@link AuthenticationDetailsSource} to * use * @return the {@link OpenIDLoginConfigurer} for further customizations @@ -216,7 +216,6 @@ public final class OpenIDLoginConfigurer> exten * Specifies the URL used to authenticate OpenID requests. If the * {@link HttpServletRequest} matches this URL the {@link OpenIDAuthenticationFilter} * will attempt to authenticate the request. The default is "/login/openid". - * * @param loginProcessingUrl the URL used to perform authentication * @return the {@link OpenIDLoginConfigurer} for additional customization */ @@ -267,7 +266,6 @@ public final class OpenIDLoginConfigurer> exten *
    • /authenticate?error GET - redirect here for failed authentication attempts
    • *
    • /authenticate?logout GET - redirect here after successfully logging out
    • *
    - * * @param loginPage the login page to redirect to if authentication is required (i.e. * "/login") * @return the {@link FormLoginConfigurer} for additional customization @@ -282,8 +280,7 @@ public final class OpenIDLoginConfigurer> exten super.init(http); OpenIDAuthenticationProvider authenticationProvider = new OpenIDAuthenticationProvider(); - authenticationProvider.setAuthenticationUserDetailsService( - getAuthenticationUserDetailsService(http)); + authenticationProvider.setAuthenticationUserDetailsService(getAuthenticationUserDetailsService(http)); authenticationProvider = postProcess(authenticationProvider); http.authenticationProvider(authenticationProvider); @@ -316,8 +313,7 @@ public final class OpenIDLoginConfigurer> exten */ private OpenIDConsumer getConsumer() throws ConsumerException { if (this.openIDConsumer == null) { - this.openIDConsumer = new OpenID4JavaConsumer(getConsumerManager(), - attributesToFetchFactory()); + this.openIDConsumer = new OpenID4JavaConsumer(getConsumerManager(), attributesToFetchFactory()); } return this.openIDConsumer; } @@ -337,7 +333,6 @@ public final class OpenIDLoginConfigurer> exten /** * Creates an {@link RegexBasedAxFetchListFactory} using the attributes populated by * {@link AttributeExchangeConfigurer} - * * @return the {@link AxFetchListFactory} to use */ private AxFetchListFactory attributesToFetchFactory() { @@ -352,23 +347,19 @@ public final class OpenIDLoginConfigurer> exten * Gets the {@link AuthenticationUserDetailsService} that was configured or defaults * to {@link UserDetailsByNameServiceWrapper} that uses a {@link UserDetailsService} * looked up using {@link HttpSecurity#getSharedObject(Class)} - * * @param http the current {@link HttpSecurity} * @return the {@link AuthenticationUserDetailsService}. */ - private AuthenticationUserDetailsService getAuthenticationUserDetailsService( - H http) { + private AuthenticationUserDetailsService getAuthenticationUserDetailsService(H http) { if (this.authenticationUserDetailsService != null) { return this.authenticationUserDetailsService; } - return new UserDetailsByNameServiceWrapper<>( - http.getSharedObject(UserDetailsService.class)); + return new UserDetailsByNameServiceWrapper<>(http.getSharedObject(UserDetailsService.class)); } /** * If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared * object. - * * @param http the {@link HttpSecurityBuilder} to use */ private void initDefaultLoginFilter(H http) { @@ -382,8 +373,8 @@ public final class OpenIDLoginConfigurer> exten loginPageGeneratingFilter.setLoginPageUrl(getLoginPage()); loginPageGeneratingFilter.setFailureUrl(getFailureUrl()); } - loginPageGeneratingFilter.setOpenIDusernameParameter( - OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD); + loginPageGeneratingFilter + .setOpenIDusernameParameter(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD); } } @@ -393,8 +384,11 @@ public final class OpenIDLoginConfigurer> exten * @author Rob Winch */ public final class AttributeExchangeConfigurer { + private String identifier; + private List attributes = new ArrayList<>(); + private List attributeConfigurers = new ArrayList<>(); /** @@ -418,7 +412,6 @@ public final class OpenIDLoginConfigurer> exten /** * Sets the regular expression for matching on OpenID's (i.e. * "https://www.google.com/.*", ".*yahoo.com.*", etc) - * * @param identifierPattern the regular expression for matching on OpenID's * @return the {@link AttributeExchangeConfigurer} for further customization of * attribute exchange @@ -453,9 +446,8 @@ public final class OpenIDLoginConfigurer> exten } /** - * Adds an {@link OpenIDAttribute} named "default-attribute". - * The name can by updated using {@link AttributeConfigurer#name(String)}. - * + * Adds an {@link OpenIDAttribute} named "default-attribute". The name + * can by updated using {@link AttributeConfigurer#name(String)}. * @param attributeCustomizer the {@link Customizer} to provide more options for * the {@link AttributeConfigurer} * @return a {@link AttributeExchangeConfigurer} for further customizations @@ -486,14 +478,18 @@ public final class OpenIDLoginConfigurer> exten * @since 3.2 */ public final class AttributeConfigurer { + private String name; + private int count = 1; + private boolean required = false; + private String type; /** - * Creates a new instance named "default-attribute". - * The name can by updated using {@link #name(String)}. + * Creates a new instance named "default-attribute". The name can by updated + * using {@link #name(String)}. * * @see AttributeExchangeConfigurer#attribute(String) */ @@ -525,7 +521,6 @@ public final class OpenIDLoginConfigurer> exten * false. Note that as outlined in the OpenID specification, * required attributes are not validated by the OpenID Provider. Developers * should perform any validation in custom code. - * * @param required specifies the attribute is required * @return the {@link AttributeConfigurer} for further customization */ @@ -557,7 +552,6 @@ public final class OpenIDLoginConfigurer> exten /** * Gets the {@link AttributeExchangeConfigurer} for further customization of * the attributes - * * @return the {@link AttributeConfigurer} */ public AttributeExchangeConfigurer and() { @@ -574,6 +568,9 @@ public final class OpenIDLoginConfigurer> exten attribute.setRequired(this.required); return attribute; } + } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java index ca7b6d2c08..acd115f157 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java @@ -50,17 +50,19 @@ import org.springframework.util.Assert; import static org.springframework.util.StringUtils.hasText; /** - * An {@link AbstractHttpConfigurer} for SAML 2.0 Login, - * which leverages the SAML 2.0 Web Browser Single Sign On (WebSSO) Flow. + * An {@link AbstractHttpConfigurer} for SAML 2.0 Login, which leverages the SAML 2.0 Web + * Browser Single Sign On (WebSSO) Flow. * *

    - * SAML 2.0 Login provides an application with the capability to have users log in - * by using their existing account at an SAML 2.0 Identity Provider. + * SAML 2.0 Login provides an application with the capability to have users log in by + * using their existing account at an SAML 2.0 Identity Provider. * *

    - * Defaults are provided for all configuration options with the only required configuration - * being {@link #relyingPartyRegistrationRepository(RelyingPartyRegistrationRepository)} . - * Alternatively, a {@link RelyingPartyRegistrationRepository} {@code @Bean} may be registered instead. + * Defaults are provided for all configuration options with the only required + * configuration being + * {@link #relyingPartyRegistrationRepository(RelyingPartyRegistrationRepository)} . + * Alternatively, a {@link RelyingPartyRegistrationRepository} {@code @Bean} may be + * registered instead. * *

    Security Filters

    * @@ -87,8 +89,9 @@ import static org.springframework.util.StringUtils.hasText; *
      *
    • {@link RelyingPartyRegistrationRepository} (required)
    • *
    • {@link Saml2AuthenticationRequestFactory} (optional)
    • - *
    • {@link DefaultLoginPageGeneratingFilter} - if {@link #loginPage(String)} is not configured - * and {@code DefaultLoginPageGeneratingFilter} is available, than a default login page will be made available
    • + *
    • {@link DefaultLoginPageGeneratingFilter} - if {@link #loginPage(String)} is not + * configured and {@code DefaultLoginPageGeneratingFilter} is available, than a default + * login page will be made available
    • *
    * * @since 5.2 @@ -98,8 +101,8 @@ import static org.springframework.util.StringUtils.hasText; * @see RelyingPartyRegistrationRepository * @see AbstractAuthenticationFilterConfigurer */ -public final class Saml2LoginConfigurer> extends - AbstractAuthenticationFilterConfigurer, Saml2WebSsoAuthenticationFilter> { +public final class Saml2LoginConfigurer> + extends AbstractAuthenticationFilterConfigurer, Saml2WebSsoAuthenticationFilter> { private String loginPage; @@ -110,14 +113,15 @@ public final class Saml2LoginConfigurer> extend private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository; private AuthenticationConverter authenticationConverter; + private AuthenticationManager authenticationManager; private Saml2WebSsoAuthenticationFilter saml2WebSsoAuthenticationFilter; /** - * Use this {@link AuthenticationConverter} when converting incoming requests to an {@link Authentication}. - * By default the {@link Saml2AuthenticationTokenConverter} is used. - * + * Use this {@link AuthenticationConverter} when converting incoming requests to an + * {@link Authentication}. By default the {@link Saml2AuthenticationTokenConverter} is + * used. * @param authenticationConverter the {@link AuthenticationConverter} to use * @return the {@link Saml2LoginConfigurer} for further configuration * @since 5.4 @@ -129,12 +133,13 @@ public final class Saml2LoginConfigurer> extend } /** - * Allows a configuration of a {@link AuthenticationManager} to be used during SAML 2 authentication. - * If none is specified, the system will create one inject it into the {@link Saml2WebSsoAuthenticationFilter} + * Allows a configuration of a {@link AuthenticationManager} to be used during SAML 2 + * authentication. If none is specified, the system will create one inject it into the + * {@link Saml2WebSsoAuthenticationFilter} * @param authenticationManager the authentication manager to be used * @return the {@link Saml2LoginConfigurer} for further configuration - * @throws IllegalArgumentException if authenticationManager is null - * configure the default manager + * @throws IllegalArgumentException if authenticationManager is null configure the + * default manager * @since 5.3 */ public Saml2LoginConfigurer authenticationManager(AuthenticationManager authenticationManager) { @@ -144,8 +149,9 @@ public final class Saml2LoginConfigurer> extend } /** - * Sets the {@code RelyingPartyRegistrationRepository} of relying parties, each party representing a - * service provider, SP and this host, and identity provider, IDP pair that communicate with each other. + * Sets the {@code RelyingPartyRegistrationRepository} of relying parties, each party + * representing a service provider, SP and this host, and identity provider, IDP pair + * that communicate with each other. * @param repo the repository of relying parties * @return the {@link Saml2LoginConfigurer} for further configuration */ @@ -186,15 +192,14 @@ public final class Saml2LoginConfigurer> extend /** * {@inheritDoc} * - * Initializes this filter chain for SAML 2 Login. - * The following actions are taken: + * Initializes this filter chain for SAML 2 Login. The following actions are taken: *
      - *
    • The WebSSO endpoint has CSRF disabled, typically {@code /login/saml2/sso}
    • - *
    • A {@link Saml2WebSsoAuthenticationFilter is configured}
    • - *
    • The {@code loginProcessingUrl} is set
    • - *
    • A custom login page is configured, or
    • - *
    • A default login page with all SAML 2.0 Identity Providers is configured
    • - *
    • An {@link OpenSamlAuthenticationProvider} is configured
    • + *
    • The WebSSO endpoint has CSRF disabled, typically {@code /login/saml2/sso}
    • + *
    • A {@link Saml2WebSsoAuthenticationFilter is configured}
    • + *
    • The {@code loginProcessingUrl} is set
    • + *
    • A custom login page is configured, or
    • + *
    • A default login page with all SAML 2.0 Identity Providers is configured
    • + *
    • An {@link OpenSamlAuthenticationProvider} is configured
    • *
    */ @Override @@ -204,10 +209,8 @@ public final class Saml2LoginConfigurer> extend this.relyingPartyRegistrationRepository = getSharedOrBean(http, RelyingPartyRegistrationRepository.class); } - saml2WebSsoAuthenticationFilter = new Saml2WebSsoAuthenticationFilter( - getAuthenticationConverter(http), - this.loginProcessingUrl - ); + saml2WebSsoAuthenticationFilter = new Saml2WebSsoAuthenticationFilter(getAuthenticationConverter(http), + this.loginProcessingUrl); setAuthenticationFilter(saml2WebSsoAuthenticationFilter); super.loginProcessingUrl(this.loginProcessingUrl); @@ -215,12 +218,10 @@ public final class Saml2LoginConfigurer> extend // Set custom login page super.loginPage(this.loginPage); super.init(http); - } else { - final Map providerUrlMap = - getIdentityProviderUrlMap( - this.authenticationRequestEndpoint.filterProcessingUrl, - this.relyingPartyRegistrationRepository - ); + } + else { + final Map providerUrlMap = getIdentityProviderUrlMap( + this.authenticationRequestEndpoint.filterProcessingUrl, this.relyingPartyRegistrationRepository); boolean singleProvider = providerUrlMap.size() == 1; if (singleProvider) { @@ -244,8 +245,9 @@ public final class Saml2LoginConfigurer> extend /** * {@inheritDoc} * - * During the {@code configure} phase, a {@link Saml2WebSsoAuthenticationRequestFilter} - * is added to handle SAML 2.0 AuthNRequest redirects + * During the {@code configure} phase, a + * {@link Saml2WebSsoAuthenticationRequestFilter} is added to handle SAML 2.0 + * AuthNRequest redirects */ @Override public void configure(B http) throws Exception { @@ -278,43 +280,31 @@ public final class Saml2LoginConfigurer> extend return; } - csrf.ignoringRequestMatchers( - new AntPathRequestMatcher(loginProcessingUrl) - ); + csrf.ignoringRequestMatchers(new AntPathRequestMatcher(loginProcessingUrl)); } private void initDefaultLoginFilter(B http) { - DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class); + DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http + .getSharedObject(DefaultLoginPageGeneratingFilter.class); if (loginPageGeneratingFilter == null || this.isCustomLoginPage()) { return; } loginPageGeneratingFilter.setSaml2LoginEnabled(true); - loginPageGeneratingFilter.setSaml2AuthenticationUrlToProviderName( - this.getIdentityProviderUrlMap( - this.authenticationRequestEndpoint.filterProcessingUrl, - this.relyingPartyRegistrationRepository - ) - ); + loginPageGeneratingFilter.setSaml2AuthenticationUrlToProviderName(this.getIdentityProviderUrlMap( + this.authenticationRequestEndpoint.filterProcessingUrl, this.relyingPartyRegistrationRepository)); loginPageGeneratingFilter.setLoginPageUrl(this.getLoginPage()); loginPageGeneratingFilter.setFailureUrl(this.getFailureUrl()); } @SuppressWarnings("unchecked") - private Map getIdentityProviderUrlMap( - String authRequestPrefixUrl, - RelyingPartyRegistrationRepository idpRepo - ) { + private Map getIdentityProviderUrlMap(String authRequestPrefixUrl, + RelyingPartyRegistrationRepository idpRepo) { Map idps = new LinkedHashMap<>(); if (idpRepo instanceof Iterable) { Iterable repo = (Iterable) idpRepo; - repo.forEach( - p -> - idps.put( - authRequestPrefixUrl.replace("{registrationId}", p.getRegistrationId()), - p.getRegistrationId() - ) - ); + repo.forEach(p -> idps.put(authRequestPrefixUrl.replace("{registrationId}", p.getRegistrationId()), + p.getRegistrationId())); } return idps; } @@ -334,7 +324,9 @@ public final class Saml2LoginConfigurer> extend } try { return context.getBean(clazz); - } catch (NoSuchBeanDefinitionException e) {} + } + catch (NoSuchBeanDefinitionException e) { + } return null; } @@ -345,6 +337,7 @@ public final class Saml2LoginConfigurer> extend } private final class AuthenticationRequestEndpointConfig { + private String filterProcessingUrl = "/saml2/authenticate/{registrationId}"; private AuthenticationRequestEndpointConfig() { @@ -354,27 +347,28 @@ public final class Saml2LoginConfigurer> extend Saml2AuthenticationRequestFactory authenticationRequestResolver = getResolver(http); Saml2AuthenticationRequestContextResolver contextResolver = getContextResolver(http); - return postProcess(new Saml2WebSsoAuthenticationRequestFilter( - contextResolver, authenticationRequestResolver)); + return postProcess( + new Saml2WebSsoAuthenticationRequestFilter(contextResolver, authenticationRequestResolver)); } private Saml2AuthenticationRequestFactory getResolver(B http) { Saml2AuthenticationRequestFactory resolver = getSharedOrBean(http, Saml2AuthenticationRequestFactory.class); - if (resolver == null ) { + if (resolver == null) { resolver = new OpenSamlAuthenticationRequestFactory(); } return resolver; } private Saml2AuthenticationRequestContextResolver getContextResolver(B http) { - Saml2AuthenticationRequestContextResolver resolver = getBeanOrNull(http, Saml2AuthenticationRequestContextResolver.class); + Saml2AuthenticationRequestContextResolver resolver = getBeanOrNull(http, + Saml2AuthenticationRequestContextResolver.class); if (resolver == null) { - return new DefaultSaml2AuthenticationRequestContextResolver( - new DefaultRelyingPartyRegistrationResolver( - Saml2LoginConfigurer.this.relyingPartyRegistrationRepository)); + return new DefaultSaml2AuthenticationRequestContextResolver(new DefaultRelyingPartyRegistrationResolver( + Saml2LoginConfigurer.this.relyingPartyRegistrationRepository)); } return resolver; } + } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistry.java b/config/src/main/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistry.java index 79a476ede0..404bc89236 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistry.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistry.java @@ -44,11 +44,17 @@ import org.springframework.util.StringUtils; * @author Rob Winch */ public class MessageSecurityMetadataSourceRegistry { + private static final String permitAll = "permitAll"; + private static final String denyAll = "denyAll"; + private static final String anonymous = "anonymous"; + private static final String authenticated = "authenticated"; + private static final String fullyAuthenticated = "fullyAuthenticated"; + private static final String rememberMe = "rememberMe"; private SecurityExpressionHandler> expressionHandler = new DefaultMessageSecurityExpressionHandler<>(); @@ -61,7 +67,6 @@ public class MessageSecurityMetadataSourceRegistry { /** * Maps any {@link Message} to a security expression. - * * @return the Expression to associate */ public Constraint anyMessage() { @@ -72,7 +77,6 @@ public class MessageSecurityMetadataSourceRegistry { * Maps any {@link Message} that has a null SimpMessageHeaderAccessor destination * header (i.e. CONNECT, CONNECT_ACK, HEARTBEAT, UNSUBSCRIBE, DISCONNECT, * DISCONNECT_ACK, OTHER) - * * @return the Expression to associate */ public Constraint nullDestMatcher() { @@ -81,7 +85,6 @@ public class MessageSecurityMetadataSourceRegistry { /** * Maps a {@link List} of {@link SimpDestinationMessageMatcher} instances. - * * @param typesToMatch the {@link SimpMessageType} instance to match on * @return the {@link Constraint} associated to the matchers. */ @@ -98,12 +101,10 @@ public class MessageSecurityMetadataSourceRegistry { * Maps a {@link List} of {@link SimpDestinationMessageMatcher} instances without * regard to the {@link SimpMessageType}. If no destination is found on the Message, * then the Matcher returns false. - * * @param patterns the patterns to create * {@link org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher} * from. Uses * {@link MessageSecurityMetadataSourceRegistry#simpDestPathMatcher(PathMatcher)} . - * * @return the {@link Constraint} that is associated to the {@link MessageMatcher} * @see MessageSecurityMetadataSourceRegistry#simpDestPathMatcher(PathMatcher) */ @@ -115,12 +116,10 @@ public class MessageSecurityMetadataSourceRegistry { * Maps a {@link List} of {@link SimpDestinationMessageMatcher} instances that match * on {@code SimpMessageType.MESSAGE}. If no destination is found on the Message, then * the Matcher returns false. - * * @param patterns the patterns to create * {@link org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher} * from. Uses * {@link MessageSecurityMetadataSourceRegistry#simpDestPathMatcher(PathMatcher)}. - * * @return the {@link Constraint} that is associated to the {@link MessageMatcher} * @see MessageSecurityMetadataSourceRegistry#simpDestPathMatcher(PathMatcher) */ @@ -132,12 +131,10 @@ public class MessageSecurityMetadataSourceRegistry { * Maps a {@link List} of {@link SimpDestinationMessageMatcher} instances that match * on {@code SimpMessageType.SUBSCRIBE}. If no destination is found on the Message, * then the Matcher returns false. - * * @param patterns the patterns to create * {@link org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher} * from. Uses * {@link MessageSecurityMetadataSourceRegistry#simpDestPathMatcher(PathMatcher)}. - * * @return the {@link Constraint} that is associated to the {@link MessageMatcher} * @see MessageSecurityMetadataSourceRegistry#simpDestPathMatcher(PathMatcher) */ @@ -148,14 +145,12 @@ public class MessageSecurityMetadataSourceRegistry { /** * Maps a {@link List} of {@link SimpDestinationMessageMatcher} instances. If no * destination is found on the Message, then the Matcher returns false. - * * @param type the {@link SimpMessageType} to match on. If null, the * {@link SimpMessageType} is not considered for matching. * @param patterns the patterns to create * {@link org.springframework.security.messaging.util.matcher.SimpDestinationMessageMatcher} * from. Uses * {@link MessageSecurityMetadataSourceRegistry#simpDestPathMatcher(PathMatcher)}. - * * @return the {@link Constraint} that is associated to the {@link MessageMatcher} * @see {@link MessageSecurityMetadataSourceRegistry#simpDestPathMatcher(PathMatcher)} */ @@ -171,13 +166,11 @@ public class MessageSecurityMetadataSourceRegistry { * The {@link PathMatcher} to be used with the * {@link MessageSecurityMetadataSourceRegistry#simpDestMatchers(String...)}. The * default is to use the default constructor of {@link AntPathMatcher}. - * * @param pathMatcher the {@link PathMatcher} to use. Cannot be null. * @return the {@link MessageSecurityMetadataSourceRegistry} for further * customization. */ - public MessageSecurityMetadataSourceRegistry simpDestPathMatcher( - PathMatcher pathMatcher) { + public MessageSecurityMetadataSourceRegistry simpDestPathMatcher(PathMatcher pathMatcher) { Assert.notNull(pathMatcher, "pathMatcher cannot be null"); this.pathMatcher.setPathMatcher(pathMatcher); this.defaultPathMatcher = false; @@ -185,9 +178,10 @@ public class MessageSecurityMetadataSourceRegistry { } /** - * Determines if the {@link #simpDestPathMatcher(PathMatcher)} has been explicitly set. - * - * @return true if {@link #simpDestPathMatcher(PathMatcher)} has been explicitly set, else false. + * Determines if the {@link #simpDestPathMatcher(PathMatcher)} has been explicitly + * set. + * @return true if {@link #simpDestPathMatcher(PathMatcher)} has been explicitly set, + * else false. */ protected boolean isSimpDestPathMatcherConfigured() { return !this.defaultPathMatcher; @@ -195,7 +189,6 @@ public class MessageSecurityMetadataSourceRegistry { /** * Maps a {@link List} of {@link MessageMatcher} instances to a security expression. - * * @param matchers the {@link MessageMatcher} instances to map. * @return The {@link Constraint} that is associated to the {@link MessageMatcher} * instances @@ -209,14 +202,15 @@ public class MessageSecurityMetadataSourceRegistry { } /** - * The {@link SecurityExpressionHandler} to be used. The - * default is to use {@link DefaultMessageSecurityExpressionHandler}. - * - * @param expressionHandler the {@link SecurityExpressionHandler} to use. Cannot be null. + * The {@link SecurityExpressionHandler} to be used. The default is to use + * {@link DefaultMessageSecurityExpressionHandler}. + * @param expressionHandler the {@link SecurityExpressionHandler} to use. Cannot be + * null. * @return the {@link MessageSecurityMetadataSourceRegistry} for further * customization. */ - public MessageSecurityMetadataSourceRegistry expressionHandler(SecurityExpressionHandler> expressionHandler) { + public MessageSecurityMetadataSourceRegistry expressionHandler( + SecurityExpressionHandler> expressionHandler) { Assert.notNull(expressionHandler, "expressionHandler cannot be null"); this.expressionHandler = expressionHandler; return this; @@ -229,13 +223,11 @@ public class MessageSecurityMetadataSourceRegistry { * This is not exposed so as not to confuse users of the API, which should never * invoke this method. *

    - * * @return the {@link MessageSecurityMetadataSource} to use */ protected MessageSecurityMetadataSource createMetadataSource() { LinkedHashMap, String> matcherToExpression = new LinkedHashMap<>(); - for (Map.Entry entry : this.matcherToExpression - .entrySet()) { + for (Map.Entry entry : this.matcherToExpression.entrySet()) { matcherToExpression.put(entry.getKey().build(), entry.getValue()); } return ExpressionBasedMessageSecurityMetadataSourceFactory @@ -249,7 +241,6 @@ public class MessageSecurityMetadataSourceRegistry { * This is not exposed so as not to confuse users of the API, which should never need * to invoke this method. *

    - * * @return true if a mapping was added, else false */ protected boolean containsMapping() { @@ -261,11 +252,11 @@ public class MessageSecurityMetadataSourceRegistry { * instances. */ public class Constraint { + private final List messageMatchers; /** * Creates a new instance - * * @param messageMatchers the {@link MessageMatcher} instances to map to this * constraint */ @@ -278,7 +269,6 @@ public class MessageSecurityMetadataSourceRegistry { * Shortcut for specifying {@link Message} instances require a particular role. If * you do not want to have "ROLE_" automatically inserted see * {@link #hasAuthority(String)}. - * * @param role the role to require (i.e. USER, ADMIN, etc). Note, it should not * start with "ROLE_" as this is automatically inserted. * @return the {@link MessageSecurityMetadataSourceRegistry} for further @@ -292,7 +282,6 @@ public class MessageSecurityMetadataSourceRegistry { * Shortcut for specifying {@link Message} instances require any of a number of * roles. If you do not want to have "ROLE_" automatically inserted see * {@link #hasAnyAuthority(String...)} - * * @param roles the roles to require (i.e. USER, ADMIN, etc). Note, it should not * start with "ROLE_" as this is automatically inserted. * @return the {@link MessageSecurityMetadataSourceRegistry} for further @@ -304,7 +293,6 @@ public class MessageSecurityMetadataSourceRegistry { /** * Specify that {@link Message} instances require a particular authority. - * * @param authority the authority to require (i.e. ROLE_USER, ROLE_ADMIN, etc). * @return the {@link MessageSecurityMetadataSourceRegistry} for further * customization @@ -315,22 +303,18 @@ public class MessageSecurityMetadataSourceRegistry { /** * Specify that {@link Message} instances requires any of a number authorities. - * * @param authorities the requests require at least one of the authorities (i.e. * "ROLE_USER","ROLE_ADMIN" would mean either "ROLE_USER" or "ROLE_ADMIN" is * required). * @return the {@link MessageSecurityMetadataSourceRegistry} for further * customization */ - public MessageSecurityMetadataSourceRegistry hasAnyAuthority( - String... authorities) { - return access(MessageSecurityMetadataSourceRegistry - .hasAnyAuthority(authorities)); + public MessageSecurityMetadataSourceRegistry hasAnyAuthority(String... authorities) { + return access(MessageSecurityMetadataSourceRegistry.hasAnyAuthority(authorities)); } /** * Specify that Messages are allowed by anyone. - * * @return the {@link MessageSecurityMetadataSourceRegistry} for further * customization */ @@ -340,7 +324,6 @@ public class MessageSecurityMetadataSourceRegistry { /** * Specify that Messages are allowed by anonymous users. - * * @return the {@link MessageSecurityMetadataSourceRegistry} for further * customization */ @@ -350,7 +333,6 @@ public class MessageSecurityMetadataSourceRegistry { /** * Specify that Messages are allowed by users that have been remembered. - * * @return the {@link MessageSecurityMetadataSourceRegistry} for further * customization * @see RememberMeConfigurer @@ -361,7 +343,6 @@ public class MessageSecurityMetadataSourceRegistry { /** * Specify that Messages are not allowed by anyone. - * * @return the {@link MessageSecurityMetadataSourceRegistry} for further * customization */ @@ -371,7 +352,6 @@ public class MessageSecurityMetadataSourceRegistry { /** * Specify that Messages are allowed by any authenticated user. - * * @return the {@link MessageSecurityMetadataSourceRegistry} for further * customization */ @@ -382,7 +362,6 @@ public class MessageSecurityMetadataSourceRegistry { /** * Specify that Messages are allowed by users who have authenticated and were not * "remembered". - * * @return the {@link MessageSecurityMetadataSourceRegistry} for further * customization * @see RememberMeConfigurer @@ -393,9 +372,8 @@ public class MessageSecurityMetadataSourceRegistry { /** * Allows specifying that Messages are secured by an arbitrary expression - * - * @param attribute the expression to secure the URLs (i.e. - * "hasRole('ROLE_USER') and hasRole('ROLE_SUPER')") + * @param attribute the expression to secure the URLs (i.e. "hasRole('ROLE_USER') + * and hasRole('ROLE_SUPER')") * @return the {@link MessageSecurityMetadataSourceRegistry} for further * customization */ @@ -405,11 +383,11 @@ public class MessageSecurityMetadataSourceRegistry { } return MessageSecurityMetadataSourceRegistry.this; } + } private static String hasAnyRole(String... authorities) { - String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, - "','ROLE_"); + String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, "','ROLE_"); return "hasAnyRole('ROLE_" + anyAuthorities + "')"; } @@ -417,8 +395,7 @@ public class MessageSecurityMetadataSourceRegistry { Assert.notNull(role, "role cannot be null"); if (role.startsWith("ROLE_")) { throw new IllegalArgumentException( - "role should not start with 'ROLE_' since it is automatically inserted. Got '" - + role + "'"); + "role should not start with 'ROLE_' since it is automatically inserted. Got '" + role + "'"); } return "hasRole('ROLE_" + role + "')"; } @@ -433,6 +410,7 @@ public class MessageSecurityMetadataSourceRegistry { } private static class PreBuiltMatcherBuilder implements MatcherBuilder { + private MessageMatcher matcher; private PreBuiltMatcherBuilder(MessageMatcher matcher) { @@ -442,10 +420,13 @@ public class MessageSecurityMetadataSourceRegistry { public MessageMatcher build() { return matcher; } + } private class PathMatcherMessageMatcherBuilder implements MatcherBuilder { + private final String pattern; + private final SimpMessageType type; private PathMatcherMessageMatcherBuilder(String pattern, SimpMessageType type) { @@ -458,22 +439,21 @@ public class MessageSecurityMetadataSourceRegistry { return new SimpDestinationMessageMatcher(pattern, pathMatcher); } else if (SimpMessageType.MESSAGE == type) { - return SimpDestinationMessageMatcher.createMessageMatcher(pattern, - pathMatcher); + return SimpDestinationMessageMatcher.createMessageMatcher(pattern, pathMatcher); } else if (SimpMessageType.SUBSCRIBE == type) { - return SimpDestinationMessageMatcher.createSubscribeMatcher(pattern, - pathMatcher); + return SimpDestinationMessageMatcher.createSubscribeMatcher(pattern, pathMatcher); } - throw new IllegalStateException(type - + " is not supported since it does not have a destination"); + throw new IllegalStateException(type + " is not supported since it does not have a destination"); } + } private interface MatcherBuilder { - MessageMatcher build(); - } + MessageMatcher build(); + + } static class DelegatingPathMatcher implements PathMatcher { @@ -510,5 +490,7 @@ public class MessageSecurityMetadataSourceRegistry { void setPathMatcher(PathMatcher pathMatcher) { this.delegate = pathMatcher; } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurity.java index e3d812db50..c0f7ec0c9b 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurity.java @@ -86,8 +86,9 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented -@Import({ServerHttpSecurityConfiguration.class, WebFluxSecurityConfiguration.class, - ReactiveOAuth2ClientImportSelector.class}) +@Import({ ServerHttpSecurityConfiguration.class, WebFluxSecurityConfiguration.class, + ReactiveOAuth2ClientImportSelector.class }) @Configuration public @interface EnableWebFluxSecurity { + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java index 4cf69de47c..af77f92b0f 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java @@ -48,15 +48,17 @@ final class ReactiveOAuth2ClientImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { boolean oauth2ClientPresent = ClassUtils.isPresent( - "org.springframework.security.oauth2.client.registration.ClientRegistration", getClass().getClassLoader()); + "org.springframework.security.oauth2.client.registration.ClientRegistration", + getClass().getClassLoader()); - return oauth2ClientPresent ? - new String[] { "org.springframework.security.config.annotation.web.reactive.ReactiveOAuth2ClientImportSelector$OAuth2ClientWebFluxSecurityConfiguration" } : - new String[] {}; + return oauth2ClientPresent ? new String[] { + "org.springframework.security.config.annotation.web.reactive.ReactiveOAuth2ClientImportSelector$OAuth2ClientWebFluxSecurityConfiguration" } + : new String[] {}; } @Configuration(proxyBeanMethods = false) static class OAuth2ClientWebFluxSecurityConfiguration implements WebFluxConfigurer { + private ReactiveClientRegistrationRepository clientRegistrationRepository; private ServerOAuth2AuthorizedClientRepository authorizedClientRepository; @@ -66,13 +68,8 @@ final class ReactiveOAuth2ClientImportSelector implements ImportSelector { @Override public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) { if (this.authorizedClientRepository != null && this.clientRegistrationRepository != null) { - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = - ReactiveOAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .refreshToken() - .clientCredentials() - .password() - .build(); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder + .builder().authorizationCode().refreshToken().clientCredentials().password().build(); DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager( this.clientRegistrationRepository, getAuthorizedClientRepository()); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); @@ -81,8 +78,7 @@ final class ReactiveOAuth2ClientImportSelector implements ImportSelector { } @Autowired(required = false) - public void setClientRegistrationRepository( - ReactiveClientRegistrationRepository clientRegistrationRepository) { + public void setClientRegistrationRepository(ReactiveClientRegistrationRepository clientRegistrationRepository) { this.clientRegistrationRepository = clientRegistrationRepository; } @@ -107,5 +103,7 @@ final class ReactiveOAuth2ClientImportSelector implements ImportSelector { } return null; } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java index b7d4b3e3c7..bfef35ed7a 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java @@ -45,7 +45,9 @@ import org.springframework.web.reactive.result.method.annotation.ArgumentResolve */ @Configuration(proxyBeanMethods = false) class ServerHttpSecurityConfiguration { + private static final String BEAN_NAME_PREFIX = "org.springframework.security.config.annotation.web.reactive.HttpSecurityConfiguration."; + private static final String HTTPSECURITY_BEAN_NAME = BEAN_NAME_PREFIX + "httpSecurity"; private ReactiveAdapterRegistry adapterRegistry = new ReactiveAdapterRegistry(); @@ -100,7 +102,7 @@ class ServerHttpSecurityConfiguration { @Bean public AuthenticationPrincipalArgumentResolver authenticationPrincipalArgumentResolver() { AuthenticationPrincipalArgumentResolver resolver = new AuthenticationPrincipalArgumentResolver( - this.adapterRegistry); + this.adapterRegistry); if (this.beanFactory != null) { resolver.setBeanResolver(new BeanFactoryResolver(this.beanFactory)); } @@ -121,10 +123,7 @@ class ServerHttpSecurityConfiguration { @Scope("prototype") public ServerHttpSecurity httpSecurity() { ContextAwareServerHttpSecurity http = new ContextAwareServerHttpSecurity(); - return http - .authenticationManager(authenticationManager()) - .headers().and() - .logout().and(); + return http.authenticationManager(authenticationManager()).headers().and().logout().and(); } private ReactiveAuthenticationManager authenticationManager() { @@ -132,8 +131,8 @@ class ServerHttpSecurityConfiguration { return this.authenticationManager; } if (this.reactiveUserDetailsService != null) { - UserDetailsRepositoryReactiveAuthenticationManager manager = - new UserDetailsRepositoryReactiveAuthenticationManager(this.reactiveUserDetailsService); + UserDetailsRepositoryReactiveAuthenticationManager manager = new UserDetailsRepositoryReactiveAuthenticationManager( + this.reactiveUserDetailsService); if (this.passwordEncoder != null) { manager.setPasswordEncoder(this.passwordEncoder); } @@ -143,12 +142,13 @@ class ServerHttpSecurityConfiguration { return null; } - private static class ContextAwareServerHttpSecurity extends ServerHttpSecurity implements - ApplicationContextAware { + private static class ContextAwareServerHttpSecurity extends ServerHttpSecurity implements ApplicationContextAware { + @Override - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { super.setApplicationContext(applicationContext); } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java index 368d99c015..559c38d578 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java @@ -40,11 +40,13 @@ import org.springframework.web.reactive.result.view.AbstractView; */ @Configuration(proxyBeanMethods = false) class WebFluxSecurityConfiguration { + public static final int WEB_FILTER_CHAIN_FILTER_ORDER = 0 - 100; private static final String BEAN_NAME_PREFIX = "org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration."; - private static final String SPRING_SECURITY_WEBFILTERCHAINFILTER_BEAN_NAME = BEAN_NAME_PREFIX + "WebFilterChainFilter"; + private static final String SPRING_SECURITY_WEBFILTERCHAINFILTER_BEAN_NAME = BEAN_NAME_PREFIX + + "WebFilterChainFilter"; public static final String REACTIVE_CLIENT_REGISTRATION_REPOSITORY_CLASSNAME = "org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository"; @@ -104,7 +106,8 @@ class WebFluxSecurityConfiguration { if (isOAuth2Present && OAuth2ClasspathGuard.shouldConfigure(this.context)) { OAuth2ClasspathGuard.configure(this.context, http); - } else { + } + else { // @formatter:off http .httpBasic().and() @@ -117,6 +120,7 @@ class WebFluxSecurityConfiguration { } private static class OAuth2ClasspathGuard { + static void configure(ApplicationContext context, ServerHttpSecurity http) { // @formatter:off http @@ -127,8 +131,11 @@ class WebFluxSecurityConfiguration { static boolean shouldConfigure(ApplicationContext context) { ClassLoader loader = context.getClassLoader(); - Class reactiveClientRegistrationRepositoryClass = ClassUtils.resolveClassName(REACTIVE_CLIENT_REGISTRATION_REPOSITORY_CLASSNAME, loader); + Class reactiveClientRegistrationRepositoryClass = ClassUtils + .resolveClassName(REACTIVE_CLIENT_REGISTRATION_REPOSITORY_CLASSNAME, loader); return context.getBeanNamesForType(reactiveClientRegistrationRepositoryClass).length == 1; } + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/servlet/configuration/EnableWebMvcSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/servlet/configuration/EnableWebMvcSecurity.java index 1afc2c710b..3c0d11f58c 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/servlet/configuration/EnableWebMvcSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/servlet/configuration/EnableWebMvcSecurity.java @@ -26,7 +26,6 @@ import org.springframework.security.config.annotation.authentication.configurati /** * Add this annotation to an {@code @Configuration} class to have the Spring Security * configuration integrate with Spring MVC. - * * @deprecated Use EnableWebSecurity instead which will automatically add the Spring MVC * related Security items. * @author Rob Winch @@ -40,4 +39,5 @@ import org.springframework.security.config.annotation.authentication.configurati @Configuration @Deprecated public @interface EnableWebMvcSecurity { + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/servlet/configuration/WebMvcSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/servlet/configuration/WebMvcSecurityConfiguration.java index ba1d7204fb..f8bd8f0d65 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/servlet/configuration/WebMvcSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/servlet/configuration/WebMvcSecurityConfiguration.java @@ -30,8 +30,10 @@ import org.springframework.web.servlet.support.RequestDataValueProcessor; /** * Used to add a {@link RequestDataValueProcessor} for Spring MVC and Spring Security CSRF * integration. This configuration is added whenever {@link EnableWebMvc} is added by - * SpringWebMvcImportSelector and the DispatcherServlet is present on the - * classpath. It also adds the {@link AuthenticationPrincipalArgumentResolver} as a + * SpringWebMvcImportSelector + * and the DispatcherServlet is present on the classpath. It also adds the + * {@link AuthenticationPrincipalArgumentResolver} as a * {@link HandlerMethodArgumentResolver}. * * @deprecated This is applied internally using SpringWebMvcImportSelector @@ -54,4 +56,5 @@ public class WebMvcSecurityConfiguration implements WebMvcConfigurer { public RequestDataValueProcessor requestDataValueProcessor() { return new CsrfRequestDataValueProcessor(); } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java index 0bb45a614f..b048d19913 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java @@ -77,14 +77,14 @@ import org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsSe * } *
    * - * * @since 4.0 * @author Rob Winch */ @Order(Ordered.HIGHEST_PRECEDENCE + 100) @Import(ObjectPostProcessorConfiguration.class) -public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends - AbstractWebSocketMessageBrokerConfigurer implements SmartInitializingSingleton { +public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends AbstractWebSocketMessageBrokerConfigurer + implements SmartInitializingSingleton { + private final WebSocketMessageSecurityMetadataSourceRegistry inboundRegistry = new WebSocketMessageSecurityMetadataSourceRegistry(); private SecurityExpressionHandler> defaultExpressionHandler = new DefaultMessageSecurityExpressionHandler<>(); @@ -117,7 +117,8 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends private PathMatcher getDefaultPathMatcher() { try { return context.getBean(SimpAnnotationMethodMessageHandler.class).getPathMatcher(); - } catch(NoSuchBeanDefinitionException e) { + } + catch (NoSuchBeanDefinitionException e) { return new AntPathMatcher(); } } @@ -131,7 +132,6 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends *

    * Subclasses can override this method to disable CSRF protection *

    - * * @return false if a CSRF token is required for connecting, else true */ protected boolean sameOriginDisabled() { @@ -141,7 +141,6 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends /** * Allows subclasses to customize the configuration of the {@link ChannelRegistration} * . - * * @param registration the {@link ChannelRegistration} to customize */ protected void customizeClientInboundChannel(ChannelRegistration registration) { @@ -153,7 +152,8 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends } @Bean - public ChannelSecurityInterceptor inboundChannelSecurity(MessageSecurityMetadataSource messageSecurityMetadataSource) { + public ChannelSecurityInterceptor inboundChannelSecurity( + MessageSecurityMetadataSource messageSecurityMetadataSource) { ChannelSecurityInterceptor channelSecurityInterceptor = new ChannelSecurityInterceptor( messageSecurityMetadataSource); MessageExpressionVoter voter = new MessageExpressionVoter<>(); @@ -180,14 +180,13 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends } /** - * * @param messages */ protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) { } - private static class WebSocketMessageSecurityMetadataSourceRegistry extends - MessageSecurityMetadataSourceRegistry { + private static class WebSocketMessageSecurityMetadataSourceRegistry extends MessageSecurityMetadataSourceRegistry { + @Override public MessageSecurityMetadataSource createMetadataSource() { return super.createMetadataSource(); @@ -202,6 +201,7 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends protected boolean isSimpDestPathMatcherConfigured() { return super.isSimpDestPathMatcherConfigured(); } + } @Autowired @@ -226,7 +226,7 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends defaultExpressionHandler = objectPostProcessor.postProcess(defaultExpressionHandler); } - private SecurityExpressionHandler> getMessageExpressionHandler() { + private SecurityExpressionHandler> getMessageExpressionHandler() { if (expressionHandler == null) { return defaultExpressionHandler; } @@ -239,8 +239,7 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends } String beanName = "stompWebSocketHandlerMapping"; - SimpleUrlHandlerMapping mapping = context.getBean(beanName, - SimpleUrlHandlerMapping.class); + SimpleUrlHandlerMapping mapping = context.getBean(beanName, SimpleUrlHandlerMapping.class); Map mappings = mapping.getHandlerMap(); for (Object object : mappings.values()) { if (object instanceof SockJsHttpRequestHandler) { @@ -248,38 +247,31 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends SockJsService sockJsService = sockjsHandler.getSockJsService(); if (!(sockJsService instanceof TransportHandlingSockJsService)) { throw new IllegalStateException( - "sockJsService must be instance of TransportHandlingSockJsService got " - + sockJsService); + "sockJsService must be instance of TransportHandlingSockJsService got " + sockJsService); } TransportHandlingSockJsService transportHandlingSockJsService = (TransportHandlingSockJsService) sockJsService; List handshakeInterceptors = transportHandlingSockJsService .getHandshakeInterceptors(); - List interceptorsToSet = new ArrayList<>( - handshakeInterceptors.size() + 1); + List interceptorsToSet = new ArrayList<>(handshakeInterceptors.size() + 1); interceptorsToSet.add(new CsrfTokenHandshakeInterceptor()); interceptorsToSet.addAll(handshakeInterceptors); - transportHandlingSockJsService - .setHandshakeInterceptors(interceptorsToSet); + transportHandlingSockJsService.setHandshakeInterceptors(interceptorsToSet); } else if (object instanceof WebSocketHttpRequestHandler) { WebSocketHttpRequestHandler handler = (WebSocketHttpRequestHandler) object; - List handshakeInterceptors = handler - .getHandshakeInterceptors(); - List interceptorsToSet = new ArrayList<>( - handshakeInterceptors.size() + 1); + List handshakeInterceptors = handler.getHandshakeInterceptors(); + List interceptorsToSet = new ArrayList<>(handshakeInterceptors.size() + 1); interceptorsToSet.add(new CsrfTokenHandshakeInterceptor()); interceptorsToSet.addAll(handshakeInterceptors); handler.setHandshakeInterceptors(interceptorsToSet); } else { - throw new IllegalStateException( - "Bean " - + beanName - + " is expected to contain mappings to either a SockJsHttpRequestHandler or a WebSocketHttpRequestHandler but got " - + object); + throw new IllegalStateException("Bean " + beanName + + " is expected to contain mappings to either a SockJsHttpRequestHandler or a WebSocketHttpRequestHandler but got " + + object); } } @@ -288,4 +280,5 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends inboundRegistry.simpDestPathMatcher(pathMatcher); } } + } diff --git a/config/src/main/java/org/springframework/security/config/authentication/AbstractUserDetailsServiceBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/authentication/AbstractUserDetailsServiceBeanDefinitionParser.java index ae1a6e9d21..915c41c698 100644 --- a/config/src/main/java/org/springframework/security/config/authentication/AbstractUserDetailsServiceBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/authentication/AbstractUserDetailsServiceBeanDefinitionParser.java @@ -32,27 +32,25 @@ import org.w3c.dom.Element; /** * @author Luke Taylor */ -public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements - BeanDefinitionParser { +public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements BeanDefinitionParser { + static final String CACHE_REF = "cache-ref"; + public static final String CACHING_SUFFIX = ".caching"; protected abstract String getBeanClassName(Element element); - protected abstract void doParse(Element element, ParserContext parserContext, - BeanDefinitionBuilder builder); + protected abstract void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder); public BeanDefinition parse(Element element, ParserContext parserContext) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .rootBeanDefinition(getBeanClassName(element)); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(getBeanClassName(element)); doParse(element, parserContext, builder); RootBeanDefinition userService = (RootBeanDefinition) builder.getBeanDefinition(); final String beanId = resolveId(element, userService, parserContext); - parserContext.registerBeanComponent(new BeanComponentDefinition(userService, - beanId)); + parserContext.registerBeanComponent(new BeanComponentDefinition(userService, beanId)); String cacheRef = element.getAttribute(CACHE_REF); @@ -62,18 +60,17 @@ public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements .rootBeanDefinition(CachingUserDetailsService.class); cachingUSBuilder.addConstructorArgReference(beanId); - cachingUSBuilder.addPropertyValue("userCache", new RuntimeBeanReference( - cacheRef)); + cachingUSBuilder.addPropertyValue("userCache", new RuntimeBeanReference(cacheRef)); BeanDefinition cachingUserService = cachingUSBuilder.getBeanDefinition(); - parserContext.registerBeanComponent(new BeanComponentDefinition( - cachingUserService, beanId + CACHING_SUFFIX)); + parserContext + .registerBeanComponent(new BeanComponentDefinition(cachingUserService, beanId + CACHING_SUFFIX)); } return null; } - private String resolveId(Element element, AbstractBeanDefinition definition, - ParserContext pc) throws BeanDefinitionStoreException { + private String resolveId(Element element, AbstractBeanDefinition definition, ParserContext pc) + throws BeanDefinitionStoreException { String id = element.getAttribute("id"); @@ -83,8 +80,7 @@ public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements id = pc.getReaderContext().generateBeanName(definition); } BeanDefinition container = pc.getContainingBeanDefinition(); - container.getPropertyValues().add("userDetailsService", - new RuntimeBeanReference(id)); + container.getPropertyValues().add("userDetailsService", new RuntimeBeanReference(id)); } if (StringUtils.hasText(id)) { @@ -93,10 +89,11 @@ public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements // If top level, use the default name or throw an exception if already used if (pc.getRegistry().containsBeanDefinition(BeanIds.USER_DETAILS_SERVICE)) { - throw new BeanDefinitionStoreException("No id supplied and another " - + "bean is already registered as " + BeanIds.USER_DETAILS_SERVICE); + throw new BeanDefinitionStoreException( + "No id supplied and another " + "bean is already registered as " + BeanIds.USER_DETAILS_SERVICE); } return BeanIds.USER_DETAILS_SERVICE; } + } diff --git a/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java index 57342c9c81..94a57b106f 100644 --- a/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParser.java @@ -48,8 +48,11 @@ import org.w3c.dom.NodeList; * @author Luke Taylor */ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinitionParser { + private static final String ATT_ALIAS = "alias"; + private static final String ATT_REF = "ref"; + private static final String ATT_ERASE_CREDENTIALS = "erase-credentials"; public BeanDefinition parse(Element element, ParserContext pc) { @@ -57,23 +60,19 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition if (!StringUtils.hasText(id)) { if (pc.getRegistry().containsBeanDefinition(BeanIds.AUTHENTICATION_MANAGER)) { - pc.getReaderContext().warning( - "Overriding globally registered AuthenticationManager", + pc.getReaderContext().warning("Overriding globally registered AuthenticationManager", pc.extractSource(element)); } id = BeanIds.AUTHENTICATION_MANAGER; } - pc.pushContainingComponent(new CompositeComponentDefinition(element.getTagName(), - pc.extractSource(element))); + pc.pushContainingComponent(new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element))); - BeanDefinitionBuilder providerManagerBldr = BeanDefinitionBuilder - .rootBeanDefinition(ProviderManager.class); + BeanDefinitionBuilder providerManagerBldr = BeanDefinitionBuilder.rootBeanDefinition(ProviderManager.class); String alias = element.getAttribute(ATT_ALIAS); List providers = new ManagedList<>(); - NamespaceHandlerResolver resolver = pc.getReaderContext() - .getNamespaceHandlerResolver(); + NamespaceHandlerResolver resolver = pc.getReaderContext().getNamespaceHandlerResolver(); NodeList children = element.getChildNodes(); @@ -83,31 +82,26 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition Element providerElt = (Element) node; if (StringUtils.hasText(providerElt.getAttribute(ATT_REF))) { if (providerElt.getAttributes().getLength() > 1) { - pc.getReaderContext().error( - "authentication-provider element cannot be used with other attributes " - + "when using 'ref' attribute", - pc.extractSource(element)); + pc.getReaderContext() + .error("authentication-provider element cannot be used with other attributes " + + "when using 'ref' attribute", pc.extractSource(element)); } NodeList providerChildren = providerElt.getChildNodes(); for (int j = 0; j < providerChildren.getLength(); j++) { if (providerChildren.item(j) instanceof Element) { - pc.getReaderContext().error( - "authentication-provider element cannot have child elements when used " - + "with 'ref' attribute", - pc.extractSource(element)); + pc.getReaderContext() + .error("authentication-provider element cannot have child elements when used " + + "with 'ref' attribute", pc.extractSource(element)); } } - providers.add(new RuntimeBeanReference(providerElt - .getAttribute(ATT_REF))); + providers.add(new RuntimeBeanReference(providerElt.getAttribute(ATT_REF))); } else { - BeanDefinition provider = resolver.resolve( - providerElt.getNamespaceURI()).parse(providerElt, pc); - Assert.notNull(provider, () -> "Parser for " + providerElt.getNodeName() - + " returned a null bean definition"); + BeanDefinition provider = resolver.resolve(providerElt.getNamespaceURI()).parse(providerElt, pc); + Assert.notNull(provider, + () -> "Parser for " + providerElt.getNodeName() + " returned a null bean definition"); String providerId = pc.getReaderContext().generateBeanName(provider); - pc.registerBeanComponent(new BeanComponentDefinition(provider, - providerId)); + pc.registerBeanComponent(new BeanComponentDefinition(provider, providerId)); providers.add(new RuntimeBeanReference(providerId)); } } @@ -120,29 +114,24 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition providerManagerBldr.addConstructorArgValue(providers); if ("false".equals(element.getAttribute(ATT_ERASE_CREDENTIALS))) { - providerManagerBldr.addPropertyValue("eraseCredentialsAfterAuthentication", - false); + providerManagerBldr.addPropertyValue("eraseCredentialsAfterAuthentication", false); } // Add the default event publisher - BeanDefinition publisher = new RootBeanDefinition( - DefaultAuthenticationEventPublisher.class); + BeanDefinition publisher = new RootBeanDefinition(DefaultAuthenticationEventPublisher.class); String pubId = pc.getReaderContext().generateBeanName(publisher); pc.registerBeanComponent(new BeanComponentDefinition(publisher, pubId)); providerManagerBldr.addPropertyReference("authenticationEventPublisher", pubId); - pc.registerBeanComponent(new BeanComponentDefinition(providerManagerBldr - .getBeanDefinition(), id)); + pc.registerBeanComponent(new BeanComponentDefinition(providerManagerBldr.getBeanDefinition(), id)); if (StringUtils.hasText(alias)) { pc.getRegistry().registerAlias(id, alias); - pc.getReaderContext().fireAliasRegistered(id, alias, - pc.extractSource(element)); + pc.getReaderContext().fireAliasRegistered(id, alias, pc.extractSource(element)); } if (!BeanIds.AUTHENTICATION_MANAGER.equals(id)) { pc.getRegistry().registerAlias(id, BeanIds.AUTHENTICATION_MANAGER); - pc.getReaderContext().fireAliasRegistered(id, BeanIds.AUTHENTICATION_MANAGER, - pc.extractSource(element)); + pc.getReaderContext().fireAliasRegistered(id, BeanIds.AUTHENTICATION_MANAGER, pc.extractSource(element)); } pc.popAndRegisterContainingComponent(); @@ -156,15 +145,16 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition * from the <http> namespace, such as OpenID, is expected to handle the * request). */ - public static final class NullAuthenticationProvider implements - AuthenticationProvider { - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public static final class NullAuthenticationProvider implements AuthenticationProvider { + + public Authentication authenticate(Authentication authentication) throws AuthenticationException { return null; } public boolean supports(Class authentication) { return false; } + } + } diff --git a/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java b/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java index 2340bd4fc9..cb92f78bd6 100644 --- a/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java @@ -38,9 +38,10 @@ import java.util.Arrays; * @author Luke Taylor * @since 3.0 */ -public class AuthenticationManagerFactoryBean implements - FactoryBean, BeanFactoryAware { +public class AuthenticationManagerFactoryBean implements FactoryBean, BeanFactoryAware { + private BeanFactory bf; + public static final String MISSING_BEAN_ERROR_MESSAGE = "Did you forget to add a global element " + "to your configuration (with child elements)? Alternatively you can use the " + "authentication-manager-ref attribute on your and elements."; @@ -56,8 +57,7 @@ public class AuthenticationManagerFactoryBean implements UserDetailsService uds = getBeanOrNull(UserDetailsService.class); if (uds == null) { - throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER, - MISSING_BEAN_ERROR_MESSAGE); + throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER, MISSING_BEAN_ERROR_MESSAGE); } DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); @@ -67,7 +67,7 @@ public class AuthenticationManagerFactoryBean implements provider.setPasswordEncoder(passwordEncoder); } provider.afterPropertiesSet(); - return new ProviderManager(Arrays. asList(provider)); + return new ProviderManager(Arrays.asList(provider)); } } @@ -86,8 +86,10 @@ public class AuthenticationManagerFactoryBean implements private T getBeanOrNull(Class type) { try { return this.bf.getBean(type); - } catch (NoSuchBeanDefinitionException noUds) { + } + catch (NoSuchBeanDefinitionException noUds) { return null; } } + } diff --git a/config/src/main/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParser.java index 6b56bff9e5..7792499a3c 100644 --- a/config/src/main/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParser.java @@ -34,6 +34,7 @@ import org.w3c.dom.Element; * @author Luke Taylor */ public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitionParser { + private static final String ATT_USER_DETAILS_REF = "user-service-ref"; public BeanDefinition parse(Element element, ParserContext pc) { @@ -45,35 +46,28 @@ public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitio PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElt, pc); BeanMetadataElement passwordEncoder = pep.getPasswordEncoder(); if (passwordEncoder != null) { - authProvider.getPropertyValues() - .addPropertyValue("passwordEncoder", passwordEncoder); + authProvider.getPropertyValues().addPropertyValue("passwordEncoder", passwordEncoder); } - Element userServiceElt = DomUtils.getChildElementByTagName(element, - Elements.USER_SERVICE); + Element userServiceElt = DomUtils.getChildElementByTagName(element, Elements.USER_SERVICE); if (userServiceElt == null) { - userServiceElt = DomUtils.getChildElementByTagName(element, - Elements.JDBC_USER_SERVICE); + userServiceElt = DomUtils.getChildElementByTagName(element, Elements.JDBC_USER_SERVICE); } if (userServiceElt == null) { - userServiceElt = DomUtils.getChildElementByTagName(element, - Elements.LDAP_USER_SERVICE); + userServiceElt = DomUtils.getChildElementByTagName(element, Elements.LDAP_USER_SERVICE); } String ref = element.getAttribute(ATT_USER_DETAILS_REF); if (StringUtils.hasText(ref)) { if (userServiceElt != null) { - pc.getReaderContext().error( - "The " + ATT_USER_DETAILS_REF - + " attribute cannot be used in combination with child" - + "elements '" + Elements.USER_SERVICE + "', '" - + Elements.JDBC_USER_SERVICE + "' or '" + pc.getReaderContext() + .error("The " + ATT_USER_DETAILS_REF + " attribute cannot be used in combination with child" + + "elements '" + Elements.USER_SERVICE + "', '" + Elements.JDBC_USER_SERVICE + "' or '" + Elements.LDAP_USER_SERVICE + "'", element); } - authProvider.getPropertyValues().add("userDetailsService", - new RuntimeBeanReference(ref)); + authProvider.getPropertyValues().add("userDetailsService", new RuntimeBeanReference(ref)); } else { // Use the child elements to create the UserDetailsService @@ -85,15 +79,14 @@ public class AuthenticationProviderBeanDefinitionParser implements BeanDefinitio } // Pinch the cache-ref from the UserDetailService element, if set. - String cacheRef = userServiceElt - .getAttribute(AbstractUserDetailsServiceBeanDefinitionParser.CACHE_REF); + String cacheRef = userServiceElt.getAttribute(AbstractUserDetailsServiceBeanDefinitionParser.CACHE_REF); if (StringUtils.hasText(cacheRef)) { - authProvider.getPropertyValues().addPropertyValue("userCache", - new RuntimeBeanReference(cacheRef)); + authProvider.getPropertyValues().addPropertyValue("userCache", new RuntimeBeanReference(cacheRef)); } } return authProvider; } + } diff --git a/config/src/main/java/org/springframework/security/config/authentication/JdbcUserServiceBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/authentication/JdbcUserServiceBeanDefinitionParser.java index 18e35d3286..6387304a21 100644 --- a/config/src/main/java/org/springframework/security/config/authentication/JdbcUserServiceBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/authentication/JdbcUserServiceBeanDefinitionParser.java @@ -25,8 +25,8 @@ import org.w3c.dom.Element; /** * @author Luke Taylor */ -public class JdbcUserServiceBeanDefinitionParser extends - AbstractUserDetailsServiceBeanDefinitionParser { +public class JdbcUserServiceBeanDefinitionParser extends AbstractUserDetailsServiceBeanDefinitionParser { + static final String ATT_DATA_SOURCE = "data-source-ref"; static final String ATT_USERS_BY_USERNAME_QUERY = "users-by-username-query"; static final String ATT_AUTHORITIES_BY_USERNAME_QUERY = "authorities-by-username-query"; @@ -37,16 +37,14 @@ public class JdbcUserServiceBeanDefinitionParser extends return "org.springframework.security.provisioning.JdbcUserDetailsManager"; } - protected void doParse(Element element, ParserContext parserContext, - BeanDefinitionBuilder builder) { + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { String dataSource = element.getAttribute(ATT_DATA_SOURCE); if (dataSource != null) { builder.addPropertyReference("dataSource", dataSource); } else { - parserContext.getReaderContext().error( - ATT_DATA_SOURCE + " is required for " + Elements.JDBC_USER_SERVICE, + parserContext.getReaderContext().error(ATT_DATA_SOURCE + " is required for " + Elements.JDBC_USER_SERVICE, parserContext.extractSource(element)); } @@ -69,8 +67,8 @@ public class JdbcUserServiceBeanDefinitionParser extends if (StringUtils.hasText(groupAuthoritiesQuery)) { builder.addPropertyValue("enableGroups", Boolean.TRUE); - builder.addPropertyValue("groupAuthoritiesByUsernameQuery", - groupAuthoritiesQuery); + builder.addPropertyValue("groupAuthoritiesByUsernameQuery", groupAuthoritiesQuery); } } + } diff --git a/config/src/main/java/org/springframework/security/config/authentication/PasswordEncoderParser.java b/config/src/main/java/org/springframework/security/config/authentication/PasswordEncoderParser.java index 0e16f1f1c6..0326fff96e 100644 --- a/config/src/main/java/org/springframework/security/config/authentication/PasswordEncoderParser.java +++ b/config/src/main/java/org/springframework/security/config/authentication/PasswordEncoderParser.java @@ -14,6 +14,7 @@ * limitations under the License. */ package org.springframework.security.config.authentication; + import java.util.HashMap; import java.util.Map; @@ -35,7 +36,9 @@ import org.w3c.dom.Element; * @author Luke Taylor */ public class PasswordEncoderParser { + static final String ATT_REF = "ref"; + public static final String ATT_HASH = "hash"; static final String ATT_BASE_64 = "base64"; static final String OPT_HASH_BCRYPT = "bcrypt"; @@ -76,20 +79,18 @@ public class PasswordEncoderParser { } else { passwordEncoder = createPasswordEncoderBeanDefinition(hash, useBase64); - ((RootBeanDefinition) passwordEncoder).setSource(parserContext - .extractSource(element)); + ((RootBeanDefinition) passwordEncoder).setSource(parserContext.extractSource(element)); } } - public static BeanDefinition createPasswordEncoderBeanDefinition(String hash, - boolean useBase64) { + public static BeanDefinition createPasswordEncoderBeanDefinition(String hash, boolean useBase64) { Class beanClass = ENCODER_CLASSES.get(hash); - BeanDefinitionBuilder beanBldr = BeanDefinitionBuilder - .rootBeanDefinition(beanClass); + BeanDefinitionBuilder beanBldr = BeanDefinitionBuilder.rootBeanDefinition(beanClass); return beanBldr.getBeanDefinition(); } public BeanMetadataElement getPasswordEncoder() { return passwordEncoder; } + } diff --git a/config/src/main/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java index 9394b24460..fc76ad0c9b 100644 --- a/config/src/main/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java @@ -38,8 +38,7 @@ import org.w3c.dom.Element; * @author Luke Taylor * @author Ben Alex */ -public class UserServiceBeanDefinitionParser extends - AbstractUserDetailsServiceBeanDefinitionParser { +public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceBeanDefinitionParser { static final String ATT_PASSWORD = "password"; static final String ATT_NAME = "name"; @@ -56,8 +55,7 @@ public class UserServiceBeanDefinitionParser extends } @SuppressWarnings("unchecked") - protected void doParse(Element element, ParserContext parserContext, - BeanDefinitionBuilder builder) { + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { String userProperties = element.getAttribute(ATT_PROPERTIES); List userElts = DomUtils.getChildElementsByTagName(element, ELT_USER); @@ -76,10 +74,8 @@ public class UserServiceBeanDefinitionParser extends } if (CollectionUtils.isEmpty(userElts)) { - throw new BeanDefinitionStoreException( - "You must supply user definitions, either with <" + ELT_USER - + "> child elements or a " + "properties file (using the '" - + ATT_PROPERTIES + "' attribute)"); + throw new BeanDefinitionStoreException("You must supply user definitions, either with <" + ELT_USER + + "> child elements or a " + "properties file (using the '" + ATT_PROPERTIES + "' attribute)"); } ManagedList users = new ManagedList<>(); @@ -95,13 +91,11 @@ public class UserServiceBeanDefinitionParser extends boolean locked = "true".equals(userElt.getAttribute(ATT_LOCKED)); boolean disabled = "true".equals(userElt.getAttribute(ATT_DISABLED)); - BeanDefinitionBuilder authorities = BeanDefinitionBuilder - .rootBeanDefinition(AuthorityUtils.class); + BeanDefinitionBuilder authorities = BeanDefinitionBuilder.rootBeanDefinition(AuthorityUtils.class); authorities.addConstructorArgValue(userElt.getAttribute(ATT_AUTHORITIES)); authorities.setFactoryMethod("commaSeparatedStringToAuthorityList"); - BeanDefinitionBuilder user = BeanDefinitionBuilder - .rootBeanDefinition(User.class); + BeanDefinitionBuilder user = BeanDefinitionBuilder.rootBeanDefinition(User.class); user.addConstructorArgValue(userName); user.addConstructorArgValue(password); user.addConstructorArgValue(!disabled); @@ -128,4 +122,5 @@ public class UserServiceBeanDefinitionParser extends } return Long.toString(random.nextLong()); } + } diff --git a/config/src/main/java/org/springframework/security/config/authentication/package-info.java b/config/src/main/java/org/springframework/security/config/authentication/package-info.java index 8c0422b51c..d3fb6b02f5 100644 --- a/config/src/main/java/org/springframework/security/config/authentication/package-info.java +++ b/config/src/main/java/org/springframework/security/config/authentication/package-info.java @@ -17,4 +17,3 @@ * Parsing of <authentication-manager> and related elements. */ package org.springframework.security.config.authentication; - diff --git a/config/src/main/java/org/springframework/security/config/core/GrantedAuthorityDefaults.java b/config/src/main/java/org/springframework/security/config/core/GrantedAuthorityDefaults.java index 62d548262d..0a479ad2ec 100644 --- a/config/src/main/java/org/springframework/security/config/core/GrantedAuthorityDefaults.java +++ b/config/src/main/java/org/springframework/security/config/core/GrantedAuthorityDefaults.java @@ -33,10 +33,10 @@ public final class GrantedAuthorityDefaults { /** * The default prefix used with role based authorization. Default is "ROLE_". - * * @return the default role prefix */ public String getRolePrefix() { return this.rolePrefix; } + } diff --git a/config/src/main/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBean.java b/config/src/main/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBean.java index 5f038883d6..7f9b9bd385 100644 --- a/config/src/main/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBean.java @@ -27,14 +27,16 @@ import org.springframework.security.util.InMemoryResource; import java.util.Collection; /** - * Constructs an {@link MapReactiveUserDetailsService} from a resource using {@link UserDetailsResourceFactoryBean}. + * Constructs an {@link MapReactiveUserDetailsService} from a resource using + * {@link UserDetailsResourceFactoryBean}. * * @author Rob Winch * @since 5.0 * @see UserDetailsResourceFactoryBean */ public class ReactiveUserDetailsServiceResourceFactoryBean - implements ResourceLoaderAware, FactoryBean { + implements ResourceLoaderAware, FactoryBean { + private UserDetailsResourceFactoryBean userDetails = new UserDetailsResourceFactoryBean(); @Override @@ -54,17 +56,18 @@ public class ReactiveUserDetailsServiceResourceFactoryBean } /** - * Sets the location of a Resource that is a Properties file in the format defined in {@link UserDetailsResourceFactoryBean}. - * - * @param resourceLocation the location of the properties file that contains the users (i.e. "classpath:users.properties") + * Sets the location of a Resource that is a Properties file in the format defined in + * {@link UserDetailsResourceFactoryBean}. + * @param resourceLocation the location of the properties file that contains the users + * (i.e. "classpath:users.properties") */ public void setResourceLocation(String resourceLocation) { this.userDetails.setResourceLocation(resourceLocation); } /** - * Sets a Resource that is a Properties file in the format defined in {@link UserDetailsResourceFactoryBean}. - * + * Sets a Resource that is a Properties file in the format defined in + * {@link UserDetailsResourceFactoryBean}. * @param resource the Resource to use */ public void setResource(Resource resource) { @@ -72,10 +75,11 @@ public class ReactiveUserDetailsServiceResourceFactoryBean } /** - * Create a ReactiveUserDetailsServiceResourceFactoryBean with the location of a Resource that is a Properties file in the - * format defined in {@link UserDetailsResourceFactoryBean}. - * - * @param resourceLocation the location of the properties file that contains the users (i.e. "classpath:users.properties") + * Create a ReactiveUserDetailsServiceResourceFactoryBean with the location of a + * Resource that is a Properties file in the format defined in + * {@link UserDetailsResourceFactoryBean}. + * @param resourceLocation the location of the properties file that contains the users + * (i.e. "classpath:users.properties") * @return the ReactiveUserDetailsServiceResourceFactoryBean */ public static ReactiveUserDetailsServiceResourceFactoryBean fromResourceLocation(String resourceLocation) { @@ -85,10 +89,10 @@ public class ReactiveUserDetailsServiceResourceFactoryBean } /** - * Create a ReactiveUserDetailsServiceResourceFactoryBean with a Resource that is a Properties file in the - * format defined in {@link UserDetailsResourceFactoryBean}. - * - * @param propertiesResource the Resource that is a properties file that contains the users + * Create a ReactiveUserDetailsServiceResourceFactoryBean with a Resource that is a + * Properties file in the format defined in {@link UserDetailsResourceFactoryBean}. + * @param propertiesResource the Resource that is a properties file that contains the + * users * @return the ReactiveUserDetailsServiceResourceFactoryBean */ public static ReactiveUserDetailsServiceResourceFactoryBean fromResource(Resource propertiesResource) { @@ -100,8 +104,8 @@ public class ReactiveUserDetailsServiceResourceFactoryBean /** * Create a ReactiveUserDetailsServiceResourceFactoryBean with a String that is in the * format defined in {@link UserDetailsResourceFactoryBean}. - * - * @param users the users in the format defined in {@link UserDetailsResourceFactoryBean} + * @param users the users in the format defined in + * {@link UserDetailsResourceFactoryBean} * @return the ReactiveUserDetailsServiceResourceFactoryBean */ public static ReactiveUserDetailsServiceResourceFactoryBean fromString(String users) { @@ -109,4 +113,5 @@ public class ReactiveUserDetailsServiceResourceFactoryBean result.setResource(new InMemoryResource(users)); return result; } + } diff --git a/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java b/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java index f455fd7363..633943f8c8 100644 --- a/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsMapFactoryBean.java @@ -34,7 +34,8 @@ import java.util.Map; * username=password[,enabled|disabled],roles... * *

    - * The enabled and disabled properties are optional with enabled being the default. For example: + * The enabled and disabled properties are optional with enabled being the default. For + * example: *

    * * user=password,ROLE_USER @@ -46,6 +47,7 @@ import java.util.Map; * @since 5.0 */ public class UserDetailsMapFactoryBean implements FactoryBean> { + private final Map userProperties; public UserDetailsMapFactoryBean(Map userProperties) { @@ -64,8 +66,8 @@ public class UserDetailsMapFactoryBean implements FactoryBean getObjectType() { return Collection.class; } + } diff --git a/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBean.java b/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBean.java index 850a72c10b..08b84253dd 100644 --- a/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBean.java @@ -37,7 +37,8 @@ import java.util.Properties; * username=password[,enabled|disabled],roles... * * - * The enabled and disabled properties are optional with enabled being the default. For example: + * The enabled and disabled properties are optional with enabled being the default. For + * example: * * * user=password,ROLE_USER @@ -49,6 +50,7 @@ import java.util.Properties; * @since 5.0 */ public class UserDetailsResourceFactoryBean implements ResourceLoaderAware, FactoryBean> { + private ResourceLoader resourceLoader = new DefaultResourceLoader(); private String resourceLocation; @@ -65,7 +67,7 @@ public class UserDetailsResourceFactoryBean implements ResourceLoaderAware, Fact public Collection getObject() throws Exception { Properties userProperties = new Properties(); Resource resource = getPropertiesResource(); - try(InputStream in = resource.getInputStream()){ + try (InputStream in = resource.getInputStream()) { userProperties.load(in); } return new UserDetailsMapFactoryBean((Map) userProperties).getObject(); @@ -77,17 +79,18 @@ public class UserDetailsResourceFactoryBean implements ResourceLoaderAware, Fact } /** - * Sets the location of a Resource that is a Properties file in the format defined in {@link UserDetailsResourceFactoryBean}. - * - * @param resourceLocation the location of the properties file that contains the users (i.e. "classpath:users.properties") + * Sets the location of a Resource that is a Properties file in the format defined in + * {@link UserDetailsResourceFactoryBean}. + * @param resourceLocation the location of the properties file that contains the users + * (i.e. "classpath:users.properties") */ public void setResourceLocation(String resourceLocation) { this.resourceLocation = resourceLocation; } /** - * Sets a Resource that is a Properties file in the format defined in {@link UserDetailsResourceFactoryBean}. - * + * Sets a Resource that is a Properties file in the format defined in + * {@link UserDetailsResourceFactoryBean}. * @param resource the Resource to use */ public void setResource(Resource resource) { @@ -104,10 +107,10 @@ public class UserDetailsResourceFactoryBean implements ResourceLoaderAware, Fact } /** - * Create a UserDetailsResourceFactoryBean with the location of a Resource that is a Properties file in the - * format defined in {@link UserDetailsResourceFactoryBean}. - * - * @param resourceLocation the location of the properties file that contains the users (i.e. "classpath:users.properties") + * Create a UserDetailsResourceFactoryBean with the location of a Resource that is a + * Properties file in the format defined in {@link UserDetailsResourceFactoryBean}. + * @param resourceLocation the location of the properties file that contains the users + * (i.e. "classpath:users.properties") * @return the UserDetailsResourceFactoryBean */ public static UserDetailsResourceFactoryBean fromResourceLocation(String resourceLocation) { @@ -117,10 +120,10 @@ public class UserDetailsResourceFactoryBean implements ResourceLoaderAware, Fact } /** - * Create a UserDetailsResourceFactoryBean with a Resource that is a Properties file in the - * format defined in {@link UserDetailsResourceFactoryBean}. - * - * @param propertiesResource the Resource that is a properties file that contains the users + * Create a UserDetailsResourceFactoryBean with a Resource that is a Properties file + * in the format defined in {@link UserDetailsResourceFactoryBean}. + * @param propertiesResource the Resource that is a properties file that contains the + * users * @return the UserDetailsResourceFactoryBean */ public static UserDetailsResourceFactoryBean fromResource(Resource propertiesResource) { @@ -131,7 +134,6 @@ public class UserDetailsResourceFactoryBean implements ResourceLoaderAware, Fact /** * Creates a UserDetailsResourceFactoryBean with a resource from the provided String - * * @param users the string representing the users * @return the UserDetailsResourceFactoryBean */ @@ -139,4 +141,5 @@ public class UserDetailsResourceFactoryBean implements ResourceLoaderAware, Fact InMemoryResource resource = new InMemoryResource(users); return fromResource(resource); } + } diff --git a/config/src/main/java/org/springframework/security/config/crypto/RsaKeyConversionServicePostProcessor.java b/config/src/main/java/org/springframework/security/config/crypto/RsaKeyConversionServicePostProcessor.java index b3cd7df87c..59edfcdd3d 100644 --- a/config/src/main/java/org/springframework/security/config/crypto/RsaKeyConversionServicePostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/crypto/RsaKeyConversionServicePostProcessor.java @@ -39,12 +39,14 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * Adds {@link RsaKeyConverters} to the configured {@link ConversionService} or {@link PropertyEditor}s + * Adds {@link RsaKeyConverters} to the configured {@link ConversionService} or + * {@link PropertyEditor}s * * @author Josh Cummings * @since 5.2 */ public class RsaKeyConversionServicePostProcessor implements BeanFactoryPostProcessor { + private static final String CONVERSION_SERVICE_BEAN_NAME = "conversionService"; private ResourceLoader resourceLoader = new DefaultResourceLoader(); @@ -71,7 +73,8 @@ public class RsaKeyConversionServicePostProcessor implements BeanFactoryPostProc ConverterRegistry registry = (ConverterRegistry) service; registry.addConverter(String.class, RSAPrivateKey.class, pkcs8); registry.addConverter(String.class, RSAPublicKey.class, x509); - } else { + } + else { beanFactory.addPropertyEditorRegistrar(registry -> { registry.registerCustomEditor(RSAPublicKey.class, new ConverterPropertyEditorAdapter<>(x509)); registry.registerCustomEditor(RSAPrivateKey.class, new ConverterPropertyEditorAdapter<>(pkcs8)); @@ -80,8 +83,8 @@ public class RsaKeyConversionServicePostProcessor implements BeanFactoryPostProc } private boolean hasUserDefinedConversionService(ConfigurableListableBeanFactory beanFactory) { - return beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && - beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class); + return beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) + && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class); } private Converter pkcs8() { @@ -97,8 +100,8 @@ public class RsaKeyConversionServicePostProcessor implements BeanFactoryPostProc } private Converter pemInputStreamConverter() { - return source -> source.startsWith("-----") ? - toInputStream(source) : toInputStream(this.resourceLoader.getResource(source)); + return source -> source.startsWith("-----") ? toInputStream(source) + : toInputStream(this.resourceLoader.getResource(source)); } private InputStream toInputStream(String raw) { @@ -108,7 +111,8 @@ public class RsaKeyConversionServicePostProcessor implements BeanFactoryPostProc private InputStream toInputStream(Resource resource) { try { return resource.getInputStream(); - } catch (IOException e) { + } + catch (IOException e) { throw new UncheckedIOException(e); } } @@ -117,7 +121,8 @@ public class RsaKeyConversionServicePostProcessor implements BeanFactoryPostProc return inputStream -> { try (InputStream is = inputStream) { return inputStreamKeyConverter.convert(is); - } catch (IOException e) { + } + catch (IOException e) { throw new UncheckedIOException(e); } }; @@ -131,6 +136,7 @@ public class RsaKeyConversionServicePostProcessor implements BeanFactoryPostProc } private static class ConverterPropertyEditorAdapter extends PropertyEditorSupport { + private final Converter converter; ConverterPropertyEditorAdapter(Converter converter) { @@ -146,9 +152,12 @@ public class RsaKeyConversionServicePostProcessor implements BeanFactoryPostProc public void setAsText(String text) throws IllegalArgumentException { if (StringUtils.hasText(text)) { setValue(this.converter.convert(text)); - } else { + } + else { setValue(null); } } + } + } diff --git a/config/src/main/java/org/springframework/security/config/debug/SecurityDebugBeanFactoryPostProcessor.java b/config/src/main/java/org/springframework/security/config/debug/SecurityDebugBeanFactoryPostProcessor.java index ab365c3f00..e6c62bae48 100644 --- a/config/src/main/java/org/springframework/security/config/debug/SecurityDebugBeanFactoryPostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/debug/SecurityDebugBeanFactoryPostProcessor.java @@ -30,14 +30,12 @@ import org.springframework.security.web.debug.DebugFilter; * @author Luke Taylor * @author Rob Winch */ -public class SecurityDebugBeanFactoryPostProcessor implements - BeanDefinitionRegistryPostProcessor { +public class SecurityDebugBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor { + private final Log logger = LogFactory.getLog(getClass()); - public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) - throws BeansException { - logger.warn("\n\n" - + "********************************************************************\n" + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + logger.warn("\n\n" + "********************************************************************\n" + "********** Security debugging is enabled. *************\n" + "********** This may include sensitive information. *************\n" + "********** Do not use in a production system! *************\n" @@ -45,21 +43,18 @@ public class SecurityDebugBeanFactoryPostProcessor implements // SPRING_SECURITY_FILTER_CHAIN does not exist yet since it is an alias that has // not been processed, so use FILTER_CHAIN_PROXY if (registry.containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) { - BeanDefinition fcpBeanDef = registry - .getBeanDefinition(BeanIds.FILTER_CHAIN_PROXY); - BeanDefinitionBuilder debugFilterBldr = BeanDefinitionBuilder - .genericBeanDefinition(DebugFilter.class); + BeanDefinition fcpBeanDef = registry.getBeanDefinition(BeanIds.FILTER_CHAIN_PROXY); + BeanDefinitionBuilder debugFilterBldr = BeanDefinitionBuilder.genericBeanDefinition(DebugFilter.class); debugFilterBldr.addConstructorArgValue(fcpBeanDef); // Remove the alias to SPRING_SECURITY_FILTER_CHAIN, so that it does not // override the new // SPRING_SECURITY_FILTER_CHAIN definition registry.removeAlias(BeanIds.SPRING_SECURITY_FILTER_CHAIN); - registry.registerBeanDefinition(BeanIds.SPRING_SECURITY_FILTER_CHAIN, - debugFilterBldr.getBeanDefinition()); + registry.registerBeanDefinition(BeanIds.SPRING_SECURITY_FILTER_CHAIN, debugFilterBldr.getBeanDefinition()); } } - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) - throws BeansException { + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } + } \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java b/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java index 3e82001c40..5dd453fca2 100644 --- a/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java +++ b/config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java @@ -91,15 +91,19 @@ import static org.springframework.security.config.http.SecurityFilters.X509_FILT * @since 3.0 */ final class AuthenticationConfigBuilder { + private final Log logger = LogFactory.getLog(getClass()); private static final String ATT_REALM = "realm"; + private static final String DEF_REALM = "Realm"; static final String OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationFilter"; static final String OPEN_ID_AUTHENTICATION_PROVIDER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationProvider"; + private static final String OPEN_ID_CONSUMER_CLASS = "org.springframework.security.openid.OpenID4JavaConsumer"; static final String OPEN_ID_ATTRIBUTE_CLASS = "org.springframework.security.openid.OpenIDAttribute"; + private static final String OPEN_ID_ATTRIBUTE_FACTORY_CLASS = "org.springframework.security.openid.RegexBasedAxFetchListFactory"; static final String AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"; @@ -108,6 +112,7 @@ final class AuthenticationConfigBuilder { private static final String ATT_AUTO_CONFIG = "auto-config"; private static final String ATT_ACCESS_DENIED_ERROR_PAGE = "error-page"; + private static final String ATT_ENTRY_POINT_REF = "entry-point-ref"; private static final String ATT_USER_SERVICE_REF = "user-service-ref"; @@ -115,45 +120,74 @@ final class AuthenticationConfigBuilder { private static final String ATT_KEY = "key"; private final Element httpElt; + private final ParserContext pc; private final boolean autoConfig; + private final boolean allowSessionCreation; private RootBeanDefinition anonymousFilter; + private BeanReference anonymousProviderRef; + private BeanDefinition rememberMeFilter; + private String rememberMeServicesId; + private BeanReference rememberMeProviderRef; + private BeanDefinition basicFilter; + private RuntimeBeanReference basicEntryPoint; + private BeanDefinition formEntryPoint; + private BeanDefinition openIDEntryPoint; + private BeanReference openIDProviderRef; + private String formFilterId = null; + private String openIDFilterId = null; + private BeanDefinition x509Filter; + private BeanReference x509ProviderRef; + private BeanDefinition jeeFilter; + private BeanReference jeeProviderRef; + private RootBeanDefinition preAuthEntryPoint; + private BeanMetadataElement mainEntryPoint; + private BeanMetadataElement accessDeniedHandler; private BeanDefinition bearerTokenAuthenticationFilter; private BeanDefinition logoutFilter; + @SuppressWarnings("rawtypes") private ManagedList logoutHandlers; + private BeanDefinition loginPageGenerationFilter; + private BeanDefinition logoutPageGenerationFilter; + private BeanDefinition etf; + private final BeanReference requestCache; + private final BeanReference portMapper; + private final BeanReference portResolver; + private final BeanMetadataElement csrfLogoutHandler; private String loginProcessingUrl; + private String openidLoginProcessingUrl; private String formLoginPage; @@ -161,34 +195,45 @@ final class AuthenticationConfigBuilder { private String openIDLoginPage; private boolean oauth2LoginEnabled; + private boolean defaultAuthorizedClientRepositoryRegistered; + private String oauth2LoginFilterId; + private BeanDefinition oauth2AuthorizationRequestRedirectFilter; + private BeanDefinition oauth2LoginEntryPoint; + private BeanReference oauth2LoginAuthenticationProviderRef; + private BeanReference oauth2LoginOidcAuthenticationProviderRef; + private BeanDefinition oauth2LoginLinks; private boolean oauth2ClientEnabled; + private BeanDefinition authorizationRequestRedirectFilter; + private BeanDefinition authorizationCodeGrantFilter; + private BeanReference authorizationCodeAuthenticationProviderRef; private final List authenticationProviders = new ManagedList<>(); + private final Map defaultDeniedHandlerMappings = new ManagedMap<>(); + private final Map defaultEntryPointMappings = new ManagedMap<>(); + private final List csrfIgnoreRequestMatchers = new ManagedList<>(); - AuthenticationConfigBuilder(Element element, boolean forceAutoConfig, - ParserContext pc, SessionCreationPolicy sessionPolicy, - BeanReference requestCache, BeanReference authenticationManager, - BeanReference sessionStrategy, BeanReference portMapper, - BeanReference portResolver, BeanMetadataElement csrfLogoutHandler) { + AuthenticationConfigBuilder(Element element, boolean forceAutoConfig, ParserContext pc, + SessionCreationPolicy sessionPolicy, BeanReference requestCache, BeanReference authenticationManager, + BeanReference sessionStrategy, BeanReference portMapper, BeanReference portResolver, + BeanMetadataElement csrfLogoutHandler) { this.httpElt = element; this.pc = pc; this.requestCache = requestCache; - autoConfig = forceAutoConfig - | "true".equals(element.getAttribute(ATT_AUTO_CONFIG)); + autoConfig = forceAutoConfig | "true".equals(element.getAttribute(ATT_AUTO_CONFIG)); this.allowSessionCreation = sessionPolicy != SessionCreationPolicy.NEVER && sessionPolicy != SessionCreationPolicy.STATELESS; this.portMapper = portMapper; @@ -214,8 +259,7 @@ final class AuthenticationConfigBuilder { // Parse remember me before logout as RememberMeServices is also a LogoutHandler // implementation. - Element rememberMeElt = DomUtils.getChildElementByTagName(httpElt, - Elements.REMEMBER_ME); + Element rememberMeElt = DomUtils.getChildElementByTagName(httpElt, Elements.REMEMBER_ME); if (rememberMeElt != null) { String key = rememberMeElt.getAttribute(ATT_KEY); @@ -224,8 +268,8 @@ final class AuthenticationConfigBuilder { key = createKey(); } - RememberMeBeanDefinitionParser rememberMeParser = new RememberMeBeanDefinitionParser( - key, authenticationManager); + RememberMeBeanDefinitionParser rememberMeParser = new RememberMeBeanDefinitionParser(key, + authenticationManager); rememberMeFilter = rememberMeParser.parse(rememberMeElt, pc); rememberMeServicesId = rememberMeParser.getRememberMeServicesId(); createRememberMeProvider(key); @@ -233,8 +277,7 @@ final class AuthenticationConfigBuilder { } private void createRememberMeProvider(String key) { - RootBeanDefinition provider = new RootBeanDefinition( - RememberMeAuthenticationProvider.class); + RootBeanDefinition provider = new RootBeanDefinition(RememberMeAuthenticationProvider.class); provider.setSource(rememberMeFilter.getSource()); provider.getConstructorArgumentValues().addGenericArgumentValue(key); @@ -247,15 +290,13 @@ final class AuthenticationConfigBuilder { void createFormLoginFilter(BeanReference sessionStrategy, BeanReference authManager) { - Element formLoginElt = DomUtils.getChildElementByTagName(httpElt, - Elements.FORM_LOGIN); + Element formLoginElt = DomUtils.getChildElementByTagName(httpElt, Elements.FORM_LOGIN); RootBeanDefinition formFilter = null; if (formLoginElt != null || autoConfig) { - FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser( - "/login", "POST", AUTHENTICATION_PROCESSING_FILTER_CLASS, - requestCache, sessionStrategy, allowSessionCreation, portMapper, - portResolver); + FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/login", "POST", + AUTHENTICATION_PROCESSING_FILTER_CLASS, requestCache, sessionStrategy, allowSessionCreation, + portMapper, portResolver); parser.parse(formLoginElt, pc); formFilter = parser.getFilterBean(); @@ -265,10 +306,8 @@ final class AuthenticationConfigBuilder { } if (formFilter != null) { - formFilter.getPropertyValues().addPropertyValue("allowSessionCreation", - allowSessionCreation); - formFilter.getPropertyValues().addPropertyValue("authenticationManager", - authManager); + formFilter.getPropertyValues().addPropertyValue("allowSessionCreation", allowSessionCreation); + formFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager); // Id is required by login page filter formFilterId = pc.getReaderContext().generateBeanName(formFilter); @@ -306,8 +345,7 @@ final class AuthenticationConfigBuilder { oauth2LoginEntryPoint = parser.getOAuth2LoginAuthenticationEntryPoint(); // generate bean name to be registered - String oauth2LoginAuthProviderId = pc.getReaderContext() - .generateBeanName(oauth2LoginAuthProvider); + String oauth2LoginAuthProviderId = pc.getReaderContext().generateBeanName(oauth2LoginAuthProvider); oauth2LoginFilterId = pc.getReaderContext().generateBeanName(oauth2LoginFilterBean); String oauth2AuthorizationRequestRedirectFilterId = pc.getReaderContext() .generateBeanName(oauth2AuthorizationRequestRedirectFilter); @@ -315,8 +353,8 @@ final class AuthenticationConfigBuilder { // register the component pc.registerBeanComponent(new BeanComponentDefinition(oauth2LoginFilterBean, oauth2LoginFilterId)); - pc.registerBeanComponent(new BeanComponentDefinition( - oauth2AuthorizationRequestRedirectFilter, oauth2AuthorizationRequestRedirectFilterId)); + pc.registerBeanComponent(new BeanComponentDefinition(oauth2AuthorizationRequestRedirectFilter, + oauth2AuthorizationRequestRedirectFilterId)); pc.registerBeanComponent(new BeanComponentDefinition(oauth2LoginAuthProvider, oauth2LoginAuthProviderId)); oauth2LoginAuthenticationProviderRef = new RuntimeBeanReference(oauth2LoginAuthProviderId); @@ -324,8 +362,8 @@ final class AuthenticationConfigBuilder { // oidc provider BeanDefinition oauth2LoginOidcAuthProvider = parser.getOAuth2LoginOidcAuthenticationProvider(); String oauth2LoginOidcAuthProviderId = pc.getReaderContext().generateBeanName(oauth2LoginOidcAuthProvider); - pc.registerBeanComponent(new BeanComponentDefinition( - oauth2LoginOidcAuthProvider, oauth2LoginOidcAuthProviderId)); + pc.registerBeanComponent( + new BeanComponentDefinition(oauth2LoginOidcAuthProvider, oauth2LoginOidcAuthProviderId)); oauth2LoginOidcAuthenticationProviderRef = new RuntimeBeanReference(oauth2LoginOidcAuthProviderId); } @@ -336,8 +374,8 @@ final class AuthenticationConfigBuilder { } this.oauth2ClientEnabled = true; - OAuth2ClientBeanDefinitionParser parser = new OAuth2ClientBeanDefinitionParser( - requestCache, authenticationManager); + OAuth2ClientBeanDefinitionParser parser = new OAuth2ClientBeanDefinitionParser(requestCache, + authenticationManager); parser.parse(oauth2ClientElt, this.pc); BeanDefinition defaultAuthorizedClientRepository = parser.getDefaultAuthorizedClientRepository(); @@ -346,29 +384,30 @@ final class AuthenticationConfigBuilder { this.authorizationRequestRedirectFilter = parser.getAuthorizationRequestRedirectFilter(); String authorizationRequestRedirectFilterId = pc.getReaderContext() .generateBeanName(this.authorizationRequestRedirectFilter); - this.pc.registerBeanComponent(new BeanComponentDefinition( - this.authorizationRequestRedirectFilter, authorizationRequestRedirectFilterId)); + this.pc.registerBeanComponent(new BeanComponentDefinition(this.authorizationRequestRedirectFilter, + authorizationRequestRedirectFilterId)); this.authorizationCodeGrantFilter = parser.getAuthorizationCodeGrantFilter(); String authorizationCodeGrantFilterId = pc.getReaderContext() .generateBeanName(this.authorizationCodeGrantFilter); - this.pc.registerBeanComponent(new BeanComponentDefinition( - this.authorizationCodeGrantFilter, authorizationCodeGrantFilterId)); + this.pc.registerBeanComponent( + new BeanComponentDefinition(this.authorizationCodeGrantFilter, authorizationCodeGrantFilterId)); BeanDefinition authorizationCodeAuthenticationProvider = parser.getAuthorizationCodeAuthenticationProvider(); String authorizationCodeAuthenticationProviderId = pc.getReaderContext() .generateBeanName(authorizationCodeAuthenticationProvider); - this.pc.registerBeanComponent(new BeanComponentDefinition( - authorizationCodeAuthenticationProvider, authorizationCodeAuthenticationProviderId)); - this.authorizationCodeAuthenticationProviderRef = new RuntimeBeanReference(authorizationCodeAuthenticationProviderId); + this.pc.registerBeanComponent(new BeanComponentDefinition(authorizationCodeAuthenticationProvider, + authorizationCodeAuthenticationProviderId)); + this.authorizationCodeAuthenticationProviderRef = new RuntimeBeanReference( + authorizationCodeAuthenticationProviderId); } void registerDefaultAuthorizedClientRepositoryIfNecessary(BeanDefinition defaultAuthorizedClientRepository) { if (!this.defaultAuthorizedClientRepositoryRegistered && defaultAuthorizedClientRepository != null) { String authorizedClientRepositoryId = pc.getReaderContext() .generateBeanName(defaultAuthorizedClientRepository); - this.pc.registerBeanComponent(new BeanComponentDefinition( - defaultAuthorizedClientRepository, authorizedClientRepositoryId)); + this.pc.registerBeanComponent( + new BeanComponentDefinition(defaultAuthorizedClientRepository, authorizedClientRepositoryId)); this.defaultAuthorizedClientRepositoryRegistered = true; } } @@ -378,16 +417,16 @@ final class AuthenticationConfigBuilder { return; } - boolean webmvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", getClass().getClassLoader()); + boolean webmvcPresent = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", + getClass().getClassLoader()); if (webmvcPresent) { - this.pc.getReaderContext().registerWithGeneratedName( - new RootBeanDefinition(OAuth2ClientWebMvcSecurityPostProcessor.class)); + this.pc.getReaderContext() + .registerWithGeneratedName(new RootBeanDefinition(OAuth2ClientWebMvcSecurityPostProcessor.class)); } } void createOpenIDLoginFilter(BeanReference sessionStrategy, BeanReference authManager) { - Element openIDLoginElt = DomUtils.getChildElementByTagName(httpElt, - Elements.OPENID_LOGIN); + Element openIDLoginElt = DomUtils.getChildElementByTagName(httpElt, Elements.OPENID_LOGIN); RootBeanDefinition openIDFilter = null; if (openIDLoginElt != null) { @@ -395,14 +434,11 @@ final class AuthenticationConfigBuilder { } if (openIDFilter != null) { - openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", - allowSessionCreation); - openIDFilter.getPropertyValues().addPropertyValue("authenticationManager", - authManager); + openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", allowSessionCreation); + openIDFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager); // Required by login page filter openIDFilterId = pc.getReaderContext().generateBeanName(openIDFilter); - pc.registerBeanComponent(new BeanComponentDefinition(openIDFilter, - openIDFilterId)); + pc.registerBeanComponent(new BeanComponentDefinition(openIDFilter, openIDFilterId)); injectRememberMeServicesRef(openIDFilter, rememberMeServicesId); createOpenIDProvider(); @@ -412,18 +448,18 @@ final class AuthenticationConfigBuilder { /** * Parses OpenID 1.0 and 2.0 - related parts of configuration xmls * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @param sessionStrategy sessionStrategy * @param openIDLoginElt the element from the xml file * @return the parsed filter as rootBeanDefinition */ - private RootBeanDefinition parseOpenIDFilter( BeanReference sessionStrategy, Element openIDLoginElt ) { + private RootBeanDefinition parseOpenIDFilter(BeanReference sessionStrategy, Element openIDLoginElt) { RootBeanDefinition openIDFilter; - FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser( - "/login/openid", null, - OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS, requestCache, - sessionStrategy, allowSessionCreation, portMapper, portResolver); + FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/login/openid", null, + OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS, requestCache, sessionStrategy, allowSessionCreation, + portMapper, portResolver); parser.parse(openIDLoginElt, pc); openIDFilter = parser.getFilterBean(); @@ -436,10 +472,8 @@ final class AuthenticationConfigBuilder { if (!attrExElts.isEmpty()) { // Set up the consumer with the required attribute list - BeanDefinitionBuilder consumerBldr = BeanDefinitionBuilder - .rootBeanDefinition(OPEN_ID_CONSUMER_CLASS); - BeanDefinitionBuilder axFactory = BeanDefinitionBuilder - .rootBeanDefinition(OPEN_ID_ATTRIBUTE_FACTORY_CLASS); + BeanDefinitionBuilder consumerBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_CONSUMER_CLASS); + BeanDefinitionBuilder axFactory = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_ATTRIBUTE_FACTORY_CLASS); ManagedMap> axMap = new ManagedMap<>(); for (Element attrExElt : attrExElts) { @@ -447,11 +481,8 @@ final class AuthenticationConfigBuilder { if (!StringUtils.hasText(identifierMatch)) { if (attrExElts.size() > 1) { - pc.getReaderContext().error( - "You must supply an identifier-match attribute if using more" - + " than one " - + Elements.OPENID_ATTRIBUTE_EXCHANGE - + " element", attrExElt); + pc.getReaderContext().error("You must supply an identifier-match attribute if using more" + + " than one " + Elements.OPENID_ATTRIBUTE_EXCHANGE + " element", attrExElt); } // Match anything identifierMatch = ".*"; @@ -462,22 +493,19 @@ final class AuthenticationConfigBuilder { axFactory.addConstructorArgValue(axMap); consumerBldr.addConstructorArgValue(axFactory.getBeanDefinition()); - openIDFilter.getPropertyValues().addPropertyValue("consumer", - consumerBldr.getBeanDefinition()); + openIDFilter.getPropertyValues().addPropertyValue("consumer", consumerBldr.getBeanDefinition()); } return openIDFilter; } private ManagedList parseOpenIDAttributes(Element attrExElt) { ManagedList attributes = new ManagedList<>(); - for (Element attElt : DomUtils.getChildElementsByTagName(attrExElt, - Elements.OPENID_ATTRIBUTE)) { + for (Element attElt : DomUtils.getChildElementsByTagName(attrExElt, Elements.OPENID_ATTRIBUTE)) { String name = attElt.getAttribute("name"); String type = attElt.getAttribute("type"); String required = attElt.getAttribute("required"); String count = attElt.getAttribute("count"); - BeanDefinitionBuilder attrBldr = BeanDefinitionBuilder - .rootBeanDefinition(OPEN_ID_ATTRIBUTE_CLASS); + BeanDefinitionBuilder attrBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_ATTRIBUTE_CLASS); attrBldr.addConstructorArgValue(name); attrBldr.addConstructorArgValue(type); if (StringUtils.hasLength(required)) { @@ -494,26 +522,22 @@ final class AuthenticationConfigBuilder { } private void createOpenIDProvider() { - Element openIDLoginElt = DomUtils.getChildElementByTagName(httpElt, - Elements.OPENID_LOGIN); + Element openIDLoginElt = DomUtils.getChildElementByTagName(httpElt, Elements.OPENID_LOGIN); BeanDefinitionBuilder openIDProviderBuilder = BeanDefinitionBuilder .rootBeanDefinition(OPEN_ID_AUTHENTICATION_PROVIDER_CLASS); RootBeanDefinition uds = new RootBeanDefinition(); uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY); uds.setFactoryMethodName("authenticationUserDetailsService"); - uds.getConstructorArgumentValues().addGenericArgumentValue( - openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF)); + uds.getConstructorArgumentValues().addGenericArgumentValue(openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF)); openIDProviderBuilder.addPropertyValue("authenticationUserDetailsService", uds); BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition(); - openIDProviderRef = new RuntimeBeanReference(pc.getReaderContext() - .registerWithGeneratedName(openIDProvider)); + openIDProviderRef = new RuntimeBeanReference(pc.getReaderContext().registerWithGeneratedName(openIDProvider)); } - private void injectRememberMeServicesRef(RootBeanDefinition bean, - String rememberMeServicesId) { + private void injectRememberMeServicesRef(RootBeanDefinition bean, String rememberMeServicesId) { if (rememberMeServicesId != null) { bean.getPropertyValues().addPropertyValue("rememberMeServices", new RuntimeBeanReference(rememberMeServicesId)); @@ -521,8 +545,7 @@ final class AuthenticationConfigBuilder { } void createBasicFilter(BeanReference authManager) { - Element basicAuthElt = DomUtils.getChildElementByTagName(httpElt, - Elements.BASIC_AUTH); + Element basicAuthElt = DomUtils.getChildElementByTagName(httpElt, Elements.BASIC_AUTH); if (basicAuthElt == null && !autoConfig) { // No basic auth, do nothing @@ -534,15 +557,13 @@ final class AuthenticationConfigBuilder { realm = DEF_REALM; } - BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder - .rootBeanDefinition(BasicAuthenticationFilter.class); + BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicAuthenticationFilter.class); String entryPointId; if (basicAuthElt != null) { if (StringUtils.hasText(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF))) { - basicEntryPoint = new RuntimeBeanReference( - basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF)); + basicEntryPoint = new RuntimeBeanReference(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF)); } injectAuthenticationDetailsSource(basicAuthElt, filterBuilder); @@ -550,8 +571,7 @@ final class AuthenticationConfigBuilder { } if (basicEntryPoint == null) { - RootBeanDefinition entryPoint = new RootBeanDefinition( - BasicAuthenticationEntryPoint.class); + RootBeanDefinition entryPoint = new RootBeanDefinition(BasicAuthenticationEntryPoint.class); entryPoint.setSource(pc.extractSource(httpElt)); entryPoint.getPropertyValues().addPropertyValue("realmName", realm); entryPointId = pc.getReaderContext().generateBeanName(entryPoint); @@ -565,17 +585,16 @@ final class AuthenticationConfigBuilder { } void createBearerTokenAuthenticationFilter(BeanReference authManager) { - Element resourceServerElt = DomUtils.getChildElementByTagName(httpElt, - Elements.OAUTH2_RESOURCE_SERVER); + Element resourceServerElt = DomUtils.getChildElementByTagName(httpElt, Elements.OAUTH2_RESOURCE_SERVER); if (resourceServerElt == null) { // No resource server, do nothing return; } - OAuth2ResourceServerBeanDefinitionParser resourceServerBuilder = - new OAuth2ResourceServerBeanDefinitionParser(authManager, authenticationProviders, - defaultEntryPointMappings, defaultDeniedHandlerMappings, csrfIgnoreRequestMatchers); + OAuth2ResourceServerBeanDefinitionParser resourceServerBuilder = new OAuth2ResourceServerBeanDefinitionParser( + authManager, authenticationProviders, defaultEntryPointMappings, defaultDeniedHandlerMappings, + csrfIgnoreRequestMatchers); bearerTokenAuthenticationFilter = resourceServerBuilder.parse(resourceServerElt, pc); } @@ -596,8 +615,7 @@ final class AuthenticationConfigBuilder { .rootBeanDefinition(SubjectDnX509PrincipalExtractor.class); extractor.addPropertyValue("subjectDnRegex", regex); - filterBuilder.addPropertyValue("principalExtractor", - extractor.getBeanDefinition()); + filterBuilder.addPropertyValue("principalExtractor", extractor.getBeanDefinition()); } injectAuthenticationDetailsSource(x509Elt, filterBuilder); @@ -611,33 +629,26 @@ final class AuthenticationConfigBuilder { x509Filter = filter; } - private void injectAuthenticationDetailsSource(Element elt, - BeanDefinitionBuilder filterBuilder) { - String authDetailsSourceRef = elt - .getAttribute(AuthenticationConfigBuilder.ATT_AUTH_DETAILS_SOURCE_REF); + private void injectAuthenticationDetailsSource(Element elt, BeanDefinitionBuilder filterBuilder) { + String authDetailsSourceRef = elt.getAttribute(AuthenticationConfigBuilder.ATT_AUTH_DETAILS_SOURCE_REF); if (StringUtils.hasText(authDetailsSourceRef)) { - filterBuilder.addPropertyReference("authenticationDetailsSource", - authDetailsSourceRef); + filterBuilder.addPropertyReference("authenticationDetailsSource", authDetailsSourceRef); } } private void createX509Provider() { Element x509Elt = DomUtils.getChildElementByTagName(httpElt, Elements.X509); - BeanDefinition provider = new RootBeanDefinition( - PreAuthenticatedAuthenticationProvider.class); + BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class); RootBeanDefinition uds = new RootBeanDefinition(); uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY); uds.setFactoryMethodName("authenticationUserDetailsService"); - uds.getConstructorArgumentValues().addGenericArgumentValue( - x509Elt.getAttribute(ATT_USER_SERVICE_REF)); + uds.getConstructorArgumentValues().addGenericArgumentValue(x509Elt.getAttribute(ATT_USER_SERVICE_REF)); - provider.getPropertyValues().addPropertyValue( - "preAuthenticatedUserDetailsService", uds); + provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", uds); - x509ProviderRef = new RuntimeBeanReference(pc.getReaderContext() - .registerWithGeneratedName(provider)); + x509ProviderRef = new RuntimeBeanReference(pc.getReaderContext().registerWithGeneratedName(provider)); } private void createPrauthEntryPoint(Element source) { @@ -662,23 +673,19 @@ final class AuthenticationConfigBuilder { BeanDefinitionBuilder adsBldr = BeanDefinitionBuilder .rootBeanDefinition(J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.class); adsBldr.addPropertyValue("userRoles2GrantedAuthoritiesMapper", - new RootBeanDefinition( - SimpleAttributes2GrantedAuthoritiesMapper.class)); + new RootBeanDefinition(SimpleAttributes2GrantedAuthoritiesMapper.class)); String roles = jeeElt.getAttribute(ATT_MAPPABLE_ROLES); Assert.hasLength(roles, "roles is expected to have length"); - BeanDefinitionBuilder rolesBuilder = BeanDefinitionBuilder - .rootBeanDefinition(StringUtils.class); + BeanDefinitionBuilder rolesBuilder = BeanDefinitionBuilder.rootBeanDefinition(StringUtils.class); rolesBuilder.addConstructorArgValue(roles); rolesBuilder.setFactoryMethod("commaDelimitedListToSet"); - RootBeanDefinition mappableRolesRetriever = new RootBeanDefinition( - SimpleMappableAttributesRetriever.class); - mappableRolesRetriever.getPropertyValues().addPropertyValue( - "mappableAttributes", rolesBuilder.getBeanDefinition()); + RootBeanDefinition mappableRolesRetriever = new RootBeanDefinition(SimpleMappableAttributesRetriever.class); + mappableRolesRetriever.getPropertyValues().addPropertyValue("mappableAttributes", + rolesBuilder.getBeanDefinition()); adsBldr.addPropertyValue("mappableRolesRetriever", mappableRolesRetriever); - filterBuilder.addPropertyValue("authenticationDetailsSource", - adsBldr.getBeanDefinition()); + filterBuilder.addPropertyValue("authenticationDetailsSource", adsBldr.getBeanDefinition()); filter = (RootBeanDefinition) filterBuilder.getBeanDefinition(); @@ -691,27 +698,22 @@ final class AuthenticationConfigBuilder { private void createJeeProvider() { Element jeeElt = DomUtils.getChildElementByTagName(httpElt, Elements.JEE); - BeanDefinition provider = new RootBeanDefinition( - PreAuthenticatedAuthenticationProvider.class); + BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class); RootBeanDefinition uds; if (StringUtils.hasText(jeeElt.getAttribute(ATT_USER_SERVICE_REF))) { uds = new RootBeanDefinition(); uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY); uds.setFactoryMethodName("authenticationUserDetailsService"); - uds.getConstructorArgumentValues().addGenericArgumentValue( - jeeElt.getAttribute(ATT_USER_SERVICE_REF)); + uds.getConstructorArgumentValues().addGenericArgumentValue(jeeElt.getAttribute(ATT_USER_SERVICE_REF)); } else { - uds = new RootBeanDefinition( - PreAuthenticatedGrantedAuthoritiesUserDetailsService.class); + uds = new RootBeanDefinition(PreAuthenticatedGrantedAuthoritiesUserDetailsService.class); } - provider.getPropertyValues().addPropertyValue( - "preAuthenticatedUserDetailsService", uds); + provider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService", uds); - jeeProviderRef = new RuntimeBeanReference(pc.getReaderContext() - .registerWithGeneratedName(provider)); + jeeProviderRef = new RuntimeBeanReference(pc.getReaderContext().registerWithGeneratedName(provider)); } void createLoginPageFilterIfNeeded() { @@ -720,8 +722,7 @@ final class AuthenticationConfigBuilder { // If no login page has been defined, add in the default page generator. if (needLoginPage && formLoginPage == null && openIDLoginPage == null) { logger.info("No login page configured. The default internal one will be used. Use the '" - + FormLoginBeanDefinitionParser.ATT_LOGIN_PAGE - + "' attribute to set the URL of the login page."); + + FormLoginBeanDefinitionParser.ATT_LOGIN_PAGE + "' attribute to set the URL of the login page."); BeanDefinitionBuilder loginPageFilter = BeanDefinitionBuilder .rootBeanDefinition(DefaultLoginPageGeneratingFilter.class); loginPageFilter.addPropertyValue("resolveHiddenInputs", new CsrfTokenHiddenInputFunction()); @@ -737,8 +738,7 @@ final class AuthenticationConfigBuilder { if (openIDFilterId != null) { loginPageFilter.addConstructorArgReference(openIDFilterId); - loginPageFilter.addPropertyValue("openIDauthenticationUrl", - openidLoginProcessingUrl); + loginPageFilter.addPropertyValue("openIDauthenticationUrl", openidLoginProcessingUrl); } if (oauth2LoginFilterId != null) { @@ -759,8 +759,8 @@ final class AuthenticationConfigBuilder { if (formLoginPage == null) { formLoginPage = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL; } - LogoutBeanDefinitionParser logoutParser = new LogoutBeanDefinitionParser( - formLoginPage, rememberMeServicesId, csrfLogoutHandler); + LogoutBeanDefinitionParser logoutParser = new LogoutBeanDefinitionParser(formLoginPage, + rememberMeServicesId, csrfLogoutHandler); logoutFilter = logoutParser.parse(logoutElt, pc); logoutHandlers = logoutParser.getLogoutHandlers(); } @@ -774,8 +774,7 @@ final class AuthenticationConfigBuilder { logoutHandlers.add(csrfLogoutHandler); } logoutHandlers.add(new RuntimeBeanReference(rememberMeServicesId)); - logoutHandlers - .add(new RootBeanDefinition(SecurityContextLogoutHandler.class)); + logoutHandlers.add(new RootBeanDefinition(SecurityContextLogoutHandler.class)); } return logoutHandlers; @@ -794,8 +793,7 @@ final class AuthenticationConfigBuilder { } void createAnonymousFilter() { - Element anonymousElt = DomUtils.getChildElementByTagName(httpElt, - Elements.ANONYMOUS); + Element anonymousElt = DomUtils.getChildElementByTagName(httpElt, Elements.ANONYMOUS); if (anonymousElt != null && "false".equals(anonymousElt.getAttribute("enabled"))) { return; @@ -828,16 +826,13 @@ final class AuthenticationConfigBuilder { anonymousFilter = new RootBeanDefinition(AnonymousAuthenticationFilter.class); anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(0, key); - anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(1, - username); + anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(1, username); anonymousFilter.getConstructorArgumentValues().addIndexedArgumentValue(2, AuthorityUtils.commaSeparatedStringToAuthorityList(grantedAuthority)); anonymousFilter.setSource(source); - RootBeanDefinition anonymousProviderBean = new RootBeanDefinition( - AnonymousAuthenticationProvider.class); - anonymousProviderBean.getConstructorArgumentValues().addIndexedArgumentValue(0, - key); + RootBeanDefinition anonymousProviderBean = new RootBeanDefinition(AnonymousAuthenticationProvider.class); + anonymousProviderBean.getConstructorArgumentValues().addIndexedArgumentValue(0, key); anonymousProviderBean.setSource(anonymousFilter.getSource()); String id = pc.getReaderContext().generateBeanName(anonymousProviderBean); pc.registerBeanComponent(new BeanComponentDefinition(anonymousProviderBean, id)); @@ -852,8 +847,7 @@ final class AuthenticationConfigBuilder { } void createExceptionTranslationFilter() { - BeanDefinitionBuilder etfBuilder = BeanDefinitionBuilder - .rootBeanDefinition(ExceptionTranslationFilter.class); + BeanDefinitionBuilder etfBuilder = BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class); accessDeniedHandler = createAccessDeniedHandler(httpElt, pc); etfBuilder.addPropertyValue("accessDeniedHandler", accessDeniedHandler); assert requestCache != null; @@ -864,10 +858,8 @@ final class AuthenticationConfigBuilder { etf = etfBuilder.getBeanDefinition(); } - private BeanMetadataElement createAccessDeniedHandler(Element element, - ParserContext pc) { - Element accessDeniedElt = DomUtils.getChildElementByTagName(element, - Elements.ACCESS_DENIED_HANDLER); + private BeanMetadataElement createAccessDeniedHandler(Element element, ParserContext pc) { + Element accessDeniedElt = DomUtils.getChildElementByTagName(element, Elements.ACCESS_DENIED_HANDLER); BeanDefinitionBuilder accessDeniedHandler = BeanDefinitionBuilder .rootBeanDefinition(AccessDeniedHandlerImpl.class); @@ -878,11 +870,9 @@ final class AuthenticationConfigBuilder { if (StringUtils.hasText(errorPage)) { if (StringUtils.hasText(ref)) { pc.getReaderContext() - .error("The attribute " - + ATT_ACCESS_DENIED_ERROR_PAGE + .error("The attribute " + ATT_ACCESS_DENIED_ERROR_PAGE + " cannot be used together with the 'ref' attribute within <" - + Elements.ACCESS_DENIED_HANDLER + ">", - pc.extractSource(accessDeniedElt)); + + Elements.ACCESS_DENIED_HANDLER + ">", pc.extractSource(accessDeniedElt)); } accessDeniedHandler.addPropertyValue("errorPage", errorPage); @@ -904,8 +894,8 @@ final class AuthenticationConfigBuilder { accessDeniedHandler = BeanDefinitionBuilder .rootBeanDefinition(RequestMatcherDelegatingAccessDeniedHandler.class); accessDeniedHandler.addConstructorArgValue(this.defaultDeniedHandlerMappings); - accessDeniedHandler.addConstructorArgValue - (BeanDefinitionBuilder.rootBeanDefinition(AccessDeniedHandlerImpl.class)); + accessDeniedHandler + .addConstructorArgValue(BeanDefinitionBuilder.rootBeanDefinition(AccessDeniedHandlerImpl.class)); return accessDeniedHandler.getBeanDefinition(); } @@ -929,12 +919,9 @@ final class AuthenticationConfigBuilder { return delegatingEntryPoint.getBeanDefinition(); } - Element basicAuthElt = DomUtils.getChildElementByTagName(httpElt, - Elements.BASIC_AUTH); - Element formLoginElt = DomUtils.getChildElementByTagName(httpElt, - Elements.FORM_LOGIN); - Element openIDLoginElt = DomUtils.getChildElementByTagName(httpElt, - Elements.OPENID_LOGIN); + Element basicAuthElt = DomUtils.getChildElementByTagName(httpElt, Elements.BASIC_AUTH); + Element formLoginElt = DomUtils.getChildElementByTagName(httpElt, Elements.FORM_LOGIN); + Element openIDLoginElt = DomUtils.getChildElementByTagName(httpElt, Elements.OPENID_LOGIN); // Basic takes precedence if explicit element is used and no others are configured if (basicAuthElt != null && formLoginElt == null && openIDLoginElt == null && oauth2LoginEntryPoint == null) { return basicEntryPoint; @@ -946,17 +933,19 @@ final class AuthenticationConfigBuilder { if (formLoginPage != null && openIDLoginPage != null) { pc.getReaderContext().error( - "Only one login-page can be defined, either for OpenID or form-login, " - + "but not both.", pc.extractSource(openIDLoginElt)); + "Only one login-page can be defined, either for OpenID or form-login, " + "but not both.", + pc.extractSource(openIDLoginElt)); } if (formFilterId != null && openIDLoginPage == null) { // gh-6802 - // If form login was enabled through element and Oauth2 login was enabled from element then use form login + // If form login was enabled through element and Oauth2 login was enabled from + // element then use form login if (formLoginElt != null && oauth2LoginEntryPoint != null) { return formEntryPoint; } - // If form login was enabled through auto-config, and Oauth2 login was not enabled then use form login + // If form login was enabled through auto-config, and Oauth2 login was not + // enabled then use form login if (oauth2LoginEntryPoint == null) { return formEntryPoint; } @@ -977,11 +966,10 @@ final class AuthenticationConfigBuilder { return oauth2LoginEntryPoint; } - pc.getReaderContext() - .error("No AuthenticationEntryPoint could be established. Please " - + "make sure you have a login mechanism configured through the namespace (such as form-login) or " - + "specify a custom AuthenticationEntryPoint with the '" - + ATT_ENTRY_POINT_REF + "' attribute ", pc.extractSource(httpElt)); + pc.getReaderContext().error("No AuthenticationEntryPoint could be established. Please " + + "make sure you have a login mechanism configured through the namespace (such as form-login) or " + + "specify a custom AuthenticationEntryPoint with the '" + ATT_ENTRY_POINT_REF + "' attribute ", + pc.extractSource(httpElt)); return null; } @@ -990,11 +978,9 @@ final class AuthenticationConfigBuilder { // Multiple case return; } - RootBeanDefinition bean = new RootBeanDefinition( - UserDetailsServiceFactoryBean.class); + RootBeanDefinition bean = new RootBeanDefinition(UserDetailsServiceFactoryBean.class); bean.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - pc.registerBeanComponent(new BeanComponentDefinition(bean, - BeanIds.USER_DETAILS_SERVICE_FACTORY)); + pc.registerBeanComponent(new BeanComponentDefinition(bean, BeanIds.USER_DETAILS_SERVICE_FACTORY)); } List getFilters() { @@ -1021,18 +1007,17 @@ final class AuthenticationConfigBuilder { } if (formFilterId != null) { - filters.add(new OrderDecorator(new RuntimeBeanReference(formFilterId), - FORM_LOGIN_FILTER)); + filters.add(new OrderDecorator(new RuntimeBeanReference(formFilterId), FORM_LOGIN_FILTER)); } if (oauth2LoginFilterId != null) { filters.add(new OrderDecorator(new RuntimeBeanReference(oauth2LoginFilterId), OAUTH2_LOGIN_FILTER)); - filters.add(new OrderDecorator(oauth2AuthorizationRequestRedirectFilter, OAUTH2_AUTHORIZATION_REQUEST_FILTER)); + filters.add( + new OrderDecorator(oauth2AuthorizationRequestRedirectFilter, OAUTH2_AUTHORIZATION_REQUEST_FILTER)); } if (openIDFilterId != null) { - filters.add(new OrderDecorator(new RuntimeBeanReference(openIDFilterId), - OPENID_FILTER)); + filters.add(new OrderDecorator(new RuntimeBeanReference(openIDFilterId), OPENID_FILTER)); } if (loginPageGenerationFilter != null) { @@ -1049,7 +1034,8 @@ final class AuthenticationConfigBuilder { } if (authorizationCodeGrantFilter != null) { - filters.add(new OrderDecorator(authorizationRequestRedirectFilter, OAUTH2_AUTHORIZATION_REQUEST_FILTER.getOrder() + 1)); + filters.add(new OrderDecorator(authorizationRequestRedirectFilter, + OAUTH2_AUTHORIZATION_REQUEST_FILTER.getOrder() + 1)); filters.add(new OrderDecorator(authorizationCodeGrantFilter, OAUTH2_AUTHORIZATION_CODE_GRANT_FILTER)); } @@ -1098,8 +1084,7 @@ final class AuthenticationConfigBuilder { return providers; } - private static class CsrfTokenHiddenInputFunction implements - Function> { + private static class CsrfTokenHiddenInputFunction implements Function> { @Override public Map apply(HttpServletRequest request) { @@ -1109,5 +1094,7 @@ final class AuthenticationConfigBuilder { } return Collections.singletonMap(token.getParameterName(), token.getToken()); } + } + } diff --git a/config/src/main/java/org/springframework/security/config/http/ChannelAttributeFactory.java b/config/src/main/java/org/springframework/security/config/http/ChannelAttributeFactory.java index c926b83465..c967584e78 100644 --- a/config/src/main/java/org/springframework/security/config/http/ChannelAttributeFactory.java +++ b/config/src/main/java/org/springframework/security/config/http/ChannelAttributeFactory.java @@ -30,8 +30,11 @@ import org.springframework.security.web.access.channel.ChannelDecisionManagerImp * @since 3.0 */ public class ChannelAttributeFactory { + private static final String OPT_REQUIRES_HTTP = "http"; + private static final String OPT_REQUIRES_HTTPS = "https"; + private static final String OPT_ANY_CHANNEL = "any"; public static List createChannelAttributes(String requiredChannel) { @@ -47,10 +50,10 @@ public class ChannelAttributeFactory { channelConfigAttribute = ChannelDecisionManagerImpl.ANY_CHANNEL; } else { - throw new BeanCreationException("Unknown channel attribute " - + requiredChannel); + throw new BeanCreationException("Unknown channel attribute " + requiredChannel); } return SecurityConfig.createList(channelConfigAttribute); } + } diff --git a/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java index b8c67e6c54..7dbbea8bf0 100644 --- a/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/CorsBeanDefinitionParser.java @@ -33,9 +33,11 @@ import org.w3c.dom.Element; * @since 4.1.1 */ public class CorsBeanDefinitionParser { + private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"; private static final String ATT_SOURCE = "configuration-source-ref"; + private static final String ATT_REF = "ref"; public BeanMetadataElement parse(Element element, ParserContext parserContext) { @@ -64,12 +66,12 @@ public class CorsBeanDefinitionParser { return new RuntimeBeanReference(configurationSourceRef); } - boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, - getClass().getClassLoader()); + boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, getClass().getClassLoader()); if (!mvcPresent) { return null; } return new RootBeanDefinition(HandlerMappingIntrospectorFactoryBean.class); } + } diff --git a/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java index 9ef1fed832..46a2c99b03 100644 --- a/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java @@ -62,30 +62,31 @@ import org.springframework.util.StringUtils; public class CsrfBeanDefinitionParser implements BeanDefinitionParser { private static final String REQUEST_DATA_VALUE_PROCESSOR = "requestDataValueProcessor"; + private static final String DISPATCHER_SERVLET_CLASS_NAME = "org.springframework.web.servlet.DispatcherServlet"; + private static final String ATT_MATCHER = "request-matcher-ref"; + private static final String ATT_REPOSITORY = "token-repository-ref"; private String csrfRepositoryRef; + private BeanDefinition csrfFilter; private String requestMatcherRef; @Override public BeanDefinition parse(Element element, ParserContext pc) { - boolean disabled = element != null - && "true".equals(element.getAttribute("disabled")); + boolean disabled = element != null && "true".equals(element.getAttribute("disabled")); if (disabled) { return null; } - boolean webmvcPresent = ClassUtils.isPresent(DISPATCHER_SERVLET_CLASS_NAME, - getClass().getClassLoader()); + boolean webmvcPresent = ClassUtils.isPresent(DISPATCHER_SERVLET_CLASS_NAME, getClass().getClassLoader()); if (webmvcPresent) { if (!pc.getRegistry().containsBeanDefinition(REQUEST_DATA_VALUE_PROCESSOR)) { - RootBeanDefinition beanDefinition = new RootBeanDefinition( - CsrfRequestDataValueProcessor.class); - BeanComponentDefinition componentDefinition = new BeanComponentDefinition( - beanDefinition, REQUEST_DATA_VALUE_PROCESSOR); + RootBeanDefinition beanDefinition = new RootBeanDefinition(CsrfRequestDataValueProcessor.class); + BeanComponentDefinition componentDefinition = new BeanComponentDefinition(beanDefinition, + REQUEST_DATA_VALUE_PROCESSOR); pc.registerBeanComponent(componentDefinition); } } @@ -97,19 +98,16 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser { if (!StringUtils.hasText(this.csrfRepositoryRef)) { - RootBeanDefinition csrfTokenRepository = new RootBeanDefinition( - HttpSessionCsrfTokenRepository.class); + RootBeanDefinition csrfTokenRepository = new RootBeanDefinition(HttpSessionCsrfTokenRepository.class); BeanDefinitionBuilder lazyTokenRepository = BeanDefinitionBuilder .rootBeanDefinition(LazyCsrfTokenRepository.class); lazyTokenRepository.addConstructorArgValue(csrfTokenRepository); - this.csrfRepositoryRef = pc.getReaderContext() - .generateBeanName(lazyTokenRepository.getBeanDefinition()); - pc.registerBeanComponent(new BeanComponentDefinition( - lazyTokenRepository.getBeanDefinition(), this.csrfRepositoryRef)); + this.csrfRepositoryRef = pc.getReaderContext().generateBeanName(lazyTokenRepository.getBeanDefinition()); + pc.registerBeanComponent( + new BeanComponentDefinition(lazyTokenRepository.getBeanDefinition(), this.csrfRepositoryRef)); } - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .rootBeanDefinition(CsrfFilter.class); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(CsrfFilter.class); builder.addConstructorArgReference(this.csrfRepositoryRef); if (StringUtils.hasText(this.requestMatcherRef)) { @@ -122,16 +120,13 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser { /** * Populate the AccessDeniedHandler on the {@link CsrfFilter} - * * @param invalidSessionStrategy the {@link InvalidSessionStrategy} to use * @param defaultDeniedHandler the {@link AccessDeniedHandler} to use */ - void initAccessDeniedHandler(BeanDefinition invalidSessionStrategy, - BeanMetadataElement defaultDeniedHandler) { - BeanMetadataElement accessDeniedHandler = createAccessDeniedHandler( - invalidSessionStrategy, defaultDeniedHandler); - this.csrfFilter.getPropertyValues().addPropertyValue("accessDeniedHandler", - accessDeniedHandler); + void initAccessDeniedHandler(BeanDefinition invalidSessionStrategy, BeanMetadataElement defaultDeniedHandler) { + BeanMetadataElement accessDeniedHandler = createAccessDeniedHandler(invalidSessionStrategy, + defaultDeniedHandler); + this.csrfFilter.getPropertyValues().addPropertyValue("accessDeniedHandler", accessDeniedHandler); } /** @@ -143,15 +138,12 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser { * {@link InvalidSessionAccessDeniedHandler} and the * {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)}. Otherwise, only * {@link #getDefaultAccessDeniedHandler(HttpSecurityBuilder)} is used. - * * @param invalidSessionStrategy the {@link InvalidSessionStrategy} to use * @param defaultDeniedHandler the {@link AccessDeniedHandler} to use - * * @return the {@link BeanMetadataElement} that is the {@link AccessDeniedHandler} to * populate on the {@link CsrfFilter} */ - private BeanMetadataElement createAccessDeniedHandler( - BeanDefinition invalidSessionStrategy, + private BeanMetadataElement createAccessDeniedHandler(BeanDefinition invalidSessionStrategy, BeanMetadataElement defaultDeniedHandler) { if (invalidSessionStrategy == null) { return defaultDeniedHandler; @@ -160,8 +152,7 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser { BeanDefinitionBuilder invalidSessionHandlerBldr = BeanDefinitionBuilder .rootBeanDefinition(InvalidSessionAccessDeniedHandler.class); invalidSessionHandlerBldr.addConstructorArgValue(invalidSessionStrategy); - handlers.put(MissingCsrfTokenException.class, - invalidSessionHandlerBldr.getBeanDefinition()); + handlers.put(MissingCsrfTokenException.class, invalidSessionHandlerBldr.getBeanDefinition()); BeanDefinitionBuilder deniedBldr = BeanDefinitionBuilder .rootBeanDefinition(DelegatingAccessDeniedHandler.class); @@ -190,29 +181,26 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser { BeanMetadataElement requestMatcher; if (StringUtils.hasText(this.requestMatcherRef)) { requestMatcher = new RuntimeBeanReference(this.requestMatcherRef); - } else { + } + else { requestMatcher = new RootBeanDefinition(DefaultRequiresCsrfMatcher.class); } - BeanDefinitionBuilder and = BeanDefinitionBuilder - .rootBeanDefinition(AndRequestMatcher.class); - BeanDefinitionBuilder negated = BeanDefinitionBuilder - .rootBeanDefinition(NegatedRequestMatcher.class); - BeanDefinitionBuilder or = BeanDefinitionBuilder - .rootBeanDefinition(OrRequestMatcher.class); + BeanDefinitionBuilder and = BeanDefinitionBuilder.rootBeanDefinition(AndRequestMatcher.class); + BeanDefinitionBuilder negated = BeanDefinitionBuilder.rootBeanDefinition(NegatedRequestMatcher.class); + BeanDefinitionBuilder or = BeanDefinitionBuilder.rootBeanDefinition(OrRequestMatcher.class); or.addConstructorArgValue(requestMatchers); negated.addConstructorArgValue(or.getBeanDefinition()); List ands = new ManagedList<>(); ands.add(requestMatcher); ands.add(negated.getBeanDefinition()); and.addConstructorArgValue(ands); - this.csrfFilter.getPropertyValues() - .add("requireCsrfProtectionMatcher", and.getBeanDefinition()); + this.csrfFilter.getPropertyValues().add("requireCsrfProtectionMatcher", and.getBeanDefinition()); } } private static final class DefaultRequiresCsrfMatcher implements RequestMatcher { - private final HashSet allowedMethods = new HashSet<>( - Arrays.asList("GET", "HEAD", "TRACE", "OPTIONS")); + + private final HashSet allowedMethods = new HashSet<>(Arrays.asList("GET", "HEAD", "TRACE", "OPTIONS")); /* * (non-Javadoc) @@ -225,5 +213,7 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser { public boolean matches(HttpServletRequest request) { return !this.allowedMethods.contains(request.getMethod()); } + } + } diff --git a/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java b/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java index ac4ec37ed3..c6a70e0886 100644 --- a/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java +++ b/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java @@ -44,6 +44,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.AnyRequestMatcher; public class DefaultFilterChainValidator implements FilterChainProxy.FilterChainValidator { + private final Log logger = LogFactory.getLog(getClass()); public void validate(FilterChainProxy fcp) { @@ -53,8 +54,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain } checkPathOrder(new ArrayList<>(fcp.getFilterChains())); - checkForDuplicateMatchers(new ArrayList<>( - fcp.getFilterChains())); + checkForDuplicateMatchers(new ArrayList<>(fcp.getFilterChains())); } private void checkPathOrder(List filterChains) { @@ -62,13 +62,11 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain Iterator chains = filterChains.iterator(); while (chains.hasNext()) { - RequestMatcher matcher = ((DefaultSecurityFilterChain) chains.next()) - .getRequestMatcher(); + RequestMatcher matcher = ((DefaultSecurityFilterChain) chains.next()).getRequestMatcher(); if (AnyRequestMatcher.INSTANCE.equals(matcher) && chains.hasNext()) { - throw new IllegalArgumentException( - "A universal match pattern ('/**') is defined " - + " before other patterns in the filter chain, causing them to be ignored. Please check the " - + "ordering in your namespace or FilterChainProxy bean configuration"); + throw new IllegalArgumentException("A universal match pattern ('/**') is defined " + + " before other patterns in the filter chain, causing them to be ignored. Please check the " + + "ordering in your namespace or FilterChainProxy bean configuration"); } } } @@ -76,18 +74,13 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain private void checkForDuplicateMatchers(List chains) { while (chains.size() > 1) { - DefaultSecurityFilterChain chain = (DefaultSecurityFilterChain) chains - .remove(0); + DefaultSecurityFilterChain chain = (DefaultSecurityFilterChain) chains.remove(0); for (SecurityFilterChain test : chains) { - if (chain.getRequestMatcher().equals( - ((DefaultSecurityFilterChain) test).getRequestMatcher())) { - throw new IllegalArgumentException( - "The FilterChainProxy contains two filter chains using the" - + " matcher " - + chain.getRequestMatcher() - + ". If you are using multiple namespace " - + "elements, you must use a 'pattern' attribute to define the request patterns to which they apply."); + if (chain.getRequestMatcher().equals(((DefaultSecurityFilterChain) test).getRequestMatcher())) { + throw new IllegalArgumentException("The FilterChainProxy contains two filter chains using the" + + " matcher " + chain.getRequestMatcher() + ". If you are using multiple namespace " + + "elements, you must use a 'pattern' attribute to define the request patterns to which they apply."); } } } @@ -126,8 +119,8 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain for (int j = i + 1; j < filters.size(); j++) { Filter f2 = filters.get(j); if (clazz.isAssignableFrom(f2.getClass())) { - logger.warn("Possible error: Filters at position " + i + " and " - + j + " are both " + "instances of " + clazz.getName()); + logger.warn("Possible error: Filters at position " + i + " and " + j + " are both " + + "instances of " + clazz.getName()); return; } } @@ -139,20 +132,15 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain * Checks for the common error of having a login page URL protected by the security * interceptor */ - private void checkLoginPageIsntProtected(FilterChainProxy fcp, - List filterStack) { - ExceptionTranslationFilter etf = getFilter(ExceptionTranslationFilter.class, - filterStack); + private void checkLoginPageIsntProtected(FilterChainProxy fcp, List filterStack) { + ExceptionTranslationFilter etf = getFilter(ExceptionTranslationFilter.class, filterStack); - if (etf == null - || !(etf.getAuthenticationEntryPoint() instanceof LoginUrlAuthenticationEntryPoint)) { + if (etf == null || !(etf.getAuthenticationEntryPoint() instanceof LoginUrlAuthenticationEntryPoint)) { return; } - String loginPage = ((LoginUrlAuthenticationEntryPoint) etf - .getAuthenticationEntryPoint()).getLoginFormUrl(); - logger.info("Checking whether login URL '" + loginPage - + "' is accessible with your configuration"); + String loginPage = ((LoginUrlAuthenticationEntryPoint) etf.getAuthenticationEntryPoint()).getLoginFormUrl(); + logger.info("Checking whether login URL '" + loginPage + "' is accessible with your configuration"); FilterInvocation loginRequest = new FilterInvocation(loginPage, "POST"); List filters = null; @@ -176,8 +164,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain return; } - FilterSecurityInterceptor fsi = getFilter(FilterSecurityInterceptor.class, - filters); + FilterSecurityInterceptor fsi = getFilter(FilterSecurityInterceptor.class, filters); FilterInvocationSecurityMetadataSource fids = fsi.getSecurityMetadataSource(); Collection attributes = fids.getAttributes(loginRequest); @@ -191,8 +178,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain return; } - AnonymousAuthenticationFilter anonPF = getFilter( - AnonymousAuthenticationFilter.class, filters); + AnonymousAuthenticationFilter anonPF = getFilter(AnonymousAuthenticationFilter.class, filters); if (anonPF == null) { logger.warn("The login page is being protected by the filter chain, but you don't appear to have" + " anonymous authentication enabled. This is almost certainly an error."); @@ -200,8 +186,8 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain } // Simulate an anonymous access with the supplied attributes. - AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", - anonPF.getPrincipal(), anonPF.getAuthorities()); + AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", anonPF.getPrincipal(), + anonPF.getAuthorities()); try { fsi.getAccessDecisionManager().decide(token, loginRequest, attributes); } diff --git a/config/src/main/java/org/springframework/security/config/http/FilterChainBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/FilterChainBeanDefinitionParser.java index ae5298b56e..cff4ded3ca 100644 --- a/config/src/main/java/org/springframework/security/config/http/FilterChainBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/FilterChainBeanDefinitionParser.java @@ -32,6 +32,7 @@ import java.util.*; * @author Luke Taylor */ public class FilterChainBeanDefinitionParser implements BeanDefinitionParser { + private static final String ATT_REQUEST_MATCHER_REF = "request-matcher-ref"; public BeanDefinition parse(Element elt, ParserContext pc) { @@ -40,8 +41,7 @@ public class FilterChainBeanDefinitionParser implements BeanDefinitionParser { String requestMatcher = elt.getAttribute(ATT_REQUEST_MATCHER_REF); String filters = elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS); - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .rootBeanDefinition(DefaultSecurityFilterChain.class); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DefaultSecurityFilterChain.class); if (StringUtils.hasText(path)) { Assert.isTrue(!StringUtils.hasText(requestMatcher), ""); @@ -57,8 +57,7 @@ public class FilterChainBeanDefinitionParser implements BeanDefinitionParser { } else { String[] filterBeanNames = StringUtils.tokenizeToStringArray(filters, ","); - ManagedList filterChain = new ManagedList<>( - filterBeanNames.length); + ManagedList filterChain = new ManagedList<>(filterBeanNames.length); for (String name : filterBeanNames) { filterChain.add(new RuntimeBeanReference(name)); @@ -69,4 +68,5 @@ public class FilterChainBeanDefinitionParser implements BeanDefinitionParser { return builder.getBeanDefinition(); } + } diff --git a/config/src/main/java/org/springframework/security/config/http/FilterChainMapBeanDefinitionDecorator.java b/config/src/main/java/org/springframework/security/config/http/FilterChainMapBeanDefinitionDecorator.java index 35a43022e4..a3cf26283d 100644 --- a/config/src/main/java/org/springframework/security/config/http/FilterChainMapBeanDefinitionDecorator.java +++ b/config/src/main/java/org/springframework/security/config/http/FilterChainMapBeanDefinitionDecorator.java @@ -40,8 +40,7 @@ import org.w3c.dom.Node; public class FilterChainMapBeanDefinitionDecorator implements BeanDefinitionDecorator { @SuppressWarnings("unchecked") - public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, - ParserContext parserContext) { + public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) { BeanDefinition filterChainProxy = holder.getBeanDefinition(); ManagedList securityFilterChains = new ManagedList<>(); @@ -49,37 +48,30 @@ public class FilterChainMapBeanDefinitionDecorator implements BeanDefinitionDeco MatcherType matcherType = MatcherType.fromElement(elt); - List filterChainElts = DomUtils.getChildElementsByTagName(elt, - Elements.FILTER_CHAIN); + List filterChainElts = DomUtils.getChildElementsByTagName(elt, Elements.FILTER_CHAIN); for (Element chain : filterChainElts) { - String path = chain - .getAttribute(HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN); - String filters = chain - .getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS); + String path = chain.getAttribute(HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN); + String filters = chain.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS); if (!StringUtils.hasText(path)) { parserContext.getReaderContext().error( - "The attribute '" - + HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN - + "' must not be empty", elt); + "The attribute '" + HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN + "' must not be empty", + elt); } if (!StringUtils.hasText(filters)) { parserContext.getReaderContext().error( - "The attribute '" + HttpSecurityBeanDefinitionParser.ATT_FILTERS - + "'must not be empty", elt); + "The attribute '" + HttpSecurityBeanDefinitionParser.ATT_FILTERS + "'must not be empty", elt); } BeanDefinition matcher = matcherType.createMatcher(parserContext, path, null); if (filters.equals(HttpSecurityBeanDefinitionParser.OPT_FILTERS_NONE)) { - securityFilterChains.add(createSecurityFilterChain(matcher, - new ManagedList(0))); + securityFilterChains.add(createSecurityFilterChain(matcher, new ManagedList(0))); } else { - String[] filterBeanNames = StringUtils - .tokenizeToStringArray(filters, ","); + String[] filterBeanNames = StringUtils.tokenizeToStringArray(filters, ","); ManagedList filterChain = new ManagedList(filterBeanNames.length); for (String name : filterBeanNames) { @@ -90,18 +82,16 @@ public class FilterChainMapBeanDefinitionDecorator implements BeanDefinitionDeco } } - filterChainProxy.getConstructorArgumentValues().addGenericArgumentValue( - securityFilterChains); + filterChainProxy.getConstructorArgumentValues().addGenericArgumentValue(securityFilterChains); return holder; } - private BeanDefinition createSecurityFilterChain(BeanDefinition matcher, - ManagedList filters) { - BeanDefinitionBuilder sfc = BeanDefinitionBuilder - .rootBeanDefinition(DefaultSecurityFilterChain.class); + private BeanDefinition createSecurityFilterChain(BeanDefinition matcher, ManagedList filters) { + BeanDefinitionBuilder sfc = BeanDefinitionBuilder.rootBeanDefinition(DefaultSecurityFilterChain.class); sfc.addConstructorArgValue(matcher); sfc.addConstructorArgValue(filters); return sfc.getBeanDefinition(); } + } diff --git a/config/src/main/java/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java b/config/src/main/java/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java index dde778d41d..b8373a83ee 100644 --- a/config/src/main/java/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java +++ b/config/src/main/java/org/springframework/security/config/http/FilterInvocationSecurityMetadataSourceParser.java @@ -48,44 +48,42 @@ import org.springframework.util.xml.DomUtils; * @author Luke Taylor */ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinitionParser { + private static final String ATT_USE_EXPRESSIONS = "use-expressions"; + private static final String ATT_HTTP_METHOD = "method"; + private static final String ATT_PATTERN = "pattern"; + private static final String ATT_ACCESS = "access"; + private static final String ATT_SERVLET_PATH = "servlet-path"; - private static final Log logger = LogFactory - .getLog(FilterInvocationSecurityMetadataSourceParser.class); + + private static final Log logger = LogFactory.getLog(FilterInvocationSecurityMetadataSourceParser.class); public BeanDefinition parse(Element element, ParserContext parserContext) { - List interceptUrls = DomUtils.getChildElementsByTagName(element, - Elements.INTERCEPT_URL); + List interceptUrls = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL); // Check for attributes that aren't allowed in this context for (Element elt : interceptUrls) { - if (StringUtils.hasLength(elt - .getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL))) { - parserContext.getReaderContext().error( - "The attribute '" - + HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL - + "' isn't allowed here.", elt); + if (StringUtils.hasLength(elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL))) { + parserContext.getReaderContext().error("The attribute '" + + HttpSecurityBeanDefinitionParser.ATT_REQUIRES_CHANNEL + "' isn't allowed here.", elt); } - if (StringUtils.hasLength(elt - .getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS))) { + if (StringUtils.hasLength(elt.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS))) { parserContext.getReaderContext().error( - "The attribute '" + HttpSecurityBeanDefinitionParser.ATT_FILTERS - + "' isn't allowed here.", elt); + "The attribute '" + HttpSecurityBeanDefinitionParser.ATT_FILTERS + "' isn't allowed here.", + elt); } if (StringUtils.hasLength(elt.getAttribute(ATT_SERVLET_PATH))) { - parserContext.getReaderContext().error( - "The attribute '" + ATT_SERVLET_PATH - + "' isn't allowed here.", elt); + parserContext.getReaderContext().error("The attribute '" + ATT_SERVLET_PATH + "' isn't allowed here.", + elt); } } - BeanDefinition mds = createSecurityMetadataSource(interceptUrls, false, element, - parserContext); + BeanDefinition mds = createSecurityMetadataSource(interceptUrls, false, element, parserContext); String id = element.getAttribute(AbstractBeanDefinitionParser.ID_ATTRIBUTE); @@ -97,8 +95,8 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit return mds; } - static RootBeanDefinition createSecurityMetadataSource(List interceptUrls, - boolean addAllAuth, Element httpElt, ParserContext pc) { + static RootBeanDefinition createSecurityMetadataSource(List interceptUrls, boolean addAllAuth, + Element httpElt, ParserContext pc) { MatcherType matcherType = MatcherType.fromElement(httpElt); boolean useExpressions = isUseExpressions(httpElt); @@ -107,14 +105,13 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit BeanDefinitionBuilder fidsBuilder; if (useExpressions) { - Element expressionHandlerElt = DomUtils.getChildElementByTagName(httpElt, - Elements.EXPRESSION_HANDLER); + Element expressionHandlerElt = DomUtils.getChildElementByTagName(httpElt, Elements.EXPRESSION_HANDLER); String expressionHandlerRef = expressionHandlerElt == null ? null : expressionHandlerElt.getAttribute("ref"); if (StringUtils.hasText(expressionHandlerRef)) { - logger.info("Using bean '" + expressionHandlerRef - + "' as web SecurityExpressionHandler implementation"); + logger.info( + "Using bean '" + expressionHandlerRef + "' as web SecurityExpressionHandler implementation"); } else { expressionHandlerRef = registerDefaultExpressionHandler(pc); @@ -126,8 +123,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit fidsBuilder.addConstructorArgReference(expressionHandlerRef); } else { - fidsBuilder = BeanDefinitionBuilder - .rootBeanDefinition(DefaultFilterInvocationSecurityMetadataSource.class); + fidsBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultFilterInvocationSecurityMetadataSource.class); fidsBuilder.addConstructorArgValue(requestToAttributesMap); } @@ -137,11 +133,10 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit } static String registerDefaultExpressionHandler(ParserContext pc) { - BeanDefinition expressionHandler = GrantedAuthorityDefaultsParserUtils.registerWithDefaultRolePrefix(pc, DefaultWebSecurityExpressionHandlerBeanFactory.class); - String expressionHandlerRef = pc.getReaderContext().generateBeanName( - expressionHandler); - pc.registerBeanComponent(new BeanComponentDefinition(expressionHandler, - expressionHandlerRef)); + BeanDefinition expressionHandler = GrantedAuthorityDefaultsParserUtils.registerWithDefaultRolePrefix(pc, + DefaultWebSecurityExpressionHandlerBeanFactory.class); + String expressionHandlerRef = pc.getReaderContext().generateBeanName(expressionHandler); + pc.registerBeanComponent(new BeanComponentDefinition(expressionHandler, expressionHandlerRef)); return expressionHandlerRef; } @@ -152,8 +147,8 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit } private static ManagedMap parseInterceptUrlsForFilterInvocationRequestMap( - MatcherType matcherType, List urlElts, boolean useExpressions, - boolean addAuthenticatedAll, ParserContext parserContext) { + MatcherType matcherType, List urlElts, boolean useExpressions, boolean addAuthenticatedAll, + ParserContext parserContext) { ManagedMap filterInvocationDefinitionMap = new ManagedMap<>(); @@ -168,8 +163,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit boolean hasMatcherRef = StringUtils.hasText(matcherRef); if (!hasMatcherRef && !StringUtils.hasText(path)) { - parserContext.getReaderContext().error( - "path attribute cannot be empty or null", urlElt); + parserContext.getReaderContext().error("path attribute cannot be empty or null", urlElt); } String method = urlElt.getAttribute(ATT_HTTP_METHOD); @@ -180,19 +174,19 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit String servletPath = urlElt.getAttribute(ATT_SERVLET_PATH); if (!StringUtils.hasText(servletPath)) { servletPath = null; - } else if (!MatcherType.mvc.equals(matcherType)) { + } + else if (!MatcherType.mvc.equals(matcherType)) { parserContext.getReaderContext().error( - ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'", urlElt); + ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'", + urlElt); } - BeanMetadataElement matcher = hasMatcherRef ? new RuntimeBeanReference(matcherRef) : matcherType.createMatcher(parserContext, path, - method, servletPath); - BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder - .rootBeanDefinition(SecurityConfig.class); + BeanMetadataElement matcher = hasMatcherRef ? new RuntimeBeanReference(matcherRef) + : matcherType.createMatcher(parserContext, path, method, servletPath); + BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder.rootBeanDefinition(SecurityConfig.class); if (useExpressions) { - logger.info("Creating access control expression attribute '" + access - + "' for " + path); + logger.info("Creating access control expression attribute '" + access + "' for " + path); // The single expression will be parsed later by the // ExpressionBasedFilterInvocationSecurityMetadataSource attributeBuilder.addConstructorArgValue(new String[] { access }); @@ -205,35 +199,34 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit } if (filterInvocationDefinitionMap.containsKey(matcher)) { - logger.warn("Duplicate URL defined: " + path - + ". The original attribute values will be overwritten"); + logger.warn("Duplicate URL defined: " + path + ". The original attribute values will be overwritten"); } - filterInvocationDefinitionMap.put(matcher, - attributeBuilder.getBeanDefinition()); + filterInvocationDefinitionMap.put(matcher, attributeBuilder.getBeanDefinition()); } if (addAuthenticatedAll && filterInvocationDefinitionMap.isEmpty()) { - BeanDefinition matcher = matcherType.createMatcher(parserContext, "/**", - null); - BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder - .rootBeanDefinition(SecurityConfig.class); + BeanDefinition matcher = matcherType.createMatcher(parserContext, "/**", null); + BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder.rootBeanDefinition(SecurityConfig.class); attributeBuilder.addConstructorArgValue(new String[] { "authenticated" }); attributeBuilder.setFactoryMethod("createList"); - filterInvocationDefinitionMap.put(matcher, - attributeBuilder.getBeanDefinition()); + filterInvocationDefinitionMap.put(matcher, attributeBuilder.getBeanDefinition()); } return filterInvocationDefinitionMap; } - static class DefaultWebSecurityExpressionHandlerBeanFactory extends GrantedAuthorityDefaultsParserUtils.AbstractGrantedAuthorityDefaultsBeanFactory { + static class DefaultWebSecurityExpressionHandlerBeanFactory + extends GrantedAuthorityDefaultsParserUtils.AbstractGrantedAuthorityDefaultsBeanFactory { + private DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler(); public DefaultWebSecurityExpressionHandler getBean() { handler.setDefaultRolePrefix(this.rolePrefix); return handler; } + } + } diff --git a/config/src/main/java/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java index 9bd44c7f7c..ffa9175348 100644 --- a/config/src/main/java/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/FormLoginBeanDefinitionParser.java @@ -35,45 +35,64 @@ import org.w3c.dom.Element; * @author Shazin Sadakath */ public class FormLoginBeanDefinitionParser { + protected final Log logger = LogFactory.getLog(getClass()); private static final String ATT_LOGIN_URL = "login-processing-url"; static final String ATT_LOGIN_PAGE = "login-page"; + private static final String DEF_LOGIN_PAGE = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL; private static final String ATT_FORM_LOGIN_TARGET_URL = "default-target-url"; + private static final String ATT_ALWAYS_USE_DEFAULT_TARGET_URL = "always-use-default-target"; + private static final String DEF_FORM_LOGIN_TARGET_URL = "/"; + private static final String ATT_USERNAME_PARAMETER = "username-parameter"; + private static final String ATT_PASSWORD_PARAMETER = "password-parameter"; private static final String ATT_FORM_LOGIN_AUTHENTICATION_FAILURE_URL = "authentication-failure-url"; + private static final String DEF_FORM_LOGIN_AUTHENTICATION_FAILURE_URL = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL + "?" + DefaultLoginPageGeneratingFilter.ERROR_PARAMETER_NAME; private static final String ATT_SUCCESS_HANDLER_REF = "authentication-success-handler-ref"; + private static final String ATT_FAILURE_HANDLER_REF = "authentication-failure-handler-ref"; + private static final String ATT_FORM_LOGIN_AUTHENTICATION_FAILURE_FORWARD_URL = "authentication-failure-forward-url"; + private static final String ATT_FORM_LOGIN_AUTHENTICATION_SUCCESS_FORWARD_URL = "authentication-success-forward-url"; private final String defaultLoginProcessingUrl; + private final String filterClassName; + private final BeanReference requestCache; + private final BeanReference sessionStrategy; + private final boolean allowSessionCreation; + private final BeanReference portMapper; + private final BeanReference portResolver; private RootBeanDefinition filterBean; + private RootBeanDefinition entryPointBean; + private String loginPage; + private String loginMethod; + private String loginProcessingUrl; - FormLoginBeanDefinitionParser(String defaultLoginProcessingUrl, String loginMethod, - String filterClassName, BeanReference requestCache, - BeanReference sessionStrategy, boolean allowSessionCreation, + FormLoginBeanDefinitionParser(String defaultLoginProcessingUrl, String loginMethod, String filterClassName, + BeanReference requestCache, BeanReference sessionStrategy, boolean allowSessionCreation, BeanReference portMapper, BeanReference portResolver) { this.defaultLoginProcessingUrl = defaultLoginProcessingUrl; this.loginMethod = loginMethod; @@ -107,15 +126,13 @@ public class FormLoginBeanDefinitionParser { WebConfigUtils.validateHttpRedirect(loginUrl, pc, source); defaultTargetUrl = elt.getAttribute(ATT_FORM_LOGIN_TARGET_URL); WebConfigUtils.validateHttpRedirect(defaultTargetUrl, pc, source); - authenticationFailureUrl = elt - .getAttribute(ATT_FORM_LOGIN_AUTHENTICATION_FAILURE_URL); + authenticationFailureUrl = elt.getAttribute(ATT_FORM_LOGIN_AUTHENTICATION_FAILURE_URL); WebConfigUtils.validateHttpRedirect(authenticationFailureUrl, pc, source); alwaysUseDefault = elt.getAttribute(ATT_ALWAYS_USE_DEFAULT_TARGET_URL); loginPage = elt.getAttribute(ATT_LOGIN_PAGE); successHandlerRef = elt.getAttribute(ATT_SUCCESS_HANDLER_REF); failureHandlerRef = elt.getAttribute(ATT_FAILURE_HANDLER_REF); - authDetailsSourceRef = elt - .getAttribute(AuthenticationConfigBuilder.ATT_AUTH_DETAILS_SOURCE_REF); + authDetailsSourceRef = elt.getAttribute(AuthenticationConfigBuilder.ATT_AUTH_DETAILS_SOURCE_REF); authenticationFailureForwardUrl = elt.getAttribute(ATT_FORM_LOGIN_AUTHENTICATION_FAILURE_FORWARD_URL); WebConfigUtils.validateHttpRedirect(authenticationFailureForwardUrl, pc, source); authenticationSuccessForwardUrl = elt.getAttribute(ATT_FORM_LOGIN_AUTHENTICATION_SUCCESS_FORWARD_URL); @@ -129,17 +146,15 @@ public class FormLoginBeanDefinitionParser { passwordParameter = elt.getAttribute(ATT_PASSWORD_PARAMETER); } - filterBean = createFilterBean(loginUrl, defaultTargetUrl, alwaysUseDefault, - loginPage, authenticationFailureUrl, successHandlerRef, - failureHandlerRef, authDetailsSourceRef, authenticationFailureForwardUrl, authenticationSuccessForwardUrl); + filterBean = createFilterBean(loginUrl, defaultTargetUrl, alwaysUseDefault, loginPage, authenticationFailureUrl, + successHandlerRef, failureHandlerRef, authDetailsSourceRef, authenticationFailureForwardUrl, + authenticationSuccessForwardUrl); if (StringUtils.hasText(usernameParameter)) { - filterBean.getPropertyValues().addPropertyValue("usernameParameter", - usernameParameter); + filterBean.getPropertyValues().addPropertyValue("usernameParameter", usernameParameter); } if (StringUtils.hasText(passwordParameter)) { - filterBean.getPropertyValues().addPropertyValue("passwordParameter", - passwordParameter); + filterBean.getPropertyValues().addPropertyValue("passwordParameter", passwordParameter); } filterBean.setSource(source); @@ -147,8 +162,7 @@ public class FormLoginBeanDefinitionParser { BeanDefinitionBuilder entryPointBuilder = BeanDefinitionBuilder .rootBeanDefinition(LoginUrlAuthenticationEntryPoint.class); entryPointBuilder.getRawBeanDefinition().setSource(source); - entryPointBuilder.addConstructorArgValue(loginPage != null ? loginPage - : DEF_LOGIN_PAGE); + entryPointBuilder.addConstructorArgValue(loginPage != null ? loginPage : DEF_LOGIN_PAGE); entryPointBuilder.addPropertyValue("portMapper", portMapper); entryPointBuilder.addPropertyValue("portResolver", portResolver); entryPointBean = (RootBeanDefinition) entryPointBuilder.getBeanDefinition(); @@ -156,13 +170,12 @@ public class FormLoginBeanDefinitionParser { return null; } - private RootBeanDefinition createFilterBean(String loginUrl, String defaultTargetUrl, - String alwaysUseDefault, String loginPage, String authenticationFailureUrl, - String successHandlerRef, String failureHandlerRef, - String authDetailsSourceRef, String authenticationFailureForwardUrl, String authenticationSuccessForwardUrl) { + private RootBeanDefinition createFilterBean(String loginUrl, String defaultTargetUrl, String alwaysUseDefault, + String loginPage, String authenticationFailureUrl, String successHandlerRef, String failureHandlerRef, + String authDetailsSourceRef, String authenticationFailureForwardUrl, + String authenticationSuccessForwardUrl) { - BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder - .rootBeanDefinition(filterClassName); + BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(filterClassName); if (!StringUtils.hasText(loginUrl)) { loginUrl = defaultLoginProcessingUrl; @@ -177,51 +190,47 @@ public class FormLoginBeanDefinitionParser { matcherBuilder.addConstructorArgValue("POST"); } - filterBuilder.addPropertyValue("requiresAuthenticationRequestMatcher", - matcherBuilder.getBeanDefinition()); + filterBuilder.addPropertyValue("requiresAuthenticationRequestMatcher", matcherBuilder.getBeanDefinition()); if (StringUtils.hasText(successHandlerRef)) { - filterBuilder.addPropertyReference("authenticationSuccessHandler", - successHandlerRef); - } else if (StringUtils.hasText(authenticationSuccessForwardUrl)) { + filterBuilder.addPropertyReference("authenticationSuccessHandler", successHandlerRef); + } + else if (StringUtils.hasText(authenticationSuccessForwardUrl)) { BeanDefinitionBuilder forwardSuccessHandler = BeanDefinitionBuilder .rootBeanDefinition(ForwardAuthenticationSuccessHandler.class); forwardSuccessHandler.addConstructorArgValue(authenticationSuccessForwardUrl); filterBuilder.addPropertyValue("authenticationSuccessHandler", forwardSuccessHandler.getBeanDefinition()); - } else { + } + else { BeanDefinitionBuilder successHandler = BeanDefinitionBuilder .rootBeanDefinition(SavedRequestAwareAuthenticationSuccessHandler.class); if ("true".equals(alwaysUseDefault)) { - successHandler - .addPropertyValue("alwaysUseDefaultTargetUrl", Boolean.TRUE); + successHandler.addPropertyValue("alwaysUseDefaultTargetUrl", Boolean.TRUE); } successHandler.addPropertyValue("requestCache", requestCache); - successHandler.addPropertyValue("defaultTargetUrl", StringUtils - .hasText(defaultTargetUrl) ? defaultTargetUrl - : DEF_FORM_LOGIN_TARGET_URL); - filterBuilder.addPropertyValue("authenticationSuccessHandler", - successHandler.getBeanDefinition()); + successHandler.addPropertyValue("defaultTargetUrl", + StringUtils.hasText(defaultTargetUrl) ? defaultTargetUrl : DEF_FORM_LOGIN_TARGET_URL); + filterBuilder.addPropertyValue("authenticationSuccessHandler", successHandler.getBeanDefinition()); } if (StringUtils.hasText(authDetailsSourceRef)) { - filterBuilder.addPropertyReference("authenticationDetailsSource", - authDetailsSourceRef); + filterBuilder.addPropertyReference("authenticationDetailsSource", authDetailsSourceRef); } if (sessionStrategy != null) { - filterBuilder.addPropertyValue("sessionAuthenticationStrategy", - sessionStrategy); + filterBuilder.addPropertyValue("sessionAuthenticationStrategy", sessionStrategy); } if (StringUtils.hasText(failureHandlerRef)) { - filterBuilder.addPropertyReference("authenticationFailureHandler", - failureHandlerRef); - } else if (StringUtils.hasText(authenticationFailureForwardUrl)) { + filterBuilder.addPropertyReference("authenticationFailureHandler", failureHandlerRef); + } + else if (StringUtils.hasText(authenticationFailureForwardUrl)) { BeanDefinitionBuilder forwardFailureHandler = BeanDefinitionBuilder .rootBeanDefinition(ForwardAuthenticationFailureHandler.class); forwardFailureHandler.addConstructorArgValue(authenticationFailureForwardUrl); filterBuilder.addPropertyValue("authenticationFailureHandler", forwardFailureHandler.getBeanDefinition()); - } else { + } + else { BeanDefinitionBuilder failureHandler = BeanDefinitionBuilder .rootBeanDefinition(SimpleUrlAuthenticationFailureHandler.class); if (!StringUtils.hasText(authenticationFailureUrl)) { @@ -233,11 +242,9 @@ public class FormLoginBeanDefinitionParser { authenticationFailureUrl = DEF_FORM_LOGIN_AUTHENTICATION_FAILURE_URL; } } - failureHandler - .addPropertyValue("defaultFailureUrl", authenticationFailureUrl); + failureHandler.addPropertyValue("defaultFailureUrl", authenticationFailureUrl); failureHandler.addPropertyValue("allowSessionCreation", allowSessionCreation); - filterBuilder.addPropertyValue("authenticationFailureHandler", - failureHandler.getBeanDefinition()); + filterBuilder.addPropertyValue("authenticationFailureHandler", failureHandler.getBeanDefinition()); } return (RootBeanDefinition) filterBuilder.getBeanDefinition(); @@ -258,4 +265,5 @@ public class FormLoginBeanDefinitionParser { String getLoginProcessingUrl() { return loginProcessingUrl; } + } diff --git a/config/src/main/java/org/springframework/security/config/http/GrantedAuthorityDefaultsParserUtils.java b/config/src/main/java/org/springframework/security/config/http/GrantedAuthorityDefaultsParserUtils.java index 39f1ae1e00..625b4a8c1f 100644 --- a/config/src/main/java/org/springframework/security/config/http/GrantedAuthorityDefaultsParserUtils.java +++ b/config/src/main/java/org/springframework/security/config/http/GrantedAuthorityDefaultsParserUtils.java @@ -29,8 +29,8 @@ import org.springframework.security.config.core.GrantedAuthorityDefaults; */ class GrantedAuthorityDefaultsParserUtils { - - static RootBeanDefinition registerWithDefaultRolePrefix(ParserContext pc, Class beanFactoryClass) { + static RootBeanDefinition registerWithDefaultRolePrefix(ParserContext pc, + Class beanFactoryClass) { RootBeanDefinition beanFactoryDefinition = new RootBeanDefinition(beanFactoryClass); String beanFactoryRef = pc.getReaderContext().generateBeanName(beanFactoryDefinition); pc.getRegistry().registerBeanDefinition(beanFactoryRef, beanFactoryDefinition); @@ -42,20 +42,25 @@ class GrantedAuthorityDefaultsParserUtils { } static abstract class AbstractGrantedAuthorityDefaultsBeanFactory implements ApplicationContextAware { + protected String rolePrefix = "ROLE_"; @Override - public final void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - String[] grantedAuthorityDefaultsBeanNames = applicationContext.getBeanNamesForType(GrantedAuthorityDefaults.class); + public final void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + String[] grantedAuthorityDefaultsBeanNames = applicationContext + .getBeanNamesForType(GrantedAuthorityDefaults.class); if (grantedAuthorityDefaultsBeanNames.length == 1) { - GrantedAuthorityDefaults grantedAuthorityDefaults = applicationContext.getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class); + GrantedAuthorityDefaults grantedAuthorityDefaults = applicationContext + .getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class); this.rolePrefix = grantedAuthorityDefaults.getRolePrefix(); } } abstract Object getBean(); + + } + + private GrantedAuthorityDefaultsParserUtils() { } - private GrantedAuthorityDefaultsParserUtils() {} } diff --git a/config/src/main/java/org/springframework/security/config/http/HandlerMappingIntrospectorFactoryBean.java b/config/src/main/java/org/springframework/security/config/http/HandlerMappingIntrospectorFactoryBean.java index 3518bf8d0b..d8f6a3c98c 100644 --- a/config/src/main/java/org/springframework/security/config/http/HandlerMappingIntrospectorFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/http/HandlerMappingIntrospectorFactoryBean.java @@ -31,15 +31,18 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector; * @author Rob Winch * @since 4.1.1 */ -class HandlerMappingIntrospectorFactoryBean implements FactoryBean, ApplicationContextAware { +class HandlerMappingIntrospectorFactoryBean + implements FactoryBean, ApplicationContextAware { + private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"; private ApplicationContext context; public HandlerMappingIntrospector getObject() { if (!this.context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) { - throw new NoSuchBeanDefinitionException(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, "A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME +" of type " + HandlerMappingIntrospector.class.getName() - + " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext."); + throw new NoSuchBeanDefinitionException(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, "A Bean named " + + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + " of type " + HandlerMappingIntrospector.class.getName() + + " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext."); } return this.context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector.class); } @@ -57,8 +60,7 @@ class HandlerMappingIntrospectorFactoryBean implements FactoryBean(); - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .rootBeanDefinition(HeaderWriterFilter.class); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(HeaderWriterFilter.class); - boolean disabled = element != null - && "true".equals(resolveAttribute(parserContext, element, "disabled")); + boolean disabled = element != null && "true".equals(resolveAttribute(parserContext, element, "disabled")); boolean defaultsDisabled = element != null && "true".equals(resolveAttribute(parserContext, element, "defaults-disabled")); @@ -126,11 +143,10 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { boolean noWriters = headerWriters.isEmpty(); if (disabled && !noWriters) { - parserContext - .getReaderContext() - .error("Cannot specify with child elements.", - element); - } else if (noWriters) { + parserContext.getReaderContext().error("Cannot specify with child elements.", + element); + } + else if (noWriters) { return null; } @@ -141,7 +157,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { /** * * Resolve the placeholder for a given attribute on a element. - * * @param pc * @param element * @param attributeName @@ -152,10 +167,9 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { } private void parseCacheControlElement(boolean addIfNotPresent, Element element) { - Element cacheControlElement = element == null ? null : DomUtils - .getChildElementByTagName(element, CACHE_CONTROL_ELEMENT); - boolean disabled = "true".equals(getAttribute(cacheControlElement, ATT_DISABLED, - "false")); + Element cacheControlElement = element == null ? null + : DomUtils.getChildElementByTagName(element, CACHE_CONTROL_ELEMENT); + boolean disabled = "true".equals(getAttribute(cacheControlElement, ATT_DISABLED, "false")); if (disabled) { return; } @@ -170,51 +184,42 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { headerWriters.add(headersWriter.getBeanDefinition()); } - private void parseHstsElement(boolean addIfNotPresent, Element element, - ParserContext context) { - Element hstsElement = element == null ? null : DomUtils.getChildElementByTagName( - element, HSTS_ELEMENT); + private void parseHstsElement(boolean addIfNotPresent, Element element, ParserContext context) { + Element hstsElement = element == null ? null : DomUtils.getChildElementByTagName(element, HSTS_ELEMENT); if (addIfNotPresent || hstsElement != null) { addHsts(addIfNotPresent, hstsElement, context); } } - private void addHsts(boolean addIfNotPresent, Element hstsElement, - ParserContext context) { - BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder - .genericBeanDefinition(HstsHeaderWriter.class); + private void addHsts(boolean addIfNotPresent, Element hstsElement, ParserContext context) { + BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder.genericBeanDefinition(HstsHeaderWriter.class); if (hstsElement != null) { - boolean disabled = "true".equals(getAttribute(hstsElement, ATT_DISABLED, - "false")); + boolean disabled = "true".equals(getAttribute(hstsElement, ATT_DISABLED, "false")); String includeSubDomains = hstsElement.getAttribute(ATT_INCLUDE_SUBDOMAINS); if (StringUtils.hasText(includeSubDomains)) { if (disabled) { - attrNotAllowed(context, ATT_INCLUDE_SUBDOMAINS, ATT_DISABLED, - hstsElement); + attrNotAllowed(context, ATT_INCLUDE_SUBDOMAINS, ATT_DISABLED, hstsElement); } headersWriter.addPropertyValue("includeSubDomains", includeSubDomains); } String maxAgeSeconds = hstsElement.getAttribute(ATT_MAX_AGE_SECONDS); if (StringUtils.hasText(maxAgeSeconds)) { if (disabled) { - attrNotAllowed(context, ATT_MAX_AGE_SECONDS, ATT_DISABLED, - hstsElement); + attrNotAllowed(context, ATT_MAX_AGE_SECONDS, ATT_DISABLED, hstsElement); } headersWriter.addPropertyValue("maxAgeInSeconds", maxAgeSeconds); } String requestMatcherRef = hstsElement.getAttribute(ATT_REQUEST_MATCHER_REF); if (StringUtils.hasText(requestMatcherRef)) { if (disabled) { - attrNotAllowed(context, ATT_REQUEST_MATCHER_REF, ATT_DISABLED, - hstsElement); + attrNotAllowed(context, ATT_REQUEST_MATCHER_REF, ATT_DISABLED, hstsElement); } headersWriter.addPropertyReference("requestMatcher", requestMatcherRef); } String preload = hstsElement.getAttribute(ATT_PRELOAD); if (StringUtils.hasText(preload)) { if (disabled) { - attrNotAllowed(context, ATT_PRELOAD, ATT_DISABLED, - hstsElement); + attrNotAllowed(context, ATT_PRELOAD, ATT_DISABLED, hstsElement); } headersWriter.addPropertyValue("preload", preload); } @@ -298,8 +303,8 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { } private void parseContentSecurityPolicyElement(boolean elementDisabled, Element element, ParserContext context) { - Element contentSecurityPolicyElement = (elementDisabled || element == null) ? null : DomUtils.getChildElementByTagName( - element, CONTENT_SECURITY_POLICY_ELEMENT); + Element contentSecurityPolicyElement = (elementDisabled || element == null) ? null + : DomUtils.getChildElementByTagName(element, CONTENT_SECURITY_POLICY_ELEMENT); if (contentSecurityPolicyElement != null) { addContentSecurityPolicy(contentSecurityPolicyElement, context); } @@ -311,9 +316,10 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { String policyDirectives = contentSecurityPolicyElement.getAttribute(ATT_POLICY_DIRECTIVES); if (!StringUtils.hasText(policyDirectives)) { - context.getReaderContext().error( - ATT_POLICY_DIRECTIVES + " requires a 'value' to be set.", contentSecurityPolicyElement); - } else { + context.getReaderContext().error(ATT_POLICY_DIRECTIVES + " requires a 'value' to be set.", + contentSecurityPolicyElement); + } + else { headersWriter.addConstructorArgValue(policyDirectives); } @@ -326,14 +332,16 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { } private void parseReferrerPolicyElement(Element element, ParserContext context) { - Element referrerPolicyElement = (element == null) ? null : DomUtils.getChildElementByTagName(element, REFERRER_POLICY_ELEMENT); + Element referrerPolicyElement = (element == null) ? null + : DomUtils.getChildElementByTagName(element, REFERRER_POLICY_ELEMENT); if (referrerPolicyElement != null) { addReferrerPolicy(referrerPolicyElement, context); } } private void addReferrerPolicy(Element referrerPolicyElement, ParserContext context) { - BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder.genericBeanDefinition(ReferrerPolicyHeaderWriter.class); + BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder + .genericBeanDefinition(ReferrerPolicyHeaderWriter.class); String policy = referrerPolicyElement.getAttribute(ATT_POLICY); if (StringUtils.hasLength(policy)) { @@ -354,11 +362,9 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder .genericBeanDefinition(FeaturePolicyHeaderWriter.class); - String policyDirectives = featurePolicyElement - .getAttribute(ATT_POLICY_DIRECTIVES); + String policyDirectives = featurePolicyElement.getAttribute(ATT_POLICY_DIRECTIVES); if (!StringUtils.hasText(policyDirectives)) { - context.getReaderContext().error( - ATT_POLICY_DIRECTIVES + " requires a 'value' to be set.", + context.getReaderContext().error(ATT_POLICY_DIRECTIVES + " requires a 'value' to be set.", featurePolicyElement); } else { @@ -368,15 +374,13 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { headerWriters.add(headersWriter.getBeanDefinition()); } - private void attrNotAllowed(ParserContext context, String attrName, - String otherAttrName, Element element) { - context.getReaderContext().error( - "Only one of '" + attrName + "' or '" + otherAttrName + "' can be set.", + private void attrNotAllowed(ParserContext context, String attrName, String otherAttrName, Element element) { + context.getReaderContext().error("Only one of '" + attrName + "' or '" + otherAttrName + "' can be set.", element); } private void parseHeaderElements(Element element) { - List headerElts = element == null ? Collections. emptyList() + List headerElts = element == null ? Collections.emptyList() : DomUtils.getChildElementsByTagName(element, GENERIC_HEADER_ELEMENT); for (Element headerElt : headerElts) { String headerFactoryRef = headerElt.getAttribute(ATT_REF); @@ -384,8 +388,7 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { headerWriters.add(new RuntimeBeanReference(headerFactoryRef)); } else { - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .genericBeanDefinition(StaticHeadersWriter.class); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(StaticHeadersWriter.class); builder.addConstructorArgValue(headerElt.getAttribute(ATT_NAME)); builder.addConstructorArgValue(headerElt.getAttribute(ATT_VALUE)); headerWriters.add(builder.getBeanDefinition()); @@ -394,10 +397,9 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { } private void parseContentTypeOptionsElement(boolean addIfNotPresent, Element element) { - Element contentTypeElt = element == null ? null : DomUtils - .getChildElementByTagName(element, CONTENT_TYPE_ELEMENT); - boolean disabled = "true".equals(getAttribute(contentTypeElt, ATT_DISABLED, - "false")); + Element contentTypeElt = element == null ? null + : DomUtils.getChildElementByTagName(element, CONTENT_TYPE_ELEMENT); + boolean disabled = "true".equals(getAttribute(contentTypeElt, ATT_DISABLED, "false")); if (disabled) { return; } @@ -412,17 +414,13 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { headerWriters.add(builder.getBeanDefinition()); } - private void parseFrameOptionsElement(boolean addIfNotPresent, Element element, - ParserContext parserContext) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .genericBeanDefinition(XFrameOptionsHeaderWriter.class); + private void parseFrameOptionsElement(boolean addIfNotPresent, Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(XFrameOptionsHeaderWriter.class); - Element frameElt = element == null ? null : DomUtils.getChildElementByTagName( - element, FRAME_OPTIONS_ELEMENT); + Element frameElt = element == null ? null : DomUtils.getChildElementByTagName(element, FRAME_OPTIONS_ELEMENT); if (frameElt != null) { String header = getAttribute(frameElt, ATT_POLICY, null); - boolean disabled = "true" - .equals(getAttribute(frameElt, ATT_DISABLED, "false")); + boolean disabled = "true".equals(getAttribute(frameElt, ATT_DISABLED, "false")); if (disabled && header != null) { this.attrNotAllowed(parserContext, ATT_DISABLED, ATT_POLICY, frameElt); @@ -436,8 +434,7 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { String strategy = getAttribute(frameElt, ATT_STRATEGY, null); if (StringUtils.hasText(strategy) && StringUtils.hasText(strategyRef)) { - parserContext.getReaderContext().error( - "Only one of 'strategy' or 'strategy-ref' can be set.", + parserContext.getReaderContext().error("Only one of 'strategy' or 'strategy-ref' can be set.", frameElt); } else if (strategyRef != null) { @@ -446,18 +443,15 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { else if (strategy != null) { String value = getAttribute(frameElt, ATT_VALUE, null); if (!StringUtils.hasText(value)) { - parserContext.getReaderContext().error( - "Strategy requires a 'value' to be set.", frameElt); + parserContext.getReaderContext().error("Strategy requires a 'value' to be set.", frameElt); } // static, whitelist, regexp if ("static".equals(strategy)) { try { - builder.addConstructorArgValue(new StaticAllowFromStrategy( - new URI(value))); + builder.addConstructorArgValue(new StaticAllowFromStrategy(new URI(value))); } catch (URISyntaxException e) { - parserContext.getReaderContext().error( - "'value' attribute doesn't represent a valid URI.", + parserContext.getReaderContext().error("'value' attribute doesn't represent a valid URI.", frameElt, e); } } @@ -466,26 +460,20 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { if ("whitelist".equals(strategy)) { allowFromStrategy = BeanDefinitionBuilder .rootBeanDefinition(WhiteListedAllowFromStrategy.class); - allowFromStrategy.addConstructorArgValue(StringUtils - .commaDelimitedListToSet(value)); + allowFromStrategy.addConstructorArgValue(StringUtils.commaDelimitedListToSet(value)); } else { - allowFromStrategy = BeanDefinitionBuilder - .rootBeanDefinition(RegExpAllowFromStrategy.class); + allowFromStrategy = BeanDefinitionBuilder.rootBeanDefinition(RegExpAllowFromStrategy.class); allowFromStrategy.addConstructorArgValue(value); } - String fromParameter = getAttribute(frameElt, ATT_FROM_PARAMETER, - "from"); - allowFromStrategy.addPropertyValue("allowFromParameterName", - fromParameter); - builder.addConstructorArgValue(allowFromStrategy - .getBeanDefinition()); + String fromParameter = getAttribute(frameElt, ATT_FROM_PARAMETER, "from"); + allowFromStrategy.addPropertyValue("allowFromParameterName", fromParameter); + builder.addConstructorArgValue(allowFromStrategy.getBeanDefinition()); } } else { - parserContext.getReaderContext() - .error("One of 'strategy' and 'strategy-ref' must be set.", - frameElt); + parserContext.getReaderContext().error("One of 'strategy' and 'strategy-ref' must be set.", + frameElt); } } else { @@ -502,12 +490,9 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { } } - private void parseXssElement(boolean addIfNotPresent, Element element, - ParserContext parserContext) { - Element xssElt = element == null ? null : DomUtils.getChildElementByTagName( - element, XSS_ELEMENT); - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .genericBeanDefinition(XXssProtectionHeaderWriter.class); + private void parseXssElement(boolean addIfNotPresent, Element element, ParserContext parserContext) { + Element xssElt = element == null ? null : DomUtils.getChildElementByTagName(element, XSS_ELEMENT); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(XXssProtectionHeaderWriter.class); if (xssElt != null) { boolean disabled = "true".equals(getAttribute(xssElt, ATT_DISABLED, "false")); @@ -548,4 +533,5 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser { return defaultValue; } } + } diff --git a/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java b/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java index 2711ebdb9f..c6b14f77cf 100644 --- a/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java +++ b/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java @@ -101,68 +101,100 @@ import static org.springframework.security.config.http.SecurityFilters.WEB_ASYNC * @since 3.0 */ class HttpConfigurationBuilder { + private static final String ATT_CREATE_SESSION = "create-session"; private static final String ATT_SESSION_FIXATION_PROTECTION = "session-fixation-protection"; + private static final String OPT_SESSION_FIXATION_NO_PROTECTION = "none"; + private static final String OPT_SESSION_FIXATION_MIGRATE_SESSION = "migrateSession"; + private static final String OPT_CHANGE_SESSION_ID = "changeSessionId"; private static final String ATT_INVALID_SESSION_URL = "invalid-session-url"; + private static final String ATT_SESSION_AUTH_STRATEGY_REF = "session-authentication-strategy-ref"; + private static final String ATT_SESSION_AUTH_ERROR_URL = "session-authentication-error-url"; + private static final String ATT_SECURITY_CONTEXT_REPOSITORY = "security-context-repository-ref"; + private static final String ATT_INVALID_SESSION_STRATEGY_REF = "invalid-session-strategy-ref"; + private static final String ATT_DISABLE_URL_REWRITING = "disable-url-rewriting"; private static final String ATT_ACCESS_MGR = "access-decision-manager-ref"; + private static final String ATT_ONCE_PER_REQUEST = "once-per-request"; private static final String ATT_REF = "ref"; private final Element httpElt; + private final ParserContext pc; + private final SessionCreationPolicy sessionPolicy; + private final List interceptUrls; + private final MatcherType matcherType; private BeanDefinition cpf; + private BeanDefinition securityContextPersistenceFilter; + private BeanReference contextRepoRef; + private BeanReference sessionRegistryRef; + private BeanDefinition concurrentSessionFilter; + private BeanDefinition webAsyncManagerFilter; + private BeanDefinition requestCacheAwareFilter; + private BeanReference sessionStrategyRef; + private RootBeanDefinition sfpf; + private BeanDefinition servApiFilter; + private BeanDefinition jaasApiFilter; + private final BeanReference portMapper; + private final BeanReference portResolver; + private BeanReference fsi; + private BeanReference requestCache; + private BeanDefinition addHeadersFilter; + private BeanMetadataElement corsFilter; + private BeanDefinition csrfFilter; + private BeanMetadataElement csrfLogoutHandler; + private BeanMetadataElement csrfAuthStrategy; private CsrfBeanDefinitionParser csrfParser; private BeanDefinition invalidSession; + private boolean addAllAuth; - HttpConfigurationBuilder(Element element, boolean addAllAuth, - ParserContext pc, BeanReference portMapper, BeanReference portResolver, - BeanReference authenticationManager) { + HttpConfigurationBuilder(Element element, boolean addAllAuth, ParserContext pc, BeanReference portMapper, + BeanReference portResolver, BeanReference authenticationManager) { this.httpElt = element; this.addAllAuth = addAllAuth; this.pc = pc; this.portMapper = portMapper; this.portResolver = portResolver; this.matcherType = MatcherType.fromElement(element); - interceptUrls = DomUtils.getChildElementsByTagName(element, - Elements.INTERCEPT_URL); + interceptUrls = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL); for (Element urlElt : interceptUrls) { if (StringUtils.hasText(urlElt.getAttribute(ATT_FILTERS))) { @@ -209,16 +241,15 @@ class HttpConfigurationBuilder { return SessionCreationPolicy.STATELESS; } - throw new IllegalStateException("Cannot convert " + createSession + " to " - + SessionCreationPolicy.class.getName()); + throw new IllegalStateException( + "Cannot convert " + createSession + " to " + SessionCreationPolicy.class.getName()); } @SuppressWarnings("rawtypes") void setLogoutHandlers(ManagedList logoutHandlers) { if (logoutHandlers != null) { if (concurrentSessionFilter != null) { - concurrentSessionFilter.getPropertyValues().add("logoutHandlers", - logoutHandlers); + concurrentSessionFilter.getPropertyValues().add("logoutHandlers", logoutHandlers); } if (servApiFilter != null) { servApiFilter.getPropertyValues().add("logoutHandlers", logoutHandlers); @@ -250,8 +281,7 @@ class HttpConfigurationBuilder { } private void createSecurityContextPersistenceFilter() { - BeanDefinitionBuilder scpf = BeanDefinitionBuilder - .rootBeanDefinition(SecurityContextPersistenceFilter.class); + BeanDefinitionBuilder scpf = BeanDefinitionBuilder.rootBeanDefinition(SecurityContextPersistenceFilter.class); String repoRef = httpElt.getAttribute(ATT_SECURITY_CONTEXT_REPOSITORY); String disableUrlRewriting = httpElt.getAttribute(ATT_DISABLE_URL_REWRITING); @@ -267,12 +297,10 @@ class HttpConfigurationBuilder { else { BeanDefinitionBuilder contextRepo; if (sessionPolicy == SessionCreationPolicy.STATELESS) { - contextRepo = BeanDefinitionBuilder - .rootBeanDefinition(NullSecurityContextRepository.class); + contextRepo = BeanDefinitionBuilder.rootBeanDefinition(NullSecurityContextRepository.class); } else { - contextRepo = BeanDefinitionBuilder - .rootBeanDefinition(HttpSessionSecurityContextRepository.class); + contextRepo = BeanDefinitionBuilder.rootBeanDefinition(HttpSessionSecurityContextRepository.class); switch (sessionPolicy) { case ALWAYS: contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE); @@ -304,8 +332,7 @@ class HttpConfigurationBuilder { } private void createSessionManagementFilters() { - Element sessionMgmtElt = DomUtils.getChildElementByTagName(httpElt, - Elements.SESSION_MANAGEMENT); + Element sessionMgmtElt = DomUtils.getChildElementByTagName(httpElt, Elements.SESSION_MANAGEMENT); Element sessionCtrlElt = null; String sessionFixationAttribute = null; @@ -317,49 +344,42 @@ class HttpConfigurationBuilder { boolean sessionControlEnabled = false; if (sessionMgmtElt != null) { if (sessionPolicy == SessionCreationPolicy.STATELESS) { - pc.getReaderContext().error( - Elements.SESSION_MANAGEMENT + " cannot be used" - + " in combination with " + ATT_CREATE_SESSION + "='" - + SessionCreationPolicy.STATELESS + "'", - pc.extractSource(sessionMgmtElt)); + pc.getReaderContext() + .error(Elements.SESSION_MANAGEMENT + " cannot be used" + " in combination with " + + ATT_CREATE_SESSION + "='" + SessionCreationPolicy.STATELESS + "'", + pc.extractSource(sessionMgmtElt)); } - sessionFixationAttribute = sessionMgmtElt - .getAttribute(ATT_SESSION_FIXATION_PROTECTION); + sessionFixationAttribute = sessionMgmtElt.getAttribute(ATT_SESSION_FIXATION_PROTECTION); invalidSessionUrl = sessionMgmtElt.getAttribute(ATT_INVALID_SESSION_URL); invalidSessionStrategyRef = sessionMgmtElt.getAttribute(ATT_INVALID_SESSION_STRATEGY_REF); - sessionAuthStratRef = sessionMgmtElt - .getAttribute(ATT_SESSION_AUTH_STRATEGY_REF); + sessionAuthStratRef = sessionMgmtElt.getAttribute(ATT_SESSION_AUTH_STRATEGY_REF); errorUrl = sessionMgmtElt.getAttribute(ATT_SESSION_AUTH_ERROR_URL); - sessionCtrlElt = DomUtils.getChildElementByTagName(sessionMgmtElt, - Elements.CONCURRENT_SESSIONS); + sessionCtrlElt = DomUtils.getChildElementByTagName(sessionMgmtElt, Elements.CONCURRENT_SESSIONS); sessionControlEnabled = sessionCtrlElt != null; if (StringUtils.hasText(invalidSessionUrl) && StringUtils.hasText(invalidSessionStrategyRef)) { - pc.getReaderContext().error(ATT_INVALID_SESSION_URL + " attribute cannot be used in combination with" + - " the " + ATT_INVALID_SESSION_STRATEGY_REF + " attribute.", sessionMgmtElt); + pc.getReaderContext().error(ATT_INVALID_SESSION_URL + " attribute cannot be used in combination with" + + " the " + ATT_INVALID_SESSION_STRATEGY_REF + " attribute.", sessionMgmtElt); } if (sessionControlEnabled) { if (StringUtils.hasText(sessionAuthStratRef)) { - pc.getReaderContext().error( - ATT_SESSION_AUTH_STRATEGY_REF + " attribute cannot be used" - + " in combination with <" - + Elements.CONCURRENT_SESSIONS + ">", - pc.extractSource(sessionCtrlElt)); + pc.getReaderContext() + .error(ATT_SESSION_AUTH_STRATEGY_REF + " attribute cannot be used" + + " in combination with <" + Elements.CONCURRENT_SESSIONS + ">", + pc.extractSource(sessionCtrlElt)); } createConcurrencyControlFilterAndSessionRegistry(sessionCtrlElt); } } if (!StringUtils.hasText(sessionFixationAttribute)) { - sessionFixationAttribute = OPT_CHANGE_SESSION_ID; + sessionFixationAttribute = OPT_CHANGE_SESSION_ID; } else if (StringUtils.hasText(sessionAuthStratRef)) { - pc.getReaderContext().error( - ATT_SESSION_FIXATION_PROTECTION + " attribute cannot be used" - + " in combination with " + ATT_SESSION_AUTH_STRATEGY_REF, - pc.extractSource(sessionMgmtElt)); + pc.getReaderContext().error(ATT_SESSION_FIXATION_PROTECTION + " attribute cannot be used" + + " in combination with " + ATT_SESSION_AUTH_STRATEGY_REF, pc.extractSource(sessionMgmtElt)); } if (sessionPolicy == SessionCreationPolicy.STATELESS) { @@ -388,21 +408,17 @@ class HttpConfigurationBuilder { String maxSessions = sessionCtrlElt.getAttribute("max-sessions"); if (StringUtils.hasText(maxSessions)) { - concurrentSessionStrategy - .addPropertyValue("maximumSessions", maxSessions); + concurrentSessionStrategy.addPropertyValue("maximumSessions", maxSessions); } - String exceptionIfMaximumExceeded = sessionCtrlElt - .getAttribute("error-if-maximum-exceeded"); + String exceptionIfMaximumExceeded = sessionCtrlElt.getAttribute("error-if-maximum-exceeded"); if (StringUtils.hasText(exceptionIfMaximumExceeded)) { - concurrentSessionStrategy.addPropertyValue("exceptionIfMaximumExceeded", - exceptionIfMaximumExceeded); + concurrentSessionStrategy.addPropertyValue("exceptionIfMaximumExceeded", exceptionIfMaximumExceeded); } delegateSessionStrategies.add(concurrentSessionStrategy.getBeanDefinition()); } - boolean useChangeSessionId = OPT_CHANGE_SESSION_ID - .equals(sessionFixationAttribute); + boolean useChangeSessionId = OPT_CHANGE_SESSION_ID.equals(sessionFixationAttribute); if (sessionFixationProtectionRequired || StringUtils.hasText(invalidSessionUrl)) { if (useChangeSessionId) { sessionFixationStrategy = BeanDefinitionBuilder @@ -433,23 +449,18 @@ class HttpConfigurationBuilder { BeanDefinitionBuilder sessionMgmtFilter = BeanDefinitionBuilder .rootBeanDefinition(SessionManagementFilter.class); - RootBeanDefinition failureHandler = new RootBeanDefinition( - SimpleUrlAuthenticationFailureHandler.class); + RootBeanDefinition failureHandler = new RootBeanDefinition(SimpleUrlAuthenticationFailureHandler.class); if (StringUtils.hasText(errorUrl)) { - failureHandler.getPropertyValues().addPropertyValue("defaultFailureUrl", - errorUrl); + failureHandler.getPropertyValues().addPropertyValue("defaultFailureUrl", errorUrl); } - sessionMgmtFilter - .addPropertyValue("authenticationFailureHandler", failureHandler); + sessionMgmtFilter.addPropertyValue("authenticationFailureHandler", failureHandler); sessionMgmtFilter.addConstructorArgValue(contextRepoRef); - if (!StringUtils.hasText(sessionAuthStratRef) && sessionFixationStrategy != null - && !useChangeSessionId) { + if (!StringUtils.hasText(sessionAuthStratRef) && sessionFixationStrategy != null && !useChangeSessionId) { if (sessionFixationProtectionRequired) { sessionFixationStrategy.addPropertyValue("migrateSessionAttributes", - sessionFixationAttribute - .equals(OPT_SESSION_FIXATION_MIGRATE_SESSION)); + sessionFixationAttribute.equals(OPT_SESSION_FIXATION_MIGRATE_SESSION)); } } @@ -459,20 +470,18 @@ class HttpConfigurationBuilder { BeanDefinition strategyBean = sessionStrategy.getBeanDefinition(); sessionStrategy.addConstructorArgValue(delegateSessionStrategies); sessionAuthStratRef = pc.getReaderContext().generateBeanName(strategyBean); - pc.registerBeanComponent(new BeanComponentDefinition(strategyBean, - sessionAuthStratRef)); + pc.registerBeanComponent(new BeanComponentDefinition(strategyBean, sessionAuthStratRef)); } - - if (StringUtils.hasText(invalidSessionUrl)) { BeanDefinitionBuilder invalidSessionBldr = BeanDefinitionBuilder .rootBeanDefinition(SimpleRedirectInvalidSessionStrategy.class); invalidSessionBldr.addConstructorArgValue(invalidSessionUrl); invalidSession = invalidSessionBldr.getBeanDefinition(); sessionMgmtFilter.addPropertyValue("invalidSessionStrategy", invalidSession); - } else if (StringUtils.hasText(invalidSessionStrategyRef)) { + } + else if (StringUtils.hasText(invalidSessionStrategyRef)) { sessionMgmtFilter.addPropertyReference("invalidSessionStrategy", invalidSessionStrategyRef); } @@ -488,8 +497,8 @@ class HttpConfigurationBuilder { final String ATT_SESSION_REGISTRY_ALIAS = "session-registry-alias"; final String ATT_SESSION_REGISTRY_REF = "session-registry-ref"; - CompositeComponentDefinition compositeDef = new CompositeComponentDefinition( - element.getTagName(), pc.extractSource(element)); + CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), + pc.extractSource(element)); pc.pushContainingComponent(compositeDef); BeanDefinitionRegistry beanRegistry = pc.getRegistry(); @@ -498,12 +507,9 @@ class HttpConfigurationBuilder { if (!StringUtils.hasText(sessionRegistryId)) { // Register an internal SessionRegistryImpl if no external reference supplied. - RootBeanDefinition sessionRegistry = new RootBeanDefinition( - SessionRegistryImpl.class); - sessionRegistryId = pc.getReaderContext().registerWithGeneratedName( - sessionRegistry); - pc.registerComponent(new BeanComponentDefinition(sessionRegistry, - sessionRegistryId)); + RootBeanDefinition sessionRegistry = new RootBeanDefinition(SessionRegistryImpl.class); + sessionRegistryId = pc.getReaderContext().registerWithGeneratedName(sessionRegistry); + pc.registerComponent(new BeanComponentDefinition(sessionRegistry, sessionRegistryId)); } String registryAlias = element.getAttribute(ATT_SESSION_REGISTRY_ALIAS); @@ -511,8 +517,7 @@ class HttpConfigurationBuilder { beanRegistry.registerAlias(sessionRegistryId, registryAlias); } - BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder - .rootBeanDefinition(ConcurrentSessionFilter.class); + BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(ConcurrentSessionFilter.class); filterBuilder.addConstructorArgReference(sessionRegistryId); Object source = pc.extractSource(element); @@ -523,8 +528,9 @@ class HttpConfigurationBuilder { String expiredSessionStrategyRef = element.getAttribute(ATT_EXPIRED_SESSION_STRATEGY_REF); if (StringUtils.hasText(expiryUrl) && StringUtils.hasText(expiredSessionStrategyRef)) { - pc.getReaderContext().error("Cannot use 'expired-url' attribute and 'expired-session-strategy-ref'" + - " attribute together.", source); + pc.getReaderContext().error( + "Cannot use 'expired-url' attribute and 'expired-session-strategy-ref'" + " attribute together.", + source); } if (StringUtils.hasText(expiryUrl)) { @@ -532,7 +538,8 @@ class HttpConfigurationBuilder { .rootBeanDefinition(SimpleRedirectSessionInformationExpiredStrategy.class); expiredSessionBldr.addConstructorArgValue(expiryUrl); filterBuilder.addConstructorArgValue(expiredSessionBldr.getBeanDefinition()); - } else if (StringUtils.hasText(expiredSessionStrategyRef)) { + } + else if (StringUtils.hasText(expiredSessionStrategyRef)) { filterBuilder.addConstructorArgReference(expiredSessionStrategyRef); } @@ -545,8 +552,7 @@ class HttpConfigurationBuilder { private void createWebAsyncManagerFilter() { boolean asyncSupported = ClassUtils.hasMethod(ServletRequest.class, "startAsync"); if (asyncSupported) { - webAsyncManagerFilter = new RootBeanDefinition( - WebAsyncManagerIntegrationFilter.class); + webAsyncManagerFilter = new RootBeanDefinition(WebAsyncManagerIntegrationFilter.class); } } @@ -561,9 +567,9 @@ class HttpConfigurationBuilder { } if ("true".equals(provideServletApi)) { - servApiFilter = GrantedAuthorityDefaultsParserUtils.registerWithDefaultRolePrefix(pc, SecurityContextHolderAwareRequestFilterBeanFactory.class); - servApiFilter.getPropertyValues().add("authenticationManager", - authenticationManager); + servApiFilter = GrantedAuthorityDefaultsParserUtils.registerWithDefaultRolePrefix(pc, + SecurityContextHolderAwareRequestFilterBeanFactory.class); + servApiFilter.getPropertyValues().add("authenticationManager", authenticationManager); } } @@ -589,8 +595,7 @@ class HttpConfigurationBuilder { return; } - RootBeanDefinition channelFilter = new RootBeanDefinition( - ChannelProcessingFilter.class); + RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class); BeanDefinitionBuilder metadataSourceBldr = BeanDefinitionBuilder .rootBeanDefinition(DefaultFilterInvocationSecurityMetadataSource.class); metadataSourceBldr.addConstructorArgValue(channelRequestMap); @@ -599,36 +604,25 @@ class HttpConfigurationBuilder { channelFilter.getPropertyValues().addPropertyValue("securityMetadataSource", metadataSourceBldr.getBeanDefinition()); - RootBeanDefinition channelDecisionManager = new RootBeanDefinition( - ChannelDecisionManagerImpl.class); - ManagedList channelProcessors = new ManagedList<>( - 3); - RootBeanDefinition secureChannelProcessor = new RootBeanDefinition( - SecureChannelProcessor.class); - RootBeanDefinition retryWithHttp = new RootBeanDefinition( - RetryWithHttpEntryPoint.class); - RootBeanDefinition retryWithHttps = new RootBeanDefinition( - RetryWithHttpsEntryPoint.class); + RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class); + ManagedList channelProcessors = new ManagedList<>(3); + RootBeanDefinition secureChannelProcessor = new RootBeanDefinition(SecureChannelProcessor.class); + RootBeanDefinition retryWithHttp = new RootBeanDefinition(RetryWithHttpEntryPoint.class); + RootBeanDefinition retryWithHttps = new RootBeanDefinition(RetryWithHttpsEntryPoint.class); retryWithHttp.getPropertyValues().addPropertyValue("portMapper", portMapper); retryWithHttp.getPropertyValues().addPropertyValue("portResolver", portResolver); retryWithHttps.getPropertyValues().addPropertyValue("portMapper", portMapper); retryWithHttps.getPropertyValues().addPropertyValue("portResolver", portResolver); - secureChannelProcessor.getPropertyValues().addPropertyValue("entryPoint", - retryWithHttps); - RootBeanDefinition inSecureChannelProcessor = new RootBeanDefinition( - InsecureChannelProcessor.class); - inSecureChannelProcessor.getPropertyValues().addPropertyValue("entryPoint", - retryWithHttp); + secureChannelProcessor.getPropertyValues().addPropertyValue("entryPoint", retryWithHttps); + RootBeanDefinition inSecureChannelProcessor = new RootBeanDefinition(InsecureChannelProcessor.class); + inSecureChannelProcessor.getPropertyValues().addPropertyValue("entryPoint", retryWithHttp); channelProcessors.add(secureChannelProcessor); channelProcessors.add(inSecureChannelProcessor); - channelDecisionManager.getPropertyValues().addPropertyValue("channelProcessors", - channelProcessors); + channelDecisionManager.getPropertyValues().addPropertyValue("channelProcessors", channelProcessors); - String id = pc.getReaderContext().registerWithGeneratedName( - channelDecisionManager); - channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager", - new RuntimeBeanReference(id)); + String id = pc.getReaderContext().registerWithGeneratedName(channelDecisionManager); + channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager", new RuntimeBeanReference(id)); cpf = channelFilter; } @@ -648,19 +642,17 @@ class HttpConfigurationBuilder { boolean hasMatcherRef = StringUtils.hasText(matcherRef); if (!hasMatcherRef && !StringUtils.hasText(path)) { - pc.getReaderContext().error("pattern attribute cannot be empty or null", - urlElt); + pc.getReaderContext().error("pattern attribute cannot be empty or null", urlElt); } String requiredChannel = urlElt.getAttribute(ATT_REQUIRES_CHANNEL); if (StringUtils.hasText(requiredChannel)) { - BeanMetadataElement matcher = hasMatcherRef ? new RuntimeBeanReference(matcherRef) : matcherType.createMatcher(pc, path, method); + BeanMetadataElement matcher = hasMatcherRef ? new RuntimeBeanReference(matcherRef) + : matcherType.createMatcher(pc, path, method); - RootBeanDefinition channelAttributes = new RootBeanDefinition( - ChannelAttributeFactory.class); - channelAttributes.getConstructorArgumentValues().addGenericArgumentValue( - requiredChannel); + RootBeanDefinition channelAttributes = new RootBeanDefinition(ChannelAttributeFactory.class); + channelAttributes.getConstructorArgumentValues().addGenericArgumentValue(requiredChannel); channelAttributes.setFactoryMethodName("createChannelAttributes"); channelRequestMap.put(matcher, channelAttributes); @@ -671,8 +663,7 @@ class HttpConfigurationBuilder { } private void createRequestCacheFilter() { - Element requestCacheElt = DomUtils.getChildElementByTagName(httpElt, - Elements.REQUEST_CACHE); + Element requestCacheElt = DomUtils.getChildElementByTagName(httpElt, Elements.REQUEST_CACHE); if (requestCacheElt != null) { requestCache = new RuntimeBeanReference(requestCacheElt.getAttribute(ATT_REF)); @@ -681,12 +672,10 @@ class HttpConfigurationBuilder { BeanDefinitionBuilder requestCacheBldr; if (sessionPolicy == SessionCreationPolicy.STATELESS) { - requestCacheBldr = BeanDefinitionBuilder - .rootBeanDefinition(NullRequestCache.class); + requestCacheBldr = BeanDefinitionBuilder.rootBeanDefinition(NullRequestCache.class); } else { - requestCacheBldr = BeanDefinitionBuilder - .rootBeanDefinition(HttpSessionRequestCache.class); + requestCacheBldr = BeanDefinitionBuilder.rootBeanDefinition(HttpSessionRequestCache.class); requestCacheBldr.addPropertyValue("createSessionAllowed", sessionPolicy == SessionCreationPolicy.IF_REQUIRED); requestCacheBldr.addPropertyValue("portResolver", portResolver); @@ -695,8 +684,7 @@ class HttpConfigurationBuilder { .rootBeanDefinition(AntPathRequestMatcher.class); requestCacheMatcherBldr.addConstructorArgValue("/**"); requestCacheMatcherBldr.addConstructorArgValue("GET"); - requestCacheBldr.addPropertyValue("requestMatcher", - requestCacheMatcherBldr.getBeanDefinition()); + requestCacheBldr.addPropertyValue("requestMatcher", requestCacheMatcherBldr.getBeanDefinition()); } } @@ -708,13 +696,11 @@ class HttpConfigurationBuilder { } requestCacheAwareFilter = new RootBeanDefinition(RequestCacheAwareFilter.class); - requestCacheAwareFilter.getConstructorArgumentValues().addGenericArgumentValue( - requestCache); + requestCacheAwareFilter.getConstructorArgumentValues().addGenericArgumentValue(requestCache); } private void createFilterSecurityInterceptor(BeanReference authManager) { - boolean useExpressions = FilterInvocationSecurityMetadataSourceParser - .isUseExpressions(httpElt); + boolean useExpressions = FilterInvocationSecurityMetadataSourceParser.isUseExpressions(httpElt); RootBeanDefinition securityMds = FilterInvocationSecurityMetadataSourceParser .createSecurityMetadataSource(interceptUrls, addAllAuth, httpElt, pc); @@ -722,11 +708,9 @@ class HttpConfigurationBuilder { ManagedList voters = new ManagedList<>(2); if (useExpressions) { - BeanDefinitionBuilder expressionVoter = BeanDefinitionBuilder - .rootBeanDefinition(WebExpressionVoter.class); + BeanDefinitionBuilder expressionVoter = BeanDefinitionBuilder.rootBeanDefinition(WebExpressionVoter.class); // Read the expression handler from the FISMS - RuntimeBeanReference expressionHandler = (RuntimeBeanReference) securityMds - .getConstructorArgumentValues() + RuntimeBeanReference expressionHandler = (RuntimeBeanReference) securityMds.getConstructorArgumentValues() .getArgumentValue(1, RuntimeBeanReference.class).getValue(); expressionVoter.addPropertyValue("expressionHandler", expressionHandler); @@ -734,7 +718,8 @@ class HttpConfigurationBuilder { voters.add(expressionVoter.getBeanDefinition()); } else { - voters.add(GrantedAuthorityDefaultsParserUtils.registerWithDefaultRolePrefix(pc, RoleVoterBeanFactory.class)); + voters.add( + GrantedAuthorityDefaultsParserUtils.registerWithDefaultRolePrefix(pc, RoleVoterBeanFactory.class)); voters.add(new RootBeanDefinition(AuthenticatedVoter.class)); } accessDecisionMgr = new RootBeanDefinition(AffirmativeBased.class); @@ -746,12 +731,10 @@ class HttpConfigurationBuilder { if (!StringUtils.hasText(accessManagerId)) { accessManagerId = pc.getReaderContext().generateBeanName(accessDecisionMgr); - pc.registerBeanComponent(new BeanComponentDefinition(accessDecisionMgr, - accessManagerId)); + pc.registerBeanComponent(new BeanComponentDefinition(accessDecisionMgr, accessManagerId)); } - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .rootBeanDefinition(FilterSecurityInterceptor.class); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class); builder.addPropertyReference("accessDecisionManager", accessManagerId); builder.addPropertyValue("authenticationManager", authManager); @@ -767,13 +750,10 @@ class HttpConfigurationBuilder { // Create and register a DefaultWebInvocationPrivilegeEvaluator for use with // taglibs etc. - BeanDefinition wipe = new RootBeanDefinition( - DefaultWebInvocationPrivilegeEvaluator.class); - wipe.getConstructorArgumentValues().addGenericArgumentValue( - new RuntimeBeanReference(fsiId)); + BeanDefinition wipe = new RootBeanDefinition(DefaultWebInvocationPrivilegeEvaluator.class); + wipe.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference(fsiId)); - pc.registerBeanComponent(new BeanComponentDefinition(wipe, pc.getReaderContext() - .generateBeanName(wipe))); + pc.registerBeanComponent(new BeanComponentDefinition(wipe, pc.getReaderContext().generateBeanName(wipe))); this.fsi = new RuntimeBeanReference(fsiId); } @@ -827,17 +807,14 @@ class HttpConfigurationBuilder { } if (concurrentSessionFilter != null) { - filters.add(new OrderDecorator(concurrentSessionFilter, - CONCURRENT_SESSION_FILTER)); + filters.add(new OrderDecorator(concurrentSessionFilter, CONCURRENT_SESSION_FILTER)); } if (webAsyncManagerFilter != null) { - filters.add(new OrderDecorator(webAsyncManagerFilter, - WEB_ASYNC_MANAGER_FILTER)); + filters.add(new OrderDecorator(webAsyncManagerFilter, WEB_ASYNC_MANAGER_FILTER)); } - filters.add(new OrderDecorator(securityContextPersistenceFilter, - SECURITY_CONTEXT_FILTER)); + filters.add(new OrderDecorator(securityContextPersistenceFilter, SECURITY_CONTEXT_FILTER)); if (servApiFilter != null) { filters.add(new OrderDecorator(servApiFilter, SERVLET_API_SUPPORT_FILTER)); @@ -873,20 +850,26 @@ class HttpConfigurationBuilder { } static class RoleVoterBeanFactory extends AbstractGrantedAuthorityDefaultsBeanFactory { + private RoleVoter voter = new RoleVoter(); public RoleVoter getBean() { voter.setRolePrefix(this.rolePrefix); return voter; } + } - static class SecurityContextHolderAwareRequestFilterBeanFactory extends GrantedAuthorityDefaultsParserUtils.AbstractGrantedAuthorityDefaultsBeanFactory { + static class SecurityContextHolderAwareRequestFilterBeanFactory + extends GrantedAuthorityDefaultsParserUtils.AbstractGrantedAuthorityDefaultsBeanFactory { + private SecurityContextHolderAwareRequestFilter filter = new SecurityContextHolderAwareRequestFilter(); public SecurityContextHolderAwareRequestFilter getBean() { filter.setRolePrefix(this.rolePrefix); return filter; } + } + } diff --git a/config/src/main/java/org/springframework/security/config/http/HttpFirewallBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/HttpFirewallBeanDefinitionParser.java index 6fd912d81a..c5d3fde8e4 100644 --- a/config/src/main/java/org/springframework/security/config/http/HttpFirewallBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/HttpFirewallBeanDefinitionParser.java @@ -35,18 +35,15 @@ public class HttpFirewallBeanDefinitionParser implements BeanDefinitionParser { String ref = element.getAttribute("ref"); if (!StringUtils.hasText(ref)) { - pc.getReaderContext().error("ref attribute is required", - pc.extractSource(element)); + pc.getReaderContext().error("ref attribute is required", pc.extractSource(element)); } // Ensure the FCP is registered. - HttpSecurityBeanDefinitionParser.registerFilterChainProxyIfNecessary(pc, - pc.extractSource(element)); - BeanDefinition filterChainProxy = pc.getRegistry().getBeanDefinition( - BeanIds.FILTER_CHAIN_PROXY); - filterChainProxy.getPropertyValues().addPropertyValue("firewall", - new RuntimeBeanReference(ref)); + HttpSecurityBeanDefinitionParser.registerFilterChainProxyIfNecessary(pc, pc.extractSource(element)); + BeanDefinition filterChainProxy = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAIN_PROXY); + filterChainProxy.getPropertyValues().addPropertyValue("firewall", new RuntimeBeanReference(ref)); return null; } + } diff --git a/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java index d9f4a74ee2..acaa187f45 100644 --- a/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java @@ -65,8 +65,8 @@ import org.springframework.util.xml.DomUtils; * @since 2.0 */ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { - private static final Log logger = LogFactory - .getLog(HttpSecurityBeanDefinitionParser.class); + + private static final Log logger = LogFactory.getLog(HttpSecurityBeanDefinitionParser.class); private static final String ATT_AUTHENTICATION_MANAGER_REF = "authentication-manager-ref"; static final String ATT_REQUEST_MATCHER_REF = "request-matcher-ref"; @@ -79,7 +79,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_REQUIRES_CHANNEL = "requires-channel"; private static final String ATT_REF = "ref"; + private static final String ATT_SECURED = "security"; + private static final String OPT_SECURITY_NONE = "none"; public HttpSecurityBeanDefinitionParser() { @@ -97,17 +99,16 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { @SuppressWarnings({ "unchecked" }) @Override public BeanDefinition parse(Element element, ParserContext pc) { - CompositeComponentDefinition compositeDef = new CompositeComponentDefinition( - element.getTagName(), pc.extractSource(element)); + CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), + pc.extractSource(element)); pc.pushContainingComponent(compositeDef); registerFilterChainProxyIfNecessary(pc, pc.extractSource(element)); // Obtain the filter chains and add the new chain to it - BeanDefinition listFactoryBean = pc.getRegistry().getBeanDefinition( - BeanIds.FILTER_CHAINS); - List filterChains = (List) listFactoryBean - .getPropertyValues().getPropertyValue("sourceList").getValue(); + BeanDefinition listFactoryBean = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAINS); + List filterChains = (List) listFactoryBean.getPropertyValues() + .getPropertyValue("sourceList").getValue(); filterChains.add(createFilterChain(element, pc)); @@ -124,20 +125,16 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { if (!secured) { if (!StringUtils.hasText(element.getAttribute(ATT_PATH_PATTERN)) && !StringUtils.hasText(ATT_REQUEST_MATCHER_REF)) { - pc.getReaderContext().error( - "The '" + ATT_SECURED - + "' attribute must be used in combination with" - + " the '" + ATT_PATH_PATTERN + "' or '" - + ATT_REQUEST_MATCHER_REF + "' attributes.", - pc.extractSource(element)); + pc.getReaderContext() + .error("The '" + ATT_SECURED + "' attribute must be used in combination with" + " the '" + + ATT_PATH_PATTERN + "' or '" + ATT_REQUEST_MATCHER_REF + "' attributes.", + pc.extractSource(element)); } for (int n = 0; n < element.getChildNodes().getLength(); n++) { if (element.getChildNodes().item(n) instanceof Element) { - pc.getReaderContext().error( - "If you are using to define an unsecured pattern, " - + "it cannot contain child elements.", - pc.extractSource(element)); + pc.getReaderContext().error("If you are using to define an unsecured pattern, " + + "it cannot contain child elements.", pc.extractSource(element)); } } @@ -148,18 +145,15 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { final BeanReference portResolver = createPortResolver(portMapper, pc); ManagedList authenticationProviders = new ManagedList<>(); - BeanReference authenticationManager = createAuthenticationManager(element, pc, - authenticationProviders); + BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders); boolean forceAutoConfig = isDefaultHttpConfig(element); - HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, - forceAutoConfig, pc, portMapper, portResolver, authenticationManager); + HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, forceAutoConfig, pc, portMapper, + portResolver, authenticationManager); - AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, - forceAutoConfig, pc, httpBldr.getSessionCreationPolicy(), - httpBldr.getRequestCache(), authenticationManager, - httpBldr.getSessionStrategy(), portMapper, portResolver, - httpBldr.getCsrfLogoutHandler()); + AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, forceAutoConfig, pc, + httpBldr.getSessionCreationPolicy(), httpBldr.getRequestCache(), authenticationManager, + httpBldr.getSessionStrategy(), portMapper, portResolver, httpBldr.getCsrfLogoutHandler()); httpBldr.setLogoutHandlers(authBldr.getLogoutHandlers()); httpBldr.setEntryPoint(authBldr.getEntryPointBean()); @@ -188,12 +182,10 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { } private static boolean isDefaultHttpConfig(Element httpElt) { - return httpElt.getChildNodes().getLength() == 0 - && httpElt.getAttributes().getLength() == 0; + return httpElt.getChildNodes().getLength() == 0 && httpElt.getAttributes().getLength() == 0; } - private BeanReference createSecurityFilterChainBean(Element element, - ParserContext pc, List filterChain) { + private BeanReference createSecurityFilterChainBean(Element element, ParserContext pc, List filterChain) { BeanMetadataElement filterChainMatcher; String requestMatcherRef = element.getAttribute(ATT_REQUEST_MATCHER_REF); @@ -202,15 +194,14 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { if (StringUtils.hasText(requestMatcherRef)) { if (StringUtils.hasText(filterChainPattern)) { pc.getReaderContext().error( - "You can't define a pattern and a request-matcher-ref for the " - + "same filter chain", pc.extractSource(element)); + "You can't define a pattern and a request-matcher-ref for the " + "same filter chain", + pc.extractSource(element)); } filterChainMatcher = new RuntimeBeanReference(requestMatcherRef); } else if (StringUtils.hasText(filterChainPattern)) { - filterChainMatcher = MatcherType.fromElement(element).createMatcher(pc, - filterChainPattern, null); + filterChainMatcher = MatcherType.fromElement(element).createMatcher(pc, filterChainPattern, null); } else { filterChainMatcher = new RootBeanDefinition(AnyRequestMatcher.class); @@ -239,21 +230,19 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { private BeanReference createPortMapper(Element elt, ParserContext pc) { // Register the portMapper. A default will always be created, even if no element // exists. - BeanDefinition portMapper = new PortMappingsBeanDefinitionParser().parse( - DomUtils.getChildElementByTagName(elt, Elements.PORT_MAPPINGS), pc); + BeanDefinition portMapper = new PortMappingsBeanDefinitionParser() + .parse(DomUtils.getChildElementByTagName(elt, Elements.PORT_MAPPINGS), pc); String portMapperName = pc.getReaderContext().generateBeanName(portMapper); pc.registerBeanComponent(new BeanComponentDefinition(portMapper, portMapperName)); return new RuntimeBeanReference(portMapperName); } - private RuntimeBeanReference createPortResolver(BeanReference portMapper, - ParserContext pc) { + private RuntimeBeanReference createPortResolver(BeanReference portMapper, ParserContext pc) { RootBeanDefinition portResolver = new RootBeanDefinition(PortResolverImpl.class); portResolver.getPropertyValues().addPropertyValue("portMapper", portMapper); String portResolverName = pc.getReaderContext().generateBeanName(portResolver); - pc.registerBeanComponent(new BeanComponentDefinition(portResolver, - portResolverName)); + pc.registerBeanComponent(new BeanComponentDefinition(portResolver, portResolverName)); return new RuntimeBeanReference(portResolverName); } @@ -268,44 +257,37 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { private BeanReference createAuthenticationManager(Element element, ParserContext pc, ManagedList authenticationProviders) { String parentMgrRef = element.getAttribute(ATT_AUTHENTICATION_MANAGER_REF); - BeanDefinitionBuilder authManager = BeanDefinitionBuilder - .rootBeanDefinition(ProviderManager.class); + BeanDefinitionBuilder authManager = BeanDefinitionBuilder.rootBeanDefinition(ProviderManager.class); authManager.addConstructorArgValue(authenticationProviders); if (StringUtils.hasText(parentMgrRef)) { - RuntimeBeanReference parentAuthManager = new RuntimeBeanReference( - parentMgrRef); + RuntimeBeanReference parentAuthManager = new RuntimeBeanReference(parentMgrRef); authManager.addConstructorArgValue(parentAuthManager); RootBeanDefinition clearCredentials = new RootBeanDefinition( ClearCredentialsMethodInvokingFactoryBean.class); - clearCredentials.getPropertyValues().addPropertyValue("targetObject", - parentAuthManager); + clearCredentials.getPropertyValues().addPropertyValue("targetObject", parentAuthManager); clearCredentials.getPropertyValues().addPropertyValue("targetMethod", "isEraseCredentialsAfterAuthentication"); - authManager.addPropertyValue("eraseCredentialsAfterAuthentication", - clearCredentials); + authManager.addPropertyValue("eraseCredentialsAfterAuthentication", clearCredentials); } else { - RootBeanDefinition amfb = new RootBeanDefinition( - AuthenticationManagerFactoryBean.class); + RootBeanDefinition amfb = new RootBeanDefinition(AuthenticationManagerFactoryBean.class); amfb.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); String amfbId = pc.getReaderContext().generateBeanName(amfb); pc.registerBeanComponent(new BeanComponentDefinition(amfb, amfbId)); - RootBeanDefinition clearCredentials = new RootBeanDefinition( - MethodInvokingFactoryBean.class); - clearCredentials.getPropertyValues().addPropertyValue("targetObject", - new RuntimeBeanReference(amfbId)); + RootBeanDefinition clearCredentials = new RootBeanDefinition(MethodInvokingFactoryBean.class); + clearCredentials.getPropertyValues().addPropertyValue("targetObject", new RuntimeBeanReference(amfbId)); clearCredentials.getPropertyValues().addPropertyValue("targetMethod", "isEraseCredentialsAfterAuthentication"); authManager.addConstructorArgValue(new RuntimeBeanReference(amfbId)); - authManager.addPropertyValue("eraseCredentialsAfterAuthentication", - clearCredentials); + authManager.addPropertyValue("eraseCredentialsAfterAuthentication", clearCredentials); } // gh-6009 - authManager.addPropertyValue("authenticationEventPublisher", new RootBeanDefinition(DefaultAuthenticationEventPublisher.class)); + authManager.addPropertyValue("authenticationEventPublisher", + new RootBeanDefinition(DefaultAuthenticationEventPublisher.class)); authManager.getRawBeanDefinition().setSource(pc.extractSource(element)); BeanDefinition authMgrBean = authManager.getBeanDefinition(); String id = pc.getReaderContext().generateBeanName(authMgrBean); @@ -314,8 +296,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { return new RuntimeBeanReference(id); } - private void checkFilterChainOrder(List filters, ParserContext pc, - Object source) { + private void checkFilterChainOrder(List filters, ParserContext pc, Object source) { logger.info("Checking sorted filter chain: " + filters); for (int i = 0; i < filters.size(); i++) { @@ -325,10 +306,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { OrderDecorator previous = filters.get(i - 1); if (filter.getOrder() == previous.getOrder()) { pc.getReaderContext() - .error("Filter beans '" - + filter.bean - + "' and '" - + previous.bean + .error("Filter beans '" + filter.bean + "' and '" + previous.bean + "' have the same 'order' value. When using custom filters, " + "please make sure the positions do not conflict with default filters. " + "Alternatively you can disable the default filters by removing the corresponding " @@ -340,8 +318,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { } List buildCustomFilterList(Element element, ParserContext pc) { - List customFilterElts = DomUtils.getChildElementsByTagName(element, - Elements.CUSTOM_FILTER); + List customFilterElts = DomUtils.getChildElementsByTagName(element, Elements.CUSTOM_FILTER); List customFilters = new ArrayList<>(); final String ATT_AFTER = "after"; @@ -356,23 +333,18 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { String ref = elt.getAttribute(ATT_REF); if (!StringUtils.hasText(ref)) { - pc.getReaderContext().error( - "The '" + ATT_REF + "' attribute must be supplied", - pc.extractSource(elt)); + pc.getReaderContext().error("The '" + ATT_REF + "' attribute must be supplied", pc.extractSource(elt)); } RuntimeBeanReference bean = new RuntimeBeanReference(ref); if (WebConfigUtils.countNonEmpty(new String[] { after, before, position }) != 1) { - pc.getReaderContext().error( - "A single '" + ATT_AFTER + "', '" + ATT_BEFORE + "', or '" - + ATT_POSITION + "' attribute must be supplied", - pc.extractSource(elt)); + pc.getReaderContext().error("A single '" + ATT_AFTER + "', '" + ATT_BEFORE + "', or '" + ATT_POSITION + + "' attribute must be supplied", pc.extractSource(elt)); } if (StringUtils.hasText(position)) { - customFilters.add(new OrderDecorator(bean, SecurityFilters - .valueOf(position))); + customFilters.add(new OrderDecorator(bean, SecurityFilters.valueOf(position))); } else if (StringUtils.hasText(after)) { SecurityFilters order = SecurityFilters.valueOf(after); @@ -406,22 +378,18 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { // FilterChainProxy BeanDefinition listFactoryBean = new RootBeanDefinition(ListFactoryBean.class); listFactoryBean.getPropertyValues().add("sourceList", new ManagedList()); - pc.registerBeanComponent(new BeanComponentDefinition(listFactoryBean, - BeanIds.FILTER_CHAINS)); + pc.registerBeanComponent(new BeanComponentDefinition(listFactoryBean, BeanIds.FILTER_CHAINS)); - BeanDefinitionBuilder fcpBldr = BeanDefinitionBuilder - .rootBeanDefinition(FilterChainProxy.class); + BeanDefinitionBuilder fcpBldr = BeanDefinitionBuilder.rootBeanDefinition(FilterChainProxy.class); fcpBldr.getRawBeanDefinition().setSource(source); fcpBldr.addConstructorArgReference(BeanIds.FILTER_CHAINS); - fcpBldr.addPropertyValue("filterChainValidator", new RootBeanDefinition( - DefaultFilterChainValidator.class)); + fcpBldr.addPropertyValue("filterChainValidator", new RootBeanDefinition(DefaultFilterChainValidator.class)); BeanDefinition fcpBean = fcpBldr.getBeanDefinition(); - pc.registerBeanComponent(new BeanComponentDefinition(fcpBean, - BeanIds.FILTER_CHAIN_PROXY)); - registry.registerAlias(BeanIds.FILTER_CHAIN_PROXY, - BeanIds.SPRING_SECURITY_FILTER_CHAIN); + pc.registerBeanComponent(new BeanComponentDefinition(fcpBean, BeanIds.FILTER_CHAIN_PROXY)); + registry.registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN); - BeanDefinitionBuilder requestRejected = BeanDefinitionBuilder.rootBeanDefinition(RequestRejectedHandlerPostProcessor.class); + BeanDefinitionBuilder requestRejected = BeanDefinitionBuilder + .rootBeanDefinition(RequestRejectedHandlerPostProcessor.class); requestRejected.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); requestRejected.addConstructorArgValue("requestRejectedHandler"); requestRejected.addConstructorArgValue(BeanIds.FILTER_CHAIN_PROXY); @@ -434,6 +402,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { } class RequestRejectedHandlerPostProcessor implements BeanDefinitionRegistryPostProcessor { + private final String beanName; private final String targetBeanName; @@ -458,10 +427,13 @@ class RequestRejectedHandlerPostProcessor implements BeanDefinitionRegistryPostP public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } + } class OrderDecorator implements Ordered { + final BeanMetadataElement bean; + final int order; OrderDecorator(BeanMetadataElement bean, SecurityFilters filterOrder) { @@ -483,6 +455,7 @@ class OrderDecorator implements Ordered { public String toString() { return bean + ", order = " + order; } + } /** @@ -495,6 +468,7 @@ class OrderDecorator implements Ordered { * @author Rob Winch */ final class ClearCredentialsMethodInvokingFactoryBean extends MethodInvokingFactoryBean { + @Override public void afterPropertiesSet() throws Exception { boolean isTargetProviderManager = getTargetObject() instanceof ProviderManager; @@ -512,10 +486,10 @@ final class ClearCredentialsMethodInvokingFactoryBean extends MethodInvokingFact * original {@link AuthenticationManager} must be a {@link ProviderManager} (we should * not magically add this functionality to their implementation since we cannot * determine if it should be on or off). - * * @return */ public boolean isEraseCredentialsAfterAuthentication() { return false; } + } diff --git a/config/src/main/java/org/springframework/security/config/http/LogoutBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/LogoutBeanDefinitionParser.java index 8b8c4f8b6c..9e9aab78c4 100644 --- a/config/src/main/java/org/springframework/security/config/http/LogoutBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/LogoutBeanDefinitionParser.java @@ -36,6 +36,7 @@ import org.w3c.dom.Element; * @author Onur Kagan Ozcan */ class LogoutBeanDefinitionParser implements BeanDefinitionParser { + static final String ATT_LOGOUT_SUCCESS_URL = "logout-success-url"; static final String ATT_INVALIDATE_SESSION = "invalidate-session"; @@ -46,12 +47,14 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_DELETE_COOKIES = "delete-cookies"; final String rememberMeServices; + private final String defaultLogoutUrl; + private ManagedList logoutHandlers = new ManagedList<>(); + private boolean csrfEnabled; - LogoutBeanDefinitionParser(String loginPageUrl, String rememberMeServices, - BeanMetadataElement csrfLogoutHandler) { + LogoutBeanDefinitionParser(String loginPageUrl, String rememberMeServices, BeanMetadataElement csrfLogoutHandler) { this.defaultLogoutUrl = loginPageUrl + "?logout"; this.rememberMeServices = rememberMeServices; this.csrfEnabled = csrfLogoutHandler != null; @@ -67,8 +70,7 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser { String invalidateSession = null; String deleteCookies = null; - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .rootBeanDefinition(LogoutFilter.class); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(LogoutFilter.class); if (element != null) { Object source = pc.extractSource(element); @@ -86,14 +88,13 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser { logoutUrl = DEF_LOGOUT_URL; } - builder.addPropertyValue("logoutRequestMatcher", - getLogoutRequestMatcher(logoutUrl)); + builder.addPropertyValue("logoutRequestMatcher", getLogoutRequestMatcher(logoutUrl)); if (StringUtils.hasText(successHandlerRef)) { if (StringUtils.hasText(logoutSuccessUrl)) { pc.getReaderContext().error( - "Use " + ATT_LOGOUT_SUCCESS_URL + " or " + ATT_LOGOUT_HANDLER - + ", but not both", pc.extractSource(element)); + "Use " + ATT_LOGOUT_SUCCESS_URL + " or " + ATT_LOGOUT_HANDLER + ", but not both", + pc.extractSource(element)); } builder.addConstructorArgReference(successHandlerRef); } @@ -106,8 +107,7 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser { } BeanDefinition sclh = new RootBeanDefinition(SecurityContextLogoutHandler.class); - sclh.getPropertyValues().addPropertyValue("invalidateHttpSession", - !"false".equals(invalidateSession)); + sclh.getPropertyValues().addPropertyValue("invalidateHttpSession", !"false".equals(invalidateSession)); logoutHandlers.add(sclh); if (rememberMeServices != null) { @@ -115,8 +115,7 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser { } if (StringUtils.hasText(deleteCookies)) { - BeanDefinition cookieDeleter = new RootBeanDefinition( - CookieClearingLogoutHandler.class); + BeanDefinition cookieDeleter = new RootBeanDefinition(CookieClearingLogoutHandler.class); String[] names = StringUtils.tokenizeToStringArray(deleteCookies, ","); cookieDeleter.getConstructorArgumentValues().addGenericArgumentValue(names); logoutHandlers.add(cookieDeleter); @@ -143,4 +142,5 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser { ManagedList getLogoutHandlers() { return logoutHandlers; } + } diff --git a/config/src/main/java/org/springframework/security/config/http/MatcherType.java b/config/src/main/java/org/springframework/security/config/http/MatcherType.java index 58cd734aed..63cbcfaf22 100644 --- a/config/src/main/java/org/springframework/security/config/http/MatcherType.java +++ b/config/src/main/java/org/springframework/security/config/http/MatcherType.java @@ -34,8 +34,9 @@ import org.w3c.dom.Element; * @since 3.1 */ public enum MatcherType { - ant(AntPathRequestMatcher.class), regex(RegexRequestMatcher.class), ciRegex( - RegexRequestMatcher.class), mvc(MvcRequestMatcher.class); + + ant(AntPathRequestMatcher.class), regex(RegexRequestMatcher.class), ciRegex(RegexRequestMatcher.class), mvc( + MvcRequestMatcher.class); private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"; @@ -56,8 +57,7 @@ public enum MatcherType { return new RootBeanDefinition(AnyRequestMatcher.class); } - BeanDefinitionBuilder matcherBldr = BeanDefinitionBuilder - .rootBeanDefinition(type); + BeanDefinitionBuilder matcherBldr = BeanDefinitionBuilder.rootBeanDefinition(type); if (this == mvc) { matcherBldr.addConstructorArgValue(new RootBeanDefinition(HandlerMappingIntrospectorFactoryBean.class)); @@ -86,4 +86,5 @@ public enum MatcherType { return ant; } + } diff --git a/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParser.java index ccc3219e46..894bc7a4ac 100644 --- a/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParser.java @@ -40,15 +40,25 @@ import static org.springframework.security.config.http.OAuth2ClientBeanDefinitio * @since 5.3 */ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser { + private static final String ELT_AUTHORIZATION_CODE_GRANT = "authorization-code-grant"; + private static final String ATT_AUTHORIZATION_REQUEST_REPOSITORY_REF = "authorization-request-repository-ref"; + private static final String ATT_AUTHORIZATION_REQUEST_RESOLVER_REF = "authorization-request-resolver-ref"; + private static final String ATT_ACCESS_TOKEN_RESPONSE_CLIENT_REF = "access-token-response-client-ref"; + private final BeanReference requestCache; + private final BeanReference authenticationManager; + private BeanDefinition defaultAuthorizedClientRepository; + private BeanDefinition authorizationRequestRedirectFilter; + private BeanDefinition authorizationCodeGrantFilter; + private BeanDefinition authorizationCodeAuthenticationProvider; OAuth2ClientBeanDefinitionParser(BeanReference requestCache, BeanReference authenticationManager) { @@ -73,43 +83,41 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser { BeanDefinitionBuilder authorizationRequestRedirectFilterBuilder = BeanDefinitionBuilder .rootBeanDefinition(OAuth2AuthorizationRequestRedirectFilter.class); - String authorizationRequestResolverRef = authorizationCodeGrantElt != null ? - authorizationCodeGrantElt.getAttribute(ATT_AUTHORIZATION_REQUEST_RESOLVER_REF) : null; + String authorizationRequestResolverRef = authorizationCodeGrantElt != null + ? authorizationCodeGrantElt.getAttribute(ATT_AUTHORIZATION_REQUEST_RESOLVER_REF) : null; if (!StringUtils.isEmpty(authorizationRequestResolverRef)) { authorizationRequestRedirectFilterBuilder.addConstructorArgReference(authorizationRequestResolverRef); - } else { + } + else { authorizationRequestRedirectFilterBuilder.addConstructorArgValue(clientRegistrationRepository); } this.authorizationRequestRedirectFilter = authorizationRequestRedirectFilterBuilder .addPropertyValue("authorizationRequestRepository", authorizationRequestRepository) - .addPropertyValue("requestCache", this.requestCache) - .getBeanDefinition(); + .addPropertyValue("requestCache", this.requestCache).getBeanDefinition(); this.authorizationCodeGrantFilter = BeanDefinitionBuilder .rootBeanDefinition(OAuth2AuthorizationCodeGrantFilter.class) - .addConstructorArgValue(clientRegistrationRepository) - .addConstructorArgValue(authorizedClientRepository) + .addConstructorArgValue(clientRegistrationRepository).addConstructorArgValue(authorizedClientRepository) .addConstructorArgValue(this.authenticationManager) - .addPropertyValue("authorizationRequestRepository", authorizationRequestRepository) - .getBeanDefinition(); + .addPropertyValue("authorizationRequestRepository", authorizationRequestRepository).getBeanDefinition(); BeanMetadataElement accessTokenResponseClient = getAccessTokenResponseClient(authorizationCodeGrantElt); this.authorizationCodeAuthenticationProvider = BeanDefinitionBuilder .rootBeanDefinition(OAuth2AuthorizationCodeAuthenticationProvider.class) - .addConstructorArgValue(accessTokenResponseClient) - .getBeanDefinition(); + .addConstructorArgValue(accessTokenResponseClient).getBeanDefinition(); return null; } private BeanMetadataElement getAuthorizationRequestRepository(Element element) { BeanMetadataElement authorizationRequestRepository; - String authorizationRequestRepositoryRef = element != null ? - element.getAttribute(ATT_AUTHORIZATION_REQUEST_REPOSITORY_REF) : null; + String authorizationRequestRepositoryRef = element != null + ? element.getAttribute(ATT_AUTHORIZATION_REQUEST_REPOSITORY_REF) : null; if (!StringUtils.isEmpty(authorizationRequestRepositoryRef)) { authorizationRequestRepository = new RuntimeBeanReference(authorizationRequestRepositoryRef); - } else { + } + else { authorizationRequestRepository = BeanDefinitionBuilder.rootBeanDefinition( "org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository") .getBeanDefinition(); @@ -119,11 +127,12 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser { private BeanMetadataElement getAccessTokenResponseClient(Element element) { BeanMetadataElement accessTokenResponseClient; - String accessTokenResponseClientRef = element != null ? - element.getAttribute(ATT_ACCESS_TOKEN_RESPONSE_CLIENT_REF) : null; + String accessTokenResponseClientRef = element != null + ? element.getAttribute(ATT_ACCESS_TOKEN_RESPONSE_CLIENT_REF) : null; if (!StringUtils.isEmpty(accessTokenResponseClientRef)) { accessTokenResponseClient = new RuntimeBeanReference(accessTokenResponseClientRef); - } else { + } + else { accessTokenResponseClient = BeanDefinitionBuilder.rootBeanDefinition( "org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient") .getBeanDefinition(); @@ -146,4 +155,5 @@ final class OAuth2ClientBeanDefinitionParser implements BeanDefinitionParser { BeanDefinition getAuthorizationCodeAuthenticationProvider() { return this.authorizationCodeAuthenticationProvider; } + } diff --git a/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserUtils.java b/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserUtils.java index c0af4d7d44..db681dfce1 100644 --- a/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserUtils.java +++ b/config/src/main/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserUtils.java @@ -28,8 +28,11 @@ import org.w3c.dom.Element; * @since 5.4 */ final class OAuth2ClientBeanDefinitionParserUtils { + private static final String ATT_CLIENT_REGISTRATION_REPOSITORY_REF = "client-registration-repository-ref"; + private static final String ATT_AUTHORIZED_CLIENT_REPOSITORY_REF = "authorized-client-repository-ref"; + private static final String ATT_AUTHORIZED_CLIENT_SERVICE_REF = "authorized-client-service-ref"; static BeanMetadataElement getClientRegistrationRepository(Element element) { @@ -37,7 +40,8 @@ final class OAuth2ClientBeanDefinitionParserUtils { String clientRegistrationRepositoryRef = element.getAttribute(ATT_CLIENT_REGISTRATION_REPOSITORY_REF); if (!StringUtils.isEmpty(clientRegistrationRepositoryRef)) { clientRegistrationRepository = new RuntimeBeanReference(clientRegistrationRepositoryRef); - } else { + } + else { clientRegistrationRepository = new RuntimeBeanReference(ClientRegistrationRepository.class); } return clientRegistrationRepository; @@ -59,17 +63,17 @@ final class OAuth2ClientBeanDefinitionParserUtils { return null; } - static BeanDefinition createDefaultAuthorizedClientRepository( - BeanMetadataElement clientRegistrationRepository, BeanMetadataElement authorizedClientService) { + static BeanDefinition createDefaultAuthorizedClientRepository(BeanMetadataElement clientRegistrationRepository, + BeanMetadataElement authorizedClientService) { if (authorizedClientService == null) { - authorizedClientService = BeanDefinitionBuilder.rootBeanDefinition( - "org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService") - .addConstructorArgValue(clientRegistrationRepository) - .getBeanDefinition(); + authorizedClientService = BeanDefinitionBuilder + .rootBeanDefinition( + "org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService") + .addConstructorArgValue(clientRegistrationRepository).getBeanDefinition(); } return BeanDefinitionBuilder.rootBeanDefinition( "org.springframework.security.oauth2.client.web.AuthenticatedPrincipalOAuth2AuthorizedClientRepository") - .addConstructorArgValue(authorizedClientService) - .getBeanDefinition(); + .addConstructorArgValue(authorizedClientService).getBeanDefinition(); } + } diff --git a/config/src/main/java/org/springframework/security/config/http/OAuth2ClientWebMvcSecurityPostProcessor.java b/config/src/main/java/org/springframework/security/config/http/OAuth2ClientWebMvcSecurityPostProcessor.java index a6535ea064..1c6add1ede 100644 --- a/config/src/main/java/org/springframework/security/config/http/OAuth2ClientWebMvcSecurityPostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/http/OAuth2ClientWebMvcSecurityPostProcessor.java @@ -38,7 +38,9 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl * @since 5.4 */ final class OAuth2ClientWebMvcSecurityPostProcessor implements BeanDefinitionRegistryPostProcessor, BeanFactoryAware { + private static final String CUSTOM_ARGUMENT_RESOLVERS_PROPERTY = "customArgumentResolvers"; + private BeanFactory beanFactory; @Override @@ -55,8 +57,8 @@ final class OAuth2ClientWebMvcSecurityPostProcessor implements BeanDefinitionReg for (String beanName : registry.getBeanDefinitionNames()) { BeanDefinition beanDefinition = registry.getBeanDefinition(beanName); if (RequestMappingHandlerAdapter.class.getName().equals(beanDefinition.getBeanClassName())) { - PropertyValue currentArgumentResolvers = - beanDefinition.getPropertyValues().getPropertyValue(CUSTOM_ARGUMENT_RESOLVERS_PROPERTY); + PropertyValue currentArgumentResolvers = beanDefinition.getPropertyValues() + .getPropertyValue(CUSTOM_ARGUMENT_RESOLVERS_PROPERTY); ManagedList argumentResolvers = new ManagedList<>(); if (currentArgumentResolvers != null) { argumentResolvers.addAll((ManagedList) currentArgumentResolvers.getValue()); @@ -65,11 +67,12 @@ final class OAuth2ClientWebMvcSecurityPostProcessor implements BeanDefinitionReg String[] authorizedClientManagerBeanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( (ListableBeanFactory) this.beanFactory, OAuth2AuthorizedClientManager.class, false, false); - BeanDefinitionBuilder beanDefinitionBuilder = - BeanDefinitionBuilder.genericBeanDefinition(OAuth2AuthorizedClientArgumentResolver.class); + BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder + .genericBeanDefinition(OAuth2AuthorizedClientArgumentResolver.class); if (authorizedClientManagerBeanNames.length == 1) { beanDefinitionBuilder.addConstructorArgReference(authorizedClientManagerBeanNames[0]); - } else { + } + else { beanDefinitionBuilder.addConstructorArgReference(clientRegistrationRepositoryBeanNames[0]); beanDefinitionBuilder.addConstructorArgReference(authorizedClientRepositoryBeanNames[0]); } @@ -88,4 +91,5 @@ final class OAuth2ClientWebMvcSecurityPostProcessor implements BeanDefinitionReg public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } + } diff --git a/config/src/main/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParser.java index 68ac6f2041..20240dcf3e 100644 --- a/config/src/main/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParser.java @@ -79,26 +79,43 @@ import static org.springframework.security.config.http.OAuth2ClientBeanDefinitio final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { private static final String DEFAULT_AUTHORIZATION_REQUEST_BASE_URI = "/oauth2/authorization"; + private static final String DEFAULT_LOGIN_URI = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL; private static final String ELT_CLIENT_REGISTRATION = "client-registration"; + private static final String ATT_REGISTRATION_ID = "registration-id"; + private static final String ATT_AUTHORIZATION_REQUEST_REPOSITORY_REF = "authorization-request-repository-ref"; + private static final String ATT_AUTHORIZATION_REQUEST_RESOLVER_REF = "authorization-request-resolver-ref"; + private static final String ATT_ACCESS_TOKEN_RESPONSE_CLIENT_REF = "access-token-response-client-ref"; + private static final String ATT_USER_AUTHORITIES_MAPPER_REF = "user-authorities-mapper-ref"; + private static final String ATT_USER_SERVICE_REF = "user-service-ref"; + private static final String ATT_OIDC_USER_SERVICE_REF = "oidc-user-service-ref"; + private static final String ATT_LOGIN_PROCESSING_URL = "login-processing-url"; + private static final String ATT_LOGIN_PAGE = "login-page"; + private static final String ATT_AUTHENTICATION_SUCCESS_HANDLER_REF = "authentication-success-handler-ref"; + private static final String ATT_AUTHENTICATION_FAILURE_HANDLER_REF = "authentication-failure-handler-ref"; + private static final String ATT_JWT_DECODER_FACTORY_REF = "jwt-decoder-factory-ref"; private final BeanReference requestCache; + private final BeanReference portMapper; + private final BeanReference portResolver; + private final BeanReference sessionStrategy; + private final boolean allowSessionCreation; private BeanDefinition defaultAuthorizedClientRepository; @@ -128,8 +145,8 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { BeanDefinition oauth2LoginBeanConfig = BeanDefinitionBuilder.rootBeanDefinition(OAuth2LoginBeanConfig.class) .getBeanDefinition(); String oauth2LoginBeanConfigId = parserContext.getReaderContext().generateBeanName(oauth2LoginBeanConfig); - parserContext.registerBeanComponent( - new BeanComponentDefinition(oauth2LoginBeanConfig, oauth2LoginBeanConfigId)); + parserContext + .registerBeanComponent(new BeanComponentDefinition(oauth2LoginBeanConfig, oauth2LoginBeanConfigId)); // configure filter BeanMetadataElement clientRegistrationRepository = getClientRegistrationRepository(element); @@ -146,8 +163,7 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { BeanDefinitionBuilder oauth2LoginAuthenticationFilterBuilder = BeanDefinitionBuilder .rootBeanDefinition(OAuth2LoginAuthenticationFilter.class) - .addConstructorArgValue(clientRegistrationRepository) - .addConstructorArgValue(authorizedClientRepository) + .addConstructorArgValue(clientRegistrationRepository).addConstructorArgValue(authorizedClientRepository) .addPropertyValue("authorizationRequestRepository", authorizationRequestRepository); if (sessionStrategy != null) { @@ -159,34 +175,35 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { if (!StringUtils.isEmpty(loginProcessingUrl)) { WebConfigUtils.validateHttpRedirect(loginProcessingUrl, parserContext, source); oauth2LoginAuthenticationFilterBuilder.addConstructorArgValue(loginProcessingUrl); - } else { + } + else { oauth2LoginAuthenticationFilterBuilder .addConstructorArgValue(OAuth2LoginAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI); } BeanDefinitionBuilder oauth2LoginAuthenticationProviderBuilder = BeanDefinitionBuilder .rootBeanDefinition(OAuth2LoginAuthenticationProvider.class) - .addConstructorArgValue(accessTokenResponseClient) - .addConstructorArgValue(oauth2UserService); + .addConstructorArgValue(accessTokenResponseClient).addConstructorArgValue(oauth2UserService); String userAuthoritiesMapperRef = element.getAttribute(ATT_USER_AUTHORITIES_MAPPER_REF); if (!StringUtils.isEmpty(userAuthoritiesMapperRef)) { - oauth2LoginAuthenticationProviderBuilder.addPropertyReference("authoritiesMapper", userAuthoritiesMapperRef); + oauth2LoginAuthenticationProviderBuilder.addPropertyReference("authoritiesMapper", + userAuthoritiesMapperRef); } oauth2LoginAuthenticationProvider = oauth2LoginAuthenticationProviderBuilder.getBeanDefinition(); - oauth2LoginOidcAuthenticationProvider = getOidcAuthProvider( - element, accessTokenResponseClient, userAuthoritiesMapperRef); + oauth2LoginOidcAuthenticationProvider = getOidcAuthProvider(element, accessTokenResponseClient, + userAuthoritiesMapperRef); BeanDefinitionBuilder oauth2AuthorizationRequestRedirectFilterBuilder = BeanDefinitionBuilder .rootBeanDefinition(OAuth2AuthorizationRequestRedirectFilter.class); String authorizationRequestResolverRef = element.getAttribute(ATT_AUTHORIZATION_REQUEST_RESOLVER_REF); if (!StringUtils.isEmpty(authorizationRequestResolverRef)) { - oauth2AuthorizationRequestRedirectFilterBuilder - .addConstructorArgReference(authorizationRequestResolverRef); - } else { + oauth2AuthorizationRequestRedirectFilterBuilder.addConstructorArgReference(authorizationRequestResolverRef); + } + else { oauth2AuthorizationRequestRedirectFilterBuilder.addConstructorArgValue(clientRegistrationRepository); } @@ -199,7 +216,8 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { if (!StringUtils.isEmpty(authenticationSuccessHandlerRef)) { oauth2LoginAuthenticationFilterBuilder.addPropertyReference("authenticationSuccessHandler", authenticationSuccessHandlerRef); - } else { + } + else { BeanDefinitionBuilder successHandlerBuilder = BeanDefinitionBuilder.rootBeanDefinition( "org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler") .addPropertyValue("requestCache", requestCache); @@ -211,17 +229,15 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { if (!StringUtils.isEmpty(loginPage)) { WebConfigUtils.validateHttpRedirect(loginPage, parserContext, source); oauth2LoginAuthenticationEntryPoint = BeanDefinitionBuilder - .rootBeanDefinition(LoginUrlAuthenticationEntryPoint.class) - .addConstructorArgValue(loginPage) - .addPropertyValue("portMapper", portMapper) - .addPropertyValue("portResolver", portResolver) + .rootBeanDefinition(LoginUrlAuthenticationEntryPoint.class).addConstructorArgValue(loginPage) + .addPropertyValue("portMapper", portMapper).addPropertyValue("portResolver", portResolver) .getBeanDefinition(); - } else { + } + else { Map entryPoint = getLoginEntryPoint(element); if (entryPoint != null) { oauth2LoginAuthenticationEntryPoint = BeanDefinitionBuilder - .rootBeanDefinition(DelegatingAuthenticationEntryPoint.class) - .addConstructorArgValue(entryPoint) + .rootBeanDefinition(DelegatingAuthenticationEntryPoint.class).addConstructorArgValue(entryPoint) .addPropertyValue("defaultEntryPoint", new LoginUrlAuthenticationEntryPoint(DEFAULT_LOGIN_URI)) .getBeanDefinition(); } @@ -231,7 +247,8 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { if (!StringUtils.isEmpty(authenticationFailureHandlerRef)) { oauth2LoginAuthenticationFilterBuilder.addPropertyReference("authenticationFailureHandler", authenticationFailureHandlerRef); - } else { + } + else { BeanDefinitionBuilder failureHandlerBuilder = BeanDefinitionBuilder.rootBeanDefinition( "org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"); failureHandlerBuilder.addConstructorArgValue( @@ -253,7 +270,8 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { String authorizationRequestRepositoryRef = element.getAttribute(ATT_AUTHORIZATION_REQUEST_REPOSITORY_REF); if (!StringUtils.isEmpty(authorizationRequestRepositoryRef)) { authorizationRequestRepository = new RuntimeBeanReference(authorizationRequestRepositoryRef); - } else { + } + else { authorizationRequestRepository = BeanDefinitionBuilder.rootBeanDefinition( "org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository") .getBeanDefinition(); @@ -261,11 +279,11 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { return authorizationRequestRepository; } - private BeanDefinition getOidcAuthProvider(Element element, - BeanMetadataElement accessTokenResponseClient, String userAuthoritiesMapperRef) { + private BeanDefinition getOidcAuthProvider(Element element, BeanMetadataElement accessTokenResponseClient, + String userAuthoritiesMapperRef) { - boolean oidcAuthenticationProviderEnabled = ClassUtils.isPresent( - "org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader()); + boolean oidcAuthenticationProviderEnabled = ClassUtils + .isPresent("org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader()); if (!oidcAuthenticationProviderEnabled) { return BeanDefinitionBuilder.rootBeanDefinition(OidcAuthenticationRequestChecker.class).getBeanDefinition(); } @@ -274,8 +292,7 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { BeanDefinitionBuilder oidcAuthProviderBuilder = BeanDefinitionBuilder.rootBeanDefinition( "org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider") - .addConstructorArgValue(accessTokenResponseClient) - .addConstructorArgValue(oidcUserService); + .addConstructorArgValue(accessTokenResponseClient).addConstructorArgValue(oidcUserService); if (!StringUtils.isEmpty(userAuthoritiesMapperRef)) { oidcAuthProviderBuilder.addPropertyReference("authoritiesMapper", userAuthoritiesMapperRef); @@ -294,7 +311,8 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { String oidcUserServiceRef = element.getAttribute(ATT_OIDC_USER_SERVICE_REF); if (!StringUtils.isEmpty(oidcUserServiceRef)) { oidcUserService = new RuntimeBeanReference(oidcUserServiceRef); - } else { + } + else { oidcUserService = BeanDefinitionBuilder .rootBeanDefinition("org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService") .getBeanDefinition(); @@ -307,7 +325,8 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { String oauth2UserServiceRef = element.getAttribute(ATT_USER_SERVICE_REF); if (!StringUtils.isEmpty(oauth2UserServiceRef)) { oauth2UserService = new RuntimeBeanReference(oauth2UserServiceRef); - } else { + } + else { oauth2UserService = BeanDefinitionBuilder .rootBeanDefinition("org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService") .getBeanDefinition(); @@ -320,7 +339,8 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { String accessTokenResponseClientRef = element.getAttribute(ATT_ACCESS_TOKEN_RESPONSE_CLIENT_REF); if (!StringUtils.isEmpty(accessTokenResponseClientRef)) { accessTokenResponseClient = new RuntimeBeanReference(accessTokenResponseClientRef); - } else { + } + else { accessTokenResponseClient = BeanDefinitionBuilder.rootBeanDefinition( "org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient") .getBeanDefinition(); @@ -417,6 +437,7 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { public boolean supports(Class authentication) { return OAuth2LoginAuthenticationToken.class.isAssignableFrom(authentication); } + } /** @@ -452,5 +473,7 @@ final class OAuth2LoginBeanDefinitionParser implements BeanDefinitionParser { return loginUrlToClientName; } + } + } diff --git a/config/src/main/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParser.java index 5068a74b45..326fc70713 100644 --- a/config/src/main/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParser.java @@ -52,12 +52,14 @@ import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; /** - * A {@link BeanDefinitionParser} for <http>'s <oauth2-resource-server> element. + * A {@link BeanDefinitionParser} for <http>'s <oauth2-resource-server> + * element. * * @since 5.3 * @author Josh Cummings */ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionParser { + static final String AUTHENTICATION_MANAGER_RESOLVER_REF = "authentication-manager-resolver-ref"; static final String BEARER_TOKEN_RESOLVER_REF = "bearer-token-resolver-ref"; static final String ENTRY_POINT_REF = "entry-point-ref"; @@ -66,21 +68,23 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa static final String AUTHENTICATION_ENTRY_POINT = "authenticationEntryPoint"; private final BeanReference authenticationManager; + private final List authenticationProviders; + private final Map entryPoints; + private final Map deniedHandlers; + private final List ignoreCsrfRequestMatchers; - private final BeanDefinition authenticationEntryPoint = - new RootBeanDefinition(BearerTokenAuthenticationEntryPoint.class); - private final BeanDefinition accessDeniedHandler = - new RootBeanDefinition(BearerTokenAccessDeniedHandler.class); + private final BeanDefinition authenticationEntryPoint = new RootBeanDefinition( + BearerTokenAuthenticationEntryPoint.class); + + private final BeanDefinition accessDeniedHandler = new RootBeanDefinition(BearerTokenAccessDeniedHandler.class); OAuth2ResourceServerBeanDefinitionParser(BeanReference authenticationManager, - List authenticationProviders, - Map entryPoints, - Map deniedHandlers, - List ignoreCsrfRequestMatchers) { + List authenticationProviders, Map entryPoints, + Map deniedHandlers, List ignoreCsrfRequestMatchers) { this.authenticationManager = authenticationManager; this.authenticationProviders = authenticationProviders; this.entryPoints = entryPoints; @@ -91,10 +95,10 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa /** * Parse a <oauth2-resource-server> element and return the corresponding * {@link BearerTokenAuthenticationFilter} - * * @param oauth2ResourceServer the <oauth2-resource-server> element. * @param pc the {@link ParserContext} - * @return a {@link BeanDefinition} representing a {@link BearerTokenAuthenticationFilter} definition + * @return a {@link BeanDefinition} representing a + * {@link BearerTokenAuthenticationFilter} definition */ @Override public BeanDefinition parse(Element oauth2ResourceServer, ParserContext pc) { @@ -104,17 +108,16 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa validateConfiguration(oauth2ResourceServer, jwt, opaqueToken, pc); if (jwt != null) { - BeanDefinition jwtAuthenticationProvider = - new JwtBeanDefinitionParser().parse(jwt, pc); - this.authenticationProviders.add(new RuntimeBeanReference - (pc.getReaderContext().registerWithGeneratedName(jwtAuthenticationProvider))); + BeanDefinition jwtAuthenticationProvider = new JwtBeanDefinitionParser().parse(jwt, pc); + this.authenticationProviders.add(new RuntimeBeanReference( + pc.getReaderContext().registerWithGeneratedName(jwtAuthenticationProvider))); } if (opaqueToken != null) { - BeanDefinition opaqueTokenAuthenticationProvider = - new OpaqueTokenBeanDefinitionParser().parse(opaqueToken, pc); - this.authenticationProviders.add(new RuntimeBeanReference - (pc.getReaderContext().registerWithGeneratedName(opaqueTokenAuthenticationProvider))); + BeanDefinition opaqueTokenAuthenticationProvider = new OpaqueTokenBeanDefinitionParser().parse(opaqueToken, + pc); + this.authenticationProviders.add(new RuntimeBeanReference( + pc.getReaderContext().registerWithGeneratedName(opaqueTokenAuthenticationProvider))); } BeanMetadataElement bearerTokenResolver = getBearerTokenResolver(oauth2ResourceServer); @@ -141,23 +144,23 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa void validateConfiguration(Element oauth2ResourceServer, Element jwt, Element opaqueToken, ParserContext pc) { if (!oauth2ResourceServer.hasAttribute(AUTHENTICATION_MANAGER_RESOLVER_REF)) { if (jwt == null && opaqueToken == null) { - pc.getReaderContext().error - ("Didn't find authentication-manager-resolver-ref, , or . " + - "Please select one.", oauth2ResourceServer); + pc.getReaderContext() + .error("Didn't find authentication-manager-resolver-ref, , or . " + + "Please select one.", oauth2ResourceServer); } return; } if (jwt != null) { - pc.getReaderContext().error - ("Found as well as authentication-manager-resolver-ref. " + - "Please select just one.", oauth2ResourceServer); + pc.getReaderContext().error( + "Found as well as authentication-manager-resolver-ref. " + "Please select just one.", + oauth2ResourceServer); } if (opaqueToken != null) { - pc.getReaderContext().error - ("Found as well as authentication-manager-resolver-ref. " + - "Please select just one.", oauth2ResourceServer); + pc.getReaderContext().error( + "Found as well as authentication-manager-resolver-ref. " + "Please select just one.", + oauth2ResourceServer); } } @@ -176,7 +179,8 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa String bearerTokenResolverRef = element.getAttribute(BEARER_TOKEN_RESOLVER_REF); if (StringUtils.isEmpty(bearerTokenResolverRef)) { return new RootBeanDefinition(DefaultBearerTokenResolver.class); - } else { + } + else { return new RuntimeBeanReference(bearerTokenResolverRef); } } @@ -185,13 +189,16 @@ final class OAuth2ResourceServerBeanDefinitionParser implements BeanDefinitionPa String entryPointRef = element.getAttribute(ENTRY_POINT_REF); if (StringUtils.isEmpty(entryPointRef)) { return this.authenticationEntryPoint; - } else { + } + else { return new RuntimeBeanReference(entryPointRef); } } + } final class JwtBeanDefinitionParser implements BeanDefinitionParser { + static final String DECODER_REF = "decoder-ref"; static final String JWK_SET_URI = "jwk-set-uri"; static final String JWT_AUTHENTICATION_CONVERTER_REF = "jwt-authentication-converter-ref"; @@ -201,8 +208,8 @@ final class JwtBeanDefinitionParser implements BeanDefinitionParser { public BeanDefinition parse(Element element, ParserContext pc) { validateConfiguration(element, pc); - BeanDefinitionBuilder jwtProviderBuilder = - BeanDefinitionBuilder.rootBeanDefinition(JwtAuthenticationProvider.class); + BeanDefinitionBuilder jwtProviderBuilder = BeanDefinitionBuilder + .rootBeanDefinition(JwtAuthenticationProvider.class); jwtProviderBuilder.addConstructorArgValue(getDecoder(element)); jwtProviderBuilder.addPropertyValue(JWT_AUTHENTICATION_CONVERTER, getJwtAuthenticationConverter(element)); @@ -214,8 +221,7 @@ final class JwtBeanDefinitionParser implements BeanDefinitionParser { boolean usesJwkSetUri = element.hasAttribute(JWK_SET_URI); if (usesDecoder == usesJwkSetUri) { - pc.getReaderContext().error - ("Please specify either decoder-ref or jwk-set-uri.", element); + pc.getReaderContext().error("Please specify either decoder-ref or jwk-set-uri.", element); } } @@ -240,10 +246,13 @@ final class JwtBeanDefinitionParser implements BeanDefinitionParser { return new JwtAuthenticationConverter(); } - JwtBeanDefinitionParser() {} + JwtBeanDefinitionParser() { + } + } final class OpaqueTokenBeanDefinitionParser implements BeanDefinitionParser { + static final String INTROSPECTOR_REF = "introspector-ref"; static final String INTROSPECTION_URI = "introspection-uri"; static final String CLIENT_ID = "client-id"; @@ -254,8 +263,8 @@ final class OpaqueTokenBeanDefinitionParser implements BeanDefinitionParser { validateConfiguration(element, pc); BeanMetadataElement introspector = getIntrospector(element); - BeanDefinitionBuilder opaqueTokenProviderBuilder = - BeanDefinitionBuilder.rootBeanDefinition(OpaqueTokenAuthenticationProvider.class); + BeanDefinitionBuilder opaqueTokenProviderBuilder = BeanDefinitionBuilder + .rootBeanDefinition(OpaqueTokenAuthenticationProvider.class); opaqueTokenProviderBuilder.addConstructorArgValue(introspector); return opaqueTokenProviderBuilder.getBeanDefinition(); @@ -263,23 +272,20 @@ final class OpaqueTokenBeanDefinitionParser implements BeanDefinitionParser { void validateConfiguration(Element element, ParserContext pc) { boolean usesIntrospector = element.hasAttribute(INTROSPECTOR_REF); - boolean usesEndpoint = element.hasAttribute(INTROSPECTION_URI) || - element.hasAttribute(CLIENT_ID) || - element.hasAttribute(CLIENT_SECRET); + boolean usesEndpoint = element.hasAttribute(INTROSPECTION_URI) || element.hasAttribute(CLIENT_ID) + || element.hasAttribute(CLIENT_SECRET); if (usesIntrospector == usesEndpoint) { - pc.getReaderContext().error - ("Please specify either introspector-ref or all of " + - "introspection-uri, client-id, and client-secret.", element); + pc.getReaderContext().error("Please specify either introspector-ref or all of " + + "introspection-uri, client-id, and client-secret.", element); return; } if (usesEndpoint) { - if (!(element.hasAttribute(INTROSPECTION_URI) && - element.hasAttribute(CLIENT_ID) && - element.hasAttribute(CLIENT_SECRET))) { - pc.getReaderContext().error - ("Please specify introspection-uri, client-id, and client-secret together", element); + if (!(element.hasAttribute(INTROSPECTION_URI) && element.hasAttribute(CLIENT_ID) + && element.hasAttribute(CLIENT_SECRET))) { + pc.getReaderContext().error("Please specify introspection-uri, client-id, and client-secret together", + element); } } } @@ -303,11 +309,13 @@ final class OpaqueTokenBeanDefinitionParser implements BeanDefinitionParser { return introspectorBuilder.getBeanDefinition(); } - OpaqueTokenBeanDefinitionParser() {} + OpaqueTokenBeanDefinitionParser() { + } + } -final class StaticAuthenticationManagerResolver implements - AuthenticationManagerResolver { +final class StaticAuthenticationManagerResolver implements AuthenticationManagerResolver { + private final AuthenticationManager authenticationManager; StaticAuthenticationManagerResolver(AuthenticationManager authenticationManager) { @@ -318,9 +326,11 @@ final class StaticAuthenticationManagerResolver implements public AuthenticationManager resolve(HttpServletRequest context) { return this.authenticationManager; } + } final class NimbusJwtDecoderJwkSetUriFactoryBean implements FactoryBean { + private final String jwkSetUri; NimbusJwtDecoderJwkSetUriFactoryBean(String jwkSetUri) { @@ -336,9 +346,11 @@ final class NimbusJwtDecoderJwkSetUriFactoryBean implements FactoryBean getObjectType() { return JwtDecoder.class; } + } final class BearerTokenRequestMatcher implements RequestMatcher { + private final BearerTokenResolver bearerTokenResolver; BearerTokenRequestMatcher(BearerTokenResolver bearerTokenResolver) { @@ -350,9 +362,10 @@ final class BearerTokenRequestMatcher implements RequestMatcher { public boolean matches(HttpServletRequest request) { try { return this.bearerTokenResolver.resolve(request) != null; - } catch (OAuth2AuthenticationException e) { + } + catch (OAuth2AuthenticationException e) { return false; } } -} +} diff --git a/config/src/main/java/org/springframework/security/config/http/PortMappingsBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/PortMappingsBeanDefinitionParser.java index 4dd13b82d9..b5ff1c4e1d 100644 --- a/config/src/main/java/org/springframework/security/config/http/PortMappingsBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/PortMappingsBeanDefinitionParser.java @@ -36,7 +36,9 @@ import org.w3c.dom.Element; * @author Luke Taylor */ class PortMappingsBeanDefinitionParser implements BeanDefinitionParser { + public static final String ATT_HTTP_PORT = "http"; + public static final String ATT_HTTPS_PORT = "https"; @SuppressWarnings("unchecked") @@ -45,11 +47,9 @@ class PortMappingsBeanDefinitionParser implements BeanDefinitionParser { portMapper.setSource(parserContext.extractSource(element)); if (element != null) { - List mappingElts = DomUtils.getChildElementsByTagName(element, - Elements.PORT_MAPPING); + List mappingElts = DomUtils.getChildElementsByTagName(element, Elements.PORT_MAPPING); if (mappingElts.isEmpty()) { - parserContext.getReaderContext().error( - "No port-mapping child elements specified", element); + parserContext.getReaderContext().error("No port-mapping child elements specified", element); } Map mappings = new ManagedMap(); @@ -59,13 +59,11 @@ class PortMappingsBeanDefinitionParser implements BeanDefinitionParser { String httpsPort = elt.getAttribute(ATT_HTTPS_PORT); if (!StringUtils.hasText(httpPort)) { - parserContext.getReaderContext().error( - "No http port supplied in port mapping", elt); + parserContext.getReaderContext().error("No http port supplied in port mapping", elt); } if (!StringUtils.hasText(httpsPort)) { - parserContext.getReaderContext().error( - "No https port supplied in port mapping", elt); + parserContext.getReaderContext().error("No https port supplied in port mapping", elt); } mappings.put(httpPort, httpsPort); @@ -76,4 +74,5 @@ class PortMappingsBeanDefinitionParser implements BeanDefinitionParser { return portMapper; } + } diff --git a/config/src/main/java/org/springframework/security/config/http/RememberMeBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/RememberMeBeanDefinitionParser.java index 0fbb14c9bc..d9866bfdb3 100644 --- a/config/src/main/java/org/springframework/security/config/http/RememberMeBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/RememberMeBeanDefinitionParser.java @@ -41,6 +41,7 @@ import org.w3c.dom.Element; * @author Oliver Becker */ class RememberMeBeanDefinitionParser implements BeanDefinitionParser { + static final String ATT_DATA_SOURCE = "data-source-ref"; static final String ATT_SERVICES_REF = "services-ref"; static final String ATT_SERVICES_ALIAS = "services-alias"; @@ -53,8 +54,11 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_REMEMBERME_COOKIE = "remember-me-cookie"; protected final Log logger = LogFactory.getLog(getClass()); + private final String key; + private final BeanReference authenticationManager; + private String rememberMeServicesId; RememberMeBeanDefinitionParser(String key, BeanReference authenticationManager) { @@ -63,8 +67,8 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser { } public BeanDefinition parse(Element element, ParserContext pc) { - CompositeComponentDefinition compositeDef = new CompositeComponentDefinition( - element.getTagName(), pc.extractSource(element)); + CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), + pc.extractSource(element)); pc.pushContainingComponent(compositeDef); String tokenRepository = element.getAttribute(ATT_TOKEN_REPOSITORY); @@ -89,37 +93,33 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser { boolean remembermeParameterSet = StringUtils.hasText(remembermeParameter); boolean remembermeCookieSet = StringUtils.hasText(remembermeCookie); - if (servicesRefSet - && (dataSourceSet || tokenRepoSet || userServiceSet || tokenValiditySet - || useSecureCookieSet || remembermeParameterSet || remembermeCookieSet)) { - pc.getReaderContext().error( - ATT_SERVICES_REF + " can't be used in combination with attributes " - + ATT_TOKEN_REPOSITORY + "," + ATT_DATA_SOURCE + ", " - + ATT_USER_SERVICE_REF + ", " + ATT_TOKEN_VALIDITY + ", " - + ATT_SECURE_COOKIE + ", " + ATT_FORM_REMEMBERME_PARAMETER - + " or " + ATT_REMEMBERME_COOKIE, source); + if (servicesRefSet && (dataSourceSet || tokenRepoSet || userServiceSet || tokenValiditySet || useSecureCookieSet + || remembermeParameterSet || remembermeCookieSet)) { + pc.getReaderContext() + .error(ATT_SERVICES_REF + " can't be used in combination with attributes " + ATT_TOKEN_REPOSITORY + + "," + ATT_DATA_SOURCE + ", " + ATT_USER_SERVICE_REF + ", " + ATT_TOKEN_VALIDITY + ", " + + ATT_SECURE_COOKIE + ", " + ATT_FORM_REMEMBERME_PARAMETER + " or " + ATT_REMEMBERME_COOKIE, + source); } if (dataSourceSet && tokenRepoSet) { - pc.getReaderContext().error( - "Specify " + ATT_TOKEN_REPOSITORY + " or " + ATT_DATA_SOURCE - + " but not both", source); + pc.getReaderContext().error("Specify " + ATT_TOKEN_REPOSITORY + " or " + ATT_DATA_SOURCE + " but not both", + source); } boolean isPersistent = dataSourceSet | tokenRepoSet; if (isPersistent) { Object tokenRepo; - services = new RootBeanDefinition( - PersistentTokenBasedRememberMeServices.class); + services = new RootBeanDefinition(PersistentTokenBasedRememberMeServices.class); if (tokenRepoSet) { tokenRepo = new RuntimeBeanReference(tokenRepository); } else { tokenRepo = new RootBeanDefinition(JdbcTokenRepositoryImpl.class); - ((BeanDefinition) tokenRepo).getPropertyValues().addPropertyValue( - "dataSource", new RuntimeBeanReference(dataSource)); + ((BeanDefinition) tokenRepo).getPropertyValues().addPropertyValue("dataSource", + new RuntimeBeanReference(dataSource)); } services.getConstructorArgumentValues().addIndexedArgumentValue(2, tokenRepo); } @@ -141,30 +141,24 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser { // PersistentTokenBasedRememberMeServices if (useSecureCookieSet) { - services.getPropertyValues().addPropertyValue("useSecureCookie", - Boolean.valueOf(useSecureCookie)); + services.getPropertyValues().addPropertyValue("useSecureCookie", Boolean.valueOf(useSecureCookie)); } if (tokenValiditySet) { boolean isTokenValidityNegative = tokenValiditySeconds.startsWith("-"); if (isTokenValidityNegative && isPersistent) { - pc.getReaderContext().error( - ATT_TOKEN_VALIDITY + " cannot be negative if using" - + " a persistent remember-me token repository", - source); + pc.getReaderContext().error(ATT_TOKEN_VALIDITY + " cannot be negative if using" + + " a persistent remember-me token repository", source); } - services.getPropertyValues().addPropertyValue("tokenValiditySeconds", - tokenValiditySeconds); + services.getPropertyValues().addPropertyValue("tokenValiditySeconds", tokenValiditySeconds); } if (remembermeParameterSet) { - services.getPropertyValues().addPropertyValue("parameter", - remembermeParameter); + services.getPropertyValues().addPropertyValue("parameter", remembermeParameter); } if (remembermeCookieSet) { - services.getPropertyValues().addPropertyValue("cookieName", - remembermeCookie); + services.getPropertyValues().addPropertyValue("cookieName", remembermeCookie); } services.setSource(source); @@ -176,14 +170,12 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser { } if (StringUtils.hasText(element.getAttribute(ATT_SERVICES_ALIAS))) { - pc.getRegistry().registerAlias(servicesName, - element.getAttribute(ATT_SERVICES_ALIAS)); + pc.getRegistry().registerAlias(servicesName, element.getAttribute(ATT_SERVICES_ALIAS)); } this.rememberMeServicesId = servicesName; - BeanDefinitionBuilder filter = BeanDefinitionBuilder - .rootBeanDefinition(RememberMeAuthenticationFilter.class); + BeanDefinitionBuilder filter = BeanDefinitionBuilder.rootBeanDefinition(RememberMeAuthenticationFilter.class); filter.getRawBeanDefinition().setSource(source); if (StringUtils.hasText(successHandlerRef)) { @@ -201,4 +193,5 @@ class RememberMeBeanDefinitionParser implements BeanDefinitionParser { String getRememberMeServicesId() { return this.rememberMeServicesId; } + } diff --git a/config/src/main/java/org/springframework/security/config/http/SecurityFilters.java b/config/src/main/java/org/springframework/security/config/http/SecurityFilters.java index ee6f366d48..b858c44054 100644 --- a/config/src/main/java/org/springframework/security/config/http/SecurityFilters.java +++ b/config/src/main/java/org/springframework/security/config/http/SecurityFilters.java @@ -15,8 +15,6 @@ */ package org.springframework.security.config.http; -import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter; - /** * Stores the default order numbers of all Spring Security filters for use in * configuration. @@ -26,43 +24,77 @@ import org.springframework.security.web.context.request.async.WebAsyncManagerInt */ enum SecurityFilters { + FIRST(Integer.MIN_VALUE), + CHANNEL_FILTER, + SECURITY_CONTEXT_FILTER, + CONCURRENT_SESSION_FILTER, - WEB_ASYNC_MANAGER_FILTER /** {@link WebAsyncManagerIntegrationFilter} */, - HEADERS_FILTER, CORS_FILTER, + + WEB_ASYNC_MANAGER_FILTER, + + HEADERS_FILTER, + + CORS_FILTER, + CSRF_FILTER, + LOGOUT_FILTER, + OAUTH2_AUTHORIZATION_REQUEST_FILTER, + X509_FILTER, + PRE_AUTH_FILTER, + CAS_FILTER, + OAUTH2_LOGIN_FILTER, + FORM_LOGIN_FILTER, + OPENID_FILTER, + LOGIN_PAGE_FILTER, + LOGOUT_PAGE_FILTER, + DIGEST_AUTH_FILTER, + BEARER_TOKEN_AUTH_FILTER, + BASIC_AUTH_FILTER, + REQUEST_CACHE_FILTER, + SERVLET_API_SUPPORT_FILTER, + JAAS_API_SUPPORT_FILTER, + REMEMBER_ME_FILTER, + ANONYMOUS_FILTER, + OAUTH2_AUTHORIZATION_CODE_GRANT_FILTER, + SESSION_MANAGEMENT_FILTER, + EXCEPTION_TRANSLATION_FILTER, + FILTER_SECURITY_INTERCEPTOR, + SWITCH_USER_FILTER, + LAST(Integer.MAX_VALUE); private static final int INTERVAL = 100; + private final int order; SecurityFilters() { - order = ordinal() * INTERVAL; + this.order = ordinal() * INTERVAL; } SecurityFilters(int order) { @@ -70,6 +102,7 @@ enum SecurityFilters { } public int getOrder() { - return order; + return this.order; } + } diff --git a/config/src/main/java/org/springframework/security/config/http/SessionCreationPolicy.java b/config/src/main/java/org/springframework/security/config/http/SessionCreationPolicy.java index fc1f2636b2..314a8cddc3 100644 --- a/config/src/main/java/org/springframework/security/config/http/SessionCreationPolicy.java +++ b/config/src/main/java/org/springframework/security/config/http/SessionCreationPolicy.java @@ -26,6 +26,7 @@ import org.springframework.security.core.context.SecurityContext; * @since 3.1 */ public enum SessionCreationPolicy { + /** Always create an {@link HttpSession} */ ALWAYS, /** @@ -40,4 +41,5 @@ public enum SessionCreationPolicy { * to obtain the {@link SecurityContext} */ STATELESS + } diff --git a/config/src/main/java/org/springframework/security/config/http/UserDetailsServiceFactoryBean.java b/config/src/main/java/org/springframework/security/config/http/UserDetailsServiceFactoryBean.java index d7e18b7dae..2f1c56a27c 100644 --- a/config/src/main/java/org/springframework/security/config/http/UserDetailsServiceFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/http/UserDetailsServiceFactoryBean.java @@ -54,8 +54,7 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware { return getUserDetailsService(); } // Overwrite with the caching version if available - String cachingId = id - + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX; + String cachingId = id + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX; if (beanFactory.containsBeanDefinition(cachingId)) { return (UserDetailsService) beanFactory.getBean(cachingId); @@ -73,9 +72,8 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware { if (!beans.isEmpty()) { if (beans.size() > 1) { - throw new ApplicationContextException( - "More than one AuthenticationUserDetailsService registered." - + " Please use a specific Id reference."); + throw new ApplicationContextException("More than one AuthenticationUserDetailsService registered." + + " Please use a specific Id reference."); } return (AuthenticationUserDetailsService) beans.values().toArray()[0]; } @@ -96,9 +94,8 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware { } } else { - throw new ApplicationContextException("Bean '" + name - + "' must be a UserDetailsService or an" - + " AuthenticationUserDetailsService"); + throw new ApplicationContextException( + "Bean '" + name + "' must be a UserDetailsService or an" + " AuthenticationUserDetailsService"); } } @@ -122,16 +119,14 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware { } else if (beans.size() > 1) { - throw new ApplicationContextException( - "More than one UserDetailsService registered. Please " - + "use a specific Id reference in or elements."); + throw new ApplicationContextException("More than one UserDetailsService registered. Please " + + "use a specific Id reference in or elements."); } return (UserDetailsService) beans.values().toArray()[0]; } - public void setApplicationContext(ApplicationContext beanFactory) - throws BeansException { + public void setApplicationContext(ApplicationContext beanFactory) throws BeansException { this.beanFactory = beanFactory; } diff --git a/config/src/main/java/org/springframework/security/config/http/WebConfigUtils.java b/config/src/main/java/org/springframework/security/config/http/WebConfigUtils.java index ea53d9dc82..d590b88a55 100644 --- a/config/src/main/java/org/springframework/security/config/http/WebConfigUtils.java +++ b/config/src/main/java/org/springframework/security/config/http/WebConfigUtils.java @@ -46,13 +46,11 @@ abstract class WebConfigUtils { * SpEL), "/" or "http" it will raise an error. */ static void validateHttpRedirect(String url, ParserContext pc, Object source) { - if (!StringUtils.hasText(url) || UrlUtils.isValidRedirectUrl(url) - || url.startsWith("$") || url.startsWith("#")) { + if (!StringUtils.hasText(url) || UrlUtils.isValidRedirectUrl(url) || url.startsWith("$") + || url.startsWith("#")) { return; } - pc.getReaderContext().warning( - url + " is not a valid redirect URL (must start with '/' or http(s))", - source); + pc.getReaderContext().warning(url + " is not a valid redirect URL (must start with '/' or http(s))", source); } } diff --git a/config/src/main/java/org/springframework/security/config/http/package-info.java b/config/src/main/java/org/springframework/security/config/http/package-info.java index 654cd0d372..aa327d361e 100644 --- a/config/src/main/java/org/springframework/security/config/http/package-info.java +++ b/config/src/main/java/org/springframework/security/config/http/package-info.java @@ -17,4 +17,3 @@ * Parsing of the <http> namespace element. */ package org.springframework.security.config.http; - diff --git a/config/src/main/java/org/springframework/security/config/ldap/ContextSourceSettingPostProcessor.java b/config/src/main/java/org/springframework/security/config/ldap/ContextSourceSettingPostProcessor.java index a55523d04f..a031988e83 100644 --- a/config/src/main/java/org/springframework/security/config/ldap/ContextSourceSettingPostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/ldap/ContextSourceSettingPostProcessor.java @@ -35,6 +35,7 @@ import org.springframework.util.ClassUtils; * @since 3.0 */ class ContextSourceSettingPostProcessor implements BeanFactoryPostProcessor, Ordered { + private static final String REQUIRED_CONTEXT_SOURCE_CLASS_NAME = "org.springframework.ldap.core.support.BaseLdapPathContextSource"; /** @@ -43,8 +44,7 @@ class ContextSourceSettingPostProcessor implements BeanFactoryPostProcessor, Ord */ private boolean defaultNameRequired; - public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) - throws BeansException { + public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException { Class contextSourceClass; try { @@ -52,31 +52,24 @@ class ContextSourceSettingPostProcessor implements BeanFactoryPostProcessor, Ord ClassUtils.getDefaultClassLoader()); } catch (ClassNotFoundException e) { - throw new ApplicationContextException( - "Couldn't locate: " - + REQUIRED_CONTEXT_SOURCE_CLASS_NAME - + ". " - + " If you are using LDAP with Spring Security, please ensure that you include the spring-ldap " - + "jar file in your application", e); + throw new ApplicationContextException("Couldn't locate: " + REQUIRED_CONTEXT_SOURCE_CLASS_NAME + ". " + + " If you are using LDAP with Spring Security, please ensure that you include the spring-ldap " + + "jar file in your application", e); } String[] sources = bf.getBeanNamesForType(contextSourceClass, false, false); if (sources.length == 0) { - throw new ApplicationContextException( - "No BaseLdapPathContextSource instances found. Have you " - + "added an <" + Elements.LDAP_SERVER - + " /> element to your application context? If you have " - + "declared an explicit bean, do not use lazy-init"); + throw new ApplicationContextException("No BaseLdapPathContextSource instances found. Have you " + + "added an <" + Elements.LDAP_SERVER + " /> element to your application context? If you have " + + "declared an explicit bean, do not use lazy-init"); } if (!bf.containsBean(BeanIds.CONTEXT_SOURCE) && defaultNameRequired) { if (sources.length > 1) { - throw new ApplicationContextException( - "More than one BaseLdapPathContextSource instance found. " - + "Please specify a specific server id using the 'server-ref' attribute when configuring your <" - + Elements.LDAP_PROVIDER + "> " + "or <" - + Elements.LDAP_USER_SERVICE + ">."); + throw new ApplicationContextException("More than one BaseLdapPathContextSource instance found. " + + "Please specify a specific server id using the 'server-ref' attribute when configuring your <" + + Elements.LDAP_PROVIDER + "> " + "or <" + Elements.LDAP_USER_SERVICE + ">."); } bf.registerAlias(sources[0], BeanIds.CONTEXT_SOURCE); @@ -90,4 +83,5 @@ class ContextSourceSettingPostProcessor implements BeanFactoryPostProcessor, Ord public int getOrder() { return LOWEST_PRECEDENCE; } + } diff --git a/config/src/main/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParser.java index e2d86aab62..84f4f14d03 100644 --- a/config/src/main/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParser.java @@ -35,10 +35,13 @@ import org.w3c.dom.Element; * @since 2.0 */ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser { + private final Log logger = LogFactory.getLog(getClass()); private static final String ATT_USER_DN_PATTERN = "user-dn-pattern"; + private static final String ATT_USER_PASSWORD = "password-attribute"; + private static final String ATT_HASH = PasswordEncoderParser.ATT_HASH; private static final String DEF_USER_SEARCH_FILTER = "uid={0}"; @@ -48,11 +51,10 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser { static final String PASSWD_AUTH_CLASS = "org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator"; public BeanDefinition parse(Element elt, ParserContext parserContext) { - RuntimeBeanReference contextSource = LdapUserServiceBeanDefinitionParser - .parseServerReference(elt, parserContext); + RuntimeBeanReference contextSource = LdapUserServiceBeanDefinitionParser.parseServerReference(elt, + parserContext); - BeanDefinition searchBean = LdapUserServiceBeanDefinitionParser.parseSearchBean( - elt, parserContext); + BeanDefinition searchBean = LdapUserServiceBeanDefinitionParser.parseSearchBean(elt, parserContext); String userDnPattern = elt.getAttribute(ATT_USER_DN_PATTERN); String[] userDnPatternArray = new String[0]; @@ -73,41 +75,33 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser { searchBean = searchBeanBuilder.getBeanDefinition(); } - BeanDefinitionBuilder authenticatorBuilder = BeanDefinitionBuilder - .rootBeanDefinition(BIND_AUTH_CLASS); - Element passwordCompareElt = DomUtils.getChildElementByTagName(elt, - Elements.LDAP_PASSWORD_COMPARE); + BeanDefinitionBuilder authenticatorBuilder = BeanDefinitionBuilder.rootBeanDefinition(BIND_AUTH_CLASS); + Element passwordCompareElt = DomUtils.getChildElementByTagName(elt, Elements.LDAP_PASSWORD_COMPARE); if (passwordCompareElt != null) { - authenticatorBuilder = BeanDefinitionBuilder - .rootBeanDefinition(PASSWD_AUTH_CLASS); + authenticatorBuilder = BeanDefinitionBuilder.rootBeanDefinition(PASSWD_AUTH_CLASS); String passwordAttribute = passwordCompareElt.getAttribute(ATT_USER_PASSWORD); if (StringUtils.hasText(passwordAttribute)) { - authenticatorBuilder.addPropertyValue("passwordAttributeName", - passwordAttribute); + authenticatorBuilder.addPropertyValue("passwordAttributeName", passwordAttribute); } - Element passwordEncoderElement = DomUtils.getChildElementByTagName( - passwordCompareElt, Elements.PASSWORD_ENCODER); + Element passwordEncoderElement = DomUtils.getChildElementByTagName(passwordCompareElt, + Elements.PASSWORD_ENCODER); String hash = passwordCompareElt.getAttribute(ATT_HASH); if (passwordEncoderElement != null) { if (StringUtils.hasText(hash)) { parserContext.getReaderContext().warning( - "Attribute 'hash' cannot be used with 'password-encoder' and " - + "will be ignored.", + "Attribute 'hash' cannot be used with 'password-encoder' and " + "will be ignored.", parserContext.extractSource(elt)); } - PasswordEncoderParser pep = new PasswordEncoderParser( - passwordEncoderElement, parserContext); - authenticatorBuilder.addPropertyValue("passwordEncoder", - pep.getPasswordEncoder()); + PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElement, parserContext); + authenticatorBuilder.addPropertyValue("passwordEncoder", pep.getPasswordEncoder()); } else if (StringUtils.hasText(hash)) { authenticatorBuilder.addPropertyValue("passwordEncoder", - PasswordEncoderParser.createPasswordEncoderBeanDefinition(hash, - false)); + PasswordEncoderParser.createPasswordEncoderBeanDefinition(hash, false)); } } @@ -118,15 +112,14 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser { authenticatorBuilder.addPropertyValue("userSearch", searchBean); } - BeanDefinitionBuilder ldapProvider = BeanDefinitionBuilder - .rootBeanDefinition(PROVIDER_CLASS); + BeanDefinitionBuilder ldapProvider = BeanDefinitionBuilder.rootBeanDefinition(PROVIDER_CLASS); ldapProvider.addConstructorArgValue(authenticatorBuilder.getBeanDefinition()); - ldapProvider.addConstructorArgValue(LdapUserServiceBeanDefinitionParser - .parseAuthoritiesPopulator(elt, parserContext)); + ldapProvider.addConstructorArgValue( + LdapUserServiceBeanDefinitionParser.parseAuthoritiesPopulator(elt, parserContext)); ldapProvider.addPropertyValue("userDetailsContextMapper", - LdapUserServiceBeanDefinitionParser.parseUserDetailsClassOrUserMapperRef( - elt, parserContext)); + LdapUserServiceBeanDefinitionParser.parseUserDetailsClassOrUserMapperRef(elt, parserContext)); return ldapProvider.getBeanDefinition(); } + } diff --git a/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java index cbdda20de6..0ca5bb99ae 100644 --- a/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java @@ -42,6 +42,7 @@ import org.springframework.util.StringUtils; * @author Evgeniy Cheban */ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { + private static final String CONTEXT_SOURCE_CLASS = "org.springframework.security.ldap.DefaultSpringSecurityContextSource"; /** @@ -51,29 +52,37 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { private static final String ATT_URL = "url"; private static final String ATT_PRINCIPAL = "manager-dn"; + private static final String ATT_PASSWORD = "manager-password"; // Properties which apply to embedded server only - when no Url is set /** sets the configuration suffix (default is "dc=springframework,dc=org"). */ public static final String ATT_ROOT_SUFFIX = "root"; + private static final String OPT_DEFAULT_ROOT_SUFFIX = "dc=springframework,dc=org"; + /** * Optionally defines an ldif resource to be loaded. Otherwise an attempt will be made * to load all ldif files found on the classpath. */ public static final String ATT_LDIF_FILE = "ldif"; + private static final String OPT_DEFAULT_LDIF_FILE = "classpath*:*.ldif"; /** Defines the port the LDAP_PROVIDER server should run on */ public static final String ATT_PORT = "port"; + private static final String RANDOM_PORT = "0"; + private static final int DEFAULT_PORT = 33389; private static final String APACHEDS_CLASSNAME = "org.apache.directory.server.core.DefaultDirectoryService"; + private static final String UNBOUNID_CLASSNAME = "com.unboundid.ldap.listener.InMemoryDirectoryServer"; private static final String APACHEDS_CONTAINER_CLASSNAME = "org.springframework.security.ldap.server.ApacheDSContainer"; + private static final String UNBOUNDID_CONTAINER_CLASSNAME = "org.springframework.security.ldap.server.UnboundIdContainer"; public BeanDefinition parse(Element elt, ParserContext parserContext) { @@ -97,22 +106,19 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { if (StringUtils.hasText(managerDn)) { if (!StringUtils.hasText(managerPassword)) { - parserContext.getReaderContext().error( - "You must specify the " + ATT_PASSWORD + " if you supply a " - + managerDn, elt); + parserContext.getReaderContext() + .error("You must specify the " + ATT_PASSWORD + " if you supply a " + managerDn, elt); } contextSource.getPropertyValues().addPropertyValue("userDn", managerDn); - contextSource.getPropertyValues().addPropertyValue("password", - managerPassword); + contextSource.getPropertyValues().addPropertyValue("password", managerPassword); } String id = elt.getAttribute(AbstractBeanDefinitionParser.ID_ATTRIBUTE); String contextSourceId = StringUtils.hasText(id) ? id : BeanIds.CONTEXT_SOURCE; - parserContext.getRegistry() - .registerBeanDefinition(contextSourceId, contextSource); + parserContext.getRegistry().registerBeanDefinition(contextSourceId, contextSource); return null; } @@ -121,14 +127,12 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { * Will be called if no url attribute is supplied. * * Registers beans to create an embedded apache directory server. - * * @return the BeanDefinition for the ContextSource for the embedded server. * * @see ApacheDSContainer * @see UnboundIdContainer */ - private RootBeanDefinition createEmbeddedServer(Element element, - ParserContext parserContext) { + private RootBeanDefinition createEmbeddedServer(Element element, ParserContext parserContext) { Object source = parserContext.extractSource(element); String suffix = element.getAttribute(ATT_ROOT_SUFFIX); @@ -137,8 +141,7 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { suffix = OPT_DEFAULT_ROOT_SUFFIX; } - BeanDefinitionBuilder contextSource = BeanDefinitionBuilder - .rootBeanDefinition(CONTEXT_SOURCE_CLASS); + BeanDefinitionBuilder contextSource = BeanDefinitionBuilder.rootBeanDefinition(CONTEXT_SOURCE_CLASS); contextSource.addConstructorArgValue(suffix); contextSource.addPropertyValue("userDn", "uid=admin,ou=system"); contextSource.addPropertyValue("password", "secret"); @@ -148,8 +151,8 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { String embeddedLdapServerConfigBeanName = parserContext.getReaderContext() .generateBeanName(embeddedLdapServerConfigBean); - parserContext.registerBeanComponent(new BeanComponentDefinition(embeddedLdapServerConfigBean, - embeddedLdapServerConfigBeanName)); + parserContext.registerBeanComponent( + new BeanComponentDefinition(embeddedLdapServerConfigBean, embeddedLdapServerConfigBeanName)); contextSource.setFactoryMethodOnBean("createEmbeddedContextSource", embeddedLdapServerConfigBeanName); @@ -166,11 +169,9 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { ldapContainer.getConstructorArgumentValues().addGenericArgumentValue(ldifs); ldapContainer.getPropertyValues().addPropertyValue("port", getPort(element)); - if (parserContext.getRegistry() - .containsBeanDefinition(BeanIds.EMBEDDED_APACHE_DS) || - parserContext.getRegistry().containsBeanDefinition(BeanIds.EMBEDDED_UNBOUNDID)) { - parserContext.getReaderContext().error( - "Only one embedded server bean is allowed per application context", + if (parserContext.getRegistry().containsBeanDefinition(BeanIds.EMBEDDED_APACHE_DS) + || parserContext.getRegistry().containsBeanDefinition(BeanIds.EMBEDDED_UNBOUNDID)) { + parserContext.getReaderContext().error("Only one embedded server bean is allowed per application context", element); } @@ -218,7 +219,8 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { private String getDefaultPort() { try (ServerSocket serverSocket = new ServerSocket(DEFAULT_PORT)) { return String.valueOf(serverSocket.getLocalPort()); - } catch (IOException e) { + } + catch (IOException e) { return RANDOM_PORT; } } @@ -251,5 +253,7 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { return new DefaultSpringSecurityContextSource(providerUrl); } + } + } diff --git a/config/src/main/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParser.java index 219de13e33..9ea520c98e 100644 --- a/config/src/main/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/ldap/LdapUserServiceBeanDefinitionParser.java @@ -32,17 +32,24 @@ import org.w3c.dom.Element; * @author Luke Taylor * @since 2.0 */ -public class LdapUserServiceBeanDefinitionParser extends - AbstractUserDetailsServiceBeanDefinitionParser { +public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServiceBeanDefinitionParser { + public static final String ATT_SERVER = "server-ref"; + public static final String ATT_USER_SEARCH_FILTER = "user-search-filter"; + public static final String ATT_USER_SEARCH_BASE = "user-search-base"; + public static final String DEF_USER_SEARCH_BASE = ""; public static final String ATT_GROUP_SEARCH_FILTER = "group-search-filter"; + public static final String ATT_GROUP_SEARCH_BASE = "group-search-base"; + public static final String ATT_GROUP_ROLE_ATTRIBUTE = "group-role-attribute"; + public static final String DEF_GROUP_SEARCH_FILTER = "(uniqueMember={0})"; + public static final String DEF_GROUP_SEARCH_BASE = ""; static final String ATT_ROLE_PREFIX = "role-prefix"; @@ -52,28 +59,29 @@ public class LdapUserServiceBeanDefinitionParser extends static final String OPT_INETORGPERSON = "inetOrgPerson"; public static final String LDAP_SEARCH_CLASS = "org.springframework.security.ldap.search.FilterBasedLdapUserSearch"; + public static final String PERSON_MAPPER_CLASS = "org.springframework.security.ldap.userdetails.PersonContextMapper"; + public static final String INET_ORG_PERSON_MAPPER_CLASS = "org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper"; + public static final String LDAP_USER_MAPPER_CLASS = "org.springframework.security.ldap.userdetails.LdapUserDetailsMapper"; + public static final String LDAP_AUTHORITIES_POPULATOR_CLASS = "org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator"; protected String getBeanClassName(Element element) { return "org.springframework.security.ldap.userdetails.LdapUserDetailsService"; } - protected void doParse(Element elt, ParserContext parserContext, - BeanDefinitionBuilder builder) { + protected void doParse(Element elt, ParserContext parserContext, BeanDefinitionBuilder builder) { if (!StringUtils.hasText(elt.getAttribute(ATT_USER_SEARCH_FILTER))) { - parserContext.getReaderContext().error("User search filter must be supplied", - elt); + parserContext.getReaderContext().error("User search filter must be supplied", elt); } builder.addConstructorArgValue(parseSearchBean(elt, parserContext)); builder.getRawBeanDefinition().setSource(parserContext.extractSource(elt)); builder.addConstructorArgValue(parseAuthoritiesPopulator(elt, parserContext)); - builder.addPropertyValue("userDetailsMapper", - parseUserDetailsClassOrUserMapperRef(elt, parserContext)); + builder.addPropertyValue("userDetailsMapper", parseUserDetailsClassOrUserMapperRef(elt, parserContext)); } static RootBeanDefinition parseSearchBean(Element elt, ParserContext parserContext) { @@ -83,9 +91,8 @@ public class LdapUserServiceBeanDefinitionParser extends if (StringUtils.hasText(userSearchBase)) { if (!StringUtils.hasText(userSearchFilter)) { - parserContext.getReaderContext().error( - ATT_USER_SEARCH_BASE + " cannot be used without a " - + ATT_USER_SEARCH_FILTER, source); + parserContext.getReaderContext() + .error(ATT_USER_SEARCH_BASE + " cannot be used without a " + ATT_USER_SEARCH_FILTER, source); } } else { @@ -96,8 +103,7 @@ public class LdapUserServiceBeanDefinitionParser extends return null; } - BeanDefinitionBuilder searchBuilder = BeanDefinitionBuilder - .rootBeanDefinition(LDAP_SEARCH_CLASS); + BeanDefinitionBuilder searchBuilder = BeanDefinitionBuilder.rootBeanDefinition(LDAP_SEARCH_CLASS); searchBuilder.getRawBeanDefinition().setSource(source); searchBuilder.addConstructorArgValue(userSearchBase); searchBuilder.addConstructorArgValue(userSearchFilter); @@ -106,8 +112,7 @@ public class LdapUserServiceBeanDefinitionParser extends return (RootBeanDefinition) searchBuilder.getBeanDefinition(); } - static RuntimeBeanReference parseServerReference(Element elt, - ParserContext parserContext) { + static RuntimeBeanReference parseServerReference(Element elt, ParserContext parserContext) { String server = elt.getAttribute(ATT_SERVER); boolean requiresDefaultName = false; @@ -123,36 +128,27 @@ public class LdapUserServiceBeanDefinitionParser extends return contextSource; } - private static void registerPostProcessorIfNecessary(BeanDefinitionRegistry registry, - boolean defaultNameRequired) { - if (registry - .containsBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR)) { + private static void registerPostProcessorIfNecessary(BeanDefinitionRegistry registry, boolean defaultNameRequired) { + if (registry.containsBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR)) { if (defaultNameRequired) { - BeanDefinition bd = registry - .getBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR); - bd.getPropertyValues().addPropertyValue("defaultNameRequired", - defaultNameRequired); + BeanDefinition bd = registry.getBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR); + bd.getPropertyValues().addPropertyValue("defaultNameRequired", defaultNameRequired); } return; } - BeanDefinitionBuilder bdb = BeanDefinitionBuilder - .rootBeanDefinition(ContextSourceSettingPostProcessor.class); + BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(ContextSourceSettingPostProcessor.class); bdb.addPropertyValue("defaultNameRequired", defaultNameRequired); - registry.registerBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR, - bdb.getBeanDefinition()); + registry.registerBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR, bdb.getBeanDefinition()); } - static BeanMetadataElement parseUserDetailsClassOrUserMapperRef(Element elt, - ParserContext parserContext) { + static BeanMetadataElement parseUserDetailsClassOrUserMapperRef(Element elt, ParserContext parserContext) { String userDetailsClass = elt.getAttribute(ATT_USER_CLASS); String userMapperRef = elt.getAttribute(ATT_USER_CONTEXT_MAPPER_REF); if (StringUtils.hasText(userDetailsClass) && StringUtils.hasText(userMapperRef)) { - parserContext.getReaderContext().error( - "Attributes " + ATT_USER_CLASS + " and " - + ATT_USER_CONTEXT_MAPPER_REF + " cannot be used together.", - parserContext.extractSource(elt)); + parserContext.getReaderContext().error("Attributes " + ATT_USER_CLASS + " and " + + ATT_USER_CONTEXT_MAPPER_REF + " cannot be used together.", parserContext.extractSource(elt)); } if (StringUtils.hasText(userMapperRef)) { @@ -176,8 +172,7 @@ public class LdapUserServiceBeanDefinitionParser extends return mapper; } - static RootBeanDefinition parseAuthoritiesPopulator(Element elt, - ParserContext parserContext) { + static RootBeanDefinition parseAuthoritiesPopulator(Element elt, ParserContext parserContext) { String groupSearchFilter = elt.getAttribute(ATT_GROUP_SEARCH_FILTER); String groupSearchBase = elt.getAttribute(ATT_GROUP_SEARCH_BASE); String groupRoleAttribute = elt.getAttribute(ATT_GROUP_ROLE_ATTRIBUTE); @@ -191,8 +186,7 @@ public class LdapUserServiceBeanDefinitionParser extends groupSearchBase = DEF_GROUP_SEARCH_BASE; } - BeanDefinitionBuilder populator = BeanDefinitionBuilder - .rootBeanDefinition(LDAP_AUTHORITIES_POPULATOR_CLASS); + BeanDefinitionBuilder populator = BeanDefinitionBuilder.rootBeanDefinition(LDAP_AUTHORITIES_POPULATOR_CLASS); populator.getRawBeanDefinition().setSource(parserContext.extractSource(elt)); populator.addConstructorArgValue(parseServerReference(elt, parserContext)); populator.addConstructorArgValue(groupSearchBase); @@ -212,4 +206,5 @@ public class LdapUserServiceBeanDefinitionParser extends return (RootBeanDefinition) populator.getBeanDefinition(); } + } diff --git a/config/src/main/java/org/springframework/security/config/ldap/package-info.java b/config/src/main/java/org/springframework/security/config/ldap/package-info.java index 392fc2146b..168ff506d5 100644 --- a/config/src/main/java/org/springframework/security/config/ldap/package-info.java +++ b/config/src/main/java/org/springframework/security/config/ldap/package-info.java @@ -17,4 +17,3 @@ * Security namespace support for LDAP authentication. */ package org.springframework.security.config.ldap; - diff --git a/config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java index 29a58e040c..0063ad72ff 100644 --- a/config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java @@ -94,21 +94,32 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP private final Log logger = LogFactory.getLog(getClass()); private static final String ATT_AUTHENTICATION_MANAGER_REF = "authentication-manager-ref"; + private static final String ATT_ACCESS = "access"; + private static final String ATT_EXPRESSION = "expression"; + private static final String ATT_ACCESS_MGR = "access-decision-manager-ref"; + private static final String ATT_RUN_AS_MGR = "run-as-manager-ref"; + private static final String ATT_USE_JSR250 = "jsr250-annotations"; + private static final String ATT_USE_SECURED = "secured-annotations"; + private static final String ATT_USE_PREPOST = "pre-post-annotations"; + private static final String ATT_REF = "ref"; + private static final String ATT_MODE = "mode"; + private static final String ATT_ADVICE_ORDER = "order"; + private static final String ATT_META_DATA_SOURCE_REF = "metadata-source-ref"; public BeanDefinition parse(Element element, ParserContext pc) { - CompositeComponentDefinition compositeDef = new CompositeComponentDefinition( - element.getTagName(), pc.extractSource(element)); + CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), + pc.extractSource(element)); pc.pushContainingComponent(compositeDef); Object source = pc.extractSource(element); @@ -117,8 +128,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP boolean jsr250Enabled = "enabled".equals(element.getAttribute(ATT_USE_JSR250)); boolean useSecured = "enabled".equals(element.getAttribute(ATT_USE_SECURED)); - boolean prePostAnnotationsEnabled = "enabled".equals(element - .getAttribute(ATT_USE_PREPOST)); + boolean prePostAnnotationsEnabled = "enabled".equals(element.getAttribute(ATT_USE_PREPOST)); boolean useAspectJ = "aspectj".equals(element.getAttribute(ATT_MODE)); BeanDefinition preInvocationVoter = null; @@ -133,15 +143,12 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP } if (prePostAnnotationsEnabled) { - Element prePostElt = DomUtils.getChildElementByTagName(element, - INVOCATION_HANDLING); - Element expressionHandlerElt = DomUtils.getChildElementByTagName(element, - EXPRESSION_HANDLER); + Element prePostElt = DomUtils.getChildElementByTagName(element, INVOCATION_HANDLING); + Element expressionHandlerElt = DomUtils.getChildElementByTagName(element, EXPRESSION_HANDLER); if (prePostElt != null && expressionHandlerElt != null) { pc.getReaderContext().error( - INVOCATION_HANDLING + " and " + EXPRESSION_HANDLER - + " cannot be used together ", source); + INVOCATION_HANDLING + " and " + EXPRESSION_HANDLER + " cannot be used together ", source); } BeanDefinitionBuilder preInvocationVoterBldr = BeanDefinitionBuilder @@ -156,12 +163,12 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP if (prePostElt != null) { // Customized override of expression handling system - String attributeFactoryRef = DomUtils.getChildElementByTagName( - prePostElt, INVOCATION_ATTRIBUTE_FACTORY).getAttribute("ref"); - String preAdviceRef = DomUtils.getChildElementByTagName(prePostElt, - PRE_INVOCATION_ADVICE).getAttribute("ref"); - String postAdviceRef = DomUtils.getChildElementByTagName(prePostElt, - POST_INVOCATION_ADVICE).getAttribute("ref"); + String attributeFactoryRef = DomUtils.getChildElementByTagName(prePostElt, INVOCATION_ATTRIBUTE_FACTORY) + .getAttribute("ref"); + String preAdviceRef = DomUtils.getChildElementByTagName(prePostElt, PRE_INVOCATION_ADVICE) + .getAttribute("ref"); + String postAdviceRef = DomUtils.getChildElementByTagName(prePostElt, POST_INVOCATION_ADVICE) + .getAttribute("ref"); mds.addConstructorArgReference(attributeFactoryRef); preInvocationVoterBldr.addConstructorArgReference(preAdviceRef); @@ -173,18 +180,15 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP : expressionHandlerElt.getAttribute("ref"); if (StringUtils.hasText(expressionHandlerRef)) { - logger.info("Using bean '" + expressionHandlerRef - + "' as method ExpressionHandler implementation"); + logger.info("Using bean '" + expressionHandlerRef + "' as method ExpressionHandler implementation"); RootBeanDefinition lazyInitPP = new RootBeanDefinition( LazyInitBeanDefinitionRegistryPostProcessor.class); - lazyInitPP.getConstructorArgumentValues().addGenericArgumentValue( - expressionHandlerRef); + lazyInitPP.getConstructorArgumentValues().addGenericArgumentValue(expressionHandlerRef); pc.getReaderContext().registerWithGeneratedName(lazyInitPP); BeanDefinitionBuilder lazyMethodSecurityExpressionHandlerBldr = BeanDefinitionBuilder .rootBeanDefinition(LazyInitTargetSource.class); - lazyMethodSecurityExpressionHandlerBldr.addPropertyValue( - "targetBeanName", expressionHandlerRef); + lazyMethodSecurityExpressionHandlerBldr.addPropertyValue("targetBeanName", expressionHandlerRef); BeanDefinitionBuilder expressionHandlerProxyBldr = BeanDefinitionBuilder .rootBeanDefinition(ProxyFactoryBean.class); @@ -193,43 +197,37 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP expressionHandlerProxyBldr.addPropertyValue("proxyInterfaces", MethodSecurityExpressionHandler.class); - expressionHandlerRef = pc.getReaderContext().generateBeanName( - expressionHandlerProxyBldr.getBeanDefinition()); + expressionHandlerRef = pc.getReaderContext() + .generateBeanName(expressionHandlerProxyBldr.getBeanDefinition()); - pc.registerBeanComponent(new BeanComponentDefinition( - expressionHandlerProxyBldr.getBeanDefinition(), + pc.registerBeanComponent(new BeanComponentDefinition(expressionHandlerProxyBldr.getBeanDefinition(), expressionHandlerRef)); } else { - RootBeanDefinition expressionHandler = registerWithDefaultRolePrefix(pc, DefaultMethodSecurityExpressionHandlerBeanFactory.class); + RootBeanDefinition expressionHandler = registerWithDefaultRolePrefix(pc, + DefaultMethodSecurityExpressionHandlerBeanFactory.class); - expressionHandlerRef = pc.getReaderContext().generateBeanName( - expressionHandler); - pc.registerBeanComponent(new BeanComponentDefinition( - expressionHandler, expressionHandlerRef)); - logger.info("Expressions were enabled for method security but no SecurityExpressionHandler was configured. " - + "All hasPermission() expressions will evaluate to false."); + expressionHandlerRef = pc.getReaderContext().generateBeanName(expressionHandler); + pc.registerBeanComponent(new BeanComponentDefinition(expressionHandler, expressionHandlerRef)); + logger.info( + "Expressions were enabled for method security but no SecurityExpressionHandler was configured. " + + "All hasPermission() expressions will evaluate to false."); } BeanDefinitionBuilder expressionPreAdviceBldr = BeanDefinitionBuilder .rootBeanDefinition(ExpressionBasedPreInvocationAdvice.class); - expressionPreAdviceBldr.addPropertyReference("expressionHandler", - expressionHandlerRef); - preInvocationVoterBldr.addConstructorArgValue(expressionPreAdviceBldr - .getBeanDefinition()); + expressionPreAdviceBldr.addPropertyReference("expressionHandler", expressionHandlerRef); + preInvocationVoterBldr.addConstructorArgValue(expressionPreAdviceBldr.getBeanDefinition()); BeanDefinitionBuilder expressionPostAdviceBldr = BeanDefinitionBuilder .rootBeanDefinition(ExpressionBasedPostInvocationAdvice.class); expressionPostAdviceBldr.addConstructorArgReference(expressionHandlerRef); - afterInvocationBldr.addConstructorArgValue(expressionPostAdviceBldr - .getBeanDefinition()); + afterInvocationBldr.addConstructorArgValue(expressionPostAdviceBldr.getBeanDefinition()); BeanDefinitionBuilder annotationInvocationFactory = BeanDefinitionBuilder .rootBeanDefinition(ExpressionBasedAnnotationAttributeFactory.class); - annotationInvocationFactory - .addConstructorArgReference(expressionHandlerRef); - mds.addConstructorArgValue(annotationInvocationFactory - .getBeanDefinition()); + annotationInvocationFactory.addConstructorArgReference(expressionHandlerRef); + mds.addConstructorArgValue(annotationInvocationFactory.getBeanDefinition()); } preInvocationVoter = preInvocationVoterBldr.getBeanDefinition(); @@ -238,12 +236,13 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP } if (useSecured) { - delegates.add(BeanDefinitionBuilder.rootBeanDefinition( - SecuredAnnotationSecurityMetadataSource.class).getBeanDefinition()); + delegates.add(BeanDefinitionBuilder.rootBeanDefinition(SecuredAnnotationSecurityMetadataSource.class) + .getBeanDefinition()); } if (jsr250Enabled) { - RootBeanDefinition jsrMetadataSource = registerWithDefaultRolePrefix(pc, Jsr250MethodSecurityMetadataSourceBeanFactory.class); + RootBeanDefinition jsrMetadataSource = registerWithDefaultRolePrefix(pc, + Jsr250MethodSecurityMetadataSourceBeanFactory.class); delegates.add(jsrMetadataSource); } @@ -254,32 +253,26 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP if (pointcutMap.size() > 0) { if (useAspectJ) { - pc.getReaderContext().error( - "You can't use AspectJ mode with protect-pointcut definitions", - source); + pc.getReaderContext().error("You can't use AspectJ mode with protect-pointcut definitions", source); } // Only add it if there are actually any pointcuts defined. - BeanDefinition mapBasedMetadataSource = new RootBeanDefinition( - MapBasedMethodSecurityMetadataSource.class); - BeanReference ref = new RuntimeBeanReference(pc.getReaderContext() - .generateBeanName(mapBasedMetadataSource)); + BeanDefinition mapBasedMetadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class); + BeanReference ref = new RuntimeBeanReference( + pc.getReaderContext().generateBeanName(mapBasedMetadataSource)); delegates.add(ref); - pc.registerBeanComponent(new BeanComponentDefinition(mapBasedMetadataSource, - ref.getBeanName())); + pc.registerBeanComponent(new BeanComponentDefinition(mapBasedMetadataSource, ref.getBeanName())); registerProtectPointcutPostProcessor(pc, pointcutMap, ref, source); } - BeanReference metadataSource = registerDelegatingMethodSecurityMetadataSource(pc, - delegates, source); + BeanReference metadataSource = registerDelegatingMethodSecurityMetadataSource(pc, delegates, source); // Check for additional after-invocation-providers.. List afterInvocationElts = DomUtils.getChildElementsByTagName(element, Elements.AFTER_INVOCATION_PROVIDER); for (Element elt : afterInvocationElts) { - afterInvocationProviders.add(new RuntimeBeanReference(elt - .getAttribute(ATT_REF))); + afterInvocationProviders.add(new RuntimeBeanReference(elt.getAttribute(ATT_REF))); } String accessManagerId = element.getAttribute(ATT_ACCESS_MGR); @@ -291,24 +284,20 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP String authMgrRef = element.getAttribute(ATT_AUTHENTICATION_MANAGER_REF); String runAsManagerId = element.getAttribute(ATT_RUN_AS_MGR); - BeanReference interceptor = registerMethodSecurityInterceptor(pc, authMgrRef, - accessManagerId, runAsManagerId, metadataSource, - afterInvocationProviders, source, useAspectJ); + BeanReference interceptor = registerMethodSecurityInterceptor(pc, authMgrRef, accessManagerId, runAsManagerId, + metadataSource, afterInvocationProviders, source, useAspectJ); if (useAspectJ) { - BeanDefinitionBuilder aspect = BeanDefinitionBuilder - .rootBeanDefinition("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"); + BeanDefinitionBuilder aspect = BeanDefinitionBuilder.rootBeanDefinition( + "org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"); aspect.setFactoryMethod("aspectOf"); aspect.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); aspect.addPropertyValue("securityInterceptor", interceptor); - String id = pc.getReaderContext().registerWithGeneratedName( - aspect.getBeanDefinition()); - pc.registerBeanComponent(new BeanComponentDefinition(aspect - .getBeanDefinition(), id)); + String id = pc.getReaderContext().registerWithGeneratedName(aspect.getBeanDefinition()); + pc.registerBeanComponent(new BeanComponentDefinition(aspect.getBeanDefinition(), id)); } else { - registerAdvisor(pc, interceptor, metadataSource, source, - element.getAttribute(ATT_ADVICE_ORDER)); + registerAdvisor(pc, interceptor, metadataSource, source, element.getAttribute(ATT_ADVICE_ORDER)); AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(pc, element); } @@ -323,11 +312,9 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP * @return */ @SuppressWarnings({ "unchecked", "rawtypes" }) - private String registerAccessManager(ParserContext pc, boolean jsr250Enabled, - BeanDefinition expressionVoter) { + private String registerAccessManager(ParserContext pc, boolean jsr250Enabled, BeanDefinition expressionVoter) { - BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder - .rootBeanDefinition(AffirmativeBased.class); + BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class); ManagedList voters = new ManagedList(4); if (expressionVoter != null) { @@ -350,37 +337,32 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP } @SuppressWarnings("rawtypes") - private BeanReference registerDelegatingMethodSecurityMetadataSource( - ParserContext pc, ManagedList delegates, Object source) { + private BeanReference registerDelegatingMethodSecurityMetadataSource(ParserContext pc, ManagedList delegates, + Object source) { RootBeanDefinition delegatingMethodSecurityMetadataSource = new RootBeanDefinition( DelegatingMethodSecurityMetadataSource.class); delegatingMethodSecurityMetadataSource.setSource(source); - delegatingMethodSecurityMetadataSource.getConstructorArgumentValues() - .addGenericArgumentValue(delegates); + delegatingMethodSecurityMetadataSource.getConstructorArgumentValues().addGenericArgumentValue(delegates); - String id = pc.getReaderContext().generateBeanName( - delegatingMethodSecurityMetadataSource); - pc.registerBeanComponent(new BeanComponentDefinition( - delegatingMethodSecurityMetadataSource, id)); + String id = pc.getReaderContext().generateBeanName(delegatingMethodSecurityMetadataSource); + pc.registerBeanComponent(new BeanComponentDefinition(delegatingMethodSecurityMetadataSource, id)); return new RuntimeBeanReference(id); } private void registerProtectPointcutPostProcessor(ParserContext parserContext, - Map> pointcutMap, - BeanReference mapBasedMethodSecurityMetadataSource, Object source) { - RootBeanDefinition ppbp = new RootBeanDefinition( - ProtectPointcutPostProcessor.class); + Map> pointcutMap, BeanReference mapBasedMethodSecurityMetadataSource, + Object source) { + RootBeanDefinition ppbp = new RootBeanDefinition(ProtectPointcutPostProcessor.class); ppbp.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); ppbp.setSource(source); - ppbp.getConstructorArgumentValues().addGenericArgumentValue( - mapBasedMethodSecurityMetadataSource); + ppbp.getConstructorArgumentValues().addGenericArgumentValue(mapBasedMethodSecurityMetadataSource); ppbp.getPropertyValues().addPropertyValue("pointcutMap", pointcutMap); parserContext.getReaderContext().registerWithGeneratedName(ppbp); } - private Map> parseProtectPointcuts( - ParserContext parserContext, List protectPointcutElts) { + private Map> parseProtectPointcuts(ParserContext parserContext, + List protectPointcutElts) { Map> pointcutMap = new LinkedHashMap<>(); for (Element childElt : protectPointcutElts) { @@ -397,10 +379,8 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP parserContext.extractSource(childElt)); } - String[] attributeTokens = StringUtils - .commaDelimitedListToStringArray(accessConfig); - List attributes = new ArrayList<>( - attributeTokens.length); + String[] attributeTokens = StringUtils.commaDelimitedListToStringArray(accessConfig); + List attributes = new ArrayList<>(attributeTokens.length); for (String token : attributeTokens) { attributes.add(new SecurityConfig(token)); @@ -412,18 +392,14 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP return pointcutMap; } - private BeanReference registerMethodSecurityInterceptor(ParserContext pc, - String authMgrRef, String accessManagerId, String runAsManagerId, - BeanReference metadataSource, - List afterInvocationProviders, Object source, - boolean useAspectJ) { - BeanDefinitionBuilder bldr = BeanDefinitionBuilder - .rootBeanDefinition(useAspectJ ? AspectJMethodSecurityInterceptor.class - : MethodSecurityInterceptor.class); + private BeanReference registerMethodSecurityInterceptor(ParserContext pc, String authMgrRef, String accessManagerId, + String runAsManagerId, BeanReference metadataSource, List afterInvocationProviders, + Object source, boolean useAspectJ) { + BeanDefinitionBuilder bldr = BeanDefinitionBuilder.rootBeanDefinition( + useAspectJ ? AspectJMethodSecurityInterceptor.class : MethodSecurityInterceptor.class); bldr.getRawBeanDefinition().setSource(source); bldr.addPropertyReference("accessDecisionManager", accessManagerId); - RootBeanDefinition authMgr = new RootBeanDefinition( - AuthenticationManagerDelegator.class); + RootBeanDefinition authMgr = new RootBeanDefinition(AuthenticationManagerDelegator.class); authMgr.getConstructorArgumentValues().addGenericArgumentValue(authMgrRef); bldr.addPropertyValue("authenticationManager", authMgr); bldr.addPropertyValue("securityMetadataSource", metadataSource); @@ -434,10 +410,8 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP if (!afterInvocationProviders.isEmpty()) { BeanDefinition afterInvocationManager; - afterInvocationManager = new RootBeanDefinition( - AfterInvocationProviderManager.class); - afterInvocationManager.getPropertyValues().addPropertyValue("providers", - afterInvocationProviders); + afterInvocationManager = new RootBeanDefinition(AfterInvocationProviderManager.class); + afterInvocationManager.getPropertyValues().addPropertyValue("providers", afterInvocationProviders); bldr.addPropertyValue("afterInvocationManager", afterInvocationManager); } @@ -448,15 +422,12 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP return new RuntimeBeanReference(id); } - private void registerAdvisor(ParserContext parserContext, BeanReference interceptor, - BeanReference metadataSource, Object source, String adviceOrder) { - if (parserContext.getRegistry().containsBeanDefinition( - BeanIds.METHOD_SECURITY_METADATA_SOURCE_ADVISOR)) { - parserContext.getReaderContext().error( - "Duplicate detected.", source); + private void registerAdvisor(ParserContext parserContext, BeanReference interceptor, BeanReference metadataSource, + Object source, String adviceOrder) { + if (parserContext.getRegistry().containsBeanDefinition(BeanIds.METHOD_SECURITY_METADATA_SOURCE_ADVISOR)) { + parserContext.getReaderContext().error("Duplicate detected.", source); } - RootBeanDefinition advisor = new RootBeanDefinition( - MethodSecurityMetadataSourceAdvisor.class); + RootBeanDefinition advisor = new RootBeanDefinition(MethodSecurityMetadataSourceAdvisor.class); if (StringUtils.hasText(adviceOrder)) { advisor.getPropertyValues().addPropertyValue("order", adviceOrder); @@ -467,17 +438,15 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP // otherwise advisor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); advisor.setSource(source); - advisor.getConstructorArgumentValues().addGenericArgumentValue( - interceptor.getBeanName()); + advisor.getConstructorArgumentValues().addGenericArgumentValue(interceptor.getBeanName()); advisor.getConstructorArgumentValues().addGenericArgumentValue(metadataSource); - advisor.getConstructorArgumentValues().addGenericArgumentValue( - metadataSource.getBeanName()); + advisor.getConstructorArgumentValues().addGenericArgumentValue(metadataSource.getBeanName()); - parserContext.getRegistry().registerBeanDefinition( - BeanIds.METHOD_SECURITY_METADATA_SOURCE_ADVISOR, advisor); + parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_SECURITY_METADATA_SOURCE_ADVISOR, advisor); } - private RootBeanDefinition registerWithDefaultRolePrefix(ParserContext pc, Class beanFactoryClass) { + private RootBeanDefinition registerWithDefaultRolePrefix(ParserContext pc, + Class beanFactoryClass) { RootBeanDefinition beanFactoryDefinition = new RootBeanDefinition(beanFactoryClass); String beanFactoryRef = pc.getReaderContext().generateBeanName(beanFactoryDefinition); pc.getRegistry().registerBeanDefinition(beanFactoryRef, beanFactoryDefinition); @@ -495,32 +464,30 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP * @author Luke Taylor * @since 3.0 */ - static final class AuthenticationManagerDelegator implements AuthenticationManager, - BeanFactoryAware { + static final class AuthenticationManagerDelegator implements AuthenticationManager, BeanFactoryAware { + private AuthenticationManager delegate; + private final Object delegateMonitor = new Object(); + private BeanFactory beanFactory; + private final String authMgrBean; AuthenticationManagerDelegator(String authMgrBean) { - this.authMgrBean = StringUtils.hasText(authMgrBean) ? authMgrBean - : BeanIds.AUTHENTICATION_MANAGER; + this.authMgrBean = StringUtils.hasText(authMgrBean) ? authMgrBean : BeanIds.AUTHENTICATION_MANAGER; } - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { synchronized (delegateMonitor) { if (delegate == null) { - Assert.state(beanFactory != null, - () -> "BeanFactory must be set to resolve " + authMgrBean); + Assert.state(beanFactory != null, () -> "BeanFactory must be set to resolve " + authMgrBean); try { - delegate = beanFactory.getBean(authMgrBean, - AuthenticationManager.class); + delegate = beanFactory.getBean(authMgrBean, AuthenticationManager.class); } catch (NoSuchBeanDefinitionException e) { if (BeanIds.AUTHENTICATION_MANAGER.equals(e.getBeanName())) { - throw new NoSuchBeanDefinitionException( - BeanIds.AUTHENTICATION_MANAGER, + throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER, AuthenticationManagerFactoryBean.MISSING_BEAN_ERROR_MESSAGE); } throw e; @@ -534,38 +501,46 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } + } static class Jsr250MethodSecurityMetadataSourceBeanFactory extends AbstractGrantedAuthorityDefaultsBeanFactory { + private Jsr250MethodSecurityMetadataSource source = new Jsr250MethodSecurityMetadataSource(); public Jsr250MethodSecurityMetadataSource getBean() { source.setDefaultRolePrefix(this.rolePrefix); return source; } + } static class DefaultMethodSecurityExpressionHandlerBeanFactory extends AbstractGrantedAuthorityDefaultsBeanFactory { + private DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler(); public DefaultMethodSecurityExpressionHandler getBean() { handler.setDefaultRolePrefix(this.rolePrefix); return handler; } + } static abstract class AbstractGrantedAuthorityDefaultsBeanFactory implements ApplicationContextAware { + protected String rolePrefix = "ROLE_"; @Override - public final void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - String[] grantedAuthorityDefaultsBeanNames = applicationContext.getBeanNamesForType(GrantedAuthorityDefaults.class); + public final void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + String[] grantedAuthorityDefaultsBeanNames = applicationContext + .getBeanNamesForType(GrantedAuthorityDefaults.class); if (grantedAuthorityDefaultsBeanNames.length == 1) { - GrantedAuthorityDefaults grantedAuthorityDefaults = applicationContext.getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class); + GrantedAuthorityDefaults grantedAuthorityDefaults = applicationContext + .getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class); this.rolePrefix = grantedAuthorityDefaults.getRolePrefix(); } } + } /** @@ -575,16 +550,16 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP * @author Rob Winch * @since 3.2 */ - private static final class LazyInitBeanDefinitionRegistryPostProcessor implements - BeanDefinitionRegistryPostProcessor { + private static final class LazyInitBeanDefinitionRegistryPostProcessor + implements BeanDefinitionRegistryPostProcessor { + private final String beanName; private LazyInitBeanDefinitionRegistryPostProcessor(String beanName) { this.beanName = beanName; } - public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) - throws BeansException { + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { if (!registry.containsBeanDefinition(beanName)) { return; } @@ -592,8 +567,9 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP beanDefinition.setLazyInit(true); } - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) - throws BeansException { + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } + } + } diff --git a/config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java b/config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java index f57eb1004b..f447972569 100644 --- a/config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java +++ b/config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java @@ -42,30 +42,31 @@ import java.util.*; * */ public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDecorator { + private final BeanDefinitionDecorator delegate = new InternalInterceptMethodsBeanDefinitionDecorator(); - public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, - ParserContext parserContext) { + public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) { MethodConfigUtils.registerDefaultMethodAccessManagerIfNecessary(parserContext); return delegate.decorate(node, definition, parserContext); } + } /** * This is the real class which does the work. We need access to the ParserContext in * order to do bean registration. */ -class InternalInterceptMethodsBeanDefinitionDecorator extends - AbstractInterceptorDrivenBeanDefinitionDecorator { +class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator { + static final String ATT_METHOD = "method"; static final String ATT_ACCESS = "access"; + private static final String ATT_ACCESS_MGR = "access-decision-manager-ref"; protected BeanDefinition createInterceptorDefinition(Node node) { Element interceptMethodsElt = (Element) node; - BeanDefinitionBuilder interceptor = BeanDefinitionBuilder - .rootBeanDefinition(MethodSecurityInterceptor.class); + BeanDefinitionBuilder interceptor = BeanDefinitionBuilder.rootBeanDefinition(MethodSecurityInterceptor.class); // Default to autowiring to pick up after invocation mgr interceptor.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE); @@ -76,26 +77,21 @@ class InternalInterceptMethodsBeanDefinitionDecorator extends accessManagerId = BeanIds.METHOD_ACCESS_MANAGER; } - interceptor.addPropertyValue("accessDecisionManager", new RuntimeBeanReference( - accessManagerId)); - interceptor.addPropertyValue("authenticationManager", new RuntimeBeanReference( - BeanIds.AUTHENTICATION_MANAGER)); + interceptor.addPropertyValue("accessDecisionManager", new RuntimeBeanReference(accessManagerId)); + interceptor.addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER)); // Lookup parent bean information String parentBeanClass = ((Element) node.getParentNode()).getAttribute("class"); // Parse the included methods - List methods = DomUtils.getChildElementsByTagName(interceptMethodsElt, - Elements.PROTECT); + List methods = DomUtils.getChildElementsByTagName(interceptMethodsElt, Elements.PROTECT); Map mappings = new ManagedMap<>(); for (Element protectmethodElt : methods) { - BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder - .rootBeanDefinition(SecurityConfig.class); + BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder.rootBeanDefinition(SecurityConfig.class); attributeBuilder.setFactoryMethod("createListFromCommaDelimitedString"); - attributeBuilder.addConstructorArgValue(protectmethodElt - .getAttribute(ATT_ACCESS)); + attributeBuilder.addConstructorArgValue(protectmethodElt.getAttribute(ATT_ACCESS)); // Support inference of class names String methodName = protectmethodElt.getAttribute(ATT_METHOD); @@ -109,11 +105,11 @@ class InternalInterceptMethodsBeanDefinitionDecorator extends mappings.put(methodName, attributeBuilder.getBeanDefinition()); } - BeanDefinition metadataSource = new RootBeanDefinition( - MapBasedMethodSecurityMetadataSource.class); + BeanDefinition metadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class); metadataSource.getConstructorArgumentValues().addGenericArgumentValue(mappings); interceptor.addPropertyValue("securityMetadataSource", metadataSource); return interceptor.getBeanDefinition(); } + } diff --git a/config/src/main/java/org/springframework/security/config/method/MethodConfigUtils.java b/config/src/main/java/org/springframework/security/config/method/MethodConfigUtils.java index 32ae929c32..05b6c645b1 100644 --- a/config/src/main/java/org/springframework/security/config/method/MethodConfigUtils.java +++ b/config/src/main/java/org/springframework/security/config/method/MethodConfigUtils.java @@ -33,28 +33,26 @@ import org.springframework.security.config.BeanIds; * @author Rob Winch */ abstract class MethodConfigUtils { + @SuppressWarnings("unchecked") static void registerDefaultMethodAccessManagerIfNecessary(ParserContext parserContext) { - if (!parserContext.getRegistry().containsBeanDefinition( - BeanIds.METHOD_ACCESS_MANAGER)) { - parserContext.getRegistry().registerBeanDefinition( - BeanIds.METHOD_ACCESS_MANAGER, + if (!parserContext.getRegistry().containsBeanDefinition(BeanIds.METHOD_ACCESS_MANAGER)) { + parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_ACCESS_MANAGER, createAccessManagerBean(RoleVoter.class, AuthenticatedVoter.class)); } } @SuppressWarnings("unchecked") - private static RootBeanDefinition createAccessManagerBean( - Class... voters) { + private static RootBeanDefinition createAccessManagerBean(Class... voters) { ManagedList defaultVoters = new ManagedList(voters.length); for (Class voter : voters) { defaultVoters.add(new RootBeanDefinition(voter)); } - BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder - .rootBeanDefinition(AffirmativeBased.class); + BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class); accessMgrBuilder.addConstructorArgValue(defaultVoters); return (RootBeanDefinition) accessMgrBuilder.getBeanDefinition(); } + } diff --git a/config/src/main/java/org/springframework/security/config/method/MethodSecurityMetadataSourceBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/method/MethodSecurityMetadataSourceBeanDefinitionParser.java index 6d4f18b79b..fbc0449fb0 100644 --- a/config/src/main/java/org/springframework/security/config/method/MethodSecurityMetadataSourceBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/method/MethodSecurityMetadataSourceBeanDefinitionParser.java @@ -32,12 +32,11 @@ import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; /** - * * @author Luke Taylor * @since 3.1 */ -public class MethodSecurityMetadataSourceBeanDefinitionParser extends - AbstractBeanDefinitionParser { +public class MethodSecurityMetadataSourceBeanDefinitionParser extends AbstractBeanDefinitionParser { + static final String ATT_METHOD = "method"; static final String ATT_ACCESS = "access"; @@ -47,16 +46,13 @@ public class MethodSecurityMetadataSourceBeanDefinitionParser extends Map> mappings = new LinkedHashMap<>(); for (Element protectmethodElt : methods) { - String[] tokens = StringUtils - .commaDelimitedListToStringArray(protectmethodElt - .getAttribute(ATT_ACCESS)); + String[] tokens = StringUtils.commaDelimitedListToStringArray(protectmethodElt.getAttribute(ATT_ACCESS)); String methodName = protectmethodElt.getAttribute(ATT_METHOD); mappings.put(methodName, SecurityConfig.createList(tokens)); } - RootBeanDefinition metadataSource = new RootBeanDefinition( - MapBasedMethodSecurityMetadataSource.class); + RootBeanDefinition metadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class); metadataSource.getConstructorArgumentValues().addGenericArgumentValue(mappings); return metadataSource; diff --git a/config/src/main/java/org/springframework/security/config/method/ProtectPointcutPostProcessor.java b/config/src/main/java/org/springframework/security/config/method/ProtectPointcutPostProcessor.java index 1164a9682a..8e561412df 100644 --- a/config/src/main/java/org/springframework/security/config/method/ProtectPointcutPostProcessor.java +++ b/config/src/main/java/org/springframework/security/config/method/ProtectPointcutPostProcessor.java @@ -59,17 +59,19 @@ import org.springframework.util.StringUtils; */ final class ProtectPointcutPostProcessor implements BeanPostProcessor { - private static final Log logger = LogFactory - .getLog(ProtectPointcutPostProcessor.class); + private static final Log logger = LogFactory.getLog(ProtectPointcutPostProcessor.class); private final Map> pointcutMap = new LinkedHashMap<>(); + private final MapBasedMethodSecurityMetadataSource mapBasedMethodSecurityMetadataSource; + private final Set pointCutExpressions = new LinkedHashSet<>(); + private final PointcutParser parser; + private final Set processedBeans = new HashSet<>(); - ProtectPointcutPostProcessor( - MapBasedMethodSecurityMetadataSource mapBasedMethodSecurityMetadataSource) { + ProtectPointcutPostProcessor(MapBasedMethodSecurityMetadataSource mapBasedMethodSecurityMetadataSource) { Assert.notNull(mapBasedMethodSecurityMetadataSource, "MapBasedMethodSecurityMetadataSource to populate is required"); this.mapBasedMethodSecurityMetadataSource = mapBasedMethodSecurityMetadataSource; @@ -86,17 +88,15 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor { // supportedPrimitives.add(PointcutPrimitive.AT_WITHIN); // supportedPrimitives.add(PointcutPrimitive.AT_ARGS); // supportedPrimitives.add(PointcutPrimitive.AT_TARGET); - parser = PointcutParser - .getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(supportedPrimitives); + parser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution( + supportedPrimitives); } - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (processedBeans.contains(beanName)) { // We already have the metadata for this bean return bean; @@ -136,27 +136,22 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor { return bean; } - private boolean attemptMatch(Class targetClass, Method method, - PointcutExpression expression, String beanName) { + private boolean attemptMatch(Class targetClass, Method method, PointcutExpression expression, String beanName) { // Determine if the presented AspectJ pointcut expression matches this method boolean matches = expression.matchesMethodExecution(method).alwaysMatches(); // Handle accordingly if (matches) { - List attr = pointcutMap.get(expression - .getPointcutExpression()); + List attr = pointcutMap.get(expression.getPointcutExpression()); if (logger.isDebugEnabled()) { - logger.debug("AspectJ pointcut expression '" - + expression.getPointcutExpression() + "' matches target class '" - + targetClass.getName() + "' (bean ID '" + beanName - + "') for method '" + method - + "'; registering security configuration attribute '" + attr + logger.debug("AspectJ pointcut expression '" + expression.getPointcutExpression() + + "' matches target class '" + targetClass.getName() + "' (bean ID '" + beanName + + "') for method '" + method + "'; registering security configuration attribute '" + attr + "'"); } - mapBasedMethodSecurityMetadataSource.addSecureMethod(targetClass, method, - attr); + mapBasedMethodSecurityMetadataSource.addSecureMethod(targetClass, method, attr); } return matches; @@ -180,8 +175,7 @@ final class ProtectPointcutPostProcessor implements BeanPostProcessor { if (logger.isDebugEnabled()) { logger.debug("AspectJ pointcut expression '" + pointcutExpression - + "' registered for security configuration attribute '" + definition - + "'"); + + "' registered for security configuration attribute '" + definition + "'"); } } diff --git a/config/src/main/java/org/springframework/security/config/method/package-info.java b/config/src/main/java/org/springframework/security/config/method/package-info.java index c985fc7e60..5e3615cd46 100644 --- a/config/src/main/java/org/springframework/security/config/method/package-info.java +++ b/config/src/main/java/org/springframework/security/config/method/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Support for parsing of the <global-method-security> and <intercept-methods> elements. + * Support for parsing of the <global-method-security> and <intercept-methods> + * elements. */ package org.springframework.security.config.method; - diff --git a/config/src/main/java/org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParser.java index 976818d0ff..fb067c901a 100644 --- a/config/src/main/java/org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParser.java @@ -45,22 +45,39 @@ import java.util.Optional; public final class ClientRegistrationsBeanDefinitionParser implements BeanDefinitionParser { private static final String ELT_CLIENT_REGISTRATION = "client-registration"; + private static final String ELT_PROVIDER = "provider"; + private static final String ATT_REGISTRATION_ID = "registration-id"; + private static final String ATT_CLIENT_ID = "client-id"; + private static final String ATT_CLIENT_SECRET = "client-secret"; + private static final String ATT_CLIENT_AUTHENTICATION_METHOD = "client-authentication-method"; + private static final String ATT_AUTHORIZATION_GRANT_TYPE = "authorization-grant-type"; + private static final String ATT_REDIRECT_URI = "redirect-uri"; + private static final String ATT_SCOPE = "scope"; + private static final String ATT_CLIENT_NAME = "client-name"; + private static final String ATT_PROVIDER_ID = "provider-id"; + private static final String ATT_AUTHORIZATION_URI = "authorization-uri"; + private static final String ATT_TOKEN_URI = "token-uri"; + private static final String ATT_USER_INFO_URI = "user-info-uri"; + private static final String ATT_USER_INFO_AUTHENTICATION_METHOD = "user-info-authentication-method"; + private static final String ATT_USER_INFO_USER_NAME_ATTRIBUTE = "user-info-user-name-attribute"; + private static final String ATT_JWK_SET_URI = "jwk-set-uri"; + private static final String ATT_ISSUER_URI = "issuer-uri"; @Override @@ -74,12 +91,11 @@ public final class ClientRegistrationsBeanDefinitionParser implements BeanDefini BeanDefinition clientRegistrationRepositoryBean = BeanDefinitionBuilder .rootBeanDefinition(InMemoryClientRegistrationRepository.class) - .addConstructorArgValue(clientRegistrations) - .getBeanDefinition(); - String clientRegistrationRepositoryId = parserContext.getReaderContext().generateBeanName( - clientRegistrationRepositoryBean); - parserContext.registerBeanComponent(new BeanComponentDefinition( - clientRegistrationRepositoryBean, clientRegistrationRepositoryId)); + .addConstructorArgValue(clientRegistrations).getBeanDefinition(); + String clientRegistrationRepositoryId = parserContext.getReaderContext() + .generateBeanName(clientRegistrationRepositoryBean); + parserContext.registerBeanComponent( + new BeanComponentDefinition(clientRegistrationRepositoryBean, clientRegistrationRepositoryId)); parserContext.popAndRegisterContainingComponent(); return null; @@ -103,23 +119,17 @@ public final class ClientRegistrationsBeanDefinitionParser implements BeanDefini continue; } } - getOptionalIfNotEmpty(clientRegistrationElt.getAttribute(ATT_CLIENT_ID)) - .ifPresent(builder::clientId); + getOptionalIfNotEmpty(clientRegistrationElt.getAttribute(ATT_CLIENT_ID)).ifPresent(builder::clientId); getOptionalIfNotEmpty(clientRegistrationElt.getAttribute(ATT_CLIENT_SECRET)) .ifPresent(builder::clientSecret); getOptionalIfNotEmpty(clientRegistrationElt.getAttribute(ATT_CLIENT_AUTHENTICATION_METHOD)) - .map(ClientAuthenticationMethod::new) - .ifPresent(builder::clientAuthenticationMethod); + .map(ClientAuthenticationMethod::new).ifPresent(builder::clientAuthenticationMethod); getOptionalIfNotEmpty(clientRegistrationElt.getAttribute(ATT_AUTHORIZATION_GRANT_TYPE)) - .map(AuthorizationGrantType::new) - .ifPresent(builder::authorizationGrantType); - getOptionalIfNotEmpty(clientRegistrationElt.getAttribute(ATT_REDIRECT_URI)) - .ifPresent(builder::redirectUri); + .map(AuthorizationGrantType::new).ifPresent(builder::authorizationGrantType); + getOptionalIfNotEmpty(clientRegistrationElt.getAttribute(ATT_REDIRECT_URI)).ifPresent(builder::redirectUri); getOptionalIfNotEmpty(clientRegistrationElt.getAttribute(ATT_SCOPE)) - .map(StringUtils::commaDelimitedListToSet) - .ifPresent(builder::scope); - getOptionalIfNotEmpty(clientRegistrationElt.getAttribute(ATT_CLIENT_NAME)) - .ifPresent(builder::clientName); + .map(StringUtils::commaDelimitedListToSet).ifPresent(builder::scope); + getOptionalIfNotEmpty(clientRegistrationElt.getAttribute(ATT_CLIENT_NAME)).ifPresent(builder::clientName); clientRegistrations.add(builder.build()); } @@ -186,17 +196,12 @@ public final class ClientRegistrationsBeanDefinitionParser implements BeanDefini private static ClientRegistration.Builder getBuilder(ClientRegistration.Builder builder, Map provider) { - getOptionalIfNotEmpty(provider.get(ATT_AUTHORIZATION_URI)) - .ifPresent(builder::authorizationUri); - getOptionalIfNotEmpty(provider.get(ATT_TOKEN_URI)) - .ifPresent(builder::tokenUri); - getOptionalIfNotEmpty(provider.get(ATT_USER_INFO_URI)) - .ifPresent(builder::userInfoUri); - getOptionalIfNotEmpty(provider.get(ATT_USER_INFO_AUTHENTICATION_METHOD)) - .map(AuthenticationMethod::new) + getOptionalIfNotEmpty(provider.get(ATT_AUTHORIZATION_URI)).ifPresent(builder::authorizationUri); + getOptionalIfNotEmpty(provider.get(ATT_TOKEN_URI)).ifPresent(builder::tokenUri); + getOptionalIfNotEmpty(provider.get(ATT_USER_INFO_URI)).ifPresent(builder::userInfoUri); + getOptionalIfNotEmpty(provider.get(ATT_USER_INFO_AUTHENTICATION_METHOD)).map(AuthenticationMethod::new) .ifPresent(builder::userInfoAuthenticationMethod); - getOptionalIfNotEmpty(provider.get(ATT_JWK_SET_URI)) - .ifPresent(builder::jwkSetUri); + getOptionalIfNotEmpty(provider.get(ATT_JWK_SET_URI)).ifPresent(builder::jwkSetUri); getOptionalIfNotEmpty(provider.get(ATT_USER_INFO_USER_NAME_ATTRIBUTE)) .ifPresent(builder::userNameAttributeName); return builder; @@ -214,10 +219,12 @@ public final class ClientRegistrationsBeanDefinitionParser implements BeanDefini } try { return CommonOAuth2Provider.valueOf(value); - } catch (Exception ex) { + } + catch (Exception ex) { return findEnum(value); } - } catch (Exception ex) { + } + catch (Exception ex) { return null; } } @@ -245,4 +252,5 @@ public final class ClientRegistrationsBeanDefinitionParser implements BeanDefini return configuredProviderId != null ? "Unknown provider ID '" + configuredProviderId + "'" : "Provider ID must be specified for client registration '" + registrationId + "'"; } + } diff --git a/config/src/main/java/org/springframework/security/config/oauth2/client/CommonOAuth2Provider.java b/config/src/main/java/org/springframework/security/config/oauth2/client/CommonOAuth2Provider.java index 71539b8ac1..6bfac7508a 100644 --- a/config/src/main/java/org/springframework/security/config/oauth2/client/CommonOAuth2Provider.java +++ b/config/src/main/java/org/springframework/security/config/oauth2/client/CommonOAuth2Provider.java @@ -35,8 +35,8 @@ public enum CommonOAuth2Provider { @Override public Builder getBuilder(String registrationId) { - ClientRegistration.Builder builder = getBuilder(registrationId, - ClientAuthenticationMethod.BASIC, DEFAULT_REDIRECT_URL); + ClientRegistration.Builder builder = getBuilder(registrationId, ClientAuthenticationMethod.BASIC, + DEFAULT_REDIRECT_URL); builder.scope("openid", "profile", "email"); builder.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth"); builder.tokenUri("https://www.googleapis.com/oauth2/v4/token"); @@ -53,8 +53,8 @@ public enum CommonOAuth2Provider { @Override public Builder getBuilder(String registrationId) { - ClientRegistration.Builder builder = getBuilder(registrationId, - ClientAuthenticationMethod.BASIC, DEFAULT_REDIRECT_URL); + ClientRegistration.Builder builder = getBuilder(registrationId, ClientAuthenticationMethod.BASIC, + DEFAULT_REDIRECT_URL); builder.scope("read:user"); builder.authorizationUri("https://github.com/login/oauth/authorize"); builder.tokenUri("https://github.com/login/oauth/access_token"); @@ -69,8 +69,8 @@ public enum CommonOAuth2Provider { @Override public Builder getBuilder(String registrationId) { - ClientRegistration.Builder builder = getBuilder(registrationId, - ClientAuthenticationMethod.POST, DEFAULT_REDIRECT_URL); + ClientRegistration.Builder builder = getBuilder(registrationId, ClientAuthenticationMethod.POST, + DEFAULT_REDIRECT_URL); builder.scope("public_profile", "email"); builder.authorizationUri("https://www.facebook.com/v2.8/dialog/oauth"); builder.tokenUri("https://graph.facebook.com/v2.8/oauth/access_token"); @@ -85,8 +85,8 @@ public enum CommonOAuth2Provider { @Override public Builder getBuilder(String registrationId) { - ClientRegistration.Builder builder = getBuilder(registrationId, - ClientAuthenticationMethod.BASIC, DEFAULT_REDIRECT_URL); + ClientRegistration.Builder builder = getBuilder(registrationId, ClientAuthenticationMethod.BASIC, + DEFAULT_REDIRECT_URL); builder.scope("openid", "profile", "email"); builder.userNameAttributeName(IdTokenClaimNames.SUB); builder.clientName("Okta"); @@ -96,8 +96,8 @@ public enum CommonOAuth2Provider { private static final String DEFAULT_REDIRECT_URL = "{baseUrl}/{action}/oauth2/code/{registrationId}"; - protected final ClientRegistration.Builder getBuilder(String registrationId, - ClientAuthenticationMethod method, String redirectUri) { + protected final ClientRegistration.Builder getBuilder(String registrationId, ClientAuthenticationMethod method, + String redirectUri) { ClientRegistration.Builder builder = ClientRegistration.withRegistrationId(registrationId); builder.clientAuthenticationMethod(method); builder.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE); diff --git a/config/src/main/java/org/springframework/security/config/package-info.java b/config/src/main/java/org/springframework/security/config/package-info.java index 9d9c373acf..f564caec1c 100644 --- a/config/src/main/java/org/springframework/security/config/package-info.java +++ b/config/src/main/java/org/springframework/security/config/package-info.java @@ -14,8 +14,7 @@ * limitations under the License. */ /** - * Support classes for the Spring Security namespace. None of the code in these packages should be used directly - * in applications. + * Support classes for the Spring Security namespace. None of the code in these packages + * should be used directly in applications. */ package org.springframework.security.config; - diff --git a/config/src/main/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBean.java b/config/src/main/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBean.java index b6552168c2..219ea6480f 100644 --- a/config/src/main/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBean.java +++ b/config/src/main/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBean.java @@ -28,13 +28,16 @@ import org.springframework.security.util.InMemoryResource; import java.util.Collection; /** - * Constructs an {@link InMemoryUserDetailsManager} from a resource using {@link UserDetailsResourceFactoryBean}. + * Constructs an {@link InMemoryUserDetailsManager} from a resource using + * {@link UserDetailsResourceFactoryBean}. * * @author Rob Winch * @since 5.0 * @see UserDetailsResourceFactoryBean */ -public class UserDetailsManagerResourceFactoryBean implements ResourceLoaderAware, FactoryBean { +public class UserDetailsManagerResourceFactoryBean + implements ResourceLoaderAware, FactoryBean { + private UserDetailsResourceFactoryBean userDetails = new UserDetailsResourceFactoryBean(); @Override @@ -54,17 +57,18 @@ public class UserDetailsManagerResourceFactoryBean implements ResourceLoaderAwar } /** - * Sets the location of a Resource that is a Properties file in the format defined in {@link UserDetailsResourceFactoryBean}. - * - * @param resourceLocation the location of the properties file that contains the users (i.e. "classpath:users.properties") + * Sets the location of a Resource that is a Properties file in the format defined in + * {@link UserDetailsResourceFactoryBean}. + * @param resourceLocation the location of the properties file that contains the users + * (i.e. "classpath:users.properties") */ public void setResourceLocation(String resourceLocation) { this.userDetails.setResourceLocation(resourceLocation); } /** - * Sets a Resource that is a Properties file in the format defined in {@link UserDetailsResourceFactoryBean}. - * + * Sets a Resource that is a Properties file in the format defined in + * {@link UserDetailsResourceFactoryBean}. * @param resource the Resource to use */ public void setResource(Resource resource) { @@ -72,10 +76,11 @@ public class UserDetailsManagerResourceFactoryBean implements ResourceLoaderAwar } /** - * Create a UserDetailsManagerResourceFactoryBean with the location of a Resource that is a Properties file in the - * format defined in {@link UserDetailsResourceFactoryBean}. - * - * @param resourceLocation the location of the properties file that contains the users (i.e. "classpath:users.properties") + * Create a UserDetailsManagerResourceFactoryBean with the location of a Resource that + * is a Properties file in the format defined in + * {@link UserDetailsResourceFactoryBean}. + * @param resourceLocation the location of the properties file that contains the users + * (i.e. "classpath:users.properties") * @return the UserDetailsManagerResourceFactoryBean */ public static UserDetailsManagerResourceFactoryBean fromResourceLocation(String resourceLocation) { @@ -85,9 +90,8 @@ public class UserDetailsManagerResourceFactoryBean implements ResourceLoaderAwar } /** - * Create a UserDetailsManagerResourceFactoryBean with a Resource that is a Properties file in the - * format defined in {@link UserDetailsResourceFactoryBean}. - * + * Create a UserDetailsManagerResourceFactoryBean with a Resource that is a Properties + * file in the format defined in {@link UserDetailsResourceFactoryBean}. * @param resource the Resource that is a properties file that contains the users * @return the UserDetailsManagerResourceFactoryBean */ @@ -98,10 +102,10 @@ public class UserDetailsManagerResourceFactoryBean implements ResourceLoaderAwar } /** - * Create a UserDetailsManagerResourceFactoryBean with a String that is in the - * format defined in {@link UserDetailsResourceFactoryBean}. - * - * @param users the users in the format defined in {@link UserDetailsResourceFactoryBean} + * Create a UserDetailsManagerResourceFactoryBean with a String that is in the format + * defined in {@link UserDetailsResourceFactoryBean}. + * @param users the users in the format defined in + * {@link UserDetailsResourceFactoryBean} * @return the UserDetailsManagerResourceFactoryBean */ public static UserDetailsManagerResourceFactoryBean fromString(String users) { @@ -109,4 +113,5 @@ public class UserDetailsManagerResourceFactoryBean implements ResourceLoaderAwar result.setResource(new InMemoryResource(users)); return result; } + } diff --git a/config/src/main/java/org/springframework/security/config/web/server/AbstractServerWebExchangeMatcherRegistry.java b/config/src/main/java/org/springframework/security/config/web/server/AbstractServerWebExchangeMatcherRegistry.java index fc2641b022..404e89ccdc 100644 --- a/config/src/main/java/org/springframework/security/config/web/server/AbstractServerWebExchangeMatcherRegistry.java +++ b/config/src/main/java/org/springframework/security/config/web/server/AbstractServerWebExchangeMatcherRegistry.java @@ -23,7 +23,6 @@ import org.springframework.security.web.server.util.matcher.ServerWebExchangeMat import java.util.List; - /** * @author Rob Winch * @since 5.0 @@ -32,52 +31,43 @@ abstract class AbstractServerWebExchangeMatcherRegistry { /** * Maps any request. - * - * @return the object that is chained after creating the {@link ServerWebExchangeMatcher} + * @return the object that is chained after creating the + * {@link ServerWebExchangeMatcher} */ public T anyExchange() { return matcher(ServerWebExchangeMatchers.anyExchange()); } /** - * Maps a {@link List} of - * {@link PathPatternParserServerWebExchangeMatcher} - * instances. - * - * @param method the {@link HttpMethod} to use for any - * {@link HttpMethod}. - * - * @return the object that is chained after creating the {@link ServerWebExchangeMatcher} + * Maps a {@link List} of {@link PathPatternParserServerWebExchangeMatcher} instances. + * @param method the {@link HttpMethod} to use for any {@link HttpMethod}. + * @return the object that is chained after creating the + * {@link ServerWebExchangeMatcher} */ public T pathMatchers(HttpMethod method) { return pathMatchers(method, new String[] { "/**" }); } /** - * Maps a {@link List} of - * {@link PathPatternParserServerWebExchangeMatcher} - * instances. - * + * Maps a {@link List} of {@link PathPatternParserServerWebExchangeMatcher} instances. * @param method the {@link HttpMethod} to use or {@code null} for any * {@link HttpMethod}. - * @param antPatterns the ant patterns to create. If {@code null} or empty, then matches on nothing. - * {@link PathPatternParserServerWebExchangeMatcher} from - * - * @return the object that is chained after creating the {@link ServerWebExchangeMatcher} + * @param antPatterns the ant patterns to create. If {@code null} or empty, then + * matches on nothing. {@link PathPatternParserServerWebExchangeMatcher} from + * @return the object that is chained after creating the + * {@link ServerWebExchangeMatcher} */ public T pathMatchers(HttpMethod method, String... antPatterns) { return matcher(ServerWebExchangeMatchers.pathMatchers(method, antPatterns)); } /** - * Maps a {@link List} of - * {@link PathPatternParserServerWebExchangeMatcher} - * instances that do not care which {@link HttpMethod} is used. - * + * Maps a {@link List} of {@link PathPatternParserServerWebExchangeMatcher} instances + * that do not care which {@link HttpMethod} is used. * @param antPatterns the ant patterns to create * {@link PathPatternParserServerWebExchangeMatcher} from - * - * @return the object that is chained after creating the {@link ServerWebExchangeMatcher} + * @return the object that is chained after creating the + * {@link ServerWebExchangeMatcher} */ public T pathMatchers(String... antPatterns) { return matcher(ServerWebExchangeMatchers.pathMatchers(antPatterns)); @@ -85,10 +75,9 @@ abstract class AbstractServerWebExchangeMatcherRegistry { /** * Associates a list of {@link ServerWebExchangeMatcher} instances - * * @param matchers the {@link ServerWebExchangeMatcher} instances - * - * @return the object that is chained after creating the {@link ServerWebExchangeMatcher} + * @return the object that is chained after creating the + * {@link ServerWebExchangeMatcher} */ public T matchers(ServerWebExchangeMatcher... matchers) { return registerMatcher(new OrServerWebExchangeMatcher(matchers)); @@ -97,7 +86,6 @@ abstract class AbstractServerWebExchangeMatcherRegistry { /** * Subclasses should implement this method for returning the object that is chained to * the creation of the {@link ServerWebExchangeMatcher} instances. - * * @param matcher the {@link ServerWebExchangeMatcher} instances that were created * @return the chained Object for the subclass which allows association of something * else to the {@link ServerWebExchangeMatcher} @@ -106,12 +94,12 @@ abstract class AbstractServerWebExchangeMatcherRegistry { /** * Associates a {@link ServerWebExchangeMatcher} instances - * * @param matcher the {@link ServerWebExchangeMatcher} instance - * - * @return the object that is chained after creating the {@link ServerWebExchangeMatcher} + * @return the object that is chained after creating the + * {@link ServerWebExchangeMatcher} */ private T matcher(ServerWebExchangeMatcher matcher) { return registerMatcher(matcher); } + } diff --git a/config/src/main/java/org/springframework/security/config/web/server/SecurityWebFiltersOrder.java b/config/src/main/java/org/springframework/security/config/web/server/SecurityWebFiltersOrder.java index 4078ff5deb..cabc272978 100644 --- a/config/src/main/java/org/springframework/security/config/web/server/SecurityWebFiltersOrder.java +++ b/config/src/main/java/org/springframework/security/config/web/server/SecurityWebFiltersOrder.java @@ -15,14 +15,13 @@ */ package org.springframework.security.config.web.server; - /** * @author Rob Winch * @since 5.0 */ public enum SecurityWebFiltersOrder { - FIRST(Integer.MIN_VALUE), - HTTP_HEADERS_WRITER, + + FIRST(Integer.MIN_VALUE), HTTP_HEADERS_WRITER, /** * {@link org.springframework.security.web.server.transport.HttpsRedirectWebFilter} */ @@ -46,15 +45,11 @@ public enum SecurityWebFiltersOrder { /** * Instance of AuthenticationWebFilter */ - FORM_LOGIN, - AUTHENTICATION, + FORM_LOGIN, AUTHENTICATION, /** * Instance of AnonymousAuthenticationWebFilter */ - ANONYMOUS_AUTHENTICATION, - OAUTH2_AUTHORIZATION_CODE, - LOGIN_PAGE_GENERATING, - LOGOUT_PAGE_GENERATING, + ANONYMOUS_AUTHENTICATION, OAUTH2_AUTHORIZATION_CODE, LOGIN_PAGE_GENERATING, LOGOUT_PAGE_GENERATING, /** * {@link org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter} */ @@ -62,11 +57,7 @@ public enum SecurityWebFiltersOrder { /** * {@link org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter} */ - SERVER_REQUEST_CACHE, - LOGOUT, - EXCEPTION_TRANSLATION, - AUTHORIZATION, - LAST(Integer.MAX_VALUE); + SERVER_REQUEST_CACHE, LOGOUT, EXCEPTION_TRANSLATION, AUTHORIZATION, LAST(Integer.MAX_VALUE); private static final int INTERVAL = 100; @@ -83,4 +74,5 @@ public enum SecurityWebFiltersOrder { public int getOrder() { return this.order; } + } diff --git a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java index 63fc32a93c..c2d7d13a28 100644 --- a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java +++ b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java @@ -182,55 +182,32 @@ import org.springframework.web.server.WebFilterChain; import static org.springframework.security.web.server.DelegatingServerAuthenticationEntryPoint.DelegateEntry; /** - * A {@link ServerHttpSecurity} is similar to Spring Security's {@code HttpSecurity} but for WebFlux. - * It allows configuring web based security for specific http requests. By default it will be applied - * to all requests, but can be restricted using {@link #securityMatcher(ServerWebExchangeMatcher)} or - * other similar methods. + * A {@link ServerHttpSecurity} is similar to Spring Security's {@code HttpSecurity} but + * for WebFlux. It allows configuring web based security for specific http requests. By + * default it will be applied to all requests, but can be restricted using + * {@link #securityMatcher(ServerWebExchangeMatcher)} or other similar methods. * * A minimal configuration can be found below: * - *
    - * @EnableWebFluxSecurity
    - * public class MyMinimalSecurityConfiguration {
    + * 
     @EnableWebFluxSecurity public class
    + * MyMinimalSecurityConfiguration {
      *
    - *     @Bean
    - *     public MapReactiveUserDetailsService userDetailsService() {
    - *          UserDetails user = User.withDefaultPasswordEncoder()
    - *               .username("user")
    - *               .password("password")
    - *               .roles("USER")
    - *               .build();
    - *          return new MapReactiveUserDetailsService(user);
    - *     }
    - * }
    + * @Bean public MapReactiveUserDetailsService userDetailsService() { UserDetails user
    + * = User.withDefaultPasswordEncoder() .username("user") .password("password")
    + * .roles("USER") .build(); return new MapReactiveUserDetailsService(user); } }
      *
      * Below is the same as our minimal configuration, but explicitly declaring the
      * {@code ServerHttpSecurity}.
      *
    - * 
    - * @EnableWebFluxSecurity
    - * public class MyExplicitSecurityConfiguration {
    - *     @Bean
    - *     public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
    - *          http
    - *               .authorizeExchange()
    - *                    .anyExchange().authenticated()
    - *                         .and()
    - *                    .httpBasic().and()
    - *                    .formLogin();
    - *          return http.build();
    - *     }
    + * 
     @EnableWebFluxSecurity public class
    + * MyExplicitSecurityConfiguration { @Bean public SecurityWebFilterChain
    + * springSecurityFilterChain(ServerHttpSecurity http) { http .authorizeExchange()
    + * .anyExchange().authenticated() .and() .httpBasic().and() .formLogin(); return
    + * http.build(); }
      *
    - *     @Bean
    - *     public MapReactiveUserDetailsService userDetailsService() {
    - *          UserDetails user = User.withDefaultPasswordEncoder()
    - *               .username("user")
    - *               .password("password")
    - *               .roles("USER")
    - *               .build();
    - *          return new MapReactiveUserDetailsService(user);
    - *     }
    - * }
    + * @Bean public MapReactiveUserDetailsService userDetailsService() { UserDetails user
    + * = User.withDefaultPasswordEncoder() .username("user") .password("password")
    + * .roles("USER") .build(); return new MapReactiveUserDetailsService(user); } }
      *
      * @author Rob Winch
      * @author Vedran Pavic
    @@ -241,6 +218,7 @@ import static org.springframework.security.web.server.DelegatingServerAuthentica
      * @since 5.0
      */
     public class ServerHttpSecurity {
    +
     	private ServerWebExchangeMatcher securityMatcher = ServerWebExchangeMatchers.anyExchange();
     
     	private AuthorizeExchangeSpec authorizeExchange;
    @@ -283,8 +261,7 @@ public class ServerHttpSecurity {
     
     	private ServerAccessDeniedHandler accessDeniedHandler;
     
    -	private List
    -			defaultAccessDeniedHandlers = new ArrayList<>();
    +	private List defaultAccessDeniedHandlers = new ArrayList<>();
     
     	private List webFilters = new ArrayList<>();
     
    @@ -295,10 +272,10 @@ public class ServerHttpSecurity {
     	private AnonymousSpec anonymous;
     
     	/**
    -	 * The ServerExchangeMatcher that determines which requests apply to this HttpSecurity instance.
    -	 *
    -	 * @param matcher the ServerExchangeMatcher that determines which requests apply to this HttpSecurity instance.
    -	 *                Default is all requests.
    +	 * The ServerExchangeMatcher that determines which requests apply to this HttpSecurity
    +	 * instance.
    +	 * @param matcher the ServerExchangeMatcher that determines which requests apply to
    +	 * this HttpSecurity instance. Default is all requests.
     	 * @return the {@link ServerHttpSecurity} to continue configuring
     	 */
     	public ServerHttpSecurity securityMatcher(ServerWebExchangeMatcher matcher) {
    @@ -345,16 +322,19 @@ public class ServerHttpSecurity {
     	}
     
     	/**
    -	 * Gets the ServerExchangeMatcher that determines which requests apply to this HttpSecurity instance.
    -	 * @return the ServerExchangeMatcher that determines which requests apply to this HttpSecurity instance.
    +	 * Gets the ServerExchangeMatcher that determines which requests apply to this
    +	 * HttpSecurity instance.
    +	 * @return the ServerExchangeMatcher that determines which requests apply to this
    +	 * HttpSecurity instance.
     	 */
     	private ServerWebExchangeMatcher getSecurityMatcher() {
     		return this.securityMatcher;
     	}
     
     	/**
    -	 * The strategy used with {@code ReactorContextWebFilter}. It does impact how the {@code SecurityContext} is
    -	 * saved which is configured on a per {@link AuthenticationWebFilter} basis.
    +	 * The strategy used with {@code ReactorContextWebFilter}. It does impact how the
    +	 * {@code SecurityContext} is saved which is configured on a per
    +	 * {@link AuthenticationWebFilter} basis.
     	 * @param securityContextRepository the repository to use
     	 * @return the {@link ServerHttpSecurity} to continue configuring
     	 */
    @@ -379,7 +359,8 @@ public class ServerHttpSecurity {
     	 *
     	 * Then all non-HTTPS requests will be redirected to HTTPS.
     	 *
    -	 * Typically, all requests should be HTTPS; however, the focus for redirection can also be narrowed:
    +	 * Typically, all requests should be HTTPS; however, the focus for redirection can
    +	 * also be narrowed:
     	 *
     	 * 
     	 *  @Bean
    @@ -392,7 +373,6 @@ public class ServerHttpSecurity {
     	 * 	    return http.build();
     	 * 	}
     	 * 
    - * * @return the {@link HttpsRedirectSpec} to customize */ public HttpsRedirectSpec redirectToHttps() { @@ -415,7 +395,8 @@ public class ServerHttpSecurity { * * Then all non-HTTPS requests will be redirected to HTTPS. * - * Typically, all requests should be HTTPS; however, the focus for redirection can also be narrowed: + * Typically, all requests should be HTTPS; however, the focus for redirection can + * also be narrowed: * *
     	 *  @Bean
    @@ -430,20 +411,20 @@ public class ServerHttpSecurity {
     	 * 	    return http.build();
     	 * 	}
     	 * 
    - * * @param httpsRedirectCustomizer the {@link Customizer} to provide more options for * the {@link HttpsRedirectSpec} * @return the {@link ServerHttpSecurity} to customize */ - public ServerHttpSecurity redirectToHttps(Customizer httpsRedirectCustomizer) { + public ServerHttpSecurity redirectToHttps(Customizer httpsRedirectCustomizer) { this.httpsRedirectSpec = new HttpsRedirectSpec(); httpsRedirectCustomizer.customize(this.httpsRedirectSpec); return this; } /** - * Configures CSRF Protection - * which is enabled by default. You can disable it using: + * Configures CSRF + * Protection which is enabled by default. You can disable it using: * *
     	 *  @Bean
    @@ -473,7 +454,6 @@ public class ServerHttpSecurity {
     	 *      return http.build();
     	 *  }
     	 * 
    - * * @return the {@link CsrfSpec} to customize */ public CsrfSpec csrf() { @@ -484,8 +464,9 @@ public class ServerHttpSecurity { } /** - * Configures CSRF Protection - * which is enabled by default. You can disable it using: + * Configures CSRF + * Protection which is enabled by default. You can disable it using: * *
     	 *  @Bean
    @@ -519,9 +500,8 @@ public class ServerHttpSecurity {
     	 *      return http.build();
     	 *  }
     	 * 
    - * - * @param csrfCustomizer the {@link Customizer} to provide more options for - * the {@link CsrfSpec} + * @param csrfCustomizer the {@link Customizer} to provide more options for the + * {@link CsrfSpec} * @return the {@link ServerHttpSecurity} to customize */ public ServerHttpSecurity csrf(Customizer csrfCustomizer) { @@ -533,9 +513,11 @@ public class ServerHttpSecurity { } /** - * Configures CORS headers. By default if a {@link CorsConfigurationSource} Bean is found, it will be used - * to create a {@link CorsWebFilter}. If {@link CorsSpec#configurationSource(CorsConfigurationSource)} is invoked - * it will be used instead. If neither has been configured, the Cors configuration will do nothing. + * Configures CORS headers. By default if a {@link CorsConfigurationSource} Bean is + * found, it will be used to create a {@link CorsWebFilter}. If + * {@link CorsSpec#configurationSource(CorsConfigurationSource)} is invoked it will be + * used instead. If neither has been configured, the Cors configuration will do + * nothing. * @return the {@link CorsSpec} to customize */ public CorsSpec cors() { @@ -546,12 +528,13 @@ public class ServerHttpSecurity { } /** - * Configures CORS headers. By default if a {@link CorsConfigurationSource} Bean is found, it will be used - * to create a {@link CorsWebFilter}. If {@link CorsSpec#configurationSource(CorsConfigurationSource)} is invoked - * it will be used instead. If neither has been configured, the Cors configuration will do nothing. - * - * @param corsCustomizer the {@link Customizer} to provide more options for - * the {@link CorsSpec} + * Configures CORS headers. By default if a {@link CorsConfigurationSource} Bean is + * found, it will be used to create a {@link CorsWebFilter}. If + * {@link CorsSpec#configurationSource(CorsConfigurationSource)} is invoked it will be + * used instead. If neither has been configured, the Cors configuration will do + * nothing. + * @param corsCustomizer the {@link Customizer} to provide more options for the + * {@link CorsSpec} * @return the {@link ServerHttpSecurity} to customize */ public ServerHttpSecurity cors(Customizer corsCustomizer) { @@ -563,7 +546,8 @@ public class ServerHttpSecurity { } /** - * Enables and Configures anonymous authentication. Anonymous Authentication is disabled by default. + * Enables and Configures anonymous authentication. Anonymous Authentication is + * disabled by default. * *
     	 *  @Bean
    @@ -579,7 +563,7 @@ public class ServerHttpSecurity {
     	 * @since 5.2.0
     	 * @author Ankur Pathak
     	 */
    -	public AnonymousSpec anonymous(){
    +	public AnonymousSpec anonymous() {
     		if (this.anonymous == null) {
     			this.anonymous = new AnonymousSpec();
     		}
    @@ -587,7 +571,8 @@ public class ServerHttpSecurity {
     	}
     
     	/**
    -	 * Enables and Configures anonymous authentication. Anonymous Authentication is disabled by default.
    +	 * Enables and Configures anonymous authentication. Anonymous Authentication is
    +	 * disabled by default.
     	 *
     	 * 
     	 *  @Bean
    @@ -602,9 +587,8 @@ public class ServerHttpSecurity {
     	 *      return http.build();
     	 *  }
     	 * 
    - * - * @param anonymousCustomizer the {@link Customizer} to provide more options for - * the {@link AnonymousSpec} + * @param anonymousCustomizer the {@link Customizer} to provide more options for the + * {@link AnonymousSpec} * @return the {@link ServerHttpSecurity} to customize */ public ServerHttpSecurity anonymous(Customizer anonymousCustomizer) { @@ -616,10 +600,11 @@ public class ServerHttpSecurity { } /** - * Configures CORS support within Spring Security. This ensures that the {@link CorsWebFilter} is place in the - * correct order. + * Configures CORS support within Spring Security. This ensures that the + * {@link CorsWebFilter} is place in the correct order. */ public class CorsSpec { + private CorsWebFilter corsFilter; /** @@ -673,7 +658,9 @@ public class ServerHttpSecurity { return this.corsFilter; } - private CorsSpec() {} + private CorsSpec() { + } + } /** @@ -692,7 +679,6 @@ public class ServerHttpSecurity { * return http.build(); * } *
    - * * @return the {@link HttpBasicSpec} to customize */ public HttpBasicSpec httpBasic() { @@ -720,9 +706,8 @@ public class ServerHttpSecurity { * return http.build(); * } *
    - * - * @param httpBasicCustomizer the {@link Customizer} to provide more options for - * the {@link HttpBasicSpec} + * @param httpBasicCustomizer the {@link Customizer} to provide more options for the + * {@link HttpBasicSpec} * @return the {@link ServerHttpSecurity} to customize */ public ServerHttpSecurity httpBasic(Customizer httpBasicCustomizer) { @@ -753,7 +738,6 @@ public class ServerHttpSecurity { * return http.build(); * } *
    - * * @return the {@link FormLoginSpec} to customize */ public FormLoginSpec formLogin() { @@ -785,9 +769,8 @@ public class ServerHttpSecurity { * return http.build(); * } *
    - * - * @param formLoginCustomizer the {@link Customizer} to provide more options for - * the {@link FormLoginSpec} + * @param formLoginCustomizer the {@link Customizer} to provide more options for the + * {@link FormLoginSpec} * @return the {@link ServerHttpSecurity} to customize */ public ServerHttpSecurity formLogin(Customizer formLoginCustomizer) { @@ -812,9 +795,9 @@ public class ServerHttpSecurity { * } *
    * - * Note that if extractor is not specified, {@link SubjectDnX509PrincipalExtractor} will be used. - * If authenticationManager is not specified, {@link ReactivePreAuthenticatedAuthenticationManager} will be used. - * + * Note that if extractor is not specified, {@link SubjectDnX509PrincipalExtractor} + * will be used. If authenticationManager is not specified, + * {@link ReactivePreAuthenticatedAuthenticationManager} will be used. * @return the {@link X509Spec} to customize * @author Alexey Nesterov * @since 5.2 @@ -843,12 +826,13 @@ public class ServerHttpSecurity { * } * * - * Note that if extractor is not specified, {@link SubjectDnX509PrincipalExtractor} will be used. - * If authenticationManager is not specified, {@link ReactivePreAuthenticatedAuthenticationManager} will be used. + * Note that if extractor is not specified, {@link SubjectDnX509PrincipalExtractor} + * will be used. If authenticationManager is not specified, + * {@link ReactivePreAuthenticatedAuthenticationManager} will be used. * * @since 5.2 - * @param x509Customizer the {@link Customizer} to provide more options for - * the {@link X509Spec} + * @param x509Customizer the {@link Customizer} to provide more options for the + * {@link X509Spec} * @return the {@link ServerHttpSecurity} to customize */ public ServerHttpSecurity x509(Customizer x509Customizer) { @@ -869,6 +853,7 @@ public class ServerHttpSecurity { public class X509Spec { private X509PrincipalExtractor principalExtractor; + private ReactiveAuthenticationManager authenticationManager; public X509Spec principalExtractor(X509PrincipalExtractor principalExtractor) { @@ -908,17 +893,20 @@ public class ServerHttpSecurity { } ReactiveUserDetailsService userDetailsService = getBean(ReactiveUserDetailsService.class); - ReactivePreAuthenticatedAuthenticationManager authenticationManager = new ReactivePreAuthenticatedAuthenticationManager(userDetailsService); + ReactivePreAuthenticatedAuthenticationManager authenticationManager = new ReactivePreAuthenticatedAuthenticationManager( + userDetailsService); return authenticationManager; } private X509Spec() { } + } /** - * Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 Provider. + * Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 + * Provider. * *
     	 *  @Bean
    @@ -931,8 +919,6 @@ public class ServerHttpSecurity {
     	 *      return http.build();
     	 *  }
     	 * 
    - * - * * @return the {@link OAuth2LoginSpec} to customize */ public OAuth2LoginSpec oauth2Login() { @@ -943,7 +929,8 @@ public class ServerHttpSecurity { } /** - * Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 Provider. + * Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 + * Provider. * *
     	 *  @Bean
    @@ -958,9 +945,8 @@ public class ServerHttpSecurity {
     	 *      return http.build();
     	 *  }
     	 * 
    - * - * @param oauth2LoginCustomizer the {@link Customizer} to provide more options for - * the {@link OAuth2LoginSpec} + * @param oauth2LoginCustomizer the {@link Customizer} to provide more options for the + * {@link OAuth2LoginSpec} * @return the {@link ServerHttpSecurity} to customize */ public ServerHttpSecurity oauth2Login(Customizer oauth2LoginCustomizer) { @@ -972,6 +958,7 @@ public class ServerHttpSecurity { } public class OAuth2LoginSpec { + private ReactiveClientRegistrationRepository clientRegistrationRepository; private ServerOAuth2AuthorizedClientRepository authorizedClientRepository; @@ -1004,7 +991,8 @@ public class ServerHttpSecurity { } /** - * The {@link ServerSecurityContextRepository} used to save the {@code Authentication}. Defaults to + * The {@link ServerSecurityContextRepository} used to save the + * {@code Authentication}. Defaults to * {@link WebSessionServerSecurityContextRepository}. * * @since 5.2 @@ -1017,37 +1005,41 @@ public class ServerHttpSecurity { } /** - * The {@link ServerAuthenticationSuccessHandler} used after authentication success. Defaults to - * {@link RedirectServerAuthenticationSuccessHandler} redirecting to "/". + * The {@link ServerAuthenticationSuccessHandler} used after authentication + * success. Defaults to {@link RedirectServerAuthenticationSuccessHandler} + * redirecting to "/". * * @since 5.2 * @param authenticationSuccessHandler the success handler to use * @return the {@link OAuth2LoginSpec} to customize */ - public OAuth2LoginSpec authenticationSuccessHandler(ServerAuthenticationSuccessHandler authenticationSuccessHandler) { + public OAuth2LoginSpec authenticationSuccessHandler( + ServerAuthenticationSuccessHandler authenticationSuccessHandler) { Assert.notNull(authenticationSuccessHandler, "authenticationSuccessHandler cannot be null"); this.authenticationSuccessHandler = authenticationSuccessHandler; return this; } /** - * The {@link ServerAuthenticationFailureHandler} used after authentication failure. - * Defaults to {@link RedirectServerAuthenticationFailureHandler} redirecting to "/login?error". + * The {@link ServerAuthenticationFailureHandler} used after authentication + * failure. Defaults to {@link RedirectServerAuthenticationFailureHandler} + * redirecting to "/login?error". * * @since 5.2 * @param authenticationFailureHandler the failure handler to use * @return the {@link OAuth2LoginSpec} to customize */ - public OAuth2LoginSpec authenticationFailureHandler(ServerAuthenticationFailureHandler authenticationFailureHandler) { + public OAuth2LoginSpec authenticationFailureHandler( + ServerAuthenticationFailureHandler authenticationFailureHandler) { Assert.notNull(authenticationFailureHandler, "authenticationFailureHandler cannot be null"); this.authenticationFailureHandler = authenticationFailureHandler; return this; } /** - * Gets the {@link ReactiveAuthenticationManager} to use. First tries an explicitly configured manager, and - * defaults to {@link OAuth2AuthorizationCodeReactiveAuthenticationManager} - * + * Gets the {@link ReactiveAuthenticationManager} to use. First tries an + * explicitly configured manager, and defaults to + * {@link OAuth2AuthorizationCodeReactiveAuthenticationManager} * @return the {@link ReactiveAuthenticationManager} to use */ private ReactiveAuthenticationManager getAuthenticationManager() { @@ -1059,18 +1051,19 @@ public class ServerHttpSecurity { private ReactiveAuthenticationManager createDefault() { ReactiveOAuth2AccessTokenResponseClient client = getAccessTokenResponseClient(); - OAuth2LoginReactiveAuthenticationManager oauth2Manager = new OAuth2LoginReactiveAuthenticationManager(client, getOauth2UserService()); + OAuth2LoginReactiveAuthenticationManager oauth2Manager = new OAuth2LoginReactiveAuthenticationManager( + client, getOauth2UserService()); GrantedAuthoritiesMapper authoritiesMapper = getBeanOrNull(GrantedAuthoritiesMapper.class); if (authoritiesMapper != null) { oauth2Manager.setAuthoritiesMapper(authoritiesMapper); } - boolean oidcAuthenticationProviderEnabled = ClassUtils.isPresent( - "org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader()); + boolean oidcAuthenticationProviderEnabled = ClassUtils + .isPresent("org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader()); if (oidcAuthenticationProviderEnabled) { - OidcAuthorizationCodeReactiveAuthenticationManager oidc = - new OidcAuthorizationCodeReactiveAuthenticationManager(client, getOidcUserService()); - ResolvableType type = ResolvableType.forClassWithGenerics( - ReactiveJwtDecoderFactory.class, ClientRegistration.class); + OidcAuthorizationCodeReactiveAuthenticationManager oidc = new OidcAuthorizationCodeReactiveAuthenticationManager( + client, getOidcUserService()); + ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveJwtDecoderFactory.class, + ClientRegistration.class); ReactiveJwtDecoderFactory jwtDecoderFactory = getBeanOrNull(type); if (jwtDecoderFactory != null) { oidc.setJwtDecoderFactory(jwtDecoderFactory); @@ -1093,13 +1086,14 @@ public class ServerHttpSecurity { return this; } - private ServerAuthenticationConverter getAuthenticationConverter(ReactiveClientRegistrationRepository clientRegistrationRepository) { + private ServerAuthenticationConverter getAuthenticationConverter( + ReactiveClientRegistrationRepository clientRegistrationRepository) { if (this.authenticationConverter == null) { - ServerOAuth2AuthorizationCodeAuthenticationTokenConverter delegate = - new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter(clientRegistrationRepository); + ServerOAuth2AuthorizationCodeAuthenticationTokenConverter delegate = new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter( + clientRegistrationRepository); delegate.setAuthorizationRequestRepository(getAuthorizationRequestRepository()); - ServerAuthenticationConverter authenticationConverter = exchange -> - delegate.convert(exchange).onErrorMap(OAuth2AuthorizationException.class, + ServerAuthenticationConverter authenticationConverter = exchange -> delegate.convert(exchange) + .onErrorMap(OAuth2AuthorizationException.class, e -> new OAuth2AuthenticationException(e.getError(), e.getError().toString())); this.authenticationConverter = authenticationConverter; return authenticationConverter; @@ -1107,17 +1101,20 @@ public class ServerHttpSecurity { return this.authenticationConverter; } - public OAuth2LoginSpec clientRegistrationRepository(ReactiveClientRegistrationRepository clientRegistrationRepository) { + public OAuth2LoginSpec clientRegistrationRepository( + ReactiveClientRegistrationRepository clientRegistrationRepository) { this.clientRegistrationRepository = clientRegistrationRepository; return this; } public OAuth2LoginSpec authorizedClientService(ReactiveOAuth2AuthorizedClientService authorizedClientService) { - this.authorizedClientRepository = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService); + this.authorizedClientRepository = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository( + authorizedClientService); return this; } - public OAuth2LoginSpec authorizedClientRepository(ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { + public OAuth2LoginSpec authorizedClientRepository( + ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { this.authorizedClientRepository = authorizedClientRepository; return this; } @@ -1126,7 +1123,8 @@ public class ServerHttpSecurity { * Sets the repository to use for storing {@link OAuth2AuthorizationRequest}'s. * * @since 5.2 - * @param authorizationRequestRepository the repository to use for storing {@link OAuth2AuthorizationRequest}'s + * @param authorizationRequestRepository the repository to use for storing + * {@link OAuth2AuthorizationRequest}'s * @return the {@link OAuth2LoginSpec} for further configuration */ public OAuth2LoginSpec authorizationRequestRepository( @@ -1139,19 +1137,23 @@ public class ServerHttpSecurity { * Sets the resolver used for resolving {@link OAuth2AuthorizationRequest}'s. * * @since 5.2 - * @param authorizationRequestResolver the resolver used for resolving {@link OAuth2AuthorizationRequest}'s + * @param authorizationRequestResolver the resolver used for resolving + * {@link OAuth2AuthorizationRequest}'s * @return the {@link OAuth2LoginSpec} for further configuration */ - public OAuth2LoginSpec authorizationRequestResolver(ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver) { + public OAuth2LoginSpec authorizationRequestResolver( + ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver) { this.authorizationRequestResolver = authorizationRequestResolver; return this; } /** - * Sets the {@link ServerWebExchangeMatcher matcher} used for determining if the request is an authentication request. + * Sets the {@link ServerWebExchangeMatcher matcher} used for determining if the + * request is an authentication request. * * @since 5.2 - * @param authenticationMatcher the {@link ServerWebExchangeMatcher matcher} used for determining if the request is an authentication request + * @param authenticationMatcher the {@link ServerWebExchangeMatcher matcher} used + * for determining if the request is an authentication request * @return the {@link OAuth2LoginSpec} for further configuration */ public OAuth2LoginSpec authenticationMatcher(ServerWebExchangeMatcher authenticationMatcher) { @@ -1174,21 +1176,21 @@ public class ServerHttpSecurity { return ServerHttpSecurity.this; } - protected void configure(ServerHttpSecurity http) { ReactiveClientRegistrationRepository clientRegistrationRepository = getClientRegistrationRepository(); ServerOAuth2AuthorizedClientRepository authorizedClientRepository = getAuthorizedClientRepository(); OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter = getRedirectWebFilter(); - ServerAuthorizationRequestRepository authorizationRequestRepository = - getAuthorizationRequestRepository(); + ServerAuthorizationRequestRepository authorizationRequestRepository = getAuthorizationRequestRepository(); oauthRedirectFilter.setAuthorizationRequestRepository(authorizationRequestRepository); oauthRedirectFilter.setRequestCache(http.requestCache.requestCache); ReactiveAuthenticationManager manager = getAuthenticationManager(); - AuthenticationWebFilter authenticationFilter = new OAuth2LoginAuthenticationWebFilter(manager, authorizedClientRepository); + AuthenticationWebFilter authenticationFilter = new OAuth2LoginAuthenticationWebFilter(manager, + authorizedClientRepository); authenticationFilter.setRequiresAuthenticationMatcher(getAuthenticationMatcher()); - authenticationFilter.setServerAuthenticationConverter(getAuthenticationConverter(clientRegistrationRepository)); + authenticationFilter + .setServerAuthenticationConverter(getAuthenticationConverter(clientRegistrationRepository)); authenticationFilter.setAuthenticationSuccessHandler(getAuthenticationSuccessHandler(http)); authenticationFilter.setAuthenticationFailureHandler(getAuthenticationFailureHandler()); @@ -1209,8 +1211,8 @@ public class ServerHttpSecurity { } MediaTypeServerWebExchangeMatcher htmlMatcher = new MediaTypeServerWebExchangeMatcher( - MediaType.APPLICATION_XHTML_XML, new MediaType("image", "*"), - MediaType.TEXT_HTML, MediaType.TEXT_PLAIN); + MediaType.APPLICATION_XHTML_XML, new MediaType("image", "*"), MediaType.TEXT_HTML, + MediaType.TEXT_PLAIN); htmlMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); ServerWebExchangeMatcher xhrMatcher = exchange -> { @@ -1221,25 +1223,26 @@ public class ServerHttpSecurity { }; ServerWebExchangeMatcher notXhrMatcher = new NegatedServerWebExchangeMatcher(xhrMatcher); - ServerWebExchangeMatcher defaultEntryPointMatcher = new AndServerWebExchangeMatcher( - notXhrMatcher, htmlMatcher); + ServerWebExchangeMatcher defaultEntryPointMatcher = new AndServerWebExchangeMatcher(notXhrMatcher, + htmlMatcher); if (providerLoginPage != null) { - ServerWebExchangeMatcher loginPageMatcher = new PathPatternParserServerWebExchangeMatcher(defaultLoginPage); + ServerWebExchangeMatcher loginPageMatcher = new PathPatternParserServerWebExchangeMatcher( + defaultLoginPage); ServerWebExchangeMatcher faviconMatcher = new PathPatternParserServerWebExchangeMatcher("/favicon.ico"); ServerWebExchangeMatcher defaultLoginPageMatcher = new AndServerWebExchangeMatcher( new OrServerWebExchangeMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher); - ServerWebExchangeMatcher matcher = new AndServerWebExchangeMatcher( - notXhrMatcher, new NegatedServerWebExchangeMatcher(defaultLoginPageMatcher)); - RedirectServerAuthenticationEntryPoint entryPoint = - new RedirectServerAuthenticationEntryPoint(providerLoginPage); + ServerWebExchangeMatcher matcher = new AndServerWebExchangeMatcher(notXhrMatcher, + new NegatedServerWebExchangeMatcher(defaultLoginPageMatcher)); + RedirectServerAuthenticationEntryPoint entryPoint = new RedirectServerAuthenticationEntryPoint( + providerLoginPage); entryPoint.setRequestCache(http.requestCache.requestCache); http.defaultEntryPoints.add(new DelegateEntry(matcher, entryPoint)); } - RedirectServerAuthenticationEntryPoint defaultEntryPoint = - new RedirectServerAuthenticationEntryPoint(defaultLoginPage); + RedirectServerAuthenticationEntryPoint defaultEntryPoint = new RedirectServerAuthenticationEntryPoint( + defaultLoginPage); defaultEntryPoint.setRequestCache(http.requestCache.requestCache); http.defaultEntryPoints.add(new DelegateEntry(defaultEntryPointMatcher, defaultEntryPoint)); } @@ -1265,7 +1268,8 @@ public class ServerHttpSecurity { } private ReactiveOAuth2UserService getOidcUserService() { - ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2UserService.class, OidcUserRequest.class, OidcUser.class); + ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2UserService.class, + OidcUserRequest.class, OidcUser.class); ReactiveOAuth2UserService bean = getBeanOrNull(type); if (bean == null) { return new OidcReactiveOAuth2UserService(); @@ -1275,7 +1279,8 @@ public class ServerHttpSecurity { } private ReactiveOAuth2UserService getOauth2UserService() { - ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2UserService.class, OAuth2UserRequest.class, OAuth2User.class); + ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2UserService.class, + OAuth2UserRequest.class, OAuth2User.class); ReactiveOAuth2UserService bean = getBeanOrNull(type); if (bean == null) { return new DefaultReactiveOAuth2UserService(); @@ -1285,17 +1290,20 @@ public class ServerHttpSecurity { } private Map getLinks() { - Iterable registrations = getBeanOrNull(ResolvableType.forClassWithGenerics(Iterable.class, ClientRegistration.class)); + Iterable registrations = getBeanOrNull( + ResolvableType.forClassWithGenerics(Iterable.class, ClientRegistration.class)); if (registrations == null) { return Collections.emptyMap(); } Map result = new HashMap<>(); - registrations.iterator().forEachRemaining(r -> result.put("/oauth2/authorization/" + r.getRegistrationId(), r.getClientName())); + registrations.iterator().forEachRemaining( + r -> result.put("/oauth2/authorization/" + r.getRegistrationId(), r.getClientName())); return result; } private ReactiveOAuth2AccessTokenResponseClient getAccessTokenResponseClient() { - ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2AccessTokenResponseClient.class, OAuth2AuthorizationCodeGrantRequest.class); + ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2AccessTokenResponseClient.class, + OAuth2AuthorizationCodeGrantRequest.class); ReactiveOAuth2AccessTokenResponseClient bean = getBeanOrNull(type); if (bean == null) { return new WebClientReactiveAuthorizationCodeTokenResponseClient(); @@ -1313,9 +1321,12 @@ public class ServerHttpSecurity { private OAuth2AuthorizationRequestRedirectWebFilter getRedirectWebFilter() { OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter; if (this.authorizationRequestResolver == null) { - oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter(getClientRegistrationRepository()); - } else { - oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter(this.authorizationRequestResolver); + oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter( + getClientRegistrationRepository()); + } + else { + oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter( + this.authorizationRequestResolver); } return oauthRedirectFilter; } @@ -1328,8 +1339,7 @@ public class ServerHttpSecurity { if (result == null) { ReactiveOAuth2AuthorizedClientService authorizedClientService = getAuthorizedClientService(); if (authorizedClientService != null) { - result = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository( - authorizedClientService); + result = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService); } } return result; @@ -1350,7 +1360,9 @@ public class ServerHttpSecurity { return service; } - private OAuth2LoginSpec() {} + private OAuth2LoginSpec() { + } + } /** @@ -1367,8 +1379,6 @@ public class ServerHttpSecurity { * return http.build(); * } * - * - * * @return the {@link OAuth2ClientSpec} to customize */ public OAuth2ClientSpec oauth2Client() { @@ -1394,7 +1404,6 @@ public class ServerHttpSecurity { * return http.build(); * } * - * * @param oauth2ClientCustomizer the {@link Customizer} to provide more options for * the {@link OAuth2ClientSpec} * @return the {@link ServerHttpSecurity} to customize @@ -1408,6 +1417,7 @@ public class ServerHttpSecurity { } public class OAuth2ClientSpec { + private ReactiveClientRegistrationRepository clientRegistrationRepository; private ServerAuthenticationConverter authenticationConverter; @@ -1430,8 +1440,8 @@ public class ServerHttpSecurity { private ServerAuthenticationConverter getAuthenticationConverter() { if (this.authenticationConverter == null) { - ServerOAuth2AuthorizationCodeAuthenticationTokenConverter authenticationConverter = - new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter(getClientRegistrationRepository()); + ServerOAuth2AuthorizationCodeAuthenticationTokenConverter authenticationConverter = new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter( + getClientRegistrationRepository()); authenticationConverter.setAuthorizationRequestRepository(getAuthorizationRequestRepository()); this.authenticationConverter = authenticationConverter; } @@ -1450,34 +1460,39 @@ public class ServerHttpSecurity { } /** - * Gets the {@link ReactiveAuthenticationManager} to use. First tries an explicitly configured manager, and - * defaults to {@link OAuth2AuthorizationCodeReactiveAuthenticationManager} - * + * Gets the {@link ReactiveAuthenticationManager} to use. First tries an + * explicitly configured manager, and defaults to + * {@link OAuth2AuthorizationCodeReactiveAuthenticationManager} * @return the {@link ReactiveAuthenticationManager} to use */ private ReactiveAuthenticationManager getAuthenticationManager() { if (this.authenticationManager == null) { - this.authenticationManager = new OAuth2AuthorizationCodeReactiveAuthenticationManager(new WebClientReactiveAuthorizationCodeTokenResponseClient()); + this.authenticationManager = new OAuth2AuthorizationCodeReactiveAuthenticationManager( + new WebClientReactiveAuthorizationCodeTokenResponseClient()); } return this.authenticationManager; } /** - * Configures the {@link ReactiveClientRegistrationRepository}. Default is to look the value up as a Bean. + * Configures the {@link ReactiveClientRegistrationRepository}. Default is to look + * the value up as a Bean. * @param clientRegistrationRepository the repository to use * @return the {@link OAuth2ClientSpec} to customize */ - public OAuth2ClientSpec clientRegistrationRepository(ReactiveClientRegistrationRepository clientRegistrationRepository) { + public OAuth2ClientSpec clientRegistrationRepository( + ReactiveClientRegistrationRepository clientRegistrationRepository) { this.clientRegistrationRepository = clientRegistrationRepository; return this; } /** - * Configures the {@link ReactiveClientRegistrationRepository}. Default is to look the value up as a Bean. + * Configures the {@link ReactiveClientRegistrationRepository}. Default is to look + * the value up as a Bean. * @param authorizedClientRepository the repository to use * @return the {@link OAuth2ClientSpec} to customize */ - public OAuth2ClientSpec authorizedClientRepository(ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { + public OAuth2ClientSpec authorizedClientRepository( + ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { this.authorizedClientRepository = authorizedClientRepository; return this; } @@ -1486,7 +1501,8 @@ public class ServerHttpSecurity { * Sets the repository to use for storing {@link OAuth2AuthorizationRequest}'s. * * @since 5.2 - * @param authorizationRequestRepository the repository to use for storing {@link OAuth2AuthorizationRequest}'s + * @param authorizationRequestRepository the repository to use for storing + * {@link OAuth2AuthorizationRequest}'s * @return the {@link OAuth2ClientSpec} to customize */ public OAuth2ClientSpec authorizationRequestRepository( @@ -1548,8 +1564,7 @@ public class ServerHttpSecurity { if (result == null) { ReactiveOAuth2AuthorizedClientService authorizedClientService = getAuthorizedClientService(); if (authorizedClientService != null) { - result = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository( - authorizedClientService); + result = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService); } } return result; @@ -1563,7 +1578,9 @@ public class ServerHttpSecurity { return service; } - private OAuth2ClientSpec() {} + private OAuth2ClientSpec() { + } + } /** @@ -1580,7 +1597,6 @@ public class ServerHttpSecurity { * return http.build(); * } * - * * @return the {@link OAuth2ResourceServerSpec} to customize */ public OAuth2ResourceServerSpec oauth2ResourceServer() { @@ -1608,12 +1624,12 @@ public class ServerHttpSecurity { * return http.build(); * } * - * - * @param oauth2ResourceServerCustomizer the {@link Customizer} to provide more options for - * the {@link OAuth2ResourceServerSpec} + * @param oauth2ResourceServerCustomizer the {@link Customizer} to provide more + * options for the {@link OAuth2ResourceServerSpec} * @return the {@link ServerHttpSecurity} to customize */ - public ServerHttpSecurity oauth2ResourceServer(Customizer oauth2ResourceServerCustomizer) { + public ServerHttpSecurity oauth2ResourceServer( + Customizer oauth2ResourceServerCustomizer) { if (this.resourceServer == null) { this.resourceServer = new OAuth2ResourceServerSpec(); } @@ -1625,20 +1641,26 @@ public class ServerHttpSecurity { * Configures OAuth2 Resource Server Support */ public class OAuth2ResourceServerSpec { + private ServerAuthenticationEntryPoint entryPoint = new BearerTokenServerAuthenticationEntryPoint(); + private ServerAccessDeniedHandler accessDeniedHandler = new BearerTokenServerAccessDeniedHandler(); + private ServerAuthenticationConverter bearerTokenConverter = new ServerBearerTokenAuthenticationConverter(); + private AuthenticationConverterServerWebExchangeMatcher authenticationConverterServerWebExchangeMatcher; private JwtSpec jwt; + private OpaqueTokenSpec opaqueToken; + private ReactiveAuthenticationManagerResolver authenticationManagerResolver; /** - * Configures the {@link ServerAccessDeniedHandler} to use for requests authenticating with - * Bearer Tokens. - * requests. - * + * Configures the {@link ServerAccessDeniedHandler} to use for requests + * authenticating with + * Bearer Tokens. requests. * @param accessDeniedHandler the {@link ServerAccessDeniedHandler} to use * @return the {@link OAuth2ResourceServerSpec} for additional configuration * @since 5.2 @@ -1650,9 +1672,10 @@ public class ServerHttpSecurity { } /** - * Configures the {@link ServerAuthenticationEntryPoint} to use for requests authenticating with - * Bearer Tokens. - * + * Configures the {@link ServerAuthenticationEntryPoint} to use for requests + * authenticating with + * Bearer Tokens. * @param entryPoint the {@link ServerAuthenticationEntryPoint} to use * @return the {@link OAuth2ResourceServerSpec} for additional configuration * @since 5.2 @@ -1664,9 +1687,10 @@ public class ServerHttpSecurity { } /** - * Configures the {@link ServerAuthenticationConverter} to use for requests authenticating with - * Bearer Tokens. - * + * Configures the {@link ServerAuthenticationConverter} to use for requests + * authenticating with + * Bearer Tokens. * @param bearerTokenConverter The {@link ServerAuthenticationConverter} to use * @return The {@link OAuth2ResourceServerSpec} for additional configuration * @since 5.2 @@ -1679,8 +1703,8 @@ public class ServerHttpSecurity { /** * Configures the {@link ReactiveAuthenticationManagerResolver} - * - * @param authenticationManagerResolver the {@link ReactiveAuthenticationManagerResolver} + * @param authenticationManagerResolver the + * {@link ReactiveAuthenticationManagerResolver} * @return the {@link OAuth2ResourceServerSpec} for additional configuration * @since 5.3 */ @@ -1693,7 +1717,6 @@ public class ServerHttpSecurity { /** * Enables JWT Resource Server support. - * * @return the {@link JwtSpec} for additional configuration */ public JwtSpec jwt() { @@ -1705,9 +1728,8 @@ public class ServerHttpSecurity { /** * Enables JWT Resource Server support. - * - * @param jwtCustomizer the {@link Customizer} to provide more options for - * the {@link JwtSpec} + * @param jwtCustomizer the {@link Customizer} to provide more options for the + * {@link JwtSpec} * @return the {@link OAuth2ResourceServerSpec} to customize */ public OAuth2ResourceServerSpec jwt(Customizer jwtCustomizer) { @@ -1720,7 +1742,6 @@ public class ServerHttpSecurity { /** * Enables Opaque Token Resource Server support. - * * @return the {@link OpaqueTokenSpec} for additional configuration */ public OpaqueTokenSpec opaqueToken() { @@ -1732,7 +1753,6 @@ public class ServerHttpSecurity { /** * Enables Opaque Token Resource Server support. - * * @param opaqueTokenCustomizer the {@link Customizer} to provide more options for * the {@link OpaqueTokenSpec} * @return the {@link OAuth2ResourceServerSpec} to customize @@ -1746,8 +1766,8 @@ public class ServerHttpSecurity { } protected void configure(ServerHttpSecurity http) { - this.authenticationConverterServerWebExchangeMatcher = - new AuthenticationConverterServerWebExchangeMatcher(this.bearerTokenConverter); + this.authenticationConverterServerWebExchangeMatcher = new AuthenticationConverterServerWebExchangeMatcher( + this.bearerTokenConverter); registerDefaultAccessDeniedHandler(http); registerDefaultAuthenticationEntryPoint(http); @@ -1760,9 +1780,11 @@ public class ServerHttpSecurity { oauth2.setServerAuthenticationConverter(bearerTokenConverter); oauth2.setAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(entryPoint)); http.addFilterAt(oauth2, SecurityWebFiltersOrder.AUTHENTICATION); - } else if (this.jwt != null) { + } + else if (this.jwt != null) { this.jwt.configure(http); - } else if (this.opaqueToken != null) { + } + else if (this.opaqueToken != null) { this.opaqueToken.configure(http); } } @@ -1770,48 +1792,45 @@ public class ServerHttpSecurity { private void validateConfiguration() { if (this.authenticationManagerResolver == null) { if (this.jwt == null && this.opaqueToken == null) { - throw new IllegalStateException("Jwt and Opaque Token are the only supported formats for bearer tokens " + - "in Spring Security and neither was found. Make sure to configure JWT " + - "via http.oauth2ResourceServer().jwt() or Opaque Tokens via " + - "http.oauth2ResourceServer().opaqueToken()."); + throw new IllegalStateException( + "Jwt and Opaque Token are the only supported formats for bearer tokens " + + "in Spring Security and neither was found. Make sure to configure JWT " + + "via http.oauth2ResourceServer().jwt() or Opaque Tokens via " + + "http.oauth2ResourceServer().opaqueToken()."); } if (this.jwt != null && this.opaqueToken != null) { - throw new IllegalStateException("Spring Security only supports JWTs or Opaque Tokens, not both at the " + - "same time."); + throw new IllegalStateException( + "Spring Security only supports JWTs or Opaque Tokens, not both at the " + "same time."); } - } else { + } + else { if (this.jwt != null || this.opaqueToken != null) { - throw new IllegalStateException("If an authenticationManagerResolver() is configured, then it takes " + - "precedence over any jwt() or opaqueToken() configuration."); + throw new IllegalStateException( + "If an authenticationManagerResolver() is configured, then it takes " + + "precedence over any jwt() or opaqueToken() configuration."); } } } private void registerDefaultAccessDeniedHandler(ServerHttpSecurity http) { - if ( http.exceptionHandling != null ) { - http.defaultAccessDeniedHandlers.add( - new ServerWebExchangeDelegatingServerAccessDeniedHandler.DelegateEntry( + if (http.exceptionHandling != null) { + http.defaultAccessDeniedHandlers + .add(new ServerWebExchangeDelegatingServerAccessDeniedHandler.DelegateEntry( this.authenticationConverterServerWebExchangeMatcher, - OAuth2ResourceServerSpec.this.accessDeniedHandler - ) - ); + OAuth2ResourceServerSpec.this.accessDeniedHandler)); } } private void registerDefaultAuthenticationEntryPoint(ServerHttpSecurity http) { if (http.exceptionHandling != null) { - http.defaultEntryPoints.add( - new DelegateEntry( - this.authenticationConverterServerWebExchangeMatcher, - OAuth2ResourceServerSpec.this.entryPoint - ) - ); + http.defaultEntryPoints.add(new DelegateEntry(this.authenticationConverterServerWebExchangeMatcher, + OAuth2ResourceServerSpec.this.entryPoint)); } } private void registerDefaultCsrfOverride(ServerHttpSecurity http) { - if ( http.csrf != null && !http.csrf.specifiedRequireCsrfProtectionMatcher ) { + if (http.csrf != null && !http.csrf.specifiedRequireCsrfProtectionMatcher) { // @formatter:off http .csrf() @@ -1825,6 +1844,7 @@ public class ServerHttpSecurity { } private class BearerTokenAuthenticationWebFilter extends AuthenticationWebFilter { + private ServerAuthenticationFailureHandler authenticationFailureHandler; BearerTokenAuthenticationWebFilter(ReactiveAuthenticationManager authenticationManager) { @@ -1834,26 +1854,30 @@ public class ServerHttpSecurity { @Override public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { WebFilterExchange webFilterExchange = new WebFilterExchange(exchange, chain); - return super.filter(exchange, chain) - .onErrorResume(AuthenticationException.class, e -> this.authenticationFailureHandler - .onAuthenticationFailure(webFilterExchange, e)); + return super.filter(exchange, chain).onErrorResume(AuthenticationException.class, + e -> this.authenticationFailureHandler.onAuthenticationFailure(webFilterExchange, e)); } @Override - public void setAuthenticationFailureHandler(ServerAuthenticationFailureHandler authenticationFailureHandler) { + public void setAuthenticationFailureHandler( + ServerAuthenticationFailureHandler authenticationFailureHandler) { super.setAuthenticationFailureHandler(authenticationFailureHandler); this.authenticationFailureHandler = authenticationFailureHandler; } + } /** * Configures JWT Resource Server Support */ public class JwtSpec { + private ReactiveAuthenticationManager authenticationManager; + private ReactiveJwtDecoder jwtDecoder; - private Converter> jwtAuthenticationConverter - = new ReactiveJwtAuthenticationConverterAdapter(new JwtAuthenticationConverter()); + + private Converter> jwtAuthenticationConverter = new ReactiveJwtAuthenticationConverterAdapter( + new JwtAuthenticationConverter()); /** * Configures the {@link ReactiveAuthenticationManager} to use @@ -1869,13 +1893,12 @@ public class ServerHttpSecurity { /** * Configures the {@link Converter} to use for converting a {@link Jwt} into * an {@link AbstractAuthenticationToken}. - * * @param jwtAuthenticationConverter the converter to use * @return the {@code JwtSpec} for additional configuration * @since 5.1.1 */ - public JwtSpec jwtAuthenticationConverter - (Converter> jwtAuthenticationConverter) { + public JwtSpec jwtAuthenticationConverter( + Converter> jwtAuthenticationConverter) { Assert.notNull(jwtAuthenticationConverter, "jwtAuthenticationConverter cannot be null"); this.jwtAuthenticationConverter = jwtAuthenticationConverter; return this; @@ -1892,8 +1915,8 @@ public class ServerHttpSecurity { } /** - * Configures a {@link ReactiveJwtDecoder} that leverages the provided {@link RSAPublicKey} - * + * Configures a {@link ReactiveJwtDecoder} that leverages the provided + * {@link RSAPublicKey} * @param publicKey the public key to use. * @return the {@code JwtSpec} for additional configuration */ @@ -1904,7 +1927,8 @@ public class ServerHttpSecurity { /** * Configures a {@link ReactiveJwtDecoder} using - * JSON Web Key (JWK) URL + * JSON Web Key + * (JWK) URL * @param jwkSetUri the URL to use. * @return the {@code JwtSpec} for additional configuration */ @@ -1935,8 +1959,7 @@ public class ServerHttpSecurity { return this.jwtDecoder; } - protected Converter> - getJwtAuthenticationConverter() { + protected Converter> getJwtAuthenticationConverter() { return this.jwtAuthenticationConverter; } @@ -1947,14 +1970,14 @@ public class ServerHttpSecurity { } ReactiveJwtDecoder jwtDecoder = getJwtDecoder(); - Converter> jwtAuthenticationConverter = - getJwtAuthenticationConverter(); - JwtReactiveAuthenticationManager authenticationManager = - new JwtReactiveAuthenticationManager(jwtDecoder); + Converter> jwtAuthenticationConverter = getJwtAuthenticationConverter(); + JwtReactiveAuthenticationManager authenticationManager = new JwtReactiveAuthenticationManager( + jwtDecoder); authenticationManager.setJwtAuthenticationConverter(jwtAuthenticationConverter); return authenticationManager; } + } /** @@ -1964,9 +1987,13 @@ public class ServerHttpSecurity { * @since 5.2 */ public class OpaqueTokenSpec { + private String introspectionUri; + private String clientId; + private String clientSecret; + private Supplier introspector; /** @@ -1977,9 +2004,8 @@ public class ServerHttpSecurity { public OpaqueTokenSpec introspectionUri(String introspectionUri) { Assert.hasText(introspectionUri, "introspectionUri cannot be empty"); this.introspectionUri = introspectionUri; - this.introspector = () -> - new NimbusReactiveOpaqueTokenIntrospector( - this.introspectionUri, this.clientId, this.clientSecret); + this.introspector = () -> new NimbusReactiveOpaqueTokenIntrospector(this.introspectionUri, + this.clientId, this.clientSecret); return this; } @@ -1994,9 +2020,8 @@ public class ServerHttpSecurity { Assert.notNull(clientSecret, "clientSecret cannot be null"); this.clientId = clientId; this.clientSecret = clientSecret; - this.introspector = () -> - new NimbusReactiveOpaqueTokenIntrospector( - this.introspectionUri, this.clientId, this.clientSecret); + this.introspector = () -> new NimbusReactiveOpaqueTokenIntrospector(this.introspectionUri, + this.clientId, this.clientSecret); return this; } @@ -2007,7 +2032,8 @@ public class ServerHttpSecurity { } /** - * Allows method chaining to continue configuring the {@link ServerHttpSecurity} + * Allows method chaining to continue configuring the + * {@link ServerHttpSecurity} * @return the {@link ServerHttpSecurity} to continue configuring */ public OAuth2ResourceServerSpec and() { @@ -2033,12 +2059,15 @@ public class ServerHttpSecurity { http.addFilterAt(oauth2, SecurityWebFiltersOrder.AUTHENTICATION); } - private OpaqueTokenSpec() {} + private OpaqueTokenSpec() { + } + } public ServerHttpSecurity and() { return ServerHttpSecurity.this; } + } /** @@ -2073,7 +2102,6 @@ public class ServerHttpSecurity { * return http.build(); * } * - * * @return the {@link HeaderSpec} to customize */ public HeaderSpec headers() { @@ -2121,9 +2149,8 @@ public class ServerHttpSecurity { * return http.build(); * } * - * - * @param headerCustomizer the {@link Customizer} to provide more options for - * the {@link HeaderSpec} + * @param headerCustomizer the {@link Customizer} to provide more options for the + * {@link HeaderSpec} * @return the {@link ServerHttpSecurity} to customize */ public ServerHttpSecurity headers(Customizer headerCustomizer) { @@ -2135,8 +2162,8 @@ public class ServerHttpSecurity { } /** - * Configures exception handling (i.e. handles when authentication is requested). An example configuration can - * be found below: + * Configures exception handling (i.e. handles when authentication is requested). An + * example configuration can be found below: * *
     	 *  @Bean
    @@ -2149,7 +2176,6 @@ public class ServerHttpSecurity {
     	 *      return http.build();
     	 *  }
     	 * 
    - * * @return the {@link ExceptionHandlingSpec} to customize */ public ExceptionHandlingSpec exceptionHandling() { @@ -2160,8 +2186,8 @@ public class ServerHttpSecurity { } /** - * Configures exception handling (i.e. handles when authentication is requested). An example configuration can - * be found below: + * Configures exception handling (i.e. handles when authentication is requested). An + * example configuration can be found below: * *
     	 *  @Bean
    @@ -2176,9 +2202,8 @@ public class ServerHttpSecurity {
     	 *      return http.build();
     	 *  }
     	 * 
    - * - * @param exceptionHandlingCustomizer the {@link Customizer} to provide more options for - * the {@link ExceptionHandlingSpec} + * @param exceptionHandlingCustomizer the {@link Customizer} to provide more options + * for the {@link ExceptionHandlingSpec} * @return the {@link ServerHttpSecurity} to customize */ public ServerHttpSecurity exceptionHandling(Customizer exceptionHandlingCustomizer) { @@ -2217,7 +2242,6 @@ public class ServerHttpSecurity { * return http.build(); * } * - * * @return the {@link AuthorizeExchangeSpec} to customize */ public AuthorizeExchangeSpec authorizeExchange() { @@ -2257,9 +2281,8 @@ public class ServerHttpSecurity { * return http.build(); * } * - * - * @param authorizeExchangeCustomizer the {@link Customizer} to provide more options for - * the {@link AuthorizeExchangeSpec} + * @param authorizeExchangeCustomizer the {@link Customizer} to provide more options + * for the {@link AuthorizeExchangeSpec} * @return the {@link ServerHttpSecurity} to customize */ public ServerHttpSecurity authorizeExchange(Customizer authorizeExchangeCustomizer) { @@ -2317,9 +2340,8 @@ public class ServerHttpSecurity { * return http.build(); * } * - * - * @param logoutCustomizer the {@link Customizer} to provide more options for - * the {@link LogoutSpec} + * @param logoutCustomizer the {@link Customizer} to provide more options for the + * {@link LogoutSpec} * @return the {@link ServerHttpSecurity} to customize */ public ServerHttpSecurity logout(Customizer logoutCustomizer) { @@ -2331,8 +2353,9 @@ public class ServerHttpSecurity { } /** - * Configures the request cache which is used when a flow is interrupted (i.e. due to requesting credentials) so - * that the request can be replayed after authentication. An example configuration can be found below: + * Configures the request cache which is used when a flow is interrupted (i.e. due to + * requesting credentials) so that the request can be replayed after authentication. + * An example configuration can be found below: * *
     	 *  @Bean
    @@ -2345,7 +2368,6 @@ public class ServerHttpSecurity {
     	 *      return http.build();
     	 *  }
     	 * 
    - * * @return the {@link RequestCacheSpec} to customize */ public RequestCacheSpec requestCache() { @@ -2353,8 +2375,9 @@ public class ServerHttpSecurity { } /** - * Configures the request cache which is used when a flow is interrupted (i.e. due to requesting credentials) so - * that the request can be replayed after authentication. An example configuration can be found below: + * Configures the request cache which is used when a flow is interrupted (i.e. due to + * requesting credentials) so that the request can be replayed after authentication. + * An example configuration can be found below: * *
     	 *  @Bean
    @@ -2369,7 +2392,6 @@ public class ServerHttpSecurity {
     	 *      return http.build();
     	 *  }
     	 * 
    - * * @param requestCacheCustomizer the {@link Customizer} to provide more options for * the {@link RequestCacheSpec} * @return the {@link ServerHttpSecurity} to customize @@ -2395,7 +2417,8 @@ public class ServerHttpSecurity { */ public SecurityWebFilterChain build() { if (this.built != null) { - throw new IllegalStateException("This has already been built with the following stacktrace. " + buildToString()); + throw new IllegalStateException( + "This has already been built with the following stacktrace. " + buildToString()); } this.built = new RuntimeException("First Build Invocation").fillInStackTrace(); if (this.headers != null) { @@ -2471,25 +2494,24 @@ public class ServerHttpSecurity { this.logout.configure(this); } this.requestCache.configure(this); - this.addFilterAt(new SecurityContextServerWebExchangeWebFilter(), SecurityWebFiltersOrder.SECURITY_CONTEXT_SERVER_WEB_EXCHANGE); + this.addFilterAt(new SecurityContextServerWebExchangeWebFilter(), + SecurityWebFiltersOrder.SECURITY_CONTEXT_SERVER_WEB_EXCHANGE); if (this.authorizeExchange != null) { ServerAuthenticationEntryPoint authenticationEntryPoint = getAuthenticationEntryPoint(); ExceptionTranslationWebFilter exceptionTranslationWebFilter = new ExceptionTranslationWebFilter(); if (authenticationEntryPoint != null) { - exceptionTranslationWebFilter.setAuthenticationEntryPoint( - authenticationEntryPoint); + exceptionTranslationWebFilter.setAuthenticationEntryPoint(authenticationEntryPoint); } ServerAccessDeniedHandler accessDeniedHandler = getAccessDeniedHandler(); if (accessDeniedHandler != null) { - exceptionTranslationWebFilter.setAccessDeniedHandler( - accessDeniedHandler); + exceptionTranslationWebFilter.setAccessDeniedHandler(accessDeniedHandler); } this.addFilterAt(exceptionTranslationWebFilter, SecurityWebFiltersOrder.EXCEPTION_TRANSLATION); this.authorizeExchange.configure(this); } AnnotationAwareOrderComparator.sort(this.webFilters); List sortedWebFilters = new ArrayList<>(); - this.webFilters.forEach( f -> { + this.webFilters.forEach(f -> { if (f instanceof OrderedWebFilter) { f = ((OrderedWebFilter) f).webFilter; } @@ -2500,8 +2522,8 @@ public class ServerHttpSecurity { } private String buildToString() { - try(StringWriter writer = new StringWriter()) { - try(PrintWriter printer = new PrintWriter(writer)) { + try (StringWriter writer = new StringWriter()) { + try (PrintWriter printer = new PrintWriter(writer)) { printer.println(); printer.println(); this.built.printStackTrace(printer); @@ -2509,7 +2531,8 @@ public class ServerHttpSecurity { printer.println(); return writer.toString(); } - } catch(IOException e) { + } + catch (IOException e) { throw new RuntimeException(e); } } @@ -2521,7 +2544,8 @@ public class ServerHttpSecurity { if (this.defaultEntryPoints.size() == 1) { return this.defaultEntryPoints.get(0).getEntryPoint(); } - DelegatingServerAuthenticationEntryPoint result = new DelegatingServerAuthenticationEntryPoint(this.defaultEntryPoints); + DelegatingServerAuthenticationEntryPoint result = new DelegatingServerAuthenticationEntryPoint( + this.defaultEntryPoints); result.setDefaultEntryPoint(this.defaultEntryPoints.get(this.defaultEntryPoints.size() - 1).getEntryPoint()); return result; } @@ -2533,8 +2557,8 @@ public class ServerHttpSecurity { if (this.defaultAccessDeniedHandlers.size() == 1) { return this.defaultAccessDeniedHandlers.get(0).getAccessDeniedHandler(); } - ServerWebExchangeDelegatingServerAccessDeniedHandler result = - new ServerWebExchangeDelegatingServerAccessDeniedHandler(this.defaultAccessDeniedHandlers); + ServerWebExchangeDelegatingServerAccessDeniedHandler result = new ServerWebExchangeDelegatingServerAccessDeniedHandler( + this.defaultAccessDeniedHandlers); result.setDefaultAccessDeniedHandler(this.defaultAccessDeniedHandlers .get(this.defaultAccessDeniedHandlers.size() - 1).getAccessDeniedHandler()); return result; @@ -2549,13 +2573,14 @@ public class ServerHttpSecurity { } private WebFilter securityContextRepositoryWebFilter() { - ServerSecurityContextRepository repository = this.securityContextRepository == null ? - new WebSessionServerSecurityContextRepository() : this.securityContextRepository; + ServerSecurityContextRepository repository = this.securityContextRepository == null + ? new WebSessionServerSecurityContextRepository() : this.securityContextRepository; WebFilter result = new ReactorContextWebFilter(repository); return new OrderedWebFilter(result, SecurityWebFiltersOrder.REACTOR_CONTEXT.getOrder()); } - protected ServerHttpSecurity() {} + protected ServerHttpSecurity() { + } /** * Configures authorization @@ -2564,10 +2589,13 @@ public class ServerHttpSecurity { * @since 5.0 * @see #authorizeExchange() */ - public class AuthorizeExchangeSpec - extends AbstractServerWebExchangeMatcherRegistry { - private DelegatingReactiveAuthorizationManager.Builder managerBldr = DelegatingReactiveAuthorizationManager.builder(); + public class AuthorizeExchangeSpec extends AbstractServerWebExchangeMatcherRegistry { + + private DelegatingReactiveAuthorizationManager.Builder managerBldr = DelegatingReactiveAuthorizationManager + .builder(); + private ServerWebExchangeMatcher matcher; + private boolean anyExchangeRegistered; /** @@ -2592,7 +2620,8 @@ public class ServerHttpSecurity { @Override protected Access registerMatcher(ServerWebExchangeMatcher matcher) { if (this.anyExchangeRegistered) { - throw new IllegalStateException("Cannot register " + matcher + " which would be unreachable because anyExchange() has already been registered."); + throw new IllegalStateException("Cannot register " + matcher + + " which would be unreachable because anyExchange() has already been registered."); } if (this.matcher != null) { throw new IllegalStateException("The matcher " + matcher + " does not have an access rule defined"); @@ -2603,7 +2632,8 @@ public class ServerHttpSecurity { protected void configure(ServerHttpSecurity http) { if (this.matcher != null) { - throw new IllegalStateException("The matcher " + this.matcher + " does not have an access rule defined"); + throw new IllegalStateException( + "The matcher " + this.matcher + " does not have an access rule defined"); } AuthorizationWebFilter result = new AuthorizationWebFilter(this.managerBldr.build()); http.addFilterAt(result, SecurityWebFiltersOrder.AUTHORIZATION); @@ -2619,7 +2649,7 @@ public class ServerHttpSecurity { * @return the {@link AuthorizeExchangeSpec} to configure */ public AuthorizeExchangeSpec permitAll() { - return access( (a, e) -> Mono.just(new AuthorizationDecision(true))); + return access((a, e) -> Mono.just(new AuthorizationDecision(true))); } /** @@ -2627,11 +2657,12 @@ public class ServerHttpSecurity { * @return the {@link AuthorizeExchangeSpec} to configure */ public AuthorizeExchangeSpec denyAll() { - return access( (a, e) -> Mono.just(new AuthorizationDecision(false))); + return access((a, e) -> Mono.just(new AuthorizationDecision(false))); } /** - * Require a specific role. This is a shorcut for {@link #hasAuthority(String)} + * Require a specific role. This is a shorcut for + * {@link #hasAuthority(String)} * @param role the role (i.e. "USER" would require "ROLE_USER") * @return the {@link AuthorizeExchangeSpec} to configure */ @@ -2640,7 +2671,8 @@ public class ServerHttpSecurity { } /** - * Require any specific role. This is a shortcut for {@link #hasAnyAuthority(String...)} + * Require any specific role. This is a shortcut for + * {@link #hasAnyAuthority(String...)} * @param roles the roles (i.e. "USER" would require "ROLE_USER") * @return the {@link AuthorizeExchangeSpec} to configure */ @@ -2650,7 +2682,8 @@ public class ServerHttpSecurity { /** * Require a specific authority. - * @param authority the authority to require (i.e. "USER" would require authority of "USER"). + * @param authority the authority to require (i.e. "USER" would require + * authority of "USER"). * @return the {@link AuthorizeExchangeSpec} to configure */ public AuthorizeExchangeSpec hasAuthority(String authority) { @@ -2659,7 +2692,8 @@ public class ServerHttpSecurity { /** * Require any authority - * @param authorities the authorities to require (i.e. "USER" would require authority of "USER"). + * @param authorities the authorities to require (i.e. "USER" would require + * authority of "USER"). * @return the {@link AuthorizeExchangeSpec} to configure */ public AuthorizeExchangeSpec hasAnyAuthority(String... authorities) { @@ -2681,12 +2715,13 @@ public class ServerHttpSecurity { */ public AuthorizeExchangeSpec access(ReactiveAuthorizationManager manager) { AuthorizeExchangeSpec.this.managerBldr - .add(new ServerWebExchangeMatcherEntry<>( - AuthorizeExchangeSpec.this.matcher, manager)); + .add(new ServerWebExchangeMatcherEntry<>(AuthorizeExchangeSpec.this.matcher, manager)); AuthorizeExchangeSpec.this.matcher = null; return AuthorizeExchangeSpec.this; } + } + } /** @@ -2697,15 +2732,17 @@ public class ServerHttpSecurity { * @see #redirectToHttps() */ public class HttpsRedirectSpec { + private ServerWebExchangeMatcher serverWebExchangeMatcher; + private PortMapper portMapper; /** * Configures when this filter should redirect to https * * By default, the filter will redirect whenever an exchange's scheme is not https - * - * @param matchers the list of conditions that, when any are met, the filter should redirect to https + * @param matchers the list of conditions that, when any are met, the filter + * should redirect to https * @return the {@link HttpsRedirectSpec} for additional configuration */ public HttpsRedirectSpec httpsRedirectWhen(ServerWebExchangeMatcher... matchers) { @@ -2717,21 +2754,17 @@ public class ServerHttpSecurity { * Configures when this filter should redirect to https * * By default, the filter will redirect whenever an exchange's scheme is not https - * * @param when determines when to redirect to https * @return the {@link HttpsRedirectSpec} for additional configuration */ - public HttpsRedirectSpec httpsRedirectWhen( - Function when) { - ServerWebExchangeMatcher matcher = e -> when.apply(e) ? - ServerWebExchangeMatcher.MatchResult.match() : - ServerWebExchangeMatcher.MatchResult.notMatch(); + public HttpsRedirectSpec httpsRedirectWhen(Function when) { + ServerWebExchangeMatcher matcher = e -> when.apply(e) ? ServerWebExchangeMatcher.MatchResult.match() + : ServerWebExchangeMatcher.MatchResult.notMatch(); return httpsRedirectWhen(matcher); } /** * Configures a custom HTTPS port to redirect to - * * @param portMapper the {@link PortMapper} to use * @return the {@link HttpsRedirectSpec} for additional configuration */ @@ -2758,66 +2791,67 @@ public class ServerHttpSecurity { public ServerHttpSecurity and() { return ServerHttpSecurity.this; } + } /** - * Configures CSRF Protection + * Configures CSRF + * Protection * * @author Rob Winch * @since 5.0 * @see #csrf() */ public class CsrfSpec { + private CsrfWebFilter filter = new CsrfWebFilter(); + private ServerCsrfTokenRepository csrfTokenRepository = new WebSessionServerCsrfTokenRepository(); private boolean specifiedRequireCsrfProtectionMatcher; /** - * Configures the {@link ServerAccessDeniedHandler} used when a CSRF token is invalid. Default is - * to send an {@link org.springframework.http.HttpStatus#FORBIDDEN}. - * + * Configures the {@link ServerAccessDeniedHandler} used when a CSRF token is + * invalid. Default is to send an + * {@link org.springframework.http.HttpStatus#FORBIDDEN}. * @param accessDeniedHandler the access denied handler. * @return the {@link CsrfSpec} for additional configuration */ - public CsrfSpec accessDeniedHandler( - ServerAccessDeniedHandler accessDeniedHandler) { + public CsrfSpec accessDeniedHandler(ServerAccessDeniedHandler accessDeniedHandler) { this.filter.setAccessDeniedHandler(accessDeniedHandler); return this; } /** - * Configures the {@link ServerCsrfTokenRepository} used to persist the CSRF Token. Default is + * Configures the {@link ServerCsrfTokenRepository} used to persist the CSRF + * Token. Default is * {@link org.springframework.security.web.server.csrf.WebSessionServerCsrfTokenRepository}. - * * @param csrfTokenRepository the repository to use * @return the {@link CsrfSpec} for additional configuration */ - public CsrfSpec csrfTokenRepository( - ServerCsrfTokenRepository csrfTokenRepository) { + public CsrfSpec csrfTokenRepository(ServerCsrfTokenRepository csrfTokenRepository) { this.csrfTokenRepository = csrfTokenRepository; return this; } /** - * Configures the {@link ServerWebExchangeMatcher} used to determine when CSRF protection is enabled. Default is - * PUT, POST, DELETE requests. - * + * Configures the {@link ServerWebExchangeMatcher} used to determine when CSRF + * protection is enabled. Default is PUT, POST, DELETE requests. * @param requireCsrfProtectionMatcher the matcher to use * @return the {@link CsrfSpec} for additional configuration */ - public CsrfSpec requireCsrfProtectionMatcher( - ServerWebExchangeMatcher requireCsrfProtectionMatcher) { + public CsrfSpec requireCsrfProtectionMatcher(ServerWebExchangeMatcher requireCsrfProtectionMatcher) { this.filter.setRequireCsrfProtectionMatcher(requireCsrfProtectionMatcher); this.specifiedRequireCsrfProtectionMatcher = true; return this; } /** - * Specifies if {@link CsrfWebFilter} should try to resolve the actual CSRF token from the body of multipart - * data requests. - * - * @param enabled true if should read from multipart form body, else false. Default is false + * Specifies if {@link CsrfWebFilter} should try to resolve the actual CSRF token + * from the body of multipart data requests. + * @param enabled true if should read from multipart form body, else false. + * Default is false * @return the {@link CsrfSpec} for additional configuration */ public CsrfSpec tokenFromMultipartDataEnabled(boolean enabled) { @@ -2825,7 +2859,6 @@ public class ServerHttpSecurity { return this; } - /** * Allows method chaining to continue configuring the {@link ServerHttpSecurity} * @return the {@link ServerHttpSecurity} to continue configuring @@ -2835,8 +2868,8 @@ public class ServerHttpSecurity { } /** - * Disables CSRF Protection. Disabling CSRF Protection is only recommended when the application is never used - * within a browser. + * Disables CSRF Protection. Disabling CSRF Protection is only recommended when + * the application is never used within a browser. * @return the {@link ServerHttpSecurity} to continue configuring */ public ServerHttpSecurity disable() { @@ -2848,13 +2881,16 @@ public class ServerHttpSecurity { if (this.csrfTokenRepository != null) { this.filter.setCsrfTokenRepository(this.csrfTokenRepository); if (ServerHttpSecurity.this.logout != null) { - ServerHttpSecurity.this.logout.addLogoutHandler(new CsrfServerLogoutHandler(this.csrfTokenRepository)); + ServerHttpSecurity.this.logout + .addLogoutHandler(new CsrfServerLogoutHandler(this.csrfTokenRepository)); } } http.addFilterAt(this.filter, SecurityWebFiltersOrder.CSRF); } - private CsrfSpec() {} + private CsrfSpec() { + } + } /** @@ -2877,7 +2913,8 @@ public class ServerHttpSecurity { } /** - * Configures what to do when an authenticated user does not hold a required authority + * Configures what to do when an authenticated user does not hold a required + * authority * @param accessDeniedHandler the access denied handler to use * @return the {@link ExceptionHandlingSpec} to configure * @@ -2896,18 +2933,21 @@ public class ServerHttpSecurity { return ServerHttpSecurity.this; } - private ExceptionHandlingSpec() {} + private ExceptionHandlingSpec() { + } + } /** - * Configures the request cache which is used when a flow is interrupted (i.e. due to requesting credentials) so - * that the request can be replayed after authentication. + * Configures the request cache which is used when a flow is interrupted (i.e. due to + * requesting credentials) so that the request can be replayed after authentication. * * @author Rob Winch * @since 5.0 * @see #requestCache() */ public class RequestCacheSpec { + private ServerRequestCache requestCache = new WebSessionServerRequestCache(); /** @@ -2944,7 +2984,9 @@ public class ServerHttpSecurity { return and(); } - private RequestCacheSpec() {} + private RequestCacheSpec() { + } + } /** @@ -2955,6 +2997,7 @@ public class ServerHttpSecurity { * @see #httpBasic() */ public class HttpBasicSpec { + private ReactiveAuthenticationManager authenticationManager; private ServerSecurityContextRepository securityContextRepository; @@ -2964,7 +3007,6 @@ public class ServerHttpSecurity { /** * The {@link ReactiveAuthenticationManager} used to authenticate. Defaults to * {@link ServerHttpSecurity#authenticationManager(ReactiveAuthenticationManager)}. - * * @param authenticationManager the authentication manager to use * @return the {@link HttpBasicSpec} to continue configuring */ @@ -2974,11 +3016,11 @@ public class ServerHttpSecurity { } /** - * The {@link ServerSecurityContextRepository} used to save the {@code Authentication}. Defaults to - * {@link NoOpServerSecurityContextRepository}. For the {@code SecurityContext} to be loaded on subsequent - * requests the {@link ReactorContextWebFilter} must be configured to be able to load the value (they are not - * implicitly linked). - * + * The {@link ServerSecurityContextRepository} used to save the + * {@code Authentication}. Defaults to + * {@link NoOpServerSecurityContextRepository}. For the {@code SecurityContext} to + * be loaded on subsequent requests the {@link ReactorContextWebFilter} must be + * configured to be able to load the value (they are not implicitly linked). * @param securityContextRepository the repository to use * @return the {@link HttpBasicSpec} to continue configuring */ @@ -2989,12 +3031,13 @@ public class ServerHttpSecurity { /** * Allows easily setting the entry point. - * @param authenticationEntryPoint the {@link ServerAuthenticationEntryPoint} to use + * @param authenticationEntryPoint the {@link ServerAuthenticationEntryPoint} to + * use * @return {@link HttpBasicSpec} for additional customization * @since 5.2.0 * @author Ankur Pathak */ - public HttpBasicSpec authenticationEntryPoint(ServerAuthenticationEntryPoint authenticationEntryPoint){ + public HttpBasicSpec authenticationEntryPoint(ServerAuthenticationEntryPoint authenticationEntryPoint) { Assert.notNull(authenticationEntryPoint, "authenticationEntryPoint cannot be null"); this.entryPoint = authenticationEntryPoint; return this; @@ -3019,21 +3062,22 @@ public class ServerHttpSecurity { protected void configure(ServerHttpSecurity http) { MediaTypeServerWebExchangeMatcher restMatcher = new MediaTypeServerWebExchangeMatcher( - MediaType.APPLICATION_ATOM_XML, - MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, - MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_XML, - MediaType.MULTIPART_FORM_DATA, MediaType.TEXT_XML); + MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, + MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_XML, MediaType.MULTIPART_FORM_DATA, + MediaType.TEXT_XML); restMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); ServerHttpSecurity.this.defaultEntryPoints.add(new DelegateEntry(restMatcher, this.entryPoint)); - AuthenticationWebFilter authenticationFilter = new AuthenticationWebFilter( - this.authenticationManager); - authenticationFilter.setAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(this.entryPoint)); + AuthenticationWebFilter authenticationFilter = new AuthenticationWebFilter(this.authenticationManager); + authenticationFilter + .setAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(this.entryPoint)); authenticationFilter.setAuthenticationConverter(new ServerHttpBasicAuthenticationConverter()); authenticationFilter.setSecurityContextRepository(this.securityContextRepository); http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.HTTP_BASIC); } - private HttpBasicSpec() {} + private HttpBasicSpec() { + } + } /** @@ -3044,7 +3088,9 @@ public class ServerHttpSecurity { * @see #formLogin() */ public class FormLoginSpec { - private final RedirectServerAuthenticationSuccessHandler defaultSuccessHandler = new RedirectServerAuthenticationSuccessHandler("/"); + + private final RedirectServerAuthenticationSuccessHandler defaultSuccessHandler = new RedirectServerAuthenticationSuccessHandler( + "/"); private RedirectServerAuthenticationEntryPoint defaultEntryPoint; @@ -3065,7 +3111,6 @@ public class ServerHttpSecurity { /** * The {@link ReactiveAuthenticationManager} used to authenticate. Defaults to * {@link ServerHttpSecurity#authenticationManager(ReactiveAuthenticationManager)}. - * * @param authenticationManager the authentication manager to use * @return the {@link FormLoginSpec} to continue configuring */ @@ -3075,29 +3120,32 @@ public class ServerHttpSecurity { } /** - * The {@link ServerAuthenticationSuccessHandler} used after authentication success. Defaults to - * {@link RedirectServerAuthenticationSuccessHandler}. + * The {@link ServerAuthenticationSuccessHandler} used after authentication + * success. Defaults to {@link RedirectServerAuthenticationSuccessHandler}. * @param authenticationSuccessHandler the success handler to use * @return the {@link FormLoginSpec} to continue configuring */ public FormLoginSpec authenticationSuccessHandler( - ServerAuthenticationSuccessHandler authenticationSuccessHandler) { + ServerAuthenticationSuccessHandler authenticationSuccessHandler) { Assert.notNull(authenticationSuccessHandler, "authenticationSuccessHandler cannot be null"); this.authenticationSuccessHandler = authenticationSuccessHandler; return this; } /** - * Configures the log in page to redirect to, the authentication failure page, and when authentication is - * performed. The default is that Spring Security will generate a log in page at "/login" and a log out page at - * "/logout". If this is customized: + * Configures the log in page to redirect to, the authentication failure page, and + * when authentication is performed. The default is that Spring Security will + * generate a log in page at "/login" and a log out page at "/logout". If this is + * customized: *
      *
    • The default log in & log out page are no longer provided
    • *
    • The application must render a log in page at the provided URL
    • - *
    • The application must render an authentication error page at the provided URL + "?error"
    • + *
    • The application must render an authentication error page at the provided + * URL + "?error"
    • *
    • Authentication will occur for POST to the provided URL
    • *
    - * @param loginPage the url to redirect to which provides a form to log in (i.e. "/login") + * @param loginPage the url to redirect to which provides a form to log in (i.e. + * "/login") * @return the {@link FormLoginSpec} to continue configuring * @see #authenticationEntryPoint(ServerAuthenticationEntryPoint) * @see #requiresAuthenticationMatcher(ServerWebExchangeMatcher) @@ -3110,7 +3158,8 @@ public class ServerHttpSecurity { this.requiresAuthenticationMatcher = ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, loginPage); } if (this.authenticationFailureHandler == null) { - this.authenticationFailureHandler = new RedirectServerAuthenticationFailureHandler(loginPage + "?error"); + this.authenticationFailureHandler = new RedirectServerAuthenticationFailureHandler( + loginPage + "?error"); } return this; } @@ -3139,22 +3188,25 @@ public class ServerHttpSecurity { } /** - * Configures how a failed authentication is handled. The default is to redirect to "/login?error". + * Configures how a failed authentication is handled. The default is to redirect + * to "/login?error". * @param authenticationFailureHandler the handler to use * @return the {@link FormLoginSpec} to continue configuring * @see #loginPage(String) */ - public FormLoginSpec authenticationFailureHandler(ServerAuthenticationFailureHandler authenticationFailureHandler) { + public FormLoginSpec authenticationFailureHandler( + ServerAuthenticationFailureHandler authenticationFailureHandler) { this.authenticationFailureHandler = authenticationFailureHandler; return this; } /** - * The {@link ServerSecurityContextRepository} used to save the {@code Authentication}. Defaults to - * {@link WebSessionServerSecurityContextRepository}. For the {@code SecurityContext} to be loaded on subsequent - * requests the {@link ReactorContextWebFilter} must be configured to be able to load the value (they are not - * implicitly linked). - * + * The {@link ServerSecurityContextRepository} used to save the + * {@code Authentication}. Defaults to + * {@link WebSessionServerSecurityContextRepository}. For the + * {@code SecurityContext} to be loaded on subsequent requests the + * {@link ReactorContextWebFilter} must be configured to be able to load the value + * (they are not implicitly linked). * @param securityContextRepository the repository to use * @return the {@link FormLoginSpec} to continue configuring */ @@ -3184,7 +3236,8 @@ public class ServerHttpSecurity { if (this.authenticationEntryPoint == null) { this.isEntryPointExplicit = false; loginPage("/login"); - } else { + } + else { this.isEntryPointExplicit = true; } if (http.requestCache != null) { @@ -3194,12 +3247,11 @@ public class ServerHttpSecurity { this.defaultEntryPoint.setRequestCache(requestCache); } } - MediaTypeServerWebExchangeMatcher htmlMatcher = new MediaTypeServerWebExchangeMatcher( - MediaType.TEXT_HTML); + MediaTypeServerWebExchangeMatcher htmlMatcher = new MediaTypeServerWebExchangeMatcher(MediaType.TEXT_HTML); htmlMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); - ServerHttpSecurity.this.defaultEntryPoints.add(0, new DelegateEntry(htmlMatcher, this.authenticationEntryPoint)); - AuthenticationWebFilter authenticationFilter = new AuthenticationWebFilter( - this.authenticationManager); + ServerHttpSecurity.this.defaultEntryPoints.add(0, + new DelegateEntry(htmlMatcher, this.authenticationEntryPoint)); + AuthenticationWebFilter authenticationFilter = new AuthenticationWebFilter(this.authenticationManager); authenticationFilter.setRequiresAuthenticationMatcher(this.requiresAuthenticationMatcher); authenticationFilter.setAuthenticationFailureHandler(this.authenticationFailureHandler); authenticationFilter.setAuthenticationConverter(new ServerFormLoginAuthenticationConverter()); @@ -3210,9 +3262,11 @@ public class ServerHttpSecurity { private FormLoginSpec() { } + } private class LoginPageSpec { + protected void configure(ServerHttpSecurity http) { if (http.authenticationEntryPoint != null) { return; @@ -3238,7 +3292,9 @@ public class ServerHttpSecurity { } } - private LoginPageSpec() {} + private LoginPageSpec() { + } + } /** @@ -3249,6 +3305,7 @@ public class ServerHttpSecurity { * @see #headers() */ public class HeaderSpec { + private final List writers; private CacheControlServerHttpHeadersWriter cacheControl = new CacheControlServerHttpHeadersWriter(); @@ -3294,9 +3351,8 @@ public class ServerHttpSecurity { /** * Configures cache control headers - * - * @param cacheCustomizer the {@link Customizer} to provide more options for - * the {@link CacheSpec} + * @param cacheCustomizer the {@link Customizer} to provide more options for the + * {@link CacheSpec} * @return the {@link HeaderSpec} to customize */ public HeaderSpec cache(Customizer cacheCustomizer) { @@ -3314,9 +3370,8 @@ public class ServerHttpSecurity { /** * Configures content type response headers - * - * @param contentTypeOptionsCustomizer the {@link Customizer} to provide more options for - * the {@link ContentTypeOptionsSpec} + * @param contentTypeOptionsCustomizer the {@link Customizer} to provide more + * options for the {@link ContentTypeOptionsSpec} * @return the {@link HeaderSpec} to customize */ public HeaderSpec contentTypeOptions(Customizer contentTypeOptionsCustomizer) { @@ -3334,9 +3389,8 @@ public class ServerHttpSecurity { /** * Configures frame options response headers - * - * @param frameOptionsCustomizer the {@link Customizer} to provide more options for - * the {@link FrameOptionsSpec} + * @param frameOptionsCustomizer the {@link Customizer} to provide more options + * for the {@link FrameOptionsSpec} * @return the {@link HeaderSpec} to customize */ public HeaderSpec frameOptions(Customizer frameOptionsCustomizer) { @@ -3346,8 +3400,8 @@ public class ServerHttpSecurity { /** * Configures custom headers writer - * - * @param serverHttpHeadersWriter the {@link ServerHttpHeadersWriter} to provide custom headers writer + * @param serverHttpHeadersWriter the {@link ServerHttpHeadersWriter} to provide + * custom headers writer * @return the {@link HeaderSpec} to customize * @since 5.3.0 * @author Ankur Pathak @@ -3368,9 +3422,8 @@ public class ServerHttpSecurity { /** * Configures the Strict Transport Security response headers - * - * @param hstsCustomizer the {@link Customizer} to provide more options for - * the {@link HstsSpec} + * @param hstsCustomizer the {@link Customizer} to provide more options for the + * {@link HstsSpec} * @return the {@link HeaderSpec} to customize */ public HeaderSpec hsts(Customizer hstsCustomizer) { @@ -3394,9 +3447,8 @@ public class ServerHttpSecurity { /** * Configures x-xss-protection response header. - * - * @param xssProtectionCustomizer the {@link Customizer} to provide more options for - * the {@link XssProtectionSpec} + * @param xssProtectionCustomizer the {@link Customizer} to provide more options + * for the {@link XssProtectionSpec} * @return the {@link HeaderSpec} to customize */ public HeaderSpec xssProtection(Customizer xssProtectionCustomizer) { @@ -3415,9 +3467,8 @@ public class ServerHttpSecurity { /** * Configures {@code Content-Security-Policy} response header. - * - * @param contentSecurityPolicyCustomizer the {@link Customizer} to provide more options for - * the {@link ContentSecurityPolicySpec} + * @param contentSecurityPolicyCustomizer the {@link Customizer} to provide more + * options for the {@link ContentSecurityPolicySpec} * @return the {@link HeaderSpec} to customize */ public HeaderSpec contentSecurityPolicy(Customizer contentSecurityPolicyCustomizer) { @@ -3453,9 +3504,8 @@ public class ServerHttpSecurity { /** * Configures {@code Referrer-Policy} response header. - * - * @param referrerPolicyCustomizer the {@link Customizer} to provide more options for - * the {@link ReferrerPolicySpec} + * @param referrerPolicyCustomizer the {@link Customizer} to provide more options + * for the {@link ReferrerPolicySpec} * @return the {@link HeaderSpec} to customize */ public HeaderSpec referrerPolicy(Customizer referrerPolicyCustomizer) { @@ -3465,9 +3515,11 @@ public class ServerHttpSecurity { /** * Configures cache control headers + * * @see #cache() */ public class CacheSpec { + /** * Disables cache control response headers * @return the {@link HeaderSpec} to configure @@ -3477,14 +3529,18 @@ public class ServerHttpSecurity { return HeaderSpec.this; } - private CacheSpec() {} + private CacheSpec() { + } + } /** * The content type headers + * * @see #contentTypeOptions() */ public class ContentTypeOptionsSpec { + /** * Disables the content type options response header * @return the {@link HeaderSpec} to configure @@ -3494,14 +3550,18 @@ public class ServerHttpSecurity { return HeaderSpec.this; } - private ContentTypeOptionsSpec() {} + private ContentTypeOptionsSpec() { + } + } /** * Configures frame options response header + * * @see #frameOptions() */ public class FrameOptionsSpec { + /** * The mode to configure. Default is * {@link org.springframework.security.web.server.header.XFrameOptionsServerHttpHeadersWriter.Mode#DENY} @@ -3514,7 +3574,8 @@ public class ServerHttpSecurity { } /** - * Allows method chaining to continue configuring the {@link ServerHttpSecurity} + * Allows method chaining to continue configuring the + * {@link ServerHttpSecurity} * @return the {@link HeaderSpec} to continue configuring */ private HeaderSpec and() { @@ -3530,14 +3591,18 @@ public class ServerHttpSecurity { return and(); } - private FrameOptionsSpec() {} + private FrameOptionsSpec() { + } + } /** * Configures Strict Transport Security response header + * * @see #hsts() */ public class HstsSpec { + /** * Configures the max age. Default is one year. * @param maxAge the max age @@ -3564,10 +3629,9 @@ public class ServerHttpSecurity { *

    * *

    - * See Website hstspreload.org - * for additional details. + * See Website hstspreload.org for + * additional details. *

    - * * @param preload if subdomains should be included * @return the {@link HstsSpec} to continue configuring * @since 5.2.0 @@ -3579,7 +3643,8 @@ public class ServerHttpSecurity { } /** - * Allows method chaining to continue configuring the {@link ServerHttpSecurity} + * Allows method chaining to continue configuring the + * {@link ServerHttpSecurity} * @return the {@link HeaderSpec} to continue configuring */ public HeaderSpec and() { @@ -3595,14 +3660,18 @@ public class ServerHttpSecurity { return HeaderSpec.this; } - private HstsSpec() {} + private HstsSpec() { + } + } /** * Configures x-xss-protection response header + * * @see #xssProtection() */ public class XssProtectionSpec { + /** * Disables the x-xss-protection response header * @return the {@link HeaderSpec} to continue configuring @@ -3612,7 +3681,9 @@ public class ServerHttpSecurity { return HeaderSpec.this; } - private XssProtectionSpec() {} + private XssProtectionSpec() { + } + } /** @@ -3622,11 +3693,13 @@ public class ServerHttpSecurity { * @since 5.1 */ public class ContentSecurityPolicySpec { + private static final String DEFAULT_SRC_SELF_POLICY = "default-src 'self'"; /** - * Whether to include the {@code Content-Security-Policy-Report-Only} header in - * the response. Otherwise, defaults to the {@code Content-Security-Policy} header. + * Whether to include the {@code Content-Security-Policy-Report-Only} header + * in the response. Otherwise, defaults to the {@code Content-Security-Policy} + * header. * @param reportOnly whether to only report policy violations * @return the {@link HeaderSpec} to continue configuring */ @@ -3637,7 +3710,6 @@ public class ServerHttpSecurity { /** * Sets the security policy directive(s) to be used in the response header. - * * @param policyDirectives the security policy directive(s) * @return the {@link HeaderSpec} to continue configuring */ @@ -3662,6 +3734,7 @@ public class ServerHttpSecurity { private ContentSecurityPolicySpec() { HeaderSpec.this.contentSecurityPolicy.setPolicyDirectives(DEFAULT_SRC_SELF_POLICY); } + } /** @@ -3698,7 +3771,6 @@ public class ServerHttpSecurity { /** * Sets the policy to be used in the response header. - * * @param referrerPolicy a referrer policy * @return the {@link ReferrerPolicySpec} to continue configuring */ @@ -3726,27 +3798,30 @@ public class ServerHttpSecurity { } private HeaderSpec() { - this.writers = new ArrayList<>( - Arrays.asList(this.cacheControl, this.contentTypeOptions, this.hsts, - this.frameOptions, this.xss, this.featurePolicy, this.contentSecurityPolicy, - this.referrerPolicy)); + this.writers = new ArrayList<>(Arrays.asList(this.cacheControl, this.contentTypeOptions, this.hsts, + this.frameOptions, this.xss, this.featurePolicy, this.contentSecurityPolicy, this.referrerPolicy)); } } /** * Configures log out + * * @author Shazin Sadakath * @since 5.0 * @see #logout() */ public final class LogoutSpec { + private LogoutWebFilter logoutWebFilter = new LogoutWebFilter(); + private final SecurityContextServerLogoutHandler DEFAULT_LOGOUT_HANDLER = new SecurityContextServerLogoutHandler(); + private List logoutHandlers = new ArrayList<>(Arrays.asList(this.DEFAULT_LOGOUT_HANDLER)); /** - * Configures the logout handler. Default is {@code SecurityContextServerLogoutHandler} + * Configures the logout handler. Default is + * {@code SecurityContextServerLogoutHandler} * @param logoutHandler * @return the {@link LogoutSpec} to configure */ @@ -3764,13 +3839,14 @@ public class ServerHttpSecurity { /** * Configures what URL a POST to will trigger a log out. - * @param logoutUrl the url to trigger a log out (i.e. "/signout" would mean a POST to "/signout" would trigger - * log out) + * @param logoutUrl the url to trigger a log out (i.e. "/signout" would mean a + * POST to "/signout" would trigger log out) * @return the {@link LogoutSpec} to configure */ public LogoutSpec logoutUrl(String logoutUrl) { Assert.notNull(logoutUrl, "logoutUrl must not be null"); - ServerWebExchangeMatcher requiresLogout = ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, logoutUrl); + ServerWebExchangeMatcher requiresLogout = ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, + logoutUrl); return requiresLogout(requiresLogout); } @@ -3813,9 +3889,11 @@ public class ServerHttpSecurity { } if (this.logoutHandlers.isEmpty()) { return null; - } else if (this.logoutHandlers.size() == 1) { + } + else if (this.logoutHandlers.size() == 1) { return this.logoutHandlers.get(0); - } else { + } + else { return new DelegatingServerLogoutHandler(this.logoutHandlers); } } @@ -3828,7 +3906,9 @@ public class ServerHttpSecurity { http.addFilterAt(this.logoutWebFilter, SecurityWebFiltersOrder.LOGOUT); } - private LogoutSpec() {} + private LogoutSpec() { + } + } private T getBean(Class beanClass) { @@ -3842,25 +3922,25 @@ public class ServerHttpSecurity { return getBeanOrNull(ResolvableType.forClass(beanClass)); } - private T getBeanOrNull(ResolvableType type) { if (this.context == null) { return null; } - String[] names = this.context.getBeanNamesForType(type); + String[] names = this.context.getBeanNamesForType(type); if (names.length == 1) { return (T) this.context.getBean(names[0]); } return null; } - protected void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { + protected void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = applicationContext; } private static class OrderedWebFilter implements WebFilter, Ordered { + private final WebFilter webFilter; + private final int order; OrderedWebFilter(WebFilter webFilter, int order) { @@ -3869,8 +3949,7 @@ public class ServerHttpSecurity { } @Override - public Mono filter(ServerWebExchange exchange, - WebFilterChain chain) { + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { return this.webFilter.filter(exchange, chain); } @@ -3881,39 +3960,44 @@ public class ServerHttpSecurity { @Override public String toString() { - return "OrderedWebFilter{" + "webFilter=" + this.webFilter + ", order=" + this.order - + '}'; + return "OrderedWebFilter{" + "webFilter=" + this.webFilter + ", order=" + this.order + '}'; } + } /** * Workaround https://jira.spring.io/projects/SPR/issues/SPR-17213 */ static class ServerWebExchangeReactorContextWebFilter implements WebFilter { + @Override public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - return chain.filter(exchange) - .subscriberContext(Context.of(ServerWebExchange.class, exchange)); + return chain.filter(exchange).subscriberContext(Context.of(ServerWebExchange.class, exchange)); } + } /** * Configures anonymous authentication + * * @author Ankur Pathak * @since 5.2.0 */ public final class AnonymousSpec { + private String key; + private AnonymousAuthenticationWebFilter authenticationFilter; + private Object principal = "anonymousUser"; + private List authorities = AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"); /** - * Sets the key to identify tokens created for anonymous authentication. Default is a - * secure randomly generated key. - * - * @param key the key to identify tokens created for anonymous authentication. Default + * Sets the key to identify tokens created for anonymous authentication. Default * is a secure randomly generated key. + * @param key the key to identify tokens created for anonymous authentication. + * Default is a secure randomly generated key. * @return the {@link AnonymousSpec} for further customization of anonymous * authentication */ @@ -3924,7 +4008,6 @@ public class ServerHttpSecurity { /** * Sets the principal for {@link Authentication} objects of anonymous users - * * @param principal used for the {@link Authentication} object of anonymous users * @return the {@link AnonymousSpec} for further customization of anonymous * authentication @@ -3935,9 +4018,9 @@ public class ServerHttpSecurity { } /** - * Sets the {@link org.springframework.security.core.Authentication#getAuthorities()} - * for anonymous users - * + * Sets the + * {@link org.springframework.security.core.Authentication#getAuthorities()} for + * anonymous users * @param authorities Sets the * {@link org.springframework.security.core.Authentication#getAuthorities()} for * anonymous users @@ -3950,9 +4033,9 @@ public class ServerHttpSecurity { } /** - * Sets the {@link org.springframework.security.core.Authentication#getAuthorities()} - * for anonymous users - * + * Sets the + * {@link org.springframework.security.core.Authentication#getAuthorities()} for + * anonymous users * @param authorities Sets the * {@link org.springframework.security.core.Authentication#getAuthorities()} for * anonymous users (i.e. "ROLE_ANONYMOUS") @@ -3964,18 +4047,15 @@ public class ServerHttpSecurity { } /** - * Sets the {@link AnonymousAuthenticationWebFilter} used to populate an anonymous user. - * If this is set, no attributes on the {@link AnonymousSpec} will be set on the - * {@link AnonymousAuthenticationWebFilter}. - * - * @param authenticationFilter the {@link AnonymousAuthenticationWebFilter} used to - * populate an anonymous user. - * + * Sets the {@link AnonymousAuthenticationWebFilter} used to populate an anonymous + * user. If this is set, no attributes on the {@link AnonymousSpec} will be set on + * the {@link AnonymousAuthenticationWebFilter}. + * @param authenticationFilter the {@link AnonymousAuthenticationWebFilter} used + * to populate an anonymous user. * @return the {@link AnonymousSpec} for further customization of anonymous * authentication */ - public AnonymousSpec authenticationFilter( - AnonymousAuthenticationWebFilter authenticationFilter) { + public AnonymousSpec authenticationFilter(AnonymousAuthenticationWebFilter authenticationFilter) { this.authenticationFilter = authenticationFilter; return this; } @@ -3999,8 +4079,7 @@ public class ServerHttpSecurity { protected void configure(ServerHttpSecurity http) { if (authenticationFilter == null) { - authenticationFilter = new AnonymousAuthenticationWebFilter(getKey(), principal, - authorities); + authenticationFilter = new AnonymousAuthenticationWebFilter(getKey(), principal, authorities); } http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.ANONYMOUS_AUTHENTICATION); } @@ -4012,8 +4091,8 @@ public class ServerHttpSecurity { return key; } - - private AnonymousSpec() {} + private AnonymousSpec() { + } } diff --git a/config/src/main/java/org/springframework/security/config/websocket/WebSocketMessageBrokerSecurityBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/websocket/WebSocketMessageBrokerSecurityBeanDefinitionParser.java index 24fe2003dc..ae05bf0061 100644 --- a/config/src/main/java/org/springframework/security/config/websocket/WebSocketMessageBrokerSecurityBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/websocket/WebSocketMessageBrokerSecurityBeanDefinitionParser.java @@ -93,8 +93,8 @@ import org.w3c.dom.Element; * @author Rob Winch * @since 4.0 */ -public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements - BeanDefinitionParser { +public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements BeanDefinitionParser { + private static final String ID_ATTR = "id"; private static final String DISABLED_ATTR = "same-origin-disabled"; @@ -119,23 +119,19 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements ManagedMap matcherToExpression = new ManagedMap<>(); String id = element.getAttribute(ID_ATTR); - Element expressionHandlerElt = DomUtils.getChildElementByTagName(element, - EXPRESSION_HANDLER); + Element expressionHandlerElt = DomUtils.getChildElementByTagName(element, EXPRESSION_HANDLER); String expressionHandlerRef = expressionHandlerElt == null ? null : expressionHandlerElt.getAttribute("ref"); boolean expressionHandlerDefined = StringUtils.hasText(expressionHandlerRef); - boolean sameOriginDisabled = Boolean.parseBoolean(element - .getAttribute(DISABLED_ATTR)); + boolean sameOriginDisabled = Boolean.parseBoolean(element.getAttribute(DISABLED_ATTR)); - List interceptMessages = DomUtils.getChildElementsByTagName(element, - Elements.INTERCEPT_MESSAGE); + List interceptMessages = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_MESSAGE); for (Element interceptMessage : interceptMessages) { String matcherPattern = interceptMessage.getAttribute(PATTERN_ATTR); String accessExpression = interceptMessage.getAttribute(ACCESS_ATTR); String messageType = interceptMessage.getAttribute(TYPE_ATTR); - BeanDefinition matcher = createMatcher(matcherPattern, messageType, - parserContext, interceptMessage); + BeanDefinition matcher = createMatcher(matcherPattern, messageType, parserContext, interceptMessage); matcherToExpression.put(matcher, accessExpression); } @@ -150,24 +146,21 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements String mdsId = context.registerWithGeneratedName(mds.getBeanDefinition()); ManagedList voters = new ManagedList<>(); - BeanDefinitionBuilder messageExpressionVoterBldr = BeanDefinitionBuilder.rootBeanDefinition(MessageExpressionVoter.class); + BeanDefinitionBuilder messageExpressionVoterBldr = BeanDefinitionBuilder + .rootBeanDefinition(MessageExpressionVoter.class); if (expressionHandlerDefined) { messageExpressionVoterBldr.addPropertyReference("expressionHandler", expressionHandlerRef); } voters.add(messageExpressionVoterBldr.getBeanDefinition()); - BeanDefinitionBuilder adm = BeanDefinitionBuilder - .rootBeanDefinition(ConsensusBased.class); + BeanDefinitionBuilder adm = BeanDefinitionBuilder.rootBeanDefinition(ConsensusBased.class); adm.addConstructorArgValue(voters); BeanDefinitionBuilder inboundChannelSecurityInterceptor = BeanDefinitionBuilder .rootBeanDefinition(ChannelSecurityInterceptor.class); - inboundChannelSecurityInterceptor.addConstructorArgValue(registry - .getBeanDefinition(mdsId)); - inboundChannelSecurityInterceptor.addPropertyValue("accessDecisionManager", - adm.getBeanDefinition()); + inboundChannelSecurityInterceptor.addConstructorArgValue(registry.getBeanDefinition(mdsId)); + inboundChannelSecurityInterceptor.addPropertyValue("accessDecisionManager", adm.getBeanDefinition()); String inSecurityInterceptorName = context - .registerWithGeneratedName(inboundChannelSecurityInterceptor - .getBeanDefinition()); + .registerWithGeneratedName(inboundChannelSecurityInterceptor.getBeanDefinition()); if (StringUtils.hasText(id)) { registry.registerAlias(inSecurityInterceptorName, id); @@ -177,8 +170,7 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements } } else { - BeanDefinitionBuilder mspp = BeanDefinitionBuilder - .rootBeanDefinition(MessageSecurityPostProcessor.class); + BeanDefinitionBuilder mspp = BeanDefinitionBuilder.rootBeanDefinition(MessageSecurityPostProcessor.class); mspp.addConstructorArgValue(inSecurityInterceptorName); mspp.addConstructorArgValue(sameOriginDisabled); context.registerWithGeneratedName(mspp.getBeanDefinition()); @@ -187,13 +179,12 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements return null; } - private BeanDefinition createMatcher(String matcherPattern, String messageType, - ParserContext parserContext, Element interceptMessage) { + private BeanDefinition createMatcher(String matcherPattern, String messageType, ParserContext parserContext, + Element interceptMessage) { boolean hasPattern = StringUtils.hasText(matcherPattern); boolean hasMessageType = StringUtils.hasText(messageType); if (!hasPattern) { - BeanDefinitionBuilder matcher = BeanDefinitionBuilder - .rootBeanDefinition(SimpMessageTypeMatcher.class); + BeanDefinitionBuilder matcher = BeanDefinitionBuilder.rootBeanDefinition(SimpMessageTypeMatcher.class); matcher.addConstructorArgValue(messageType); return matcher.getBeanDefinition(); } @@ -208,25 +199,19 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements factoryName = "createSubscribeMatcher"; } else { - parserContext - .getReaderContext() - .error("Cannot use intercept-websocket@message-type=" - + messageType - + " with a pattern because the type does not have a destination.", - interceptMessage); + parserContext.getReaderContext().error("Cannot use intercept-websocket@message-type=" + messageType + + " with a pattern because the type does not have a destination.", interceptMessage); } } - BeanDefinitionBuilder matcher = BeanDefinitionBuilder - .rootBeanDefinition(SimpDestinationMessageMatcher.class); + BeanDefinitionBuilder matcher = BeanDefinitionBuilder.rootBeanDefinition(SimpDestinationMessageMatcher.class); matcher.setFactoryMethod(factoryName); matcher.addConstructorArgValue(matcherPattern); matcher.addConstructorArgValue(new RuntimeBeanReference("springSecurityMessagePathMatcher")); return matcher.getBeanDefinition(); } - static class MessageSecurityPostProcessor implements - BeanDefinitionRegistryPostProcessor { + static class MessageSecurityPostProcessor implements BeanDefinitionRegistryPostProcessor { /** * This is not available prior to Spring 4.2 @@ -248,22 +233,19 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements this.sameOriginDisabled = sameOriginDisabled; } - public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) - throws BeansException { + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { String[] beanNames = registry.getBeanDefinitionNames(); for (String beanName : beanNames) { BeanDefinition bd = registry.getBeanDefinition(beanName); String beanClassName = bd.getBeanClassName(); - if (SimpAnnotationMethodMessageHandler.class.getName().equals(beanClassName) || - WEB_SOCKET_AMMH_CLASS_NAME.equals(beanClassName)) { - PropertyValue current = bd.getPropertyValues().getPropertyValue( - CUSTOM_ARG_RESOLVERS_PROP); + if (SimpAnnotationMethodMessageHandler.class.getName().equals(beanClassName) + || WEB_SOCKET_AMMH_CLASS_NAME.equals(beanClassName)) { + PropertyValue current = bd.getPropertyValues().getPropertyValue(CUSTOM_ARG_RESOLVERS_PROP); ManagedList argResolvers = new ManagedList<>(); if (current != null) { argResolvers.addAll((ManagedList) current.getValue()); } - argResolvers.add(new RootBeanDefinition( - AuthenticationPrincipalArgumentResolver.class)); + argResolvers.add(new RootBeanDefinition(AuthenticationPrincipalArgumentResolver.class)); bd.getPropertyValues().add(CUSTOM_ARG_RESOLVERS_PROP, argResolvers); if (!registry.containsBeanDefinition(PATH_MATCHER_BEAN_NAME)) { @@ -292,20 +274,17 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements return; } ManagedList interceptors = new ManagedList(); - interceptors.add(new RootBeanDefinition( - SecurityContextChannelInterceptor.class)); + interceptors.add(new RootBeanDefinition(SecurityContextChannelInterceptor.class)); if (!sameOriginDisabled) { interceptors.add(new RootBeanDefinition(CsrfChannelInterceptor.class)); } interceptors.add(registry.getBeanDefinition(inboundSecurityInterceptorId)); - BeanDefinition inboundChannel = registry - .getBeanDefinition(CLIENT_INBOUND_CHANNEL_BEAN_ID); + BeanDefinition inboundChannel = registry.getBeanDefinition(CLIENT_INBOUND_CHANNEL_BEAN_ID); PropertyValue currentInterceptorsPv = inboundChannel.getPropertyValues() .getPropertyValue(INTERCEPTORS_PROP); if (currentInterceptorsPv != null) { - ManagedList currentInterceptors = (ManagedList) currentInterceptorsPv - .getValue(); + ManagedList currentInterceptors = (ManagedList) currentInterceptorsPv.getValue(); interceptors.addAll(currentInterceptors); } @@ -323,15 +302,14 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements String interceptorPropertyName = "handshakeInterceptors"; ManagedList interceptors = new ManagedList<>(); interceptors.add(new RootBeanDefinition(CsrfTokenHandshakeInterceptor.class)); - interceptors.addAll((ManagedList) bd.getPropertyValues().get( - interceptorPropertyName)); + interceptors.addAll((ManagedList) bd.getPropertyValues().get(interceptorPropertyName)); bd.getPropertyValues().add(interceptorPropertyName, interceptors); } - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) - throws BeansException { + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } + } static class DelegatingPathMatcher implements PathMatcher { @@ -369,5 +347,7 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements void setPathMatcher(PathMatcher pathMatcher) { this.delegate = pathMatcher; } + } + } diff --git a/config/src/test/java/org/springframework/security/BeanNameCollectingPostProcessor.java b/config/src/test/java/org/springframework/security/BeanNameCollectingPostProcessor.java index ff39888179..58a232135f 100644 --- a/config/src/test/java/org/springframework/security/BeanNameCollectingPostProcessor.java +++ b/config/src/test/java/org/springframework/security/BeanNameCollectingPostProcessor.java @@ -25,19 +25,19 @@ import org.springframework.beans.factory.config.BeanPostProcessor; * @author Luke Taylor */ public class BeanNameCollectingPostProcessor implements BeanPostProcessor { + Set beforeInitPostProcessedBeans = new HashSet<>(); + Set afterInitPostProcessedBeans = new HashSet<>(); - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (beanName != null) { beforeInitPostProcessedBeans.add(beanName); } return bean; } - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (beanName != null) { afterInitPostProcessedBeans.add(beanName); } @@ -51,4 +51,5 @@ public class BeanNameCollectingPostProcessor implements BeanPostProcessor { public Set getAfterInitPostProcessedBeans() { return afterInitPostProcessedBeans; } + } diff --git a/config/src/test/java/org/springframework/security/CollectingAppListener.java b/config/src/test/java/org/springframework/security/CollectingAppListener.java index 1dd1c5c21a..0589657430 100644 --- a/config/src/test/java/org/springframework/security/CollectingAppListener.java +++ b/config/src/test/java/org/springframework/security/CollectingAppListener.java @@ -30,9 +30,13 @@ import org.springframework.security.authentication.event.AbstractAuthenticationF * @since 3.1 */ public class CollectingAppListener implements ApplicationListener { + Set events = new HashSet<>(); + Set authenticationEvents = new HashSet<>(); + Set authenticationFailureEvents = new HashSet<>(); + Set authorizationEvents = new HashSet<>(); public void onApplicationEvent(ApplicationEvent event) { @@ -65,4 +69,5 @@ public class CollectingAppListener implements ApplicationListener { public Set getAuthorizationEvents() { return authorizationEvents; } + } diff --git a/config/src/test/java/org/springframework/security/config/ConfigTestUtils.java b/config/src/test/java/org/springframework/security/config/ConfigTestUtils.java index a95ffe3c4e..845323e7db 100644 --- a/config/src/test/java/org/springframework/security/config/ConfigTestUtils.java +++ b/config/src/test/java/org/springframework/security/config/ConfigTestUtils.java @@ -16,14 +16,13 @@ package org.springframework.security.config; public abstract class ConfigTestUtils { + public static final String AUTH_PROVIDER_XML = "" - + " " - + " " + + " " + " " + " " + " " + " " + " " - + " " - + " " - + ""; + + " " + " " + ""; + } diff --git a/config/src/test/java/org/springframework/security/config/DataSourcePopulator.java b/config/src/test/java/org/springframework/security/config/DataSourcePopulator.java index 212e2ad6b6..09142c1fd6 100644 --- a/config/src/test/java/org/springframework/security/config/DataSourcePopulator.java +++ b/config/src/test/java/org/springframework/security/config/DataSourcePopulator.java @@ -27,6 +27,7 @@ import org.springframework.util.Assert; * @author Ben Alex */ public class DataSourcePopulator implements InitializingBean { + // ~ Instance fields // ================================================================================================ @@ -35,8 +36,10 @@ public class DataSourcePopulator implements InitializingBean { public void afterPropertiesSet() { Assert.notNull(template, "dataSource required"); - template.execute("CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(500) NOT NULL,ENABLED BOOLEAN NOT NULL);"); - template.execute("CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));"); + template.execute( + "CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(500) NOT NULL,ENABLED BOOLEAN NOT NULL);"); + template.execute( + "CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));"); template.execute("CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY);"); /* @@ -66,4 +69,5 @@ public class DataSourcePopulator implements InitializingBean { public void setDataSource(DataSource dataSource) { this.template = new JdbcTemplate(dataSource); } + } diff --git a/config/src/test/java/org/springframework/security/config/FilterChainProxyConfigTests.java b/config/src/test/java/org/springframework/security/config/FilterChainProxyConfigTests.java index 42a6eba6d5..88da0c4605 100644 --- a/config/src/test/java/org/springframework/security/config/FilterChainProxyConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/FilterChainProxyConfigTests.java @@ -50,6 +50,7 @@ import org.springframework.security.web.util.matcher.AnyRequestMatcher; * @author Ben Alex */ public class FilterChainProxyConfigTests { + private ClassPathXmlApplicationContext appCtx; // ~ Methods @@ -59,8 +60,7 @@ public class FilterChainProxyConfigTests { public void loadContext() { System.setProperty("sec1235.pattern1", "/login"); System.setProperty("sec1235.pattern2", "/logout"); - appCtx = new ClassPathXmlApplicationContext( - "org/springframework/security/util/filtertest-valid.xml"); + appCtx = new ClassPathXmlApplicationContext("org/springframework/security/util/filtertest-valid.xml"); } @After @@ -72,15 +72,13 @@ public class FilterChainProxyConfigTests { @Test public void normalOperation() throws Exception { - FilterChainProxy filterChainProxy = appCtx.getBean("filterChain", - FilterChainProxy.class); + FilterChainProxy filterChainProxy = appCtx.getBean("filterChain", FilterChainProxy.class); doNormalOperation(filterChainProxy); } @Test public void normalOperationWithNewConfig() throws Exception { - FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxy", - FilterChainProxy.class); + FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxy", FilterChainProxy.class); filterChainProxy.setFirewall(new DefaultHttpFirewall()); checkPathAndFilterOrder(filterChainProxy); doNormalOperation(filterChainProxy); @@ -88,8 +86,7 @@ public class FilterChainProxyConfigTests { @Test public void normalOperationWithNewConfigRegex() throws Exception { - FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxyRegex", - FilterChainProxy.class); + FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxyRegex", FilterChainProxy.class); filterChainProxy.setFirewall(new DefaultHttpFirewall()); checkPathAndFilterOrder(filterChainProxy); doNormalOperation(filterChainProxy); @@ -97,8 +94,7 @@ public class FilterChainProxyConfigTests { @Test public void normalOperationWithNewConfigNonNamespace() throws Exception { - FilterChainProxy filterChainProxy = appCtx.getBean( - "newFilterChainProxyNonNamespace", FilterChainProxy.class); + FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxyNonNamespace", FilterChainProxy.class); filterChainProxy.setFirewall(new DefaultHttpFirewall()); checkPathAndFilterOrder(filterChainProxy); doNormalOperation(filterChainProxy); @@ -106,26 +102,24 @@ public class FilterChainProxyConfigTests { @Test public void pathWithNoMatchHasNoFilters() { - FilterChainProxy filterChainProxy = appCtx.getBean( - "newFilterChainProxyNoDefaultPath", FilterChainProxy.class); + FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxyNoDefaultPath", FilterChainProxy.class); assertThat(filterChainProxy.getFilters("/nomatch")).isNull(); } // SEC-1235 @Test public void mixingPatternsAndPlaceholdersDoesntCauseOrderingIssues() { - FilterChainProxy fcp = appCtx.getBean("sec1235FilterChainProxy", - FilterChainProxy.class); + FilterChainProxy fcp = appCtx.getBean("sec1235FilterChainProxy", FilterChainProxy.class); List chains = fcp.getFilterChains(); assertThat(getPattern(chains.get(0))).isEqualTo("/login*"); assertThat(getPattern(chains.get(1))).isEqualTo("/logout"); - assertThat(((DefaultSecurityFilterChain) chains.get(2)).getRequestMatcher() instanceof AnyRequestMatcher).isTrue(); + assertThat(((DefaultSecurityFilterChain) chains.get(2)).getRequestMatcher() instanceof AnyRequestMatcher) + .isTrue(); } private String getPattern(SecurityFilterChain chain) { - return ((AntPathRequestMatcher) ((DefaultSecurityFilterChain) chain) - .getRequestMatcher()).getPattern(); + return ((AntPathRequestMatcher) ((DefaultSecurityFilterChain) chain).getRequestMatcher()).getPattern(); } private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy) { @@ -158,13 +152,12 @@ public class FilterChainProxyConfigTests { FilterChain chain = mock(FilterChain.class); filterChainProxy.doFilter(request, response, chain); - verify(chain).doFilter(any(HttpServletRequest.class), - any(HttpServletResponse.class)); + verify(chain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class)); request.setServletPath("/a/path/which/doesnt/match/any/filter.html"); chain = mock(FilterChain.class); filterChainProxy.doFilter(request, response, chain); - verify(chain).doFilter(any(HttpServletRequest.class), - any(HttpServletResponse.class)); + verify(chain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class)); } + } diff --git a/config/src/test/java/org/springframework/security/config/InvalidConfigurationTests.java b/config/src/test/java/org/springframework/security/config/InvalidConfigurationTests.java index 25ca973ef3..02011b0cc7 100644 --- a/config/src/test/java/org/springframework/security/config/InvalidConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/InvalidConfigurationTests.java @@ -34,6 +34,7 @@ import org.springframework.security.config.util.InMemoryXmlApplicationContext; * @author Luke Taylor */ public class InvalidConfigurationTests { + private InMemoryXmlApplicationContext appContext; @After @@ -65,8 +66,7 @@ public class InvalidConfigurationTests { assertThat(cause instanceof NoSuchBeanDefinitionException).isTrue(); NoSuchBeanDefinitionException nsbe = (NoSuchBeanDefinitionException) cause; assertThat(nsbe.getBeanName()).isEqualTo(BeanIds.AUTHENTICATION_MANAGER); - assertThat(nsbe.getMessage()).endsWith( - AuthenticationManagerFactoryBean.MISSING_BEAN_ERROR_MESSAGE); + assertThat(nsbe.getMessage()).endsWith(AuthenticationManagerFactoryBean.MISSING_BEAN_ERROR_MESSAGE); } } @@ -80,4 +80,5 @@ public class InvalidConfigurationTests { private void setContext(String context) { appContext = new InMemoryXmlApplicationContext(context); } + } diff --git a/config/src/test/java/org/springframework/security/config/MockAfterInvocationProvider.java b/config/src/test/java/org/springframework/security/config/MockAfterInvocationProvider.java index 6fc6ae1b3c..68f71e579c 100644 --- a/config/src/test/java/org/springframework/security/config/MockAfterInvocationProvider.java +++ b/config/src/test/java/org/springframework/security/config/MockAfterInvocationProvider.java @@ -24,9 +24,8 @@ import org.springframework.security.core.Authentication; public class MockAfterInvocationProvider implements AfterInvocationProvider { - public Object decide(Authentication authentication, Object object, - Collection config, Object returnedObject) - throws AccessDeniedException { + public Object decide(Authentication authentication, Object object, Collection config, + Object returnedObject) throws AccessDeniedException { return returnedObject; } diff --git a/config/src/test/java/org/springframework/security/config/MockEventListener.java b/config/src/test/java/org/springframework/security/config/MockEventListener.java index f92f7bcc8d..c566e15a99 100644 --- a/config/src/test/java/org/springframework/security/config/MockEventListener.java +++ b/config/src/test/java/org/springframework/security/config/MockEventListener.java @@ -26,8 +26,8 @@ import java.util.List; * @author Rob Winch * @since 5.0.2 */ -public class MockEventListener - implements ApplicationListener { +public class MockEventListener implements ApplicationListener { + private List events = new ArrayList<>(); public void onApplicationEvent(T event) { @@ -37,4 +37,5 @@ public class MockEventListener public List getEvents() { return this.events; } + } diff --git a/config/src/test/java/org/springframework/security/config/MockTransactionManager.java b/config/src/test/java/org/springframework/security/config/MockTransactionManager.java index fb4a207c96..bba810c227 100644 --- a/config/src/test/java/org/springframework/security/config/MockTransactionManager.java +++ b/config/src/test/java/org/springframework/security/config/MockTransactionManager.java @@ -26,8 +26,8 @@ import org.springframework.transaction.TransactionStatus; * @author Luke Taylor */ public class MockTransactionManager implements PlatformTransactionManager { - public TransactionStatus getTransaction(TransactionDefinition definition) - throws TransactionException { + + public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { return mock(TransactionStatus.class); } @@ -36,4 +36,5 @@ public class MockTransactionManager implements PlatformTransactionManager { public void rollback(TransactionStatus status) throws TransactionException { } + } diff --git a/config/src/test/java/org/springframework/security/config/MockUserServiceBeanPostProcessor.java b/config/src/test/java/org/springframework/security/config/MockUserServiceBeanPostProcessor.java index eb7acd044f..d403987473 100644 --- a/config/src/test/java/org/springframework/security/config/MockUserServiceBeanPostProcessor.java +++ b/config/src/test/java/org/springframework/security/config/MockUserServiceBeanPostProcessor.java @@ -26,18 +26,16 @@ import org.springframework.beans.factory.config.BeanPostProcessor; */ public class MockUserServiceBeanPostProcessor implements BeanPostProcessor { - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof PostProcessedMockUserDetailsService) { - ((PostProcessedMockUserDetailsService) bean) - .setPostProcessorWasHere("Hello from the post processor!"); + ((PostProcessedMockUserDetailsService) bean).setPostProcessorWasHere("Hello from the post processor!"); } return bean; } + } diff --git a/config/src/test/java/org/springframework/security/config/PostProcessedMockUserDetailsService.java b/config/src/test/java/org/springframework/security/config/PostProcessedMockUserDetailsService.java index 2e85d78f7b..7245db7ecf 100644 --- a/config/src/test/java/org/springframework/security/config/PostProcessedMockUserDetailsService.java +++ b/config/src/test/java/org/springframework/security/config/PostProcessedMockUserDetailsService.java @@ -19,6 +19,7 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; public class PostProcessedMockUserDetailsService implements UserDetailsService { + private String postProcessorWasHere; public PostProcessedMockUserDetailsService() { @@ -36,4 +37,5 @@ public class PostProcessedMockUserDetailsService implements UserDetailsService { public UserDetails loadUserByUsername(String username) { throw new UnsupportedOperationException("Not for actual use"); } + } diff --git a/config/src/test/java/org/springframework/security/config/SecurityNamespaceHandlerTests.java b/config/src/test/java/org/springframework/security/config/SecurityNamespaceHandlerTests.java index a2d17aa5dc..7831e310fb 100644 --- a/config/src/test/java/org/springframework/security/config/SecurityNamespaceHandlerTests.java +++ b/config/src/test/java/org/springframework/security/config/SecurityNamespaceHandlerTests.java @@ -41,7 +41,6 @@ import static org.powermock.api.mockito.PowerMockito.verifyStatic; import static org.powermock.api.mockito.PowerMockito.verifyZeroInteractions; /** - * * @author Luke Taylor * @author Rob Winch * @since 3.0 @@ -50,15 +49,16 @@ import static org.powermock.api.mockito.PowerMockito.verifyZeroInteractions; @PrepareForTest({ ClassUtils.class }) @PowerMockIgnore({ "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", "javax.xml.parsers.*" }) public class SecurityNamespaceHandlerTests { + @Rule public ExpectedException thrown = ExpectedException.none(); - private static final String XML_AUTHENTICATION_MANAGER = "" - + " " + " " - + " " - + " " + " " - + ""; + private static final String XML_AUTHENTICATION_MANAGER = "" + " " + + " " + " " + + " " + " " + ""; + private static final String XML_HTTP_BLOCK = ""; + private static final String FILTER_CHAIN_PROXY_CLASSNAME = "org.springframework.security.web.FilterChainProxy"; @Test @@ -74,15 +74,13 @@ public class SecurityNamespaceHandlerTests { @Test public void pre32SchemaAreNotSupported() { try { - new InMemoryXmlApplicationContext( - "" - + " " - + "", "3.0.3", null); + new InMemoryXmlApplicationContext("" + + " " + "", "3.0.3", + null); fail("Expected BeanDefinitionParsingException"); } catch (BeanDefinitionParsingException expected) { - assertThat(expected.getMessage().contains( - "You cannot use a spring-security-2.0.xsd")); + assertThat(expected.getMessage().contains("You cannot use a spring-security-2.0.xsd")); } } @@ -91,8 +89,8 @@ public class SecurityNamespaceHandlerTests { public void initDoesNotLogErrorWhenFilterChainProxyFailsToLoad() throws Exception { String className = "javax.servlet.Filter"; spy(ClassUtils.class); - doThrow(new NoClassDefFoundError(className)).when(ClassUtils.class, "forName", - eq(FILTER_CHAIN_PROXY_CLASSNAME), any(ClassLoader.class)); + doThrow(new NoClassDefFoundError(className)).when(ClassUtils.class, "forName", eq(FILTER_CHAIN_PROXY_CLASSNAME), + any(ClassLoader.class)); Log logger = mock(Log.class); SecurityNamespaceHandler handler = new SecurityNamespaceHandler(); @@ -111,8 +109,8 @@ public class SecurityNamespaceHandlerTests { thrown.expect(BeanDefinitionParsingException.class); thrown.expectMessage("NoClassDefFoundError: " + className); spy(ClassUtils.class); - doThrow(new NoClassDefFoundError(className)).when(ClassUtils.class, "forName", - eq(FILTER_CHAIN_PROXY_CLASSNAME), any(ClassLoader.class)); + doThrow(new NoClassDefFoundError(className)).when(ClassUtils.class, "forName", eq(FILTER_CHAIN_PROXY_CLASSNAME), + any(ClassLoader.class)); new InMemoryXmlApplicationContext(XML_AUTHENTICATION_MANAGER + XML_HTTP_BLOCK); } @@ -120,8 +118,8 @@ public class SecurityNamespaceHandlerTests { public void filterNoClassDefFoundErrorNoHttpBlock() throws Exception { String className = "javax.servlet.Filter"; spy(ClassUtils.class); - doThrow(new NoClassDefFoundError(className)).when(ClassUtils.class, "forName", - eq(FILTER_CHAIN_PROXY_CLASSNAME), any(ClassLoader.class)); + doThrow(new NoClassDefFoundError(className)).when(ClassUtils.class, "forName", eq(FILTER_CHAIN_PROXY_CLASSNAME), + any(ClassLoader.class)); new InMemoryXmlApplicationContext(XML_AUTHENTICATION_MANAGER); // should load just fine since no http block } @@ -151,9 +149,10 @@ public class SecurityNamespaceHandlerTests { public void websocketNotFoundExceptionNoMessageBlock() throws Exception { String className = FILTER_CHAIN_PROXY_CLASSNAME; spy(ClassUtils.class); - doThrow(new ClassNotFoundException(className)).when(ClassUtils.class, "forName", - eq(Message.class.getName()), any(ClassLoader.class)); + doThrow(new ClassNotFoundException(className)).when(ClassUtils.class, "forName", eq(Message.class.getName()), + any(ClassLoader.class)); new InMemoryXmlApplicationContext(XML_AUTHENTICATION_MANAGER); // should load just fine since no websocket block } + } diff --git a/config/src/test/java/org/springframework/security/config/TestBusinessBean.java b/config/src/test/java/org/springframework/security/config/TestBusinessBean.java index 8a27748dcf..aac8eefd0e 100644 --- a/config/src/test/java/org/springframework/security/config/TestBusinessBean.java +++ b/config/src/test/java/org/springframework/security/config/TestBusinessBean.java @@ -29,4 +29,5 @@ public interface TestBusinessBean { void doSomething(); void unprotected(); + } diff --git a/config/src/test/java/org/springframework/security/config/TestBusinessBeanImpl.java b/config/src/test/java/org/springframework/security/config/TestBusinessBeanImpl.java index 18e5dbbe7f..3630dcd3a8 100644 --- a/config/src/test/java/org/springframework/security/config/TestBusinessBeanImpl.java +++ b/config/src/test/java/org/springframework/security/config/TestBusinessBeanImpl.java @@ -21,8 +21,8 @@ import org.springframework.security.core.session.SessionCreationEvent; /** * @author Luke Taylor */ -public class TestBusinessBeanImpl implements TestBusinessBean, - ApplicationListener { +public class TestBusinessBeanImpl implements TestBusinessBean, ApplicationListener { + public void setInteger(int i) { } @@ -46,4 +46,5 @@ public class TestBusinessBeanImpl implements TestBusinessBean, public void onApplicationEvent(SessionCreationEvent event) { System.out.println(event); } + } diff --git a/config/src/test/java/org/springframework/security/config/TransactionalTestBusinessBean.java b/config/src/test/java/org/springframework/security/config/TransactionalTestBusinessBean.java index f45648d261..7b59815a83 100644 --- a/config/src/test/java/org/springframework/security/config/TransactionalTestBusinessBean.java +++ b/config/src/test/java/org/springframework/security/config/TransactionalTestBusinessBean.java @@ -21,6 +21,7 @@ import org.springframework.transaction.annotation.Transactional; * @author Luke Taylor */ public class TransactionalTestBusinessBean implements TestBusinessBean { + public void setInteger(int i) { } @@ -37,4 +38,5 @@ public class TransactionalTestBusinessBean implements TestBusinessBean { public void unprotected() { } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/ConcereteSecurityConfigurerAdapter.java b/config/src/test/java/org/springframework/security/config/annotation/ConcereteSecurityConfigurerAdapter.java index 78c12afeea..5075300c77 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/ConcereteSecurityConfigurerAdapter.java +++ b/config/src/test/java/org/springframework/security/config/annotation/ConcereteSecurityConfigurerAdapter.java @@ -22,8 +22,8 @@ import java.util.List; * @author Rob Winch * */ -class ConcereteSecurityConfigurerAdapter extends - SecurityConfigurerAdapter> { +class ConcereteSecurityConfigurerAdapter extends SecurityConfigurerAdapter> { + private List list = new ArrayList<>(); @Override @@ -35,4 +35,5 @@ class ConcereteSecurityConfigurerAdapter extends this.list = l; return this; } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/ObjectPostProcessorTests.java b/config/src/test/java/org/springframework/security/config/annotation/ObjectPostProcessorTests.java index ad93dc340e..ee88e3c219 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/ObjectPostProcessorTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/ObjectPostProcessorTests.java @@ -32,8 +32,7 @@ public class ObjectPostProcessorTests { @Test public void convertTypes() { - assertThat((Object) PerformConversion.perform(new ArrayList<>())) - .isInstanceOf(LinkedList.class); + assertThat((Object) PerformConversion.perform(new ArrayList<>())).isInstanceOf(LinkedList.class); } static class ListToLinkedListObjectPostProcessor implements ObjectPostProcessor> { @@ -41,13 +40,15 @@ public class ObjectPostProcessorTests { public > O postProcess(O l) { return (O) new LinkedList(l); } + } static class PerformConversion { + public static List perform(ArrayList l) { return new ListToLinkedListObjectPostProcessor().postProcess(l); } + } + } - - diff --git a/config/src/test/java/org/springframework/security/config/annotation/SecurityConfigurerAdapterClosureTests.java b/config/src/test/java/org/springframework/security/config/annotation/SecurityConfigurerAdapterClosureTests.java index 9565546229..83535e1211 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/SecurityConfigurerAdapterClosureTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/SecurityConfigurerAdapterClosureTests.java @@ -15,7 +15,6 @@ */ package org.springframework.security.config.annotation; - import java.util.ArrayList; import java.util.List; @@ -30,6 +29,7 @@ import static org.mockito.Mockito.mock; * */ public class SecurityConfigurerAdapterClosureTests { + ConcereteSecurityConfigurerAdapter conf = new ConcereteSecurityConfigurerAdapter(); @Test @@ -49,8 +49,8 @@ public class SecurityConfigurerAdapterClosureTests { assertThat(this.conf.list).contains("a"); } - static class ConcereteSecurityConfigurerAdapter extends - SecurityConfigurerAdapter> { + static class ConcereteSecurityConfigurerAdapter extends SecurityConfigurerAdapter> { + private List list = new ArrayList(); @Override @@ -62,5 +62,7 @@ public class SecurityConfigurerAdapterClosureTests { this.list = l; return this; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/SecurityConfigurerAdapterTests.java b/config/src/test/java/org/springframework/security/config/annotation/SecurityConfigurerAdapterTests.java index 2b01f0137f..753c5c39d5 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/SecurityConfigurerAdapterTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/SecurityConfigurerAdapterTests.java @@ -22,6 +22,7 @@ import org.junit.Test; import org.springframework.core.Ordered; public class SecurityConfigurerAdapterTests { + ConcereteSecurityConfigurerAdapter adapter; @Before @@ -39,6 +40,7 @@ public class SecurityConfigurerAdapterTests { } static class OrderedObjectPostProcessor implements ObjectPostProcessor, Ordered { + private final int order; OrderedObjectPostProcessor(int order) { @@ -53,5 +55,7 @@ public class SecurityConfigurerAdapterTests { public String postProcess(String object) { return object + " " + order; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java index 6fac5b0e29..0bf1a8e566 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java @@ -63,6 +63,7 @@ import static org.springframework.security.test.web.servlet.response.SecurityMoc * @author Rob Winch */ public class AuthenticationManagerBuilderTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -84,15 +85,14 @@ public class AuthenticationManagerBuilderTests { ObjectPostProcessor opp = mock(ObjectPostProcessor.class); AuthenticationEventPublisher aep = mock(AuthenticationEventPublisher.class); when(opp.postProcess(any())).thenAnswer(a -> a.getArgument(0)); - AuthenticationManager am = new AuthenticationManagerBuilder(opp) - .authenticationEventPublisher(aep) - .inMemoryAuthentication() - .and() - .build(); + AuthenticationManager am = new AuthenticationManagerBuilder(opp).authenticationEventPublisher(aep) + .inMemoryAuthentication().and().build(); try { am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); - } catch (AuthenticationException success) {} + } + catch (AuthenticationException success) { + } verify(aep).publishAuthenticationFailure(any(), any()); } @@ -100,8 +100,8 @@ public class AuthenticationManagerBuilderTests { @Test public void getAuthenticationManagerWhenGlobalPasswordEncoderBeanThenUsed() throws Exception { this.spring.register(PasswordEncoderGlobalConfig.class).autowire(); - AuthenticationManager manager = this.spring.getContext() - .getBean(AuthenticationConfiguration.class).getAuthenticationManager(); + AuthenticationManager manager = this.spring.getContext().getBean(AuthenticationConfiguration.class) + .getAuthenticationManager(); Authentication auth = manager.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); @@ -111,6 +111,7 @@ public class AuthenticationManagerBuilderTests { @EnableWebSecurity static class PasswordEncoderGlobalConfig extends WebSecurityConfigurerAdapter { + @Autowired void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -124,13 +125,14 @@ public class AuthenticationManagerBuilderTests { PasswordEncoder passwordEncoder() { return NoOpPasswordEncoder.getInstance(); } + } @Test public void getAuthenticationManagerWhenProtectedPasswordEncoderBeanThenUsed() throws Exception { this.spring.register(PasswordEncoderGlobalConfig.class).autowire(); - AuthenticationManager manager = this.spring.getContext() - .getBean(AuthenticationConfiguration.class).getAuthenticationManager(); + AuthenticationManager manager = this.spring.getContext().getBean(AuthenticationConfiguration.class) + .getAuthenticationManager(); Authentication auth = manager.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); @@ -140,6 +142,7 @@ public class AuthenticationManagerBuilderTests { @EnableWebSecurity static class PasswordEncoderConfig extends WebSecurityConfigurerAdapter { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -152,6 +155,7 @@ public class AuthenticationManagerBuilderTests { PasswordEncoder passwordEncoder() { return NoOpPasswordEncoder.getInstance(); } + } @Autowired(required = false) @@ -161,22 +165,18 @@ public class AuthenticationManagerBuilderTests { public void authenticationManagerWhenMultipleProvidersThenWorks() throws Exception { this.spring.register(MultiAuthenticationProvidersConfig.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(authenticated().withUsername("user").withRoles("USER")); + this.mockMvc.perform(formLogin()).andExpect(authenticated().withUsername("user").withRoles("USER")); this.mockMvc.perform(formLogin().user("admin")) - .andExpect(authenticated().withUsername("admin").withRoles("USER", "ADMIN")); + .andExpect(authenticated().withUsername("admin").withRoles("USER", "ADMIN")); } @EnableWebSecurity - static class MultiAuthenticationProvidersConfig - extends WebSecurityConfigurerAdapter { + static class MultiAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication() - .withUser(PasswordEncodedUser.user()) - .and() - .inMemoryAuthentication() - .withUser(PasswordEncodedUser.admin()); + auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user()).and().inMemoryAuthentication() + .withUser(PasswordEncodedUser.admin()); } } @@ -219,7 +219,7 @@ public class AuthenticationManagerBuilderTests { this.spring.register(UserFromPropertiesConfig.class).autowire(); this.mockMvc.perform(formLogin().user("joe", "joespassword")) - .andExpect(authenticated().withUsername("joe").withRoles("USER")); + .andExpect(authenticated().withUsername("joe").withRoles("USER")); } @Configuration @@ -248,6 +248,7 @@ public class AuthenticationManagerBuilderTests { properties.load(this.users.getInputStream()); return new InMemoryUserDetailsManager(properties); } + } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/BaseAuthenticationConfig.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/BaseAuthenticationConfig.java index b2546aee46..c38be2364e 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/BaseAuthenticationConfig.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/BaseAuthenticationConfig.java @@ -19,13 +19,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; - /** - * * @author Rob Winch */ @Configuration public class BaseAuthenticationConfig { + @Autowired protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -35,4 +34,5 @@ public class BaseAuthenticationConfig { .withUser("admin").password("password").roles("USER", "ADMIN"); // @formatter:on } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.java index cab352ce61..fd39a39dbf 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.java @@ -33,6 +33,7 @@ import static org.springframework.security.test.web.servlet.response.SecurityMoc * @author Rob Winch */ public class NamespaceAuthenticationManagerTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -44,15 +45,16 @@ public class NamespaceAuthenticationManagerTests { this.spring.register(EraseCredentialsTrueDefaultConfig.class).autowire(); this.mockMvc.perform(formLogin()) - .andExpect(authenticated().withAuthentication(a-> assertThat(a.getCredentials()).isNull())); + .andExpect(authenticated().withAuthentication(a -> assertThat(a.getCredentials()).isNull())); this.mockMvc.perform(formLogin()) - .andExpect(authenticated().withAuthentication(a-> assertThat(a.getCredentials()).isNull())); + .andExpect(authenticated().withAuthentication(a -> assertThat(a.getCredentials()).isNull())); // no exception due to username being cleared out } @EnableWebSecurity static class EraseCredentialsTrueDefaultConfig extends WebSecurityConfigurerAdapter { + @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -61,6 +63,7 @@ public class NamespaceAuthenticationManagerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test @@ -68,15 +71,16 @@ public class NamespaceAuthenticationManagerTests { this.spring.register(EraseCredentialsFalseConfig.class).autowire(); this.mockMvc.perform(formLogin()) - .andExpect(authenticated().withAuthentication(a-> assertThat(a.getCredentials()).isNotNull())); + .andExpect(authenticated().withAuthentication(a -> assertThat(a.getCredentials()).isNotNull())); this.mockMvc.perform(formLogin()) - .andExpect(authenticated().withAuthentication(a-> assertThat(a.getCredentials()).isNotNull())); + .andExpect(authenticated().withAuthentication(a -> assertThat(a.getCredentials()).isNotNull())); // no exception due to username being cleared out } @EnableWebSecurity static class EraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter { + @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -86,6 +90,7 @@ public class NamespaceAuthenticationManagerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test @@ -94,11 +99,12 @@ public class NamespaceAuthenticationManagerTests { this.spring.register(GlobalEraseCredentialsFalseConfig.class).autowire(); this.mockMvc.perform(formLogin()) - .andExpect(authenticated().withAuthentication(a-> assertThat(a.getCredentials()).isNotNull())); + .andExpect(authenticated().withAuthentication(a -> assertThat(a.getCredentials()).isNotNull())); } @EnableWebSecurity static class GlobalEraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter { + @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -108,5 +114,7 @@ public class NamespaceAuthenticationManagerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java index d4ec0812ca..6379257b25 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java @@ -49,12 +49,12 @@ public class NamespaceAuthenticationProviderTests { public void authenticationProviderRef() throws Exception { this.spring.register(AuthenticationProviderRefConfig.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(authenticated().withUsername("user")); + this.mockMvc.perform(formLogin()).andExpect(authenticated().withUsername("user")); } @EnableWebSecurity static class AuthenticationProviderRefConfig extends WebSecurityConfigurerAdapter { + protected void configure(AuthenticationManagerBuilder auth) { // @formatter:off auth @@ -68,6 +68,7 @@ public class NamespaceAuthenticationProviderTests { result.setUserDetailsService(new InMemoryUserDetailsManager(PasswordEncodedUser.user())); return result; } + } @Test @@ -75,12 +76,12 @@ public class NamespaceAuthenticationProviderTests { public void authenticationProviderUserServiceRef() throws Exception { this.spring.register(AuthenticationProviderRefConfig.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(authenticated().withUsername("user")); + this.mockMvc.perform(formLogin()).andExpect(authenticated().withUsername("user")); } @EnableWebSecurity static class UserServiceRefConfig extends WebSecurityConfigurerAdapter { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth @@ -92,5 +93,7 @@ public class NamespaceAuthenticationProviderTests { public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager(PasswordEncodedUser.user()); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.java index 8e17e22a47..bc809bc3db 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.java @@ -53,12 +53,12 @@ public class NamespaceJdbcUserServiceTests { public void jdbcUserService() throws Exception { this.spring.register(DataSourceConfig.class, JdbcUserServiceConfig.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(authenticated().withUsername("user")); + this.mockMvc.perform(formLogin()).andExpect(authenticated().withUsername("user")); } @EnableWebSecurity static class JdbcUserServiceConfig extends WebSecurityConfigurerAdapter { + @Autowired private DataSource dataSource; @@ -71,27 +71,30 @@ public class NamespaceJdbcUserServiceTests { .dataSource(this.dataSource); // jdbc-user-service@data-source-ref // @formatter:on } + } @Configuration static class DataSourceConfig { + @Bean public DataSource dataSource() { EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); return builder.setType(EmbeddedDatabaseType.HSQL).build(); } + } @Test public void jdbcUserServiceCustom() throws Exception { this.spring.register(CustomDataSourceConfig.class, CustomJdbcUserServiceSampleConfig.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(authenticated().withUsername("user").withRoles("DBA", "USER")); + this.mockMvc.perform(formLogin()).andExpect(authenticated().withUsername("user").withRoles("DBA", "USER")); } @EnableWebSecurity static class CustomJdbcUserServiceSampleConfig extends WebSecurityConfigurerAdapter { + @Autowired private DataSource dataSource; @@ -129,16 +132,22 @@ public class NamespaceJdbcUserServiceTests { @Override public void removeUserFromCache(String username) { } + } + } + @Configuration static class CustomDataSourceConfig { + @Bean public DataSource dataSource() { EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder() - // simulate that the DB already has the schema loaded and users in it - .addScript("CustomJdbcUserServiceSampleConfig.sql"); + // simulate that the DB already has the schema loaded and users in it + .addScript("CustomJdbcUserServiceSampleConfig.sql"); return builder.setType(EmbeddedDatabaseType.HSQL).build(); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.java index e4ed142b39..7d40fc7d13 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.java @@ -52,12 +52,12 @@ public class NamespacePasswordEncoderTests { public void passwordEncoderRefWithInMemory() throws Exception { this.spring.register(PasswordEncoderWithInMemoryConfig.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(authenticated()); + this.mockMvc.perform(formLogin()).andExpect(authenticated()); } @EnableWebSecurity static class PasswordEncoderWithInMemoryConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); @@ -68,18 +68,19 @@ public class NamespacePasswordEncoderTests { .passwordEncoder(encoder); // @formatter:on } + } @Test public void passwordEncoderRefWithJdbc() throws Exception { this.spring.register(PasswordEncoderWithJdbcConfig.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(authenticated()); + this.mockMvc.perform(formLogin()).andExpect(authenticated()); } @EnableWebSecurity static class PasswordEncoderWithJdbcConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { @@ -99,18 +100,19 @@ public class NamespacePasswordEncoderTests { EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); return builder.setType(EmbeddedDatabaseType.HSQL).build(); } + } @Test public void passwordEncoderRefWithUserDetailsService() throws Exception { this.spring.register(PasswordEncoderWithUserDetailsServiceConfig.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(authenticated()); + this.mockMvc.perform(formLogin()).andExpect(authenticated()); } @EnableWebSecurity static class PasswordEncoderWithUserDetailsServiceConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); @@ -134,5 +136,7 @@ public class NamespacePasswordEncoderTests { EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); return builder.setType(EmbeddedDatabaseType.HSQL).build(); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.java index 2b2287b4f2..42b359193a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.java @@ -49,6 +49,7 @@ public class PasswordEncoderConfigurerTests { @EnableWebSecurity static class PasswordEncoderConfig extends WebSecurityConfigurerAdapter { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { BCryptPasswordEncoder encoder = passwordEncoder(); // @formatter:off @@ -67,19 +68,19 @@ public class PasswordEncoderConfigurerTests { public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } + } @Test public void passwordEncoderRefWhenAuthenticationManagerBuilderThenAuthenticationSuccess() throws Exception { this.spring.register(PasswordEncoderNoAuthManagerLoadsConfig.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(authenticated()); + this.mockMvc.perform(formLogin()).andExpect(authenticated()); } @EnableWebSecurity - static class PasswordEncoderNoAuthManagerLoadsConfig extends - WebSecurityConfigurerAdapter { + static class PasswordEncoderNoAuthManagerLoadsConfig extends WebSecurityConfigurerAdapter { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { BCryptPasswordEncoder encoder = passwordEncoder(); // @formatter:off @@ -94,5 +95,7 @@ public class PasswordEncoderConfigurerTests { public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationPublishTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationPublishTests.java index d797632e5b..cea8e87e92 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationPublishTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationPublishTests.java @@ -37,6 +37,7 @@ import static org.assertj.core.api.Assertions.*; */ @RunWith(SpringJUnit4ClassRunner.class) public class AuthenticationConfigurationPublishTests { + @Autowired MockEventListener listener; @@ -58,6 +59,7 @@ public class AuthenticationConfigurationPublishTests { @EnableGlobalAuthentication @Import(AuthenticationTestConfiguration.class) static class Config { + @Bean AuthenticationEventPublisher publisher() { return new DefaultAuthenticationEventPublisher(); @@ -65,8 +67,10 @@ public class AuthenticationConfigurationPublishTests { @Bean MockEventListener eventListener() { - return new MockEventListener(){}; + return new MockEventListener() { + }; } + } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java index 14546c85f7..7a7d98d083 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java @@ -79,81 +79,100 @@ public class AuthenticationConfigurationTests { @Test public void orderingAutowiredOnEnableGlobalMethodSecurity() { - this.spring.register(AuthenticationTestConfiguration.class, GlobalMethodSecurityAutowiredConfig.class, ServicesConfig.class).autowire(); + this.spring.register(AuthenticationTestConfiguration.class, GlobalMethodSecurityAutowiredConfig.class, + ServicesConfig.class).autowire(); - SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")); this.service.run(); } @EnableGlobalMethodSecurity(securedEnabled = true) static class GlobalMethodSecurityAutowiredConfig { + } @Test public void orderingAutowiredOnEnableWebSecurity() { - this.spring.register(AuthenticationTestConfiguration.class, WebSecurityConfig.class, GlobalMethodSecurityAutowiredConfig.class, ServicesConfig.class).autowire(); + this.spring.register(AuthenticationTestConfiguration.class, WebSecurityConfig.class, + GlobalMethodSecurityAutowiredConfig.class, ServicesConfig.class).autowire(); - SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")); this.service.run(); } @EnableWebSecurity - static class WebSecurityConfig {} + static class WebSecurityConfig { + } @Test public void orderingAutowiredOnEnableWebMvcSecurity() { - this.spring.register(AuthenticationTestConfiguration.class, WebMvcSecurityConfig.class, GlobalMethodSecurityAutowiredConfig.class, ServicesConfig.class).autowire(); + this.spring.register(AuthenticationTestConfiguration.class, WebMvcSecurityConfig.class, + GlobalMethodSecurityAutowiredConfig.class, ServicesConfig.class).autowire(); - SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")); this.service.run(); } @EnableWebMvcSecurity - static class WebMvcSecurityConfig {} + static class WebMvcSecurityConfig { + + } @Test public void getAuthenticationManagerWhenNoAuthenticationThenNull() throws Exception { this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class).autowire(); - assertThat(this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager()).isNull(); + assertThat(this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager()) + .isNull(); } - @Test public void getAuthenticationManagerWhenNoOpGlobalAuthenticationConfigurerAdapterThenNull() throws Exception { - this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class, NoOpGlobalAuthenticationConfigurerAdapter.class).autowire(); + this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class, + NoOpGlobalAuthenticationConfigurerAdapter.class).autowire(); - assertThat(this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager()).isNull(); + assertThat(this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager()) + .isNull(); } @Configuration - static class NoOpGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {} + static class NoOpGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { + + } @Test public void getAuthenticationWhenGlobalAuthenticationConfigurerAdapterThenAuthenticates() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password"); - this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class, UserGlobalAuthenticationConfigurerAdapter.class).autowire(); + this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class, + UserGlobalAuthenticationConfigurerAdapter.class).autowire(); - AuthenticationManager authentication = this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager(); + AuthenticationManager authentication = this.spring.getContext().getBean(AuthenticationConfiguration.class) + .getAuthenticationManager(); assertThat(authentication.authenticate(token).getName()).isEqualTo(token.getName()); } @Configuration static class UserGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { + public void init(AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication() - .withUser(PasswordEncodedUser.user()); + auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user()); } + } @Test public void getAuthenticationWhenAuthenticationManagerBeanThenAuthenticates() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password"); - this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class, AuthenticationManagerBeanConfig.class).autowire(); + this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class, + AuthenticationManagerBeanConfig.class).autowire(); - AuthenticationManager authentication = this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager(); + AuthenticationManager authentication = this.spring.getContext().getBean(AuthenticationConfiguration.class) + .getAuthenticationManager(); when(authentication.authenticate(token)).thenReturn(TestAuthentication.authenticatedUser()); assertThat(authentication.authenticate(token).getName()).isEqualTo(token.getName()); @@ -161,70 +180,93 @@ public class AuthenticationConfigurationTests { @Configuration static class AuthenticationManagerBeanConfig { + AuthenticationManager authenticationManager = mock(AuthenticationManager.class); @Bean public AuthenticationManager authenticationManager() { return this.authenticationManager; } + } - // - // // - // - @Configuration - static class ServicesConfig { - @Bean - public Service service() { - return new ServiceImpl(); - } + + // + // // + // + @Configuration + static class ServicesConfig { + + @Bean + public Service service() { + return new ServiceImpl(); } - interface Service { - void run(); + } + + interface Service { + + void run(); + + } + + static class ServiceImpl implements Service { + + @Secured("ROLE_USER") + public void run() { } - static class ServiceImpl implements Service { - @Secured("ROLE_USER") - public void run() {} + } + + @Test + public void getAuthenticationWhenMultipleThenOrdered() throws Exception { + this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class, + AuthenticationManagerBeanConfig.class).autowire(); + AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class); + config.setGlobalAuthenticationConfigurers(Arrays.asList(new LowestOrderGlobalAuthenticationConfigurerAdapter(), + new HighestOrderGlobalAuthenticationConfigurerAdapter(), + new DefaultOrderGlobalAuthenticationConfigurerAdapter())); + } + + static class DefaultOrderGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { + + static List> inits = new ArrayList<>(); + static List> configs = new ArrayList<>(); + + public void init(AuthenticationManagerBuilder auth) throws Exception { + inits.add(getClass()); } - @Test - public void getAuthenticationWhenMultipleThenOrdered() throws Exception { - this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class, AuthenticationManagerBeanConfig.class).autowire(); - AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class); - config.setGlobalAuthenticationConfigurers(Arrays.asList(new LowestOrderGlobalAuthenticationConfigurerAdapter(), new HighestOrderGlobalAuthenticationConfigurerAdapter(), new DefaultOrderGlobalAuthenticationConfigurerAdapter())); + public void configure(AuthenticationManagerBuilder auth) { + configs.add(getClass()); } - static class DefaultOrderGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { - static List> inits = new ArrayList<>(); - static List> configs = new ArrayList<>(); + } - public void init(AuthenticationManagerBuilder auth) throws Exception { - inits.add(getClass()); - } + @Order(Ordered.LOWEST_PRECEDENCE) + static class LowestOrderGlobalAuthenticationConfigurerAdapter + extends DefaultOrderGlobalAuthenticationConfigurerAdapter { - public void configure(AuthenticationManagerBuilder auth) { - configs.add(getClass()); - } - } + } - @Order(Ordered.LOWEST_PRECEDENCE) - static class LowestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {} + @Order(Ordered.HIGHEST_PRECEDENCE) + static class HighestOrderGlobalAuthenticationConfigurerAdapter + extends DefaultOrderGlobalAuthenticationConfigurerAdapter { - @Order(Ordered.HIGHEST_PRECEDENCE) - static class HighestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {} + } @Test public void getAuthenticationWhenConfiguredThenBootNotTrigger() throws Exception { this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class).autowire(); AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class); - config.setGlobalAuthenticationConfigurers(Arrays.asList(new ConfiguresInMemoryConfigurerAdapter(), new BootGlobalAuthenticationConfigurerAdapter())); + config.setGlobalAuthenticationConfigurers(Arrays.asList(new ConfiguresInMemoryConfigurerAdapter(), + new BootGlobalAuthenticationConfigurerAdapter())); AuthenticationManager authenticationManager = config.getAuthenticationManager(); authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); - assertThatThrownBy(() -> authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot", "password"))) - .isInstanceOf(AuthenticationException.class); + assertThatThrownBy( + () -> authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot", "password"))) + .isInstanceOf(AuthenticationException.class); } @@ -247,16 +289,21 @@ public class AuthenticationConfigurationTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Order(Ordered.LOWEST_PRECEDENCE) static class BootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter { + public void init(AuthenticationManagerBuilder auth) throws Exception { auth.apply(new DefaultBootGlobalAuthenticationConfigurerAdapter()); } + } - static class DefaultBootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter { + static class DefaultBootGlobalAuthenticationConfigurerAdapter + extends DefaultOrderGlobalAuthenticationConfigurerAdapter { + @Override public void configure(AuthenticationManagerBuilder auth) { if (auth.isConfigured()) { @@ -273,6 +320,7 @@ public class AuthenticationConfigurationTests { auth.authenticationProvider(provider); } + } // gh-2531 @@ -301,6 +349,7 @@ public class AuthenticationConfigurationTests { public AuthenticationManager manager() { return null; } + } @Test @@ -313,19 +362,24 @@ public class AuthenticationConfigurationTests { @Configuration @Import(AuthenticationConfiguration.class) - static class Sec2822Config {} + static class Sec2822Config { + + } @Configuration @EnableWebSecurity static class Sec2822WebSecurity extends WebSecurityConfigurerAdapter { + @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication(); } + } @Configuration static class Sec2822UseAuth { + @Autowired public void useAuthenticationManager(AuthenticationConfiguration auth) throws Exception { auth.getAuthenticationManager(); @@ -338,52 +392,62 @@ public class AuthenticationConfigurationTests { return new BootGlobalAuthenticationConfigurerAdapter(); } - static class BootGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { } + static class BootGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { + + } + } // sec-2868 @Test - public void getAuthenticationWhenUserDetailsServiceBeanThenAuthenticationManagerUsesUserDetailsServiceBean() throws Exception { + public void getAuthenticationWhenUserDetailsServiceBeanThenAuthenticationManagerUsesUserDetailsServiceBean() + throws Exception { this.spring.register(UserDetailsServiceBeanConfig.class).autowire(); UserDetailsService uds = this.spring.getContext().getBean(UserDetailsService.class); - AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager(); + AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) + .getAuthenticationManager(); when(uds.loadUserByUsername("user")).thenReturn(PasswordEncodedUser.user(), PasswordEncodedUser.user()); am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); assertThatThrownBy(() -> am.authenticate(new UsernamePasswordAuthenticationToken("user", "invalid"))) - .isInstanceOf(AuthenticationException.class); + .isInstanceOf(AuthenticationException.class); } @Configuration - @Import({AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class}) + @Import({ AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class }) static class UserDetailsServiceBeanConfig { + UserDetailsService uds = mock(UserDetailsService.class); @Bean UserDetailsService userDetailsService() { return this.uds; } + } @Test public void getAuthenticationWhenUserDetailsServiceAndPasswordEncoderBeanThenEncoderUsed() throws Exception { UserDetails user = new User("user", "$2a$10$FBAKClV1zBIOOC9XMXf3AO8RoGXYVYsfvUdoLxGkd/BnXEn4tqT3u", - AuthorityUtils.createAuthorityList("ROLE_USER")); + AuthorityUtils.createAuthorityList("ROLE_USER")); this.spring.register(UserDetailsServiceBeanWithPasswordEncoderConfig.class).autowire(); UserDetailsService uds = this.spring.getContext().getBean(UserDetailsService.class); - AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager(); - when(uds.loadUserByUsername("user")).thenReturn(User.withUserDetails(user).build(), User.withUserDetails(user).build()); + AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) + .getAuthenticationManager(); + when(uds.loadUserByUsername("user")).thenReturn(User.withUserDetails(user).build(), + User.withUserDetails(user).build()); am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); assertThatThrownBy(() -> am.authenticate(new UsernamePasswordAuthenticationToken("user", "invalid"))) - .isInstanceOf(AuthenticationException.class); + .isInstanceOf(AuthenticationException.class); } @Configuration - @Import({AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class}) + @Import({ AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class }) static class UserDetailsServiceBeanWithPasswordEncoderConfig { + UserDetailsService uds = mock(UserDetailsService.class); @Bean @@ -395,16 +459,19 @@ public class AuthenticationConfigurationTests { PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } + } @Test public void getAuthenticationWhenUserDetailsServiceAndPasswordManagerThenManagerUsed() throws Exception { - UserDetails user = new User("user", "{noop}password", - AuthorityUtils.createAuthorityList("ROLE_USER")); + UserDetails user = new User("user", "{noop}password", AuthorityUtils.createAuthorityList("ROLE_USER")); this.spring.register(UserDetailsPasswordManagerBeanConfig.class).autowire(); - UserDetailsPasswordManagerBeanConfig.Manager manager = this.spring.getContext().getBean(UserDetailsPasswordManagerBeanConfig.Manager.class); - AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager(); - when(manager.loadUserByUsername("user")).thenReturn(User.withUserDetails(user).build(), User.withUserDetails(user).build()); + UserDetailsPasswordManagerBeanConfig.Manager manager = this.spring.getContext() + .getBean(UserDetailsPasswordManagerBeanConfig.Manager.class); + AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) + .getAuthenticationManager(); + when(manager.loadUserByUsername("user")).thenReturn(User.withUserDetails(user).build(), + User.withUserDetails(user).build()); when(manager.updatePassword(any(), any())).thenReturn(user); am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); @@ -413,8 +480,9 @@ public class AuthenticationConfigurationTests { } @Configuration - @Import({AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class}) + @Import({ AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class }) static class UserDetailsPasswordManagerBeanConfig { + Manager manager = mock(Manager.class); @Bean @@ -423,15 +491,18 @@ public class AuthenticationConfigurationTests { } interface Manager extends UserDetailsService, UserDetailsPasswordService { + } + } - //gh-3091 + // gh-3091 @Test public void getAuthenticationWhenAuthenticationProviderBeanThenUsed() throws Exception { this.spring.register(AuthenticationProviderBeanConfig.class).autowire(); AuthenticationProvider ap = this.spring.getContext().getBean(AuthenticationProvider.class); - AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager(); + AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) + .getAuthenticationManager(); when(ap.supports(any())).thenReturn(true); when(ap.authenticate(any())).thenReturn(TestAuthentication.authenticatedUser()); @@ -439,21 +510,25 @@ public class AuthenticationConfigurationTests { } @Configuration - @Import({AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class}) + @Import({ AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class }) static class AuthenticationProviderBeanConfig { + AuthenticationProvider provider = mock(AuthenticationProvider.class); @Bean AuthenticationProvider authenticationProvider() { return this.provider; } + } @Test - public void getAuthenticationWhenAuthenticationProviderAndUserDetailsBeanThenAuthenticationProviderUsed() throws Exception { + public void getAuthenticationWhenAuthenticationProviderAndUserDetailsBeanThenAuthenticationProviderUsed() + throws Exception { this.spring.register(AuthenticationProviderBeanAndUserDetailsServiceConfig.class).autowire(); AuthenticationProvider ap = this.spring.getContext().getBean(AuthenticationProvider.class); - AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager(); + AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) + .getAuthenticationManager(); when(ap.supports(any())).thenReturn(true); when(ap.authenticate(any())).thenReturn(TestAuthentication.authenticatedUser()); @@ -461,8 +536,9 @@ public class AuthenticationConfigurationTests { } @Configuration - @Import({AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class}) + @Import({ AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class }) static class AuthenticationProviderBeanAndUserDetailsServiceConfig { + AuthenticationProvider provider = mock(AuthenticationProvider.class); UserDetailsService uds = mock(UserDetailsService.class); @@ -476,11 +552,13 @@ public class AuthenticationConfigurationTests { AuthenticationProvider authenticationProvider() { return this.provider; } + } @Test public void enableGlobalMethodSecurityWhenPreAuthorizeThenNoException() { - this.spring.register(UsesPreAuthorizeMethodSecurityConfig.class, AuthenticationManagerBeanConfig.class).autowire(); + this.spring.register(UsesPreAuthorizeMethodSecurityConfig.class, AuthenticationManagerBeanConfig.class) + .autowire(); // no exception } @@ -488,13 +566,17 @@ public class AuthenticationConfigurationTests { @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) static class UsesPreAuthorizeMethodSecurityConfig { + @PreAuthorize("denyAll") - void run() {} + void run() { + } + } @Test public void enableGlobalMethodSecurityWhenPreAuthorizeThenUsesMethodSecurityService() { - this.spring.register(ServicesConfig.class, UsesPreAuthorizeMethodSecurityConfig.class, AuthenticationManagerBeanConfig.class).autowire(); + this.spring.register(ServicesConfig.class, UsesPreAuthorizeMethodSecurityConfig.class, + AuthenticationManagerBeanConfig.class).autowire(); // no exception } @@ -502,8 +584,10 @@ public class AuthenticationConfigurationTests { @Configuration @EnableGlobalMethodSecurity(securedEnabled = true) static class UsesServiceMethodSecurityConfig { + @Autowired Service service; + } @Test @@ -537,11 +621,12 @@ public class AuthenticationConfigurationTests { this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager(); - assertThatThrownBy(ap::build) - .isInstanceOf(AlreadyBuiltException.class); + assertThatThrownBy(ap::build).isInstanceOf(AlreadyBuiltException.class); } @Configuration static class AuthenticationConfigurationSubclass extends AuthenticationConfiguration { + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthenticationTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthenticationTests.java index 0670a82769..604ea5a1c2 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthenticationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthenticationTests.java @@ -26,11 +26,11 @@ import org.springframework.security.config.annotation.authentication.builders.Au import org.springframework.security.config.test.SpringTestRule; /** - * * @author Rob Winch * */ public class EnableGlobalAuthenticationTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -52,6 +52,7 @@ public class EnableGlobalAuthenticationTests { public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("user").password("password").roles("USER"); } + } @Test @@ -66,6 +67,7 @@ public class EnableGlobalAuthenticationTests { @EnableGlobalAuthentication static class BeanProxyEnabledByDefaultConfig { + @Bean public Child child() { return new Child(); @@ -75,6 +77,7 @@ public class EnableGlobalAuthenticationTests { public Parent parent() { return new Parent(child()); } + } @Test @@ -90,6 +93,7 @@ public class EnableGlobalAuthenticationTests { @Configuration(proxyBeanMethods = false) @EnableGlobalAuthentication static class BeanProxyDisabledConfig { + @Bean public Child child() { return new Child(); @@ -99,9 +103,11 @@ public class EnableGlobalAuthenticationTests { public Parent parent() { return new Parent(child()); } + } static class Parent { + private Child child; Parent(Child child) { @@ -111,10 +117,14 @@ public class EnableGlobalAuthenticationTests { public Child getChild() { return child; } + } static class Child { + Child() { } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurerTests.java index b8b98509e6..0c786825ff 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurerTests.java @@ -41,4 +41,5 @@ public class LdapAuthenticationProviderConfigurerTests { assertThat(configurer.getAuthoritiesMapper()).isInstanceOf(NullAuthoritiesMapper.class); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/UserDetailsManagerConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/UserDetailsManagerConfigurerTests.java index 501c6cfe79..522887cf80 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/UserDetailsManagerConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/configurers/provisioning/UserDetailsManagerConfigurerTests.java @@ -28,10 +28,9 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.provisioning.InMemoryUserDetailsManager; /** -* -* @author Rob Winch -* @author Adolfo Eloy -*/ + * @author Rob Winch + * @author Adolfo Eloy + */ public class UserDetailsManagerConfigurerTests { private InMemoryUserDetailsManager userDetailsManager; @@ -43,16 +42,9 @@ public class UserDetailsManagerConfigurerTests { @Test public void allAttributesSupported() { - UserDetails userDetails = new UserDetailsManagerConfigurer>(userDetailsManager) - .withUser("user") - .password("password") - .roles("USER") - .disabled(true) - .accountExpired(true) - .accountLocked(true) - .credentialsExpired(true) - .build(); + UserDetails userDetails = new UserDetailsManagerConfigurer>( + userDetailsManager).withUser("user").password("password").roles("USER").disabled(true) + .accountExpired(true).accountLocked(true).credentialsExpired(true).build(); assertThat(userDetails.getUsername()).isEqualTo("user"); assertThat(userDetails.getPassword()).isEqualTo("password"); @@ -67,12 +59,8 @@ public class UserDetailsManagerConfigurerTests { public void authoritiesWithGrantedAuthorityWorks() { SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); - UserDetails userDetails = new UserDetailsManagerConfigurer>(userDetailsManager) - .withUser("user") - .password("password") - .authorities(authority) - .build(); + UserDetails userDetails = new UserDetailsManagerConfigurer>( + userDetailsManager).withUser("user").password("password").authorities(authority).build(); assertThat(userDetails.getAuthorities().stream().findFirst().get()).isEqualTo(authority); } @@ -81,12 +69,8 @@ public class UserDetailsManagerConfigurerTests { public void authoritiesWithStringAuthorityWorks() { String authority = "ROLE_USER"; - UserDetails userDetails = new UserDetailsManagerConfigurer>(userDetailsManager) - .withUser("user") - .password("password") - .authorities(authority) - .build(); + UserDetails userDetails = new UserDetailsManagerConfigurer>( + userDetailsManager).withUser("user").password("password").authorities(authority).build(); assertThat(userDetails.getAuthorities().stream().findFirst().get().getAuthority()).isEqualTo(authority); } @@ -95,13 +79,10 @@ public class UserDetailsManagerConfigurerTests { public void authoritiesWithAListOfGrantedAuthorityWorks() { SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); - UserDetails userDetails = new UserDetailsManagerConfigurer>(userDetailsManager) - .withUser("user") - .password("password") - .authorities(Arrays.asList(authority)) - .build(); + UserDetails userDetails = new UserDetailsManagerConfigurer>( + userDetailsManager).withUser("user").password("password").authorities(Arrays.asList(authority)).build(); assertThat(userDetails.getAuthorities().stream().findFirst().get()).isEqualTo(authority); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/configuration/AroundMethodInterceptor.java b/config/src/test/java/org/springframework/security/config/annotation/configuration/AroundMethodInterceptor.java index be4f491a96..354b99247a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/configuration/AroundMethodInterceptor.java +++ b/config/src/test/java/org/springframework/security/config/annotation/configuration/AroundMethodInterceptor.java @@ -19,7 +19,9 @@ import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class AroundMethodInterceptor implements MethodInterceptor { + public Object invoke(MethodInvocation methodInvocation) throws Throwable { return String.valueOf(methodInvocation.proceed()); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessorTests.java b/config/src/test/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessorTests.java index 9f51ff9038..eac66ebd19 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessorTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessorTests.java @@ -39,10 +39,10 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; /** - * * @author Rob Winch */ public class AutowireBeanFactoryObjectPostProcessorTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -127,10 +127,12 @@ public class AutowireBeanFactoryObjectPostProcessorTests { @Configuration static class Config { + @Bean public ObjectPostProcessor objectPostProcessor(AutowireCapableBeanFactory beanFactory) { return new AutowireBeanFactoryObjectPostProcessor(beanFactory); } + } @Test @@ -144,12 +146,14 @@ public class AutowireBeanFactoryObjectPostProcessorTests { @Configuration static class SmartConfig { + SmartInitializingSingleton toTest = mock(SmartInitializingSingleton.class); @Autowired public void configure(ObjectPostProcessor p) { p.postProcess(this.toTest); } + } @Test @@ -164,6 +168,7 @@ public class AutowireBeanFactoryObjectPostProcessorTests { @Configuration static class WithBeanNameAutoProxyCreatorConfig { + @Bean public ObjectPostProcessor objectPostProcessor(AutowireCapableBeanFactory beanFactory) { return new AutowireBeanFactoryObjectPostProcessor(beanFactory); @@ -173,5 +178,7 @@ public class AutowireBeanFactoryObjectPostProcessorTests { public void configure(ObjectPostProcessor p) { p.postProcess(new Object()); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/configuration/MyAdvisedBean.java b/config/src/test/java/org/springframework/security/config/annotation/configuration/MyAdvisedBean.java index d68c075ee9..493c2928c7 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/configuration/MyAdvisedBean.java +++ b/config/src/test/java/org/springframework/security/config/annotation/configuration/MyAdvisedBean.java @@ -20,4 +20,5 @@ public class MyAdvisedBean { public Object doStuff() { return null; } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/issue50/ApplicationConfig.java b/config/src/test/java/org/springframework/security/config/annotation/issue50/ApplicationConfig.java index 168d33d687..fb87a6eaf0 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/issue50/ApplicationConfig.java +++ b/config/src/test/java/org/springframework/security/config/annotation/issue50/ApplicationConfig.java @@ -38,6 +38,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; @EnableJpaRepositories("org.springframework.security.config.annotation.issue50.repo") @EnableTransactionManagement public class ApplicationConfig { + @Bean public DataSource dataSource() { EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); @@ -65,4 +66,5 @@ public class ApplicationConfig { txManager.setEntityManagerFactory(entityManagerFactory().getObject()); return txManager; } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/issue50/Issue50Tests.java b/config/src/test/java/org/springframework/security/config/annotation/issue50/Issue50Tests.java index 3d6f172921..df654ed93b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/issue50/Issue50Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/issue50/Issue50Tests.java @@ -43,8 +43,9 @@ import static org.assertj.core.api.Assertions.assertThat; */ @Transactional @RunWith(SpringRunner.class) -@ContextConfiguration(classes = {ApplicationConfig.class, SecurityConfig.class}) +@ContextConfiguration(classes = { ApplicationConfig.class, SecurityConfig.class }) public class Issue50Tests { + @Autowired private AuthenticationManager authenticationManager; @@ -53,7 +54,8 @@ public class Issue50Tests { @Before public void setup() { - SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("test", null, "ROLE_ADMIN")); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("test", null, "ROLE_ADMIN")); } @After @@ -82,7 +84,7 @@ public class Issue50Tests { public void authenticateWhenValidUserThenAuthenticates() { this.userRepo.save(User.withUsernameAndPassword("test", "password")); Authentication result = this.authenticationManager - .authenticate(new UsernamePasswordAuthenticationToken("test", "password")); + .authenticate(new UsernamePasswordAuthenticationToken("test", "password")); assertThat(result.getName()).isEqualTo("test"); } @@ -91,6 +93,7 @@ public class Issue50Tests { SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("test", null, "ROLE_USER")); this.userRepo.save(User.withUsernameAndPassword("denied", "password")); Authentication result = this.authenticationManager - .authenticate(new UsernamePasswordAuthenticationToken("test", "password")); + .authenticate(new UsernamePasswordAuthenticationToken("test", "password")); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/issue50/SecurityConfig.java b/config/src/test/java/org/springframework/security/config/annotation/issue50/SecurityConfig.java index b7051ebe51..791452636f 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/issue50/SecurityConfig.java +++ b/config/src/test/java/org/springframework/security/config/annotation/issue50/SecurityConfig.java @@ -42,6 +42,7 @@ import org.springframework.util.Assert; @EnableGlobalMethodSecurity(prePostEnabled = true) @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { + @Autowired private UserRepository myUserRepository; @@ -76,14 +77,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { return true; } - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { Object principal = authentication.getPrincipal(); String username = String.valueOf(principal); User user = myUserRepository.findByUsername(username); if (user == null) { - throw new UsernameNotFoundException("No user for principal " - + principal); + throw new UsernameNotFoundException("No user for principal " + principal); } if (!authentication.getCredentials().equals(user.getPassword())) { throw new BadCredentialsException("Invalid password"); @@ -92,4 +91,5 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { } }; } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/issue50/domain/User.java b/config/src/test/java/org/springframework/security/config/annotation/issue50/domain/User.java index 7d4a7dabf2..919a378429 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/issue50/domain/User.java +++ b/config/src/test/java/org/springframework/security/config/annotation/issue50/domain/User.java @@ -63,6 +63,7 @@ public class User { User user = new User(); user.setUsername(username); user.setPassword(password); - return user; + return user; } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/issue50/repo/UserRepository.java b/config/src/test/java/org/springframework/security/config/annotation/issue50/repo/UserRepository.java index 08a6f05176..f788d5caca 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/issue50/repo/UserRepository.java +++ b/config/src/test/java/org/springframework/security/config/annotation/issue50/repo/UserRepository.java @@ -27,4 +27,5 @@ public interface UserRepository extends CrudRepository { @PreAuthorize("hasRole('ROLE_ADMIN')") User findByUsername(String username); + } \ No newline at end of file diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/Authz.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/Authz.java index d4be78f42a..c206ef37f2 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/Authz.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/Authz.java @@ -35,7 +35,7 @@ public class Authz { } public boolean check(Authentication authentication, String message) { - return message != null && - message.contains(authentication.getName()); + return message != null && message.contains(authentication.getName()); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/DelegatingReactiveMessageService.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/DelegatingReactiveMessageService.java index 11e9e42a1a..4365f3ae9b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/DelegatingReactiveMessageService.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/DelegatingReactiveMessageService.java @@ -22,6 +22,7 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; public class DelegatingReactiveMessageService implements ReactiveMessageService { + private final ReactiveMessageService delegate; public DelegatingReactiveMessageService(ReactiveMessageService delegate) { @@ -41,29 +42,25 @@ public class DelegatingReactiveMessageService implements ReactiveMessageService @Override @PreAuthorize("hasRole('ADMIN')") - public Mono monoPreAuthorizeHasRoleFindById( - long id) { + public Mono monoPreAuthorizeHasRoleFindById(long id) { return delegate.monoPreAuthorizeHasRoleFindById(id); } @Override @PostAuthorize("returnObject?.contains(authentication?.name)") - public Mono monoPostAuthorizeFindById( - long id) { + public Mono monoPostAuthorizeFindById(long id) { return delegate.monoPostAuthorizeFindById(id); } @Override @PreAuthorize("@authz.check(#id)") - public Mono monoPreAuthorizeBeanFindById( - long id) { + public Mono monoPreAuthorizeBeanFindById(long id) { return delegate.monoPreAuthorizeBeanFindById(id); } @Override @PostAuthorize("@authz.check(authentication, returnObject)") - public Mono monoPostAuthorizeBeanFindById( - long id) { + public Mono monoPostAuthorizeBeanFindById(long id) { return delegate.monoPostAuthorizeBeanFindById(id); } @@ -74,29 +71,25 @@ public class DelegatingReactiveMessageService implements ReactiveMessageService @Override @PreAuthorize("hasRole('ADMIN')") - public Flux fluxPreAuthorizeHasRoleFindById( - long id) { + public Flux fluxPreAuthorizeHasRoleFindById(long id) { return delegate.fluxPreAuthorizeHasRoleFindById(id); } @Override @PostAuthorize("returnObject?.contains(authentication?.name)") - public Flux fluxPostAuthorizeFindById( - long id) { + public Flux fluxPostAuthorizeFindById(long id) { return delegate.fluxPostAuthorizeFindById(id); } @Override @PreAuthorize("@authz.check(#id)") - public Flux fluxPreAuthorizeBeanFindById( - long id) { + public Flux fluxPreAuthorizeBeanFindById(long id) { return delegate.fluxPreAuthorizeBeanFindById(id); } @Override @PostAuthorize("@authz.check(authentication, returnObject)") - public Flux fluxPostAuthorizeBeanFindById( - long id) { + public Flux fluxPostAuthorizeBeanFindById(long id) { return delegate.fluxPostAuthorizeBeanFindById(id); } @@ -107,29 +100,26 @@ public class DelegatingReactiveMessageService implements ReactiveMessageService @Override @PreAuthorize("hasRole('ADMIN')") - public Publisher publisherPreAuthorizeHasRoleFindById( - long id) { + public Publisher publisherPreAuthorizeHasRoleFindById(long id) { return delegate.publisherPreAuthorizeHasRoleFindById(id); } @Override @PostAuthorize("returnObject?.contains(authentication?.name)") - public Publisher publisherPostAuthorizeFindById( - long id) { + public Publisher publisherPostAuthorizeFindById(long id) { return delegate.publisherPostAuthorizeFindById(id); } @Override @PreAuthorize("@authz.check(#id)") - public Publisher publisherPreAuthorizeBeanFindById( - long id) { + public Publisher publisherPreAuthorizeBeanFindById(long id) { return delegate.publisherPreAuthorizeBeanFindById(id); } @Override @PostAuthorize("@authz.check(authentication, returnObject)") - public Publisher publisherPostAuthorizeBeanFindById( - long id) { + public Publisher publisherPostAuthorizeBeanFindById(long id) { return delegate.publisherPostAuthorizeBeanFindById(id); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/EnableReactiveMethodSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/EnableReactiveMethodSecurityTests.java index 9f87b52d4a..a84df2224a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/EnableReactiveMethodSecurityTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/EnableReactiveMethodSecurityTests.java @@ -44,12 +44,19 @@ import static org.mockito.Mockito.*; @RunWith(SpringRunner.class) @ContextConfiguration public class EnableReactiveMethodSecurityTests { - @Autowired ReactiveMessageService messageService; + + @Autowired + ReactiveMessageService messageService; + ReactiveMessageService delegate; + TestPublisher result = TestPublisher.create(); - Context withAdmin = ReactiveSecurityContextHolder.withAuthentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")); - Context withUser = ReactiveSecurityContextHolder.withAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")); + Context withAdmin = ReactiveSecurityContextHolder + .withAuthentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")); + + Context withUser = ReactiveSecurityContextHolder + .withAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")); @After public void cleanup() { @@ -64,9 +71,8 @@ public class EnableReactiveMethodSecurityTests { @Test public void notPublisherPreAuthorizeFindByIdThenThrowsIllegalStateException() { assertThatThrownBy(() -> this.messageService.notPublisherPreAuthorizeFindById(1L)) - .isInstanceOf(IllegalStateException.class) - .extracting(Throwable::getMessage) - .isEqualTo("The returnType class java.lang.String on public abstract java.lang.String org.springframework.security.config.annotation.method.configuration.ReactiveMessageService.notPublisherPreAuthorizeFindById(long) must return an instance of org.reactivestreams.Publisher (i.e. Mono / Flux) in order to support Reactor Context"); + .isInstanceOf(IllegalStateException.class).extracting(Throwable::getMessage).isEqualTo( + "The returnType class java.lang.String on public abstract java.lang.String org.springframework.security.config.annotation.method.configuration.ReactiveMessageService.notPublisherPreAuthorizeFindById(long) must return an instance of org.reactivestreams.Publisher (i.e. Mono / Flux) in order to support Reactor Context"); } @Test @@ -82,21 +88,15 @@ public class EnableReactiveMethodSecurityTests { public void monoWhenPermitAllThenSuccess() { when(this.delegate.monoFindById(1L)).thenReturn(Mono.just("success")); - StepVerifier.create(this.delegate.monoFindById(1L)) - .expectNext("success") - .verifyComplete(); + StepVerifier.create(this.delegate.monoFindById(1L)).expectNext("success").verifyComplete(); } @Test public void monoPreAuthorizeHasRoleWhenGrantedThenSuccess() { when(this.delegate.monoPreAuthorizeHasRoleFindById(1L)).thenReturn(Mono.just("result")); - Mono findById = this.messageService.monoPreAuthorizeHasRoleFindById(1L) - .subscriberContext(withAdmin); - StepVerifier - .create(findById) - .expectNext("result") - .verifyComplete(); + Mono findById = this.messageService.monoPreAuthorizeHasRoleFindById(1L).subscriberContext(withAdmin); + StepVerifier.create(findById).expectNext("result").verifyComplete(); } @Test @@ -104,10 +104,7 @@ public class EnableReactiveMethodSecurityTests { when(this.delegate.monoPreAuthorizeHasRoleFindById(1L)).thenReturn(Mono.from(result)); Mono findById = this.messageService.monoPreAuthorizeHasRoleFindById(1L); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); result.assertNoSubscribers(); } @@ -116,12 +113,8 @@ public class EnableReactiveMethodSecurityTests { public void monoPreAuthorizeHasRoleWhenNotAuthorizedThenDenied() { when(this.delegate.monoPreAuthorizeHasRoleFindById(1L)).thenReturn(Mono.from(result)); - Mono findById = this.messageService.monoPreAuthorizeHasRoleFindById(1L) - .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + Mono findById = this.messageService.monoPreAuthorizeHasRoleFindById(1L).subscriberContext(withUser); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); result.assertNoSubscribers(); } @@ -130,12 +123,8 @@ public class EnableReactiveMethodSecurityTests { public void monoPreAuthorizeBeanWhenGrantedThenSuccess() { when(this.delegate.monoPreAuthorizeBeanFindById(2L)).thenReturn(Mono.just("result")); - Mono findById = this.messageService.monoPreAuthorizeBeanFindById(2L) - .subscriberContext(withAdmin); - StepVerifier - .create(findById) - .expectNext("result") - .verifyComplete(); + Mono findById = this.messageService.monoPreAuthorizeBeanFindById(2L).subscriberContext(withAdmin); + StepVerifier.create(findById).expectNext("result").verifyComplete(); } @Test @@ -143,10 +132,7 @@ public class EnableReactiveMethodSecurityTests { when(this.delegate.monoPreAuthorizeBeanFindById(2L)).thenReturn(Mono.just("result")); Mono findById = this.messageService.monoPreAuthorizeBeanFindById(2L); - StepVerifier - .create(findById) - .expectNext("result") - .verifyComplete(); + StepVerifier.create(findById).expectNext("result").verifyComplete(); } @Test @@ -154,10 +140,7 @@ public class EnableReactiveMethodSecurityTests { when(this.delegate.monoPreAuthorizeBeanFindById(1L)).thenReturn(Mono.from(result)); Mono findById = this.messageService.monoPreAuthorizeBeanFindById(1L); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); result.assertNoSubscribers(); } @@ -166,12 +149,8 @@ public class EnableReactiveMethodSecurityTests { public void monoPreAuthorizeBeanWhenNotAuthorizedThenDenied() { when(this.delegate.monoPreAuthorizeBeanFindById(1L)).thenReturn(Mono.from(result)); - Mono findById = this.messageService.monoPreAuthorizeBeanFindById(1L) - .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + Mono findById = this.messageService.monoPreAuthorizeBeanFindById(1L).subscriberContext(withUser); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); result.assertNoSubscribers(); } @@ -180,36 +159,24 @@ public class EnableReactiveMethodSecurityTests { public void monoPostAuthorizeWhenAuthorizedThenSuccess() { when(this.delegate.monoPostAuthorizeFindById(1L)).thenReturn(Mono.just("user")); - Mono findById = this.messageService.monoPostAuthorizeFindById(1L) - .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectNext("user") - .verifyComplete(); + Mono findById = this.messageService.monoPostAuthorizeFindById(1L).subscriberContext(withUser); + StepVerifier.create(findById).expectNext("user").verifyComplete(); } @Test public void monoPostAuthorizeWhenNotAuthorizedThenDenied() { when(this.delegate.monoPostAuthorizeBeanFindById(1L)).thenReturn(Mono.just("not-authorized")); - Mono findById = this.messageService.monoPostAuthorizeBeanFindById(1L) - .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + Mono findById = this.messageService.monoPostAuthorizeBeanFindById(1L).subscriberContext(withUser); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); } @Test public void monoPostAuthorizeWhenBeanAndAuthorizedThenSuccess() { when(this.delegate.monoPostAuthorizeBeanFindById(2L)).thenReturn(Mono.just("user")); - Mono findById = this.messageService.monoPostAuthorizeBeanFindById(2L) - .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectNext("user") - .verifyComplete(); + Mono findById = this.messageService.monoPostAuthorizeBeanFindById(2L).subscriberContext(withUser); + StepVerifier.create(findById).expectNext("user").verifyComplete(); } @Test @@ -217,22 +184,15 @@ public class EnableReactiveMethodSecurityTests { when(this.delegate.monoPostAuthorizeBeanFindById(2L)).thenReturn(Mono.just("anonymous")); Mono findById = this.messageService.monoPostAuthorizeBeanFindById(2L); - StepVerifier - .create(findById) - .expectNext("anonymous") - .verifyComplete(); + StepVerifier.create(findById).expectNext("anonymous").verifyComplete(); } @Test public void monoPostAuthorizeWhenBeanAndNotAuthorizedThenDenied() { when(this.delegate.monoPostAuthorizeBeanFindById(1L)).thenReturn(Mono.just("not-authorized")); - Mono findById = this.messageService.monoPostAuthorizeBeanFindById(1L) - .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + Mono findById = this.messageService.monoPostAuthorizeBeanFindById(1L).subscriberContext(withUser); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); } // Flux tests @@ -250,20 +210,15 @@ public class EnableReactiveMethodSecurityTests { public void fluxWhenPermitAllThenSuccess() { when(this.delegate.fluxFindById(1L)).thenReturn(Flux.just("success")); - StepVerifier.create(this.delegate.fluxFindById(1L)) - .expectNext("success") - .verifyComplete(); + StepVerifier.create(this.delegate.fluxFindById(1L)).expectNext("success").verifyComplete(); } @Test public void fluxPreAuthorizeHasRoleWhenGrantedThenSuccess() { when(this.delegate.fluxPreAuthorizeHasRoleFindById(1L)).thenReturn(Flux.just("result")); - Flux findById = this.messageService.fluxPreAuthorizeHasRoleFindById(1L) - .subscriberContext(withAdmin); - StepVerifier - .create(findById) - .consumeNextWith( s -> AssertionsForClassTypes.assertThat(s).isEqualTo("result")) + Flux findById = this.messageService.fluxPreAuthorizeHasRoleFindById(1L).subscriberContext(withAdmin); + StepVerifier.create(findById).consumeNextWith(s -> AssertionsForClassTypes.assertThat(s).isEqualTo("result")) .verifyComplete(); } @@ -272,10 +227,7 @@ public class EnableReactiveMethodSecurityTests { when(this.delegate.fluxPreAuthorizeHasRoleFindById(1L)).thenReturn(Flux.from(result)); Flux findById = this.messageService.fluxPreAuthorizeHasRoleFindById(1L); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); result.assertNoSubscribers(); } @@ -284,12 +236,8 @@ public class EnableReactiveMethodSecurityTests { public void fluxPreAuthorizeHasRoleWhenNotAuthorizedThenDenied() { when(this.delegate.fluxPreAuthorizeHasRoleFindById(1L)).thenReturn(Flux.from(result)); - Flux findById = this.messageService.fluxPreAuthorizeHasRoleFindById(1L) - .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + Flux findById = this.messageService.fluxPreAuthorizeHasRoleFindById(1L).subscriberContext(withUser); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); result.assertNoSubscribers(); } @@ -298,12 +246,8 @@ public class EnableReactiveMethodSecurityTests { public void fluxPreAuthorizeBeanWhenGrantedThenSuccess() { when(this.delegate.fluxPreAuthorizeBeanFindById(2L)).thenReturn(Flux.just("result")); - Flux findById = this.messageService.fluxPreAuthorizeBeanFindById(2L) - .subscriberContext(withAdmin); - StepVerifier - .create(findById) - .expectNext("result") - .verifyComplete(); + Flux findById = this.messageService.fluxPreAuthorizeBeanFindById(2L).subscriberContext(withAdmin); + StepVerifier.create(findById).expectNext("result").verifyComplete(); } @Test @@ -311,10 +255,7 @@ public class EnableReactiveMethodSecurityTests { when(this.delegate.fluxPreAuthorizeBeanFindById(2L)).thenReturn(Flux.just("result")); Flux findById = this.messageService.fluxPreAuthorizeBeanFindById(2L); - StepVerifier - .create(findById) - .expectNext("result") - .verifyComplete(); + StepVerifier.create(findById).expectNext("result").verifyComplete(); } @Test @@ -322,10 +263,7 @@ public class EnableReactiveMethodSecurityTests { when(this.delegate.fluxPreAuthorizeBeanFindById(1L)).thenReturn(Flux.from(result)); Flux findById = this.messageService.fluxPreAuthorizeBeanFindById(1L); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); result.assertNoSubscribers(); } @@ -334,12 +272,8 @@ public class EnableReactiveMethodSecurityTests { public void fluxPreAuthorizeBeanWhenNotAuthorizedThenDenied() { when(this.delegate.fluxPreAuthorizeBeanFindById(1L)).thenReturn(Flux.from(result)); - Flux findById = this.messageService.fluxPreAuthorizeBeanFindById(1L) - .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + Flux findById = this.messageService.fluxPreAuthorizeBeanFindById(1L).subscriberContext(withUser); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); result.assertNoSubscribers(); } @@ -348,36 +282,24 @@ public class EnableReactiveMethodSecurityTests { public void fluxPostAuthorizeWhenAuthorizedThenSuccess() { when(this.delegate.fluxPostAuthorizeFindById(1L)).thenReturn(Flux.just("user")); - Flux findById = this.messageService.fluxPostAuthorizeFindById(1L) - .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectNext("user") - .verifyComplete(); + Flux findById = this.messageService.fluxPostAuthorizeFindById(1L).subscriberContext(withUser); + StepVerifier.create(findById).expectNext("user").verifyComplete(); } @Test public void fluxPostAuthorizeWhenNotAuthorizedThenDenied() { when(this.delegate.fluxPostAuthorizeBeanFindById(1L)).thenReturn(Flux.just("not-authorized")); - Flux findById = this.messageService.fluxPostAuthorizeBeanFindById(1L) - .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + Flux findById = this.messageService.fluxPostAuthorizeBeanFindById(1L).subscriberContext(withUser); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); } @Test public void fluxPostAuthorizeWhenBeanAndAuthorizedThenSuccess() { when(this.delegate.fluxPostAuthorizeBeanFindById(2L)).thenReturn(Flux.just("user")); - Flux findById = this.messageService.fluxPostAuthorizeBeanFindById(2L) - .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectNext("user") - .verifyComplete(); + Flux findById = this.messageService.fluxPostAuthorizeBeanFindById(2L).subscriberContext(withUser); + StepVerifier.create(findById).expectNext("user").verifyComplete(); } @Test @@ -385,22 +307,15 @@ public class EnableReactiveMethodSecurityTests { when(this.delegate.fluxPostAuthorizeBeanFindById(2L)).thenReturn(Flux.just("anonymous")); Flux findById = this.messageService.fluxPostAuthorizeBeanFindById(2L); - StepVerifier - .create(findById) - .expectNext("anonymous") - .verifyComplete(); + StepVerifier.create(findById).expectNext("anonymous").verifyComplete(); } @Test public void fluxPostAuthorizeWhenBeanAndNotAuthorizedThenDenied() { when(this.delegate.fluxPostAuthorizeBeanFindById(1L)).thenReturn(Flux.just("not-authorized")); - Flux findById = this.messageService.fluxPostAuthorizeBeanFindById(1L) - .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + Flux findById = this.messageService.fluxPostAuthorizeBeanFindById(1L).subscriberContext(withUser); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); } // Publisher tests @@ -418,9 +333,7 @@ public class EnableReactiveMethodSecurityTests { public void publisherWhenPermitAllThenSuccess() { when(this.delegate.publisherFindById(1L)).thenReturn(publisherJust("success")); - StepVerifier.create(this.delegate.publisherFindById(1L)) - .expectNext("success") - .verifyComplete(); + StepVerifier.create(this.delegate.publisherFindById(1L)).expectNext("success").verifyComplete(); } @Test @@ -429,9 +342,7 @@ public class EnableReactiveMethodSecurityTests { Publisher findById = Flux.from(this.messageService.publisherPreAuthorizeHasRoleFindById(1L)) .subscriberContext(withAdmin); - StepVerifier - .create(findById) - .consumeNextWith( s -> AssertionsForClassTypes.assertThat(s).isEqualTo("result")) + StepVerifier.create(findById).consumeNextWith(s -> AssertionsForClassTypes.assertThat(s).isEqualTo("result")) .verifyComplete(); } @@ -440,10 +351,7 @@ public class EnableReactiveMethodSecurityTests { when(this.delegate.publisherPreAuthorizeHasRoleFindById(1L)).thenReturn(result); Publisher findById = this.messageService.publisherPreAuthorizeHasRoleFindById(1L); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); result.assertNoSubscribers(); } @@ -454,10 +362,7 @@ public class EnableReactiveMethodSecurityTests { Publisher findById = Flux.from(this.messageService.publisherPreAuthorizeHasRoleFindById(1L)) .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); result.assertNoSubscribers(); } @@ -468,10 +373,7 @@ public class EnableReactiveMethodSecurityTests { Publisher findById = Flux.from(this.messageService.publisherPreAuthorizeBeanFindById(2L)) .subscriberContext(withAdmin); - StepVerifier - .create(findById) - .expectNext("result") - .verifyComplete(); + StepVerifier.create(findById).expectNext("result").verifyComplete(); } @Test @@ -479,10 +381,7 @@ public class EnableReactiveMethodSecurityTests { when(this.delegate.publisherPreAuthorizeBeanFindById(2L)).thenReturn(publisherJust("result")); Publisher findById = this.messageService.publisherPreAuthorizeBeanFindById(2L); - StepVerifier - .create(findById) - .expectNext("result") - .verifyComplete(); + StepVerifier.create(findById).expectNext("result").verifyComplete(); } @Test @@ -490,10 +389,7 @@ public class EnableReactiveMethodSecurityTests { when(this.delegate.publisherPreAuthorizeBeanFindById(1L)).thenReturn(result); Publisher findById = this.messageService.publisherPreAuthorizeBeanFindById(1L); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); result.assertNoSubscribers(); } @@ -504,10 +400,7 @@ public class EnableReactiveMethodSecurityTests { Publisher findById = Flux.from(this.messageService.publisherPreAuthorizeBeanFindById(1L)) .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); result.assertNoSubscribers(); } @@ -518,10 +411,7 @@ public class EnableReactiveMethodSecurityTests { Publisher findById = Flux.from(this.messageService.publisherPostAuthorizeFindById(1L)) .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectNext("user") - .verifyComplete(); + StepVerifier.create(findById).expectNext("user").verifyComplete(); } @Test @@ -530,10 +420,7 @@ public class EnableReactiveMethodSecurityTests { Publisher findById = Flux.from(this.messageService.publisherPostAuthorizeBeanFindById(1L)) .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); } @Test @@ -542,10 +429,7 @@ public class EnableReactiveMethodSecurityTests { Publisher findById = Flux.from(this.messageService.publisherPostAuthorizeBeanFindById(2L)) .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectNext("user") - .verifyComplete(); + StepVerifier.create(findById).expectNext("user").verifyComplete(); } @Test @@ -553,10 +437,7 @@ public class EnableReactiveMethodSecurityTests { when(this.delegate.publisherPostAuthorizeBeanFindById(2L)).thenReturn(publisherJust("anonymous")); Publisher findById = this.messageService.publisherPostAuthorizeBeanFindById(2L); - StepVerifier - .create(findById) - .expectNext("anonymous") - .verifyComplete(); + StepVerifier.create(findById).expectNext("anonymous").verifyComplete(); } @Test @@ -565,10 +446,7 @@ public class EnableReactiveMethodSecurityTests { Publisher findById = Flux.from(this.messageService.publisherPostAuthorizeBeanFindById(1L)) .subscriberContext(withUser); - StepVerifier - .create(findById) - .expectError(AccessDeniedException.class) - .verify(); + StepVerifier.create(findById).expectError(AccessDeniedException.class).verify(); } static Publisher publisher(Flux flux) { @@ -581,6 +459,7 @@ public class EnableReactiveMethodSecurityTests { @EnableReactiveMethodSecurity static class Config { + ReactiveMessageService delegate = mock(ReactiveMessageService.class); @Bean @@ -592,5 +471,7 @@ public class EnableReactiveMethodSecurityTests { public Authz authz() { return new Authz(); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java index 902af21b20..e63e57dbfb 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java @@ -68,13 +68,13 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** - * * @author Rob Winch * @author Artsiom Yudovin */ @RunWith(SpringJUnit4ClassRunner.class) @SecurityTestExecutionListeners public class GlobalMethodSecurityConfigurationTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -112,11 +112,13 @@ public class GlobalMethodSecurityConfigurationTests { @EnableGlobalMethodSecurity public static class CustomMetadataSourceConfig extends GlobalMethodSecurityConfiguration { + @Bean @Override protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() { return mock(MethodSecurityMetadataSource.class); } + } @Test @@ -125,13 +127,17 @@ public class GlobalMethodSecurityConfigurationTests { try { this.authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("foo", "bar")); - } catch(AuthenticationException e) {} + } + catch (AuthenticationException e) { + } - assertThat(this.events.getEvents()).extracting(Object::getClass).containsOnly((Class) AuthenticationFailureBadCredentialsEvent.class); + assertThat(this.events.getEvents()).extracting(Object::getClass) + .containsOnly((Class) AuthenticationFailureBadCredentialsEvent.class); } @EnableGlobalMethodSecurity(prePostEnabled = true) public static class InMemoryAuthWithGlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration { + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -142,8 +148,10 @@ public class GlobalMethodSecurityConfigurationTests { @Bean public MockEventListener listener() { - return new MockEventListener() {}; + return new MockEventListener() { + }; } + } @Test @@ -154,8 +162,7 @@ public class GlobalMethodSecurityConfigurationTests { AuthenticationTrustResolver trustResolver = this.spring.getContext().getBean(AuthenticationTrustResolver.class); when(trustResolver.isAnonymous(any())).thenReturn(true, false); - assertThatThrownBy(() -> this.service.preAuthorizeNotAnonymous()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorizeNotAnonymous()).isInstanceOf(AccessDeniedException.class); this.service.preAuthorizeNotAnonymous(); @@ -174,6 +181,7 @@ public class GlobalMethodSecurityConfigurationTests { public MethodSecurityServiceImpl service() { return new MethodSecurityServiceImpl(); } + } // SEC-2301 @@ -183,8 +191,7 @@ public class GlobalMethodSecurityConfigurationTests { this.spring.register(ExpressionHandlerHasBeanResolverSetConfig.class).autowire(); Authz authz = this.spring.getContext().getBean(Authz.class); - assertThatThrownBy(() -> this.service.preAuthorizeBean(false)) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorizeBean(false)).isInstanceOf(AccessDeniedException.class); this.service.preAuthorizeBean(true); } @@ -201,6 +208,7 @@ public class GlobalMethodSecurityConfigurationTests { public Authz authz() { return new Authz(); } + } @Test @@ -208,8 +216,7 @@ public class GlobalMethodSecurityConfigurationTests { public void methodSecuritySupportsAnnotaitonsOnInterfaceParamerNames() { this.spring.register(MethodSecurityServiceConfig.class).autowire(); - assertThatThrownBy(() -> this.service.postAnnotation("deny")) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.postAnnotation("deny")).isInstanceOf(AccessDeniedException.class); this.service.postAnnotation("grant"); // no exception @@ -222,6 +229,7 @@ public class GlobalMethodSecurityConfigurationTests { public MethodSecurityService service() { return new MethodSecurityServiceImpl(); } + } @Test @@ -234,8 +242,7 @@ public class GlobalMethodSecurityConfigurationTests { this.service.hasPermission("something"); // no exception - assertThatThrownBy(() -> this.service.hasPermission("something")) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.hasPermission("something")).isInstanceOf(AccessDeniedException.class); } @EnableGlobalMethodSecurity(prePostEnabled = true) @@ -250,6 +257,7 @@ public class GlobalMethodSecurityConfigurationTests { public MethodSecurityService service() { return new MethodSecurityServiceImpl(); } + } @Test @@ -271,6 +279,7 @@ public class GlobalMethodSecurityConfigurationTests { public PermissionEvaluator permissionEvaluator2() { return mock(PermissionEvaluator.class); } + } // SEC-2425 @@ -279,12 +288,13 @@ public class GlobalMethodSecurityConfigurationTests { public void enableGlobalMethodSecurityWorksOnSuperclass() { this.spring.register(ChildConfig.class).autowire(); - assertThatThrownBy(() -> this.service.preAuthorize()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); } @Configuration - static class ChildConfig extends ParentConfig {} + static class ChildConfig extends ParentConfig { + + } @EnableGlobalMethodSecurity(prePostEnabled = true) static class ParentConfig { @@ -293,6 +303,7 @@ public class GlobalMethodSecurityConfigurationTests { public MethodSecurityService service() { return new MethodSecurityServiceImpl(); } + } // SEC-2479 @@ -308,26 +319,29 @@ public class GlobalMethodSecurityConfigurationTests { child.refresh(); this.spring.context(child).autowire(); - assertThatThrownBy(() -> this.service.preAuthorize()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); } } } @Configuration static class Sec2479ParentConfig { + @Bean public AuthenticationManager am() { return mock(AuthenticationManager.class); } + } @EnableGlobalMethodSecurity(prePostEnabled = true) static class Sec2479ChildConfig { + @Bean public MethodSecurityService service() { return new MethodSecurityServiceImpl(); } + } @Test @@ -342,6 +356,7 @@ public class GlobalMethodSecurityConfigurationTests { @EnableGlobalMethodSecurity(prePostEnabled = true) static class Sec2815Config { + @Bean public MethodSecurityService service() { return new MethodSecurityServiceImpl(); @@ -359,6 +374,7 @@ public class GlobalMethodSecurityConfigurationTests { @Configuration static class AuthConfig extends GlobalAuthenticationConfigurerAdapter { + @Autowired DataSource dataSource; @@ -366,16 +382,19 @@ public class GlobalMethodSecurityConfigurationTests { public void init(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication(); } + } + } static class MockBeanPostProcessor implements BeanPostProcessor { + Map beforeInit = new HashMap<>(); + Map afterInit = new HashMap<>(); @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws - BeansException { + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { this.beforeInit.put(beanName, bean); return bean; } @@ -385,6 +404,7 @@ public class GlobalMethodSecurityConfigurationTests { this.afterInit.put(beanName, bean); return bean; } + } // SEC-3045 @@ -392,12 +412,13 @@ public class GlobalMethodSecurityConfigurationTests { public void globalSecurityProxiesSecurity() { this.spring.register(Sec3005Config.class).autowire(); - assertThat(this.service.getClass()).matches(c-> !Proxy.isProxyClass(c), "is not proxy class"); + assertThat(this.service.getClass()).matches(c -> !Proxy.isProxyClass(c), "is not proxy class"); } - @EnableGlobalMethodSecurity(prePostEnabled = true, mode= AdviceMode.ASPECTJ) + @EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.ASPECTJ) @EnableTransactionManagement static class Sec3005Config { + @Bean public MethodSecurityService service() { return new MethodSecurityServiceImpl(); @@ -407,25 +428,26 @@ public class GlobalMethodSecurityConfigurationTests { public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication(); } + } // - // // gh-3797 - // def preAuthorizeBeanSpel() { - // setup: - // SecurityContextHolder.getContext().setAuthentication( - // new TestingAuthenticationToken("user", "password","ROLE_USER")) - // context = new AnnotationConfigApplicationContext(PreAuthorizeBeanSpelConfig) - // BeanSpelService service = context.getBean(BeanSpelService) - // when: - // service.run(true) - // then: - // noExceptionThrown() - // when: - // service.run(false) - // then: - // thrown(AccessDeniedException) - // } + // // gh-3797 + // def preAuthorizeBeanSpel() { + // setup: + // SecurityContextHolder.getContext().setAuthentication( + // new TestingAuthenticationToken("user", "password","ROLE_USER")) + // context = new AnnotationConfigApplicationContext(PreAuthorizeBeanSpelConfig) + // BeanSpelService service = context.getBean(BeanSpelService) + // when: + // service.run(true) + // then: + // noExceptionThrown() + // when: + // service.run(false) + // then: + // thrown(AccessDeniedException) + // } // @Test @@ -433,8 +455,7 @@ public class GlobalMethodSecurityConfigurationTests { public void preAuthorizeBeanSpel() { this.spring.register(PreAuthorizeBeanSpelConfig.class).autowire(); - assertThatThrownBy(() -> this.service.preAuthorizeBean(false)) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorizeBean(false)).isInstanceOf(AccessDeniedException.class); this.service.preAuthorizeBean(true); } @@ -442,6 +463,7 @@ public class GlobalMethodSecurityConfigurationTests { @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) public static class PreAuthorizeBeanSpelConfig { + @Bean MethodSecurityService service() { return new MethodSecurityServiceImpl(); @@ -451,6 +473,7 @@ public class GlobalMethodSecurityConfigurationTests { Authz authz() { return new Authz(); } + } // gh-3394 @@ -459,14 +482,14 @@ public class GlobalMethodSecurityConfigurationTests { public void roleHierarchy() { this.spring.register(RoleHierarchyConfig.class).autowire(); - assertThatThrownBy(() -> this.service.preAuthorize()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); this.service.preAuthorizeAdmin(); } @EnableGlobalMethodSecurity(prePostEnabled = true) @Configuration public static class RoleHierarchyConfig { + @Bean MethodSecurityService service() { return new MethodSecurityServiceImpl(); @@ -478,6 +501,7 @@ public class GlobalMethodSecurityConfigurationTests { result.setHierarchy("ROLE_USER > ROLE_ADMIN"); return result; } + } @Test @@ -485,11 +509,10 @@ public class GlobalMethodSecurityConfigurationTests { public void grantedAuthorityDefaultsAutowires() { this.spring.register(CustomGrantedAuthorityConfig.class).autowire(); - CustomGrantedAuthorityConfig.CustomAuthorityService customService = this.spring.getContext().getBean( - CustomGrantedAuthorityConfig.CustomAuthorityService.class); + CustomGrantedAuthorityConfig.CustomAuthorityService customService = this.spring.getContext() + .getBean(CustomGrantedAuthorityConfig.CustomAuthorityService.class); - assertThatThrownBy(() -> this.service.preAuthorize()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); customService.customPrefixRoleUser(); // no exception @@ -514,9 +537,13 @@ public class GlobalMethodSecurityConfigurationTests { } static class CustomAuthorityService { + @PreAuthorize("hasRole('ROLE:USER')") - public void customPrefixRoleUser() {} + public void customPrefixRoleUser() { + } + } + } @Test @@ -527,8 +554,7 @@ public class GlobalMethodSecurityConfigurationTests { EmptyRolePrefixGrantedAuthorityConfig.CustomAuthorityService customService = this.spring.getContext() .getBean(EmptyRolePrefixGrantedAuthorityConfig.CustomAuthorityService.class); - assertThatThrownBy(() -> this.service.securedUser()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.securedUser()).isInstanceOf(AccessDeniedException.class); customService.emptyPrefixRoleUser(); // no exception @@ -536,6 +562,7 @@ public class GlobalMethodSecurityConfigurationTests { @EnableGlobalMethodSecurity(securedEnabled = true) static class EmptyRolePrefixGrantedAuthorityConfig { + @Bean public GrantedAuthorityDefaults ga() { return new GrantedAuthorityDefaults(""); @@ -552,18 +579,22 @@ public class GlobalMethodSecurityConfigurationTests { } static class CustomAuthorityService { + @Secured("USER") - public void emptyPrefixRoleUser() {} + public void emptyPrefixRoleUser() { + } + } + } @Test public void methodSecurityInterceptorUsesMetadataSourceBeanWhenProxyingDisabled() { this.spring.register(CustomMetadataSourceBeanProxyEnabledConfig.class).autowire(); - MethodSecurityInterceptor methodInterceptor = - (MethodSecurityInterceptor) this.spring.getContext().getBean(MethodInterceptor.class); - MethodSecurityMetadataSource methodSecurityMetadataSource = - this.spring.getContext().getBean(MethodSecurityMetadataSource.class); + MethodSecurityInterceptor methodInterceptor = (MethodSecurityInterceptor) this.spring.getContext() + .getBean(MethodInterceptor.class); + MethodSecurityMetadataSource methodSecurityMetadataSource = this.spring.getContext() + .getBean(MethodSecurityMetadataSource.class); assertThat(methodInterceptor.getSecurityMetadataSource()).isSameAs(methodSecurityMetadataSource); } @@ -571,5 +602,7 @@ public class GlobalMethodSecurityConfigurationTests { @EnableGlobalMethodSecurity(prePostEnabled = true) @Configuration public static class CustomMetadataSourceBeanProxyEnabledConfig extends GlobalMethodSecurityConfiguration { + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.java index b558c9911d..e3d4baf3cb 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.java @@ -29,6 +29,7 @@ import javax.annotation.security.PermitAll; * @author Rob Winch */ public interface MethodSecurityService { + @PreAuthorize("denyAll") String preAuthorize(); @@ -67,4 +68,5 @@ public interface MethodSecurityService { @PostAuthorize("#o?.contains('grant')") String postAnnotation(@P("o") String object); + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceConfig.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceConfig.java index 0a5fd815eb..664919232b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceConfig.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceConfig.java @@ -21,8 +21,10 @@ import org.springframework.context.annotation.Bean; * @author Josh Cummings */ public class MethodSecurityServiceConfig { + @Bean MethodSecurityService service() { return new MethodSecurityServiceImpl(); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.java index 1ce3a60f3a..94a05216bc 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.java @@ -23,6 +23,7 @@ import org.springframework.security.core.context.SecurityContextHolder; * @author Rob Winch */ public class MethodSecurityServiceImpl implements MethodSecurityService { + @Override public String preAuthorize() { return null; diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityExpressionHandlerTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityExpressionHandlerTests.java index 74cf91ab87..f904f0df58 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityExpressionHandlerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityExpressionHandlerTests.java @@ -35,7 +35,6 @@ import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; /** - * * @author Rob Winch * @author Josh Cummings */ @@ -54,11 +53,9 @@ public class NamespaceGlobalMethodSecurityExpressionHandlerTests { public void methodSecurityWhenUsingCustomPermissionEvaluatorThenPreAuthorizesAccordingly() { this.spring.register(CustomAccessDecisionManagerConfig.class, MethodSecurityServiceConfig.class).autowire(); - assertThatCode(() -> this.service.hasPermission("granted")) - .doesNotThrowAnyException(); + assertThatCode(() -> this.service.hasPermission("granted")).doesNotThrowAnyException(); - assertThatThrownBy(() -> this.service.hasPermission("denied")) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.hasPermission("denied")).isInstanceOf(AccessDeniedException.class); } @Test @@ -66,30 +63,33 @@ public class NamespaceGlobalMethodSecurityExpressionHandlerTests { public void methodSecurityWhenUsingCustomPermissionEvaluatorThenPostAuthorizesAccordingly() { this.spring.register(CustomAccessDecisionManagerConfig.class, MethodSecurityServiceConfig.class).autowire(); - assertThatCode(() -> this.service.postHasPermission("granted")) - .doesNotThrowAnyException(); + assertThatCode(() -> this.service.postHasPermission("granted")).doesNotThrowAnyException(); - assertThatThrownBy(() -> this.service.postHasPermission("denied")) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.postHasPermission("denied")).isInstanceOf(AccessDeniedException.class); } @EnableGlobalMethodSecurity(prePostEnabled = true) public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration { + @Override protected MethodSecurityExpressionHandler createExpressionHandler() { DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); expressionHandler.setPermissionEvaluator(new PermissionEvaluator() { - public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) { + public boolean hasPermission(Authentication authentication, Object targetDomainObject, + Object permission) { return "granted".equals(targetDomainObject); } - public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) { + public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, + Object permission) { throw new UnsupportedOperationException(); } }); return expressionHandler; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.java index 1174a77d34..7655f8c422 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.java @@ -60,7 +60,6 @@ import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; /** - * * @author Rob Winch * @author Josh Cummings */ @@ -81,11 +80,9 @@ public class NamespaceGlobalMethodSecurityTests { public void methodSecurityWhenCustomAccessDecisionManagerThenAuthorizes() { this.spring.register(CustomAccessDecisionManagerConfig.class, MethodSecurityServiceConfig.class).autowire(); - assertThatThrownBy(() -> this.service.preAuthorize()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); - assertThatThrownBy(() -> this.service.secured()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.secured()).isInstanceOf(AccessDeniedException.class); } @@ -98,16 +95,22 @@ public class NamespaceGlobalMethodSecurityTests { } public static class DenyAllAccessDecisionManager implements AccessDecisionManager { - public void decide(Authentication authentication, Object object, Collection configAttributes) { + + public void decide(Authentication authentication, Object object, + Collection configAttributes) { throw new AccessDeniedException("Always Denied"); } + public boolean supports(ConfigAttribute attribute) { return true; } + public boolean supports(Class clazz) { return true; } + } + } // --- after-invocation-provider @@ -117,13 +120,11 @@ public class NamespaceGlobalMethodSecurityTests { public void methodSecurityWhenCustomAfterInvocationManagerThenAuthorizes() { this.spring.register(CustomAfterInvocationManagerConfig.class, MethodSecurityServiceConfig.class).autowire(); - assertThatThrownBy(() -> this.service.preAuthorizePermitAll()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorizePermitAll()).isInstanceOf(AccessDeniedException.class); } @EnableGlobalMethodSecurity(prePostEnabled = true) - public static class CustomAfterInvocationManagerConfig - extends GlobalMethodSecurityConfiguration { + public static class CustomAfterInvocationManagerConfig extends GlobalMethodSecurityConfiguration { @Override protected AfterInvocationManager afterInvocationManager() { @@ -131,10 +132,9 @@ public class NamespaceGlobalMethodSecurityTests { } public static class AfterInvocationManagerStub implements AfterInvocationManager { - public Object decide(Authentication authentication, - Object object, - Collection attributes, - Object returnedObject) throws AccessDeniedException { + + public Object decide(Authentication authentication, Object object, Collection attributes, + Object returnedObject) throws AccessDeniedException { throw new AccessDeniedException("custom AfterInvocationManager"); } @@ -142,10 +142,13 @@ public class NamespaceGlobalMethodSecurityTests { public boolean supports(ConfigAttribute attribute) { return true; } + public boolean supports(Class clazz) { return true; } + } + } // --- authentication-manager-ref --- @@ -155,8 +158,7 @@ public class NamespaceGlobalMethodSecurityTests { public void methodSecurityWhenCustomAuthenticationManagerThenAuthorizes() { this.spring.register(CustomAuthenticationConfig.class, MethodSecurityServiceConfig.class).autowire(); - assertThatThrownBy(() -> this.service.preAuthorize()) - .isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(UnsupportedOperationException.class); } @EnableGlobalMethodSecurity(prePostEnabled = true) @@ -175,6 +177,7 @@ public class NamespaceGlobalMethodSecurityTests { throw new UnsupportedOperationException(); }; } + } // --- jsr250-annotations --- @@ -184,17 +187,13 @@ public class NamespaceGlobalMethodSecurityTests { public void methodSecurityWhenJsr250EnabledThenAuthorizes() { this.spring.register(Jsr250Config.class, MethodSecurityServiceConfig.class).autowire(); - assertThatCode(() -> this.service.preAuthorize()) - .doesNotThrowAnyException(); + assertThatCode(() -> this.service.preAuthorize()).doesNotThrowAnyException(); - assertThatCode(() -> this.service.secured()) - .doesNotThrowAnyException(); + assertThatCode(() -> this.service.secured()).doesNotThrowAnyException(); - assertThatThrownBy(() -> this.service.jsr250()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(AccessDeniedException.class); - assertThatCode(() -> this.service.jsr250PermitAll()) - .doesNotThrowAnyException(); + assertThatCode(() -> this.service.jsr250PermitAll()).doesNotThrowAnyException(); } @@ -209,16 +208,14 @@ public class NamespaceGlobalMethodSecurityTests { @Test @WithMockUser public void methodSecurityWhenCustomMethodSecurityMetadataSourceThenAuthorizes() { - this.spring.register(CustomMethodSecurityMetadataSourceConfig.class, MethodSecurityServiceConfig.class).autowire(); + this.spring.register(CustomMethodSecurityMetadataSourceConfig.class, MethodSecurityServiceConfig.class) + .autowire(); - assertThatThrownBy(() -> this.service.preAuthorize()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); - assertThatThrownBy(() -> this.service.secured()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.secured()).isInstanceOf(AccessDeniedException.class); - assertThatThrownBy(() -> this.service.jsr250()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(AccessDeniedException.class); } @EnableGlobalMethodSecurity @@ -228,16 +225,18 @@ public class NamespaceGlobalMethodSecurityTests { protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() { return new AbstractMethodSecurityMetadataSource() { public Collection getAttributes(Method method, Class targetClass) { - // require ROLE_NOBODY for any method on MethodSecurityService interface - return MethodSecurityService.class.isAssignableFrom(targetClass) ? - Arrays.asList(new SecurityConfig("ROLE_NOBODY")) : - Collections.emptyList(); + // require ROLE_NOBODY for any method on MethodSecurityService + // interface + return MethodSecurityService.class.isAssignableFrom(targetClass) + ? Arrays.asList(new SecurityConfig("ROLE_NOBODY")) : Collections.emptyList(); } + public Collection getAllConfigAttributes() { return null; } }; } + } // --- mode --- @@ -247,10 +246,13 @@ public class NamespaceGlobalMethodSecurityTests { public void contextRefreshWhenUsingAspectJThenAutowire() throws Exception { this.spring.register(AspectJModeConfig.class, MethodSecurityServiceConfig.class).autowire(); - assertThat(this.spring.getContext().getBean(Class.forName("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"))).isNotNull(); + assertThat(this.spring.getContext().getBean( + Class.forName("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"))) + .isNotNull(); assertThat(this.spring.getContext().getBean(AspectJMethodSecurityInterceptor.class)).isNotNull(); - //TODO diagnose why aspectj isn't weaving method security advice around MethodSecurityServiceImpl + // TODO diagnose why aspectj isn't weaving method security advice around + // MethodSecurityServiceImpl } @EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, securedEnabled = true) @@ -260,48 +262,51 @@ public class NamespaceGlobalMethodSecurityTests { @Test public void contextRefreshWhenUsingAspectJAndCustomGlobalMethodSecurityConfigurationThenAutowire() - throws Exception { + throws Exception { this.spring.register(AspectJModeExtendsGMSCConfig.class).autowire(); - assertThat(this.spring.getContext().getBean(Class.forName("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"))).isNotNull(); + assertThat(this.spring.getContext().getBean( + Class.forName("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"))) + .isNotNull(); assertThat(this.spring.getContext().getBean(AspectJMethodSecurityInterceptor.class)).isNotNull(); } @EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, securedEnabled = true) public static class AspectJModeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration { + } // --- order --- - private static class AdvisorOrderConfig - implements ImportBeanDefinitionRegistrar { + private static class AdvisorOrderConfig implements ImportBeanDefinitionRegistrar { private static class ExceptingInterceptor implements MethodInterceptor { + @Override public Object invoke(MethodInvocation invocation) { throw new UnsupportedOperationException("Deny All"); } + } @Override - public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { - BeanDefinitionBuilder advice = BeanDefinitionBuilder - .rootBeanDefinition(ExceptingInterceptor.class); - registry.registerBeanDefinition("exceptingInterceptor", - advice.getBeanDefinition()); + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, + BeanDefinitionRegistry registry) { + BeanDefinitionBuilder advice = BeanDefinitionBuilder.rootBeanDefinition(ExceptingInterceptor.class); + registry.registerBeanDefinition("exceptingInterceptor", advice.getBeanDefinition()); BeanDefinitionBuilder advisor = BeanDefinitionBuilder - .rootBeanDefinition(MethodSecurityMetadataSourceAdvisor.class); + .rootBeanDefinition(MethodSecurityMetadataSourceAdvisor.class); advisor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); advisor.addConstructorArgValue("exceptingInterceptor"); advisor.addConstructorArgReference("methodSecurityMetadataSource"); advisor.addConstructorArgValue("methodSecurityMetadataSource"); advisor.addPropertyValue("order", 0); - registry.registerBeanDefinition("exceptingAdvisor", - advisor.getBeanDefinition()); + registry.registerBeanDefinition("exceptingAdvisor", advisor.getBeanDefinition()); } + } @Test @@ -309,13 +314,10 @@ public class NamespaceGlobalMethodSecurityTests { public void methodSecurityWhenOrderSpecifiedThenConfigured() { this.spring.register(CustomOrderConfig.class, MethodSecurityServiceConfig.class).autowire(); - assertThat(this.spring.getContext() - .getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class) - .getOrder()) - .isEqualTo(-135); + assertThat(this.spring.getContext().getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class) + .getOrder()).isEqualTo(-135); - assertThatThrownBy(() -> this.service.jsr250()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(AccessDeniedException.class); } @EnableGlobalMethodSecurity(order = -135, jsr250Enabled = true) @@ -329,37 +331,34 @@ public class NamespaceGlobalMethodSecurityTests { public void methodSecurityWhenOrderUnspecifiedThenConfiguredToLowestPrecedence() { this.spring.register(DefaultOrderConfig.class, MethodSecurityServiceConfig.class).autowire(); - assertThat(this.spring.getContext() - .getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class) - .getOrder()) - .isEqualTo(Ordered.LOWEST_PRECEDENCE); + assertThat(this.spring.getContext().getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class) + .getOrder()).isEqualTo(Ordered.LOWEST_PRECEDENCE); - assertThatThrownBy(() -> this.service.jsr250()) - .isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(UnsupportedOperationException.class); } @EnableGlobalMethodSecurity(jsr250Enabled = true) @Import(AdvisorOrderConfig.class) public static class DefaultOrderConfig { + } @Test @WithMockUser public void methodSecurityWhenOrderUnspecifiedAndCustomGlobalMethodSecurityConfigurationThenConfiguredToLowestPrecedence() { - this.spring.register(DefaultOrderExtendsMethodSecurityConfig.class, MethodSecurityServiceConfig.class).autowire(); + this.spring.register(DefaultOrderExtendsMethodSecurityConfig.class, MethodSecurityServiceConfig.class) + .autowire(); - assertThat(this.spring.getContext() - .getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class) - .getOrder()) - .isEqualTo(Ordered.LOWEST_PRECEDENCE); + assertThat(this.spring.getContext().getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class) + .getOrder()).isEqualTo(Ordered.LOWEST_PRECEDENCE); - assertThatThrownBy(() -> this.service.jsr250()) - .isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(UnsupportedOperationException.class); } @EnableGlobalMethodSecurity(jsr250Enabled = true) @Import(AdvisorOrderConfig.class) public static class DefaultOrderExtendsMethodSecurityConfig extends GlobalMethodSecurityConfiguration { + } // --- pre-post-annotations --- @@ -369,18 +368,16 @@ public class NamespaceGlobalMethodSecurityTests { public void methodSecurityWhenPrePostEnabledThenPreAuthorizes() { this.spring.register(PreAuthorizeConfig.class, MethodSecurityServiceConfig.class).autowire(); - assertThatCode(() -> this.service.secured()) - .doesNotThrowAnyException(); + assertThatCode(() -> this.service.secured()).doesNotThrowAnyException(); - assertThatCode(() -> this.service.jsr250()) - .doesNotThrowAnyException(); + assertThatCode(() -> this.service.jsr250()).doesNotThrowAnyException(); - assertThatThrownBy(() -> this.service.preAuthorize()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); } @EnableGlobalMethodSecurity(prePostEnabled = true) public static class PreAuthorizeConfig { + } @Test @@ -388,18 +385,16 @@ public class NamespaceGlobalMethodSecurityTests { public void methodSecurityWhenPrePostEnabledAndCustomGlobalMethodSecurityConfigurationThenPreAuthorizes() { this.spring.register(PreAuthorizeExtendsGMSCConfig.class, MethodSecurityServiceConfig.class).autowire(); - assertThatCode(() -> this.service.secured()) - .doesNotThrowAnyException(); + assertThatCode(() -> this.service.secured()).doesNotThrowAnyException(); - assertThatCode(() -> this.service.jsr250()) - .doesNotThrowAnyException(); + assertThatCode(() -> this.service.jsr250()).doesNotThrowAnyException(); - assertThatThrownBy(() -> this.service.preAuthorize()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); } @EnableGlobalMethodSecurity(prePostEnabled = true) public static class PreAuthorizeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration { + } // --- proxy-target-class --- @@ -410,15 +405,14 @@ public class NamespaceGlobalMethodSecurityTests { this.spring.register(ProxyTargetClassConfig.class, MethodSecurityServiceConfig.class).autowire(); // make sure service was actually proxied - assertThat(this.service.getClass().getInterfaces()) - .doesNotContain(MethodSecurityService.class); + assertThat(this.service.getClass().getInterfaces()).doesNotContain(MethodSecurityService.class); - assertThatThrownBy(() -> this.service.preAuthorize()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); } @EnableGlobalMethodSecurity(proxyTargetClass = true, prePostEnabled = true) public static class ProxyTargetClassConfig { + } @Test @@ -426,15 +420,14 @@ public class NamespaceGlobalMethodSecurityTests { public void methodSecurityWhenDefaultProxyThenWiresToInterface() { this.spring.register(DefaultProxyConfig.class, MethodSecurityServiceConfig.class).autowire(); - assertThat(this.service.getClass().getInterfaces()) - .contains(MethodSecurityService.class); + assertThat(this.service.getClass().getInterfaces()).contains(MethodSecurityService.class); - assertThatThrownBy(() -> this.service.preAuthorize()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); } @EnableGlobalMethodSecurity(prePostEnabled = true) public static class DefaultProxyConfig { + } // --- run-as-manager-ref --- @@ -445,7 +438,7 @@ public class NamespaceGlobalMethodSecurityTests { this.spring.register(CustomRunAsManagerConfig.class, MethodSecurityServiceConfig.class).autowire(); assertThat(service.runAs().getAuthorities()) - .anyMatch(authority -> "ROLE_RUN_AS_SUPER".equals(authority.getAuthority())); + .anyMatch(authority -> "ROLE_RUN_AS_SUPER".equals(authority.getAuthority())); } @EnableGlobalMethodSecurity(securedEnabled = true) @@ -457,6 +450,7 @@ public class NamespaceGlobalMethodSecurityTests { runAsManager.setKey("some key"); return runAsManager; } + } // --- secured-annotation --- @@ -466,21 +460,18 @@ public class NamespaceGlobalMethodSecurityTests { public void methodSecurityWhenSecuredEnabledThenSecures() { this.spring.register(SecuredConfig.class, MethodSecurityServiceConfig.class).autowire(); - assertThatThrownBy(() -> this.service.secured()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.secured()).isInstanceOf(AccessDeniedException.class); - assertThatCode(() -> this.service.securedUser()) - .doesNotThrowAnyException(); + assertThatCode(() -> this.service.securedUser()).doesNotThrowAnyException(); - assertThatCode(() -> this.service.preAuthorize()) - .doesNotThrowAnyException(); + assertThatCode(() -> this.service.preAuthorize()).doesNotThrowAnyException(); - assertThatCode(() -> this.service.jsr250()) - .doesNotThrowAnyException(); + assertThatCode(() -> this.service.jsr250()).doesNotThrowAnyException(); } @EnableGlobalMethodSecurity(securedEnabled = true) public static class SecuredConfig { + } // --- unsorted --- @@ -488,14 +479,13 @@ public class NamespaceGlobalMethodSecurityTests { @Test @WithMockUser public void methodSecurityWhenMissingEnableAnnotationThenShowsHelpfulError() { - assertThatThrownBy(() -> - this.spring.register(ExtendsNoEnableAnntotationConfig.class).autowire()) - .hasStackTraceContaining(EnableGlobalMethodSecurity.class.getName() + " is required"); + assertThatThrownBy(() -> this.spring.register(ExtendsNoEnableAnntotationConfig.class).autowire()) + .hasStackTraceContaining(EnableGlobalMethodSecurity.class.getName() + " is required"); } @Configuration - public static class ExtendsNoEnableAnntotationConfig - extends GlobalMethodSecurityConfiguration { + public static class ExtendsNoEnableAnntotationConfig extends GlobalMethodSecurityConfiguration { + } @Test @@ -503,18 +493,17 @@ public class NamespaceGlobalMethodSecurityTests { public void methodSecurityWhenImportingGlobalMethodSecurityConfigurationSubclassThenAuthorizes() { this.spring.register(ImportSubclassGMSCConfig.class, MethodSecurityServiceConfig.class).autowire(); - assertThatCode(() -> this.service.secured()) - .doesNotThrowAnyException(); + assertThatCode(() -> this.service.secured()).doesNotThrowAnyException(); - assertThatCode(() -> this.service.jsr250()) - .doesNotThrowAnyException(); + assertThatCode(() -> this.service.jsr250()).doesNotThrowAnyException(); - assertThatThrownBy(() -> this.service.preAuthorize()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); } @Configuration @Import(PreAuthorizeExtendsGMSCConfig.class) public static class ImportSubclassGMSCConfig { + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMessageService.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMessageService.java index d4bc9d45c9..636db9b6ff 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMessageService.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMessageService.java @@ -20,23 +20,37 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; public interface ReactiveMessageService { + String notPublisherPreAuthorizeFindById(long id); Mono monoFindById(long id); + Mono monoPreAuthorizeHasRoleFindById(long id); + Mono monoPostAuthorizeFindById(long id); + Mono monoPreAuthorizeBeanFindById(long id); + Mono monoPostAuthorizeBeanFindById(long id); Flux fluxFindById(long id); + Flux fluxPreAuthorizeHasRoleFindById(long id); + Flux fluxPostAuthorizeFindById(long id); + Flux fluxPreAuthorizeBeanFindById(long id); + Flux fluxPostAuthorizeBeanFindById(long id); Publisher publisherFindById(long id); + Publisher publisherPreAuthorizeHasRoleFindById(long id); + Publisher publisherPostAuthorizeFindById(long id); + Publisher publisherPreAuthorizeBeanFindById(long id); + Publisher publisherPostAuthorizeBeanFindById(long id); + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfigurationTests.java index 9df29cd18f..8fe7565b04 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfigurationTests.java @@ -46,14 +46,13 @@ public class ReactiveMethodSecurityConfigurationTests { public void rolePrefixWithGrantedAuthorityDefaults() throws NoSuchMethodException { this.spring.register(WithRolePrefixConfiguration.class).autowire(); - TestingAuthenticationToken authentication = new TestingAuthenticationToken( - "principal", "credential", "CUSTOM_ABC"); + TestingAuthenticationToken authentication = new TestingAuthenticationToken("principal", "credential", + "CUSTOM_ABC"); MockMethodInvocation methodInvocation = new MockMethodInvocation(new Foo(), Foo.class, "bar", String.class); - EvaluationContext context = this.methodSecurityExpressionHandler - .createEvaluationContext(authentication, methodInvocation); - SecurityExpressionRoot root = (SecurityExpressionRoot) context.getRootObject() - .getValue(); + EvaluationContext context = this.methodSecurityExpressionHandler.createEvaluationContext(authentication, + methodInvocation); + SecurityExpressionRoot root = (SecurityExpressionRoot) context.getRootObject().getValue(); assertThat(root.hasRole("ROLE_ABC")).isFalse(); assertThat(root.hasRole("ROLE_CUSTOM_ABC")).isFalse(); @@ -65,14 +64,13 @@ public class ReactiveMethodSecurityConfigurationTests { public void rolePrefixWithDefaultConfig() throws NoSuchMethodException { this.spring.register(ReactiveMethodSecurityConfiguration.class).autowire(); - TestingAuthenticationToken authentication = new TestingAuthenticationToken( - "principal", "credential", "ROLE_ABC"); + TestingAuthenticationToken authentication = new TestingAuthenticationToken("principal", "credential", + "ROLE_ABC"); MockMethodInvocation methodInvocation = new MockMethodInvocation(new Foo(), Foo.class, "bar", String.class); - EvaluationContext context = this.methodSecurityExpressionHandler - .createEvaluationContext(authentication, methodInvocation); - SecurityExpressionRoot root = (SecurityExpressionRoot) context.getRootObject() - .getValue(); + EvaluationContext context = this.methodSecurityExpressionHandler.createEvaluationContext(authentication, + methodInvocation); + SecurityExpressionRoot root = (SecurityExpressionRoot) context.getRootObject().getValue(); assertThat(root.hasRole("ROLE_ABC")).isTrue(); assertThat(root.hasRole("ABC")).isTrue(); @@ -81,24 +79,25 @@ public class ReactiveMethodSecurityConfigurationTests { @Configuration @EnableReactiveMethodSecurity // this imports ReactiveMethodSecurityConfiguration static class WithRolePrefixConfiguration { + @Bean GrantedAuthorityDefaults grantedAuthorityDefaults() { return new GrantedAuthorityDefaults("CUSTOM_"); } + } @Test public void rolePrefixWithGrantedAuthorityDefaultsAndSubclassWithProxyingEnabled() throws NoSuchMethodException { this.spring.register(SubclassConfig.class).autowire(); - TestingAuthenticationToken authentication = new TestingAuthenticationToken( - "principal", "credential", "ROLE_ABC"); + TestingAuthenticationToken authentication = new TestingAuthenticationToken("principal", "credential", + "ROLE_ABC"); MockMethodInvocation methodInvocation = new MockMethodInvocation(new Foo(), Foo.class, "bar", String.class); - EvaluationContext context = this.methodSecurityExpressionHandler - .createEvaluationContext(authentication, methodInvocation); - SecurityExpressionRoot root = (SecurityExpressionRoot) context.getRootObject() - .getValue(); + EvaluationContext context = this.methodSecurityExpressionHandler.createEvaluationContext(authentication, + methodInvocation); + SecurityExpressionRoot root = (SecurityExpressionRoot) context.getRootObject().getValue(); assertThat(root.hasRole("ROLE_ABC")).isTrue(); assertThat(root.hasRole("ABC")).isTrue(); @@ -106,10 +105,14 @@ public class ReactiveMethodSecurityConfigurationTests { @Configuration static class SubclassConfig extends ReactiveMethodSecurityConfiguration { + } private static class Foo { - public void bar(String param){ + + public void bar(String param) { } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.java index 13ffa15645..1f7031541d 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.java @@ -42,6 +42,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * */ public class SampleEnableGlobalMethodSecurityTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -50,8 +51,8 @@ public class SampleEnableGlobalMethodSecurityTests { @Before public void setup() { - SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken("user", "password", "ROLE_USER")); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")); } @Test @@ -61,12 +62,12 @@ public class SampleEnableGlobalMethodSecurityTests { assertThat(this.methodSecurityService.secured()).isNull(); assertThat(this.methodSecurityService.jsr250()).isNull(); - assertThatThrownBy(() -> this.methodSecurityService.preAuthorize()) - .isInstanceOf(AccessDeniedException.class); + assertThatThrownBy(() -> this.methodSecurityService.preAuthorize()).isInstanceOf(AccessDeniedException.class); } - @EnableGlobalMethodSecurity(prePostEnabled=true) + @EnableGlobalMethodSecurity(prePostEnabled = true) static class SampleWebSecurityConfig { + @Bean public MethodSecurityService methodSecurityService() { return new MethodSecurityServiceImpl(); @@ -81,8 +82,8 @@ public class SampleEnableGlobalMethodSecurityTests { .withUser("admin").password("password").roles("USER", "ADMIN"); // @formatter:on } - } + } @Test public void customPermissionHandler() { @@ -91,12 +92,12 @@ public class SampleEnableGlobalMethodSecurityTests { assertThat(this.methodSecurityService.hasPermission("allowed")).isNull(); assertThatThrownBy(() -> this.methodSecurityService.hasPermission("denied")) - .isInstanceOf(AccessDeniedException.class); + .isInstanceOf(AccessDeniedException.class); } - - @EnableGlobalMethodSecurity(prePostEnabled=true) + @EnableGlobalMethodSecurity(prePostEnabled = true) public static class CustomPermissionEvaluatorWebSecurityConfig extends GlobalMethodSecurityConfiguration { + @Bean public MethodSecurityService methodSecurityService() { return new MethodSecurityServiceImpl(); @@ -118,18 +119,20 @@ public class SampleEnableGlobalMethodSecurityTests { .withUser("admin").password("password").roles("USER", "ADMIN"); // @formatter:on } + } static class CustomPermissionEvaluator implements PermissionEvaluator { - public boolean hasPermission(Authentication authentication, - Object targetDomainObject, Object permission) { + + public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) { return !"denied".equals(targetDomainObject); } - public boolean hasPermission(Authentication authentication, - Serializable targetId, String targetType, Object permission) { + public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, + Object permission) { return !"denied".equals(targetId); } } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java b/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java index 53441757f8..c8d3563122 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java @@ -77,21 +77,23 @@ public class Sec2758Tests { this.spring.register(SecurityConfig.class).autowire(); - assertThatCode(() -> service.doJsr250()) - .doesNotThrowAnyException(); + assertThatCode(() -> service.doJsr250()).doesNotThrowAnyException(); - assertThatCode(() -> service.doPreAuthorize()) - .doesNotThrowAnyException(); + assertThatCode(() -> service.doPreAuthorize()).doesNotThrowAnyException(); } @EnableWebSecurity - @EnableGlobalMethodSecurity(prePostEnabled=true, jsr250Enabled = true) + @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true) static class SecurityConfig extends WebSecurityConfigurerAdapter { @RestController static class RootController { + @GetMapping("/") - public String ok() { return "ok"; } + public String ok() { + return "ok"; + } + } @Override @@ -116,11 +118,15 @@ public class Sec2758Tests { } static class Service { + @PreAuthorize("hasRole('CUSTOM')") - public void doPreAuthorize() {} + public void doPreAuthorize() { + } @RolesAllowed("CUSTOM") - public void doJsr250() {} + public void doJsr250() { + } + } static class DefaultRolesPrefixPostProcessor implements BeanPostProcessor, PriorityOrdered { @@ -148,5 +154,7 @@ public class Sec2758Tests { public int getOrder() { return PriorityOrdered.HIGHEST_PRECEDENCE; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractConfiguredSecurityBuilderTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractConfiguredSecurityBuilderTests.java index 4f6fa4a613..b35dbf989c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractConfiguredSecurityBuilderTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractConfiguredSecurityBuilderTests.java @@ -34,6 +34,7 @@ import static org.mockito.Mockito.verify; * @author Joe Grandja */ public class AbstractConfiguredSecurityBuilderTests { + private TestConfiguredSecurityBuilder builder; @Before @@ -80,7 +81,8 @@ public class AbstractConfiguredSecurityBuilderTests { @Test(expected = IllegalStateException.class) public void getConfigurerWhenMultipleConfigurersThenThrowIllegalStateException() throws Exception { - TestConfiguredSecurityBuilder builder = new TestConfiguredSecurityBuilder(mock(ObjectPostProcessor.class), true); + TestConfiguredSecurityBuilder builder = new TestConfiguredSecurityBuilder(mock(ObjectPostProcessor.class), + true); builder.apply(new DelegateSecurityConfigurer()); builder.apply(new DelegateSecurityConfigurer()); builder.getConfigurer(DelegateSecurityConfigurer.class); @@ -88,7 +90,8 @@ public class AbstractConfiguredSecurityBuilderTests { @Test(expected = IllegalStateException.class) public void removeConfigurerWhenMultipleConfigurersThenThrowIllegalStateException() throws Exception { - TestConfiguredSecurityBuilder builder = new TestConfiguredSecurityBuilder(mock(ObjectPostProcessor.class), true); + TestConfiguredSecurityBuilder builder = new TestConfiguredSecurityBuilder(mock(ObjectPostProcessor.class), + true); builder.apply(new DelegateSecurityConfigurer()); builder.apply(new DelegateSecurityConfigurer()); builder.removeConfigurer(DelegateSecurityConfigurer.class); @@ -98,10 +101,12 @@ public class AbstractConfiguredSecurityBuilderTests { public void removeConfigurersWhenMultipleConfigurersThenConfigurersRemoved() throws Exception { DelegateSecurityConfigurer configurer1 = new DelegateSecurityConfigurer(); DelegateSecurityConfigurer configurer2 = new DelegateSecurityConfigurer(); - TestConfiguredSecurityBuilder builder = new TestConfiguredSecurityBuilder(mock(ObjectPostProcessor.class), true); + TestConfiguredSecurityBuilder builder = new TestConfiguredSecurityBuilder(mock(ObjectPostProcessor.class), + true); builder.apply(configurer1); builder.apply(configurer2); - List removedConfigurers = builder.removeConfigurers(DelegateSecurityConfigurer.class); + List removedConfigurers = builder + .removeConfigurers(DelegateSecurityConfigurer.class); assertThat(removedConfigurers).hasSize(2); assertThat(removedConfigurers).containsExactly(configurer1, configurer2); assertThat(builder.getConfigurers(DelegateSecurityConfigurer.class)).isEmpty(); @@ -111,7 +116,8 @@ public class AbstractConfiguredSecurityBuilderTests { public void getConfigurersWhenMultipleConfigurersThenConfigurersReturned() throws Exception { DelegateSecurityConfigurer configurer1 = new DelegateSecurityConfigurer(); DelegateSecurityConfigurer configurer2 = new DelegateSecurityConfigurer(); - TestConfiguredSecurityBuilder builder = new TestConfiguredSecurityBuilder(mock(ObjectPostProcessor.class), true); + TestConfiguredSecurityBuilder builder = new TestConfiguredSecurityBuilder(mock(ObjectPostProcessor.class), + true); builder.apply(configurer1); builder.apply(configurer2); List configurers = builder.getConfigurers(DelegateSecurityConfigurer.class); @@ -120,29 +126,39 @@ public class AbstractConfiguredSecurityBuilderTests { assertThat(builder.getConfigurers(DelegateSecurityConfigurer.class)).hasSize(2); } - private static class DelegateSecurityConfigurer extends SecurityConfigurerAdapter { + private static class DelegateSecurityConfigurer + extends SecurityConfigurerAdapter { + private static SecurityConfigurer CONFIGURER; @Override public void init(TestConfiguredSecurityBuilder builder) throws Exception { builder.apply(CONFIGURER); } + } - private static class TestSecurityConfigurer extends SecurityConfigurerAdapter { } + private static class TestSecurityConfigurer + extends SecurityConfigurerAdapter { - private static class TestConfiguredSecurityBuilder extends AbstractConfiguredSecurityBuilder { + } + + private static class TestConfiguredSecurityBuilder + extends AbstractConfiguredSecurityBuilder { private TestConfiguredSecurityBuilder(ObjectPostProcessor objectPostProcessor) { super(objectPostProcessor); } - private TestConfiguredSecurityBuilder(ObjectPostProcessor objectPostProcessor, boolean allowConfigurersOfSameType) { + private TestConfiguredSecurityBuilder(ObjectPostProcessor objectPostProcessor, + boolean allowConfigurersOfSameType) { super(objectPostProcessor, allowConfigurersOfSameType); } public Object performBuild() { return "success"; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java index b2694200b0..bb52d221ec 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java @@ -30,10 +30,11 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon * * @author Ankur Pathak */ -public class AbstractRequestMatcherRegistryAnyMatcherTests{ +public class AbstractRequestMatcherRegistryAnyMatcherTests { @EnableWebSecurity static class AntMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -43,15 +44,17 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests{ // @formatter:on } + } @Test(expected = BeanCreationException.class) - public void antMatchersCanNotWorkAfterAnyRequest(){ + public void antMatchersCanNotWorkAfterAnyRequest() { loadConfig(AntMatchersAfterAnyRequestConfig.class); } @EnableWebSecurity static class MvcMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -61,6 +64,7 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests{ // @formatter:on } + } @Test(expected = BeanCreationException.class) @@ -70,6 +74,7 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests{ @EnableWebSecurity static class RegexMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -79,6 +84,7 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests{ // @formatter:on } + } @Test(expected = BeanCreationException.class) @@ -88,6 +94,7 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests{ @EnableWebSecurity static class AnyRequestAfterItselfConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -97,6 +104,7 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests{ // @formatter:on } + } @Test(expected = BeanCreationException.class) @@ -106,6 +114,7 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests{ @EnableWebSecurity static class RequestMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -115,6 +124,7 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests{ // @formatter:on } + } @Test(expected = BeanCreationException.class) @@ -129,4 +139,5 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests{ context.setServletContext(new MockServletContext()); context.refresh(); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java index e0070a80c9..04fd95279b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java @@ -32,6 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Joe Grandja */ public class AbstractRequestMatcherRegistryTests { + private TestRequestMatcherRegistry matcherRegistry; @Before @@ -87,5 +88,7 @@ public class AbstractRequestMatcherRegistryTests { protected List chainRequestMatchers(List requestMatchers) { return requestMatchers; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/HttpSecurityHeadersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/HttpSecurityHeadersTests.java index 9a7a66ec64..7d24eb0c30 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/HttpSecurityHeadersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/HttpSecurityHeadersTests.java @@ -41,7 +41,6 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** - * * @author Rob Winch * */ @@ -49,8 +48,10 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @ContextConfiguration @WebAppConfiguration public class HttpSecurityHeadersTests { + @Autowired WebApplicationContext wac; + @Autowired Filter springSecurityFilterChain; @@ -58,44 +59,46 @@ public class HttpSecurityHeadersTests { @Before public void setup() { - mockMvc = MockMvcBuilders - .webAppContextSetup(wac) - .addFilters(springSecurityFilterChain) - .build(); + mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(springSecurityFilterChain).build(); } // gh-2953 // gh-3975 @Test public void headerWhenSpringMvcResourceThenCacheRelatedHeadersReset() throws Exception { - mockMvc.perform(get("/resources/file.js")) - .andExpect(status().isOk()) - .andExpect(header().string(HttpHeaders.CACHE_CONTROL, "max-age=12345")) - .andExpect(header().doesNotExist(HttpHeaders.PRAGMA)) - .andExpect(header().doesNotExist(HttpHeaders.EXPIRES)); + mockMvc.perform(get("/resources/file.js")).andExpect(status().isOk()) + .andExpect(header().string(HttpHeaders.CACHE_CONTROL, "max-age=12345")) + .andExpect(header().doesNotExist(HttpHeaders.PRAGMA)) + .andExpect(header().doesNotExist(HttpHeaders.EXPIRES)); } @Test public void headerWhenNotSpringResourceThenCacheRelatedHeadersSet() throws Exception { mockMvc.perform(get("/notresource")) - .andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate")) - .andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")) - .andExpect(header().string(HttpHeaders.EXPIRES, "0")); + .andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate")) + .andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")) + .andExpect(header().string(HttpHeaders.EXPIRES, "0")); } @EnableWebSecurity static class WebSecurityConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) { } + } @EnableWebMvc @Configuration static class WebMvcConfig implements WebMvcConfigurer { + @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/").setCachePeriod(12345); + registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/") + .setCachePeriod(12345); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java index 760152d496..0e779e9c4a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java @@ -48,6 +48,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Joe Grandja */ public class SampleWebSecurityConfigurerAdapterTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -55,7 +56,9 @@ public class SampleWebSecurityConfigurerAdapterTests { private FilterChainProxy springSecurityFilterChain; private MockHttpServletRequest request; + private MockHttpServletResponse response; + private MockFilterChain chain; @Before @@ -129,10 +132,12 @@ public class SampleWebSecurityConfigurerAdapterTests { * * * + * * @author Rob Winch */ @EnableWebSecurity public static class HelloWorldWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -141,8 +146,8 @@ public class SampleWebSecurityConfigurerAdapterTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } - } + } @Test public void readmeSampleWhenRequestSecureResourceThenRedirectToLogin() throws Exception { @@ -201,11 +206,13 @@ public class SampleWebSecurityConfigurerAdapterTests { * * * - * + * * * * * + * * @author Rob Winch */ @EnableWebSecurity @@ -213,9 +220,7 @@ public class SampleWebSecurityConfigurerAdapterTests { @Override public void configure(WebSecurity web) { - web - .ignoring() - .antMatchers("/resources/**"); + web.ignoring().antMatchers("/resources/**"); } @Override @@ -242,8 +247,8 @@ public class SampleWebSecurityConfigurerAdapterTests { .withUser(PasswordEncodedUser.admin()); // @formatter:on } - } + } @Test public void multiHttpSampleWhenRequestSecureResourceThenRedirectToLogin() throws Exception { @@ -293,7 +298,8 @@ public class SampleWebSecurityConfigurerAdapterTests { this.spring.register(SampleMultiHttpSecurityConfig.class).autowire(); this.request.setServletPath("/api/admin/test"); - this.request.addHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString("user:password".getBytes())); + this.request.addHeader("Authorization", + "Basic " + Base64.getEncoder().encodeToString("user:password".getBytes())); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN); @@ -304,7 +310,8 @@ public class SampleWebSecurityConfigurerAdapterTests { this.spring.register(SampleMultiHttpSecurityConfig.class).autowire(); this.request.setServletPath("/api/admin/test"); - this.request.addHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString("admin:password".getBytes())); + this.request.addHeader("Authorization", + "Basic " + Base64.getEncoder().encodeToString("admin:password".getBytes())); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); @@ -339,15 +346,18 @@ public class SampleWebSecurityConfigurerAdapterTests { * * * - * + * * * * * + * * @author Rob Winch */ @EnableWebSecurity public static class SampleMultiHttpSecurityConfig { + @Autowired protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -361,6 +371,7 @@ public class SampleWebSecurityConfigurerAdapterTests { @Configuration @Order(1) public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -372,15 +383,15 @@ public class SampleWebSecurityConfigurerAdapterTests { .httpBasic(); // @formatter:on } + } @Configuration public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { + @Override public void configure(WebSecurity web) { - web - .ignoring() - .antMatchers("/resources/**"); + web.ignoring().antMatchers("/resources/**"); } @Override @@ -396,6 +407,9 @@ public class SampleWebSecurityConfigurerAdapterTests { .permitAll(); // @formatter:on } + } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterPowermockTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterPowermockTests.java index a0643fcf3f..bcebf665c5 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterPowermockTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterPowermockTests.java @@ -53,14 +53,15 @@ import static org.powermock.api.mockito.PowerMockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; /** - * * @author Rob Winch * */ @RunWith(PowerMockRunner.class) @PrepareForTest({ SpringFactoriesLoader.class, WebAsyncManager.class }) -@PowerMockIgnore({ "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", "javax.xml.parsers.*", "javax.xml.transform.*" }) +@PowerMockIgnore({ "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", "javax.xml.parsers.*", + "javax.xml.transform.*" }) public class WebSecurityConfigurerAdapterPowermockTests { + ConfigurableWebApplicationContext context; @Rule @@ -80,9 +81,8 @@ public class WebSecurityConfigurerAdapterPowermockTests { public void loadConfigWhenDefaultConfigurerAsSpringFactoryhenDefaultConfigurerApplied() { spy(SpringFactoriesLoader.class); DefaultConfigurer configurer = new DefaultConfigurer(); - when(SpringFactoriesLoader - .loadFactories(AbstractHttpConfigurer.class, getClass().getClassLoader())) - .thenReturn(Arrays.asList(configurer)); + when(SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, getClass().getClassLoader())) + .thenReturn(Arrays.asList(configurer)); loadConfig(Config.class); @@ -100,13 +100,17 @@ public class WebSecurityConfigurerAdapterPowermockTests { @EnableWebSecurity static class Config extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) { } + } static class DefaultConfigurer extends AbstractHttpConfigurer { + boolean init; + boolean configure; @Override @@ -118,6 +122,7 @@ public class WebSecurityConfigurerAdapterPowermockTests { public void configure(HttpSecurity builder) { this.configure = true; } + } @Test @@ -128,15 +133,15 @@ public class WebSecurityConfigurerAdapterPowermockTests { this.mockMvc.perform(get("/").requestAttr(WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE, webAsyncManager)); - ArgumentCaptor callableProcessingInterceptorArgCaptor = - ArgumentCaptor.forClass(CallableProcessingInterceptor.class); - verify(webAsyncManager, atLeastOnce()).registerCallableInterceptor(any(), callableProcessingInterceptorArgCaptor.capture()); + ArgumentCaptor callableProcessingInterceptorArgCaptor = ArgumentCaptor + .forClass(CallableProcessingInterceptor.class); + verify(webAsyncManager, atLeastOnce()).registerCallableInterceptor(any(), + callableProcessingInterceptorArgCaptor.capture()); - CallableProcessingInterceptor callableProcessingInterceptor = - callableProcessingInterceptorArgCaptor.getAllValues().stream() - .filter(e -> SecurityContextCallableProcessingInterceptor.class.isAssignableFrom(e.getClass())) - .findFirst() - .orElse(null); + CallableProcessingInterceptor callableProcessingInterceptor = callableProcessingInterceptorArgCaptor + .getAllValues().stream() + .filter(e -> SecurityContextCallableProcessingInterceptor.class.isAssignableFrom(e.getClass())) + .findFirst().orElse(null); assertThat(callableProcessingInterceptor).isNotNull(); } @@ -156,5 +161,7 @@ public class WebSecurityConfigurerAdapterPowermockTests { @Override protected void configure(HttpSecurity http) { } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.java index 4d8bf244d1..a5a3ff02c4 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.java @@ -71,6 +71,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Joe Grandja */ public class WebSecurityConfigurerAdapterTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -81,14 +82,12 @@ public class WebSecurityConfigurerAdapterTests { public void loadConfigWhenRequestSecureThenDefaultSecurityHeadersReturned() throws Exception { this.spring.register(HeadersArePopulatedByDefaultConfig.class).autowire(); - this.mockMvc.perform(get("/").secure(true)) - .andExpect(header().string("X-Content-Type-Options", "nosniff")) - .andExpect(header().string("X-Frame-Options", "DENY")) - .andExpect(header().string("Strict-Transport-Security", "max-age=31536000 ; includeSubDomains")) - .andExpect(header().string("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate")) - .andExpect(header().string("Pragma", "no-cache")) - .andExpect(header().string("Expires", "0")) - .andExpect(header().string("X-XSS-Protection", "1; mode=block")); + this.mockMvc.perform(get("/").secure(true)).andExpect(header().string("X-Content-Type-Options", "nosniff")) + .andExpect(header().string("X-Frame-Options", "DENY")) + .andExpect(header().string("Strict-Transport-Security", "max-age=31536000 ; includeSubDomains")) + .andExpect(header().string("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate")) + .andExpect(header().string("Pragma", "no-cache")).andExpect(header().string("Expires", "0")) + .andExpect(header().string("X-XSS-Protection", "1; mode=block")); } @EnableWebSecurity @@ -106,14 +105,14 @@ public class WebSecurityConfigurerAdapterTests { @Override protected void configure(HttpSecurity http) { } + } @Test public void loadConfigWhenRequestAuthenticateThenAuthenticationEventPublished() throws Exception { this.spring.register(InMemoryAuthWithWebSecurityConfigurerAdapter.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(status().is3xxRedirection()); + this.mockMvc.perform(formLogin()).andExpect(status().is3xxRedirection()); assertThat(InMemoryAuthWithWebSecurityConfigurerAdapter.EVENTS).isNotEmpty(); assertThat(InMemoryAuthWithWebSecurityConfigurerAdapter.EVENTS).hasSize(1); @@ -121,7 +120,7 @@ public class WebSecurityConfigurerAdapterTests { @EnableWebSecurity static class InMemoryAuthWithWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter - implements ApplicationListener { + implements ApplicationListener { static List EVENTS = new ArrayList<>(); @@ -138,22 +137,22 @@ public class WebSecurityConfigurerAdapterTests { public void onApplicationEvent(AuthenticationSuccessEvent event) { EVENTS.add(event); } + } @Test public void loadConfigWhenInMemoryConfigureProtectedThenPasswordUpgraded() throws Exception { this.spring.register(InMemoryConfigureProtectedConfig.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(status().is3xxRedirection()); + this.mockMvc.perform(formLogin()).andExpect(status().is3xxRedirection()); - UserDetailsService uds = this.spring.getContext() - .getBean(UserDetailsService.class); + UserDetailsService uds = this.spring.getContext().getBean(UserDetailsService.class); assertThat(uds.loadUserByUsername("user").getPassword()).startsWith("{bcrypt}"); } @EnableWebSecurity static class InMemoryConfigureProtectedConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -168,22 +167,22 @@ public class WebSecurityConfigurerAdapterTests { public UserDetailsService userDetailsServiceBean() throws Exception { return super.userDetailsServiceBean(); } + } @Test public void loadConfigWhenInMemoryConfigureGlobalThenPasswordUpgraded() throws Exception { this.spring.register(InMemoryConfigureGlobalConfig.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(status().is3xxRedirection()); + this.mockMvc.perform(formLogin()).andExpect(status().is3xxRedirection()); - UserDetailsService uds = this.spring.getContext() - .getBean(UserDetailsService.class); + UserDetailsService uds = this.spring.getContext().getBean(UserDetailsService.class); assertThat(uds.loadUserByUsername("user").getPassword()).startsWith("{bcrypt}"); } @EnableWebSecurity static class InMemoryConfigureGlobalConfig extends WebSecurityConfigurerAdapter { + @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -198,24 +197,28 @@ public class WebSecurityConfigurerAdapterTests { public UserDetailsService userDetailsServiceBean() throws Exception { return super.userDetailsServiceBean(); } + } @Test public void loadConfigWhenCustomContentNegotiationStrategyBeanThenOverridesDefault() { - OverrideContentNegotiationStrategySharedObjectConfig.CONTENT_NEGOTIATION_STRATEGY_BEAN = mock(ContentNegotiationStrategy.class); + OverrideContentNegotiationStrategySharedObjectConfig.CONTENT_NEGOTIATION_STRATEGY_BEAN = mock( + ContentNegotiationStrategy.class); this.spring.register(OverrideContentNegotiationStrategySharedObjectConfig.class).autowire(); - OverrideContentNegotiationStrategySharedObjectConfig securityConfig = - this.spring.getContext().getBean(OverrideContentNegotiationStrategySharedObjectConfig.class); + OverrideContentNegotiationStrategySharedObjectConfig securityConfig = this.spring.getContext() + .getBean(OverrideContentNegotiationStrategySharedObjectConfig.class); assertThat(securityConfig.contentNegotiationStrategySharedObject).isNotNull(); assertThat(securityConfig.contentNegotiationStrategySharedObject) - .isSameAs(OverrideContentNegotiationStrategySharedObjectConfig.CONTENT_NEGOTIATION_STRATEGY_BEAN); + .isSameAs(OverrideContentNegotiationStrategySharedObjectConfig.CONTENT_NEGOTIATION_STRATEGY_BEAN); } @EnableWebSecurity static class OverrideContentNegotiationStrategySharedObjectConfig extends WebSecurityConfigurerAdapter { + static ContentNegotiationStrategy CONTENT_NEGOTIATION_STRATEGY_BEAN; + private ContentNegotiationStrategy contentNegotiationStrategySharedObject; @Bean @@ -228,21 +231,24 @@ public class WebSecurityConfigurerAdapterTests { this.contentNegotiationStrategySharedObject = http.getSharedObject(ContentNegotiationStrategy.class); super.configure(http); } + } @Test public void loadConfigWhenDefaultContentNegotiationStrategyThenHeaderContentNegotiationStrategy() { this.spring.register(ContentNegotiationStrategyDefaultSharedObjectConfig.class).autowire(); - ContentNegotiationStrategyDefaultSharedObjectConfig securityConfig = - this.spring.getContext().getBean(ContentNegotiationStrategyDefaultSharedObjectConfig.class); + ContentNegotiationStrategyDefaultSharedObjectConfig securityConfig = this.spring.getContext() + .getBean(ContentNegotiationStrategyDefaultSharedObjectConfig.class); assertThat(securityConfig.contentNegotiationStrategySharedObject).isNotNull(); - assertThat(securityConfig.contentNegotiationStrategySharedObject).isInstanceOf(HeaderContentNegotiationStrategy.class); + assertThat(securityConfig.contentNegotiationStrategySharedObject) + .isInstanceOf(HeaderContentNegotiationStrategy.class); } @EnableWebSecurity static class ContentNegotiationStrategyDefaultSharedObjectConfig extends WebSecurityConfigurerAdapter { + private ContentNegotiationStrategy contentNegotiationStrategySharedObject; @Override @@ -250,6 +256,7 @@ public class WebSecurityConfigurerAdapterTests { this.contentNegotiationStrategySharedObject = http.getSharedObject(ContentNegotiationStrategy.class); super.configure(http); } + } @Test @@ -258,23 +265,26 @@ public class WebSecurityConfigurerAdapterTests { MyFilter myFilter = this.spring.getContext().getBean(MyFilter.class); - Throwable thrown = catchThrowable(() -> myFilter.userDetailsService.loadUserByUsername("user") ); + Throwable thrown = catchThrowable(() -> myFilter.userDetailsService.loadUserByUsername("user")); assertThat(thrown).isNull(); - thrown = catchThrowable(() -> myFilter.userDetailsService.loadUserByUsername("admin") ); + thrown = catchThrowable(() -> myFilter.userDetailsService.loadUserByUsername("admin")); assertThat(thrown).isInstanceOf(UsernameNotFoundException.class); } @Configuration static class RequiresUserDetailsServiceConfig { + @Bean public MyFilter myFilter(UserDetailsService userDetailsService) { return new MyFilter(userDetailsService); } + } @EnableWebSecurity static class UserDetailsServiceConfig extends WebSecurityConfigurerAdapter { + @Autowired private MyFilter myFilter; @@ -297,9 +307,11 @@ public class WebSecurityConfigurerAdapterTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } static class MyFilter extends OncePerRequestFilter { + private UserDetailsService userDetailsService; MyFilter(UserDetailsService userDetailsService) { @@ -307,11 +319,11 @@ public class WebSecurityConfigurerAdapterTests { } @Override - protected void doFilterInternal(HttpServletRequest request, - HttpServletResponse response, - FilterChain filterChain) throws ServletException, IOException { + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { filterChain.doFilter(request, response); } + } // SEC-2274: WebSecurityConfigurer adds ApplicationContext as a shared object @@ -319,8 +331,8 @@ public class WebSecurityConfigurerAdapterTests { public void loadConfigWhenSharedObjectsCreatedThenApplicationContextAdded() { this.spring.register(ApplicationContextSharedObjectConfig.class).autowire(); - ApplicationContextSharedObjectConfig securityConfig = - this.spring.getContext().getBean(ApplicationContextSharedObjectConfig.class); + ApplicationContextSharedObjectConfig securityConfig = this.spring.getContext() + .getBean(ApplicationContextSharedObjectConfig.class); assertThat(securityConfig.applicationContextSharedObject).isNotNull(); assertThat(securityConfig.applicationContextSharedObject).isSameAs(this.spring.getContext()); @@ -328,6 +340,7 @@ public class WebSecurityConfigurerAdapterTests { @EnableWebSecurity static class ApplicationContextSharedObjectConfig extends WebSecurityConfigurerAdapter { + private ApplicationContext applicationContextSharedObject; @Override @@ -335,6 +348,7 @@ public class WebSecurityConfigurerAdapterTests { this.applicationContextSharedObject = http.getSharedObject(ApplicationContext.class); super.configure(http); } + } @Test @@ -342,17 +356,18 @@ public class WebSecurityConfigurerAdapterTests { CustomTrustResolverConfig.AUTHENTICATION_TRUST_RESOLVER_BEAN = mock(AuthenticationTrustResolver.class); this.spring.register(CustomTrustResolverConfig.class).autowire(); - CustomTrustResolverConfig securityConfig = - this.spring.getContext().getBean(CustomTrustResolverConfig.class); + CustomTrustResolverConfig securityConfig = this.spring.getContext().getBean(CustomTrustResolverConfig.class); assertThat(securityConfig.authenticationTrustResolverSharedObject).isNotNull(); assertThat(securityConfig.authenticationTrustResolverSharedObject) - .isSameAs(CustomTrustResolverConfig.AUTHENTICATION_TRUST_RESOLVER_BEAN); + .isSameAs(CustomTrustResolverConfig.AUTHENTICATION_TRUST_RESOLVER_BEAN); } @EnableWebSecurity static class CustomTrustResolverConfig extends WebSecurityConfigurerAdapter { + static AuthenticationTrustResolver AUTHENTICATION_TRUST_RESOLVER_BEAN; + private AuthenticationTrustResolver authenticationTrustResolverSharedObject; @Bean @@ -365,21 +380,23 @@ public class WebSecurityConfigurerAdapterTests { this.authenticationTrustResolverSharedObject = http.getSharedObject(AuthenticationTrustResolver.class); super.configure(http); } + } @Test public void compareOrderWebSecurityConfigurerAdapterWhenLowestOrderToDefaultOrderThenGreaterThanZero() { AnnotationAwareOrderComparator comparator = new AnnotationAwareOrderComparator(); - assertThat(comparator.compare( - new LowestPriorityWebSecurityConfig(), - new DefaultOrderWebSecurityConfig())).isGreaterThan(0); + assertThat(comparator.compare(new LowestPriorityWebSecurityConfig(), new DefaultOrderWebSecurityConfig())) + .isGreaterThan(0); } static class DefaultOrderWebSecurityConfig extends WebSecurityConfigurerAdapter { + } @Order static class LowestPriorityWebSecurityConfig extends WebSecurityConfigurerAdapter { + } // gh-7515 @@ -387,17 +404,17 @@ public class WebSecurityConfigurerAdapterTests { public void performWhenUsingAuthenticationEventPublisherBeanThenUses() throws Exception { this.spring.register(CustomAuthenticationEventPublisherBean.class).autowire(); - AuthenticationEventPublisher authenticationEventPublisher = - this.spring.getContext().getBean(AuthenticationEventPublisher.class); + AuthenticationEventPublisher authenticationEventPublisher = this.spring.getContext() + .getBean(AuthenticationEventPublisher.class); - this.mockMvc.perform(get("/") - .with(httpBasic("user", "password"))); + this.mockMvc.perform(get("/").with(httpBasic("user", "password"))); verify(authenticationEventPublisher).publishAuthenticationSuccess(any(Authentication.class)); } @EnableWebSecurity static class CustomAuthenticationEventPublisherBean extends WebSecurityConfigurerAdapter { + @Bean @Override public UserDetailsService userDetailsService() { @@ -408,6 +425,7 @@ public class WebSecurityConfigurerAdapterTests { public AuthenticationEventPublisher authenticationEventPublisher() { return mock(AuthenticationEventPublisher.class); } + } // gh-4400 @@ -415,24 +433,27 @@ public class WebSecurityConfigurerAdapterTests { public void performWhenUsingAuthenticationEventPublisherInDslThenUses() throws Exception { this.spring.register(CustomAuthenticationEventPublisherDsl.class).autowire(); - AuthenticationEventPublisher authenticationEventPublisher = - CustomAuthenticationEventPublisherDsl.EVENT_PUBLISHER; + AuthenticationEventPublisher authenticationEventPublisher = CustomAuthenticationEventPublisherDsl.EVENT_PUBLISHER; - this.mockMvc.perform(get("/") - .with(httpBasic("user", "password"))); // fails since no providers configured + this.mockMvc.perform(get("/").with(httpBasic("user", "password"))); // fails since + // no + // providers + // configured - verify(authenticationEventPublisher).publishAuthenticationFailure( - any(AuthenticationException.class), + verify(authenticationEventPublisher).publishAuthenticationFailure(any(AuthenticationException.class), any(Authentication.class)); } @EnableWebSecurity static class CustomAuthenticationEventPublisherDsl extends WebSecurityConfigurerAdapter { + static AuthenticationEventPublisher EVENT_PUBLISHER = mock(AuthenticationEventPublisher.class); @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationEventPublisher(EVENT_PUBLISHER); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java index 620abd0367..4e76f6a82e 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java @@ -49,6 +49,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Joe Grandja */ public class HttpConfigurationTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -57,11 +58,11 @@ public class HttpConfigurationTests { @Test public void configureWhenAddFilterUnregisteredThenThrowsBeanCreationException() { - Throwable thrown = catchThrowable(() -> this.spring.register(UnregisteredFilterConfig.class).autowire() ); + Throwable thrown = catchThrowable(() -> this.spring.register(UnregisteredFilterConfig.class).autowire()); assertThat(thrown).isInstanceOf(BeanCreationException.class); - assertThat(thrown.getMessage()).contains("The Filter class " + UnregisteredFilter.class.getName() + - " does not have a registered order and cannot be added without a specified order." + - " Consider using addFilterBefore or addFilterAfter instead."); + assertThat(thrown.getMessage()).contains("The Filter class " + UnregisteredFilter.class.getName() + + " does not have a registered order and cannot be added without a specified order." + + " Consider using addFilterBefore or addFilterAfter instead."); } @EnableWebSecurity @@ -81,15 +82,17 @@ public class HttpConfigurationTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } static class UnregisteredFilter extends OncePerRequestFilter { + @Override - protected void doFilterInternal(HttpServletRequest request, - HttpServletResponse response, - FilterChain filterChain) throws ServletException, IOException { + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { filterChain.doFilter(request, response); } + } // https://github.com/spring-projects/spring-security-javaconfig/issues/104 @@ -100,12 +103,13 @@ public class HttpConfigurationTests { this.mockMvc.perform(get("/")); - verify(CasAuthenticationFilterConfig.CAS_AUTHENTICATION_FILTER).doFilter( - any(ServletRequest.class), any(ServletResponse.class), any(FilterChain.class)); + verify(CasAuthenticationFilterConfig.CAS_AUTHENTICATION_FILTER).doFilter(any(ServletRequest.class), + any(ServletResponse.class), any(FilterChain.class)); } @EnableWebSecurity static class CasAuthenticationFilterConfig extends WebSecurityConfigurerAdapter { + static CasAuthenticationFilter CAS_AUTHENTICATION_FILTER; protected void configure(HttpSecurity http) { @@ -114,6 +118,7 @@ public class HttpConfigurationTests { .addFilter(CAS_AUTHENTICATION_FILTER); // @formatter:on } + } @Test @@ -128,6 +133,7 @@ public class HttpConfigurationTests { @EnableWebSecurity static class RequestMatcherRegistryConfigs extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -142,5 +148,7 @@ public class HttpConfigurationTests { .httpBasic(); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java index a5a33c4fe5..ac5075b71c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java @@ -63,33 +63,38 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; /** - * Tests to verify that all the functionality of attributes are present in Java Config. + * Tests to verify that all the functionality of attributes are present in Java + * Config. * * @author Rob Winch * @author Joe Grandja */ public class NamespaceHttpTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @Autowired private MockMvc mockMvc; - @Test // http@access-decision-manager-ref + @Test // http@access-decision-manager-ref public void configureWhenAccessDecisionManagerSetThenVerifyUse() throws Exception { AccessDecisionManagerRefConfig.ACCESS_DECISION_MANAGER = mock(AccessDecisionManager.class); when(AccessDecisionManagerRefConfig.ACCESS_DECISION_MANAGER.supports(FilterInvocation.class)).thenReturn(true); - when(AccessDecisionManagerRefConfig.ACCESS_DECISION_MANAGER.supports(any(ConfigAttribute.class))).thenReturn(true); + when(AccessDecisionManagerRefConfig.ACCESS_DECISION_MANAGER.supports(any(ConfigAttribute.class))) + .thenReturn(true); this.spring.register(AccessDecisionManagerRefConfig.class).autowire(); this.mockMvc.perform(get("/")); - verify(AccessDecisionManagerRefConfig.ACCESS_DECISION_MANAGER, times(1)).decide(any(Authentication.class), any(), anyCollection()); + verify(AccessDecisionManagerRefConfig.ACCESS_DECISION_MANAGER, times(1)).decide(any(Authentication.class), + any(), anyCollection()); } @EnableWebSecurity static class AccessDecisionManagerRefConfig extends WebSecurityConfigurerAdapter { + static AccessDecisionManager ACCESS_DECISION_MANAGER; @Override @@ -101,19 +106,20 @@ public class NamespaceHttpTests { .accessDecisionManager(ACCESS_DECISION_MANAGER); // @formatter:on } + } - @Test // http@access-denied-page + @Test // http@access-denied-page public void configureWhenAccessDeniedPageSetAndRequestForbiddenThenForwardedToAccessDeniedPage() throws Exception { this.spring.register(AccessDeniedPageConfig.class).autowire(); - this.mockMvc.perform(get("/admin").with(user(PasswordEncodedUser.user()))) - .andExpect(status().isForbidden()) - .andExpect(forwardedUrl("/AccessDeniedPage")); + this.mockMvc.perform(get("/admin").with(user(PasswordEncodedUser.user()))).andExpect(status().isForbidden()) + .andExpect(forwardedUrl("/AccessDeniedPage")); } @EnableWebSecurity static class AccessDeniedPageConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -126,9 +132,10 @@ public class NamespaceHttpTests { .accessDeniedPage("/AccessDeniedPage"); // @formatter:on } + } - @Test // http@authentication-manager-ref + @Test // http@authentication-manager-ref public void configureWhenAuthenticationManagerProvidedThenVerifyUse() throws Exception { AuthenticationManagerRefConfig.AUTHENTICATION_MANAGER = mock(AuthenticationManager.class); this.spring.register(AuthenticationManagerRefConfig.class).autowire(); @@ -140,6 +147,7 @@ public class NamespaceHttpTests { @EnableWebSecurity static class AuthenticationManagerRefConfig extends WebSecurityConfigurerAdapter { + static AuthenticationManager AUTHENTICATION_MANAGER; @Override @@ -157,9 +165,10 @@ public class NamespaceHttpTests { .formLogin(); // @formatter:on } + } - @Test // http@create-session=always + @Test // http@create-session=always public void configureWhenSessionCreationPolicyAlwaysThenSessionCreatedOnRequest() throws Exception { this.spring.register(CreateSessionAlwaysConfig.class).autowire(); @@ -172,6 +181,7 @@ public class NamespaceHttpTests { @EnableWebSecurity static class CreateSessionAlwaysConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -183,9 +193,10 @@ public class NamespaceHttpTests { .sessionCreationPolicy(SessionCreationPolicy.ALWAYS); // @formatter:on } + } - @Test // http@create-session=stateless + @Test // http@create-session=stateless public void configureWhenSessionCreationPolicyStatelessThenSessionNotCreatedOnRequest() throws Exception { this.spring.register(CreateSessionStatelessConfig.class).autowire(); @@ -197,6 +208,7 @@ public class NamespaceHttpTests { @EnableWebSecurity static class CreateSessionStatelessConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -208,9 +220,10 @@ public class NamespaceHttpTests { .sessionCreationPolicy(SessionCreationPolicy.STATELESS); // @formatter:on } + } - @Test // http@create-session=ifRequired + @Test // http@create-session=ifRequired public void configureWhenSessionCreationPolicyIfRequiredThenSessionCreatedWhenRequiredOnRequest() throws Exception { this.spring.register(IfRequiredConfig.class).autowire(); @@ -228,6 +241,7 @@ public class NamespaceHttpTests { @EnableWebSecurity static class IfRequiredConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -242,9 +256,10 @@ public class NamespaceHttpTests { .formLogin(); // @formatter:on } + } - @Test // http@create-session=never + @Test // http@create-session=never public void configureWhenSessionCreationPolicyNeverThenSessionNotCreatedOnRequest() throws Exception { this.spring.register(CreateSessionNeverConfig.class).autowire(); @@ -256,6 +271,7 @@ public class NamespaceHttpTests { @EnableWebSecurity static class CreateSessionNeverConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -267,19 +283,21 @@ public class NamespaceHttpTests { .sessionCreationPolicy(SessionCreationPolicy.NEVER); // @formatter:on } + } - @Test // http@entry-point-ref - public void configureWhenAuthenticationEntryPointSetAndRequestUnauthorizedThenRedirectedToAuthenticationEntryPoint() throws Exception { + @Test // http@entry-point-ref + public void configureWhenAuthenticationEntryPointSetAndRequestUnauthorizedThenRedirectedToAuthenticationEntryPoint() + throws Exception { this.spring.register(EntryPointRefConfig.class).autowire(); - this.mockMvc.perform(get("/")) - .andExpect(status().is3xxRedirection()) - .andExpect(redirectedUrlPattern("**/entry-point")); + this.mockMvc.perform(get("/")).andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrlPattern("**/entry-point")); } @EnableWebSecurity static class EntryPointRefConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -293,9 +311,10 @@ public class NamespaceHttpTests { .formLogin(); // @formatter:on } + } - @Test // http@jaas-api-provision + @Test // http@jaas-api-provision public void configureWhenJaasApiIntegrationFilterAddedThenJaasSubjectObtained() throws Exception { LoginContext loginContext = mock(LoginContext.class); when(loginContext.getSubject()).thenReturn(new Subject()); @@ -313,6 +332,7 @@ public class NamespaceHttpTests { @EnableWebSecurity static class JaasApiProvisionConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) { // @formatter:off @@ -320,19 +340,20 @@ public class NamespaceHttpTests { .addFilter(new JaasApiIntegrationFilter()); // @formatter:on } + } - @Test // http@realm + @Test // http@realm public void configureWhenHttpBasicAndRequestUnauthorizedThenReturnWWWAuthenticateWithRealm() throws Exception { this.spring.register(RealmConfig.class).autowire(); - this.mockMvc.perform(get("/")) - .andExpect(status().isUnauthorized()) - .andExpect(header().string("WWW-Authenticate", "Basic realm=\"RealmConfig\"")); + this.mockMvc.perform(get("/")).andExpect(status().isUnauthorized()) + .andExpect(header().string("WWW-Authenticate", "Basic realm=\"RealmConfig\"")); } @EnableWebSecurity static class RealmConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -344,21 +365,24 @@ public class NamespaceHttpTests { .realmName("RealmConfig"); // @formatter:on } + } - @Test // http@request-matcher-ref ant + @Test // http@request-matcher-ref ant public void configureWhenAntPatternMatchingThenAntPathRequestMatcherUsed() { this.spring.register(RequestMatcherAntConfig.class).autowire(); FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class); assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class); - DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(0); + DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains() + .get(0); assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class); } @EnableWebSecurity static class RequestMatcherAntConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) { // @formatter:off @@ -366,21 +390,24 @@ public class NamespaceHttpTests { .antMatcher("/api/**"); // @formatter:on } + } - @Test // http@request-matcher-ref regex + @Test // http@request-matcher-ref regex public void configureWhenRegexPatternMatchingThenRegexRequestMatcherUsed() { this.spring.register(RequestMatcherRegexConfig.class).autowire(); FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class); assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class); - DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(0); + DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains() + .get(0); assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(RegexRequestMatcher.class); } @EnableWebSecurity static class RequestMatcherRegexConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) { // @formatter:off @@ -388,21 +415,25 @@ public class NamespaceHttpTests { .regexMatcher("/regex/.*"); // @formatter:on } + } - @Test // http@request-matcher-ref + @Test // http@request-matcher-ref public void configureWhenRequestMatcherProvidedThenRequestMatcherUsed() { this.spring.register(RequestMatcherRefConfig.class).autowire(); FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class); assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class); - DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(0); - assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(RequestMatcherRefConfig.MyRequestMatcher.class); + DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains() + .get(0); + assertThat(securityFilterChain.getRequestMatcher()) + .isInstanceOf(RequestMatcherRefConfig.MyRequestMatcher.class); } @EnableWebSecurity static class RequestMatcherRefConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) { // @formatter:off @@ -412,28 +443,34 @@ public class NamespaceHttpTests { } static class MyRequestMatcher implements RequestMatcher { + public boolean matches(HttpServletRequest request) { return true; } + } + } - @Test // http@security=none + @Test // http@security=none public void configureWhenIgnoredAntPatternsThenAntPathRequestMatcherUsedWithNoFilters() { this.spring.register(SecurityNoneConfig.class).autowire(); FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class); assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class); - DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(0); + DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains() + .get(0); assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class); - assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern()).isEqualTo("/resources/**"); + assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern()) + .isEqualTo("/resources/**"); assertThat(securityFilterChain.getFilters()).isEmpty(); assertThat(filterChainProxy.getFilterChains().get(1)).isInstanceOf(DefaultSecurityFilterChain.class); securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(1); assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class); - assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern()).isEqualTo("/public/**"); + assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern()) + .isEqualTo("/public/**"); assertThat(securityFilterChain.getFilters()).isEmpty(); } @@ -442,17 +479,16 @@ public class NamespaceHttpTests { @Override public void configure(WebSecurity web) { - web - .ignoring() - .antMatchers("/resources/**", "/public/**"); + web.ignoring().antMatchers("/resources/**", "/public/**"); } @Override protected void configure(HttpSecurity http) { } + } - @Test // http@security-context-repository-ref + @Test // http@security-context-repository-ref public void configureWhenNullSecurityContextRepositoryThenSecurityContextNotSavedInSession() throws Exception { this.spring.register(SecurityContextRepoConfig.class).autowire(); @@ -463,6 +499,7 @@ public class NamespaceHttpTests { @EnableWebSecurity static class SecurityContextRepoConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -485,19 +522,22 @@ public class NamespaceHttpTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } - @Test // http@servlet-api-provision=false + @Test // http@servlet-api-provision=false public void configureWhenServletApiDisabledThenRequestNotServletApiWrapper() throws Exception { this.spring.register(ServletApiProvisionConfig.class, MainController.class).autowire(); this.mockMvc.perform(get("/")); - assertThat(MainController.HTTP_SERVLET_REQUEST_TYPE).isNotInstanceOf(SecurityContextHolderAwareRequestWrapper.class); + assertThat(MainController.HTTP_SERVLET_REQUEST_TYPE) + .isNotInstanceOf(SecurityContextHolderAwareRequestWrapper.class); } @EnableWebSecurity static class ServletApiProvisionConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -509,19 +549,22 @@ public class NamespaceHttpTests { .disable(); // @formatter:on } + } - @Test // http@servlet-api-provision defaults to true + @Test // http@servlet-api-provision defaults to true public void configureWhenServletApiDefaultThenRequestIsServletApiWrapper() throws Exception { this.spring.register(ServletApiProvisionDefaultsConfig.class, MainController.class).autowire(); this.mockMvc.perform(get("/")); - assertThat(SecurityContextHolderAwareRequestWrapper.class).isAssignableFrom(MainController.HTTP_SERVLET_REQUEST_TYPE); + assertThat(SecurityContextHolderAwareRequestWrapper.class) + .isAssignableFrom(MainController.HTTP_SERVLET_REQUEST_TYPE); } @EnableWebSecurity static class ServletApiProvisionDefaultsConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -530,10 +573,12 @@ public class NamespaceHttpTests { .anyRequest().permitAll(); // @formatter:on } + } @Controller static class MainController { + static Class HTTP_SERVLET_REQUEST_TYPE; @GetMapping("/") @@ -541,20 +586,22 @@ public class NamespaceHttpTests { HTTP_SERVLET_REQUEST_TYPE = request.getClass(); return "index"; } + } - @Test // http@use-expressions=true + @Test // http@use-expressions=true public void configureWhenUseExpressionsEnabledThenExpressionBasedSecurityMetadataSource() { this.spring.register(UseExpressionsConfig.class).autowire(); UseExpressionsConfig config = this.spring.getContext().getBean(UseExpressionsConfig.class); assertThat(ExpressionBasedFilterInvocationSecurityMetadataSource.class) - .isAssignableFrom(config.filterInvocationSecurityMetadataSourceType); + .isAssignableFrom(config.filterInvocationSecurityMetadataSourceType); } @EnableWebSecurity static class UseExpressionsConfig extends WebSecurityConfigurerAdapter { + private Class filterInvocationSecurityMetadataSourceType; @Override @@ -574,24 +621,26 @@ public class NamespaceHttpTests { final HttpSecurity http = this.getHttp(); web.postBuildAction(() -> { FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class); - UseExpressionsConfig.this.filterInvocationSecurityMetadataSourceType = - securityInterceptor.getSecurityMetadataSource().getClass(); + UseExpressionsConfig.this.filterInvocationSecurityMetadataSourceType = securityInterceptor + .getSecurityMetadataSource().getClass(); }); } + } - @Test // http@use-expressions=false + @Test // http@use-expressions=false public void configureWhenUseExpressionsDisabledThenDefaultSecurityMetadataSource() { this.spring.register(DisableUseExpressionsConfig.class).autowire(); DisableUseExpressionsConfig config = this.spring.getContext().getBean(DisableUseExpressionsConfig.class); assertThat(DefaultFilterInvocationSecurityMetadataSource.class) - .isAssignableFrom(config.filterInvocationSecurityMetadataSourceType); + .isAssignableFrom(config.filterInvocationSecurityMetadataSourceType); } @EnableWebSecurity static class DisableUseExpressionsConfig extends WebSecurityConfigurerAdapter { + private Class filterInvocationSecurityMetadataSourceType; @Override @@ -611,9 +660,11 @@ public class NamespaceHttpTests { final HttpSecurity http = this.getHttp(); web.postBuildAction(() -> { FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class); - DisableUseExpressionsConfig.this.filterInvocationSecurityMetadataSourceType = - securityInterceptor.getSecurityMetadataSource().getClass(); + DisableUseExpressionsConfig.this.filterInvocationSecurityMetadataSourceType = securityInterceptor + .getSecurityMetadataSource().getClass(); }); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java index a096e39ec6..b773e244c8 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java @@ -45,10 +45,13 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Rob Winch */ public class WebSecurityTests { + AnnotationConfigWebApplicationContext context; MockHttpServletRequest request; + MockHttpServletResponse response; + MockFilterChain chain; @Autowired @@ -97,14 +100,14 @@ public class WebSecurityTests { this.request.setRequestURI("/other"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); } @EnableWebSecurity @Configuration @EnableWebMvc static class MvcMatcherConfig extends WebSecurityConfigurerAdapter { + @Override public void configure(WebSecurity web) { // @formatter:off @@ -134,11 +137,14 @@ public class WebSecurityTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Test @@ -173,14 +179,14 @@ public class WebSecurityTests { this.request.setRequestURI("/other/path"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); } @EnableWebSecurity @Configuration @EnableWebMvc static class MvcMatcherServletPathConfig extends WebSecurityConfigurerAdapter { + @Override public void configure(WebSecurity web) { // @formatter:off @@ -211,19 +217,24 @@ public class WebSecurityTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Configuration static class LegacyMvcMatchingConfig implements WebMvcConfigurer { + @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseSuffixPatternMatch(true); } + } public void loadConfig(Class... configs) { diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/AuthenticationPrincipalArgumentResolverTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/AuthenticationPrincipalArgumentResolverTests.java index 021865f318..df01d613d2 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/AuthenticationPrincipalArgumentResolverTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/AuthenticationPrincipalArgumentResolverTests.java @@ -42,7 +42,6 @@ import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; /** - * * @author Rob Winch * */ @@ -50,6 +49,7 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc; @ContextConfiguration @WebAppConfiguration public class AuthenticationPrincipalArgumentResolverTests { + @Autowired WebApplicationContext wac; @@ -62,21 +62,19 @@ public class AuthenticationPrincipalArgumentResolverTests { public void authenticationPrincipalExpressionWhenBeanExpressionSuppliedThenBeanUsed() throws Exception { User user = new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER")); SecurityContext context = SecurityContextHolder.createEmptyContext(); - context.setAuthentication(new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities())); + context.setAuthentication( + new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities())); SecurityContextHolder.setContext(context); - MockMvc mockMvc = MockMvcBuilders - .webAppContextSetup(wac) - .build(); + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); - mockMvc.perform(get("/users/self")) - .andExpect(status().isOk()) - .andExpect(content().string("extracted-user")); + mockMvc.perform(get("/users/self")).andExpect(status().isOk()).andExpect(content().string("extracted-user")); } @EnableWebSecurity @EnableWebMvc static class Config { + @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java index 35dac47b9c..c8b2c3e75d 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java @@ -45,6 +45,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Joe Grandja */ public class EnableWebSecurityTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -56,12 +57,14 @@ public class EnableWebSecurityTests { this.spring.register(SecurityConfig.class).autowire(); AuthenticationManager authenticationManager = this.spring.getContext().getBean(AuthenticationManager.class); - Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); + Authentication authentication = authenticationManager + .authenticate(new UsernamePasswordAuthenticationToken("user", "password")); assertThat(authentication.isAuthenticated()).isTrue(); } @EnableWebSecurity static class SecurityConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -87,6 +90,7 @@ public class EnableWebSecurityTests { .formLogin(); // @formatter:on } + } @Test @@ -97,10 +101,12 @@ public class EnableWebSecurityTests { @Configuration static class ChildSecurityConfig extends DebugSecurityConfig { + } - @EnableWebSecurity(debug=true) + @EnableWebSecurity(debug = true) static class DebugSecurityConfig extends WebSecurityConfigurerAdapter { + } @Test @@ -108,12 +114,13 @@ public class EnableWebSecurityTests { this.spring.register(AuthenticationPrincipalConfig.class).autowire(); this.mockMvc.perform(get("/").with(authentication(new TestingAuthenticationToken("user1", "password")))) - .andExpect(content().string("user1")); + .andExpect(content().string("user1")); } @EnableWebSecurity @EnableWebMvc static class AuthenticationPrincipalConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) { } @@ -125,7 +132,9 @@ public class EnableWebSecurityTests { String principal(@AuthenticationPrincipal String principal) { return principal; } + } + } @Test @@ -133,12 +142,13 @@ public class EnableWebSecurityTests { this.spring.register(SecurityFilterChainAuthenticationPrincipalConfig.class).autowire(); this.mockMvc.perform(get("/").with(authentication(new TestingAuthenticationToken("user1", "password")))) - .andExpect(content().string("user1")); + .andExpect(content().string("user1")); } @EnableWebSecurity @EnableWebMvc static class SecurityFilterChainAuthenticationPrincipalConfig { + @Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http.build(); @@ -151,7 +161,9 @@ public class EnableWebSecurityTests { String principal(@AuthenticationPrincipal String principal) { return principal; } + } + } @Test @@ -166,6 +178,7 @@ public class EnableWebSecurityTests { @EnableWebSecurity static class BeanProxyEnabledByDefaultConfig extends WebSecurityConfigurerAdapter { + @Bean public Child child() { return new Child(); @@ -175,6 +188,7 @@ public class EnableWebSecurityTests { public Parent parent() { return new Parent(child()); } + } @Test @@ -190,6 +204,7 @@ public class EnableWebSecurityTests { @Configuration(proxyBeanMethods = false) @EnableWebSecurity static class BeanProxyDisabledConfig extends WebSecurityConfigurerAdapter { + @Bean public Child child() { return new Child(); @@ -199,9 +214,11 @@ public class EnableWebSecurityTests { public Parent parent() { return new Parent(child()); } + } static class Parent { + private Child child; Parent(Child child) { @@ -211,10 +228,14 @@ public class EnableWebSecurityTests { public Child getChild() { return child; } + } static class Child { + Child() { } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java index 5297578a65..e27fd51616 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java @@ -62,6 +62,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Eleftheria Stein */ public class HttpSecurityConfigurationTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -70,11 +71,9 @@ public class HttpSecurityConfigurationTests { @Test public void postWhenDefaultFilterChainBeanThenRespondsWithForbidden() throws Exception { - this.spring.register(DefaultWithFilterChainConfig.class) - .autowire(); + this.spring.register(DefaultWithFilterChainConfig.class).autowire(); - this.mockMvc.perform(post("/")) - .andExpect(status().isForbidden()); + this.mockMvc.perform(post("/")).andExpect(status().isForbidden()); } @Test @@ -83,13 +82,14 @@ public class HttpSecurityConfigurationTests { MvcResult mvcResult = this.mockMvc.perform(get("/").secure(true)) .andExpect(header().string(HttpHeaders.X_CONTENT_TYPE_OPTIONS, "nosniff")) - .andExpect(header().string(HttpHeaders.X_FRAME_OPTIONS, XFrameOptionsHeaderWriter.XFrameOptionsMode.DENY.name())) - .andExpect(header().string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains")) + .andExpect(header().string(HttpHeaders.X_FRAME_OPTIONS, + XFrameOptionsHeaderWriter.XFrameOptionsMode.DENY.name())) + .andExpect( + header().string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains")) .andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate")) .andExpect(header().string(HttpHeaders.EXPIRES, "0")) .andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")) - .andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")) - .andReturn(); + .andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactlyInAnyOrder( HttpHeaders.X_CONTENT_TYPE_OPTIONS, HttpHeaders.X_FRAME_OPTIONS, HttpHeaders.STRICT_TRANSPORT_SECURITY, HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA, HttpHeaders.X_XSS_PROTECTION); @@ -99,57 +99,54 @@ public class HttpSecurityConfigurationTests { public void logoutWhenDefaultFilterChainBeanThenCreatesDefaultLogoutEndpoint() throws Exception { this.spring.register(DefaultWithFilterChainConfig.class).autowire(); - this.mockMvc.perform(post("/logout").with(csrf())) - .andExpect(redirectedUrl("/login?logout")); + this.mockMvc.perform(post("/logout").with(csrf())).andExpect(redirectedUrl("/login?logout")); } @Test public void loadConfigWhenDefaultConfigThenWebAsyncManagerIntegrationFilterAdded() throws Exception { this.spring.register(DefaultWithFilterChainConfig.class, NameController.class).autowire(); - MvcResult mvcResult = this.mockMvc.perform(get("/name").with(user("Bob"))) - .andExpect(request().asyncStarted()) + MvcResult mvcResult = this.mockMvc.perform(get("/name").with(user("Bob"))).andExpect(request().asyncStarted()) .andReturn(); - this.mockMvc.perform(asyncDispatch(mvcResult)) - .andExpect(status().isOk()) - .andExpect(content().string("Bob")); + this.mockMvc.perform(asyncDispatch(mvcResult)).andExpect(status().isOk()).andExpect(content().string("Bob")); } @RestController static class NameController { + @GetMapping("/name") public Callable name() { return () -> SecurityContextHolder.getContext().getAuthentication().getName(); } + } @EnableWebSecurity static class DefaultWithFilterChainConfig { + @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http.build(); } + } @Test public void getWhenDefaultFilterChainBeanThenAnonymousPermitted() throws Exception { this.spring.register(AuthorizeRequestsConfig.class, UserDetailsConfig.class, BaseController.class).autowire(); - this.mockMvc.perform(get("/")) - .andExpect(status().isOk()); + this.mockMvc.perform(get("/")).andExpect(status().isOk()); } @EnableWebSecurity static class AuthorizeRequestsConfig { + @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - return http - .authorizeRequests(authorize -> authorize - .anyRequest().permitAll() - ) - .build(); + return http.authorizeRequests(authorize -> authorize.anyRequest().permitAll()).build(); } + } @Test @@ -159,13 +156,9 @@ public class HttpSecurityConfigurationTests { MockHttpSession session = new MockHttpSession(); String sessionId = session.getId(); - MvcResult result = - this.mockMvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .session(session) - .with(csrf())) - .andReturn(); + MvcResult result = this.mockMvc.perform( + post("/login").param("username", "user").param("password", "password").session(session).with(csrf())) + .andReturn(); assertThat(result.getRequest().getSession(false).getId()).isNotEqualTo(sessionId); } @@ -174,15 +167,11 @@ public class HttpSecurityConfigurationTests { public void authenticateWhenDefaultFilterChainBeanThenRedirectsToSavedRequest() throws Exception { this.spring.register(SecurityEnabledConfig.class, UserDetailsConfig.class).autowire(); - MockHttpSession session = (MockHttpSession) - this.mockMvc.perform(get("/messages")) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mockMvc.perform(get("/messages")).andReturn().getRequest() + .getSession(); - this.mockMvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .session(session) - .with(csrf())) + this.mockMvc.perform( + post("/login").param("username", "user").param("password", "password").session(session).with(csrf())) .andExpect(redirectedUrl("http://localhost/messages")); } @@ -190,8 +179,9 @@ public class HttpSecurityConfigurationTests { public void authenticateWhenDefaultFilterChainBeanThenRolePrefixIsSet() throws Exception { this.spring.register(SecurityEnabledConfig.class, UserDetailsConfig.class, UserController.class).autowire(); - this.mockMvc.perform(get("/user") - .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + this.mockMvc + .perform(get("/user") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) .andExpect(status().isOk()); } @@ -199,50 +189,51 @@ public class HttpSecurityConfigurationTests { public void loginWhenUsingDefaultsThenDefaultLoginPageGenerated() throws Exception { this.spring.register(SecurityEnabledConfig.class).autowire(); - this.mockMvc.perform(get("/login")) - .andExpect(status().isOk()); + this.mockMvc.perform(get("/login")).andExpect(status().isOk()); } @EnableWebSecurity static class SecurityEnabledConfig { + @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - return http - .authorizeRequests(authorize -> authorize - .anyRequest().authenticated() - ) - .formLogin(withDefaults()) + return http.authorizeRequests(authorize -> authorize.anyRequest().authenticated()).formLogin(withDefaults()) .build(); } + } @Configuration static class UserDetailsConfig { + @Bean public UserDetailsService userDetailsService() { - UserDetails user = User.withDefaultPasswordEncoder() - .username("user") - .password("password") - .roles("USER") + UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("USER") .build(); return new InMemoryUserDetailsManager(user); } + } @RestController static class BaseController { + @GetMapping("/") public void index() { } + } @RestController static class UserController { + @GetMapping("/user") public void user(HttpServletRequest request) { if (!request.isUserInRole("USER")) { throw new AccessDeniedException("This resource is only available to users"); } } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfigurationTests.java index 48eb3fd45d..f9fe77d875 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfigurationTests.java @@ -64,6 +64,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Joe Grandja */ public class OAuth2ClientConfigurationTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -78,14 +79,14 @@ public class OAuth2ClientConfigurationTests { ClientRegistrationRepository clientRegistrationRepository = mock(ClientRegistrationRepository.class); ClientRegistration clientRegistration = clientRegistration().registrationId(clientRegistrationId).build(); - when(clientRegistrationRepository.findByRegistrationId(eq(clientRegistrationId))).thenReturn(clientRegistration); + when(clientRegistrationRepository.findByRegistrationId(eq(clientRegistrationId))) + .thenReturn(clientRegistration); OAuth2AuthorizedClientRepository authorizedClientRepository = mock(OAuth2AuthorizedClientRepository.class); OAuth2AuthorizedClient authorizedClient = mock(OAuth2AuthorizedClient.class); when(authorizedClient.getClientRegistration()).thenReturn(clientRegistration); - when(authorizedClientRepository.loadAuthorizedClient( - eq(clientRegistrationId), eq(authentication), any(HttpServletRequest.class))) - .thenReturn(authorizedClient); + when(authorizedClientRepository.loadAuthorizedClient(eq(clientRegistrationId), eq(authentication), + any(HttpServletRequest.class))).thenReturn(authorizedClient); OAuth2AccessToken accessToken = mock(OAuth2AccessToken.class); when(authorizedClient.getAccessToken()).thenReturn(accessToken); @@ -97,14 +98,14 @@ public class OAuth2ClientConfigurationTests { OAuth2AuthorizedClientArgumentResolverConfig.ACCESS_TOKEN_RESPONSE_CLIENT = accessTokenResponseClient; this.spring.register(OAuth2AuthorizedClientArgumentResolverConfig.class).autowire(); - this.mockMvc.perform(get("/authorized-client").with(authentication(authentication))) - .andExpect(status().isOk()) + this.mockMvc.perform(get("/authorized-client").with(authentication(authentication))).andExpect(status().isOk()) .andExpect(content().string("resolved")); verifyZeroInteractions(accessTokenResponseClient); } @Test - public void requestWhenAuthorizedClientNotFoundAndClientCredentialsThenTokenResponseClientIsUsed() throws Exception { + public void requestWhenAuthorizedClientNotFoundAndClientCredentialsThenTokenResponseClientIsUsed() + throws Exception { String clientRegistrationId = "client1"; String principalName = "user1"; TestingAuthenticationToken authentication = new TestingAuthenticationToken(principalName, "password"); @@ -117,9 +118,7 @@ public class OAuth2ClientConfigurationTests { when(clientRegistrationRepository.findByRegistrationId(clientRegistrationId)).thenReturn(clientRegistration); OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("access-token-1234") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(300) - .build(); + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(300).build(); when(accessTokenResponseClient.getTokenResponse(any(OAuth2ClientCredentialsGrantRequest.class))) .thenReturn(accessTokenResponse); @@ -128,8 +127,7 @@ public class OAuth2ClientConfigurationTests { OAuth2AuthorizedClientArgumentResolverConfig.ACCESS_TOKEN_RESPONSE_CLIENT = accessTokenResponseClient; this.spring.register(OAuth2AuthorizedClientArgumentResolverConfig.class).autowire(); - this.mockMvc.perform(get("/authorized-client").with(authentication(authentication))) - .andExpect(status().isOk()) + this.mockMvc.perform(get("/authorized-client").with(authentication(authentication))).andExpect(status().isOk()) .andExpect(content().string("resolved")); verify(accessTokenResponseClient, times(1)).getTokenResponse(any(OAuth2ClientCredentialsGrantRequest.class)); } @@ -137,6 +135,7 @@ public class OAuth2ClientConfigurationTests { @EnableWebMvc @EnableWebSecurity static class OAuth2AuthorizedClientArgumentResolverConfig extends WebSecurityConfigurerAdapter { + static ClientRegistrationRepository CLIENT_REGISTRATION_REPOSITORY; static OAuth2AuthorizedClientRepository AUTHORIZED_CLIENT_REPOSITORY; static OAuth2AccessTokenResponseClient ACCESS_TOKEN_RESPONSE_CLIENT; @@ -149,9 +148,11 @@ public class OAuth2ClientConfigurationTests { public class Controller { @GetMapping("/authorized-client") - public String authorizedClient(@RegisteredOAuth2AuthorizedClient("client1") OAuth2AuthorizedClient authorizedClient) { + public String authorizedClient( + @RegisteredOAuth2AuthorizedClient("client1") OAuth2AuthorizedClient authorizedClient) { return authorizedClient != null ? "resolved" : "not-resolved"; } + } @Bean @@ -168,15 +169,18 @@ public class OAuth2ClientConfigurationTests { public OAuth2AccessTokenResponseClient accessTokenResponseClient() { return ACCESS_TOKEN_RESPONSE_CLIENT; } + } // gh-5321 @Test public void loadContextWhenOAuth2AuthorizedClientRepositoryRegisteredTwiceThenThrowNoUniqueBeanDefinitionException() { - assertThatThrownBy(() -> this.spring.register(OAuth2AuthorizedClientRepositoryRegisteredTwiceConfig.class).autowire()) - .hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class) - .hasMessageContaining("Expected single matching bean of type '" + OAuth2AuthorizedClientRepository.class.getName() + - "' but found 2: authorizedClientRepository1,authorizedClientRepository2"); + assertThatThrownBy( + () -> this.spring.register(OAuth2AuthorizedClientRepositoryRegisteredTwiceConfig.class).autowire()) + .hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class) + .hasMessageContaining("Expected single matching bean of type '" + + OAuth2AuthorizedClientRepository.class.getName() + + "' but found 2: authorizedClientRepository1,authorizedClientRepository2"); } @EnableWebMvc @@ -213,13 +217,14 @@ public class OAuth2ClientConfigurationTests { public OAuth2AccessTokenResponseClient accessTokenResponseClient() { return mock(OAuth2AccessTokenResponseClient.class); } + } @Test public void loadContextWhenClientRegistrationRepositoryNotRegisteredThenThrowNoSuchBeanDefinitionException() { assertThatThrownBy(() -> this.spring.register(ClientRegistrationRepositoryNotRegisteredConfig.class).autowire()) - .hasRootCauseInstanceOf(NoSuchBeanDefinitionException.class) - .hasMessageContaining("No qualifying bean of type '" + ClientRegistrationRepository.class.getName() + "' available"); + .hasRootCauseInstanceOf(NoSuchBeanDefinitionException.class).hasMessageContaining( + "No qualifying bean of type '" + ClientRegistrationRepository.class.getName() + "' available"); } @EnableWebMvc @@ -236,13 +241,14 @@ public class OAuth2ClientConfigurationTests { .oauth2Login(); // @formatter:on } + } @Test public void loadContextWhenClientRegistrationRepositoryRegisteredTwiceThenThrowNoUniqueBeanDefinitionException() { - assertThatThrownBy(() -> this.spring.register(ClientRegistrationRepositoryRegisteredTwiceConfig.class).autowire()) - .hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class) - .hasMessageContaining("expected single matching bean but found 2: clientRegistrationRepository1,clientRegistrationRepository2"); + assertThatThrownBy(() -> this.spring.register(ClientRegistrationRepositoryRegisteredTwiceConfig.class) + .autowire()).hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class).hasMessageContaining( + "expected single matching bean but found 2: clientRegistrationRepository1,clientRegistrationRepository2"); } @EnableWebMvc @@ -279,13 +285,14 @@ public class OAuth2ClientConfigurationTests { public OAuth2AccessTokenResponseClient accessTokenResponseClient() { return mock(OAuth2AccessTokenResponseClient.class); } + } @Test public void loadContextWhenAccessTokenResponseClientRegisteredTwiceThenThrowNoUniqueBeanDefinitionException() { assertThatThrownBy(() -> this.spring.register(AccessTokenResponseClientRegisteredTwiceConfig.class).autowire()) - .hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class) - .hasMessageContaining("expected single matching bean but found 2: accessTokenResponseClient1,accessTokenResponseClient2"); + .hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class).hasMessageContaining( + "expected single matching bean but found 2: accessTokenResponseClient1,accessTokenResponseClient2"); } @EnableWebMvc @@ -322,6 +329,7 @@ public class OAuth2ClientConfigurationTests { public OAuth2AccessTokenResponseClient accessTokenResponseClient2() { return mock(OAuth2AccessTokenResponseClient.class); } + } // gh-8700 @@ -336,8 +344,8 @@ public class OAuth2ClientConfigurationTests { OAuth2AuthorizedClientManager authorizedClientManager = mock(OAuth2AuthorizedClientManager.class); ClientRegistration clientRegistration = clientRegistration().registrationId(clientRegistrationId).build(); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - clientRegistration, principalName, TestOAuth2AccessTokens.noScopes()); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(clientRegistration, principalName, + TestOAuth2AccessTokens.noScopes()); when(authorizedClientManager.authorize(any())).thenReturn(authorizedClient); @@ -346,8 +354,7 @@ public class OAuth2ClientConfigurationTests { OAuth2AuthorizedClientManagerRegisteredConfig.AUTHORIZED_CLIENT_MANAGER = authorizedClientManager; this.spring.register(OAuth2AuthorizedClientManagerRegisteredConfig.class).autowire(); - this.mockMvc.perform(get("/authorized-client").with(authentication(authentication))) - .andExpect(status().isOk()) + this.mockMvc.perform(get("/authorized-client").with(authentication(authentication))).andExpect(status().isOk()) .andExpect(content().string("resolved")); verify(authorizedClientManager).authorize(any()); @@ -358,6 +365,7 @@ public class OAuth2ClientConfigurationTests { @EnableWebMvc @EnableWebSecurity static class OAuth2AuthorizedClientManagerRegisteredConfig extends WebSecurityConfigurerAdapter { + static ClientRegistrationRepository CLIENT_REGISTRATION_REPOSITORY; static OAuth2AuthorizedClientRepository AUTHORIZED_CLIENT_REPOSITORY; static OAuth2AuthorizedClientManager AUTHORIZED_CLIENT_MANAGER; @@ -370,9 +378,11 @@ public class OAuth2ClientConfigurationTests { public class Controller { @GetMapping("/authorized-client") - public String authorizedClient(@RegisteredOAuth2AuthorizedClient("client1") OAuth2AuthorizedClient authorizedClient) { + public String authorizedClient( + @RegisteredOAuth2AuthorizedClient("client1") OAuth2AuthorizedClient authorizedClient) { return authorizedClient != null ? "resolved" : "not-resolved"; } + } @Bean @@ -389,5 +399,7 @@ public class OAuth2ClientConfigurationTests { public OAuth2AuthorizedClientManager authorizedClientManager() { return AUTHORIZED_CLIENT_MANAGER; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/Sec2515Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/Sec2515Tests.java index 845488117c..1b536a4fe6 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/Sec2515Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/Sec2515Tests.java @@ -34,6 +34,7 @@ import static org.mockito.Mockito.mock; * @author Joe Grandja */ public class Sec2515Tests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -51,6 +52,7 @@ public class Sec2515Tests { public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } + } @Test(expected = FatalBeanException.class) @@ -62,10 +64,11 @@ public class Sec2515Tests { static class CustomBeanNameStackOverflowSecurityConfig extends WebSecurityConfigurerAdapter { @Override - @Bean(name="custom") + @Bean(name = "custom") public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } + } // SEC-2549 @@ -73,7 +76,8 @@ public class Sec2515Tests { public void loadConfigWhenChildClassLoaderSetThenContextLoads() { CanLoadWithChildConfig.AUTHENTICATION_MANAGER = mock(AuthenticationManager.class); this.spring.register(CanLoadWithChildConfig.class); - AnnotationConfigWebApplicationContext context = (AnnotationConfigWebApplicationContext) this.spring.getContext(); + AnnotationConfigWebApplicationContext context = (AnnotationConfigWebApplicationContext) this.spring + .getContext(); context.setClassLoader(new URLClassLoader(new URL[0], context.getClassLoader())); this.spring.autowire(); @@ -82,12 +86,14 @@ public class Sec2515Tests { @EnableWebSecurity static class CanLoadWithChildConfig extends WebSecurityConfigurerAdapter { + static AuthenticationManager AUTHENTICATION_MANAGER; @Bean public AuthenticationManager authenticationManager() { return AUTHENTICATION_MANAGER; } + } // SEC-2515 @@ -109,5 +115,7 @@ public class Sec2515Tests { protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication(); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfigurationResourceServerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfigurationResourceServerTests.java index 23e84c88b9..6b4d806e1e 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfigurationResourceServerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfigurationResourceServerTests.java @@ -44,11 +44,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * Tests for applications of {@link SecurityReactorContextConfiguration} in resource servers. + * Tests for applications of {@link SecurityReactorContextConfiguration} in resource + * servers. * * @author Josh Cummings */ public class SecurityReactorContextConfigurationResourceServerTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -61,9 +63,7 @@ public class SecurityReactorContextConfigurationResourceServerTests { BearerTokenAuthentication authentication = bearer(); this.spring.register(BearerFilterConfig.class, WebServerConfig.class, Controller.class).autowire(); - this.mockMvc.perform(get("/token") - .with(authentication(authentication))) - .andExpect(status().isOk()) + this.mockMvc.perform(get("/token").with(authentication(authentication))).andExpect(status().isOk()) .andExpect(content().string("Bearer token")); } @@ -73,30 +73,28 @@ public class SecurityReactorContextConfigurationResourceServerTests { BearerTokenAuthentication authentication = bearer(); this.spring.register(BearerFilterlessConfig.class, WebServerConfig.class, Controller.class).autowire(); - this.mockMvc.perform(get("/token") - .with(authentication(authentication))) - .andExpect(status().isOk()) + this.mockMvc.perform(get("/token").with(authentication(authentication))).andExpect(status().isOk()) .andExpect(content().string("")); } - @EnableWebSecurity static class BearerFilterConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { } @Bean WebClient rest() { - ServletBearerExchangeFilterFunction bearer = - new ServletBearerExchangeFilterFunction(); - return WebClient.builder() - .filter(bearer).build(); + ServletBearerExchangeFilterFunction bearer = new ServletBearerExchangeFilterFunction(); + return WebClient.builder().filter(bearer).build(); } + } @EnableWebSecurity static class BearerFilterlessConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { } @@ -105,35 +103,33 @@ public class SecurityReactorContextConfigurationResourceServerTests { WebClient rest() { return WebClient.create(); } + } @RestController static class Controller { + private final WebClient rest; + private final String uri; @Autowired - Controller(MockWebServer server, WebClient rest) { + Controller(MockWebServer server, WebClient rest) { this.uri = server.url("/").toString(); this.rest = rest; } @GetMapping("/token") public String token() { - return this.rest.get() - .uri(this.uri) - .retrieve() - .bodyToMono(String.class) - .flatMap(result -> this.rest.get() - .uri(this.uri) - .retrieve() - .bodyToMono(String.class)) - .block(); + return this.rest.get().uri(this.uri).retrieve().bodyToMono(String.class) + .flatMap(result -> this.rest.get().uri(this.uri).retrieve().bodyToMono(String.class)).block(); } + } @Configuration static class WebServerConfig { + private final MockWebServer server = new MockWebServer(); @Bean @@ -147,6 +143,7 @@ public class SecurityReactorContextConfigurationResourceServerTests { void shutdown() throws Exception { this.server.shutdown(); } + } static class AuthorizationHeaderDispatcher extends Dispatcher { @@ -161,5 +158,7 @@ public class SecurityReactorContextConfigurationResourceServerTests { } return response.setBody(header); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfigurationTests.java index 11d8317dde..daadc8d6b5 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfigurationTests.java @@ -59,11 +59,14 @@ import static org.springframework.security.config.annotation.web.configuration.S * @since 5.2 */ public class SecurityReactorContextConfigurationTests { + private MockHttpServletRequest servletRequest; + private MockHttpServletResponse servletResponse; + private Authentication authentication; - private SecurityReactorContextConfiguration.SecurityReactorContextSubscriberRegistrar subscriberRegistrar = - new SecurityReactorContextConfiguration.SecurityReactorContextSubscriberRegistrar(); + + private SecurityReactorContextConfiguration.SecurityReactorContextSubscriberRegistrar subscriberRegistrar = new SecurityReactorContextConfiguration.SecurityReactorContextSubscriberRegistrar(); @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -90,14 +93,15 @@ public class SecurityReactorContextConfigurationTests { return context; } }; - CoreSubscriber resultSubscriber = this.subscriberRegistrar.createSubscriberIfNecessary(originalSubscriber); + CoreSubscriber resultSubscriber = this.subscriberRegistrar + .createSubscriberIfNecessary(originalSubscriber); assertThat(resultSubscriber).isSameAs(originalSubscriber); } @Test public void createSubscriberIfNecessaryWhenWebSecurityContextAvailableThenCreateWithParentContext() { - RequestContextHolder.setRequestAttributes( - new ServletRequestAttributes(this.servletRequest, this.servletResponse)); + RequestContextHolder + .setRequestAttributes(new ServletRequestAttributes(this.servletRequest, this.servletResponse)); SecurityContextHolder.getContext().setAuthentication(this.authentication); String testKey = "test_key"; @@ -116,16 +120,15 @@ public class SecurityReactorContextConfigurationTests { assertThat(resultContext.getOrEmpty(testKey)).hasValue(testValue); Map securityContextAttributes = resultContext.getOrDefault(SECURITY_CONTEXT_ATTRIBUTES, null); assertThat(securityContextAttributes).hasSize(3); - assertThat(securityContextAttributes).contains( - entry(HttpServletRequest.class, this.servletRequest), + assertThat(securityContextAttributes).contains(entry(HttpServletRequest.class, this.servletRequest), entry(HttpServletResponse.class, this.servletResponse), entry(Authentication.class, this.authentication)); } @Test public void createSubscriberIfNecessaryWhenParentContextContainsSecurityContextAttributesThenUseParentContext() { - RequestContextHolder.setRequestAttributes( - new ServletRequestAttributes(this.servletRequest, this.servletResponse)); + RequestContextHolder + .setRequestAttributes(new ServletRequestAttributes(this.servletRequest, this.servletResponse)); SecurityContextHolder.getContext().setAuthentication(this.authentication); Context parentContext = Context.of(SECURITY_CONTEXT_ATTRIBUTES, new HashMap<>()); @@ -143,76 +146,75 @@ public class SecurityReactorContextConfigurationTests { @Test public void createSubscriberIfNecessaryWhenNotServletRequestAttributesThenStillCreate() { - RequestContextHolder.setRequestAttributes( - new RequestAttributes() { - @Override - public Object getAttribute(String name, int scope) { - return null; - } + RequestContextHolder.setRequestAttributes(new RequestAttributes() { + @Override + public Object getAttribute(String name, int scope) { + return null; + } - @Override - public void setAttribute(String name, Object value, int scope) { - } + @Override + public void setAttribute(String name, Object value, int scope) { + } - @Override - public void removeAttribute(String name, int scope) { - } + @Override + public void removeAttribute(String name, int scope) { + } - @Override - public String[] getAttributeNames(int scope) { - return new String[0]; - } + @Override + public String[] getAttributeNames(int scope) { + return new String[0]; + } - @Override - public void registerDestructionCallback(String name, Runnable callback, int scope) { - } + @Override + public void registerDestructionCallback(String name, Runnable callback, int scope) { + } - @Override - public Object resolveReference(String key) { - return null; - } + @Override + public Object resolveReference(String key) { + return null; + } - @Override - public String getSessionId() { - return null; - } + @Override + public String getSessionId() { + return null; + } - @Override - public Object getSessionMutex() { - return null; - } - }); + @Override + public Object getSessionMutex() { + return null; + } + }); - CoreSubscriber subscriber = this.subscriberRegistrar.createSubscriberIfNecessary(Operators.emptySubscriber()); + CoreSubscriber subscriber = this.subscriberRegistrar + .createSubscriberIfNecessary(Operators.emptySubscriber()); assertThat(subscriber).isInstanceOf(SecurityReactorContextConfiguration.SecurityReactorContextSubscriber.class); } @Test public void createPublisherWhenLastOperatorAddedThenSecurityContextAttributesAvailable() { - // Trigger the importing of SecurityReactorContextConfiguration via OAuth2ImportSelector + // Trigger the importing of SecurityReactorContextConfiguration via + // OAuth2ImportSelector this.spring.register(SecurityConfig.class).autowire(); // Setup for SecurityReactorContextSubscriberRegistrar - RequestContextHolder.setRequestAttributes( - new ServletRequestAttributes(this.servletRequest, this.servletResponse)); + RequestContextHolder + .setRequestAttributes(new ServletRequestAttributes(this.servletRequest, this.servletResponse)); SecurityContextHolder.getContext().setAuthentication(this.authentication); ClientResponse clientResponseOk = ClientResponse.create(HttpStatus.OK).build(); - ExchangeFilterFunction filter = (req, next) -> - Mono.subscriberContext() - .filter(ctx -> ctx.hasKey(SECURITY_CONTEXT_ATTRIBUTES)) - .map(ctx -> ctx.get(SECURITY_CONTEXT_ATTRIBUTES)) - .cast(Map.class) - .map(attributes -> { - if (attributes.containsKey(HttpServletRequest.class) && - attributes.containsKey(HttpServletResponse.class) && - attributes.containsKey(Authentication.class)) { - return clientResponseOk; - } else { - return ClientResponse.create(HttpStatus.NOT_FOUND).build(); - } - }); + ExchangeFilterFunction filter = (req, next) -> Mono.subscriberContext() + .filter(ctx -> ctx.hasKey(SECURITY_CONTEXT_ATTRIBUTES)).map(ctx -> ctx.get(SECURITY_CONTEXT_ATTRIBUTES)) + .cast(Map.class).map(attributes -> { + if (attributes.containsKey(HttpServletRequest.class) + && attributes.containsKey(HttpServletResponse.class) + && attributes.containsKey(Authentication.class)) { + return clientResponseOk; + } + else { + return ClientResponse.create(HttpStatus.NOT_FOUND).build(); + } + }); ClientRequest clientRequest = ClientRequest.create(GET, URI.create("https://example.com")).build(); MockExchangeFunction exchange = new MockExchangeFunction(); @@ -225,11 +227,8 @@ public class SecurityReactorContextConfigurationTests { Mono clientResponseMono = filter.filter(clientRequest, exchange) .flatMap(response -> filter.filter(clientRequest, exchange)); - StepVerifier.create(clientResponseMono) - .expectAccessibleContext() - .contains(SECURITY_CONTEXT_ATTRIBUTES, expectedContextAttributes) - .then() - .expectNext(clientResponseOk) + StepVerifier.create(clientResponseMono).expectAccessibleContext() + .contains(SECURITY_CONTEXT_ATTRIBUTES, expectedContextAttributes).then().expectNext(clientResponseOk) .verifyComplete(); } @@ -239,5 +238,7 @@ public class SecurityReactorContextConfigurationTests { @Override protected void configure(HttpSecurity http) throws Exception { } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfigurationTests.java index 9d714433e9..37cac4700b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfigurationTests.java @@ -75,8 +75,7 @@ public class WebMvcSecurityConfigurationTests { @Test public void authenticationPrincipalResolved() throws Exception { - mockMvc.perform(get("/authentication-principal")) - .andExpect(assertResult(authentication.getPrincipal())) + mockMvc.perform(get("/authentication-principal")).andExpect(assertResult(authentication.getPrincipal())) .andExpect(view().name("authentication-principal-view")); } @@ -90,8 +89,7 @@ public class WebMvcSecurityConfigurationTests { @Test public void csrfToken() throws Exception { CsrfToken csrfToken = new DefaultCsrfToken("headerName", "paramName", "token"); - MockHttpServletRequestBuilder request = get("/csrf").requestAttr( - CsrfToken.class.getName(), csrfToken); + MockHttpServletRequestBuilder request = get("/csrf").requestAttr(CsrfToken.class.getName(), csrfToken); mockMvc.perform(request).andExpect(assertResult(csrfToken)); } @@ -104,32 +102,33 @@ public class WebMvcSecurityConfigurationTests { static class TestController { @RequestMapping("/authentication-principal") - public ModelAndView authenticationPrincipal( - @AuthenticationPrincipal String principal) { + public ModelAndView authenticationPrincipal(@AuthenticationPrincipal String principal) { return new ModelAndView("authentication-principal-view", "result", principal); } @RequestMapping("/deprecated-authentication-principal") public ModelAndView deprecatedAuthenticationPrincipal( @org.springframework.security.web.bind.annotation.AuthenticationPrincipal String principal) { - return new ModelAndView("deprecated-authentication-principal-view", "result", - principal); + return new ModelAndView("deprecated-authentication-principal-view", "result", principal); } @RequestMapping("/csrf") public ModelAndView csrf(CsrfToken token) { return new ModelAndView("view", "result", token); } + } @Configuration @EnableWebMvc @EnableWebSecurity static class Config { + @Bean public TestController testController() { return new TestController(); } + } } \ No newline at end of file diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java index 6f27f16b18..d661a39575 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java @@ -74,6 +74,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Evgeniy Cheban */ public class WebSecurityConfigurationTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -118,11 +119,10 @@ public class WebSecurityConfigurationTests { @Configuration @Order(1) static class WebConfigurer1 extends WebSecurityConfigurerAdapter { + @Override public void configure(WebSecurity web) { - web - .ignoring() - .antMatchers("/ignore1", "/ignore2"); + web.ignoring().antMatchers("/ignore1", "/ignore2"); } @Override @@ -134,11 +134,13 @@ public class WebSecurityConfigurationTests { .anyRequest().hasRole("1"); // @formatter:on } + } @Configuration @Order(2) static class WebConfigurer2 extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -148,11 +150,13 @@ public class WebSecurityConfigurationTests { .anyRequest().hasRole("2"); // @formatter:on } + } @Configuration @Order(3) static class WebConfigurer3 extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -162,6 +166,7 @@ public class WebSecurityConfigurationTests { .anyRequest().hasRole("3"); // @formatter:on } + } @Configuration @@ -175,7 +180,9 @@ public class WebSecurityConfigurationTests { .anyRequest().hasRole("4"); // @formatter:on } + } + } @Test @@ -208,44 +215,29 @@ public class WebSecurityConfigurationTests { @Order(1) @Bean SecurityFilterChain filterChain1(HttpSecurity http) throws Exception { - return http - .antMatcher("/role1/**") - .authorizeRequests(authorize -> authorize - .anyRequest().hasRole("1") - ) + return http.antMatcher("/role1/**").authorizeRequests(authorize -> authorize.anyRequest().hasRole("1")) .build(); } @Order(2) @Bean SecurityFilterChain filterChain2(HttpSecurity http) throws Exception { - return http - .antMatcher("/role2/**") - .authorizeRequests(authorize -> authorize - .anyRequest().hasRole("2") - ) + return http.antMatcher("/role2/**").authorizeRequests(authorize -> authorize.anyRequest().hasRole("2")) .build(); } @Order(3) @Bean SecurityFilterChain filterChain3(HttpSecurity http) throws Exception { - return http - .antMatcher("/role3/**") - .authorizeRequests(authorize -> authorize - .anyRequest().hasRole("3") - ) + return http.antMatcher("/role3/**").authorizeRequests(authorize -> authorize.anyRequest().hasRole("3")) .build(); } @Bean SecurityFilterChain filterChain4(HttpSecurity http) throws Exception { - return http - .authorizeRequests(authorize -> authorize - .anyRequest().hasRole("4") - ) - .build(); + return http.authorizeRequests(authorize -> authorize.anyRequest().hasRole("4")).build(); } + } @Test @@ -253,9 +245,9 @@ public class WebSecurityConfigurationTests { Throwable thrown = catchThrowable(() -> this.spring.register(DuplicateOrderConfig.class).autowire()); assertThat(thrown).isInstanceOf(BeanCreationException.class) - .hasMessageContaining("@Order on WebSecurityConfigurers must be unique") - .hasMessageContaining(DuplicateOrderConfig.WebConfigurer1.class.getName()) - .hasMessageContaining(DuplicateOrderConfig.WebConfigurer2.class.getName()); + .hasMessageContaining("@Order on WebSecurityConfigurers must be unique") + .hasMessageContaining(DuplicateOrderConfig.WebConfigurer1.class.getName()) + .hasMessageContaining(DuplicateOrderConfig.WebConfigurer2.class.getName()); } @EnableWebSecurity @@ -264,6 +256,7 @@ public class WebSecurityConfigurationTests { @Configuration static class WebConfigurer1 extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -273,10 +266,12 @@ public class WebSecurityConfigurationTests { .anyRequest().hasRole("1"); // @formatter:on } + } @Configuration static class WebConfigurer2 extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -286,7 +281,9 @@ public class WebSecurityConfigurationTests { .anyRequest().hasRole("2"); // @formatter:on } + } + } @Test @@ -296,32 +293,36 @@ public class WebSecurityConfigurationTests { this.spring.register(PrivilegeEvaluatorConfigurerAdapterConfig.class).autowire(); assertThat(this.spring.getContext().getBean(WebInvocationPrivilegeEvaluator.class)) - .isSameAs(PrivilegeEvaluatorConfigurerAdapterConfig.PRIVILEGE_EVALUATOR); + .isSameAs(PrivilegeEvaluatorConfigurerAdapterConfig.PRIVILEGE_EVALUATOR); } @EnableWebSecurity static class PrivilegeEvaluatorConfigurerAdapterConfig extends WebSecurityConfigurerAdapter { + static WebInvocationPrivilegeEvaluator PRIVILEGE_EVALUATOR; @Override public void configure(WebSecurity web) { web.privilegeEvaluator(PRIVILEGE_EVALUATOR); } + } @Test public void loadConfigWhenSecurityExpressionHandlerSetThenIsRegistered() { WebSecurityExpressionHandlerConfig.EXPRESSION_HANDLER = mock(SecurityExpressionHandler.class); - when(WebSecurityExpressionHandlerConfig.EXPRESSION_HANDLER.getExpressionParser()).thenReturn(mock(ExpressionParser.class)); + when(WebSecurityExpressionHandlerConfig.EXPRESSION_HANDLER.getExpressionParser()) + .thenReturn(mock(ExpressionParser.class)); this.spring.register(WebSecurityExpressionHandlerConfig.class).autowire(); assertThat(this.spring.getContext().getBean(SecurityExpressionHandler.class)) - .isSameAs(WebSecurityExpressionHandlerConfig.EXPRESSION_HANDLER); + .isSameAs(WebSecurityExpressionHandlerConfig.EXPRESSION_HANDLER); } @EnableWebSecurity static class WebSecurityExpressionHandlerConfig extends WebSecurityConfigurerAdapter { + static SecurityExpressionHandler EXPRESSION_HANDLER; @Override @@ -338,13 +339,13 @@ public class WebSecurityConfigurationTests { .expressionHandler(EXPRESSION_HANDLER); // @formatter:on } + } @Test public void loadConfigWhenSecurityExpressionHandlerIsNullThenException() { - Throwable thrown = catchThrowable(() -> - this.spring.register(NullWebSecurityExpressionHandlerConfig.class).autowire() - ); + Throwable thrown = catchThrowable( + () -> this.spring.register(NullWebSecurityExpressionHandlerConfig.class).autowire()); assertThat(thrown).isInstanceOf(BeanCreationException.class); assertThat(thrown).hasRootCauseExactlyInstanceOf(IllegalArgumentException.class); @@ -357,6 +358,7 @@ public class WebSecurityConfigurationTests { public void configure(WebSecurity web) { web.expressionHandler(null); } + } @Test @@ -364,11 +366,12 @@ public class WebSecurityConfigurationTests { this.spring.register(WebSecurityExpressionHandlerDefaultsConfig.class).autowire(); assertThat(this.spring.getContext().getBean(SecurityExpressionHandler.class)) - .isInstanceOf(DefaultWebSecurityExpressionHandler.class); + .isInstanceOf(DefaultWebSecurityExpressionHandler.class); } @EnableWebSecurity static class WebSecurityExpressionHandlerDefaultsConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -377,6 +380,7 @@ public class WebSecurityConfigurationTests { .anyRequest().authenticated(); // @formatter:on } + } @Test @@ -386,50 +390,53 @@ public class WebSecurityConfigurationTests { FilterInvocation invocation = new FilterInvocation(new MockHttpServletRequest("GET", ""), new MockHttpServletResponse(), new MockFilterChain()); - AbstractSecurityExpressionHandler handler = this.spring.getContext().getBean(AbstractSecurityExpressionHandler.class); + AbstractSecurityExpressionHandler handler = this.spring.getContext() + .getBean(AbstractSecurityExpressionHandler.class); EvaluationContext evaluationContext = handler.createEvaluationContext(authentication, invocation); - Expression expression = handler.getExpressionParser() - .parseExpression("hasRole('ROLE_USER')"); + Expression expression = handler.getExpressionParser().parseExpression("hasRole('ROLE_USER')"); boolean granted = expression.getValue(evaluationContext, Boolean.class); assertThat(granted).isTrue(); } @EnableWebSecurity static class WebSecurityExpressionHandlerRoleHierarchyBeanConfig extends WebSecurityConfigurerAdapter { + @Bean RoleHierarchy roleHierarchy() { RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER"); return roleHierarchy; } + } @Test public void securityExpressionHandlerWhenPermissionEvaluatorBeanThenPermissionEvaluatorUsed() { this.spring.register(WebSecurityExpressionHandlerPermissionEvaluatorBeanConfig.class).autowire(); TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "notused"); - FilterInvocation invocation = new FilterInvocation(new MockHttpServletRequest("GET", ""), new MockHttpServletResponse(), new MockFilterChain()); + FilterInvocation invocation = new FilterInvocation(new MockHttpServletRequest("GET", ""), + new MockHttpServletResponse(), new MockFilterChain()); - AbstractSecurityExpressionHandler handler = this.spring.getContext().getBean(AbstractSecurityExpressionHandler.class); + AbstractSecurityExpressionHandler handler = this.spring.getContext() + .getBean(AbstractSecurityExpressionHandler.class); EvaluationContext evaluationContext = handler.createEvaluationContext(authentication, invocation); - Expression expression = handler.getExpressionParser() - .parseExpression("hasPermission(#study,'DELETE')"); + Expression expression = handler.getExpressionParser().parseExpression("hasPermission(#study,'DELETE')"); boolean granted = expression.getValue(evaluationContext, Boolean.class); assertThat(granted).isTrue(); } @EnableWebSecurity static class WebSecurityExpressionHandlerPermissionEvaluatorBeanConfig extends WebSecurityConfigurerAdapter { + static final PermissionEvaluator PERMIT_ALL_PERMISSION_EVALUATOR = new PermissionEvaluator() { @Override - public boolean hasPermission(Authentication authentication, - Object targetDomainObject, Object permission) { + public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) { return true; } @Override - public boolean hasPermission(Authentication authentication, - Serializable targetId, String targetType, Object permission) { + public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, + Object permission) { return true; } }; @@ -438,6 +445,7 @@ public class WebSecurityConfigurationTests { public PermissionEvaluator permissionEvaluator() { return PERMIT_ALL_PERMISSION_EVALUATOR; } + } @Test @@ -445,11 +453,12 @@ public class WebSecurityConfigurationTests { this.spring.register(WebInvocationPrivilegeEvaluatorDefaultsConfig.class).autowire(); assertThat(this.spring.getContext().getBean(WebInvocationPrivilegeEvaluator.class)) - .isInstanceOf(DefaultWebInvocationPrivilegeEvaluator.class); + .isInstanceOf(DefaultWebInvocationPrivilegeEvaluator.class); } @EnableWebSecurity static class WebInvocationPrivilegeEvaluatorDefaultsConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -458,6 +467,7 @@ public class WebSecurityConfigurationTests { .anyRequest().authenticated(); // @formatter:on } + } @Test @@ -465,19 +475,17 @@ public class WebSecurityConfigurationTests { this.spring.register(AuthorizeRequestsFilterChainConfig.class).autowire(); assertThat(this.spring.getContext().getBean(WebInvocationPrivilegeEvaluator.class)) - .isInstanceOf(DefaultWebInvocationPrivilegeEvaluator.class); + .isInstanceOf(DefaultWebInvocationPrivilegeEvaluator.class); } @EnableWebSecurity static class AuthorizeRequestsFilterChainConfig { + @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - return http - .authorizeRequests(authorize -> authorize - .anyRequest().authenticated() - ) - .build(); + return http.authorizeRequests(authorize -> authorize.anyRequest().authenticated()).build(); } + } // SEC-2303 @@ -491,6 +499,7 @@ public class WebSecurityConfigurationTests { @EnableWebSecurity static class DefaultExpressionHandlerSetsBeanResolverConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -502,10 +511,12 @@ public class WebSecurityConfigurationTests { @RestController public class HomeController { + @GetMapping("/") public String home() { return "home"; } + } @Bean @@ -514,6 +525,7 @@ public class WebSecurityConfigurationTests { } static class MyBean { + public boolean deny() { return false; } @@ -521,7 +533,9 @@ public class WebSecurityConfigurationTests { public boolean grant() { return true; } + } + } @Rule @@ -545,14 +559,17 @@ public class WebSecurityConfigurationTests { @EnableWebSecurity static class ParentConfig extends WebSecurityConfigurerAdapter { + @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication(); } + } @EnableWebSecurity static class ChildConfig extends WebSecurityConfigurerAdapter { + } // SEC-2773 @@ -564,7 +581,8 @@ public class WebSecurityConfigurationTests { @Test public void loadConfigWhenBeanProxyingEnabledAndSubclassThenFilterChainsCreated() { - this.spring.register(GlobalAuthenticationWebSecurityConfigurerAdaptersConfig.class, SubclassConfig.class).autowire(); + this.spring.register(GlobalAuthenticationWebSecurityConfigurerAdaptersConfig.class, SubclassConfig.class) + .autowire(); FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class); List filterChains = filterChainProxy.getFilterChains(); @@ -574,19 +592,20 @@ public class WebSecurityConfigurationTests { @Configuration static class SubclassConfig extends WebSecurityConfiguration { + } @Import(AuthenticationTestConfiguration.class) @EnableGlobalAuthentication static class GlobalAuthenticationWebSecurityConfigurerAdaptersConfig { + @Configuration @Order(1) static class WebConfigurer1 extends WebSecurityConfigurerAdapter { + @Override public void configure(WebSecurity web) { - web - .ignoring() - .antMatchers("/ignore1", "/ignore2"); + web.ignoring().antMatchers("/ignore1", "/ignore2"); } @Override @@ -598,6 +617,7 @@ public class WebSecurityConfigurationTests { .anyRequest().anonymous(); // @formatter:on } + } @Configuration @@ -611,7 +631,9 @@ public class WebSecurityConfigurationTests { .anyRequest().authenticated(); // @formatter:on } + } + } @Test @@ -627,28 +649,25 @@ public class WebSecurityConfigurationTests { @EnableWebSecurity @Import(AuthenticationTestConfiguration.class) static class AdapterAndFilterChainConfig { + @Order(1) @Configuration static class WebConfigurer extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { - http - .antMatcher("/config/**") - .authorizeRequests(authorize -> authorize - .anyRequest().permitAll() - ); + http.antMatcher("/config/**").authorizeRequests(authorize -> authorize.anyRequest().permitAll()); } + } @Order(2) @Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - return http - .antMatcher("/filter/**") - .authorizeRequests(authorize -> authorize - .anyRequest().authenticated() - ) + return http.antMatcher("/filter/**").authorizeRequests(authorize -> authorize.anyRequest().authenticated()) .build(); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/sec2377/Sec2377Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/sec2377/Sec2377Tests.java index 59631f73b6..246fffe71b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/sec2377/Sec2377Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/sec2377/Sec2377Tests.java @@ -38,10 +38,10 @@ public class Sec2377Tests { public void refreshContextWhenParentAndChildRegisteredThenNoException() { this.parent.register(Sec2377AConfig.class).autowire(); - ConfigurableApplicationContext context = - this.child.register(Sec2377BConfig.class).getContext(); + ConfigurableApplicationContext context = this.child.register(Sec2377BConfig.class).getContext(); context.setParent(this.parent.getContext()); this.child.autowire(); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistryTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistryTests.java index f5f3e9f89b..9f175cf52b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistryTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistryTests.java @@ -29,6 +29,7 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.List; public class AbstractConfigAttributeRequestMatcherRegistryTests { + private ConcreteAbstractRequestMatcherMappingConfigurer registry; @Before @@ -37,7 +38,7 @@ public class AbstractConfigAttributeRequestMatcherRegistryTests { } @Test - public void testGetRequestMatcherIsTypeRegexMatcher(){ + public void testGetRequestMatcherIsTypeRegexMatcher() { List requestMatchers = registry.regexMatchers(HttpMethod.GET, "/a.*"); for (RequestMatcher requestMatcher : requestMatchers) { @@ -46,8 +47,8 @@ public class AbstractConfigAttributeRequestMatcherRegistryTests { } @Test - public void testRequestMatcherIsTypeRegexMatcher(){ - List requestMatchers = registry.regexMatchers( "/a.*"); + public void testRequestMatcherIsTypeRegexMatcher() { + List requestMatchers = registry.regexMatchers("/a.*"); for (RequestMatcher requestMatcher : requestMatchers) { assertThat(requestMatcher).isInstanceOf(RegexRequestMatcher.class); @@ -55,7 +56,7 @@ public class AbstractConfigAttributeRequestMatcherRegistryTests { } @Test - public void testGetRequestMatcherIsTypeAntPathRequestMatcher(){ + public void testGetRequestMatcherIsTypeAntPathRequestMatcher() { List requestMatchers = registry.antMatchers(HttpMethod.GET, "/a.*"); for (RequestMatcher requestMatcher : requestMatchers) { @@ -64,7 +65,7 @@ public class AbstractConfigAttributeRequestMatcherRegistryTests { } @Test - public void testRequestMatcherIsTypeAntPathRequestMatcher(){ + public void testRequestMatcherIsTypeAntPathRequestMatcher() { List requestMatchers = registry.antMatchers("/a.*"); for (RequestMatcher requestMatcher : requestMatchers) { @@ -72,7 +73,9 @@ public class AbstractConfigAttributeRequestMatcherRegistryTests { } } - static class ConcreteAbstractRequestMatcherMappingConfigurer extends AbstractConfigAttributeRequestMatcherRegistry> { + static class ConcreteAbstractRequestMatcherMappingConfigurer + extends AbstractConfigAttributeRequestMatcherRegistry> { + List decisionVoters() { return null; } @@ -88,5 +91,7 @@ public class AbstractConfigAttributeRequestMatcherRegistryTests { public List mvcMatchers(HttpMethod method, String... mvcPatterns) { return null; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.java index fca1d0ab8e..93b035ce64 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.java @@ -40,6 +40,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Josh Cummings */ public class AnonymousConfigurerTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -50,8 +51,7 @@ public class AnonymousConfigurerTests { public void requestWhenAnonymousTwiceInvokedThenDoesNotOverride() throws Exception { this.spring.register(InvokeTwiceDoesNotOverride.class, PrincipalController.class).autowire(); - this.mockMvc.perform(get("/")) - .andExpect(content().string("principal")); + this.mockMvc.perform(get("/")).andExpect(content().string("principal")); } @EnableWebSecurity @@ -69,14 +69,14 @@ public class AnonymousConfigurerTests { .anonymous(); // @formatter:on } + } @Test public void requestWhenAnonymousPrincipalInLambdaThenPrincipalUsed() throws Exception { this.spring.register(AnonymousPrincipalInLambdaConfig.class, PrincipalController.class).autowire(); - this.mockMvc.perform(get("/")) - .andExpect(content().string("principal")); + this.mockMvc.perform(get("/")).andExpect(content().string("principal")); } @EnableWebSecurity @@ -93,18 +93,19 @@ public class AnonymousConfigurerTests { ); // @formatter:on } + } @Test public void requestWhenAnonymousDisabledInLambdaThenRespondsWithForbidden() throws Exception { this.spring.register(AnonymousDisabledInLambdaConfig.class, PrincipalController.class).autowire(); - this.mockMvc.perform(get("/")) - .andExpect(status().isForbidden()); + this.mockMvc.perform(get("/")).andExpect(status().isForbidden()); } @EnableWebSecurity static class AnonymousDisabledInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -124,18 +125,19 @@ public class AnonymousConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test public void requestWhenAnonymousWithDefaultsInLambdaThenRespondsWithOk() throws Exception { this.spring.register(AnonymousWithDefaultsInLambdaConfig.class, PrincipalController.class).autowire(); - this.mockMvc.perform(get("/")) - .andExpect(status().isOk()); + this.mockMvc.perform(get("/")).andExpect(status().isOk()); } @EnableWebSecurity static class AnonymousWithDefaultsInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -155,13 +157,17 @@ public class AnonymousConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @RestController static class PrincipalController { + @GetMapping("/") String principal(@AuthenticationPrincipal String principal) { return principal; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java index d10ea89dce..f2388b2184 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java @@ -58,11 +58,15 @@ import static org.springframework.security.config.Customizer.withDefaults; * */ public class AuthorizeRequestsTests { + AnnotationConfigWebApplicationContext context; MockHttpServletRequest request; + MockHttpServletResponse response; + MockFilterChain chain; + MockServletContext servletContext; @Autowired @@ -98,6 +102,7 @@ public class AuthorizeRequestsTests { @EnableWebSecurity @Configuration static class AntMatchersNoPatternsConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -114,6 +119,7 @@ public class AuthorizeRequestsTests { .inMemoryAuthentication(); // @formatter:on } + } @Test @@ -129,6 +135,7 @@ public class AuthorizeRequestsTests { @EnableWebSecurity @Configuration static class AntMatchersNoPatternsInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -147,6 +154,7 @@ public class AuthorizeRequestsTests { .inMemoryAuthentication(); // @formatter:on } + } // SEC-2256 @@ -190,6 +198,7 @@ public class AuthorizeRequestsTests { @EnableWebSecurity @Configuration static class AntPatchersPathVariables extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -207,6 +216,7 @@ public class AuthorizeRequestsTests { .inMemoryAuthentication(); // @formatter:on } + } // gh-3786 @@ -231,6 +241,7 @@ public class AuthorizeRequestsTests { @EnableWebSecurity @Configuration static class AntMatchersPathVariablesCamelCaseVariables extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -248,6 +259,7 @@ public class AuthorizeRequestsTests { .inMemoryAuthentication(); // @formatter:on } + } // gh-3394 @@ -256,8 +268,10 @@ public class AuthorizeRequestsTests { loadConfig(RoleHiearchyConfig.class); SecurityContext securityContext = new SecurityContextImpl(); - securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("test", "notused", AuthorityUtils.createAuthorityList("ROLE_USER"))); - this.request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, securityContext); + securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("test", "notused", + AuthorityUtils.createAuthorityList("ROLE_USER"))); + this.request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, + securityContext); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); @@ -267,6 +281,7 @@ public class AuthorizeRequestsTests { @EnableWebSecurity @Configuration static class RoleHiearchyConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -290,6 +305,7 @@ public class AuthorizeRequestsTests { result.setHierarchy("ROLE_USER > ROLE_ADMIN"); return result; } + } @Test @@ -299,30 +315,28 @@ public class AuthorizeRequestsTests { this.request.setRequestURI("/path"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); this.request.setRequestURI("/path.html"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); this.request.setServletPath("/path/"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); } @EnableWebSecurity @Configuration @EnableWebMvc static class MvcMatcherConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -343,11 +357,14 @@ public class AuthorizeRequestsTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Test @@ -357,30 +374,28 @@ public class AuthorizeRequestsTests { this.request.setRequestURI("/path"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); this.request.setRequestURI("/path.html"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); this.request.setServletPath("/path/"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); } @EnableWebSecurity @Configuration @EnableWebMvc static class MvcMatcherInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -403,11 +418,14 @@ public class AuthorizeRequestsTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Test @@ -418,8 +436,7 @@ public class AuthorizeRequestsTests { this.request.setRequestURI("/spring/path"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); @@ -427,8 +444,7 @@ public class AuthorizeRequestsTests { this.request.setRequestURI("/spring/path.html"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); @@ -436,8 +452,7 @@ public class AuthorizeRequestsTests { this.request.setRequestURI("/spring/path/"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); @@ -460,6 +475,7 @@ public class AuthorizeRequestsTests { @Configuration @EnableWebMvc static class MvcMatcherServletPathConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -480,11 +496,14 @@ public class AuthorizeRequestsTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Test @@ -495,8 +514,7 @@ public class AuthorizeRequestsTests { this.request.setRequestURI("/spring/path"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); @@ -504,8 +522,7 @@ public class AuthorizeRequestsTests { this.request.setRequestURI("/spring/path.html"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); @@ -513,8 +530,7 @@ public class AuthorizeRequestsTests { this.request.setRequestURI("/spring/path/"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); @@ -537,6 +553,7 @@ public class AuthorizeRequestsTests { @Configuration @EnableWebMvc static class MvcMatcherServletPathInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -559,11 +576,14 @@ public class AuthorizeRequestsTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Test @@ -581,14 +601,14 @@ public class AuthorizeRequestsTests { this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); } @EnableWebSecurity @Configuration @EnableWebMvc static class MvcMatcherPathVariablesConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -609,11 +629,14 @@ public class AuthorizeRequestsTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Test @@ -631,14 +654,14 @@ public class AuthorizeRequestsTests { this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); } @EnableWebSecurity @Configuration @EnableWebMvc static class MvcMatcherPathVariablesInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -661,17 +684,21 @@ public class AuthorizeRequestsTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @EnableWebSecurity @Configuration @EnableWebMvc static class MvcMatcherPathServletPathRequiredConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -692,19 +719,24 @@ public class AuthorizeRequestsTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Configuration static class LegacyMvcMatchingConfig implements WebMvcConfigurer { + @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseSuffixPatternMatch(true); } + } public void loadConfig(Class... configs) { @@ -715,4 +747,5 @@ public class AuthorizeRequestsTests { this.context.getAutowireCapableBeanFactory().autowireBean(this); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java index c33682e716..64f867793c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java @@ -56,8 +56,7 @@ public class ChannelSecurityConfigurerTests { ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class); this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(InsecureChannelProcessor.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(InsecureChannelProcessor.class)); } @Test @@ -65,8 +64,7 @@ public class ChannelSecurityConfigurerTests { ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class); this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(SecureChannelProcessor.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(SecureChannelProcessor.class)); } @Test @@ -74,8 +72,7 @@ public class ChannelSecurityConfigurerTests { ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class); this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(ChannelDecisionManagerImpl.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(ChannelDecisionManagerImpl.class)); } @Test @@ -83,12 +80,12 @@ public class ChannelSecurityConfigurerTests { ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class); this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(ChannelProcessingFilter.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(ChannelProcessingFilter.class)); } @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor; @Override @@ -104,21 +101,23 @@ public class ChannelSecurityConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } @Test public void requiresChannelWhenInvokesTwiceThenUsesOriginalRequiresSecure() throws Exception { this.spring.register(DuplicateInvocationsDoesNotOverrideConfig.class).autowire(); - mvc.perform(get("/")) - .andExpect(redirectedUrl("https://localhost/")); + mvc.perform(get("/")).andExpect(redirectedUrl("https://localhost/")); } @EnableWebSecurity @@ -134,14 +133,14 @@ public class ChannelSecurityConfigurerTests { .requiresChannel(); // @formatter:on } + } @Test public void requestWhenRequiresChannelConfiguredInLambdaThenRedirectsToHttps() throws Exception { this.spring.register(RequiresChannelInLambdaConfig.class).autowire(); - mvc.perform(get("/")) - .andExpect(redirectedUrl("https://localhost/")); + mvc.perform(get("/")).andExpect(redirectedUrl("https://localhost/")); } @EnableWebSecurity @@ -157,5 +156,7 @@ public class ChannelSecurityConfigurerTests { ); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurerTests.java index b880b3ef5b..cdd731287e 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurerTests.java @@ -55,6 +55,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Eleftheria Stein */ public class CorsConfigurerTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -64,8 +65,8 @@ public class CorsConfigurerTests { @Test public void configureWhenNoMvcThenException() { assertThatThrownBy(() -> this.spring.register(DefaultCorsConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasMessageContaining("Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext"); + .isInstanceOf(BeanCreationException.class).hasMessageContaining( + "Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext"); } @EnableWebSecurity @@ -81,14 +82,14 @@ public class CorsConfigurerTests { .cors(); // @formatter:on } + } @Test public void getWhenCrossOriginAnnotationThenRespondsWithCorsHeaders() throws Exception { this.spring.register(MvcCorsConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ORIGIN, "https://example.com")) + this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com")) .andExpect(header().exists("Access-Control-Allow-Origin")) .andExpect(header().exists("X-Content-Type-Options")); } @@ -99,8 +100,7 @@ public class CorsConfigurerTests { this.mvc.perform(options("/") .header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name()) - .header(HttpHeaders.ORIGIN, "https://example.com")) - .andExpect(status().isOk()) + .header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk()) .andExpect(header().exists("Access-Control-Allow-Origin")) .andExpect(header().exists("X-Content-Type-Options")); } @@ -121,23 +121,23 @@ public class CorsConfigurerTests { } @RestController - @CrossOrigin(methods = { - RequestMethod.GET, RequestMethod.POST - }) + @CrossOrigin(methods = { RequestMethod.GET, RequestMethod.POST }) static class CorsController { + @RequestMapping("/") String hello() { return "Hello"; } + } + } @Test public void getWhenDefaultsInLambdaAndCrossOriginAnnotationThenRespondsWithCorsHeaders() throws Exception { this.spring.register(MvcCorsInLambdaConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ORIGIN, "https://example.com")) + this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com")) .andExpect(header().exists("Access-Control-Allow-Origin")) .andExpect(header().exists("X-Content-Type-Options")); } @@ -148,8 +148,7 @@ public class CorsConfigurerTests { this.mvc.perform(options("/") .header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name()) - .header(HttpHeaders.ORIGIN, "https://example.com")) - .andExpect(status().isOk()) + .header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk()) .andExpect(header().exists("Access-Control-Allow-Origin")) .andExpect(header().exists("X-Content-Type-Options")); } @@ -171,23 +170,23 @@ public class CorsConfigurerTests { } @RestController - @CrossOrigin(methods = { - RequestMethod.GET, RequestMethod.POST - }) + @CrossOrigin(methods = { RequestMethod.GET, RequestMethod.POST }) static class CorsController { + @RequestMapping("/") String hello() { return "Hello"; } + } + } @Test public void getWhenCorsConfigurationSourceBeanThenRespondsWithCorsHeaders() throws Exception { this.spring.register(ConfigSourceConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ORIGIN, "https://example.com")) + this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com")) .andExpect(header().exists("Access-Control-Allow-Origin")) .andExpect(header().exists("X-Content-Type-Options")); } @@ -198,8 +197,7 @@ public class CorsConfigurerTests { this.mvc.perform(options("/") .header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name()) - .header(HttpHeaders.ORIGIN, "https://example.com")) - .andExpect(status().isOk()) + .header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk()) .andExpect(header().exists("Access-Control-Allow-Origin")) .andExpect(header().exists("X-Content-Type-Options")); } @@ -223,12 +221,11 @@ public class CorsConfigurerTests { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.setAllowedOrigins(Collections.singletonList("*")); - corsConfiguration.setAllowedMethods(Arrays.asList( - RequestMethod.GET.name(), - RequestMethod.POST.name())); + corsConfiguration.setAllowedMethods(Arrays.asList(RequestMethod.GET.name(), RequestMethod.POST.name())); source.registerCorsConfiguration("/**", corsConfiguration); return source; } + } @Test @@ -236,8 +233,7 @@ public class CorsConfigurerTests { throws Exception { this.spring.register(ConfigSourceInLambdaConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ORIGIN, "https://example.com")) + this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com")) .andExpect(header().exists("Access-Control-Allow-Origin")) .andExpect(header().exists("X-Content-Type-Options")); } @@ -249,8 +245,7 @@ public class CorsConfigurerTests { this.mvc.perform(options("/") .header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name()) - .header(HttpHeaders.ORIGIN, "https://example.com")) - .andExpect(status().isOk()) + .header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk()) .andExpect(header().exists("Access-Control-Allow-Origin")) .andExpect(header().exists("X-Content-Type-Options")); } @@ -275,20 +270,18 @@ public class CorsConfigurerTests { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.setAllowedOrigins(Collections.singletonList("*")); - corsConfiguration.setAllowedMethods(Arrays.asList( - RequestMethod.GET.name(), - RequestMethod.POST.name())); + corsConfiguration.setAllowedMethods(Arrays.asList(RequestMethod.GET.name(), RequestMethod.POST.name())); source.registerCorsConfiguration("/**", corsConfiguration); return source; } + } @Test public void getWhenCorsFilterBeanThenRespondsWithCorsHeaders() throws Exception { this.spring.register(CorsFilterConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ORIGIN, "https://example.com")) + this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com")) .andExpect(header().exists("Access-Control-Allow-Origin")) .andExpect(header().exists("X-Content-Type-Options")); } @@ -299,8 +292,7 @@ public class CorsConfigurerTests { this.mvc.perform(options("/") .header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name()) - .header(HttpHeaders.ORIGIN, "https://example.com")) - .andExpect(status().isOk()) + .header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk()) .andExpect(header().exists("Access-Control-Allow-Origin")) .andExpect(header().exists("X-Content-Type-Options")); } @@ -324,20 +316,18 @@ public class CorsConfigurerTests { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.setAllowedOrigins(Collections.singletonList("*")); - corsConfiguration.setAllowedMethods(Arrays.asList( - RequestMethod.GET.name(), - RequestMethod.POST.name())); + corsConfiguration.setAllowedMethods(Arrays.asList(RequestMethod.GET.name(), RequestMethod.POST.name())); source.registerCorsConfiguration("/**", corsConfiguration); return new CorsFilter(source); } + } @Test public void getWhenConfigSourceInLambdaConfigAndCorsFilterBeanThenRespondsWithCorsHeaders() throws Exception { this.spring.register(CorsFilterInLambdaConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ORIGIN, "https://example.com")) + this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com")) .andExpect(header().exists("Access-Control-Allow-Origin")) .andExpect(header().exists("X-Content-Type-Options")); } @@ -348,8 +338,7 @@ public class CorsConfigurerTests { this.mvc.perform(options("/") .header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name()) - .header(HttpHeaders.ORIGIN, "https://example.com")) - .andExpect(status().isOk()) + .header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk()) .andExpect(header().exists("Access-Control-Allow-Origin")) .andExpect(header().exists("X-Content-Type-Options")); } @@ -374,11 +363,11 @@ public class CorsConfigurerTests { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.setAllowedOrigins(Collections.singletonList("*")); - corsConfiguration.setAllowedMethods(Arrays.asList( - RequestMethod.GET.name(), - RequestMethod.POST.name())); + corsConfiguration.setAllowedMethods(Arrays.asList(RequestMethod.GET.name(), RequestMethod.POST.name())); source.registerCorsConfiguration("/**", corsConfiguration); return new CorsFilter(source); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerIgnoringRequestMatchersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerIgnoringRequestMatchersTests.java index 56d99f0610..9825c8ea99 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerIgnoringRequestMatchersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerIgnoringRequestMatchersTests.java @@ -48,21 +48,18 @@ public class CsrfConfigurerIgnoringRequestMatchersTests { public final SpringTestRule spring = new SpringTestRule(); @Test - public void requestWhenIgnoringRequestMatchersThenAugmentedByConfiguredRequestMatcher() - throws Exception { + public void requestWhenIgnoringRequestMatchersThenAugmentedByConfiguredRequestMatcher() throws Exception { this.spring.register(IgnoringRequestMatchers.class, BasicController.class).autowire(); - this.mvc.perform(get("/path")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/path")).andExpect(status().isForbidden()); - this.mvc.perform(post("/path")) - .andExpect(status().isOk()); + this.mvc.perform(post("/path")).andExpect(status().isOk()); } @EnableWebSecurity static class IgnoringRequestMatchers extends WebSecurityConfigurerAdapter { - RequestMatcher requestMatcher = - request -> HttpMethod.POST.name().equals(request.getMethod()); + + RequestMatcher requestMatcher = request -> HttpMethod.POST.name().equals(request.getMethod()); @Override protected void configure(HttpSecurity http) throws Exception { @@ -73,24 +70,22 @@ public class CsrfConfigurerIgnoringRequestMatchersTests { .ignoringRequestMatchers(this.requestMatcher); // @formatter:on } + } @Test - public void requestWhenIgnoringRequestMatchersInLambdaThenAugmentedByConfiguredRequestMatcher() - throws Exception { + public void requestWhenIgnoringRequestMatchersInLambdaThenAugmentedByConfiguredRequestMatcher() throws Exception { this.spring.register(IgnoringRequestInLambdaMatchers.class, BasicController.class).autowire(); - this.mvc.perform(get("/path")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/path")).andExpect(status().isForbidden()); - this.mvc.perform(post("/path")) - .andExpect(status().isOk()); + this.mvc.perform(post("/path")).andExpect(status().isOk()); } @EnableWebSecurity static class IgnoringRequestInLambdaMatchers extends WebSecurityConfigurerAdapter { - RequestMatcher requestMatcher = - request -> HttpMethod.POST.name().equals(request.getMethod()); + + RequestMatcher requestMatcher = request -> HttpMethod.POST.name().equals(request.getMethod()); @Override protected void configure(HttpSecurity http) throws Exception { @@ -103,28 +98,25 @@ public class CsrfConfigurerIgnoringRequestMatchersTests { ); // @formatter:on } + } @Test - public void requestWhenIgnoringRequestMatcherThenUnionsWithConfiguredIgnoringAntMatchers() - throws Exception { + public void requestWhenIgnoringRequestMatcherThenUnionsWithConfiguredIgnoringAntMatchers() throws Exception { this.spring.register(IgnoringPathsAndMatchers.class, BasicController.class).autowire(); - this.mvc.perform(put("/csrf")) - .andExpect(status().isForbidden()); + this.mvc.perform(put("/csrf")).andExpect(status().isForbidden()); - this.mvc.perform(post("/csrf")) - .andExpect(status().isOk()); + this.mvc.perform(post("/csrf")).andExpect(status().isOk()); - this.mvc.perform(put("/no-csrf")) - .andExpect(status().isOk()); + this.mvc.perform(put("/no-csrf")).andExpect(status().isOk()); } @EnableWebSecurity static class IgnoringPathsAndMatchers extends WebSecurityConfigurerAdapter { - RequestMatcher requestMatcher = - request -> HttpMethod.POST.name().equals(request.getMethod()); + + RequestMatcher requestMatcher = request -> HttpMethod.POST.name().equals(request.getMethod()); @Override protected void configure(HttpSecurity http) throws Exception { @@ -135,6 +127,7 @@ public class CsrfConfigurerIgnoringRequestMatchersTests { .ignoringRequestMatchers(this.requestMatcher); // @formatter:on } + } @Test @@ -143,20 +136,17 @@ public class CsrfConfigurerIgnoringRequestMatchersTests { this.spring.register(IgnoringPathsAndMatchersInLambdaConfig.class, BasicController.class).autowire(); - this.mvc.perform(put("/csrf")) - .andExpect(status().isForbidden()); + this.mvc.perform(put("/csrf")).andExpect(status().isForbidden()); - this.mvc.perform(post("/csrf")) - .andExpect(status().isOk()); + this.mvc.perform(post("/csrf")).andExpect(status().isOk()); - this.mvc.perform(put("/no-csrf")) - .andExpect(status().isOk()); + this.mvc.perform(put("/no-csrf")).andExpect(status().isOk()); } @EnableWebSecurity static class IgnoringPathsAndMatchersInLambdaConfig extends WebSecurityConfigurerAdapter { - RequestMatcher requestMatcher = - request -> HttpMethod.POST.name().equals(request.getMethod()); + + RequestMatcher requestMatcher = request -> HttpMethod.POST.name().equals(request.getMethod()); @Override protected void configure(HttpSecurity http) throws Exception { @@ -169,10 +159,12 @@ public class CsrfConfigurerIgnoringRequestMatchersTests { ); // @formatter:on } + } @RestController public static class BasicController { + @RequestMapping("/path") public String path() { return "path"; @@ -187,5 +179,7 @@ public class CsrfConfigurerIgnoringRequestMatchersTests { public String noCsrf() { return "no-csrf"; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerNoWebMvcTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerNoWebMvcTests.java index 61df857d62..a7da0f3829 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerNoWebMvcTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerNoWebMvcTests.java @@ -36,6 +36,7 @@ import org.springframework.web.servlet.support.RequestDataValueProcessor; * */ public class CsrfConfigurerNoWebMvcTests { + ConfigurableApplicationContext context; @After @@ -73,15 +74,18 @@ public class CsrfConfigurerNoWebMvcTests { @Override protected void configure(HttpSecurity http) { } + } @EnableWebSecurity static class EnableWebOverrideRequestDataConfig { + @Bean @Primary public RequestDataValueProcessor requestDataValueProcessor() { return mock(RequestDataValueProcessor.class); } + } @EnableWebSecurity @@ -90,6 +94,7 @@ public class CsrfConfigurerNoWebMvcTests { @Override protected void configure(HttpSecurity http) { } + } private void loadContext(Class configs) { @@ -98,4 +103,5 @@ public class CsrfConfigurerNoWebMvcTests { annotationConfigApplicationContext.refresh(); this.context = annotationConfigApplicationContext; } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java index 7165b06422..f7fb67a934 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java @@ -75,6 +75,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Sam Simmons */ public class CsrfConfigurerTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -83,83 +84,83 @@ public class CsrfConfigurerTests { @Test public void postWhenWebSecurityEnabledThenRespondsWithForbidden() throws Exception { - this.spring.register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) + this.spring + .register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) .autowire(); - this.mvc.perform(post("/")) - .andExpect(status().isForbidden()); + this.mvc.perform(post("/")).andExpect(status().isForbidden()); } @Test public void putWhenWebSecurityEnabledThenRespondsWithForbidden() throws Exception { - this.spring.register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) + this.spring + .register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) .autowire(); - this.mvc.perform(put("/")) - .andExpect(status().isForbidden()); + this.mvc.perform(put("/")).andExpect(status().isForbidden()); } @Test public void patchWhenWebSecurityEnabledThenRespondsWithForbidden() throws Exception { - this.spring.register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) + this.spring + .register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) .autowire(); - this.mvc.perform(patch("/")) - .andExpect(status().isForbidden()); + this.mvc.perform(patch("/")).andExpect(status().isForbidden()); } @Test public void deleteWhenWebSecurityEnabledThenRespondsWithForbidden() throws Exception { - this.spring.register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) + this.spring + .register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) .autowire(); - this.mvc.perform(delete("/")) - .andExpect(status().isForbidden()); + this.mvc.perform(delete("/")).andExpect(status().isForbidden()); } @Test public void invalidWhenWebSecurityEnabledThenRespondsWithForbidden() throws Exception { - this.spring.register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) + this.spring + .register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) .autowire(); - this.mvc.perform(request("INVALID", URI.create("/"))) - .andExpect(status().isForbidden()); + this.mvc.perform(request("INVALID", URI.create("/"))).andExpect(status().isForbidden()); } @Test public void getWhenWebSecurityEnabledThenRespondsWithOk() throws Exception { - this.spring.register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) + this.spring + .register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) .autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()); + this.mvc.perform(get("/")).andExpect(status().isOk()); } @Test public void headWhenWebSecurityEnabledThenRespondsWithOk() throws Exception { - this.spring.register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) + this.spring + .register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) .autowire(); - this.mvc.perform(head("/")) - .andExpect(status().isOk()); + this.mvc.perform(head("/")).andExpect(status().isOk()); } @Test public void traceWhenWebSecurityEnabledThenRespondsWithOk() throws Exception { - this.spring.register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) + this.spring + .register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) .autowire(); - this.mvc.perform(request(HttpMethod.TRACE, "/")) - .andExpect(status().isOk()); + this.mvc.perform(request(HttpMethod.TRACE, "/")).andExpect(status().isOk()); } @Test public void optionsWhenWebSecurityEnabledThenRespondsWithOk() throws Exception { - this.spring.register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) + this.spring + .register(CsrfAppliedDefaultConfig.class, AllowHttpMethodsFirewallConfig.class, BasicController.class) .autowire(); - this.mvc.perform(options("/")) - .andExpect(status().isOk()); + this.mvc.perform(options("/")).andExpect(status().isOk()); } @Test @@ -171,12 +172,14 @@ public class CsrfConfigurerTests { @Configuration static class AllowHttpMethodsFirewallConfig { + @Bean StrictHttpFirewall strictHttpFirewall() { StrictHttpFirewall result = new StrictHttpFirewall(); result.setUnsafeAllowAnyHttpMethod(true); return result; } + } @EnableWebSecurity @@ -185,14 +188,14 @@ public class CsrfConfigurerTests { @Override protected void configure(HttpSecurity http) { } + } @Test public void postWhenCsrfDisabledThenRespondsWithOk() throws Exception { this.spring.register(DisableCsrfConfig.class, BasicController.class).autowire(); - this.mvc.perform(post("/")) - .andExpect(status().isOk()); + this.mvc.perform(post("/")).andExpect(status().isOk()); } @EnableWebSecurity @@ -206,14 +209,14 @@ public class CsrfConfigurerTests { .disable(); // @formatter:on } + } @Test public void postWhenCsrfDisabledInLambdaThenRespondsWithOk() throws Exception { this.spring.register(DisableCsrfInLambdaConfig.class, BasicController.class).autowire(); - this.mvc.perform(post("/")) - .andExpect(status().isOk()); + this.mvc.perform(post("/")).andExpect(status().isOk()); } @EnableWebSecurity @@ -226,6 +229,7 @@ public class CsrfConfigurerTests { .csrf(AbstractHttpConfigurer::disable); // @formatter:on } + } // SEC-2498 @@ -235,11 +239,8 @@ public class CsrfConfigurerTests { MvcResult mvcResult = this.mvc.perform(post("/to-save")).andReturn(); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .session((MockHttpSession) mvcResult.getRequest().getSession())) - .andExpect(status().isFound()) + this.mvc.perform(post("/login").param("username", "user").param("password", "password") + .session((MockHttpSession) mvcResult.getRequest().getSession())).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/to-save")); } @@ -268,6 +269,7 @@ public class CsrfConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test @@ -278,17 +280,13 @@ public class CsrfConfigurerTests { when(CsrfDisablesPostRequestFromRequestCacheConfig.REPO.generateToken(any())).thenReturn(csrfToken); this.spring.register(CsrfDisablesPostRequestFromRequestCacheConfig.class).autowire(); - MvcResult mvcResult = this.mvc.perform(post("/some-url")) - .andReturn(); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .with(csrf()) - .session((MockHttpSession) mvcResult.getRequest().getSession())) - .andExpect(status().isFound()) + MvcResult mvcResult = this.mvc.perform(post("/some-url")).andReturn(); + this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf()) + .session((MockHttpSession) mvcResult.getRequest().getSession())).andExpect(status().isFound()) .andExpect(redirectedUrl("/")); - verify(CsrfDisablesPostRequestFromRequestCacheConfig.REPO, atLeastOnce()).loadToken(any(HttpServletRequest.class)); + verify(CsrfDisablesPostRequestFromRequestCacheConfig.REPO, atLeastOnce()) + .loadToken(any(HttpServletRequest.class)); } @Test @@ -299,21 +297,18 @@ public class CsrfConfigurerTests { when(CsrfDisablesPostRequestFromRequestCacheConfig.REPO.generateToken(any())).thenReturn(csrfToken); this.spring.register(CsrfDisablesPostRequestFromRequestCacheConfig.class).autowire(); - MvcResult mvcResult = this.mvc.perform(get("/some-url")) - .andReturn(); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .with(csrf()) - .session((MockHttpSession) mvcResult.getRequest().getSession())) - .andExpect(status().isFound()) + MvcResult mvcResult = this.mvc.perform(get("/some-url")).andReturn(); + this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf()) + .session((MockHttpSession) mvcResult.getRequest().getSession())).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/some-url")); - verify(CsrfDisablesPostRequestFromRequestCacheConfig.REPO, atLeastOnce()).loadToken(any(HttpServletRequest.class)); + verify(CsrfDisablesPostRequestFromRequestCacheConfig.REPO, atLeastOnce()) + .loadToken(any(HttpServletRequest.class)); } @EnableWebSecurity static class CsrfDisablesPostRequestFromRequestCacheConfig extends WebSecurityConfigurerAdapter { + static CsrfTokenRepository REPO; @Override @@ -338,6 +333,7 @@ public class CsrfConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } // SEC-2422 @@ -345,19 +341,16 @@ public class CsrfConfigurerTests { public void postWhenCsrfEnabledAndSessionIsExpiredThenRespondsWithForbidden() throws Exception { this.spring.register(InvalidSessionUrlConfig.class).autowire(); - MvcResult mvcResult = this.mvc.perform(post("/") - .param("_csrf", "abc")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/error/sessionError")) - .andReturn(); + MvcResult mvcResult = this.mvc.perform(post("/").param("_csrf", "abc")).andExpect(status().isFound()) + .andExpect(redirectedUrl("/error/sessionError")).andReturn(); - this.mvc.perform(post("/") - .session((MockHttpSession) mvcResult.getRequest().getSession())) + this.mvc.perform(post("/").session((MockHttpSession) mvcResult.getRequest().getSession())) .andExpect(status().isForbidden()); } @EnableWebSecurity static class InvalidSessionUrlConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -368,16 +361,15 @@ public class CsrfConfigurerTests { .invalidSessionUrl("/error/sessionError"); // @formatter:on } + } @Test public void requireCsrfProtectionMatcherWhenRequestDoesNotMatchThenRespondsWithOk() throws Exception { this.spring.register(RequireCsrfProtectionMatcherConfig.class, BasicController.class).autowire(); - when(RequireCsrfProtectionMatcherConfig.MATCHER.matches(any())) - .thenReturn(false); + when(RequireCsrfProtectionMatcherConfig.MATCHER.matches(any())).thenReturn(false); - this.mvc.perform(get("/")) - .andExpect(status().isOk()); + this.mvc.perform(get("/")).andExpect(status().isOk()); } @Test @@ -386,12 +378,12 @@ public class CsrfConfigurerTests { when(RequireCsrfProtectionMatcherConfig.MATCHER.matches(any())).thenReturn(true); this.spring.register(RequireCsrfProtectionMatcherConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/")).andExpect(status().isForbidden()); } @EnableWebSecurity static class RequireCsrfProtectionMatcherConfig extends WebSecurityConfigurerAdapter { + static RequestMatcher MATCHER; @Override @@ -402,17 +394,16 @@ public class CsrfConfigurerTests { .requireCsrfProtectionMatcher(MATCHER); // @formatter:on } + } @Test public void requireCsrfProtectionMatcherInLambdaWhenRequestDoesNotMatchThenRespondsWithOk() throws Exception { RequireCsrfProtectionMatcherInLambdaConfig.MATCHER = mock(RequestMatcher.class); this.spring.register(RequireCsrfProtectionMatcherInLambdaConfig.class, BasicController.class).autowire(); - when(RequireCsrfProtectionMatcherInLambdaConfig.MATCHER.matches(any())) - .thenReturn(false); + when(RequireCsrfProtectionMatcherInLambdaConfig.MATCHER.matches(any())).thenReturn(false); - this.mvc.perform(get("/")) - .andExpect(status().isOk()); + this.mvc.perform(get("/")).andExpect(status().isOk()); } @Test @@ -421,12 +412,12 @@ public class CsrfConfigurerTests { when(RequireCsrfProtectionMatcherInLambdaConfig.MATCHER.matches(any())).thenReturn(true); this.spring.register(RequireCsrfProtectionMatcherInLambdaConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/")).andExpect(status().isForbidden()); } @EnableWebSecurity static class RequireCsrfProtectionMatcherInLambdaConfig extends WebSecurityConfigurerAdapter { + static RequestMatcher MATCHER; @Override @@ -436,6 +427,7 @@ public class CsrfConfigurerTests { .csrf(csrf -> csrf.requireCsrfProtectionMatcher(MATCHER)); // @formatter:on } + } @Test @@ -445,8 +437,7 @@ public class CsrfConfigurerTests { .thenReturn(new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token")); this.spring.register(CsrfTokenRepositoryConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()); + this.mvc.perform(get("/")).andExpect(status().isOk()); verify(CsrfTokenRepositoryConfig.REPO).loadToken(any(HttpServletRequest.class)); } @@ -455,12 +446,10 @@ public class CsrfConfigurerTests { CsrfTokenRepositoryConfig.REPO = mock(CsrfTokenRepository.class); this.spring.register(CsrfTokenRepositoryConfig.class, BasicController.class).autowire(); - this.mvc.perform(post("/logout") - .with(csrf()) - .with(user("user"))); + this.mvc.perform(post("/logout").with(csrf()).with(user("user"))); - verify(CsrfTokenRepositoryConfig.REPO) - .saveToken(isNull(), any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(CsrfTokenRepositoryConfig.REPO).saveToken(isNull(), any(HttpServletRequest.class), + any(HttpServletResponse.class)); } @Test @@ -471,18 +460,16 @@ public class CsrfConfigurerTests { when(CsrfTokenRepositoryConfig.REPO.generateToken(any())).thenReturn(csrfToken); this.spring.register(CsrfTokenRepositoryConfig.class, BasicController.class).autowire(); - this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password")) + this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")) .andExpect(redirectedUrl("/")); - verify(CsrfTokenRepositoryConfig.REPO) - .saveToken(isNull(), any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(CsrfTokenRepositoryConfig.REPO).saveToken(isNull(), any(HttpServletRequest.class), + any(HttpServletResponse.class)); } @EnableWebSecurity static class CsrfTokenRepositoryConfig extends WebSecurityConfigurerAdapter { + static CsrfTokenRepository REPO; @Override @@ -504,6 +491,7 @@ public class CsrfConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test @@ -513,13 +501,13 @@ public class CsrfConfigurerTests { .thenReturn(new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token")); this.spring.register(CsrfTokenRepositoryInLambdaConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()); + this.mvc.perform(get("/")).andExpect(status().isOk()); verify(CsrfTokenRepositoryInLambdaConfig.REPO).loadToken(any(HttpServletRequest.class)); } @EnableWebSecurity static class CsrfTokenRepositoryInLambdaConfig extends WebSecurityConfigurerAdapter { + static CsrfTokenRepository REPO; @Override @@ -530,6 +518,7 @@ public class CsrfConfigurerTests { .csrf(csrf -> csrf.csrfTokenRepository(REPO)); // @formatter:on } + } @Test @@ -537,15 +526,15 @@ public class CsrfConfigurerTests { AccessDeniedHandlerConfig.DENIED_HANDLER = mock(AccessDeniedHandler.class); this.spring.register(AccessDeniedHandlerConfig.class, BasicController.class).autowire(); - this.mvc.perform(post("/")) - .andExpect(status().isOk()); + this.mvc.perform(post("/")).andExpect(status().isOk()); - verify(AccessDeniedHandlerConfig.DENIED_HANDLER) - .handle(any(HttpServletRequest.class), any(HttpServletResponse.class), any()); + verify(AccessDeniedHandlerConfig.DENIED_HANDLER).handle(any(HttpServletRequest.class), + any(HttpServletResponse.class), any()); } @EnableWebSecurity static class AccessDeniedHandlerConfig extends WebSecurityConfigurerAdapter { + static AccessDeniedHandler DENIED_HANDLER; @Override @@ -556,26 +545,22 @@ public class CsrfConfigurerTests { .accessDeniedHandler(DENIED_HANDLER); // @formatter:on } + } @Test public void loginWhenNoCsrfTokenThenRespondsWithForbidden() throws Exception { this.spring.register(FormLoginConfig.class).autowire(); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password")) - .andExpect(status().isForbidden()) - .andExpect(unauthenticated()); + this.mvc.perform(post("/login").param("username", "user").param("password", "password")) + .andExpect(status().isForbidden()).andExpect(unauthenticated()); } @Test public void logoutWhenNoCsrfTokenThenRespondsWithForbidden() throws Exception { this.spring.register(FormLoginConfig.class).autowire(); - this.mvc.perform(post("/logout") - .with(user("username"))) - .andExpect(status().isForbidden()) + this.mvc.perform(post("/logout").with(user("username"))).andExpect(status().isForbidden()) .andExpect(authenticated()); } @@ -584,9 +569,7 @@ public class CsrfConfigurerTests { public void logoutWhenCsrfEnabledAndGetRequestThenDoesNotLogout() throws Exception { this.spring.register(FormLoginConfig.class).autowire(); - this.mvc.perform(get("/logout") - .with(user("username"))) - .andExpect(authenticated()); + this.mvc.perform(get("/logout").with(user("username"))).andExpect(authenticated()); } @EnableWebSecurity @@ -599,15 +582,14 @@ public class CsrfConfigurerTests { .formLogin(); // @formatter:on } + } @Test public void logoutWhenGetRequestAndGetEnabledForLogoutThenLogsOut() throws Exception { this.spring.register(LogoutAllowsGetConfig.class).autowire(); - this.mvc.perform(get("/logout") - .with(user("username"))) - .andExpect(unauthenticated()); + this.mvc.perform(get("/logout").with(user("username"))).andExpect(unauthenticated()); } @EnableWebSecurity @@ -623,18 +605,19 @@ public class CsrfConfigurerTests { .logoutRequestMatcher(new AntPathRequestMatcher("/logout")); // @formatter:on } + } // SEC-2749 @Test public void configureWhenRequireCsrfProtectionMatcherNullThenException() { assertThatThrownBy(() -> this.spring.register(NullRequireCsrfProtectionMatcherConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasRootCauseInstanceOf(IllegalArgumentException.class); + .isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class); } @EnableWebSecurity static class NullRequireCsrfProtectionMatcherConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -643,14 +626,14 @@ public class CsrfConfigurerTests { .requireCsrfProtectionMatcher(null); // @formatter:on } + } @Test public void getWhenDefaultCsrfTokenRepositoryThenDoesNotCreateSession() throws Exception { this.spring.register(DefaultDoesNotCreateSession.class).autowire(); - MvcResult mvcResult = this.mvc.perform(get("/")) - .andReturn(); + MvcResult mvcResult = this.mvc.perform(get("/")).andReturn(); assertThat(mvcResult.getRequest().getSession(false)).isNull(); } @@ -679,10 +662,12 @@ public class CsrfConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @EnableWebSecurity static class NullAuthenticationStrategy extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -691,17 +676,18 @@ public class CsrfConfigurerTests { .sessionAuthenticationStrategy(null); // @formatter:on } + } @Test public void getWhenNullAuthenticationStrategyThenException() { assertThatThrownBy(() -> this.spring.register(NullAuthenticationStrategy.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasRootCauseInstanceOf(IllegalArgumentException.class); + .isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class); } @EnableWebSecurity static class CsrfAuthenticationStrategyConfig extends WebSecurityConfigurerAdapter { + static SessionAuthenticationStrategy STRATEGY; @Override @@ -723,6 +709,7 @@ public class CsrfConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test @@ -731,18 +718,16 @@ public class CsrfConfigurerTests { this.spring.register(CsrfAuthenticationStrategyConfig.class).autowire(); - this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password")) + this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")) .andExpect(redirectedUrl("/")); - verify(CsrfAuthenticationStrategyConfig.STRATEGY, atLeastOnce()) - .onAuthentication(any(Authentication.class), any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(CsrfAuthenticationStrategyConfig.STRATEGY, atLeastOnce()).onAuthentication(any(Authentication.class), + any(HttpServletRequest.class), any(HttpServletResponse.class)); } @RestController static class BasicController { + @GetMapping("/") public void rootGet() { } @@ -750,5 +735,7 @@ public class CsrfConfigurerTests { @PostMapping("/") public void rootPost() { } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.java index 3802618cf3..8a2ca92a2a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.java @@ -78,6 +78,7 @@ public class DefaultFiltersTests { @EnableWebSecurity static class FilterChainProxyBuilderMissingConfig { + @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -86,31 +87,36 @@ public class DefaultFiltersTests { .withUser("user").password("password").roles("USER"); // @formatter:on } + } @Test public void nullWebInvocationPrivilegeEvaluator() { this.spring.register(NullWebInvocationPrivilegeEvaluatorConfig.class, UserDetailsServiceConfig.class); - List filterChains = this.spring.getContext().getBean(FilterChainProxy.class).getFilterChains(); + List filterChains = this.spring.getContext().getBean(FilterChainProxy.class) + .getFilterChains(); assertThat(filterChains.size()).isEqualTo(1); DefaultSecurityFilterChain filterChain = (DefaultSecurityFilterChain) filterChains.get(0); assertThat(filterChain.getRequestMatcher()).isInstanceOf(AnyRequestMatcher.class); assertThat(filterChain.getFilters().size()).isEqualTo(1); - long filter = filterChain.getFilters().stream() - .filter(it -> it instanceof UsernamePasswordAuthenticationFilter).count(); + long filter = filterChain.getFilters().stream().filter(it -> it instanceof UsernamePasswordAuthenticationFilter) + .count(); assertThat(filter).isEqualTo(1); } @Configuration static class UserDetailsServiceConfig { + @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager(PasswordEncodedUser.user(), PasswordEncodedUser.admin()); } + } @EnableWebSecurity static class NullWebInvocationPrivilegeEvaluatorConfig extends WebSecurityConfigurerAdapter { + NullWebInvocationPrivilegeEvaluatorConfig() { super(true); } @@ -118,12 +124,14 @@ public class DefaultFiltersTests { protected void configure(HttpSecurity http) throws Exception { http.formLogin(); } + } @Test public void filterChainProxyBuilderIgnoringResources() { this.spring.register(FilterChainProxyBuilderIgnoringConfig.class, UserDetailsServiceConfig.class); - List filterChains = this.spring.getContext().getBean(FilterChainProxy.class).getFilterChains(); + List filterChains = this.spring.getContext().getBean(FilterChainProxy.class) + .getFilterChains(); assertThat(filterChains.size()).isEqualTo(2); DefaultSecurityFilterChain firstFilter = (DefaultSecurityFilterChain) filterChains.get(0); DefaultSecurityFilterChain secondFilter = (DefaultSecurityFilterChain) filterChains.get(1); @@ -148,6 +156,7 @@ public class DefaultFiltersTests { @EnableWebSecurity static class FilterChainProxyBuilderIgnoringConfig extends WebSecurityConfigurerAdapter { + @Override public void configure(WebSecurity web) { // @formatter:off @@ -165,6 +174,7 @@ public class DefaultFiltersTests { .anyRequest().hasRole("USER"); // @formatter:on } + } @Test @@ -185,7 +195,10 @@ public class DefaultFiltersTests { @EnableWebSecurity static class DefaultFiltersConfigPermitAll extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) { } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurerTests.java index 0bd6e0417f..16df77bbd5 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurerTests.java @@ -68,8 +68,7 @@ public class DefaultLoginPageConfigurerTests { public void getWhenFormLoginEnabledThenRedirectsToLoginPage() throws Exception { this.spring.register(DefaultLoginPageConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(redirectedUrl("http://localhost/login")); + this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/login")); } @Test @@ -78,47 +77,33 @@ public class DefaultLoginPageConfigurerTests { CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN"); String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN"); - this.mvc.perform(get("/login") - .sessionAttr(csrfAttributeName, csrfToken)) - .andExpect(content().string( - "\n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " Please sign in\n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
    \n" + - "
    \n" + - " \n" + - "

    \n" + - " \n" + - " \n" + - "

    \n" + - "

    \n" + - " \n" + - " \n" + - "

    \n" + - "\n" + - " \n" + - "
    \n" + - "
    \n" + - "" - )); + this.mvc.perform(get("/login").sessionAttr(csrfAttributeName, csrfToken)) + .andExpect(content().string("\n" + "\n" + " \n" + + " \n" + + " \n" + + " \n" + " \n" + + " Please sign in\n" + + " \n" + + " \n" + + " \n" + " \n" + "
    \n" + + "
    \n" + + " \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + "\n" + + " \n" + + "
    \n" + "
    \n" + "")); } @Test public void loginWhenNoCredentialsThenRedirectedToLoginPageWithError() throws Exception { this.spring.register(DefaultLoginPageConfig.class).autowire(); - this.mvc.perform(post("/login") - .with(csrf())) - .andExpect(redirectedUrl("/login?error")); + this.mvc.perform(post("/login").with(csrf())).andExpect(redirectedUrl("/login?error")); } @Test @@ -127,53 +112,37 @@ public class DefaultLoginPageConfigurerTests { CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN"); String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN"); - MvcResult mvcResult = this.mvc.perform(post("/login") - .with(csrf())) - .andReturn(); + MvcResult mvcResult = this.mvc.perform(post("/login").with(csrf())).andReturn(); - this.mvc.perform(get("/login?error") - .session((MockHttpSession) mvcResult.getRequest().getSession()) + this.mvc.perform(get("/login?error").session((MockHttpSession) mvcResult.getRequest().getSession()) .sessionAttr(csrfAttributeName, csrfToken)) - .andExpect(content().string( - "\n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " Please sign in\n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
    \n" + - "
    \n" + - " \n" + - "
    Bad credentials

    \n" + - " \n" + - " \n" + - "

    \n" + - "

    \n" + - " \n" + - " \n" + - "

    \n" + - "\n" + - " \n" + - "
    \n" + - "
    \n" + - "" - )); + .andExpect(content().string("\n" + "\n" + " \n" + + " \n" + + " \n" + + " \n" + " \n" + + " Please sign in\n" + + " \n" + + " \n" + + " \n" + " \n" + "
    \n" + + "
    \n" + + " \n" + + "
    Bad credentials

    \n" + + " \n" + + " \n" + + "

    \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + "\n" + + " \n" + + "
    \n" + "
    \n" + "")); } @Test public void loginWhenValidCredentialsThenRedirectsToDefaultSuccessPage() throws Exception { this.spring.register(DefaultLoginPageConfig.class).autowire(); - this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password")) + this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")) .andExpect(redirectedUrl("/")); } @@ -183,42 +152,32 @@ public class DefaultLoginPageConfigurerTests { CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN"); String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN"); - this.mvc.perform(get("/login?logout") - .sessionAttr(csrfAttributeName, csrfToken)) - .andExpect(content().string( - "\n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " Please sign in\n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
    \n" + - "
    \n" + - " \n" + - "
    You have been signed out

    \n" + - " \n" + - " \n" + - "

    \n" + - "

    \n" + - " \n" + - " \n" + - "

    \n" + - "\n" + - " \n" + - "
    \n" + - "
    \n" + - "" - )); + this.mvc.perform(get("/login?logout").sessionAttr(csrfAttributeName, csrfToken)) + .andExpect(content().string("\n" + "\n" + " \n" + + " \n" + + " \n" + + " \n" + " \n" + + " Please sign in\n" + + " \n" + + " \n" + + " \n" + " \n" + "
    \n" + + "
    \n" + + " \n" + + "
    You have been signed out

    \n" + + " \n" + + " \n" + + "

    \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + "\n" + + " \n" + + "
    \n" + "
    \n" + "")); } @EnableWebSecurity static class DefaultLoginPageConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -238,19 +197,19 @@ public class DefaultLoginPageConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test public void loginPageWhenLoggedOutAndCustomLogoutSuccessHandlerThenDoesNotRenderLoginPage() throws Exception { this.spring.register(DefaultLoginPageCustomLogoutSuccessHandlerConfig.class).autowire(); - this.mvc.perform(get("/login?logout")) - .andExpect(content().string("")); + this.mvc.perform(get("/login?logout")).andExpect(content().string("")); } - @EnableWebSecurity static class DefaultLoginPageCustomLogoutSuccessHandlerConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -264,18 +223,19 @@ public class DefaultLoginPageConfigurerTests { .formLogin(); // @formatter:on } + } @Test public void loginPageWhenLoggedOutAndCustomLogoutSuccessUrlThenDoesNotRenderLoginPage() throws Exception { this.spring.register(DefaultLoginPageCustomLogoutSuccessUrlConfig.class).autowire(); - this.mvc.perform(get("/login?logout")) - .andExpect(content().string("")); + this.mvc.perform(get("/login?logout")).andExpect(content().string("")); } @EnableWebSecurity static class DefaultLoginPageCustomLogoutSuccessUrlConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -289,6 +249,7 @@ public class DefaultLoginPageConfigurerTests { .formLogin(); // @formatter:on } + } @Test @@ -297,43 +258,33 @@ public class DefaultLoginPageConfigurerTests { CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN"); String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN"); - this.mvc.perform(get("/login") - .sessionAttr(csrfAttributeName, csrfToken)) - .andExpect(content().string( - "\n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " Please sign in\n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
    \n" + - "
    \n" + - " \n" + - "

    \n" + - " \n" + - " \n" + - "

    \n" + - "

    \n" + - " \n" + - " \n" + - "

    \n" + - "

    Remember me on this computer.

    \n" + - "\n" + - " \n" + - "
    \n" + - "
    \n" + - "" - )); + this.mvc.perform(get("/login").sessionAttr(csrfAttributeName, csrfToken)) + .andExpect(content().string("\n" + "\n" + " \n" + + " \n" + + " \n" + + " \n" + " \n" + + " Please sign in\n" + + " \n" + + " \n" + + " \n" + " \n" + "
    \n" + + "
    \n" + + " \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + + "

    Remember me on this computer.

    \n" + + "\n" + + " \n" + + "
    \n" + "
    \n" + "")); } @EnableWebSecurity static class DefaultLoginPageWithRememberMeConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -346,6 +297,7 @@ public class DefaultLoginPageConfigurerTests { .rememberMe(); // @formatter:on } + } @Test @@ -355,38 +307,28 @@ public class DefaultLoginPageConfigurerTests { CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN"); String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN"); - this.mvc.perform(get("/login") - .sessionAttr(csrfAttributeName, csrfToken)) - .andExpect(content().string( - "\n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " Please sign in\n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
    \n" + - "
    \n" + - " \n" + - "

    \n" + - " \n" + - " \n" + - "

    \n" + - "\n" + - " \n" + - "
    \n" + - "
    \n" + - "" - )); + this.mvc.perform(get("/login").sessionAttr(csrfAttributeName, csrfToken)) + .andExpect(content().string("\n" + "\n" + " \n" + + " \n" + + " \n" + + " \n" + " \n" + + " Please sign in\n" + + " \n" + + " \n" + + " \n" + " \n" + "
    \n" + + "
    \n" + + " \n" + + "

    \n" + " \n" + + " \n" + + "

    \n" + "\n" + + " \n" + + "
    \n" + "
    \n" + "")); } @EnableWebSecurity static class DefaultLoginPageWithOpenIDConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -397,6 +339,7 @@ public class DefaultLoginPageConfigurerTests { .openidLogin(); // @formatter:on } + } @Test @@ -405,53 +348,43 @@ public class DefaultLoginPageConfigurerTests { CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN"); String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN"); - this.mvc.perform(get("/login") - .sessionAttr(csrfAttributeName, csrfToken)) - .andExpect(content().string( - "\n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " Please sign in\n" + - " \n" + - " \n" + - " \n" + - " \n" + - "
    \n" + - "
    \n" + - " \n" + - "

    \n" + - " \n" + - " \n" + - "

    \n" + - "

    \n" + - " \n" + - " \n" + - "

    \n" + - "

    Remember me on this computer.

    \n" + - "\n" + - " \n" + - "
    \n" + - "
    \n" + - " \n" + - "

    \n" + - " \n" + - " \n" + - "

    \n" + - "

    Remember me on this computer.

    \n" + - "\n" + - " \n" + - "
    \n" + - "
    \n" + - "" - )); + this.mvc.perform(get("/login").sessionAttr(csrfAttributeName, csrfToken)) + .andExpect(content().string("\n" + "\n" + " \n" + + " \n" + + " \n" + + " \n" + " \n" + + " Please sign in\n" + + " \n" + + " \n" + + " \n" + " \n" + "
    \n" + + "
    \n" + + " \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + + "

    Remember me on this computer.

    \n" + + "\n" + + " \n" + + "
    \n" + + "
    \n" + + " \n" + + "

    \n" + " \n" + + " \n" + + "

    \n" + + "

    Remember me on this computer.

    \n" + + "\n" + + " \n" + + "
    \n" + "
    \n" + "")); } @EnableWebSecurity static class DefaultLoginPageWithFormLoginOpenIDRememberMeConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -466,6 +399,7 @@ public class DefaultLoginPageConfigurerTests { .openidLogin(); // @formatter:on } + } @Test @@ -474,13 +408,13 @@ public class DefaultLoginPageConfigurerTests { FilterChainProxy filterChain = this.spring.getContext().getBean(FilterChainProxy.class); assertThat(filterChain.getFilterChains().get(0).getFilters().stream() - .filter(filter -> filter.getClass().isAssignableFrom(DefaultLoginPageGeneratingFilter.class)) - .count()) - .isZero(); + .filter(filter -> filter.getClass().isAssignableFrom(DefaultLoginPageGeneratingFilter.class)).count()) + .isZero(); } @EnableWebSecurity static class DefaultLoginWithCustomAuthenticationEntryPointConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -494,6 +428,7 @@ public class DefaultLoginPageConfigurerTests { .formLogin(); // @formatter:on } + } @Test @@ -501,8 +436,7 @@ public class DefaultLoginPageConfigurerTests { ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class); this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(DefaultLoginPageGeneratingFilter.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(DefaultLoginPageGeneratingFilter.class)); } @Test @@ -519,8 +453,7 @@ public class DefaultLoginPageConfigurerTests { ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class); this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(LoginUrlAuthenticationEntryPoint.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(LoginUrlAuthenticationEntryPoint.class)); } @Test @@ -528,12 +461,12 @@ public class DefaultLoginPageConfigurerTests { ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class); this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(ExceptionTranslationFilter.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(ExceptionTranslationFilter.class)); } @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor; @Override @@ -550,12 +483,16 @@ public class DefaultLoginPageConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerAccessDeniedHandlerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerAccessDeniedHandlerTests.java index ef1084cdbd..ab6021c5c0 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerAccessDeniedHandlerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerAccessDeniedHandlerTests.java @@ -43,6 +43,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @RunWith(SpringJUnit4ClassRunner.class) @SecurityTestExecutionListeners public class ExceptionHandlingConfigurerAccessDeniedHandlerTests { + @Autowired MockMvc mvc; @@ -51,22 +52,19 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests { @Test @WithMockUser(roles = "ANYTHING") - public void getWhenAccessDeniedOverriddenThenCustomizesResponseByRequest() - throws Exception { + public void getWhenAccessDeniedOverriddenThenCustomizesResponseByRequest() throws Exception { this.spring.register(RequestMatcherBasedAccessDeniedHandlerConfig.class).autowire(); - this.mvc.perform(get("/hello")) - .andExpect(status().isIAmATeapot()); + this.mvc.perform(get("/hello")).andExpect(status().isIAmATeapot()); - this.mvc.perform(get("/goodbye")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/goodbye")).andExpect(status().isForbidden()); } @EnableWebSecurity static class RequestMatcherBasedAccessDeniedHandlerConfig extends WebSecurityConfigurerAdapter { - AccessDeniedHandler teapotDeniedHandler = - (request, response, exception) -> - response.setStatus(HttpStatus.I_AM_A_TEAPOT.value()); + + AccessDeniedHandler teapotDeniedHandler = (request, response, exception) -> response + .setStatus(HttpStatus.I_AM_A_TEAPOT.value()); @Override protected void configure(HttpSecurity http) throws Exception { @@ -84,26 +82,24 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests { AnyRequestMatcher.INSTANCE); // @formatter:on } + } @Test @WithMockUser(roles = "ANYTHING") - public void getWhenAccessDeniedOverriddenInLambdaThenCustomizesResponseByRequest() - throws Exception { + public void getWhenAccessDeniedOverriddenInLambdaThenCustomizesResponseByRequest() throws Exception { this.spring.register(RequestMatcherBasedAccessDeniedHandlerInLambdaConfig.class).autowire(); - this.mvc.perform(get("/hello")) - .andExpect(status().isIAmATeapot()); + this.mvc.perform(get("/hello")).andExpect(status().isIAmATeapot()); - this.mvc.perform(get("/goodbye")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/goodbye")).andExpect(status().isForbidden()); } @EnableWebSecurity static class RequestMatcherBasedAccessDeniedHandlerInLambdaConfig extends WebSecurityConfigurerAdapter { - AccessDeniedHandler teapotDeniedHandler = - (request, response, exception) -> - response.setStatus(HttpStatus.I_AM_A_TEAPOT.value()); + + AccessDeniedHandler teapotDeniedHandler = (request, response, exception) -> response + .setStatus(HttpStatus.I_AM_A_TEAPOT.value()); @Override protected void configure(HttpSecurity http) throws Exception { @@ -126,26 +122,24 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests { ); // @formatter:on } + } @Test @WithMockUser(roles = "ANYTHING") - public void getWhenAccessDeniedOverriddenByOnlyOneHandlerThenAllRequestsUseThatHandler() - throws Exception { + public void getWhenAccessDeniedOverriddenByOnlyOneHandlerThenAllRequestsUseThatHandler() throws Exception { this.spring.register(SingleRequestMatcherAccessDeniedHandlerConfig.class).autowire(); - this.mvc.perform(get("/hello")) - .andExpect(status().isIAmATeapot()); + this.mvc.perform(get("/hello")).andExpect(status().isIAmATeapot()); - this.mvc.perform(get("/goodbye")) - .andExpect(status().isIAmATeapot()); + this.mvc.perform(get("/goodbye")).andExpect(status().isIAmATeapot()); } @EnableWebSecurity static class SingleRequestMatcherAccessDeniedHandlerConfig extends WebSecurityConfigurerAdapter { - AccessDeniedHandler teapotDeniedHandler = - (request, response, exception) -> - response.setStatus(HttpStatus.I_AM_A_TEAPOT.value()); + + AccessDeniedHandler teapotDeniedHandler = (request, response, exception) -> response + .setStatus(HttpStatus.I_AM_A_TEAPOT.value()); @Override protected void configure(HttpSecurity http) throws Exception { @@ -160,5 +154,7 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests { new AntPathRequestMatcher("/hello/**")); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.java index 5b4ea82259..54b341f14f 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.java @@ -67,12 +67,12 @@ public class ExceptionHandlingConfigurerTests { public void configureWhenRegisteringObjectPostProcessorThenInvokedOnExceptionTranslationFilter() { this.spring.register(ObjectPostProcessorConfig.class, DefaultSecurityConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(ExceptionTranslationFilter.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(ExceptionTranslationFilter.class)); } @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class); @Override @@ -87,13 +87,16 @@ public class ExceptionHandlingConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } // SEC-2199 @@ -101,8 +104,7 @@ public class ExceptionHandlingConfigurerTests { public void getWhenAcceptHeaderIsApplicationXhtmlXmlThenRespondsWith302() throws Exception { this.spring.register(HttpBasicAndFormLoginEntryPointsConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_XHTML_XML)) + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, MediaType.APPLICATION_XHTML_XML)) .andExpect(status().isFound()); } @@ -111,9 +113,7 @@ public class ExceptionHandlingConfigurerTests { public void getWhenAcceptHeaderIsImageGifThenRespondsWith302() throws Exception { this.spring.register(HttpBasicAndFormLoginEntryPointsConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, MediaType.IMAGE_GIF)) - .andExpect(status().isFound()); + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, MediaType.IMAGE_GIF)).andExpect(status().isFound()); } // SEC-2199 @@ -121,9 +121,7 @@ public class ExceptionHandlingConfigurerTests { public void getWhenAcceptHeaderIsImageJpgThenRespondsWith302() throws Exception { this.spring.register(HttpBasicAndFormLoginEntryPointsConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, MediaType.IMAGE_JPEG)) - .andExpect(status().isFound()); + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, MediaType.IMAGE_JPEG)).andExpect(status().isFound()); } // SEC-2199 @@ -131,9 +129,7 @@ public class ExceptionHandlingConfigurerTests { public void getWhenAcceptHeaderIsImagePngThenRespondsWith302() throws Exception { this.spring.register(HttpBasicAndFormLoginEntryPointsConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, MediaType.IMAGE_PNG)) - .andExpect(status().isFound()); + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, MediaType.IMAGE_PNG)).andExpect(status().isFound()); } // SEC-2199 @@ -141,9 +137,7 @@ public class ExceptionHandlingConfigurerTests { public void getWhenAcceptHeaderIsTextHtmlThenRespondsWith302() throws Exception { this.spring.register(HttpBasicAndFormLoginEntryPointsConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML)) - .andExpect(status().isFound()); + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML)).andExpect(status().isFound()); } // SEC-2199 @@ -151,9 +145,7 @@ public class ExceptionHandlingConfigurerTests { public void getWhenAcceptHeaderIsTextPlainThenRespondsWith302() throws Exception { this.spring.register(HttpBasicAndFormLoginEntryPointsConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, MediaType.TEXT_PLAIN)) - .andExpect(status().isFound()); + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, MediaType.TEXT_PLAIN)).andExpect(status().isFound()); } // SEC-2199 @@ -161,8 +153,7 @@ public class ExceptionHandlingConfigurerTests { public void getWhenAcceptHeaderIsApplicationAtomXmlThenRespondsWith401() throws Exception { this.spring.register(HttpBasicAndFormLoginEntryPointsConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_ATOM_XML)) + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, MediaType.APPLICATION_ATOM_XML)) .andExpect(status().isUnauthorized()); } @@ -171,8 +162,7 @@ public class ExceptionHandlingConfigurerTests { public void getWhenAcceptHeaderIsApplicationFormUrlEncodedThenRespondsWith401() throws Exception { this.spring.register(HttpBasicAndFormLoginEntryPointsConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_FORM_URLENCODED)) + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, MediaType.APPLICATION_FORM_URLENCODED)) .andExpect(status().isUnauthorized()); } @@ -181,8 +171,7 @@ public class ExceptionHandlingConfigurerTests { public void getWhenAcceptHeaderIsApplicationJsonThenRespondsWith401() throws Exception { this.spring.register(HttpBasicAndFormLoginEntryPointsConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON)) + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON)) .andExpect(status().isUnauthorized()); } @@ -191,8 +180,7 @@ public class ExceptionHandlingConfigurerTests { public void getWhenAcceptHeaderIsApplicationOctetStreamThenRespondsWith401() throws Exception { this.spring.register(HttpBasicAndFormLoginEntryPointsConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_OCTET_STREAM)) + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, MediaType.APPLICATION_OCTET_STREAM)) .andExpect(status().isUnauthorized()); } @@ -201,8 +189,7 @@ public class ExceptionHandlingConfigurerTests { public void getWhenAcceptHeaderIsMultipartFormDataThenRespondsWith401() throws Exception { this.spring.register(HttpBasicAndFormLoginEntryPointsConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, MediaType.MULTIPART_FORM_DATA)) + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, MediaType.MULTIPART_FORM_DATA)) .andExpect(status().isUnauthorized()); } @@ -211,9 +198,7 @@ public class ExceptionHandlingConfigurerTests { public void getWhenAcceptHeaderIsTextXmlThenRespondsWith401() throws Exception { this.spring.register(HttpBasicAndFormLoginEntryPointsConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, MediaType.TEXT_XML)) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, MediaType.TEXT_XML)).andExpect(status().isUnauthorized()); } // gh-4831 @@ -221,18 +206,15 @@ public class ExceptionHandlingConfigurerTests { public void getWhenAcceptIsAnyThenRespondsWith401() throws Exception { this.spring.register(DefaultSecurityConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, MediaType.ALL)) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, MediaType.ALL)).andExpect(status().isUnauthorized()); } @Test public void getWhenAcceptIsChromeThenRespondsWith302() throws Exception { this.spring.register(DefaultSecurityConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, - "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")) + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, + "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")) .andExpect(status().isFound()); } @@ -240,9 +222,7 @@ public class ExceptionHandlingConfigurerTests { public void getWhenAcceptIsTextPlainAndXRequestedWithIsXHRThenRespondsWith401() throws Exception { this.spring.register(HttpBasicAndFormLoginEntryPointsConfig.class).autowire(); - this.mvc.perform(get("/") - .header("Accept", MediaType.TEXT_PLAIN) - .header("X-Requested-With", "XMLHttpRequest")) + this.mvc.perform(get("/").header("Accept", MediaType.TEXT_PLAIN).header("X-Requested-With", "XMLHttpRequest")) .andExpect(status().isUnauthorized()); } @@ -284,12 +264,13 @@ public class ExceptionHandlingConfigurerTests { .formLogin(); // @formatter:on } + } @Test public void getWhenCustomContentNegotiationStrategyThenStrategyIsUsed() throws Exception { - this.spring.register(OverrideContentNegotiationStrategySharedObjectConfig.class, - DefaultSecurityConfig.class).autowire(); + this.spring.register(OverrideContentNegotiationStrategySharedObjectConfig.class, DefaultSecurityConfig.class) + .autowire(); this.mvc.perform(get("/")); @@ -299,38 +280,39 @@ public class ExceptionHandlingConfigurerTests { @EnableWebSecurity static class OverrideContentNegotiationStrategySharedObjectConfig extends WebSecurityConfigurerAdapter { + static ContentNegotiationStrategy CNS = mock(ContentNegotiationStrategy.class); @Bean public static ContentNegotiationStrategy cns() { return CNS; } + } @Test public void getWhenUsingDefaultsAndUnauthenticatedThenRedirectsToLogin() throws Exception { this.spring.register(DefaultHttpConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, "bogus/type")) + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, "bogus/type")) .andExpect(redirectedUrl("http://localhost/login")); } @EnableWebSecurity static class DefaultHttpConfig extends WebSecurityConfigurerAdapter { + } @Test public void getWhenDeclaringHttpBasicBeforeFormLoginThenRespondsWith401() throws Exception { this.spring.register(BasicAuthenticationEntryPointBeforeFormLoginConfig.class).autowire(); - this.mvc.perform(get("/") - .header(HttpHeaders.ACCEPT, "bogus/type")) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, "bogus/type")).andExpect(status().isUnauthorized()); } @EnableWebSecurity static class BasicAuthenticationEntryPointBeforeFormLoginConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -343,6 +325,7 @@ public class ExceptionHandlingConfigurerTests { .formLogin(); // @formatter:on } + } @Test @@ -351,26 +334,20 @@ public class ExceptionHandlingConfigurerTests { this.mvc.perform(get("/")); - verify(InvokeTwiceDoesNotOverrideConfig.AEP) - .commence(any(HttpServletRequest.class), - any(HttpServletResponse.class), any(AuthenticationException.class)); + verify(InvokeTwiceDoesNotOverrideConfig.AEP).commence(any(HttpServletRequest.class), + any(HttpServletResponse.class), any(AuthenticationException.class)); } @EnableWebSecurity static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter { + static AuthenticationEntryPoint AEP = mock(AuthenticationEntryPoint.class); @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:on - http - .authorizeRequests() - .anyRequest().authenticated() - .and() - .exceptionHandling() - .authenticationEntryPoint(AEP) - .and() - .exceptionHandling(); + http.authorizeRequests().anyRequest().authenticated().and().exceptionHandling() + .authenticationEntryPoint(AEP).and().exceptionHandling(); // @formatter:off } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurerTests.java index 4f7844ca69..a052ff016b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurerTests.java @@ -84,13 +84,14 @@ public class ExpressionUrlAuthorizationConfigurerTests { @Test public void configureWhenHasRoleStartingWithStringRoleThenException() { assertThatThrownBy(() -> this.spring.register(HasRoleStartingWithRoleConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("role should not start with 'ROLE_' since it is automatically inserted. Got 'ROLE_USER'"); + .isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class) + .hasMessageContaining( + "role should not start with 'ROLE_' since it is automatically inserted. Got 'ROLE_USER'"); } @EnableWebSecurity static class HasRoleStartingWithRoleConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -99,18 +100,19 @@ public class ExpressionUrlAuthorizationConfigurerTests { .anyRequest().hasRole("ROLE_USER"); // @formatter:on } + } @Test public void configureWhenNoCustomAccessDecisionManagerThenUsesAffirmativeBased() { this.spring.register(NoSpecificAccessDecisionManagerConfig.class).autowire(); - verify(NoSpecificAccessDecisionManagerConfig.objectPostProcessor) - .postProcess(any(AffirmativeBased.class)); + verify(NoSpecificAccessDecisionManagerConfig.objectPostProcessor).postProcess(any(AffirmativeBased.class)); } @EnableWebSecurity static class NoSpecificAccessDecisionManagerConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class); @Override @@ -126,34 +128,37 @@ public class ExpressionUrlAuthorizationConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } @Test public void configureWhenAuthorizedRequestsAndNoRequestsThenException() { assertThatThrownBy(() -> this.spring.register(NoRequestsConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasMessageContaining("At least one mapping is required (i.e. authorizeRequests().anyRequest().authenticated())"); + .isInstanceOf(BeanCreationException.class).hasMessageContaining( + "At least one mapping is required (i.e. authorizeRequests().anyRequest().authenticated())"); } @EnableWebSecurity static class NoRequestsConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http .authorizeRequests(); // @formatter:on } + } @Test public void configureWhenAnyRequestIncompleteMappingThenException() { assertThatThrownBy(() -> this.spring.register(IncompleteMappingConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasMessageContaining("An incomplete mapping was found for "); + .isInstanceOf(BeanCreationException.class).hasMessageContaining("An incomplete mapping was found for "); } @EnableWebSecurity static class IncompleteMappingConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -163,15 +168,14 @@ public class ExpressionUrlAuthorizationConfigurerTests { .anyRequest(); // @formatter:on } + } @Test - public void getWhenHasAnyAuthorityRoleUserConfiguredAndAuthorityIsRoleUserThenRespondsWithOk() - throws Exception { + public void getWhenHasAnyAuthorityRoleUserConfiguredAndAuthorityIsRoleUserThenRespondsWithOk() throws Exception { this.spring.register(RoleUserAnyAuthorityConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user").authorities(new SimpleGrantedAuthority("ROLE_USER")))) + this.mvc.perform(get("/").with(user("user").authorities(new SimpleGrantedAuthority("ROLE_USER")))) .andExpect(status().isOk()); } @@ -180,22 +184,20 @@ public class ExpressionUrlAuthorizationConfigurerTests { throws Exception { this.spring.register(RoleUserAnyAuthorityConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user").authorities(new SimpleGrantedAuthority("ROLE_ADMIN")))) + this.mvc.perform(get("/").with(user("user").authorities(new SimpleGrantedAuthority("ROLE_ADMIN")))) .andExpect(status().isForbidden()); } @Test - public void getWhenHasAnyAuthorityRoleUserConfiguredAndNoAuthorityThenRespondsWithUnauthorized() - throws Exception { + public void getWhenHasAnyAuthorityRoleUserConfiguredAndNoAuthorityThenRespondsWithUnauthorized() throws Exception { this.spring.register(RoleUserAnyAuthorityConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/")).andExpect(status().isUnauthorized()); } @EnableWebSecurity static class RoleUserAnyAuthorityConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -206,15 +208,14 @@ public class ExpressionUrlAuthorizationConfigurerTests { .anyRequest().hasAnyAuthority("ROLE_USER"); // @formatter:on } + } @Test - public void getWhenHasAuthorityRoleUserConfiguredAndAuthorityIsRoleUserThenRespondsWithOk() - throws Exception { + public void getWhenHasAuthorityRoleUserConfiguredAndAuthorityIsRoleUserThenRespondsWithOk() throws Exception { this.spring.register(RoleUserAuthorityConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user").authorities(new SimpleGrantedAuthority("ROLE_USER")))) + this.mvc.perform(get("/").with(user("user").authorities(new SimpleGrantedAuthority("ROLE_USER")))) .andExpect(status().isOk()); } @@ -223,22 +224,20 @@ public class ExpressionUrlAuthorizationConfigurerTests { throws Exception { this.spring.register(RoleUserAuthorityConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user").authorities(new SimpleGrantedAuthority("ROLE_ADMIN")))) + this.mvc.perform(get("/").with(user("user").authorities(new SimpleGrantedAuthority("ROLE_ADMIN")))) .andExpect(status().isForbidden()); } @Test - public void getWhenHasAuthorityRoleUserConfiguredAndNoAuthorityThenRespondsWithUnauthorized() - throws Exception { + public void getWhenHasAuthorityRoleUserConfiguredAndNoAuthorityThenRespondsWithUnauthorized() throws Exception { this.spring.register(RoleUserAuthorityConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/")).andExpect(status().isUnauthorized()); } @EnableWebSecurity static class RoleUserAuthorityConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -249,25 +248,22 @@ public class ExpressionUrlAuthorizationConfigurerTests { .anyRequest().hasAuthority("ROLE_USER"); // @formatter:on } + } @Test - public void getWhenAuthorityRoleUserOrAdminRequiredAndAuthorityIsRoleUserThenRespondsWithOk() - throws Exception { + public void getWhenAuthorityRoleUserOrAdminRequiredAndAuthorityIsRoleUserThenRespondsWithOk() throws Exception { this.spring.register(RoleUserOrRoleAdminAuthorityConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user").authorities(new SimpleGrantedAuthority("ROLE_USER")))) + this.mvc.perform(get("/").with(user("user").authorities(new SimpleGrantedAuthority("ROLE_USER")))) .andExpect(status().isOk()); } @Test - public void getWhenAuthorityRoleUserOrAdminRequiredAndAuthorityIsRoleAdminThenRespondsWithOk() - throws Exception { + public void getWhenAuthorityRoleUserOrAdminRequiredAndAuthorityIsRoleAdminThenRespondsWithOk() throws Exception { this.spring.register(RoleUserOrRoleAdminAuthorityConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user").authorities(new SimpleGrantedAuthority("ROLE_ADMIN")))) + this.mvc.perform(get("/").with(user("user").authorities(new SimpleGrantedAuthority("ROLE_ADMIN")))) .andExpect(status().isOk()); } @@ -276,22 +272,20 @@ public class ExpressionUrlAuthorizationConfigurerTests { throws Exception { this.spring.register(RoleUserOrRoleAdminAuthorityConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user").authorities(new SimpleGrantedAuthority("ROLE_OTHER")))) + this.mvc.perform(get("/").with(user("user").authorities(new SimpleGrantedAuthority("ROLE_OTHER")))) .andExpect(status().isForbidden()); } @Test - public void getWhenAuthorityRoleUserOrAdminAuthRequiredAndNoUserThenRespondsWithUnauthorized() - throws Exception { + public void getWhenAuthorityRoleUserOrAdminAuthRequiredAndNoUserThenRespondsWithUnauthorized() throws Exception { this.spring.register(RoleUserOrRoleAdminAuthorityConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/")).andExpect(status().isUnauthorized()); } @EnableWebSecurity static class RoleUserOrRoleAdminAuthorityConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -302,28 +296,26 @@ public class ExpressionUrlAuthorizationConfigurerTests { .anyRequest().hasAnyAuthority("ROLE_USER", "ROLE_ADMIN"); // @formatter:on } + } @Test public void getWhenHasAnyRoleUserConfiguredAndRoleIsUserThenRespondsWithOk() throws Exception { this.spring.register(RoleUserConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user").roles("USER"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isOk()); } @Test public void getWhenHasAnyRoleUserConfiguredAndRoleIsAdminThenRespondsWithForbidden() throws Exception { this.spring.register(RoleUserConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user").roles("ADMIN"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/").with(user("user").roles("ADMIN"))).andExpect(status().isForbidden()); } @EnableWebSecurity static class RoleUserConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -332,37 +324,33 @@ public class ExpressionUrlAuthorizationConfigurerTests { .anyRequest().hasAnyRole("USER"); // @formatter:on } + } @Test public void getWhenRoleUserOrAdminConfiguredAndRoleIsUserThenRespondsWithOk() throws Exception { this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user").roles("USER"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isOk()); } @Test public void getWhenRoleUserOrAdminConfiguredAndRoleIsAdminThenRespondsWithOk() throws Exception { this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user").roles("ADMIN"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/").with(user("user").roles("ADMIN"))).andExpect(status().isOk()); } @Test public void getWhenRoleUserOrAdminConfiguredAndRoleIsOtherThenRespondsWithForbidden() throws Exception { this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user").roles("OTHER"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/").with(user("user").roles("OTHER"))).andExpect(status().isForbidden()); } @EnableWebSecurity static class RoleUserOrAdminConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -371,34 +359,32 @@ public class ExpressionUrlAuthorizationConfigurerTests { .anyRequest().hasAnyRole("USER", "ADMIN"); // @formatter:on } + } @Test public void getWhenHasIpAddressConfiguredAndIpAddressMatchesThenRespondsWithOk() throws Exception { this.spring.register(HasIpAddressConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(request -> { - request.setRemoteAddr("192.168.1.0"); - return request; - })) - .andExpect(status().isOk()); + this.mvc.perform(get("/").with(request -> { + request.setRemoteAddr("192.168.1.0"); + return request; + })).andExpect(status().isOk()); } @Test public void getWhenHasIpAddressConfiguredAndIpAddressDoesNotMatchThenRespondsWithUnauthorized() throws Exception { this.spring.register(HasIpAddressConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(request -> { - request.setRemoteAddr("192.168.1.1"); - return request; - })) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/").with(request -> { + request.setRemoteAddr("192.168.1.1"); + return request; + })).andExpect(status().isUnauthorized()); } @EnableWebSecurity static class HasIpAddressConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -409,27 +395,26 @@ public class ExpressionUrlAuthorizationConfigurerTests { .anyRequest().hasIpAddress("192.168.1.0"); // @formatter:on } + } @Test public void getWhenAnonymousConfiguredAndAnonymousUserThenRespondsWithOk() throws Exception { this.spring.register(AnonymousConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()); + this.mvc.perform(get("/")).andExpect(status().isOk()); } @Test public void getWhenAnonymousConfiguredAndLoggedInUserThenRespondsWithForbidden() throws Exception { this.spring.register(AnonymousConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/").with(user("user"))).andExpect(status().isForbidden()); } @EnableWebSecurity static class AnonymousConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -440,27 +425,28 @@ public class ExpressionUrlAuthorizationConfigurerTests { .anyRequest().anonymous(); // @formatter:on } + } @Test public void getWhenRememberMeConfiguredAndNoUserThenRespondsWithUnauthorized() throws Exception { this.spring.register(RememberMeConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/")).andExpect(status().isUnauthorized()); } @Test public void getWhenRememberMeConfiguredAndRememberMeTokenThenRespondsWithOk() throws Exception { this.spring.register(RememberMeConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(authentication(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER"))))) + this.mvc.perform(get("/").with(authentication( + new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER"))))) .andExpect(status().isOk()); } @EnableWebSecurity static class RememberMeConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -482,27 +468,26 @@ public class ExpressionUrlAuthorizationConfigurerTests { .withUser("user").password("password").roles("USER"); // @formatter:on } + } @Test public void getWhenDenyAllConfiguredAndNoUserThenRespondsWithUnauthorized() throws Exception { this.spring.register(DenyAllConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/")).andExpect(status().isUnauthorized()); } @Test public void getWheDenyAllConfiguredAndUserLoggedInThenRespondsWithForbidden() throws Exception { this.spring.register(DenyAllConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user").roles("USER"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isForbidden()); } @EnableWebSecurity static class DenyAllConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -513,27 +498,28 @@ public class ExpressionUrlAuthorizationConfigurerTests { .anyRequest().denyAll(); // @formatter:on } + } @Test public void getWhenNotDenyAllConfiguredAndNoUserThenRespondsWithOk() throws Exception { this.spring.register(NotDenyAllConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()); + this.mvc.perform(get("/")).andExpect(status().isOk()); } @Test public void getWhenNotDenyAllConfiguredAndRememberMeTokenThenRespondsWithOk() throws Exception { this.spring.register(NotDenyAllConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(authentication(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER"))))) + this.mvc.perform(get("/").with(authentication( + new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER"))))) .andExpect(status().isOk()); } @EnableWebSecurity static class NotDenyAllConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -544,14 +530,15 @@ public class ExpressionUrlAuthorizationConfigurerTests { .anyRequest().not().denyAll(); // @formatter:on } + } @Test public void getWhenFullyAuthenticatedConfiguredAndRememberMeTokenThenRespondsWithUnauthorized() throws Exception { this.spring.register(FullyAuthenticatedConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(authentication(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER"))))) + this.mvc.perform(get("/").with(authentication( + new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER"))))) .andExpect(status().isUnauthorized()); } @@ -559,13 +546,12 @@ public class ExpressionUrlAuthorizationConfigurerTests { public void getWhenFullyAuthenticatedConfiguredAndUserThenRespondsWithOk() throws Exception { this.spring.register(FullyAuthenticatedConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/") - .with(user("user").roles("USER"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isOk()); } @EnableWebSecurity static class FullyAuthenticatedConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -578,37 +564,33 @@ public class ExpressionUrlAuthorizationConfigurerTests { .anyRequest().fullyAuthenticated(); // @formatter:on } + } @Test public void getWhenAccessRoleUserOrGetRequestConfiguredThenRespondsWithOk() throws Exception { this.spring.register(AccessConfig.class, BasicController.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()); + this.mvc.perform(get("/")).andExpect(status().isOk()); } @Test public void postWhenAccessRoleUserOrGetRequestConfiguredAndRoleUserThenRespondsWithOk() throws Exception { this.spring.register(AccessConfig.class, BasicController.class).autowire(); - this.mvc.perform(post("/") - .with(csrf()) - .with(user("user").roles("USER"))) - .andExpect(status().isOk()); + this.mvc.perform(post("/").with(csrf()).with(user("user").roles("USER"))).andExpect(status().isOk()); } @Test public void postWhenAccessRoleUserOrGetRequestConfiguredThenRespondsWithUnauthorized() throws Exception { this.spring.register(AccessConfig.class, BasicController.class).autowire(); - this.mvc.perform(post("/") - .with(csrf())) - .andExpect(status().isUnauthorized()); + this.mvc.perform(post("/").with(csrf())).andExpect(status().isUnauthorized()); } @EnableWebSecurity static class AccessConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -621,19 +603,19 @@ public class ExpressionUrlAuthorizationConfigurerTests { .anyRequest().access("hasRole('ROLE_USER') or request.method == 'GET'"); // @formatter:on } + } @Test public void authorizeRequestsWhenInvokedTwiceThenUsesOriginalConfiguration() throws Exception { this.spring.register(InvokeTwiceDoesNotResetConfig.class, BasicController.class).autowire(); - this.mvc.perform(post("/") - .with(csrf())) - .andExpect(status().isUnauthorized()); + this.mvc.perform(post("/").with(csrf())).andExpect(status().isUnauthorized()); } @EnableWebSecurity static class InvokeTwiceDoesNotResetConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -646,6 +628,7 @@ public class ExpressionUrlAuthorizationConfigurerTests { .authorizeRequests(); // @formatter:on } + } @Test @@ -655,6 +638,7 @@ public class ExpressionUrlAuthorizationConfigurerTests { @EnableWebSecurity static class AllPropertiesWorkConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { SecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler(); @@ -672,6 +656,7 @@ public class ExpressionUrlAuthorizationConfigurerTests { .formLogin(); // @formatter:on } + } @Test @@ -686,6 +671,7 @@ public class ExpressionUrlAuthorizationConfigurerTests { @EnableWebSecurity static class AuthorizedRequestsWithPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ApplicationListener AL = mock(ApplicationListener.class); @Override @@ -708,46 +694,40 @@ public class ExpressionUrlAuthorizationConfigurerTests { public ApplicationListener applicationListener() { return AL; } + } @Test public void getWhenPermissionCheckAndRoleDoesNotMatchThenRespondsWithForbidden() throws Exception { this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire(); - this.mvc.perform(get("/admin") - .with(user("user").roles("USER"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/admin").with(user("user").roles("USER"))).andExpect(status().isForbidden()); } @Test public void getWhenPermissionCheckAndRoleMatchesThenRespondsWithOk() throws Exception { this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire(); - this.mvc.perform(get("/user") - .with(user("user").roles("USER"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/user").with(user("user").roles("USER"))).andExpect(status().isOk()); } @Test public void getWhenPermissionCheckAndAuthenticationNameMatchesThenRespondsWithOk() throws Exception { this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire(); - this.mvc.perform(get("/allow") - .with(user("user").roles("USER"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/allow").with(user("user").roles("USER"))).andExpect(status().isOk()); } @Test public void getWhenPermissionCheckAndAuthenticationNameDoesNotMatchThenRespondsWithForbidden() throws Exception { this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire(); - this.mvc.perform(get("/deny") - .with(user("user").roles("USER"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/deny").with(user("user").roles("USER"))).andExpect(status().isForbidden()); } @EnableWebSecurity static class UseBeansInExpressions extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -766,40 +746,34 @@ public class ExpressionUrlAuthorizationConfigurerTests { } static class Checker { + public boolean check(Authentication authentication, String customArg) { return authentication.getName().contains(customArg); } + } + } @Test - public void getWhenCustomExpressionHandlerAndRoleDoesNotMatchThenRespondsWithForbidden() - throws Exception { + public void getWhenCustomExpressionHandlerAndRoleDoesNotMatchThenRespondsWithForbidden() throws Exception { this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire(); - this.mvc.perform(get("/admin") - .with(user("user").roles("USER"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/admin").with(user("user").roles("USER"))).andExpect(status().isForbidden()); } @Test - public void getWhenCustomExpressionHandlerAndRoleMatchesThenRespondsWithOk() - throws Exception { + public void getWhenCustomExpressionHandlerAndRoleMatchesThenRespondsWithOk() throws Exception { this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire(); - this.mvc.perform(get("/user") - .with(user("user").roles("USER"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/user").with(user("user").roles("USER"))).andExpect(status().isOk()); } @Test - public void getWhenCustomExpressionHandlerAndAuthenticationNameMatchesThenRespondsWithOk() - throws Exception { + public void getWhenCustomExpressionHandlerAndAuthenticationNameMatchesThenRespondsWithOk() throws Exception { this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire(); - this.mvc.perform(get("/allow") - .with(user("user").roles("USER"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/allow").with(user("user").roles("USER"))).andExpect(status().isOk()); } @Test @@ -807,13 +781,12 @@ public class ExpressionUrlAuthorizationConfigurerTests { throws Exception { this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire(); - this.mvc.perform(get("/deny") - .with(user("user").roles("USER"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/deny").with(user("user").roles("USER"))).andExpect(status().isForbidden()); } @EnableWebSecurity static class CustomExpressionRootConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -835,14 +808,15 @@ public class ExpressionUrlAuthorizationConfigurerTests { static class CustomExpressionHandler extends DefaultWebSecurityExpressionHandler { @Override - protected SecurityExpressionOperations createSecurityExpressionRoot( - Authentication authentication, FilterInvocation fi) { + protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, + FilterInvocation fi) { WebSecurityExpressionRoot root = new CustomExpressionRoot(authentication, fi); root.setPermissionEvaluator(getPermissionEvaluator()); root.setTrustResolver(new AuthenticationTrustResolverImpl()); root.setRoleHierarchy(getRoleHierarchy()); return root; } + } static class CustomExpressionRoot extends WebSecurityExpressionRoot { @@ -855,20 +829,22 @@ public class ExpressionUrlAuthorizationConfigurerTests { Authentication auth = this.getAuthentication(); return auth.getName().contains(customArg); } + } + } - //SEC-3011 + // SEC-3011 @Test public void configureWhenRegisteringObjectPostProcessorThenInvokedOnAccessDecisionManager() { this.spring.register(Sec3011Config.class).autowire(); - verify(Sec3011Config.objectPostProcessor) - .postProcess(any(AccessDecisionManager.class)); + verify(Sec3011Config.objectPostProcessor).postProcess(any(AccessDecisionManager.class)); } @EnableWebSecurity static class Sec3011Config extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class); @Override @@ -892,6 +868,7 @@ public class ExpressionUrlAuthorizationConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } @Test @@ -899,8 +876,7 @@ public class ExpressionUrlAuthorizationConfigurerTests { throws Exception { this.spring.register(PermissionEvaluatorConfig.class, WildcardController.class).autowire(); - this.mvc.perform(get("/allow")) - .andExpect(status().isOk()); + this.mvc.perform(get("/allow")).andExpect(status().isOk()); } @Test @@ -908,8 +884,7 @@ public class ExpressionUrlAuthorizationConfigurerTests { throws Exception { this.spring.register(PermissionEvaluatorConfig.class, WildcardController.class).autowire(); - this.mvc.perform(get("/deny")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/deny")).andExpect(status().isForbidden()); } @Test @@ -917,8 +892,7 @@ public class ExpressionUrlAuthorizationConfigurerTests { throws Exception { this.spring.register(PermissionEvaluatorConfig.class, WildcardController.class).autowire(); - this.mvc.perform(get("/allowObject")) - .andExpect(status().isOk()); + this.mvc.perform(get("/allowObject")).andExpect(status().isOk()); } @Test @@ -926,12 +900,12 @@ public class ExpressionUrlAuthorizationConfigurerTests { throws Exception { this.spring.register(PermissionEvaluatorConfig.class, WildcardController.class).autowire(); - this.mvc.perform(get("/denyObject")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/denyObject")).andExpect(status().isForbidden()); } @EnableWebSecurity static class PermissionEvaluatorConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -949,7 +923,8 @@ public class ExpressionUrlAuthorizationConfigurerTests { public PermissionEvaluator permissionEvaluator() { return new PermissionEvaluator() { @Override - public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) { + public boolean hasPermission(Authentication authentication, Object targetDomainObject, + Object permission) { return "TESTOBJ".equals(targetDomainObject) && "PERMISSION".equals(permission); } @@ -960,28 +935,26 @@ public class ExpressionUrlAuthorizationConfigurerTests { } }; } + } @Test public void getWhenRegisteringRoleHierarchyAndRelatedRoleAllowedThenRespondsWithOk() throws Exception { this.spring.register(RoleHierarchyConfig.class, WildcardController.class).autowire(); - this.mvc.perform(get("/allow") - .with(user("user").roles("USER"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/allow").with(user("user").roles("USER"))).andExpect(status().isOk()); } @Test public void getWhenRegisteringRoleHierarchyAndNoRelatedRolesAllowedThenRespondsWithForbidden() throws Exception { this.spring.register(RoleHierarchyConfig.class, WildcardController.class).autowire(); - this.mvc.perform(get("/deny") - .with(user("user").roles("USER"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/deny").with(user("user").roles("USER"))).andExpect(status().isForbidden()); } @EnableWebSecurity static class RoleHierarchyConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -999,10 +972,12 @@ public class ExpressionUrlAuthorizationConfigurerTests { roleHierarchy.setHierarchy("ROLE_USER > ROLE_MEMBER"); return roleHierarchy; } + } @RestController static class BasicController { + @GetMapping("/") public void rootGet() { } @@ -1010,19 +985,25 @@ public class ExpressionUrlAuthorizationConfigurerTests { @PostMapping("/") public void rootPost() { } + } @RestController static class WildcardController { + @GetMapping("/{path}") public void wildcard(@PathVariable String path) { } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.java index 736cc130a6..4eb2835e9a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.java @@ -58,6 +58,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @since 5.1 */ public class FormLoginConfigurerTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -66,19 +67,18 @@ public class FormLoginConfigurerTests { @Test public void requestCache() throws Exception { - this.spring.register(RequestCacheConfig.class, - AuthenticationTestConfiguration.class).autowire(); + this.spring.register(RequestCacheConfig.class, AuthenticationTestConfiguration.class).autowire(); RequestCacheConfig config = this.spring.getContext().getBean(RequestCacheConfig.class); - this.mockMvc.perform(formLogin()) - .andExpect(authenticated()); + this.mockMvc.perform(formLogin()).andExpect(authenticated()); verify(config.requestCache).getRequest(any(), any()); } @EnableWebSecurity static class RequestCacheConfig extends WebSecurityConfigurerAdapter { + private RequestCache requestCache = mock(RequestCache.class); @Override @@ -90,27 +90,28 @@ public class FormLoginConfigurerTests { .requestCache(this.requestCache); // @formatter:on } + } @Test public void requestCacheAsBean() throws Exception { - this.spring.register(RequestCacheBeanConfig.class, - AuthenticationTestConfiguration.class).autowire(); + this.spring.register(RequestCacheBeanConfig.class, AuthenticationTestConfiguration.class).autowire(); RequestCache requestCache = this.spring.getContext().getBean(RequestCache.class); - this.mockMvc.perform(formLogin()) - .andExpect(authenticated()); + this.mockMvc.perform(formLogin()).andExpect(authenticated()); verify(requestCache).getRequest(any(), any()); } @EnableWebSecurity static class RequestCacheBeanConfig { + @Bean RequestCache requestCache() { return mock(RequestCache.class); } + } @Test @@ -118,16 +119,14 @@ public class FormLoginConfigurerTests { this.spring.register(FormLoginConfig.class).autowire(); this.mockMvc.perform(formLogin().user("username", "user").password("password", "password")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/")); + .andExpect(status().isFound()).andExpect(redirectedUrl("/")); } @Test public void loginWhenFormLoginConfiguredThenHasDefaultFailureUrl() throws Exception { this.spring.register(FormLoginConfig.class).autowire(); - this.mockMvc.perform(formLogin().user("invalid")) - .andExpect(status().isFound()) + this.mockMvc.perform(formLogin().user("invalid")).andExpect(status().isFound()) .andExpect(redirectedUrl("/login?error")); } @@ -135,38 +134,34 @@ public class FormLoginConfigurerTests { public void loginWhenFormLoginConfiguredThenHasDefaultSuccessUrl() throws Exception { this.spring.register(FormLoginConfig.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/")); + this.mockMvc.perform(formLogin()).andExpect(status().isFound()).andExpect(redirectedUrl("/")); } @Test public void getLoginPageWhenFormLoginConfiguredThenNotSecured() throws Exception { this.spring.register(FormLoginConfig.class).autowire(); - this.mockMvc.perform(get("/login")) - .andExpect(status().isFound()); + this.mockMvc.perform(get("/login")).andExpect(status().isFound()); } @Test public void loginWhenFormLoginConfiguredThenSecured() throws Exception { this.spring.register(FormLoginConfig.class).autowire(); - this.mockMvc.perform(post("/login")) - .andExpect(status().isForbidden()); + this.mockMvc.perform(post("/login")).andExpect(status().isForbidden()); } @Test public void requestProtectedWhenFormLoginConfiguredThenRedirectsToLogin() throws Exception { this.spring.register(FormLoginConfig.class).autowire(); - this.mockMvc.perform(get("/private")) - .andExpect(status().isFound()) + this.mockMvc.perform(get("/private")).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/login")); } @EnableWebSecurity static class FormLoginConfig extends WebSecurityConfigurerAdapter { + @Override public void configure(WebSecurity web) { // @formatter:off @@ -196,6 +191,7 @@ public class FormLoginConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test @@ -203,16 +199,14 @@ public class FormLoginConfigurerTests { this.spring.register(FormLoginInLambdaConfig.class).autowire(); this.mockMvc.perform(formLogin().user("username", "user").password("password", "password")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/")); + .andExpect(status().isFound()).andExpect(redirectedUrl("/")); } @Test public void loginWhenFormLoginDefaultsInLambdaThenHasDefaultFailureUrl() throws Exception { this.spring.register(FormLoginInLambdaConfig.class).autowire(); - this.mockMvc.perform(formLogin().user("invalid")) - .andExpect(status().isFound()) + this.mockMvc.perform(formLogin().user("invalid")).andExpect(status().isFound()) .andExpect(redirectedUrl("/login?error")); } @@ -220,38 +214,34 @@ public class FormLoginConfigurerTests { public void loginWhenFormLoginDefaultsInLambdaThenHasDefaultSuccessUrl() throws Exception { this.spring.register(FormLoginInLambdaConfig.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/")); + this.mockMvc.perform(formLogin()).andExpect(status().isFound()).andExpect(redirectedUrl("/")); } @Test public void getLoginPageWhenFormLoginDefaultsInLambdaThenNotSecured() throws Exception { this.spring.register(FormLoginInLambdaConfig.class).autowire(); - this.mockMvc.perform(get("/login")) - .andExpect(status().isOk()); + this.mockMvc.perform(get("/login")).andExpect(status().isOk()); } @Test public void loginWhenFormLoginDefaultsInLambdaThenSecured() throws Exception { this.spring.register(FormLoginInLambdaConfig.class).autowire(); - this.mockMvc.perform(post("/login")) - .andExpect(status().isForbidden()); + this.mockMvc.perform(post("/login")).andExpect(status().isForbidden()); } @Test public void requestProtectedWhenFormLoginDefaultsInLambdaThenRedirectsToLogin() throws Exception { this.spring.register(FormLoginInLambdaConfig.class).autowire(); - this.mockMvc.perform(get("/private")) - .andExpect(status().isFound()) + this.mockMvc.perform(get("/private")).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/login")); } @EnableWebSecurity static class FormLoginInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -272,37 +262,34 @@ public class FormLoginConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test public void getLoginPageWhenFormLoginPermitAllThenPermittedAndNoRedirect() throws Exception { this.spring.register(FormLoginConfigPermitAll.class).autowire(); - this.mockMvc.perform(get("/login")) - .andExpect(status().isOk()) - .andExpect(redirectedUrl(null)); + this.mockMvc.perform(get("/login")).andExpect(status().isOk()).andExpect(redirectedUrl(null)); } @Test public void getLoginPageWithErrorQueryWhenFormLoginPermitAllThenPermittedAndNoRedirect() throws Exception { this.spring.register(FormLoginConfigPermitAll.class).autowire(); - this.mockMvc.perform(get("/login?error")) - .andExpect(status().isOk()) - .andExpect(redirectedUrl(null)); + this.mockMvc.perform(get("/login?error")).andExpect(status().isOk()).andExpect(redirectedUrl(null)); } @Test public void loginWhenFormLoginPermitAllAndInvalidUserThenRedirectsToLoginPageWithError() throws Exception { this.spring.register(FormLoginConfigPermitAll.class).autowire(); - this.mockMvc.perform(formLogin().user("invalid")) - .andExpect(status().isFound()) + this.mockMvc.perform(formLogin().user("invalid")).andExpect(status().isFound()) .andExpect(redirectedUrl("/login?error")); } @EnableWebSecurity static class FormLoginConfigPermitAll extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -314,30 +301,28 @@ public class FormLoginConfigurerTests { .permitAll(); // @formatter:on } + } @Test public void getLoginPageWhenCustomLoginPageThenPermittedAndNoRedirect() throws Exception { this.spring.register(FormLoginDefaultsConfig.class).autowire(); - this.mockMvc.perform(get("/authenticate")) - .andExpect(redirectedUrl(null)); + this.mockMvc.perform(get("/authenticate")).andExpect(redirectedUrl(null)); } @Test public void getLoginPageWithErrorQueryWhenCustomLoginPageThenPermittedAndNoRedirect() throws Exception { this.spring.register(FormLoginDefaultsConfig.class).autowire(); - this.mockMvc.perform(get("/authenticate?error")) - .andExpect(redirectedUrl(null)); + this.mockMvc.perform(get("/authenticate?error")).andExpect(redirectedUrl(null)); } @Test public void loginWhenCustomLoginPageAndInvalidUserThenRedirectsToCustomLoginPageWithError() throws Exception { this.spring.register(FormLoginDefaultsConfig.class).autowire(); - this.mockMvc.perform(formLogin("/authenticate").user("invalid")) - .andExpect(status().isFound()) + this.mockMvc.perform(formLogin("/authenticate").user("invalid")).andExpect(status().isFound()) .andExpect(redirectedUrl("/authenticate?error")); } @@ -345,20 +330,19 @@ public class FormLoginConfigurerTests { public void logoutWhenCustomLoginPageThenRedirectsToCustomLoginPage() throws Exception { this.spring.register(FormLoginDefaultsConfig.class).autowire(); - this.mockMvc.perform(logout()) - .andExpect(redirectedUrl("/authenticate?logout")); + this.mockMvc.perform(logout()).andExpect(redirectedUrl("/authenticate?logout")); } @Test public void getLoginPageWithLogoutQueryWhenCustomLoginPageThenPermittedAndNoRedirect() throws Exception { this.spring.register(FormLoginDefaultsConfig.class).autowire(); - this.mockMvc.perform(get("/authenticate?logout")) - .andExpect(redirectedUrl(null)); + this.mockMvc.perform(get("/authenticate?logout")).andExpect(redirectedUrl(null)); } @EnableWebSecurity static class FormLoginDefaultsConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -374,18 +358,19 @@ public class FormLoginConfigurerTests { .permitAll(); // @formatter:on } + } @Test public void getLoginPageWhenCustomLoginPageInLambdaThenPermittedAndNoRedirect() throws Exception { this.spring.register(FormLoginDefaultsInLambdaConfig.class).autowire(); - this.mockMvc.perform(get("/authenticate")) - .andExpect(redirectedUrl(null)); + this.mockMvc.perform(get("/authenticate")).andExpect(redirectedUrl(null)); } @EnableWebSecurity static class FormLoginDefaultsInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -402,19 +387,19 @@ public class FormLoginConfigurerTests { .logout(LogoutConfigurer::permitAll); // @formatter:on } + } @Test public void loginWhenCustomLoginProcessingUrlThenRedirectsToHome() throws Exception { this.spring.register(FormLoginLoginProcessingUrlConfig.class).autowire(); - this.mockMvc.perform(formLogin("/loginCheck")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/")); + this.mockMvc.perform(formLogin("/loginCheck")).andExpect(status().isFound()).andExpect(redirectedUrl("/")); } @EnableWebSecurity static class FormLoginLoginProcessingUrlConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -445,19 +430,19 @@ public class FormLoginConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test public void loginWhenCustomLoginProcessingUrlInLambdaThenRedirectsToHome() throws Exception { this.spring.register(FormLoginLoginProcessingUrlInLambdaConfig.class).autowire(); - this.mockMvc.perform(formLogin("/loginCheck")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/")); + this.mockMvc.perform(formLogin("/loginCheck")).andExpect(status().isFound()).andExpect(redirectedUrl("/")); } @EnableWebSecurity static class FormLoginLoginProcessingUrlInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -490,6 +475,7 @@ public class FormLoginConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test @@ -498,8 +484,7 @@ public class FormLoginConfigurerTests { when(FormLoginUsesPortMapperConfig.PORT_MAPPER.lookupHttpsPort(any())).thenReturn(9443); this.spring.register(FormLoginUsesPortMapperConfig.class).autowire(); - this.mockMvc.perform(get("http://localhost:9090")) - .andExpect(status().isFound()) + this.mockMvc.perform(get("http://localhost:9090")).andExpect(status().isFound()) .andExpect(redirectedUrl("https://localhost:9443/login")); verify(FormLoginUsesPortMapperConfig.PORT_MAPPER).lookupHttpsPort(any()); @@ -507,6 +492,7 @@ public class FormLoginConfigurerTests { @EnableWebSecurity static class FormLoginUsesPortMapperConfig extends WebSecurityConfigurerAdapter { + static PortMapper PORT_MAPPER; @Override @@ -522,23 +508,24 @@ public class FormLoginConfigurerTests { .portMapper() .portMapper(PORT_MAPPER); // @formatter:on - LoginUrlAuthenticationEntryPoint authenticationEntryPoint = - (LoginUrlAuthenticationEntryPoint) http.getConfigurer(FormLoginConfigurer.class).getAuthenticationEntryPoint(); + LoginUrlAuthenticationEntryPoint authenticationEntryPoint = (LoginUrlAuthenticationEntryPoint) http + .getConfigurer(FormLoginConfigurer.class).getAuthenticationEntryPoint(); authenticationEntryPoint.setForceHttps(true); } + } @Test public void failureUrlWhenPermitAllAndFailureHandlerThenSecured() throws Exception { this.spring.register(PermitAllIgnoresFailureHandlerConfig.class).autowire(); - this.mockMvc.perform(get("/login?error")) - .andExpect(status().isFound()) + this.mockMvc.perform(get("/login?error")).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/login")); } @EnableWebSecurity static class PermitAllIgnoresFailureHandlerConfig extends WebSecurityConfigurerAdapter { + static AuthenticationFailureHandler FAILURE_HANDLER = mock(AuthenticationFailureHandler.class); @Override @@ -553,18 +540,19 @@ public class FormLoginConfigurerTests { .permitAll(); // @formatter:on } + } @Test public void formLoginWhenInvokedTwiceThenUsesOriginalUsernameParameter() throws Exception { this.spring.register(DuplicateInvocationsDoesNotOverrideConfig.class).autowire(); - this.mockMvc.perform(formLogin().user("custom-username", "user")) - .andExpect(authenticated()); + this.mockMvc.perform(formLogin().user("custom-username", "user")).andExpect(authenticated()); } @EnableWebSecurity static class DuplicateInvocationsDoesNotOverrideConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -584,22 +572,21 @@ public class FormLoginConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test public void loginWhenInvalidLoginAndFailureForwardUrlThenForwardsToFailureForwardUrl() throws Exception { this.spring.register(FormLoginUserForwardAuthenticationSuccessAndFailureConfig.class).autowire(); - this.mockMvc.perform(formLogin().user("invalid")) - .andExpect(forwardedUrl("/failure_forward_url")); + this.mockMvc.perform(formLogin().user("invalid")).andExpect(forwardedUrl("/failure_forward_url")); } @Test public void loginWhenSuccessForwardUrlThenForwardsToSuccessForwardUrl() throws Exception { this.spring.register(FormLoginUserForwardAuthenticationSuccessAndFailureConfig.class).autowire(); - this.mockMvc.perform(formLogin()) - .andExpect(forwardedUrl("/success_forward_url")); + this.mockMvc.perform(formLogin()).andExpect(forwardedUrl("/success_forward_url")); } @EnableWebSecurity @@ -629,6 +616,7 @@ public class FormLoginConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test @@ -645,8 +633,7 @@ public class FormLoginConfigurerTests { ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class); this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(LoginUrlAuthenticationEntryPoint.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(LoginUrlAuthenticationEntryPoint.class)); } @Test @@ -654,12 +641,12 @@ public class FormLoginConfigurerTests { ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class); this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(ExceptionTranslationFilter.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(ExceptionTranslationFilter.class)); } @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor; @Override @@ -676,12 +663,16 @@ public class FormLoginConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerEagerHeadersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerEagerHeadersTests.java index f3a21064ff..874d2f889d 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerEagerHeadersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerEagerHeadersTests.java @@ -46,33 +46,32 @@ public class HeadersConfigurerEagerHeadersTests { @EnableWebSecurity public static class HeadersAtTheBeginningOfRequestConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { - //@ formatter:off - http - .headers() - .addObjectPostProcessor(new ObjectPostProcessor() { - @Override - public HeaderWriterFilter postProcess(HeaderWriterFilter filter) { - filter.setShouldWriteHeadersEagerly(true); - return filter; - } - }); - //@ formatter:on + // @ formatter:off + http.headers().addObjectPostProcessor(new ObjectPostProcessor() { + @Override + public HeaderWriterFilter postProcess(HeaderWriterFilter filter) { + filter.setShouldWriteHeadersEagerly(true); + return filter; + } + }); + // @ formatter:on } + } @Test public void requestWhenHeadersEagerlyConfiguredThenHeadersAreWritten() throws Exception { this.spring.register(HeadersAtTheBeginningOfRequestConfig.class).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(header().string("X-Content-Type-Options", "nosniff")) + this.mvc.perform(get("/").secure(true)).andExpect(header().string("X-Content-Type-Options", "nosniff")) .andExpect(header().string("X-Frame-Options", "DENY")) .andExpect(header().string("Strict-Transport-Security", "max-age=31536000 ; includeSubDomains")) .andExpect(header().string(CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate")) - .andExpect(header().string(EXPIRES, "0")) - .andExpect(header().string(PRAGMA, "no-cache")) + .andExpect(header().string(EXPIRES, "0")).andExpect(header().string(PRAGMA, "no-cache")) .andExpect(header().string("X-XSS-Protection", "1; mode=block")); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.java index 390925e8d5..6f2fd87029 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.java @@ -65,12 +65,12 @@ public class HeadersConfigurerTests { MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) .andExpect(header().string(HttpHeaders.X_CONTENT_TYPE_OPTIONS, "nosniff")) .andExpect(header().string(HttpHeaders.X_FRAME_OPTIONS, XFrameOptionsMode.DENY.name())) - .andExpect(header().string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains")) + .andExpect( + header().string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains")) .andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate")) .andExpect(header().string(HttpHeaders.EXPIRES, "0")) .andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")) - .andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")) - .andReturn(); + .andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactlyInAnyOrder( HttpHeaders.X_CONTENT_TYPE_OPTIONS, HttpHeaders.X_FRAME_OPTIONS, HttpHeaders.STRICT_TRANSPORT_SECURITY, HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA, HttpHeaders.X_XSS_PROTECTION); @@ -86,6 +86,7 @@ public class HeadersConfigurerTests { .headers(); // @formatter:on } + } @Test @@ -95,12 +96,12 @@ public class HeadersConfigurerTests { MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) .andExpect(header().string(HttpHeaders.X_CONTENT_TYPE_OPTIONS, "nosniff")) .andExpect(header().string(HttpHeaders.X_FRAME_OPTIONS, XFrameOptionsMode.DENY.name())) - .andExpect(header().string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains")) + .andExpect( + header().string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains")) .andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate")) .andExpect(header().string(HttpHeaders.EXPIRES, "0")) .andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")) - .andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")) - .andReturn(); + .andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactlyInAnyOrder( HttpHeaders.X_CONTENT_TYPE_OPTIONS, HttpHeaders.X_FRAME_OPTIONS, HttpHeaders.STRICT_TRANSPORT_SECURITY, HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA, HttpHeaders.X_XSS_PROTECTION); @@ -116,6 +117,7 @@ public class HeadersConfigurerTests { .headers(withDefaults()); // @formatter:on } + } @Test @@ -124,8 +126,7 @@ public class HeadersConfigurerTests { this.spring.register(ContentTypeOptionsConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/")) - .andExpect(header().string(HttpHeaders.X_CONTENT_TYPE_OPTIONS, "nosniff")) - .andReturn(); + .andExpect(header().string(HttpHeaders.X_CONTENT_TYPE_OPTIONS, "nosniff")).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_CONTENT_TYPE_OPTIONS); } @@ -141,16 +142,15 @@ public class HeadersConfigurerTests { .contentTypeOptions(); // @formatter:on } + } @Test - public void getWhenOnlyContentTypeConfiguredInLambdaThenOnlyContentTypeHeaderInResponse() - throws Exception { + public void getWhenOnlyContentTypeConfiguredInLambdaThenOnlyContentTypeHeaderInResponse() throws Exception { this.spring.register(ContentTypeOptionsInLambdaConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/")) - .andExpect(header().string(HttpHeaders.X_CONTENT_TYPE_OPTIONS, "nosniff")) - .andReturn(); + .andExpect(header().string(HttpHeaders.X_CONTENT_TYPE_OPTIONS, "nosniff")).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_CONTENT_TYPE_OPTIONS); } @@ -168,6 +168,7 @@ public class HeadersConfigurerTests { ); // @formatter:on } + } @Test @@ -176,8 +177,7 @@ public class HeadersConfigurerTests { this.spring.register(FrameOptionsConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/")) - .andExpect(header().string(HttpHeaders.X_FRAME_OPTIONS, XFrameOptionsMode.DENY.name())) - .andReturn(); + .andExpect(header().string(HttpHeaders.X_FRAME_OPTIONS, XFrameOptionsMode.DENY.name())).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_FRAME_OPTIONS); } @@ -193,6 +193,7 @@ public class HeadersConfigurerTests { .frameOptions(); // @formatter:on } + } @Test @@ -201,7 +202,8 @@ public class HeadersConfigurerTests { this.spring.register(HstsConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains")) + .andExpect( + header().string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains")) .andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.STRICT_TRANSPORT_SECURITY); } @@ -218,6 +220,7 @@ public class HeadersConfigurerTests { .httpStrictTransportSecurity(); // @formatter:on } + } @Test @@ -228,8 +231,7 @@ public class HeadersConfigurerTests { MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) .andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate")) .andExpect(header().string(HttpHeaders.EXPIRES, "0")) - .andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")) - .andReturn(); + .andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactlyInAnyOrder(HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA); } @@ -246,6 +248,7 @@ public class HeadersConfigurerTests { .cacheControl(); // @formatter:on } + } @Test @@ -256,8 +259,7 @@ public class HeadersConfigurerTests { MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) .andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate")) .andExpect(header().string(HttpHeaders.EXPIRES, "0")) - .andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")) - .andReturn(); + .andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactlyInAnyOrder(HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA); } @@ -276,6 +278,7 @@ public class HeadersConfigurerTests { ); // @formatter:on } + } @Test @@ -284,8 +287,7 @@ public class HeadersConfigurerTests { this.spring.register(XssProtectionConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")) - .andReturn(); + .andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION); } @@ -301,16 +303,15 @@ public class HeadersConfigurerTests { .xssProtection(); // @formatter:on } + } @Test - public void getWhenOnlyXssProtectionConfiguredInLambdaThenOnlyXssProtectionHeaderInResponse() - throws Exception { + public void getWhenOnlyXssProtectionConfiguredInLambdaThenOnlyXssProtectionHeaderInResponse() throws Exception { this.spring.register(XssProtectionInLambdaConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")) - .andReturn(); + .andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION); } @@ -328,6 +329,7 @@ public class HeadersConfigurerTests { ); // @formatter:on } + } @Test @@ -350,6 +352,7 @@ public class HeadersConfigurerTests { .frameOptions().sameOrigin(); // @formatter:on } + } @Test @@ -375,14 +378,14 @@ public class HeadersConfigurerTests { ); // @formatter:on } + } @Test public void getWhenHeaderDefaultsDisabledAndPublicHpkpWithNoPinThenNoHeadersInResponse() throws Exception { this.spring.register(HpkpConfigNoPins.class).autowire(); - MvcResult mvcResult = this.mvc.perform(get("/")) - .andReturn(); + MvcResult mvcResult = this.mvc.perform(get("/")).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).isEmpty(); } @@ -398,11 +401,11 @@ public class HeadersConfigurerTests { .httpPublicKeyPinning(); // @formatter:on } + } @Test - public void getWhenSecureRequestAndHpkpWithPinThenPublicKeyPinsReportOnlyHeaderInResponse() - throws Exception { + public void getWhenSecureRequestAndHpkpWithPinThenPublicKeyPinsReportOnlyHeaderInResponse() throws Exception { this.spring.register(HpkpConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) @@ -413,12 +416,10 @@ public class HeadersConfigurerTests { } @Test - public void getWhenInsecureRequestHeaderDefaultsDisabledAndHpkpWithPinThenNoHeadersInResponse() - throws Exception { + public void getWhenInsecureRequestHeaderDefaultsDisabledAndHpkpWithPinThenNoHeadersInResponse() throws Exception { this.spring.register(HpkpConfig.class).autowire(); - MvcResult mvcResult = this.mvc.perform(get("/")) - .andReturn(); + MvcResult mvcResult = this.mvc.perform(get("/")).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).isEmpty(); } @@ -435,6 +436,7 @@ public class HeadersConfigurerTests { .addSha256Pins("d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="); // @formatter:on } + } @Test @@ -442,9 +444,9 @@ public class HeadersConfigurerTests { throws Exception { this.spring.register(HpkpConfigWithPins.class).autowire(); - MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY, - "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\"")) + MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string( + HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY, + "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\"")) .andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY); } @@ -466,6 +468,7 @@ public class HeadersConfigurerTests { .withPins(pins); // @formatter:on } + } @Test @@ -493,6 +496,7 @@ public class HeadersConfigurerTests { .maxAgeInSeconds(604800); // @formatter:on } + } @Test @@ -520,6 +524,7 @@ public class HeadersConfigurerTests { .reportOnly(false); // @formatter:on } + } @Test @@ -527,9 +532,9 @@ public class HeadersConfigurerTests { throws Exception { this.spring.register(HpkpConfigIncludeSubDomains.class).autowire(); - MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY, - "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; includeSubDomains")) + MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string( + HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY, + "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; includeSubDomains")) .andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY); } @@ -548,15 +553,16 @@ public class HeadersConfigurerTests { .includeSubDomains(true); // @formatter:on } + } @Test public void getWhenHpkpWithReportUriThenPublicKeyPinsReportOnlyHeaderWithReportUriInResponse() throws Exception { this.spring.register(HpkpConfigWithReportURI.class).autowire(); - MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY, - "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\"")) + MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string( + HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY, + "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\"")) .andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY); } @@ -575,6 +581,7 @@ public class HeadersConfigurerTests { .reportUri(new URI("https://example.net/pkp-report")); // @formatter:on } + } @Test @@ -582,9 +589,9 @@ public class HeadersConfigurerTests { throws Exception { this.spring.register(HpkpConfigWithReportURIAsString.class).autowire(); - MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY, - "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\"")) + MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string( + HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY, + "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\"")) .andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY); } @@ -603,6 +610,7 @@ public class HeadersConfigurerTests { .reportUri("https://example.net/pkp-report"); // @formatter:on } + } @Test @@ -610,9 +618,9 @@ public class HeadersConfigurerTests { throws Exception { this.spring.register(HpkpWithReportUriInLambdaConfig.class).autowire(); - MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY, - "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\"")) + MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string( + HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY, + "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\"")) .andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY); } @@ -635,6 +643,7 @@ public class HeadersConfigurerTests { ); // @formatter:on } + } @Test @@ -642,8 +651,7 @@ public class HeadersConfigurerTests { this.spring.register(ContentSecurityPolicyDefaultConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY, "default-src 'self'")) - .andReturn(); + .andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY, "default-src 'self'")).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY); } @@ -659,17 +667,20 @@ public class HeadersConfigurerTests { .contentSecurityPolicy("default-src 'self'"); // @formatter:on } + } @Test - public void getWhenContentSecurityPolicyWithReportOnlyThenContentSecurityPolicyReportOnlyHeaderInResponse() throws Exception { + public void getWhenContentSecurityPolicyWithReportOnlyThenContentSecurityPolicyReportOnlyHeaderInResponse() + throws Exception { this.spring.register(ContentSecurityPolicyReportOnlyConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) .andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY, "default-src 'self'; script-src trustedscripts.example.com")) .andReturn(); - assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY); + assertThat(mvcResult.getResponse().getHeaderNames()) + .containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY); } @EnableWebSecurity @@ -685,6 +696,7 @@ public class HeadersConfigurerTests { .reportOnly(); // @formatter:on } + } @Test @@ -696,7 +708,8 @@ public class HeadersConfigurerTests { .andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY, "default-src 'self'; script-src trustedscripts.example.com")) .andReturn(); - assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY); + assertThat(mvcResult.getResponse().getHeaderNames()) + .containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY); } @EnableWebSecurity @@ -717,13 +730,13 @@ public class HeadersConfigurerTests { ); // @formatter:on } + } @Test public void configureWhenContentSecurityPolicyEmptyThenException() { assertThatThrownBy(() -> this.spring.register(ContentSecurityPolicyInvalidConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasRootCauseInstanceOf(IllegalArgumentException.class); + .isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class); } @EnableWebSecurity @@ -738,13 +751,13 @@ public class HeadersConfigurerTests { .contentSecurityPolicy(""); // @formatter:on } + } @Test public void configureWhenContentSecurityPolicyEmptyInLambdaThenException() { assertThatThrownBy(() -> this.spring.register(ContentSecurityPolicyInvalidInLambdaConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasRootCauseInstanceOf(IllegalArgumentException.class); + .isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class); } @EnableWebSecurity @@ -763,6 +776,7 @@ public class HeadersConfigurerTests { ); // @formatter:on } + } @Test @@ -770,9 +784,7 @@ public class HeadersConfigurerTests { this.spring.register(ContentSecurityPolicyNoDirectivesInLambdaConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY, - "default-src 'self'")) - .andReturn(); + .andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY, "default-src 'self'")).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY); } @@ -790,6 +802,7 @@ public class HeadersConfigurerTests { ); // @formatter:on } + } @Test @@ -797,8 +810,7 @@ public class HeadersConfigurerTests { this.spring.register(ReferrerPolicyDefaultConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string("Referrer-Policy", ReferrerPolicy.NO_REFERRER.getPolicy())) - .andReturn(); + .andExpect(header().string("Referrer-Policy", ReferrerPolicy.NO_REFERRER.getPolicy())).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy"); } @@ -814,6 +826,7 @@ public class HeadersConfigurerTests { .referrerPolicy(); // @formatter:on } + } @Test @@ -821,8 +834,7 @@ public class HeadersConfigurerTests { this.spring.register(ReferrerPolicyDefaultInLambdaConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string("Referrer-Policy", ReferrerPolicy.NO_REFERRER.getPolicy())) - .andReturn(); + .andExpect(header().string("Referrer-Policy", ReferrerPolicy.NO_REFERRER.getPolicy())).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy"); } @@ -840,6 +852,7 @@ public class HeadersConfigurerTests { ); // @formatter:on } + } @Test @@ -848,8 +861,7 @@ public class HeadersConfigurerTests { this.spring.register(ReferrerPolicyCustomConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string("Referrer-Policy", ReferrerPolicy.SAME_ORIGIN.getPolicy())) - .andReturn(); + .andExpect(header().string("Referrer-Policy", ReferrerPolicy.SAME_ORIGIN.getPolicy())).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy"); } @@ -865,6 +877,7 @@ public class HeadersConfigurerTests { .referrerPolicy(ReferrerPolicy.SAME_ORIGIN); // @formatter:on } + } @Test @@ -872,8 +885,7 @@ public class HeadersConfigurerTests { this.spring.register(ReferrerPolicyCustomInLambdaConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string("Referrer-Policy", ReferrerPolicy.SAME_ORIGIN.getPolicy())) - .andReturn(); + .andExpect(header().string("Referrer-Policy", ReferrerPolicy.SAME_ORIGIN.getPolicy())).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy"); } @@ -893,6 +905,7 @@ public class HeadersConfigurerTests { ); // @formatter:on } + } @Test @@ -900,8 +913,7 @@ public class HeadersConfigurerTests { this.spring.register(FeaturePolicyConfig.class).autowire(); MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string("Feature-Policy", "geolocation 'self'")) - .andReturn(); + .andExpect(header().string("Feature-Policy", "geolocation 'self'")).andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Feature-Policy"); } @@ -917,13 +929,13 @@ public class HeadersConfigurerTests { .featurePolicy("geolocation 'self'"); // @formatter:on } + } @Test public void configureWhenFeaturePolicyEmptyThenException() { assertThatThrownBy(() -> this.spring.register(FeaturePolicyInvalidConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasRootCauseInstanceOf(IllegalArgumentException.class); + .isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class); } @EnableWebSecurity @@ -938,6 +950,7 @@ public class HeadersConfigurerTests { .featurePolicy(""); // @formatter:on } + } @Test @@ -945,9 +958,8 @@ public class HeadersConfigurerTests { throws Exception { this.spring.register(HstsWithPreloadConfig.class).autowire(); - MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string(HttpHeaders.STRICT_TRANSPORT_SECURITY, - "max-age=31536000 ; includeSubDomains ; preload")) + MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header() + .string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains ; preload")) .andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.STRICT_TRANSPORT_SECURITY); } @@ -965,6 +977,7 @@ public class HeadersConfigurerTests { .preload(true); // @formatter:on } + } @Test @@ -972,9 +985,8 @@ public class HeadersConfigurerTests { throws Exception { this.spring.register(HstsWithPreloadInLambdaConfig.class).autowire(); - MvcResult mvcResult = this.mvc.perform(get("/").secure(true)) - .andExpect(header().string(HttpHeaders.STRICT_TRANSPORT_SECURITY, - "max-age=31536000 ; includeSubDomains ; preload")) + MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header() + .string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains ; preload")) .andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.STRICT_TRANSPORT_SECURITY); } @@ -993,5 +1005,7 @@ public class HeadersConfigurerTests { ); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.java index 455621bedb..4a6fc362e7 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.java @@ -62,12 +62,12 @@ public class HttpBasicConfigurerTests { public void configureWhenRegisteringObjectPostProcessorThenInvokedOnBasicAuthenticationFilter() { this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(BasicAuthenticationFilter.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(BasicAuthenticationFilter.class)); } @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class); @Override @@ -82,26 +82,29 @@ public class HttpBasicConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } @Test public void httpBasicWhenUsingDefaultsInLambdaThenResponseIncludesBasicChallenge() throws Exception { this.spring.register(DefaultsLambdaEntryPointConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/")).andExpect(status().isUnauthorized()) .andExpect(header().string("WWW-Authenticate", "Basic realm=\"Realm\"")); } @EnableWebSecurity static class DefaultsLambdaEntryPointConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -121,20 +124,21 @@ public class HttpBasicConfigurerTests { .inMemoryAuthentication(); // @formatter:on } + } - //SEC-2198 + // SEC-2198 @Test public void httpBasicWhenUsingDefaultsThenResponseIncludesBasicChallenge() throws Exception { this.spring.register(DefaultsEntryPointConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/")).andExpect(status().isUnauthorized()) .andExpect(header().string("WWW-Authenticate", "Basic realm=\"Realm\"")); } @EnableWebSecurity static class DefaultsEntryPointConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -153,6 +157,7 @@ public class HttpBasicConfigurerTests { .inMemoryAuthentication(); // @formatter:on } + } @Test @@ -161,14 +166,13 @@ public class HttpBasicConfigurerTests { this.mvc.perform(get("/")); - verify(CustomAuthenticationEntryPointConfig.ENTRY_POINT) - .commence(any(HttpServletRequest.class), - any(HttpServletResponse.class), - any(AuthenticationException.class)); + verify(CustomAuthenticationEntryPointConfig.ENTRY_POINT).commence(any(HttpServletRequest.class), + any(HttpServletResponse.class), any(AuthenticationException.class)); } @EnableWebSecurity static class CustomAuthenticationEntryPointConfig extends WebSecurityConfigurerAdapter { + static AuthenticationEntryPoint ENTRY_POINT = mock(AuthenticationEntryPoint.class); @Override @@ -190,6 +194,7 @@ public class HttpBasicConfigurerTests { .inMemoryAuthentication(); // @formatter:on } + } @Test @@ -198,14 +203,13 @@ public class HttpBasicConfigurerTests { this.mvc.perform(get("/")); - verify(DuplicateDoesNotOverrideConfig.ENTRY_POINT) - .commence(any(HttpServletRequest.class), - any(HttpServletResponse.class), - any(AuthenticationException.class)); + verify(DuplicateDoesNotOverrideConfig.ENTRY_POINT).commence(any(HttpServletRequest.class), + any(HttpServletResponse.class), any(AuthenticationException.class)); } @EnableWebSecurity static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter { + static AuthenticationEntryPoint ENTRY_POINT = mock(AuthenticationEntryPoint.class); @Override @@ -229,16 +233,15 @@ public class HttpBasicConfigurerTests { .inMemoryAuthentication(); // @formatter:on } + } - //SEC-3019 + // SEC-3019 @Test public void httpBasicWhenRememberMeConfiguredThenSetsRememberMeCookie() throws Exception { this.spring.register(BasicUsesRememberMeConfig.class).autowire(); - this.mvc.perform(get("/") - .with(httpBasic("user", "password")) - .param("remember-me", "true")) + this.mvc.perform(get("/").with(httpBasic("user", "password")).param("remember-me", "true")) .andExpect(cookie().exists("remember-me")); } @@ -259,7 +262,7 @@ public class HttpBasicConfigurerTests { @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( - // @formatter:off + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") @@ -268,5 +271,7 @@ public class HttpBasicConfigurerTests { // @formatter:on ); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java index 45836760f6..4937f4edb3 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java @@ -40,10 +40,13 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon * */ public class HttpSecurityAntMatchersTests { + AnnotationConfigWebApplicationContext context; MockHttpServletRequest request; + MockHttpServletResponse response; + MockFilterChain chain; @Autowired @@ -77,6 +80,7 @@ public class HttpSecurityAntMatchersTests { @EnableWebSecurity @Configuration static class AntMatchersNoPatternsConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -95,6 +99,7 @@ public class HttpSecurityAntMatchersTests { .inMemoryAuthentication(); // @formatter:on } + } // SEC-3135 @@ -111,6 +116,7 @@ public class HttpSecurityAntMatchersTests { @EnableWebSecurity @Configuration static class AntMatchersEmptyPatternsConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -130,6 +136,7 @@ public class HttpSecurityAntMatchersTests { .inMemoryAuthentication(); // @formatter:on } + } public void loadConfig(Class... configs) { @@ -140,5 +147,4 @@ public class HttpSecurityAntMatchersTests { context.getAutowireCapableBeanFactory().autowireBean(this); } - } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java index e7a80a6e7b..c4b585ed8b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java @@ -41,10 +41,13 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon * */ public class HttpSecurityLogoutTests { + AnnotationConfigWebApplicationContext context; MockHttpServletRequest request; + MockHttpServletResponse response; + MockFilterChain chain; @Autowired @@ -72,7 +75,8 @@ public class HttpSecurityLogoutTests { SecurityContext currentContext = SecurityContextHolder.createEmptyContext(); currentContext.setAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")); - request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, currentContext); + request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, + currentContext); request.setMethod("POST"); request.setServletPath("/logout"); @@ -84,6 +88,7 @@ public class HttpSecurityLogoutTests { @EnableWebSecurity @Configuration static class ClearAuthenticationFalseConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -100,6 +105,7 @@ public class HttpSecurityLogoutTests { .inMemoryAuthentication(); // @formatter:on } + } public void loadConfig(Class... configs) { @@ -110,5 +116,4 @@ public class HttpSecurityLogoutTests { context.getAutowireCapableBeanFactory().autowireBean(this); } - } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java index fec73febcc..c5ea556034 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java @@ -47,10 +47,13 @@ import static org.springframework.security.config.Customizer.withDefaults; * */ public class HttpSecurityRequestMatchersTests { + AnnotationConfigWebApplicationContext context; MockHttpServletRequest request; + MockHttpServletResponse response; + MockFilterChain chain; @Autowired @@ -78,24 +81,21 @@ public class HttpSecurityRequestMatchersTests { this.request.setServletPath("/path"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); this.request.setServletPath("/path.html"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); this.request.setServletPath("/path/"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); } @Test @@ -109,6 +109,7 @@ public class HttpSecurityRequestMatchersTests { @Configuration @EnableWebMvc static class MvcMatcherConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -130,11 +131,14 @@ public class HttpSecurityRequestMatchersTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Test @@ -144,30 +148,28 @@ public class HttpSecurityRequestMatchersTests { this.request.setServletPath("/path"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); this.request.setServletPath("/path.html"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); this.request.setServletPath("/path/"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); } @EnableWebSecurity @Configuration @EnableWebMvc static class RequestMatchersMvcMatcherConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -191,11 +193,14 @@ public class HttpSecurityRequestMatchersTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Test @@ -205,30 +210,28 @@ public class HttpSecurityRequestMatchersTests { this.request.setServletPath("/path"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); this.request.setServletPath("/path.html"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); this.request.setServletPath("/path/"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); } @EnableWebSecurity @Configuration @EnableWebMvc static class RequestMatchersMvcMatcherInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -247,11 +250,14 @@ public class HttpSecurityRequestMatchersTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Test @@ -262,8 +268,7 @@ public class HttpSecurityRequestMatchersTests { this.request.setRequestURI("/spring/path"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); @@ -286,8 +291,8 @@ public class HttpSecurityRequestMatchersTests { @EnableWebSecurity @Configuration @EnableWebMvc - static class RequestMatchersMvcMatcherServeltPathConfig - extends WebSecurityConfigurerAdapter { + static class RequestMatchersMvcMatcherServeltPathConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -312,11 +317,14 @@ public class HttpSecurityRequestMatchersTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Test @@ -327,8 +335,7 @@ public class HttpSecurityRequestMatchersTests { this.request.setRequestURI("/spring/path"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); @@ -351,8 +358,8 @@ public class HttpSecurityRequestMatchersTests { @EnableWebSecurity @Configuration @EnableWebMvc - static class RequestMatchersMvcMatcherServletPathInLambdaConfig - extends WebSecurityConfigurerAdapter { + static class RequestMatchersMvcMatcherServletPathInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -372,19 +379,24 @@ public class HttpSecurityRequestMatchersTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Configuration static class LegacyMvcMatchingConfig implements WebMvcConfigurer { + @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseSuffixPatternMatch(true); } + } public void loadConfig(Class... configs) { @@ -395,4 +407,5 @@ public class HttpSecurityRequestMatchersTests { this.context.getAutowireCapableBeanFactory().autowireBean(this); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/Issue55Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/Issue55Tests.java index 62aeedce86..c8fd168420 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/Issue55Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/Issue55Tests.java @@ -59,9 +59,9 @@ public class Issue55Tests { assertThat(filter.getAuthenticationManager().authenticate(token)).isEqualTo(CustomAuthenticationManager.RESULT); } - @EnableWebSecurity static class WebSecurityConfigurerAdapterDefaultsAuthManagerConfig { + @Component public static class WebSecurityAdapter extends WebSecurityConfigurerAdapter { @@ -73,19 +73,24 @@ public class Issue55Tests { .anyRequest().hasRole("USER"); // @formatter:on } + } @Configuration public static class AuthenticationManagerConfiguration { + @Bean public AuthenticationManager authenticationManager() throws Exception { return new CustomAuthenticationManager(); } + } + } @Test - public void multiHttpWebSecurityConfigurerAdapterDefaultsToAutowired() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + public void multiHttpWebSecurityConfigurerAdapterDefaultsToAutowired() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { TestingAuthenticationToken token = new TestingAuthenticationToken("test", "this"); this.spring.register(MultiWebSecurityConfigurerAdapterDefaultsAuthManagerConfig.class); this.spring.getContext().getBean(FilterChainProxy.class); @@ -93,15 +98,19 @@ public class Issue55Tests { FilterSecurityInterceptor filter = (FilterSecurityInterceptor) findFilter(FilterSecurityInterceptor.class, 0); assertThat(filter.getAuthenticationManager().authenticate(token)).isEqualTo(CustomAuthenticationManager.RESULT); - FilterSecurityInterceptor secondFilter = (FilterSecurityInterceptor) findFilter(FilterSecurityInterceptor.class, 1); - assertThat(secondFilter.getAuthenticationManager().authenticate(token)).isEqualTo(CustomAuthenticationManager.RESULT); + FilterSecurityInterceptor secondFilter = (FilterSecurityInterceptor) findFilter(FilterSecurityInterceptor.class, + 1); + assertThat(secondFilter.getAuthenticationManager().authenticate(token)) + .isEqualTo(CustomAuthenticationManager.RESULT); } @EnableWebSecurity static class MultiWebSecurityConfigurerAdapterDefaultsAuthManagerConfig { + @Component @Order(1) public static class ApiWebSecurityAdapter extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -110,10 +119,12 @@ public class Issue55Tests { .anyRequest().hasRole("USER"); // @formatter:on } + } @Component public static class WebSecurityAdapter extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -122,23 +133,29 @@ public class Issue55Tests { .anyRequest().hasRole("USER"); // @formatter:on } + } @Configuration public static class AuthenticationManagerConfiguration { + @Bean public AuthenticationManager authenticationManager() throws Exception { return new CustomAuthenticationManager(); } + } + } static class CustomAuthenticationManager implements AuthenticationManager { + static Authentication RESULT = new TestingAuthenticationToken("test", "this", "ROLE_USER"); public Authentication authenticate(Authentication authentication) throws AuthenticationException { return RESULT; } + } Filter findFilter(Class filter, int index) { @@ -154,4 +171,5 @@ public class Issue55Tests { SecurityFilterChain filterChain(int index) { return this.spring.getContext().getBean(FilterChainProxy.class).getFilterChains().get(index); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurerTests.java index 57de13f087..cb2165b31c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurerTests.java @@ -76,6 +76,7 @@ public class JeeConfigurerTests { @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor; @Override @@ -90,13 +91,16 @@ public class JeeConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } @Test @@ -105,18 +109,16 @@ public class JeeConfigurerTests { Principal user = mock(Principal.class); when(user.getName()).thenReturn("user"); - this.mvc.perform(get("/") - .principal(user) - .with(request -> { - request.addUserRole("ROLE_ADMIN"); - request.addUserRole("ROLE_USER"); - return request; - })) - .andExpect(authenticated().withRoles("USER")); + this.mvc.perform(get("/").principal(user).with(request -> { + request.addUserRole("ROLE_ADMIN"); + request.addUserRole("ROLE_USER"); + return request; + })).andExpect(authenticated().withRoles("USER")); } @EnableWebSecurity static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -127,6 +129,7 @@ public class JeeConfigurerTests { .jee(); // @formatter:on } + } @Test @@ -135,18 +138,16 @@ public class JeeConfigurerTests { Principal user = mock(Principal.class); when(user.getName()).thenReturn("user"); - this.mvc.perform(get("/") - .principal(user) - .with(request -> { - request.addUserRole("ROLE_ADMIN"); - request.addUserRole("ROLE_USER"); - return request; - })) - .andExpect(authenticated().withRoles("USER")); + this.mvc.perform(get("/").principal(user).with(request -> { + request.addUserRole("ROLE_ADMIN"); + request.addUserRole("ROLE_USER"); + return request; + })).andExpect(authenticated().withRoles("USER")); } @EnableWebSecurity public static class JeeMappableRolesConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -161,6 +162,7 @@ public class JeeConfigurerTests { ); // @formatter:on } + } @Test @@ -169,14 +171,11 @@ public class JeeConfigurerTests { Principal user = mock(Principal.class); when(user.getName()).thenReturn("user"); - this.mvc.perform(get("/") - .principal(user) - .with(request -> { - request.addUserRole("ROLE_ADMIN"); - request.addUserRole("ROLE_USER"); - return request; - })) - .andExpect(authenticated().withAuthorities(AuthorityUtils.createAuthorityList("ROLE_USER"))); + this.mvc.perform(get("/").principal(user).with(request -> { + request.addUserRole("ROLE_ADMIN"); + request.addUserRole("ROLE_USER"); + return request; + })).andExpect(authenticated().withAuthorities(AuthorityUtils.createAuthorityList("ROLE_USER"))); } @EnableWebSecurity @@ -196,6 +195,7 @@ public class JeeConfigurerTests { ); // @formatter:on } + } @Test @@ -209,20 +209,18 @@ public class JeeConfigurerTests { when(JeeCustomAuthenticatedUserDetailsServiceConfig.authenticationUserDetailsService.loadUserDetails(any())) .thenReturn(userDetails); - this.mvc.perform(get("/") - .principal(user) - .with(request -> { - request.addUserRole("ROLE_ADMIN"); - request.addUserRole("ROLE_USER"); - return request; - })) - .andExpect(authenticated().withRoles("USER")); + this.mvc.perform(get("/").principal(user).with(request -> { + request.addUserRole("ROLE_ADMIN"); + request.addUserRole("ROLE_USER"); + return request; + })).andExpect(authenticated().withRoles("USER")); } @EnableWebSecurity public static class JeeCustomAuthenticatedUserDetailsServiceConfig extends WebSecurityConfigurerAdapter { - static AuthenticationUserDetailsService authenticationUserDetailsService = - mock(AuthenticationUserDetailsService.class); + + static AuthenticationUserDetailsService authenticationUserDetailsService = mock( + AuthenticationUserDetailsService.class); @Override protected void configure(HttpSecurity http) throws Exception { @@ -238,5 +236,7 @@ public class JeeConfigurerTests { ); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerClearSiteDataTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerClearSiteDataTests.java index 79d32b7467..8b8a8ac9e8 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerClearSiteDataTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerClearSiteDataTests.java @@ -43,8 +43,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. /** * - * Tests for {@link HeaderWriterLogoutHandler} that passing {@link ClearSiteDataHeaderWriter} - * implementation. + * Tests for {@link HeaderWriterLogoutHandler} that passing + * {@link ClearSiteDataHeaderWriter} implementation. * * @author Rafiullah Hamedy * @@ -55,8 +55,7 @@ public class LogoutConfigurerClearSiteDataTests { private static final String CLEAR_SITE_DATA_HEADER = "Clear-Site-Data"; - private static final ClearSiteDataHeaderWriter.Directive[] SOURCE = - { CACHE, COOKIES, STORAGE, EXECUTION_CONTEXTS }; + private static final ClearSiteDataHeaderWriter.Directive[] SOURCE = { CACHE, COOKIES, STORAGE, EXECUTION_CONTEXTS }; private static final String HEADER_VALUE = "\"cache\", \"cookies\", \"storage\", \"executionContexts\""; @@ -72,7 +71,7 @@ public class LogoutConfigurerClearSiteDataTests { this.spring.register(HttpLogoutConfig.class).autowire(); this.mvc.perform(get("/logout").secure(true).with(csrf())) - .andExpect(header().doesNotExist(CLEAR_SITE_DATA_HEADER)); + .andExpect(header().doesNotExist(CLEAR_SITE_DATA_HEADER)); } @Test @@ -80,8 +79,7 @@ public class LogoutConfigurerClearSiteDataTests { public void logoutWhenRequestTypePostAndNotSecureThenHeaderNotPresent() throws Exception { this.spring.register(HttpLogoutConfig.class).autowire(); - this.mvc.perform(post("/logout").with(csrf())) - .andExpect(header().doesNotExist(CLEAR_SITE_DATA_HEADER)); + this.mvc.perform(post("/logout").with(csrf())).andExpect(header().doesNotExist(CLEAR_SITE_DATA_HEADER)); } @Test @@ -90,11 +88,12 @@ public class LogoutConfigurerClearSiteDataTests { this.spring.register(HttpLogoutConfig.class).autowire(); this.mvc.perform(post("/logout").secure(true).with(csrf())) - .andExpect(header().stringValues(CLEAR_SITE_DATA_HEADER, HEADER_VALUE)); + .andExpect(header().stringValues(CLEAR_SITE_DATA_HEADER, HEADER_VALUE)); } @EnableWebSecurity static class HttpLogoutConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -103,5 +102,7 @@ public class LogoutConfigurerClearSiteDataTests { .addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(SOURCE))); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerTests.java index bb24708390..65659ac6ac 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerTests.java @@ -66,12 +66,12 @@ public class LogoutConfigurerTests { @Test public void configureWhenDefaultLogoutSuccessHandlerForHasNullLogoutHandlerThenException() { assertThatThrownBy(() -> this.spring.register(NullLogoutSuccessHandlerConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasRootCauseInstanceOf(IllegalArgumentException.class); + .isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class); } @EnableWebSecurity static class NullLogoutSuccessHandlerConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -80,17 +80,18 @@ public class LogoutConfigurerTests { .defaultLogoutSuccessHandlerFor(null, mock(RequestMatcher.class)); // @formatter:on } + } @Test public void configureWhenDefaultLogoutSuccessHandlerForHasNullLogoutHandlerInLambdaThenException() { assertThatThrownBy(() -> this.spring.register(NullLogoutSuccessHandlerInLambdaConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasRootCauseInstanceOf(IllegalArgumentException.class); + .isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class); } @EnableWebSecurity static class NullLogoutSuccessHandlerInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -100,17 +101,18 @@ public class LogoutConfigurerTests { ); // @formatter:on } + } @Test public void configureWhenDefaultLogoutSuccessHandlerForHasNullMatcherThenException() { assertThatThrownBy(() -> this.spring.register(NullMatcherConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasRootCauseInstanceOf(IllegalArgumentException.class); + .isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class); } @EnableWebSecurity static class NullMatcherConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -119,17 +121,18 @@ public class LogoutConfigurerTests { .defaultLogoutSuccessHandlerFor(mock(LogoutSuccessHandler.class), null); // @formatter:on } + } @Test public void configureWhenDefaultLogoutSuccessHandlerForHasNullMatcherInLambdaThenException() { assertThatThrownBy(() -> this.spring.register(NullMatcherInLambdaConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasRootCauseInstanceOf(IllegalArgumentException.class); + .isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class); } @EnableWebSecurity static class NullMatcherInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -139,18 +142,19 @@ public class LogoutConfigurerTests { ); // @formatter:on } + } @Test public void configureWhenRegisteringObjectPostProcessorThenInvokedOnLogoutFilter() { this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(LogoutFilter.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(LogoutFilter.class)); } @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class); @Override @@ -165,27 +169,29 @@ public class LogoutConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } @Test public void logoutWhenInvokedTwiceThenUsesOriginalLogoutUrl() throws Exception { this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire(); - this.mvc.perform(post("/custom/logout") - .with(csrf())) - .andExpect(status().isFound()) + this.mvc.perform(post("/custom/logout").with(csrf())).andExpect(status().isFound()) .andExpect(redirectedUrl("/login?logout")); } @EnableWebSecurity static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -204,6 +210,7 @@ public class LogoutConfigurerTests { .inMemoryAuthentication(); // @formatter:on } + } // SEC-2311 @@ -211,36 +218,28 @@ public class LogoutConfigurerTests { public void logoutWhenGetRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception { this.spring.register(CsrfDisabledConfig.class).autowire(); - this.mvc.perform(get("/logout")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/login?logout")); + this.mvc.perform(get("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout")); } @Test public void logoutWhenPostRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception { this.spring.register(CsrfDisabledConfig.class).autowire(); - this.mvc.perform(post("/logout")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/login?logout")); + this.mvc.perform(post("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout")); } @Test public void logoutWhenPutRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception { this.spring.register(CsrfDisabledConfig.class).autowire(); - this.mvc.perform(put("/logout")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/login?logout")); + this.mvc.perform(put("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout")); } @Test public void logoutWhenDeleteRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception { this.spring.register(CsrfDisabledConfig.class).autowire(); - this.mvc.perform(delete("/logout")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/login?logout")); + this.mvc.perform(delete("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout")); } @EnableWebSecurity @@ -255,23 +254,21 @@ public class LogoutConfigurerTests { .logout(); // @formatter:on } + } @Test public void logoutWhenGetRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception { this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire(); - this.mvc.perform(get("/custom/logout")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/login?logout")); + this.mvc.perform(get("/custom/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout")); } @Test public void logoutWhenPostRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception { this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire(); - this.mvc.perform(post("/custom/logout")) - .andExpect(status().isFound()) + this.mvc.perform(post("/custom/logout")).andExpect(status().isFound()) .andExpect(redirectedUrl("/login?logout")); } @@ -279,17 +276,14 @@ public class LogoutConfigurerTests { public void logoutWhenPutRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception { this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire(); - this.mvc.perform(put("/custom/logout")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/login?logout")); + this.mvc.perform(put("/custom/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout")); } @Test public void logoutWhenDeleteRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception { this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire(); - this.mvc.perform(delete("/custom/logout")) - .andExpect(status().isFound()) + this.mvc.perform(delete("/custom/logout")).andExpect(status().isFound()) .andExpect(redirectedUrl("/login?logout")); } @@ -306,15 +300,14 @@ public class LogoutConfigurerTests { .logoutUrl("/custom/logout"); // @formatter:on } + } @Test public void logoutWhenCustomLogoutUrlInLambdaThenRedirectsToLogin() throws Exception { this.spring.register(CsrfDisabledAndCustomLogoutInLambdaConfig.class).autowire(); - this.mvc.perform(get("/custom/logout")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/login?logout")); + this.mvc.perform(get("/custom/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout")); } @EnableWebSecurity @@ -329,18 +322,19 @@ public class LogoutConfigurerTests { .logout(logout -> logout.logoutUrl("/custom/logout")); // @formatter:on } + } // SEC-3170 @Test public void configureWhenLogoutHandlerNullThenException() { assertThatThrownBy(() -> this.spring.register(NullLogoutHandlerConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasRootCauseInstanceOf(IllegalArgumentException.class); + .isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class); } @EnableWebSecurity static class NullLogoutHandlerConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -349,17 +343,18 @@ public class LogoutConfigurerTests { .addLogoutHandler(null); // @formatter:on } + } @Test public void configureWhenLogoutHandlerNullInLambdaThenException() { assertThatThrownBy(() -> this.spring.register(NullLogoutHandlerInLambdaConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasRootCauseInstanceOf(IllegalArgumentException.class); + .isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class); } @EnableWebSecurity static class NullLogoutHandlerInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -367,6 +362,7 @@ public class LogoutConfigurerTests { .logout(logout -> logout.addLogoutHandler(null)); // @formatter:on } + } // SEC-3170 @@ -374,14 +370,13 @@ public class LogoutConfigurerTests { public void rememberMeWhenRememberMeServicesNotLogoutHandlerThenRedirectsToLogin() throws Exception { this.spring.register(RememberMeNoLogoutHandler.class).autowire(); - this.mvc.perform(post("/logout") - .with(csrf())) - .andExpect(status().isFound()) + this.mvc.perform(post("/logout").with(csrf())).andExpect(status().isFound()) .andExpect(redirectedUrl("/login?logout")); } @EnableWebSecurity static class RememberMeNoLogoutHandler extends WebSecurityConfigurerAdapter { + static RememberMeServices REMEMBER_ME = mock(RememberMeServices.class); @Override @@ -392,18 +387,16 @@ public class LogoutConfigurerTests { .rememberMeServices(REMEMBER_ME); // @formatter:on } + } @Test public void logoutWhenAcceptTextHtmlThenRedirectsToLogin() throws Exception { this.spring.register(BasicSecurityConfig.class).autowire(); - this.mvc.perform(post("/logout") - .with(csrf()) - .with(user("user")) - .header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML_VALUE)) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/login?logout")); + this.mvc.perform( + post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML_VALUE)) + .andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout")); } // gh-3282 @@ -411,11 +404,8 @@ public class LogoutConfigurerTests { public void logoutWhenAcceptApplicationJsonThenReturnsStatusNoContent() throws Exception { this.spring.register(BasicSecurityConfig.class).autowire(); - this.mvc.perform(post("/logout") - .with(csrf()) - .with(user("user")) - .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)) - .andExpect(status().isNoContent()); + this.mvc.perform(post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT, + MediaType.APPLICATION_JSON_VALUE)).andExpect(status().isNoContent()); } // gh-4831 @@ -423,10 +413,8 @@ public class LogoutConfigurerTests { public void logoutWhenAcceptAllThenReturnsStatusNoContent() throws Exception { this.spring.register(BasicSecurityConfig.class).autowire(); - this.mvc.perform(post("/logout") - .with(csrf()) - .with(user("user")) - .header(HttpHeaders.ACCEPT, MediaType.ALL_VALUE)) + this.mvc.perform( + post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT, MediaType.ALL_VALUE)) .andExpect(status().isNoContent()); } @@ -435,11 +423,9 @@ public class LogoutConfigurerTests { public void logoutWhenAcceptFromChromeThenRedirectsToLogin() throws Exception { this.spring.register(BasicSecurityConfig.class).autowire(); - this.mvc.perform(post("/logout") - .with(csrf()).with(user("user")) - .header(HttpHeaders.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/login?logout")); + this.mvc.perform(post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT, + "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")) + .andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout")); } // gh-3997 @@ -447,29 +433,26 @@ public class LogoutConfigurerTests { public void logoutWhenXMLHttpRequestThenReturnsStatusNoContent() throws Exception { this.spring.register(BasicSecurityConfig.class).autowire(); - this.mvc.perform(post("/logout") - .with(csrf()) - .with(user("user")) - .header(HttpHeaders.ACCEPT, "text/html,application/json") - .header("X-Requested-With", "XMLHttpRequest")) + this.mvc.perform(post("/logout").with(csrf()).with(user("user")) + .header(HttpHeaders.ACCEPT, "text/html,application/json").header("X-Requested-With", "XMLHttpRequest")) .andExpect(status().isNoContent()); } @EnableWebSecurity static class BasicSecurityConfig extends WebSecurityConfigurerAdapter { + } @Test public void logoutWhenDisabledThenLogoutUrlNotFound() throws Exception { this.spring.register(LogoutDisabledConfig.class).autowire(); - this.mvc.perform(post("/logout") - .with(csrf())) - .andExpect(status().isNotFound()); + this.mvc.perform(post("/logout").with(csrf())).andExpect(status().isNotFound()); } @EnableWebSecurity static class LogoutDisabledConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -478,5 +461,7 @@ public class LogoutConfigurerTests { .disable(); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceDebugTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceDebugTests.java index 13fdc95f49..c386e59c80 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceDebugTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceDebugTests.java @@ -45,6 +45,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder * @author Josh Cummings */ public class NamespaceDebugTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -60,8 +61,9 @@ public class NamespaceDebugTests { verify(appender, atLeastOnce()).doAppend(any(ILoggingEvent.class)); } - @EnableWebSecurity(debug=true) + @EnableWebSecurity(debug = true) static class DebugWebSecurity extends WebSecurityConfigurerAdapter { + } @Test @@ -75,6 +77,7 @@ public class NamespaceDebugTests { @EnableWebSecurity static class NoDebugWebSecurity extends WebSecurityConfigurerAdapter { + } private Appender mockAppenderFor(String name) { @@ -88,4 +91,5 @@ public class NamespaceDebugTests { private Class filterChainClass() { return this.spring.getContext().getBean("springSecurityFilterChain").getClass(); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpAnonymousTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpAnonymousTests.java index f6bd08bf47..c7716f1d4b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpAnonymousTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpAnonymousTests.java @@ -57,12 +57,12 @@ public class NamespaceHttpAnonymousTests { public void anonymousRequestWhenUsingDefaultAnonymousConfigurationThenUsesAnonymousAuthentication() throws Exception { this.spring.register(AnonymousConfig.class, AnonymousController.class).autowire(); - this.mvc.perform(get("/type")) - .andExpect(content().string(AnonymousAuthenticationToken.class.getSimpleName())); + this.mvc.perform(get("/type")).andExpect(content().string(AnonymousAuthenticationToken.class.getSimpleName())); } @EnableWebSecurity static class AnonymousConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -72,18 +72,18 @@ public class NamespaceHttpAnonymousTests { .anyRequest().denyAll(); // @formatter:on } + } @Test - public void anonymousRequestWhenDisablingAnonymousThenDenies() - throws Exception { + public void anonymousRequestWhenDisablingAnonymousThenDenies() throws Exception { this.spring.register(AnonymousDisabledConfig.class, AnonymousController.class).autowire(); - this.mvc.perform(get("/type")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/type")).andExpect(status().isForbidden()); } @EnableWebSecurity static class AnonymousDisabledConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -103,18 +103,18 @@ public class NamespaceHttpAnonymousTests { .withUser(PasswordEncodedUser.admin()); // @formatter:on } + } @Test - public void requestWhenAnonymousThenSendsAnonymousConfiguredAuthorities() - throws Exception { + public void requestWhenAnonymousThenSendsAnonymousConfiguredAuthorities() throws Exception { this.spring.register(AnonymousGrantedAuthorityConfig.class, AnonymousController.class).autowire(); - this.mvc.perform(get("/type")) - .andExpect(content().string(AnonymousAuthenticationToken.class.getSimpleName())); + this.mvc.perform(get("/type")).andExpect(content().string(AnonymousAuthenticationToken.class.getSimpleName())); } @EnableWebSecurity static class AnonymousGrantedAuthorityConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -127,17 +127,18 @@ public class NamespaceHttpAnonymousTests { .authorities("ROLE_ANON"); // @formatter:on } + } @Test public void anonymousRequestWhenAnonymousKeyConfiguredThenKeyIsUsed() throws Exception { this.spring.register(AnonymousKeyConfig.class, AnonymousController.class).autowire(); - this.mvc.perform(get("/key")) - .andExpect(content().string(String.valueOf("AnonymousKeyConfig".hashCode()))); + this.mvc.perform(get("/key")).andExpect(content().string(String.valueOf("AnonymousKeyConfig".hashCode()))); } @EnableWebSecurity static class AnonymousKeyConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -149,17 +150,18 @@ public class NamespaceHttpAnonymousTests { .anonymous().key("AnonymousKeyConfig"); // @formatter:on } + } @Test public void anonymousRequestWhenAnonymousUsernameConfiguredThenUsernameIsUsed() throws Exception { this.spring.register(AnonymousUsernameConfig.class, AnonymousController.class).autowire(); - this.mvc.perform(get("/principal")) - .andExpect(content().string("AnonymousUsernameConfig")); + this.mvc.perform(get("/principal")).andExpect(content().string("AnonymousUsernameConfig")); } @EnableWebSecurity static class AnonymousUsernameConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -171,39 +173,33 @@ public class NamespaceHttpAnonymousTests { .anonymous().principal("AnonymousUsernameConfig"); // @formatter:on } + } @RestController static class AnonymousController { + @GetMapping("/type") String type() { - return anonymousToken() - .map(AnonymousAuthenticationToken::getClass) - .map(Class::getSimpleName) - .orElse(null); + return anonymousToken().map(AnonymousAuthenticationToken::getClass).map(Class::getSimpleName).orElse(null); } @GetMapping("/key") String key() { - return anonymousToken() - .map(AnonymousAuthenticationToken::getKeyHash) - .map(String::valueOf) - .orElse(null); + return anonymousToken().map(AnonymousAuthenticationToken::getKeyHash).map(String::valueOf).orElse(null); } @GetMapping("/principal") String principal() { - return anonymousToken() - .map(AnonymousAuthenticationToken::getName) - .orElse(null); + return anonymousToken().map(AnonymousAuthenticationToken::getName).orElse(null); } Optional anonymousToken() { - return Optional.of(SecurityContextHolder.getContext()) - .map(SecurityContext::getAuthentication) + return Optional.of(SecurityContextHolder.getContext()).map(SecurityContext::getAuthentication) .filter(a -> a instanceof AnonymousAuthenticationToken) .map(AnonymousAuthenticationToken.class::cast); } + } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java index 30239fcf54..e020066b5e 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java @@ -65,25 +65,21 @@ public class NamespaceHttpBasicTests { public void basicAuthenticationWhenUsingDefaultsThenMatchesNamespace() throws Exception { this.spring.register(HttpBasicConfig.class, UserConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/")).andExpect(status().isUnauthorized()); - this.mvc.perform(get("/") - .with(httpBasic("user", "invalid"))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Realm\"")); - this.mvc.perform(get("/") - .with(httpBasic("user", "password"))) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isNotFound()); } @Configuration static class UserConfig { + @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( - // @formatter:off + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") @@ -92,10 +88,12 @@ public class NamespaceHttpBasicTests { // @formatter:on ); } + } @EnableWebSecurity static class HttpBasicConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -105,27 +103,24 @@ public class NamespaceHttpBasicTests { .httpBasic(); // @formatter:on } + } @Test public void basicAuthenticationWhenUsingDefaultsInLambdaThenMatchesNamespace() throws Exception { this.spring.register(HttpBasicLambdaConfig.class, UserConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/")).andExpect(status().isUnauthorized()); - this.mvc.perform(get("/") - .with(httpBasic("user", "invalid"))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Realm\"")); - this.mvc.perform(get("/") - .with(httpBasic("user", "password"))) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isNotFound()); } @EnableWebSecurity static class HttpBasicLambdaConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -136,6 +131,7 @@ public class NamespaceHttpBasicTests { .httpBasic(withDefaults()); // @formatter:on } + } /** @@ -145,14 +141,13 @@ public class NamespaceHttpBasicTests { public void basicAuthenticationWhenUsingCustomRealmThenMatchesNamespace() throws Exception { this.spring.register(CustomHttpBasicConfig.class, UserConfig.class).autowire(); - this.mvc.perform(get("/") - .with(httpBasic("user", "invalid"))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Custom Realm\"")); } @EnableWebSecurity static class CustomHttpBasicConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -163,20 +158,20 @@ public class NamespaceHttpBasicTests { .httpBasic().realmName("Custom Realm"); // @formatter:on } + } @Test public void basicAuthenticationWhenUsingCustomRealmInLambdaThenMatchesNamespace() throws Exception { this.spring.register(CustomHttpBasicLambdaConfig.class, UserConfig.class).autowire(); - this.mvc.perform(get("/") - .with(httpBasic("user", "invalid"))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Custom Realm\"")); } @EnableWebSecurity static class CustomHttpBasicLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -188,6 +183,7 @@ public class NamespaceHttpBasicTests { .httpBasic(httpBasicConfig -> httpBasicConfig.realmName("Custom Realm")); // @formatter:on } + } /** @@ -197,19 +193,19 @@ public class NamespaceHttpBasicTests { public void basicAuthenticationWhenUsingAuthenticationDetailsSourceRefThenMatchesNamespace() throws Exception { this.spring.register(AuthenticationDetailsSourceHttpBasicConfig.class, UserConfig.class).autowire(); - AuthenticationDetailsSource source = - this.spring.getContext().getBean(AuthenticationDetailsSource.class); + AuthenticationDetailsSource source = this.spring.getContext() + .getBean(AuthenticationDetailsSource.class); - this.mvc.perform(get("/") - .with(httpBasic("user", "password"))); + this.mvc.perform(get("/").with(httpBasic("user", "password"))); verify(source).buildDetails(any(HttpServletRequest.class)); } @EnableWebSecurity static class AuthenticationDetailsSourceHttpBasicConfig extends WebSecurityConfigurerAdapter { - AuthenticationDetailsSource authenticationDetailsSource = - mock(AuthenticationDetailsSource.class); + + AuthenticationDetailsSource authenticationDetailsSource = mock( + AuthenticationDetailsSource.class); @Override protected void configure(HttpSecurity http) throws Exception { @@ -224,6 +220,7 @@ public class NamespaceHttpBasicTests { AuthenticationDetailsSource authenticationDetailsSource() { return this.authenticationDetailsSource; } + } @Test @@ -231,19 +228,19 @@ public class NamespaceHttpBasicTests { throws Exception { this.spring.register(AuthenticationDetailsSourceHttpBasicLambdaConfig.class, UserConfig.class).autowire(); - AuthenticationDetailsSource source = - this.spring.getContext().getBean(AuthenticationDetailsSource.class); + AuthenticationDetailsSource source = this.spring.getContext() + .getBean(AuthenticationDetailsSource.class); - this.mvc.perform(get("/") - .with(httpBasic("user", "password"))); + this.mvc.perform(get("/").with(httpBasic("user", "password"))); verify(source).buildDetails(any(HttpServletRequest.class)); } @EnableWebSecurity static class AuthenticationDetailsSourceHttpBasicLambdaConfig extends WebSecurityConfigurerAdapter { - AuthenticationDetailsSource authenticationDetailsSource = - mock(AuthenticationDetailsSource.class); + + AuthenticationDetailsSource authenticationDetailsSource = mock( + AuthenticationDetailsSource.class); @Override protected void configure(HttpSecurity http) throws Exception { @@ -258,6 +255,7 @@ public class NamespaceHttpBasicTests { AuthenticationDetailsSource authenticationDetailsSource() { return this.authenticationDetailsSource; } + } /** @@ -267,22 +265,17 @@ public class NamespaceHttpBasicTests { public void basicAuthenticationWhenUsingEntryPointRefThenMatchesNamespace() throws Exception { this.spring.register(EntryPointRefHttpBasicConfig.class, UserConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().is(999)); + this.mvc.perform(get("/")).andExpect(status().is(999)); - this.mvc.perform(get("/") - .with(httpBasic("user", "invalid"))) - .andExpect(status().is(999)); + this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().is(999)); - this.mvc.perform(get("/") - .with(httpBasic("user", "password"))) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isNotFound()); } @EnableWebSecurity static class EntryPointRefHttpBasicConfig extends WebSecurityConfigurerAdapter { - AuthenticationEntryPoint authenticationEntryPoint = - (request, response, ex) -> response.setStatus(999); + + AuthenticationEntryPoint authenticationEntryPoint = (request, response, ex) -> response.setStatus(999); @Override protected void configure(HttpSecurity http) throws Exception { @@ -295,28 +288,24 @@ public class NamespaceHttpBasicTests { .authenticationEntryPoint(this.authenticationEntryPoint); // @formatter:on } + } @Test public void basicAuthenticationWhenUsingEntryPointRefInLambdaThenMatchesNamespace() throws Exception { this.spring.register(EntryPointRefHttpBasicLambdaConfig.class, UserConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().is(999)); + this.mvc.perform(get("/")).andExpect(status().is(999)); - this.mvc.perform(get("/") - .with(httpBasic("user", "invalid"))) - .andExpect(status().is(999)); + this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().is(999)); - this.mvc.perform(get("/") - .with(httpBasic("user", "password"))) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isNotFound()); } @EnableWebSecurity static class EntryPointRefHttpBasicLambdaConfig extends WebSecurityConfigurerAdapter { - AuthenticationEntryPoint authenticationEntryPoint = - (request, response, ex) -> response.setStatus(999); + + AuthenticationEntryPoint authenticationEntryPoint = (request, response, ex) -> response.setStatus(999); @Override protected void configure(HttpSecurity http) throws Exception { @@ -330,5 +319,7 @@ public class NamespaceHttpBasicTests { httpBasicConfig.authenticationEntryPoint(this.authenticationEntryPoint)); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java index 9c504e0c8f..4bc72dc12c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java @@ -15,7 +15,6 @@ */ package org.springframework.security.config.annotation.web.configurers; - import java.io.IOException; import java.util.List; import java.util.stream.Collectors; @@ -66,6 +65,7 @@ public class NamespaceHttpCustomFilterTests { @EnableWebSecurity static class CustomFilterBeforeConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -73,6 +73,7 @@ public class NamespaceHttpCustomFilterTests { .formLogin(); // @formatter:on } + } @Test @@ -83,6 +84,7 @@ public class NamespaceHttpCustomFilterTests { @EnableWebSecurity static class CustomFilterAfterConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -90,6 +92,7 @@ public class NamespaceHttpCustomFilterTests { .formLogin(); // @formatter:on } + } @Test @@ -100,6 +103,7 @@ public class NamespaceHttpCustomFilterTests { @EnableWebSecurity static class CustomFilterPositionConfig extends WebSecurityConfigurerAdapter { + CustomFilterPositionConfig() { // do not add the default filters to make testing easier super(true); @@ -113,8 +117,8 @@ public class NamespaceHttpCustomFilterTests { .addFilter(new CustomFilter()); // @formatter:on } - } + } @Test public void getFiltersWhenFilterAddedAtPositionThenBehaviorMatchesNamespace() { @@ -124,6 +128,7 @@ public class NamespaceHttpCustomFilterTests { @EnableWebSecurity static class CustomFilterPositionAtConfig extends WebSecurityConfigurerAdapter { + CustomFilterPositionAtConfig() { // do not add the default filters to make testing easier super(true); @@ -135,6 +140,7 @@ public class NamespaceHttpCustomFilterTests { .addFilterAt(new OtherCustomFilter(), UsernamePasswordAuthenticationFilter.class); // @formatter:on } + } @Test @@ -145,6 +151,7 @@ public class NamespaceHttpCustomFilterTests { @EnableWebSecurity static class NoAuthenticationManagerInHttpConfigurationConfig extends WebSecurityConfigurerAdapter { + NoAuthenticationManagerInHttpConfigurationConfig() { super(true); } @@ -163,14 +170,16 @@ public class NamespaceHttpCustomFilterTests { .addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class); // @formatter:on } + } @Configuration static class UserDetailsServiceConfig { + @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( - // @formatter:off + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") @@ -178,28 +187,35 @@ public class NamespaceHttpCustomFilterTests { .build()); // @formatter:on } + + } + + static class CustomFilter extends UsernamePasswordAuthenticationFilter { + } - static class CustomFilter extends UsernamePasswordAuthenticationFilter {} static class OtherCustomFilter extends OncePerRequestFilter { - protected void doFilterInternal( - HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) - throws ServletException, IOException { + + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { filterChain.doFilter(request, response); } + } static class CustomAuthenticationManager implements AuthenticationManager { - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + + public Authentication authenticate(Authentication authentication) throws AuthenticationException { return null; } + } private ListAssert> assertThatFilters() { FilterChainProxy filterChain = this.spring.getContext().getBean(FilterChainProxy.class); - List> filters = filterChain.getFilters("/").stream() - .map(Object::getClass).collect(Collectors.toList()); + List> filters = filterChain.getFilters("/").stream().map(Object::getClass) + .collect(Collectors.toList()); return assertThat(filters); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java index 7bea9d6eac..9b3e68ad68 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java @@ -15,7 +15,6 @@ */ package org.springframework.security.config.annotation.web.configurers; - import java.security.Principal; import org.junit.Rule; @@ -46,7 +45,8 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; /** - * Tests to verify that all the functionality of attributes is present + * Tests to verify that all the functionality of attributes is + * present * * @author Rob Winch * @author Josh Cummings @@ -73,7 +73,9 @@ public class NamespaceHttpExpressionHandlerTests { @EnableWebMvc @EnableWebSecurity private static class ExpressionHandlerConfig extends WebSecurityConfigurerAdapter { - ExpressionHandlerConfig() {} + + ExpressionHandlerConfig() { + } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { @@ -100,17 +102,21 @@ public class NamespaceHttpExpressionHandlerTests { ExpressionParser expressionParser() { return spy(new SpelExpressionParser()); } + } @RestController private static class ExpressionHandlerController { + @GetMapping("/whoami") String whoami(Principal user) { return user.getName(); } + } private T verifyBean(String beanName, Class beanClass) { return verify(this.spring.getContext().getBean(beanName, beanClass)); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.java index 63876be7f9..75b24bdd09 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.java @@ -52,12 +52,13 @@ public class NamespaceHttpFirewallTests { @Test public void requestWhenPathContainsDoubleDotsThenBehaviorMatchesNamespace() { this.rule.register(HttpFirewallConfig.class).autowire(); - assertThatCode(() -> this.mvc.perform(get("/public/../private/"))) - .isInstanceOf(RequestRejectedException.class); + assertThatCode(() -> this.mvc.perform(get("/public/../private/"))).isInstanceOf(RequestRejectedException.class); } @EnableWebSecurity - static class HttpFirewallConfig {} + static class HttpFirewallConfig { + + } @Test public void requestWithCustomFirewallThenBehaviorMatchesNamespace() { @@ -68,11 +69,12 @@ public class NamespaceHttpFirewallTests { @EnableWebSecurity static class CustomHttpFirewallConfig extends WebSecurityConfigurerAdapter { + @Override public void configure(WebSecurity web) { - web - .httpFirewall(new CustomHttpFirewall()); + web.httpFirewall(new CustomHttpFirewall()); } + } @Test @@ -84,21 +86,24 @@ public class NamespaceHttpFirewallTests { @EnableWebSecurity static class CustomHttpFirewallBeanConfig { + @Bean HttpFirewall firewall() { return new CustomHttpFirewall(); } + } static class CustomHttpFirewall extends DefaultHttpFirewall { @Override - public FirewalledRequest getFirewalledRequest(HttpServletRequest request) - throws RequestRejectedException { + public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException { if (request.getParameter("deny") != null) { throw new RequestRejectedException("custom rejection"); } return super.getFirewalledRequest(request); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java index 04fd811943..66f4a2c207 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java @@ -59,22 +59,15 @@ public class NamespaceHttpFormLoginTests { @Autowired MockMvc mvc; - @Test public void formLoginWhenDefaultConfigurationThenMatchesNamespace() throws Exception { this.spring.register(FormLoginConfig.class, UserDetailsServiceConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(redirectedUrl("http://localhost/login")); + this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/login")); - this.mvc.perform(post("/login") - .with(csrf())) - .andExpect(redirectedUrl("/login?error")); + this.mvc.perform(post("/login").with(csrf())).andExpect(redirectedUrl("/login?error")); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .with(csrf())) + this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf())) .andExpect(redirectedUrl("/")); } @@ -83,9 +76,7 @@ public class NamespaceHttpFormLoginTests { @Override public void configure(WebSecurity web) { - web - .ignoring() - .antMatchers("/resources/**"); + web.ignoring().antMatchers("/resources/**"); } @Override @@ -98,28 +89,25 @@ public class NamespaceHttpFormLoginTests { .formLogin(); // @formatter:on } + } @Test public void formLoginWithCustomEndpointsThenBehaviorMatchesNamespace() throws Exception { this.spring.register(FormLoginCustomConfig.class, UserDetailsServiceConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(redirectedUrl("http://localhost/authentication/login")); + this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/authentication/login")); - this.mvc.perform(post("/authentication/login/process") - .with(csrf())) + this.mvc.perform(post("/authentication/login/process").with(csrf())) .andExpect(redirectedUrl("/authentication/login?failed")); - this.mvc.perform(post("/authentication/login/process") - .param("username", "user") - .param("password", "password") - .with(csrf())) - .andExpect(redirectedUrl("/default")); + this.mvc.perform(post("/authentication/login/process").param("username", "user").param("password", "password") + .with(csrf())).andExpect(redirectedUrl("/default")); } @EnableWebSecurity static class FormLoginCustomConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { boolean alwaysUseDefaultSuccess = true; // @formatter:off @@ -136,32 +124,27 @@ public class NamespaceHttpFormLoginTests { .defaultSuccessUrl("/default", alwaysUseDefaultSuccess); // form-login@default-target-url / form-login@always-use-default-target // @formatter:on } + } @Test public void formLoginWithCustomHandlersThenBehaviorMatchesNamespace() throws Exception { this.spring.register(FormLoginCustomRefsConfig.class, UserDetailsServiceConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(redirectedUrl("http://localhost/login")); + this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/login")); - this.mvc.perform(post("/login") - .with(csrf())) - .andExpect(redirectedUrl("/custom/failure")); + this.mvc.perform(post("/login").with(csrf())).andExpect(redirectedUrl("/custom/failure")); verifyBean(WebAuthenticationDetailsSource.class).buildDetails(any(HttpServletRequest.class)); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .with(csrf())) + this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf())) .andExpect(redirectedUrl("/custom/targetUrl")); } @EnableWebSecurity static class FormLoginCustomRefsConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { - SavedRequestAwareAuthenticationSuccessHandler successHandler = - new SavedRequestAwareAuthenticationSuccessHandler(); + SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler(); successHandler.setDefaultTargetUrl("/custom/targetUrl"); // @formatter:off http @@ -181,14 +164,16 @@ public class NamespaceHttpFormLoginTests { WebAuthenticationDetailsSource authenticationDetailsSource() { return spy(WebAuthenticationDetailsSource.class); } + } @Configuration static class UserDetailsServiceConfig { + @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( - // @formatter:off + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") @@ -196,9 +181,11 @@ public class NamespaceHttpFormLoginTests { .build()); // @formatter:on } + } private T verifyBean(Class beanClass) { return verify(this.spring.getContext().getBean(beanClass)); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java index 22a29ce700..6c92e4a2f3 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java @@ -47,6 +47,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * */ public class NamespaceHttpHeadersTests { + static final Map defaultHeaders = new LinkedHashMap<>(); static { @@ -69,12 +70,12 @@ public class NamespaceHttpHeadersTests { public void secureRequestWhenDefaultConfigThenBehaviorMatchesNamespace() throws Exception { this.spring.register(HeadersDefaultConfig.class).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(includesDefaults()); + this.mvc.perform(get("/").secure(true)).andExpect(includesDefaults()); } @EnableWebSecurity static class HeadersDefaultConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -82,18 +83,19 @@ public class NamespaceHttpHeadersTests { .headers(); // @formatter:on } + } @Test public void secureRequestWhenCacheControlOnlyThenBehaviorMatchesNamespace() throws Exception { this.spring.register(HeadersCacheControlConfig.class).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(includes("Cache-Control", "Expires", "Pragma")); + this.mvc.perform(get("/").secure(true)).andExpect(includes("Cache-Control", "Expires", "Pragma")); } @EnableWebSecurity static class HeadersCacheControlConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -103,18 +105,19 @@ public class NamespaceHttpHeadersTests { .cacheControl(); // @formatter:on } + } @Test public void secureRequestWhenHstsOnlyThenBehaviorMatchesNamespace() throws Exception { this.spring.register(HstsConfig.class).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(includes("Strict-Transport-Security")); + this.mvc.perform(get("/").secure(true)).andExpect(includes("Strict-Transport-Security")); } @EnableWebSecurity static class HstsConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -124,6 +127,7 @@ public class NamespaceHttpHeadersTests { .httpStrictTransportSecurity(); // @formatter:on } + } @Test @@ -136,6 +140,7 @@ public class NamespaceHttpHeadersTests { @EnableWebSecurity static class HstsCustomConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -149,18 +154,19 @@ public class NamespaceHttpHeadersTests { .includeSubDomains(false); // @formatter:on } + } @Test public void requestWhenFrameOptionsSameOriginThenBehaviorMatchesNamespace() throws Exception { this.spring.register(FrameOptionsSameOriginConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(includes(Collections.singletonMap("X-Frame-Options", "SAMEORIGIN"))); + this.mvc.perform(get("/")).andExpect(includes(Collections.singletonMap("X-Frame-Options", "SAMEORIGIN"))); } @EnableWebSecurity static class FrameOptionsSameOriginConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -172,9 +178,11 @@ public class NamespaceHttpHeadersTests { .sameOrigin(); // @formatter:on } + } - // frame-options@strategy, frame-options@value, frame-options@parameter are not provided instead use frame-options@ref + // frame-options@strategy, frame-options@value, frame-options@parameter are not + // provided instead use frame-options@ref @Test public void requestWhenFrameOptionsAllowFromThenBehaviorMatchesNamespace() throws Exception { @@ -186,6 +194,7 @@ public class NamespaceHttpHeadersTests { @EnableWebSecurity static class FrameOptionsAllowFromConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -197,18 +206,19 @@ public class NamespaceHttpHeadersTests { new StaticAllowFromStrategy(URI.create("https://example.com")))); // @formatter:on } + } @Test public void requestWhenXssOnlyThenBehaviorMatchesNamespace() throws Exception { this.spring.register(XssProtectionConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(includes("X-XSS-Protection")); + this.mvc.perform(get("/")).andExpect(includes("X-XSS-Protection")); } @EnableWebSecurity static class XssProtectionConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -219,18 +229,19 @@ public class NamespaceHttpHeadersTests { .xssProtection(); // @formatter:on } + } @Test public void requestWhenXssCustomThenBehaviorMatchesNamespace() throws Exception { this.spring.register(XssProtectionCustomConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(includes(Collections.singletonMap("X-XSS-Protection", "1"))); + this.mvc.perform(get("/")).andExpect(includes(Collections.singletonMap("X-XSS-Protection", "1"))); } @EnableWebSecurity static class XssProtectionCustomConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -243,18 +254,19 @@ public class NamespaceHttpHeadersTests { .block(false); // @formatter:on } + } @Test public void requestWhenXContentTypeOptionsOnlyThenBehaviorMatchesNamespace() throws Exception { this.spring.register(ContentTypeOptionsConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(includes("X-Content-Type-Options")); + this.mvc.perform(get("/")).andExpect(includes("X-Content-Type-Options")); } @EnableWebSecurity static class ContentTypeOptionsConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -265,6 +277,7 @@ public class NamespaceHttpHeadersTests { .contentTypeOptions(); // @formatter:on } + } // header@name / header@value are not provided instead use header@ref @@ -279,6 +292,7 @@ public class NamespaceHttpHeadersTests { @EnableWebSecurity static class HeaderRefConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -288,6 +302,7 @@ public class NamespaceHttpHeadersTests { .addHeaderWriter(new StaticHeadersWriter("customHeaderName", "customHeaderValue")); // @formatter:on } + } private static ResultMatcher includesDefaults() { @@ -310,4 +325,5 @@ public class NamespaceHttpHeadersTests { } }; } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java index bea987ff28..5e2f6e1fd7 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java @@ -59,45 +59,32 @@ public class NamespaceHttpInterceptUrlTests { public void unauthenticatedRequestWhenUrlRequiresAuthenticationThenBehaviorMatchesNamespace() throws Exception { this.spring.register(HttpInterceptUrlConfig.class).autowire(); - this.mvc.perform(get("/users")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/users")).andExpect(status().isForbidden()); } @Test public void authenticatedRequestWhenUrlRequiresElevatedPrivilegesThenBehaviorMatchesNamespace() throws Exception { this.spring.register(HttpInterceptUrlConfig.class).autowire(); - - this.mvc.perform(get("/users") - .with(authentication(user("ROLE_USER")))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/users").with(authentication(user("ROLE_USER")))).andExpect(status().isForbidden()); } @Test public void authenticatedRequestWhenAuthorizedThenBehaviorMatchesNamespace() throws Exception { this.spring.register(HttpInterceptUrlConfig.class, BaseController.class).autowire(); - this.mvc.perform(get("/users") - .with(authentication(user("ROLE_ADMIN")))) - .andExpect(status().isOk()) - .andReturn(); + this.mvc.perform(get("/users").with(authentication(user("ROLE_ADMIN")))).andExpect(status().isOk()).andReturn(); } @Test public void requestWhenMappedByPostInterceptUrlThenBehaviorMatchesNamespace() throws Exception { this.spring.register(HttpInterceptUrlConfig.class, BaseController.class).autowire(); - this.mvc.perform(get("/admin/post") - .with(authentication(user("ROLE_USER")))) - .andExpect(status().isOk()); + this.mvc.perform(get("/admin/post").with(authentication(user("ROLE_USER")))).andExpect(status().isOk()); - this.mvc.perform(post("/admin/post") - .with(authentication(user("ROLE_USER")))) - .andExpect(status().isForbidden()); + this.mvc.perform(post("/admin/post").with(authentication(user("ROLE_USER")))).andExpect(status().isForbidden()); - this.mvc.perform(post("/admin/post") - .with(csrf()) - .with(authentication(user("ROLE_ADMIN")))) + this.mvc.perform(post("/admin/post").with(csrf()).with(authentication(user("ROLE_ADMIN")))) .andExpect(status().isOk()); } @@ -105,14 +92,11 @@ public class NamespaceHttpInterceptUrlTests { public void requestWhenRequiresChannelThenBehaviorMatchesNamespace() throws Exception { this.spring.register(HttpInterceptUrlConfig.class).autowire(); - this.mvc.perform(get("/login")) - .andExpect(redirectedUrl("https://localhost/login")); + this.mvc.perform(get("/login")).andExpect(redirectedUrl("https://localhost/login")); - this.mvc.perform(get("/secured/a")) - .andExpect(redirectedUrl("https://localhost/secured/a")); + this.mvc.perform(get("/secured/a")).andExpect(redirectedUrl("https://localhost/secured/a")); - this.mvc.perform(get("https://localhost/user")) - .andExpect(redirectedUrl("http://localhost/user")); + this.mvc.perform(get("https://localhost/user")).andExpect(redirectedUrl("http://localhost/user")); } @EnableWebSecurity @@ -154,10 +138,12 @@ public class NamespaceHttpInterceptUrlTests { .withUser("admin").password("password").roles("USER", "ADMIN"); // @formatter:on } + } @RestController static class BaseController { + @GetMapping("/users") public String users() { return "ok"; @@ -182,6 +168,7 @@ public class NamespaceHttpInterceptUrlTests { public String signup() { return "signup"; } + } private static Authentication user(String role) { diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.java index f9841f024a..be01d6b2cf 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.java @@ -15,7 +15,6 @@ */ package org.springframework.security.config.annotation.web.configurers; - import java.security.Principal; import java.util.stream.Collectors; @@ -66,16 +65,12 @@ public class NamespaceHttpJeeTests { Principal user = mock(Principal.class); when(user.getName()).thenReturn("joe"); - this.mvc.perform(get("/roles") - .principal(user) - .with(request -> { - request.addUserRole("ROLE_admin"); - request.addUserRole("ROLE_user"); - request.addUserRole("ROLE_unmapped"); - return request; - })) - .andExpect(status().isOk()) - .andExpect(content().string("ROLE_admin,ROLE_user")); + this.mvc.perform(get("/roles").principal(user).with(request -> { + request.addUserRole("ROLE_admin"); + request.addUserRole("ROLE_user"); + request.addUserRole("ROLE_unmapped"); + return request; + })).andExpect(status().isOk()).andExpect(content().string("ROLE_admin,ROLE_user")); } @EnableWebSecurity @@ -92,6 +87,7 @@ public class NamespaceHttpJeeTests { .mappableRoles("user", "admin"); // @formatter:on } + } @Test @@ -104,12 +100,9 @@ public class NamespaceHttpJeeTests { User result = new User(user.getName(), "N/A", true, true, true, true, AuthorityUtils.createAuthorityList("ROLE_user")); - when(bean(AuthenticationUserDetailsService.class).loadUserDetails(any())) - .thenReturn(result); + when(bean(AuthenticationUserDetailsService.class).loadUserDetails(any())).thenReturn(result); - this.mvc.perform(get("/roles") - .principal(user)) - .andExpect(status().isOk()) + this.mvc.perform(get("/roles").principal(user)).andExpect(status().isOk()) .andExpect(content().string("ROLE_user")); verifyBean(AuthenticationUserDetailsService.class).loadUserDetails(any()); @@ -117,8 +110,9 @@ public class NamespaceHttpJeeTests { @EnableWebSecurity public static class JeeUserServiceRefConfig extends WebSecurityConfigurerAdapter { - private final AuthenticationUserDetailsService authenticationUserDetailsService = - mock(AuthenticationUserDetailsService.class); + + private final AuthenticationUserDetailsService authenticationUserDetailsService = mock( + AuthenticationUserDetailsService.class); @Override protected void configure(HttpSecurity http) throws Exception { @@ -137,10 +131,12 @@ public class NamespaceHttpJeeTests { public AuthenticationUserDetailsService authenticationUserDetailsService() { return this.authenticationUserDetailsService; } + } @RestController static class BaseController { + @GetMapping("/authenticated") public String authenticated(Authentication authentication) { return authentication.getName(); @@ -148,9 +144,9 @@ public class NamespaceHttpJeeTests { @GetMapping("/roles") public String roles(Authentication authentication) { - return authentication.getAuthorities().stream() - .map(Object::toString).collect(Collectors.joining(",")); + return authentication.getAuthorities().stream().map(Object::toString).collect(Collectors.joining(",")); } + } private T bean(Class beanClass) { @@ -160,4 +156,5 @@ public class NamespaceHttpJeeTests { private T verifyBean(Class beanClass) { return verify(this.spring.getContext().getBean(beanClass)); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java index 6a74081ee4..23cc3dbdf4 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java @@ -71,18 +71,17 @@ public class NamespaceHttpLogoutTests { public void logoutWhenUsingDefaultsThenMatchesNamespace() throws Exception { this.spring.register(HttpLogoutConfig.class).autowire(); - this.mvc.perform(post("/logout").with(csrf())) - .andExpect(authenticated(false)) - .andExpect(redirectedUrl("/login?logout")) - .andExpect(noCookies()) - .andExpect(session(Objects::isNull)); + this.mvc.perform(post("/logout").with(csrf())).andExpect(authenticated(false)) + .andExpect(redirectedUrl("/login?logout")).andExpect(noCookies()).andExpect(session(Objects::isNull)); } @EnableWebSecurity static class HttpLogoutConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) { } + } @Test @@ -90,16 +89,17 @@ public class NamespaceHttpLogoutTests { public void logoutWhenDisabledInLambdaThenRespondsWithNotFound() throws Exception { this.spring.register(HttpLogoutDisabledInLambdaConfig.class).autowire(); - this.mvc.perform(post("/logout").with(csrf()).with(user("user"))) - .andExpect(status().isNotFound()); + this.mvc.perform(post("/logout").with(csrf()).with(user("user"))).andExpect(status().isNotFound()); } @EnableWebSecurity static class HttpLogoutDisabledInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { http.logout(AbstractHttpConfigurer::disable); } + } /** @@ -110,16 +110,15 @@ public class NamespaceHttpLogoutTests { public void logoutWhenUsingVariousCustomizationsMatchesNamespace() throws Exception { this.spring.register(CustomHttpLogoutConfig.class).autowire(); - this.mvc.perform(post("/custom-logout").with(csrf())) - .andExpect(authenticated(false)) + this.mvc.perform(post("/custom-logout").with(csrf())).andExpect(authenticated(false)) .andExpect(redirectedUrl("/logout-success")) .andExpect(result -> assertThat(result.getResponse().getCookies()).hasSize(1)) - .andExpect(cookie().maxAge("remove", 0)) - .andExpect(session(Objects::nonNull)); + .andExpect(cookie().maxAge("remove", 0)).andExpect(session(Objects::nonNull)); } @EnableWebSecurity static class CustomHttpLogoutConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -131,6 +130,7 @@ public class NamespaceHttpLogoutTests { .logoutSuccessUrl("/logout-success"); // logout@success-url (default is /login?logout) // @formatter:on } + } @Test @@ -138,16 +138,15 @@ public class NamespaceHttpLogoutTests { public void logoutWhenUsingVariousCustomizationsInLambdaThenMatchesNamespace() throws Exception { this.spring.register(CustomHttpLogoutInLambdaConfig.class).autowire(); - this.mvc.perform(post("/custom-logout").with(csrf())) - .andExpect(authenticated(false)) + this.mvc.perform(post("/custom-logout").with(csrf())).andExpect(authenticated(false)) .andExpect(redirectedUrl("/logout-success")) .andExpect(result -> assertThat(result.getResponse().getCookies()).hasSize(1)) - .andExpect(cookie().maxAge("remove", 0)) - .andExpect(session(Objects::nonNull)); + .andExpect(cookie().maxAge("remove", 0)).andExpect(session(Objects::nonNull)); } @EnableWebSecurity static class CustomHttpLogoutInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -160,6 +159,7 @@ public class NamespaceHttpLogoutTests { ); // @formatter:on } + } /** @@ -170,19 +170,17 @@ public class NamespaceHttpLogoutTests { public void logoutWhenUsingSuccessHandlerRefThenMatchesNamespace() throws Exception { this.spring.register(SuccessHandlerRefHttpLogoutConfig.class).autowire(); - this.mvc.perform(post("/logout").with(csrf())) - .andExpect(authenticated(false)) - .andExpect(redirectedUrl("/SuccessHandlerRefHttpLogoutConfig")) - .andExpect(noCookies()) + this.mvc.perform(post("/logout").with(csrf())).andExpect(authenticated(false)) + .andExpect(redirectedUrl("/SuccessHandlerRefHttpLogoutConfig")).andExpect(noCookies()) .andExpect(session(Objects::isNull)); } @EnableWebSecurity static class SuccessHandlerRefHttpLogoutConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { - SimpleUrlLogoutSuccessHandler logoutSuccessHandler = - new SimpleUrlLogoutSuccessHandler(); + SimpleUrlLogoutSuccessHandler logoutSuccessHandler = new SimpleUrlLogoutSuccessHandler(); logoutSuccessHandler.setDefaultTargetUrl("/SuccessHandlerRefHttpLogoutConfig"); // @formatter:off http @@ -190,6 +188,7 @@ public class NamespaceHttpLogoutTests { .logoutSuccessHandler(logoutSuccessHandler); // @formatter:on } + } @Test @@ -197,15 +196,14 @@ public class NamespaceHttpLogoutTests { public void logoutWhenUsingSuccessHandlerRefInLambdaThenMatchesNamespace() throws Exception { this.spring.register(SuccessHandlerRefHttpLogoutInLambdaConfig.class).autowire(); - this.mvc.perform(post("/logout").with(csrf())) - .andExpect(authenticated(false)) - .andExpect(redirectedUrl("/SuccessHandlerRefHttpLogoutConfig")) - .andExpect(noCookies()) + this.mvc.perform(post("/logout").with(csrf())).andExpect(authenticated(false)) + .andExpect(redirectedUrl("/SuccessHandlerRefHttpLogoutConfig")).andExpect(noCookies()) .andExpect(session(Objects::isNull)); } @EnableWebSecurity static class SuccessHandlerRefHttpLogoutInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { SimpleUrlLogoutSuccessHandler logoutSuccessHandler = new SimpleUrlLogoutSuccessHandler(); @@ -216,13 +214,12 @@ public class NamespaceHttpLogoutTests { .logout(logout -> logout.logoutSuccessHandler(logoutSuccessHandler)); // @formatter:on } + } ResultMatcher authenticated(boolean authenticated) { - return result -> assertThat( - Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()) - .map(Authentication::isAuthenticated) - .orElse(false)).isEqualTo(authenticated); + return result -> assertThat(Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()) + .map(Authentication::isAuthenticated).orElse(false)).isEqualTo(authenticated); } ResultMatcher noCookies() { @@ -233,4 +230,5 @@ public class NamespaceHttpLogoutTests { return result -> assertThat(result.getRequest().getSession(false)) .is(new Condition(sessionPredicate, "sessionPredicate failed")); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java index 7687bab5d5..ca2ab7c267 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java @@ -86,15 +86,14 @@ public class NamespaceHttpOpenIDLoginTests { @Test public void openidLoginWhenUsingDefaultsThenMatchesNamespace() throws Exception { this.spring.register(OpenIDLoginConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(redirectedUrl("http://localhost/login")); - this.mvc.perform(post("/login/openid").with(csrf())) - .andExpect(redirectedUrl("/login?error")); + this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/login")); + this.mvc.perform(post("/login/openid").with(csrf())).andExpect(redirectedUrl("/login?error")); } @Configuration @EnableWebSecurity static class OpenIDLoginConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -106,6 +105,7 @@ public class NamespaceHttpOpenIDLoginTests { .permitAll(); // @formatter:on } + } @Test @@ -114,49 +114,42 @@ public class NamespaceHttpOpenIDLoginTests { AuthRequest mockAuthRequest = mock(AuthRequest.class); DiscoveryInformation mockDiscoveryInformation = mock(DiscoveryInformation.class); when(mockAuthRequest.getDestinationUrl(anyBoolean())).thenReturn("mockUrl"); - when(OpenIDLoginAttributeExchangeConfig.CONSUMER_MANAGER.associate(any())) - .thenReturn(mockDiscoveryInformation); - when(OpenIDLoginAttributeExchangeConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(), any())) - .thenReturn(mockAuthRequest); + when(OpenIDLoginAttributeExchangeConfig.CONSUMER_MANAGER.associate(any())).thenReturn(mockDiscoveryInformation); + when(OpenIDLoginAttributeExchangeConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(), + any())).thenReturn(mockAuthRequest); this.spring.register(OpenIDLoginAttributeExchangeConfig.class).autowire(); try (MockWebServer server = new MockWebServer()) { String endpoint = server.url("/").toString(); - server.enqueue(new MockResponse() - .addHeader(YADIS_XRDS_LOCATION, endpoint)); + server.enqueue(new MockResponse().addHeader(YADIS_XRDS_LOCATION, endpoint)); server.enqueue(new MockResponse() .setBody(String.format("%s", endpoint))); MvcResult mvcResult = this.mvc.perform(get("/login/openid") .param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, "https://www.google.com/1")) - .andExpect(status().isFound()) - .andReturn(); + .andExpect(status().isFound()).andReturn(); - Object attributeObject = mvcResult.getRequest().getSession().getAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST"); + Object attributeObject = mvcResult.getRequest().getSession() + .getAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST"); assertThat(attributeObject).isInstanceOf(List.class); List attributeList = (List) attributeObject; - assertThat(attributeList.stream().anyMatch(attribute -> - "firstname".equals(attribute.getName()) - && "https://axschema.org/namePerson/first".equals(attribute.getType()) - && attribute.isRequired())) - .isTrue(); - assertThat(attributeList.stream().anyMatch(attribute -> - "lastname".equals(attribute.getName()) - && "https://axschema.org/namePerson/last".equals(attribute.getType()) - && attribute.isRequired())) - .isTrue(); - assertThat(attributeList.stream().anyMatch(attribute -> - "email".equals(attribute.getName()) - && "https://axschema.org/contact/email".equals(attribute.getType()) - && attribute.isRequired())) - .isTrue(); + assertThat(attributeList.stream().anyMatch(attribute -> "firstname".equals(attribute.getName()) + && "https://axschema.org/namePerson/first".equals(attribute.getType()) && attribute.isRequired())) + .isTrue(); + assertThat(attributeList.stream().anyMatch(attribute -> "lastname".equals(attribute.getName()) + && "https://axschema.org/namePerson/last".equals(attribute.getType()) && attribute.isRequired())) + .isTrue(); + assertThat(attributeList.stream().anyMatch(attribute -> "email".equals(attribute.getName()) + && "https://axschema.org/contact/email".equals(attribute.getType()) && attribute.isRequired())) + .isTrue(); } } @Configuration @EnableWebSecurity static class OpenIDLoginAttributeExchangeConfig extends WebSecurityConfigurerAdapter { + static ConsumerManager CONSUMER_MANAGER; @Override @@ -196,13 +189,13 @@ public class NamespaceHttpOpenIDLoginTests { .permitAll(); // @formatter:on } + } @Test public void openidLoginWhenUsingCustomEndpointsThenMatchesNamespace() throws Exception { this.spring.register(OpenIDLoginCustomConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(redirectedUrl("http://localhost/authentication/login")); + this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/authentication/login")); this.mvc.perform(post("/authentication/login/process").with(csrf())) .andExpect(redirectedUrl("/authentication/login?failed")); } @@ -210,6 +203,7 @@ public class NamespaceHttpOpenIDLoginTests { @Configuration @EnableWebSecurity static class OpenIDLoginCustomConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { boolean alwaysUseDefaultSuccess = true; @@ -226,15 +220,13 @@ public class NamespaceHttpOpenIDLoginTests { .defaultSuccessUrl("/default", alwaysUseDefaultSuccess); // openid-login@default-target-url / openid-login@always-use-default-target // @formatter:on } + } @Test public void openidLoginWithCustomHandlersThenBehaviorMatchesNamespace() throws Exception { - OpenIDAuthenticationToken token = new OpenIDAuthenticationToken( - OpenIDAuthenticationStatus.SUCCESS, - "identityUrl", - "message", - Arrays.asList(new OpenIDAttribute("name", "type"))); + OpenIDAuthenticationToken token = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, + "identityUrl", "message", Arrays.asList(new OpenIDAttribute("name", "type"))); OpenIDLoginCustomRefsConfig.AUDS = mock(AuthenticationUserDetailsService.class); when(OpenIDLoginCustomRefsConfig.AUDS.loadUserDetails(any(Authentication.class))) @@ -246,15 +238,12 @@ public class NamespaceHttpOpenIDLoginTests { when(OpenIDLoginCustomRefsConfig.CONSUMER.endConsumption(any(HttpServletRequest.class))) .thenThrow(new AuthenticationServiceException("boom")); - this.mvc.perform(post("/login/openid").with(csrf()) - .param("openid.identity", "identity")) + this.mvc.perform(post("/login/openid").with(csrf()).param("openid.identity", "identity")) .andExpect(redirectedUrl("/custom/failure")); reset(OpenIDLoginCustomRefsConfig.CONSUMER); - when(OpenIDLoginCustomRefsConfig.CONSUMER.endConsumption(any(HttpServletRequest.class))) - .thenReturn(token); - this.mvc.perform(post("/login/openid").with(csrf()) - .param("openid.identity", "identity")) + when(OpenIDLoginCustomRefsConfig.CONSUMER.endConsumption(any(HttpServletRequest.class))).thenReturn(token); + this.mvc.perform(post("/login/openid").with(csrf()).param("openid.identity", "identity")) .andExpect(redirectedUrl("/custom/targetUrl")); verify(OpenIDLoginCustomRefsConfig.AUDS).loadUserDetails(any(Authentication.class)); @@ -264,14 +253,14 @@ public class NamespaceHttpOpenIDLoginTests { @Configuration @EnableWebSecurity static class OpenIDLoginCustomRefsConfig extends WebSecurityConfigurerAdapter { + static AuthenticationUserDetailsService AUDS; static AuthenticationDetailsSource ADS; static OpenIDConsumer CONSUMER; @Override protected void configure(HttpSecurity http) throws Exception { - SavedRequestAwareAuthenticationSuccessHandler handler = - new SavedRequestAwareAuthenticationSuccessHandler(); + SavedRequestAwareAuthenticationSuccessHandler handler = new SavedRequestAwareAuthenticationSuccessHandler(); handler.setDefaultTargetUrl("/custom/targetUrl"); // @formatter:off http @@ -293,14 +282,16 @@ public class NamespaceHttpOpenIDLoginTests { }); // @formatter:on } + } @Configuration static class UserDetailsServiceConfig { + @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( - // @formatter:off + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") @@ -308,5 +299,7 @@ public class NamespaceHttpOpenIDLoginTests { .build()); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.java index 062d561a06..b57f8ea6e5 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.java @@ -15,7 +15,6 @@ */ package org.springframework.security.config.annotation.web.configurers; - import org.junit.Rule; import org.junit.Test; @@ -49,14 +48,12 @@ public class NamespaceHttpPortMappingsTests { public void portMappingWhenRequestRequiresChannelThenBehaviorMatchesNamespace() throws Exception { this.spring.register(HttpInterceptUrlWithPortMapperConfig.class).autowire(); - this.mvc.perform(get("http://localhost:9080/login")) - .andExpect(redirectedUrl("https://localhost:9443/login")); + this.mvc.perform(get("http://localhost:9080/login")).andExpect(redirectedUrl("https://localhost:9443/login")); this.mvc.perform(get("http://localhost:9080/secured/a")) .andExpect(redirectedUrl("https://localhost:9443/secured/a")); - this.mvc.perform(get("https://localhost:9443/user")) - .andExpect(redirectedUrl("http://localhost:9080/user")); + this.mvc.perform(get("https://localhost:9443/user")).andExpect(redirectedUrl("http://localhost:9080/user")); } @EnableWebSecurity @@ -86,5 +83,7 @@ public class NamespaceHttpPortMappingsTests { .withUser("admin").password("password").roles("USER", "ADMIN"); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java index 4504f74d6f..6669eff98a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java @@ -59,13 +59,13 @@ public class NamespaceHttpRequestCacheTests { @Test public void requestWhenCustomRequestCacheThenBehaviorMatchesNamespace() throws Exception { this.spring.register(RequestCacheRefConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/")).andExpect(status().isForbidden()); verifyBean(RequestCache.class).saveRequest(any(HttpServletRequest.class), any(HttpServletResponse.class)); } @EnableWebSecurity static class RequestCacheRefConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -90,15 +90,14 @@ public class NamespaceHttpRequestCacheTests { public RequestCache requestCache() { return mock(RequestCache.class); } + } @Test public void requestWhenDefaultConfigurationThenUsesHttpSessionRequestCache() throws Exception { this.spring.register(DefaultRequestCacheRefConfig.class).autowire(); - MvcResult result = this.mvc.perform(get("/")) - .andExpect(status().isForbidden()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/")).andExpect(status().isForbidden()).andReturn(); HttpSession session = result.getRequest().getSession(false); assertThat(session).isNotNull(); @@ -107,6 +106,7 @@ public class NamespaceHttpRequestCacheTests { @EnableWebSecurity static class DefaultRequestCacheRefConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -123,9 +123,11 @@ public class NamespaceHttpRequestCacheTests { .withUser(PasswordEncodedUser.admin()); // @formatter:on } + } private T verifyBean(Class beanClass) { return verify(this.spring.getContext().getBean(beanClass)); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpServerAccessDeniedHandlerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpServerAccessDeniedHandlerTests.java index 94c07da54c..75eca225e8 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpServerAccessDeniedHandlerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpServerAccessDeniedHandlerTests.java @@ -15,7 +15,6 @@ */ package org.springframework.security.config.annotation.web.configurers; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -44,7 +43,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * Tests to verify that all the functionality of attributes is present + * Tests to verify that all the functionality of attributes is + * present * * @author Rob Winch * @author Josh Cummings @@ -61,14 +61,13 @@ public class NamespaceHttpServerAccessDeniedHandlerTests { @Test public void requestWhenCustomAccessDeniedPageThenBehaviorMatchesNamespace() throws Exception { this.spring.register(AccessDeniedPageConfig.class).autowire(); - this.mvc.perform(get("/") - .with(authentication(user()))) - .andExpect(status().isForbidden()) + this.mvc.perform(get("/").with(authentication(user()))).andExpect(status().isForbidden()) .andExpect(forwardedUrl("/AccessDeniedPageConfig")); } @EnableWebSecurity static class AccessDeniedPageConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -79,6 +78,7 @@ public class NamespaceHttpServerAccessDeniedHandlerTests { .accessDeniedPage("/AccessDeniedPageConfig"); // @formatter:on } + } private static Authentication user() { @@ -89,14 +89,13 @@ public class NamespaceHttpServerAccessDeniedHandlerTests { public void requestWhenCustomAccessDeniedPageInLambdaThenForwardedToCustomPage() throws Exception { this.spring.register(AccessDeniedPageInLambdaConfig.class).autowire(); - this.mvc.perform(get("/") - .with(authentication(user()))) - .andExpect(status().isForbidden()) + this.mvc.perform(get("/").with(authentication(user()))).andExpect(status().isForbidden()) .andExpect(forwardedUrl("/AccessDeniedPageConfig")); } @EnableWebSecurity static class AccessDeniedPageInLambdaConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -109,19 +108,20 @@ public class NamespaceHttpServerAccessDeniedHandlerTests { ); // @formatter:on } + } @Test public void requestWhenCustomAccessDeniedHandlerThenBehaviorMatchesNamespace() throws Exception { this.spring.register(AccessDeniedHandlerRefConfig.class).autowire(); - this.mvc.perform(get("/") - .with(authentication(user()))); - verifyBean(AccessDeniedHandler.class) - .handle(any(HttpServletRequest.class), any(HttpServletResponse.class), any(AccessDeniedException.class)); + this.mvc.perform(get("/").with(authentication(user()))); + verifyBean(AccessDeniedHandler.class).handle(any(HttpServletRequest.class), any(HttpServletResponse.class), + any(AccessDeniedException.class)); } @EnableWebSecurity static class AccessDeniedHandlerRefConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -137,21 +137,22 @@ public class NamespaceHttpServerAccessDeniedHandlerTests { AccessDeniedHandler accessDeniedHandler() { return mock(AccessDeniedHandler.class); } + } @Test public void requestWhenCustomAccessDeniedHandlerInLambdaThenBehaviorMatchesNamespace() throws Exception { this.spring.register(AccessDeniedHandlerRefInLambdaConfig.class).autowire(); - this.mvc.perform(get("/") - .with(authentication(user()))); + this.mvc.perform(get("/").with(authentication(user()))); - verify(AccessDeniedHandlerRefInLambdaConfig.accessDeniedHandler) - .handle(any(HttpServletRequest.class), any(HttpServletResponse.class), any(AccessDeniedException.class)); + verify(AccessDeniedHandlerRefInLambdaConfig.accessDeniedHandler).handle(any(HttpServletRequest.class), + any(HttpServletResponse.class), any(AccessDeniedException.class)); } @EnableWebSecurity static class AccessDeniedHandlerRefInLambdaConfig extends WebSecurityConfigurerAdapter { + static AccessDeniedHandler accessDeniedHandler = mock(AccessDeniedHandler.class); protected void configure(HttpSecurity http) throws Exception { @@ -171,9 +172,11 @@ public class NamespaceHttpServerAccessDeniedHandlerTests { AccessDeniedHandler accessDeniedHandler() { return accessDeniedHandler; } + } private T verifyBean(Class beanClass) { return verify(this.spring.getContext().getBean(beanClass)); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java index f77c04facd..26f3c39a83 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java @@ -51,7 +51,8 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; /** - * Tests to verify that all the functionality of attributes is present in Java config + * Tests to verify that all the functionality of attributes is present in Java + * config * * @author Rob Winch * @author Josh Cummings @@ -59,8 +60,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. */ public class NamespaceHttpX509Tests { - private static final User USER = - new User("customuser", "password", AuthorityUtils.createAuthorityList("ROLE_USER")); + private static final User USER = new User("customuser", "password", + AuthorityUtils.createAuthorityList("ROLE_USER")); @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -72,13 +73,13 @@ public class NamespaceHttpX509Tests { public void x509AuthenticationWhenUsingX509DefaultConfigurationThenMatchesNamespace() throws Exception { this.spring.register(X509Config.class, X509Controller.class).autowire(); X509Certificate certificate = loadCert("rod.cer"); - this.mvc.perform(get("/whoami").with(x509(certificate))) - .andExpect(content().string("rod")); + this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("rod")); } @EnableWebSecurity @EnableWebMvc public static class X509Config extends WebSecurityConfigurerAdapter { + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -98,6 +99,7 @@ public class NamespaceHttpX509Tests { .x509(); // @formatter:on } + } @Test @@ -105,8 +107,7 @@ public class NamespaceHttpX509Tests { this.spring.register(AuthenticationDetailsSourceRefConfig.class, X509Controller.class).autowire(); X509Certificate certificate = loadCert("rod.cer"); - this.mvc.perform(get("/whoami").with(x509(certificate))) - .andExpect(content().string("rod")); + this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("rod")); verifyBean(AuthenticationDetailsSource.class).buildDetails(any()); } @@ -114,6 +115,7 @@ public class NamespaceHttpX509Tests { @EnableWebSecurity @EnableWebMvc static class AuthenticationDetailsSourceRefConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -136,24 +138,24 @@ public class NamespaceHttpX509Tests { } @Bean - AuthenticationDetailsSource - authenticationDetailsSource() { + AuthenticationDetailsSource authenticationDetailsSource() { return mock(AuthenticationDetailsSource.class); } + } @Test public void x509AuthenticationWhenHasSubjectPrincipalRegexThenMatchesNamespace() throws Exception { this.spring.register(SubjectPrincipalRegexConfig.class, X509Controller.class).autowire(); X509Certificate certificate = loadCert("rodatexampledotcom.cer"); - this.mvc.perform(get("/whoami").with(x509(certificate))) - .andExpect(content().string("rod")); + this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("rod")); } @EnableWebMvc @EnableWebSecurity public static class SubjectPrincipalRegexConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -174,19 +176,20 @@ public class NamespaceHttpX509Tests { .subjectPrincipalRegex("CN=(.*?)@example.com(?:,|$)"); // @formatter:on } + } @Test public void x509AuthenticationWhenHasCustomPrincipalExtractorThenMatchesNamespace() throws Exception { this.spring.register(CustomPrincipalExtractorConfig.class, X509Controller.class).autowire(); X509Certificate certificate = loadCert("rodatexampledotcom.cer"); - this.mvc.perform(get("/whoami").with(x509(certificate))) - .andExpect(content().string("rod@example.com")); + this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("rod@example.com")); } @EnableWebMvc @EnableWebSecurity public static class CustomPrincipalExtractorConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -211,23 +214,25 @@ public class NamespaceHttpX509Tests { private String extractCommonName(X509Certificate certificate) { try { return ((X500Name) certificate.getSubjectDN()).getCommonName(); - } catch (Exception e) { + } + catch (Exception e) { throw new IllegalArgumentException(e); } } + } @Test public void x509AuthenticationWhenHasCustomUserDetailsServiceThenMatchesNamespace() throws Exception { this.spring.register(UserDetailsServiceRefConfig.class, X509Controller.class).autowire(); X509Certificate certificate = loadCert("rodatexampledotcom.cer"); - this.mvc.perform(get("/whoami").with(x509(certificate))) - .andExpect(content().string("customuser")); + this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("customuser")); } @EnableWebMvc @EnableWebSecurity public static class UserDetailsServiceRefConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -248,23 +253,22 @@ public class NamespaceHttpX509Tests { .userDetailsService(username -> USER); // @formatter:on } + } @Test public void x509AuthenticationWhenHasCustomAuthenticationUserDetailsServiceThenMatchesNamespace() throws Exception { this.spring.register(AuthenticationUserDetailsServiceConfig.class, X509Controller.class).autowire(); X509Certificate certificate = loadCert("rodatexampledotcom.cer"); - this.mvc.perform(get("/whoami").with(x509(certificate))) - .andExpect(content().string("customuser")); + this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("customuser")); } @EnableWebMvc @EnableWebSecurity public static class AuthenticationUserDetailsServiceConfig extends WebSecurityConfigurerAdapter { + protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth. - inMemoryAuthentication() - .withUser("rod").password("password").roles("USER", "ADMIN"); + auth.inMemoryAuthentication().withUser("rod").password("password").roles("USER", "ADMIN"); } protected void configure(HttpSecurity http) throws Exception { @@ -277,21 +281,25 @@ public class NamespaceHttpX509Tests { .authenticationUserDetailsService(authentication -> USER); // @formatter:on } + } @RestController public static class X509Controller { + @GetMapping("/whoami") - public String whoami(@AuthenticationPrincipal(expression="username") String name) { + public String whoami(@AuthenticationPrincipal(expression = "username") String name) { return name; } + } T loadCert(String location) { try (InputStream is = new ClassPathResource(location).getInputStream()) { CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); return (T) certFactory.generateCertificate(is); - } catch (Exception e) { + } + catch (Exception e) { throw new IllegalArgumentException(e); } } @@ -299,4 +307,5 @@ public class NamespaceHttpX509Tests { T verifyBean(Class beanClass) { return verify(this.spring.getContext().getBean(beanClass)); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java index b46aab6f9b..1fd45ff8e7 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java @@ -80,30 +80,22 @@ public class NamespaceRememberMeTests { @Test public void rememberMeLoginWhenUsingDefaultsThenMatchesNamespace() throws Exception { this.spring.register(RememberMeConfig.class, SecurityController.class).autowire(); - MvcResult result = this.mvc.perform(post("/login") - .with(rememberMeLogin())) - .andReturn(); + MvcResult result = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn(); MockHttpSession session = (MockHttpSession) result.getRequest().getSession(); Cookie rememberMe = result.getResponse().getCookie("remember-me"); assertThat(rememberMe).isNotNull(); - this.mvc.perform(get("/authentication-class") - .cookie(rememberMe)) + this.mvc.perform(get("/authentication-class").cookie(rememberMe)) .andExpect(content().string(RememberMeAuthenticationToken.class.getName())); - result = this.mvc.perform(post("/logout").with(csrf()) - .session(session) - .cookie(rememberMe)) - .andExpect(redirectedUrl("/login?logout")) - .andReturn(); + result = this.mvc.perform(post("/logout").with(csrf()).session(session).cookie(rememberMe)) + .andExpect(redirectedUrl("/login?logout")).andReturn(); rememberMe = result.getResponse().getCookie("remember-me"); assertThat(rememberMe).isNotNull().extracting(Cookie::getMaxAge).isEqualTo(0); - this.mvc.perform(post("/authentication-class").with(csrf()) - .cookie(rememberMe)) - .andExpect(redirectedUrl("http://localhost/login")) - .andReturn(); + this.mvc.perform(post("/authentication-class").with(csrf()).cookie(rememberMe)) + .andExpect(redirectedUrl("http://localhost/login")).andReturn(); } @Configuration @@ -122,28 +114,33 @@ public class NamespaceRememberMeTests { .rememberMe(); // @formatter:on } + } - // SEC-3170 - RememberMeService implementations should not have to also implement LogoutHandler + // SEC-3170 - RememberMeService implementations should not have to also implement + // LogoutHandler @Test public void logoutWhenCustomRememberMeServicesDeclaredThenUses() throws Exception { RememberMeServicesRefConfig.REMEMBER_ME_SERVICES = mock(RememberMeServicesWithoutLogoutHandler.class); this.spring.register(RememberMeServicesRefConfig.class).autowire(); this.mvc.perform(get("/")); - verify(RememberMeServicesRefConfig.REMEMBER_ME_SERVICES) - .autoLogin(any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(RememberMeServicesRefConfig.REMEMBER_ME_SERVICES).autoLogin(any(HttpServletRequest.class), + any(HttpServletResponse.class)); this.mvc.perform(post("/login").with(csrf())); - verify(RememberMeServicesRefConfig.REMEMBER_ME_SERVICES) - .loginFail(any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(RememberMeServicesRefConfig.REMEMBER_ME_SERVICES).loginFail(any(HttpServletRequest.class), + any(HttpServletResponse.class)); } - interface RememberMeServicesWithoutLogoutHandler extends RememberMeServices {} + interface RememberMeServicesWithoutLogoutHandler extends RememberMeServices { + + } @Configuration @EnableWebSecurity static class RememberMeServicesRefConfig extends WebSecurityConfigurerAdapter { + static RememberMeServices REMEMBER_ME_SERVICES; @Override @@ -156,6 +153,7 @@ public class NamespaceRememberMeTests { .rememberMeServices(REMEMBER_ME_SERVICES); // @formatter:on } + } @Test @@ -163,24 +161,22 @@ public class NamespaceRememberMeTests { AuthSuccessConfig.SUCCESS_HANDLER = mock(AuthenticationSuccessHandler.class); this.spring.register(AuthSuccessConfig.class).autowire(); - MvcResult result = this.mvc.perform(post("/login") - .with(rememberMeLogin())) - .andReturn(); + MvcResult result = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn(); verifyZeroInteractions(AuthSuccessConfig.SUCCESS_HANDLER); Cookie rememberMe = result.getResponse().getCookie("remember-me"); assertThat(rememberMe).isNotNull(); - this.mvc.perform(get("/somewhere") - .cookie(rememberMe)); + this.mvc.perform(get("/somewhere").cookie(rememberMe)); - verify(AuthSuccessConfig.SUCCESS_HANDLER).onAuthenticationSuccess - (any(HttpServletRequest.class), any(HttpServletResponse.class), any(Authentication.class)); + verify(AuthSuccessConfig.SUCCESS_HANDLER).onAuthenticationSuccess(any(HttpServletRequest.class), + any(HttpServletResponse.class), any(Authentication.class)); } @Configuration @EnableWebSecurity static class AuthSuccessConfig extends UsersConfig { + static AuthenticationSuccessHandler SUCCESS_HANDLER; @Override @@ -193,33 +189,28 @@ public class NamespaceRememberMeTests { .authenticationSuccessHandler(SUCCESS_HANDLER); // @formatter:on } + } @Test public void rememberMeLoginWhenKeyDeclaredThenMatchesNamespace() throws Exception { this.spring.register(WithoutKeyConfig.class, KeyConfig.class, SecurityController.class).autowire(); - Cookie withoutKey = this.mvc.perform(post("/without-key/login") - .with(rememberMeLogin())) - .andExpect(redirectedUrl("/")) - .andReturn().getResponse().getCookie("remember-me"); + Cookie withoutKey = this.mvc.perform(post("/without-key/login").with(rememberMeLogin())) + .andExpect(redirectedUrl("/")).andReturn().getResponse().getCookie("remember-me"); - this.mvc.perform(get("/somewhere") - .cookie(withoutKey)) - .andExpect(status().isFound()) + this.mvc.perform(get("/somewhere").cookie(withoutKey)).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/login")); - Cookie withKey = this.mvc.perform(post("/login") - .with(rememberMeLogin())) - .andReturn().getResponse().getCookie("remember-me"); - this.mvc.perform(get("/somewhere") - .cookie(withKey)) - .andExpect(status().isNotFound()); + Cookie withKey = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse() + .getCookie("remember-me"); + this.mvc.perform(get("/somewhere").cookie(withKey)).andExpect(status().isNotFound()); } @Configuration @EnableWebSecurity @Order(0) static class WithoutKeyConfig extends UsersConfig { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -231,11 +222,13 @@ public class NamespaceRememberMeTests { .rememberMe(); // @formatter:on } + } @Configuration @EnableWebSecurity static class KeyConfig extends UsersConfig { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -249,18 +242,20 @@ public class NamespaceRememberMeTests { .key("KeyConfig"); // @formatter:on } + } - // http/remember-me@services-alias is not supported use standard aliasing instead (i.e. @Bean("alias")) + // http/remember-me@services-alias is not supported use standard aliasing instead + // (i.e. @Bean("alias")) - // http/remember-me@data-source-ref is not supported directly. Instead use http/remember-me@token-repository-ref example + // http/remember-me@data-source-ref is not supported directly. Instead use + // http/remember-me@token-repository-ref example @Test public void rememberMeLoginWhenDeclaredTokenRepositoryThenMatchesNamespace() throws Exception { TokenRepositoryRefConfig.TOKEN_REPOSITORY = mock(PersistentTokenRepository.class); this.spring.register(TokenRepositoryRefConfig.class).autowire(); - this.mvc.perform(post("/login") - .with(rememberMeLogin())); + this.mvc.perform(post("/login").with(rememberMeLogin())); verify(TokenRepositoryRefConfig.TOKEN_REPOSITORY).createNewToken(any(PersistentRememberMeToken.class)); } @@ -268,6 +263,7 @@ public class NamespaceRememberMeTests { @Configuration @EnableWebSecurity static class TokenRepositoryRefConfig extends UsersConfig { + static PersistentTokenRepository TOKEN_REPOSITORY; @Override @@ -283,14 +279,14 @@ public class NamespaceRememberMeTests { .tokenRepository(TOKEN_REPOSITORY); // @formatter:on } + } @Test public void rememberMeLoginWhenTokenValidityDeclaredThenMatchesNamespace() throws Exception { this.spring.register(TokenValiditySecondsConfig.class).autowire(); - Cookie expiredRememberMe = this.mvc.perform(post("/login") - .with(rememberMeLogin())) - .andReturn().getResponse().getCookie("remember-me"); + Cookie expiredRememberMe = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse() + .getCookie("remember-me"); assertThat(expiredRememberMe).extracting(Cookie::getMaxAge).isEqualTo(314); } @@ -298,6 +294,7 @@ public class NamespaceRememberMeTests { @Configuration @EnableWebSecurity static class TokenValiditySecondsConfig extends UsersConfig { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -311,25 +308,23 @@ public class NamespaceRememberMeTests { .tokenValiditySeconds(314); // @formatter:on } + } @Test public void rememberMeLoginWhenUsingDefaultsThenCookieMaxAgeMatchesNamespace() throws Exception { this.spring.register(RememberMeConfig.class).autowire(); - Cookie expiredRememberMe = this.mvc.perform(post("/login") - .with(rememberMeLogin())) - .andReturn().getResponse().getCookie("remember-me"); + Cookie expiredRememberMe = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse() + .getCookie("remember-me"); - assertThat(expiredRememberMe).extracting(Cookie::getMaxAge) - .isEqualTo(AbstractRememberMeServices.TWO_WEEKS_S); + assertThat(expiredRememberMe).extracting(Cookie::getMaxAge).isEqualTo(AbstractRememberMeServices.TWO_WEEKS_S); } @Test public void rememberMeLoginWhenUsingSecureCookieThenMatchesNamespace() throws Exception { this.spring.register(UseSecureCookieConfig.class).autowire(); - Cookie secureCookie = this.mvc.perform(post("/login") - .with(rememberMeLogin())) - .andReturn().getResponse().getCookie("remember-me"); + Cookie secureCookie = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse() + .getCookie("remember-me"); assertThat(secureCookie).extracting(Cookie::getSecure).isEqualTo(true); } @@ -337,6 +332,7 @@ public class NamespaceRememberMeTests { @Configuration @EnableWebSecurity static class UseSecureCookieConfig extends UsersConfig { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -347,15 +343,14 @@ public class NamespaceRememberMeTests { .useSecureCookie(true); // @formatter:on } + } @Test public void rememberMeLoginWhenUsingDefaultsThenCookieSecurityMatchesNamespace() throws Exception { this.spring.register(RememberMeConfig.class).autowire(); - Cookie secureCookie = this.mvc.perform(post("/login") - .with(rememberMeLogin()) - .secure(true)) - .andReturn().getResponse().getCookie("remember-me"); + Cookie secureCookie = this.mvc.perform(post("/login").with(rememberMeLogin()).secure(true)).andReturn() + .getResponse().getCookie("remember-me"); assertThat(secureCookie).extracting(Cookie::getSecure).isEqualTo(true); } @@ -363,9 +358,8 @@ public class NamespaceRememberMeTests { @Test public void rememberMeLoginWhenParameterSpecifiedThenMatchesNamespace() throws Exception { this.spring.register(RememberMeParameterConfig.class).autowire(); - Cookie rememberMe = this.mvc.perform(post("/login") - .with(rememberMeLogin("rememberMe", true))) - .andReturn().getResponse().getCookie("remember-me"); + Cookie rememberMe = this.mvc.perform(post("/login").with(rememberMeLogin("rememberMe", true))).andReturn() + .getResponse().getCookie("remember-me"); assertThat(rememberMe).isNotNull(); } @@ -373,6 +367,7 @@ public class NamespaceRememberMeTests { @Configuration @EnableWebSecurity static class RememberMeParameterConfig extends UsersConfig { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -383,6 +378,7 @@ public class NamespaceRememberMeTests { .rememberMeParameter("rememberMe"); // @formatter:on } + } // SEC-2880 @@ -390,9 +386,8 @@ public class NamespaceRememberMeTests { @Test public void rememberMeLoginWhenCookieNameDeclaredThenMatchesNamespace() throws Exception { this.spring.register(RememberMeCookieNameConfig.class).autowire(); - Cookie rememberMe = this.mvc.perform(post("/login") - .with(rememberMeLogin())) - .andReturn().getResponse().getCookie("rememberMe"); + Cookie rememberMe = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse() + .getCookie("rememberMe"); assertThat(rememberMe).isNotNull(); } @@ -400,6 +395,7 @@ public class NamespaceRememberMeTests { @Configuration @EnableWebSecurity static class RememberMeCookieNameConfig extends UsersConfig { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -410,6 +406,7 @@ public class NamespaceRememberMeTests { .rememberMeCookieName("rememberMe"); // @formatter:on } + } @Test @@ -417,16 +414,15 @@ public class NamespaceRememberMeTests { DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE = mock(UserDetailsService.class); this.spring.register(DefaultsUserDetailsServiceWithDaoConfig.class).autowire(); - this.mvc.perform(post("/login") - .with(rememberMeLogin())); + this.mvc.perform(post("/login").with(rememberMeLogin())); - verify(DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE) - .loadUserByUsername("user"); + verify(DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE).loadUserByUsername("user"); } @EnableWebSecurity @Configuration static class DefaultsUserDetailsServiceWithDaoConfig extends WebSecurityConfigurerAdapter { + static UserDetailsService USERDETAILS_SERVICE; @Override @@ -446,6 +442,7 @@ public class NamespaceRememberMeTests { .userDetailsService(USERDETAILS_SERVICE); // @formatter:on } + } @Test @@ -456,16 +453,15 @@ public class NamespaceRememberMeTests { when(UserServiceRefConfig.USERDETAILS_SERVICE.loadUserByUsername("user")) .thenReturn(new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))); - this.mvc.perform(post("/login") - .with(rememberMeLogin())); + this.mvc.perform(post("/login").with(rememberMeLogin())); - verify(UserServiceRefConfig.USERDETAILS_SERVICE) - .loadUserByUsername("user"); + verify(UserServiceRefConfig.USERDETAILS_SERVICE).loadUserByUsername("user"); } @Configuration @EnableWebSecurity static class UserServiceRefConfig extends UsersConfig { + static UserDetailsService USERDETAILS_SERVICE; @Override @@ -478,6 +474,7 @@ public class NamespaceRememberMeTests { .userDetailsService(USERDETAILS_SERVICE); // @formatter:on } + } static RequestPostProcessor rememberMeLogin() { @@ -495,11 +492,12 @@ public class NamespaceRememberMeTests { } static class UsersConfig extends WebSecurityConfigurerAdapter { + @Override @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( - // @formatter:off + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") @@ -507,13 +505,17 @@ public class NamespaceRememberMeTests { .build()); // @formatter:on } + } @RestController static class SecurityController { + @GetMapping("/authentication-class") String authenticationClass(Authentication authentication) { return authentication.getClass().getName(); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java index 21ba2ef19d..105d370ec9 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java @@ -65,7 +65,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * * @author Rob Winch * @author Josh Cummings */ @@ -79,40 +78,34 @@ public class NamespaceSessionManagementTests { @Test public void authenticateWhenDefaultSessionManagementThenMatchesNamespace() throws Exception { - this.spring.register - (SessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class).autowire(); + this.spring.register(SessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class) + .autowire(); MockHttpSession session = new MockHttpSession(); String sessionId = session.getId(); - MvcResult result = - this.mvc.perform(get("/auth") - .session(session) - .with(httpBasic("user", "password"))) - .andExpect(session()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/auth").session(session).with(httpBasic("user", "password"))) + .andExpect(session()).andReturn(); assertThat(result.getRequest().getSession(false).getId()).isNotEqualTo(sessionId); } @EnableWebSecurity static class SessionManagementConfig extends WebSecurityConfigurerAdapter { + } @Test public void authenticateWhenUsingInvalidSessionUrlThenMatchesNamespace() throws Exception { this.spring.register(CustomSessionManagementConfig.class).autowire(); - this.mvc.perform(get("/auth") - .with(request -> { - request.setRequestedSessionIdValid(false); - request.setRequestedSessionId("id"); - return request; - })) - .andExpect(redirectedUrl("/invalid-session")); + this.mvc.perform(get("/auth").with(request -> { + request.setRequestedSessionIdValid(false); + request.setRequestedSessionId("id"); + return request; + })).andExpect(redirectedUrl("/invalid-session")); } - @Test public void authenticateWhenUsingExpiredUrlThenMatchesNamespace() throws Exception { this.spring.register(CustomSessionManagementConfig.class).autowire(); @@ -123,53 +116,49 @@ public class NamespaceSessionManagementTests { SessionRegistry sessionRegistry = this.spring.getContext().getBean(SessionRegistry.class); when(sessionRegistry.getSessionInformation(session.getId())).thenReturn(sessionInformation); - this.mvc.perform(get("/auth").session(session)) - .andExpect(redirectedUrl("/expired-session")); + this.mvc.perform(get("/auth").session(session)).andExpect(redirectedUrl("/expired-session")); } @Test public void authenticateWhenUsingMaxSessionsThenMatchesNamespace() throws Exception { - this.spring.register(CustomSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class).autowire(); + this.spring.register(CustomSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class) + .autowire(); - this.mvc.perform(get("/auth") - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isOk()); - this.mvc.perform(get("/auth") - .with(httpBasic("user", "password"))) + this.mvc.perform(get("/auth").with(httpBasic("user", "password"))) .andExpect(redirectedUrl("/session-auth-error")); } @Test public void authenticateWhenUsingFailureUrlThenMatchesNamespace() throws Exception { - this.spring.register(CustomSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class).autowire(); + this.spring.register(CustomSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class) + .autowire(); MockHttpServletRequest mock = spy(MockHttpServletRequest.class); mock.setSession(new MockHttpSession()); when(mock.changeSessionId()).thenThrow(SessionAuthenticationException.class); mock.setMethod("GET"); - this.mvc.perform(get("/auth") - .with(request -> mock) - .with(httpBasic("user", "password"))) + this.mvc.perform(get("/auth").with(request -> mock).with(httpBasic("user", "password"))) .andExpect(redirectedUrl("/session-auth-error")); } @Test public void authenticateWhenUsingSessionRegistryThenMatchesNamespace() throws Exception { - this.spring.register(CustomSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class).autowire(); + this.spring.register(CustomSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class) + .autowire(); SessionRegistry sessionRegistry = this.spring.getContext().getBean(SessionRegistry.class); - this.mvc.perform(get("/auth") - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isOk()); verify(sessionRegistry).registerNewSession(any(String.class), any(Object.class)); } @EnableWebSecurity static class CustomSessionManagementConfig extends WebSecurityConfigurerAdapter { + SessionRegistry sessionRegistry = spy(SessionRegistryImpl.class); @Override @@ -195,28 +184,27 @@ public class NamespaceSessionManagementTests { SessionRegistry sessionRegistry() { return this.sessionRegistry; } - } + } // gh-3371 @Test public void authenticateWhenUsingCustomInvalidSessionStrategyThenMatchesNamespace() throws Exception { this.spring.register(InvalidSessionStrategyConfig.class).autowire(); - this.mvc.perform(get("/auth") - .with(request -> { - request.setRequestedSessionIdValid(false); - request.setRequestedSessionId("id"); - return request; - })) - .andExpect(status().isOk()); + this.mvc.perform(get("/auth").with(request -> { + request.setRequestedSessionIdValid(false); + request.setRequestedSessionId("id"); + return request; + })).andExpect(status().isOk()); - verifyBean(InvalidSessionStrategy.class) - .onInvalidSessionDetected(any(HttpServletRequest.class), any(HttpServletResponse.class)); + verifyBean(InvalidSessionStrategy.class).onInvalidSessionDetected(any(HttpServletRequest.class), + any(HttpServletResponse.class)); } @EnableWebSecurity static class InvalidSessionStrategyConfig extends WebSecurityConfigurerAdapter { + InvalidSessionStrategy invalidSessionStrategy = mock(InvalidSessionStrategy.class); @Override @@ -232,25 +220,24 @@ public class NamespaceSessionManagementTests { InvalidSessionStrategy invalidSessionStrategy() { return this.invalidSessionStrategy; } + } @Test public void authenticateWhenUsingCustomSessionAuthenticationStrategyThenMatchesNamespace() throws Exception { - this.spring.register(RefsSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class).autowire(); + this.spring.register(RefsSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class) + .autowire(); - this.mvc.perform(get("/auth") - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isOk()); - verifyBean(SessionAuthenticationStrategy.class) - .onAuthentication(any(Authentication.class), - any(HttpServletRequest.class), any(HttpServletResponse.class)); + verifyBean(SessionAuthenticationStrategy.class).onAuthentication(any(Authentication.class), + any(HttpServletRequest.class), any(HttpServletResponse.class)); } @EnableWebSecurity static class RefsSessionManagementConfig extends WebSecurityConfigurerAdapter { - SessionAuthenticationStrategy sessionAuthenticationStrategy = - mock(SessionAuthenticationStrategy.class); + + SessionAuthenticationStrategy sessionAuthenticationStrategy = mock(SessionAuthenticationStrategy.class); @Override protected void configure(HttpSecurity http) throws Exception { @@ -267,26 +254,27 @@ public class NamespaceSessionManagementTests { SessionAuthenticationStrategy sessionAuthenticationStrategy() { return this.sessionAuthenticationStrategy; } + } @Test public void authenticateWhenNoSessionFixationProtectionThenMatchesNamespace() throws Exception { - this.spring.register(SFPNoneSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class).autowire(); + this.spring + .register(SFPNoneSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class) + .autowire(); MockHttpSession givenSession = new MockHttpSession(); String givenSessionId = givenSession.getId(); - MockHttpSession resultingSession = (MockHttpSession) - this.mvc.perform(get("/auth") - .session(givenSession) - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()) - .andReturn().getRequest().getSession(false); + MockHttpSession resultingSession = (MockHttpSession) this.mvc + .perform(get("/auth").session(givenSession).with(httpBasic("user", "password"))) + .andExpect(status().isOk()).andReturn().getRequest().getSession(false); assertThat(givenSessionId).isEqualTo(resultingSession.getId()); } @EnableWebSecurity static class SFPNoneSessionManagementConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -297,22 +285,21 @@ public class NamespaceSessionManagementTests { .httpBasic(); // @formatter:on } + } @Test public void authenticateWhenMigrateSessionFixationProtectionThenMatchesNamespace() throws Exception { - this.spring.register(SFPMigrateSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class).autowire(); + this.spring.register(SFPMigrateSessionManagementConfig.class, BasicController.class, + UserDetailsServiceConfig.class).autowire(); MockHttpSession givenSession = new MockHttpSession(); String givenSessionId = givenSession.getId(); givenSession.setAttribute("name", "value"); - MockHttpSession resultingSession = (MockHttpSession) - this.mvc.perform(get("/auth") - .session(givenSession) - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()) - .andReturn().getRequest().getSession(false); + MockHttpSession resultingSession = (MockHttpSession) this.mvc + .perform(get("/auth").session(givenSession).with(httpBasic("user", "password"))) + .andExpect(status().isOk()).andReturn().getRequest().getSession(false); assertThat(givenSessionId).isNotEqualTo(resultingSession.getId()); assertThat(resultingSession.getAttribute("name")).isEqualTo("value"); @@ -320,6 +307,7 @@ public class NamespaceSessionManagementTests { @EnableWebSecurity static class SFPMigrateSessionManagementConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -329,6 +317,7 @@ public class NamespaceSessionManagementTests { .httpBasic(); // @formatter:on } + } // SEC-2913 @@ -336,9 +325,7 @@ public class NamespaceSessionManagementTests { public void authenticateWhenUsingSessionFixationProtectionThenUsesNonNullEventPublisher() throws Exception { this.spring.register(SFPPostProcessedConfig.class, UserDetailsServiceConfig.class).autowire(); - this.mvc.perform(get("/auth") - .session(new MockHttpSession()) - .with(httpBasic("user", "password"))) + this.mvc.perform(get("/auth").session(new MockHttpSession()).with(httpBasic("user", "password"))) .andExpect(status().isNotFound()); verifyBean(MockEventListener.class).onApplicationEvent(any(SessionFixationProtectionEvent.class)); @@ -346,6 +333,7 @@ public class NamespaceSessionManagementTests { @EnableWebSecurity static class SFPPostProcessedConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -360,6 +348,7 @@ public class NamespaceSessionManagementTests { public MockEventListener eventListener() { return spy(new MockEventListener()); } + } @Test @@ -370,12 +359,9 @@ public class NamespaceSessionManagementTests { String givenSessionId = givenSession.getId(); givenSession.setAttribute("name", "value"); - MockHttpSession resultingSession = (MockHttpSession) - this.mvc.perform(get("/auth") - .session(givenSession) - .with(httpBasic("user", "password"))) - .andExpect(status().isNotFound()) - .andReturn().getRequest().getSession(false); + MockHttpSession resultingSession = (MockHttpSession) this.mvc + .perform(get("/auth").session(givenSession).with(httpBasic("user", "password"))) + .andExpect(status().isNotFound()).andReturn().getRequest().getSession(false); assertThat(givenSessionId).isNotEqualTo(resultingSession.getId()); assertThat(resultingSession.getAttribute("name")).isNull(); @@ -383,6 +369,7 @@ public class NamespaceSessionManagementTests { @EnableWebSecurity static class SFPNewSessionSessionManagementConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -393,27 +380,30 @@ public class NamespaceSessionManagementTests { .httpBasic(); // @formatter:on } - } + } private T verifyBean(Class clazz) { return verify(this.spring.getContext().getBean(clazz)); } static class MockEventListener implements ApplicationListener { + List events = new ArrayList<>(); public void onApplicationEvent(SessionFixationProtectionEvent event) { this.events.add(event); } + } @Configuration static class UserDetailsServiceConfig { + @Bean UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( - // @formatter:off + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") @@ -421,10 +411,12 @@ public class NamespaceSessionManagementTests { .build()); // @formatter:on } + } @RestController static class BasicController { + @GetMapping("/") public String ok() { return "ok"; @@ -434,6 +426,7 @@ public class NamespaceSessionManagementTests { public String auth(Principal principal) { return principal.getName(); } + } private static SessionResultMatcher session() { @@ -441,8 +434,11 @@ public class NamespaceSessionManagementTests { } private static class SessionResultMatcher implements ResultMatcher { + private String id; + private Boolean valid; + private Boolean exists = true; public ResultMatcher exists(boolean exists) { @@ -474,7 +470,8 @@ public class NamespaceSessionManagementTests { if (this.valid != null) { if (this.valid) { assertThat(session.isInvalid()).isFalse(); - } else { + } + else { assertThat(session.isInvalid()).isTrue(); } } @@ -483,5 +480,7 @@ public class NamespaceSessionManagementTests { assertThat(session.getId()).isEqualTo(this.id); } } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.java index be0d8b9cd2..0af8e42362 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.java @@ -49,18 +49,15 @@ public class PermitAllSupportTests { public void performWhenUsingPermitAllExactUrlRequestMatcherThenMatchesExactUrl() throws Exception { this.spring.register(PermitAllConfig.class).autowire(); - this.mvc.perform(get("/app/xyz").contextPath("/app")) - .andExpect(status().isNotFound()); - this.mvc.perform(get("/app/xyz?def").contextPath("/app")) - .andExpect(status().isFound()); - this.mvc.perform(post("/app/abc?def").with(csrf()).contextPath("/app")) - .andExpect(status().isNotFound()); - this.mvc.perform(get("/app/abc").with(csrf()).contextPath("/app")) - .andExpect(status().isFound()); + this.mvc.perform(get("/app/xyz").contextPath("/app")).andExpect(status().isNotFound()); + this.mvc.perform(get("/app/xyz?def").contextPath("/app")).andExpect(status().isFound()); + this.mvc.perform(post("/app/abc?def").with(csrf()).contextPath("/app")).andExpect(status().isNotFound()); + this.mvc.perform(get("/app/abc").with(csrf()).contextPath("/app")).andExpect(status().isFound()); } @EnableWebSecurity static class PermitAllConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -73,6 +70,7 @@ public class PermitAllSupportTests { .loginProcessingUrl("/abc?def").permitAll(); // @formatter:on } + } @Test @@ -93,5 +91,7 @@ public class PermitAllSupportTests { .permitAll(); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java index 715e079c9e..0d1519882d 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java @@ -35,6 +35,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Josh Cummings */ public class PortMapperConfigurerTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -45,8 +46,7 @@ public class PortMapperConfigurerTests { public void requestWhenPortMapperTwiceInvokedThenDoesNotOverride() throws Exception { this.spring.register(InvokeTwiceDoesNotOverride.class).autowire(); - this.mockMvc.perform(get("http://localhost:543")) - .andExpect(redirectedUrl("https://localhost:123")); + this.mockMvc.perform(get("http://localhost:543")).andExpect(redirectedUrl("https://localhost:123")); } @EnableWebSecurity @@ -65,18 +65,19 @@ public class PortMapperConfigurerTests { .portMapper(); // @formatter:on } + } @Test public void requestWhenPortMapperHttpMapsToInLambdaThenRedirectsToHttpsPort() throws Exception { this.spring.register(HttpMapsToInLambdaConfig.class).autowire(); - this.mockMvc.perform(get("http://localhost:543")) - .andExpect(redirectedUrl("https://localhost:123")); + this.mockMvc.perform(get("http://localhost:543")).andExpect(redirectedUrl("https://localhost:123")); } @EnableWebSecurity static class HttpMapsToInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -91,18 +92,19 @@ public class PortMapperConfigurerTests { ); // @formatter:on } + } @Test public void requestWhenCustomPortMapperInLambdaThenRedirectsToHttpsPort() throws Exception { this.spring.register(CustomPortMapperInLambdaConfig.class).autowire(); - this.mockMvc.perform(get("http://localhost:543")) - .andExpect(redirectedUrl("https://localhost:123")); + this.mockMvc.perform(get("http://localhost:543")).andExpect(redirectedUrl("https://localhost:123")); } @EnableWebSecurity static class CustomPortMapperInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { PortMapperImpl customPortMapper = new PortMapperImpl(); @@ -119,5 +121,7 @@ public class PortMapperConfigurerTests { ); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java index 2988162ff0..e3ea0b15ea 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java @@ -80,17 +80,13 @@ public class RememberMeConfigurerTests { public void postWhenNoUserDetailsServiceThenException() { this.spring.register(NullUserDetailsConfig.class).autowire(); - assertThatThrownBy(() -> - mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .param("remember-me", "true") - .with(csrf()))) - .hasMessageContaining("UserDetailsService is required"); + assertThatThrownBy(() -> mvc.perform(post("/login").param("username", "user").param("password", "password") + .param("remember-me", "true").with(csrf()))).hasMessageContaining("UserDetailsService is required"); } @EnableWebSecurity static class NullUserDetailsConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -113,18 +109,19 @@ public class RememberMeConfigurerTests { .authenticationProvider(provider); // @formatter:on } + } @Test public void configureWhenRegisteringObjectPostProcessorThenInvokedOnRememberMeAuthenticationFilter() { this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(RememberMeAuthenticationFilter.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(RememberMeAuthenticationFilter.class)); } @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class); @Override @@ -148,13 +145,16 @@ public class RememberMeConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } @Test @@ -163,15 +163,14 @@ public class RememberMeConfigurerTests { .thenReturn(new User("user", "password", Collections.emptyList())); this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire(); - this.mvc.perform(get("/") - .with(httpBasic("user", "password")) - .param("remember-me", "true")); + this.mvc.perform(get("/").with(httpBasic("user", "password")).param("remember-me", "true")); verify(DuplicateDoesNotOverrideConfig.userDetailsService).loadUserByUsername("user"); } @EnableWebSecurity static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter { + static UserDetailsService userDetailsService = mock(UserDetailsService.class); @Override @@ -190,7 +189,7 @@ public class RememberMeConfigurerTests { @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( - // @formatter:off + // @formatter:off User.withDefaultPasswordEncoder() .username("user") .password("password") @@ -199,81 +198,56 @@ public class RememberMeConfigurerTests { // @formatter:on ); } + } @Test public void loginWhenRememberMeTrueThenRespondsWithRememberMeCookie() throws Exception { this.spring.register(RememberMeConfig.class).autowire(); - this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password") - .param("remember-me", "true")) - .andExpect(cookie().exists("remember-me")); + this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password") + .param("remember-me", "true")).andExpect(cookie().exists("remember-me")); } @Test public void getWhenRememberMeCookieThenAuthenticationIsRememberMeAuthenticationToken() throws Exception { this.spring.register(RememberMeConfig.class).autowire(); - MvcResult mvcResult = this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password") - .param("remember-me", "true")) - .andReturn(); + MvcResult mvcResult = this.mvc.perform(post("/login").with(csrf()).param("username", "user") + .param("password", "password").param("remember-me", "true")).andReturn(); Cookie rememberMeCookie = mvcResult.getResponse().getCookie("remember-me"); - this.mvc.perform(get("/abc") - .cookie(rememberMeCookie)) - .andExpect(authenticated().withAuthentication(auth -> - assertThat(auth).isInstanceOf(RememberMeAuthenticationToken.class))); + this.mvc.perform(get("/abc").cookie(rememberMeCookie)).andExpect(authenticated() + .withAuthentication(auth -> assertThat(auth).isInstanceOf(RememberMeAuthenticationToken.class))); } @Test public void logoutWhenRememberMeCookieThenAuthenticationIsRememberMeCookieExpired() throws Exception { this.spring.register(RememberMeConfig.class).autowire(); - MvcResult mvcResult = this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password") - .param("remember-me", "true")) - .andReturn(); + MvcResult mvcResult = this.mvc.perform(post("/login").with(csrf()).param("username", "user") + .param("password", "password").param("remember-me", "true")).andReturn(); Cookie rememberMeCookie = mvcResult.getResponse().getCookie("remember-me"); HttpSession session = mvcResult.getRequest().getSession(); - this.mvc.perform(post("/logout") - .with(csrf()) - .cookie(rememberMeCookie) - .session((MockHttpSession) session)) - .andExpect(redirectedUrl("/login?logout")) - .andExpect(cookie().maxAge("remember-me", 0)); + this.mvc.perform(post("/logout").with(csrf()).cookie(rememberMeCookie).session((MockHttpSession) session)) + .andExpect(redirectedUrl("/login?logout")).andExpect(cookie().maxAge("remember-me", 0)); } @Test public void getWhenRememberMeCookieAndLoggedOutThenRedirectsToLogin() throws Exception { this.spring.register(RememberMeConfig.class).autowire(); - MvcResult loginMvcResult = this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password") - .param("remember-me", "true")) - .andReturn(); + MvcResult loginMvcResult = this.mvc.perform(post("/login").with(csrf()).param("username", "user") + .param("password", "password").param("remember-me", "true")).andReturn(); Cookie rememberMeCookie = loginMvcResult.getResponse().getCookie("remember-me"); HttpSession session = loginMvcResult.getRequest().getSession(); - MvcResult logoutMvcResult = this.mvc.perform(post("/logout") - .with(csrf()) - .cookie(rememberMeCookie) - .session((MockHttpSession) session)) + MvcResult logoutMvcResult = this.mvc + .perform(post("/logout").with(csrf()).cookie(rememberMeCookie).session((MockHttpSession) session)) .andReturn(); Cookie expiredRememberMeCookie = logoutMvcResult.getResponse().getCookie("remember-me"); - this.mvc.perform(get("/abc") - .with(csrf()) - .cookie(expiredRememberMeCookie)) + this.mvc.perform(get("/abc").with(csrf()).cookie(expiredRememberMeCookie)) .andExpect(redirectedUrl("http://localhost/login")); } @@ -301,19 +275,15 @@ public class RememberMeConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } - } + } @Test public void loginWhenRememberMeConfiguredInLambdaThenRespondsWithRememberMeCookie() throws Exception { this.spring.register(RememberMeInLambdaConfig.class).autowire(); - this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password") - .param("remember-me", "true")) - .andExpect(cookie().exists("remember-me")); + this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password") + .param("remember-me", "true")).andExpect(cookie().exists("remember-me")); } @EnableWebSecurity @@ -340,23 +310,21 @@ public class RememberMeConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test public void loginWhenRememberMeTrueAndCookieDomainThenRememberMeCookieHasDomain() throws Exception { this.spring.register(RememberMeCookieDomainConfig.class).autowire(); - this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password") - .param("remember-me", "true")) - .andExpect(cookie().exists("remember-me")) + this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password") + .param("remember-me", "true")).andExpect(cookie().exists("remember-me")) .andExpect(cookie().domain("remember-me", "spring.io")); } @EnableWebSecurity static class RememberMeCookieDomainConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -378,23 +346,21 @@ public class RememberMeConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test public void loginWhenRememberMeTrueAndCookieDomainInLambdaThenRememberMeCookieHasDomain() throws Exception { this.spring.register(RememberMeCookieDomainInLambdaConfig.class).autowire(); - this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password") - .param("remember-me", "true")) - .andExpect(cookie().exists("remember-me")) + this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password") + .param("remember-me", "true")).andExpect(cookie().exists("remember-me")) .andExpect(cookie().domain("remember-me", "spring.io")); } @EnableWebSecurity static class RememberMeCookieDomainInLambdaConfig extends WebSecurityConfigurerAdapter { + protected void configure(HttpSecurity http) throws Exception { // @formatter:off http @@ -418,18 +384,19 @@ public class RememberMeConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test public void configureWhenRememberMeCookieNameAndRememberMeServicesThenException() { assertThatThrownBy(() -> this.spring.register(RememberMeCookieNameAndRememberMeServicesConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasRootCauseInstanceOf(IllegalArgumentException.class) + .isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class) .hasMessageContaining("Can not set rememberMeCookieName and custom rememberMeServices."); } @EnableWebSecurity static class RememberMeCookieNameAndRememberMeServicesConfig extends WebSecurityConfigurerAdapter { + static RememberMeServices REMEMBER_ME = mock(RememberMeServices.class); protected void configure(HttpSecurity http) throws Exception { @@ -455,25 +422,19 @@ public class RememberMeConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test - public void getWhenRememberMeCookieAndNoKeyConfiguredThenKeyFromRememberMeServicesIsUsed() - throws Exception { + public void getWhenRememberMeCookieAndNoKeyConfiguredThenKeyFromRememberMeServicesIsUsed() throws Exception { this.spring.register(FallbackRememberMeKeyConfig.class).autowire(); - MvcResult mvcResult = this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password") - .param("remember-me", "true")) - .andReturn(); + MvcResult mvcResult = this.mvc.perform(post("/login").with(csrf()).param("username", "user") + .param("password", "password").param("remember-me", "true")).andReturn(); Cookie rememberMeCookie = mvcResult.getResponse().getCookie("remember-me"); - this.mvc.perform(get("/abc") - .cookie(rememberMeCookie)) - .andExpect(authenticated().withAuthentication(auth -> - assertThat(auth).isInstanceOf(RememberMeAuthenticationToken.class))); + this.mvc.perform(get("/abc").cookie(rememberMeCookie)).andExpect(authenticated() + .withAuthentication(auth -> assertThat(auth).isInstanceOf(RememberMeAuthenticationToken.class))); } @EnableWebSecurity @@ -487,5 +448,7 @@ public class RememberMeConfigurerTests { .rememberMeServices(new TokenBasedRememberMeServices("key", userDetailsService())); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java index 3647b0210a..6e8c4b0ac4 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java @@ -69,12 +69,12 @@ public class RequestCacheConfigurerTests { public void configureWhenRegisteringObjectPostProcessorThenInvokedOnExceptionTranslationFilter() { this.spring.register(ObjectPostProcessorConfig.class, DefaultSecurityConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(RequestCacheAwareFilter.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(RequestCacheAwareFilter.class)); } @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class); @Override @@ -89,13 +89,16 @@ public class RequestCacheConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } @Test @@ -104,12 +107,13 @@ public class RequestCacheConfigurerTests { this.mvc.perform(get("/")); - verify(InvokeTwiceDoesNotOverrideConfig.requestCache) - .getMatchingRequest(any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(InvokeTwiceDoesNotOverrideConfig.requestCache).getMatchingRequest(any(HttpServletRequest.class), + any(HttpServletResponse.class)); } @EnableWebSecurity static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter { + static RequestCache requestCache = mock(RequestCache.class); @Override @@ -122,32 +126,29 @@ public class RequestCacheConfigurerTests { .requestCache(); // @formatter:on } + } @Test public void getWhenBookmarkedUrlIsFaviconIcoThenPostAuthenticationRedirectsToRoot() throws Exception { this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire(); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(get("/favicon.ico")) - .andExpect(redirectedUrl("http://localhost/login")) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/favicon.ico")) + .andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession(); - this.mvc.perform(formLogin(session)) - .andExpect(redirectedUrl("/")); // ignores favicon.ico + this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/")); // ignores + // favicon.ico } @Test public void getWhenBookmarkedUrlIsFaviconPngThenPostAuthenticationRedirectsToRoot() throws Exception { this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire(); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(get("/favicon.png")) - .andExpect(redirectedUrl("http://localhost/login")) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/favicon.png")) + .andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession(); - this.mvc.perform(formLogin(session)) - .andExpect(redirectedUrl("/")); // ignores favicon.png + this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/")); // ignores + // favicon.png } // SEC-2321 @@ -155,16 +156,15 @@ public class RequestCacheConfigurerTests { public void getWhenBookmarkedRequestIsApplicationJsonThenPostAuthenticationRedirectsToRoot() throws Exception { this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire(); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(get("/messages") - .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON)) - .andExpect(redirectedUrl("http://localhost/login")) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mvc + .perform(get("/messages").header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON)) + .andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession(); - this.mvc.perform(formLogin(session)) - .andExpect(redirectedUrl("/")); // ignores application/json + this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/")); // ignores + // application/json - // This is desirable since JSON requests are typically not invoked directly from the browser and we don't want the browser to replay them + // This is desirable since JSON requests are typically not invoked directly from + // the browser and we don't want the browser to replay them } // SEC-2321 @@ -172,87 +172,74 @@ public class RequestCacheConfigurerTests { public void getWhenBookmarkedRequestIsXRequestedWithThenPostAuthenticationRedirectsToRoot() throws Exception { this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire(); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(get("/messages") - .header("X-Requested-With", "XMLHttpRequest")) - .andExpect(redirectedUrl("http://localhost/login")) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mvc + .perform(get("/messages").header("X-Requested-With", "XMLHttpRequest")) + .andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession(); - this.mvc.perform(formLogin(session)) - .andExpect(redirectedUrl("/")); + this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/")); - // This is desirable since XHR requests are typically not invoked directly from the browser and we don't want the browser to replay them + // This is desirable since XHR requests are typically not invoked directly from + // the browser and we don't want the browser to replay them } + @Test public void getWhenBookmarkedRequestIsTextEventStreamThenPostAuthenticationRedirectsToRoot() throws Exception { this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire(); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(get("/messages") - .header(HttpHeaders.ACCEPT, MediaType.TEXT_EVENT_STREAM)) - .andExpect(redirectedUrl("http://localhost/login")) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mvc + .perform(get("/messages").header(HttpHeaders.ACCEPT, MediaType.TEXT_EVENT_STREAM)) + .andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession(); - this.mvc.perform(formLogin(session)) - .andExpect(redirectedUrl("/")); // ignores text/event-stream + this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/")); // ignores + // text/event-stream - // This is desirable since event-stream requests are typically not invoked directly from the browser and we don't want the browser to replay them + // This is desirable since event-stream requests are typically not invoked + // directly from the browser and we don't want the browser to replay them } @Test public void getWhenBookmarkedRequestIsAllMediaTypeThenPostAuthenticationRemembers() throws Exception { this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire(); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(get("/messages") - .header(HttpHeaders.ACCEPT, MediaType.ALL)) - .andExpect(redirectedUrl("http://localhost/login")) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mvc + .perform(get("/messages").header(HttpHeaders.ACCEPT, MediaType.ALL)) + .andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession(); - this.mvc.perform(formLogin(session)) - .andExpect(redirectedUrl("http://localhost/messages")); + this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("http://localhost/messages")); } @Test public void getWhenBookmarkedRequestIsTextHtmlThenPostAuthenticationRemembers() throws Exception { this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire(); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(get("/messages") - .header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML)) - .andExpect(redirectedUrl("http://localhost/login")) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mvc + .perform(get("/messages").header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML)) + .andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession(); - this.mvc.perform(formLogin(session)) - .andExpect(redirectedUrl("http://localhost/messages")); + this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("http://localhost/messages")); } @Test public void getWhenBookmarkedRequestIsChromeThenPostAuthenticationRemembers() throws Exception { this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire(); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(get("/messages") - .header(HttpHeaders.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")) - .andExpect(redirectedUrl("http://localhost/login")) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mvc + .perform(get("/messages").header(HttpHeaders.ACCEPT, + "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")) + .andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession(); - this.mvc.perform(formLogin(session)) - .andExpect(redirectedUrl("http://localhost/messages")); + this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("http://localhost/messages")); } @Test public void getWhenBookmarkedRequestIsRequestedWithAndroidThenPostAuthenticationRemembers() throws Exception { this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire(); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(get("/messages") - .header("X-Requested-With", "com.android")) - .andExpect(redirectedUrl("http://localhost/login")) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mvc + .perform(get("/messages").header("X-Requested-With", "com.android")) + .andExpect(redirectedUrl("http://localhost/login")).andReturn().getRequest().getSession(); - this.mvc.perform(formLogin(session)) - .andExpect(redirectedUrl("http://localhost/messages")); + this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("http://localhost/messages")); } @EnableWebSecurity @@ -268,19 +255,18 @@ public class RequestCacheConfigurerTests { .formLogin(); // @formatter:on } + } // gh-6102 @Test public void getWhenRequestCacheIsDisabledThenExceptionTranslationFilterDoesNotStoreRequest() throws Exception { - this.spring.register(RequestCacheDisabledConfig.class, ExceptionHandlingConfigurerTests.DefaultSecurityConfig.class).autowire(); + this.spring.register(RequestCacheDisabledConfig.class, + ExceptionHandlingConfigurerTests.DefaultSecurityConfig.class).autowire(); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(get("/bob")) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession(); - this.mvc.perform(formLogin(session)) - .andExpect(redirectedUrl("/")); + this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/")); } // SEC-7060 @@ -290,37 +276,36 @@ public class RequestCacheConfigurerTests { MockMultipartFile aFile = new MockMultipartFile("aFile", "A_FILE".getBytes()); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(multipart("/upload") - .file(aFile)) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mvc.perform(multipart("/upload").file(aFile)).andReturn() + .getRequest().getSession(); this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/")); } @EnableWebSecurity static class RequestCacheDisabledConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); http.requestCache().disable(); } + } @Test - public void getWhenRequestCacheIsDisabledInLambdaThenExceptionTranslationFilterDoesNotStoreRequest() throws Exception { + public void getWhenRequestCacheIsDisabledInLambdaThenExceptionTranslationFilterDoesNotStoreRequest() + throws Exception { this.spring.register(RequestCacheDisabledInLambdaConfig.class, DefaultSecurityConfig.class).autowire(); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(get("/bob")) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession(); - this.mvc.perform(formLogin(session)) - .andExpect(redirectedUrl("/")); + this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/")); } @EnableWebSecurity static class RequestCacheDisabledInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -333,22 +318,21 @@ public class RequestCacheConfigurerTests { .requestCache(RequestCacheConfigurer::disable); // @formatter:on } + } @Test public void getWhenRequestCacheInLambdaThenRedirectedToCachedPage() throws Exception { this.spring.register(RequestCacheInLambdaConfig.class, DefaultSecurityConfig.class).autowire(); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(get("/bob")) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession(); - this.mvc.perform(formLogin(session)) - .andExpect(redirectedUrl("http://localhost/bob")); + this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("http://localhost/bob")); } @EnableWebSecurity static class RequestCacheInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -361,22 +345,21 @@ public class RequestCacheConfigurerTests { .requestCache(withDefaults()); // @formatter:on } + } @Test public void getWhenCustomRequestCacheInLambdaThenCustomRequestCacheUsed() throws Exception { this.spring.register(CustomRequestCacheInLambdaConfig.class, DefaultSecurityConfig.class).autowire(); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(get("/bob")) - .andReturn().getRequest().getSession(); + MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession(); - this.mvc.perform(formLogin(session)) - .andExpect(redirectedUrl("/")); + this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/")); } @EnableWebSecurity static class CustomRequestCacheInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -392,6 +375,7 @@ public class RequestCacheConfigurerTests { ); // @formatter:on } + } @EnableWebSecurity @@ -408,13 +392,11 @@ public class RequestCacheConfigurerTests { ); // @formatter:on } + } private static RequestBuilder formLogin(MockHttpSession session) { - return post("/login") - .param("username", "user") - .param("password", "password") - .session(session) - .with(csrf()); + return post("/login").param("username", "user").param("password", "password").session(session).with(csrf()); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java index 4bc131761b..9ebf93e7bc 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java @@ -47,10 +47,8 @@ public class RequestMatcherConfigurerTests { public void authorizeRequestsWhenInvokedMultipleTimesThenChainsPaths() throws Exception { this.spring.register(Sec2908Config.class).autowire(); - this.mvc.perform(get("/oauth/abc")) - .andExpect(status().isForbidden()); - this.mvc.perform(get("/api/abc")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/oauth/abc")).andExpect(status().isForbidden()); + this.mvc.perform(get("/api/abc")).andExpect(status().isForbidden()); } @EnableWebSecurity @@ -70,16 +68,15 @@ public class RequestMatcherConfigurerTests { .anyRequest().denyAll(); // @formatter:on } + } @Test public void authorizeRequestsWhenInvokedMultipleTimesInLambdaThenChainsPaths() throws Exception { this.spring.register(AuthorizeRequestInLambdaConfig.class).autowire(); - this.mvc.perform(get("/oauth/abc")) - .andExpect(status().isForbidden()); - this.mvc.perform(get("/api/abc")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/oauth/abc")).andExpect(status().isForbidden()); + this.mvc.perform(get("/api/abc")).andExpect(status().isForbidden()); } @EnableWebSecurity @@ -103,5 +100,7 @@ public class RequestMatcherConfigurerTests { ); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.java index 6d2b21c65e..1c40d63e70 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.java @@ -52,6 +52,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder * @author Eleftheria Stein */ public class SecurityContextConfigurerTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -62,12 +63,12 @@ public class SecurityContextConfigurerTests { public void configureWhenRegisteringObjectPostProcessorThenInvokedOnSecurityContextPersistenceFilter() { this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(SecurityContextPersistenceFilter.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(SecurityContextPersistenceFilter.class)); } @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class); @Override @@ -82,13 +83,16 @@ public class SecurityContextConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } @Test @@ -98,12 +102,12 @@ public class SecurityContextConfigurerTests { this.mvc.perform(get("/")); - verify(DuplicateDoesNotOverrideConfig.SCR) - .loadContext(any(HttpRequestResponseHolder.class)); + verify(DuplicateDoesNotOverrideConfig.SCR).loadContext(any(HttpRequestResponseHolder.class)); } @EnableWebSecurity static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter { + static SecurityContextRepository SCR = mock(SecurityContextRepository.class); @Override @@ -116,9 +120,10 @@ public class SecurityContextConfigurerTests { .securityContext(); // @formatter:on } + } - //SEC-2932 + // SEC-2932 @Test public void securityContextWhenSecurityContextRepositoryNotConfiguredThenDoesNotThrowException() throws Exception { this.spring.register(SecurityContextRepositoryDefaultsSecurityContextRepositoryConfig.class).autowire(); @@ -129,6 +134,7 @@ public class SecurityContextConfigurerTests { @Configuration @EnableWebSecurity static class SecurityContextRepositoryDefaultsSecurityContextRepositoryConfig extends WebSecurityConfigurerAdapter { + SecurityContextRepositoryDefaultsSecurityContextRepositoryConfig() { super(true); } @@ -157,6 +163,7 @@ public class SecurityContextConfigurerTests { .withUser("user").password("password").roles("USER"); // @formatter:on } + } @Test @@ -170,6 +177,7 @@ public class SecurityContextConfigurerTests { @EnableWebSecurity static class SecurityContextWithDefaultsInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -187,6 +195,7 @@ public class SecurityContextConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test @@ -200,6 +209,7 @@ public class SecurityContextConfigurerTests { @EnableWebSecurity static class SecurityContextDisabledInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -217,6 +227,7 @@ public class SecurityContextConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test @@ -230,6 +241,7 @@ public class SecurityContextConfigurerTests { @EnableWebSecurity static class NullSecurityContextRepositoryInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -250,5 +262,7 @@ public class SecurityContextConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.java index 7a9e5b1f94..17ac88b691 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.java @@ -77,6 +77,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Onur Kagan Ozcan */ public class ServletApiConfigurerTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -93,6 +94,7 @@ public class ServletApiConfigurerTests { @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class); @Override @@ -107,13 +109,16 @@ public class ServletApiConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } // SEC-2215 @@ -128,8 +133,7 @@ public class ServletApiConfigurerTests { public void configureWhenUsingDefaultsThenAuthenticationEntryPointIsLogin() throws Exception { this.spring.register(ServletApiConfig.class).autowire(); - this.mvc.perform(formLogin()) - .andExpect(status().isFound()); + this.mvc.perform(formLogin()).andExpect(status().isFound()); } // SEC-2926 @@ -137,13 +141,14 @@ public class ServletApiConfigurerTests { public void configureWhenUsingDefaultsThenRolePrefixIsSet() throws Exception { this.spring.register(ServletApiConfig.class, AdminController.class).autowire(); - this.mvc.perform(get("/admin") - .with(authentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN")))) + this.mvc.perform( + get("/admin").with(authentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN")))) .andExpect(status().isOk()); } @EnableWebSecurity static class ServletApiConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -157,6 +162,7 @@ public class ServletApiConfigurerTests { public AuthenticationManager customAuthenticationManager() throws Exception { return super.authenticationManagerBean(); } + } @Test @@ -165,13 +171,13 @@ public class ServletApiConfigurerTests { this.mvc.perform(get("/")); - verify(CustomEntryPointConfig.ENTRYPOINT) - .commence(any(HttpServletRequest.class), - any(HttpServletResponse.class), any(AuthenticationException.class)); + verify(CustomEntryPointConfig.ENTRYPOINT).commence(any(HttpServletRequest.class), + any(HttpServletResponse.class), any(AuthenticationException.class)); } @EnableWebSecurity static class CustomEntryPointConfig extends WebSecurityConfigurerAdapter { + static AuthenticationEntryPoint ENTRYPOINT = spy(AuthenticationEntryPoint.class); @Override @@ -196,23 +202,24 @@ public class ServletApiConfigurerTests { .withUser("user").password("password").roles("USER"); // @formatter:on } + } @Test public void servletApiWhenInvokedTwiceThenUsesOriginalRole() throws Exception { this.spring.register(DuplicateInvocationsDoesNotOverrideConfig.class, AdminController.class).autowire(); - this.mvc.perform(get("/admin") - .with(user("user").authorities(AuthorityUtils.createAuthorityList("PERMISSION_ADMIN")))) + this.mvc.perform( + get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("PERMISSION_ADMIN")))) .andExpect(status().isOk()); - this.mvc.perform(get("/admin") - .with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN")))) + this.mvc.perform(get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN")))) .andExpect(status().isForbidden()); } @EnableWebSecurity static class DuplicateInvocationsDoesNotOverrideConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -223,6 +230,7 @@ public class ServletApiConfigurerTests { .servletApi(); // @formatter:on } + } @Test @@ -236,6 +244,7 @@ public class ServletApiConfigurerTests { @EnableWebSecurity static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter { + static AuthenticationTrustResolver TR = spy(AuthenticationTrustResolver.class); @Override @@ -245,19 +254,20 @@ public class ServletApiConfigurerTests { .setSharedObject(AuthenticationTrustResolver.class, TR); // @formatter:on } + } @Test public void requestWhenServletApiWithDefaultsInLambdaThenUsesDefaultRolePrefix() throws Exception { this.spring.register(ServletApiWithDefaultsInLambdaConfig.class, AdminController.class).autowire(); - this.mvc.perform(get("/admin") - .with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN")))) + this.mvc.perform(get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN")))) .andExpect(status().isOk()); } @EnableWebSecurity static class ServletApiWithDefaultsInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -265,23 +275,24 @@ public class ServletApiConfigurerTests { .servletApi(withDefaults()); // @formatter:on } + } @Test public void requestWhenRolePrefixInLambdaThenUsesCustomRolePrefix() throws Exception { this.spring.register(RolePrefixInLambdaConfig.class, AdminController.class).autowire(); - this.mvc.perform(get("/admin") - .with(user("user").authorities(AuthorityUtils.createAuthorityList("PERMISSION_ADMIN")))) + this.mvc.perform( + get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("PERMISSION_ADMIN")))) .andExpect(status().isOk()); - this.mvc.perform(get("/admin") - .with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN")))) + this.mvc.perform(get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN")))) .andExpect(status().isForbidden()); } @EnableWebSecurity static class RolePrefixInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -292,16 +303,19 @@ public class ServletApiConfigurerTests { ); // @formatter:on } + } @RestController static class AdminController { + @GetMapping("/admin") public void admin(HttpServletRequest request) { if (!request.isUserInRole("ADMIN")) { throw new AccessDeniedException("This resource is only available to admins"); } } + } @Test @@ -325,6 +339,7 @@ public class ServletApiConfigurerTests { @EnableWebSecurity static class ServletApiWithLogoutConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -333,22 +348,21 @@ public class ServletApiConfigurerTests { .logout(); // @formatter:on } + } @Test public void logoutServletApiWhenCsrfDisabled() throws Exception { ConfigurableWebApplicationContext context = this.spring.register(CsrfDisabledConfig.class).getContext(); - MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context) - .apply(springSecurity()) - .build(); - MvcResult mvcResult = mockMvc.perform(get("/")) - .andReturn(); + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build(); + MvcResult mvcResult = mockMvc.perform(get("/")).andReturn(); assertThat(mvcResult.getRequest().getSession(false)).isNull(); } @Configuration @EnableWebSecurity static class CsrfDisabledConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -359,20 +373,20 @@ public class ServletApiConfigurerTests { @RestController static class LogoutController { + @GetMapping("/") String logout(HttpServletRequest request) throws ServletException { request.getSession().setAttribute("foo", "bar"); request.logout(); return "logout"; } + } + } private T getFilter(Class filterClass) { - return (T) getFilters().stream() - .filter(filterClass::isInstance) - .findFirst() - .orElse(null); + return (T) getFilters().stream().filter(filterClass::isInstance).findFirst().orElse(null); } private List getFilters() { @@ -383,7 +397,8 @@ public class ServletApiConfigurerTests { private T getFieldValue(Object target, String fieldName) { try { return (T) FieldUtils.getFieldValue(target, fieldName); - } catch (Exception e) { + } + catch (Exception e) { throw new RuntimeException(e); } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java index cd8d78f5bf..78ff856f7a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java @@ -46,17 +46,19 @@ import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; /** - * * @author Rob Winch */ @RunWith(PowerMockRunner.class) @PowerMockIgnore({ "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", "javax.xml.parsers.*" }) public class SessionManagementConfigurerServlet31Tests { + @Mock Method method; MockHttpServletRequest request; + MockHttpServletResponse response; + MockFilterChain chain; ConfigurableApplicationContext context; @@ -80,7 +82,7 @@ public class SessionManagementConfigurerServlet31Tests { @Test public void changeSessionIdThenPreserveParameters() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); - String id = request.getSession().getId(); + String id = request.getSession().getId(); request.getSession(); request.setServletPath("/login"); request.setMethod("POST"); @@ -101,8 +103,8 @@ public class SessionManagementConfigurerServlet31Tests { } @EnableWebSecurity - static class SessionManagementDefaultSessionFixationServlet31Config extends - WebSecurityConfigurerAdapter { + static class SessionManagementDefaultSessionFixationServlet31Config extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -121,6 +123,7 @@ public class SessionManagementConfigurerServlet31Tests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } private void loadConfig(Class... classes) { @@ -128,19 +131,17 @@ public class SessionManagementConfigurerServlet31Tests { context.register(classes); context.refresh(); this.context = context; - this.springSecurityFilterChain = this.context.getBean( - "springSecurityFilterChain", Filter.class); + this.springSecurityFilterChain = this.context.getBean("springSecurityFilterChain", Filter.class); } private void login(Authentication auth) { HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository(); - HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder( - request, response); + HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response); repo.loadContext(requestResponseHolder); SecurityContextImpl securityContextImpl = new SecurityContextImpl(); securityContextImpl.setAuthentication(auth); - repo.saveContext(securityContextImpl, requestResponseHolder.getRequest(), - requestResponseHolder.getResponse()); + repo.saveContext(securityContextImpl, requestResponseHolder.getRequest(), requestResponseHolder.getResponse()); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionAuthenticationStrategyTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionAuthenticationStrategyTests.java index eb8f2d0e02..061505129b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionAuthenticationStrategyTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionAuthenticationStrategyTests.java @@ -52,13 +52,15 @@ public class SessionManagementConfigurerSessionAuthenticationStrategyTests { public void requestWhenCustomSessionAuthenticationStrategyProvidedThenCalled() throws Exception { this.spring.register(CustomSessionAuthenticationStrategyConfig.class).autowire(); this.mvc.perform(formLogin().user("user").password("password")); - verify(CustomSessionAuthenticationStrategyConfig.customSessionAuthenticationStrategy) - .onAuthentication(any(Authentication.class), any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(CustomSessionAuthenticationStrategyConfig.customSessionAuthenticationStrategy).onAuthentication( + any(Authentication.class), any(HttpServletRequest.class), any(HttpServletResponse.class)); } @EnableWebSecurity static class CustomSessionAuthenticationStrategyConfig extends WebSecurityConfigurerAdapter { - static SessionAuthenticationStrategy customSessionAuthenticationStrategy = mock(SessionAuthenticationStrategy.class); + + static SessionAuthenticationStrategy customSessionAuthenticationStrategy = mock( + SessionAuthenticationStrategy.class); @Override public void configure(HttpSecurity http) throws Exception { @@ -79,5 +81,7 @@ public class SessionManagementConfigurerSessionAuthenticationStrategyTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java index c3412a840a..6cf6576b1b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java @@ -38,6 +38,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Josh Cummings */ public class SessionManagementConfigurerSessionCreationPolicyTests { + @Autowired MockMvc mvc; @@ -45,8 +46,7 @@ public class SessionManagementConfigurerSessionCreationPolicyTests { public final SpringTestRule spring = new SpringTestRule(); @Test - public void getWhenSharedObjectSessionCreationPolicyConfigurationThenOverrides() - throws Exception { + public void getWhenSharedObjectSessionCreationPolicyConfigurationThenOverrides() throws Exception { this.spring.register(StatelessCreateSessionSharedObjectConfig.class).autowire(); @@ -57,16 +57,17 @@ public class SessionManagementConfigurerSessionCreationPolicyTests { @EnableWebSecurity static class StatelessCreateSessionSharedObjectConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); http.setSharedObject(SessionCreationPolicy.class, SessionCreationPolicy.STATELESS); } + } @Test - public void getWhenUserSessionCreationPolicyConfigurationThenOverrides() - throws Exception { + public void getWhenUserSessionCreationPolicyConfigurationThenOverrides() throws Exception { this.spring.register(StatelessCreateSessionUserConfig.class).autowire(); @@ -77,6 +78,7 @@ public class SessionManagementConfigurerSessionCreationPolicyTests { @EnableWebSecurity static class StatelessCreateSessionUserConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); @@ -87,31 +89,32 @@ public class SessionManagementConfigurerSessionCreationPolicyTests { http.setSharedObject(SessionCreationPolicy.class, SessionCreationPolicy.ALWAYS); } + } @Test - public void getWhenDefaultsThenLoginChallengeCreatesSession() - throws Exception { + public void getWhenDefaultsThenLoginChallengeCreatesSession() throws Exception { this.spring.register(DefaultConfig.class, BasicController.class).autowire(); - MvcResult result = - this.mvc.perform(get("/")) - .andExpect(status().isUnauthorized()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/")).andExpect(status().isUnauthorized()).andReturn(); assertThat(result.getRequest().getSession(false)).isNotNull(); } @EnableWebSecurity static class DefaultConfig extends WebSecurityConfigurerAdapter { + } @RestController static class BasicController { + @GetMapping("/") public String root() { return "ok"; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.java index b1104f58d3..f7521d3d5f 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.java @@ -85,12 +85,13 @@ public class SessionManagementConfigurerTests { this.mvc.perform(get("/")); - verify(SessionManagementRequestCacheConfig.REQUEST_CACHE) - .getMatchingRequest(any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(SessionManagementRequestCacheConfig.REQUEST_CACHE).getMatchingRequest(any(HttpServletRequest.class), + any(HttpServletResponse.class)); } @EnableWebSecurity static class SessionManagementRequestCacheConfig extends WebSecurityConfigurerAdapter { + static RequestCache REQUEST_CACHE; @Override @@ -104,25 +105,25 @@ public class SessionManagementConfigurerTests { .sessionCreationPolicy(SessionCreationPolicy.STATELESS); // @formatter:on } + } @Test public void sessionManagementWhenConfiguredThenDoesNotOverrideSecurityContextRepository() throws Exception { SessionManagementSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO = mock(SecurityContextRepository.class); - when(SessionManagementSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO.loadContext(any(HttpRequestResponseHolder.class))) - .thenReturn(mock(SecurityContext.class)); + when(SessionManagementSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO + .loadContext(any(HttpRequestResponseHolder.class))).thenReturn(mock(SecurityContext.class)); this.spring.register(SessionManagementSecurityContextRepositoryConfig.class).autowire(); this.mvc.perform(get("/")); - verify(SessionManagementSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO).saveContext( - any(SecurityContext.class), - any(HttpServletRequest.class), - any(HttpServletResponse.class)); + verify(SessionManagementSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO) + .saveContext(any(SecurityContext.class), any(HttpServletRequest.class), any(HttpServletResponse.class)); } @EnableWebSecurity static class SessionManagementSecurityContextRepositoryConfig extends WebSecurityConfigurerAdapter { + static SecurityContextRepository SECURITY_CONTEXT_REPO; @Override @@ -136,14 +137,14 @@ public class SessionManagementConfigurerTests { .sessionCreationPolicy(SessionCreationPolicy.STATELESS); // @formatter:on } + } @Test public void sessionManagementWhenInvokedTwiceThenUsesOriginalSessionCreationPolicy() throws Exception { this.spring.register(InvokeTwiceDoesNotOverride.class).autowire(); - MvcResult mvcResult = this.mvc.perform(get("/")) - .andReturn(); + MvcResult mvcResult = this.mvc.perform(get("/")).andReturn(); HttpSession session = mvcResult.getRequest().getSession(false); assertThat(session).isNull(); @@ -151,6 +152,7 @@ public class SessionManagementConfigurerTests { @EnableWebSecurity static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -161,6 +163,7 @@ public class SessionManagementConfigurerTests { .sessionManagement(); // @formatter:on } + } // SEC-2137 @@ -171,17 +174,15 @@ public class SessionManagementConfigurerTests { MockHttpSession session = new MockHttpSession(); String sessionId = session.getId(); - MvcResult mvcResult = this.mvc.perform(get("/") - .with(httpBasic("user", "password")) - .session(session)) - .andExpect(status().isNotFound()) - .andReturn(); + MvcResult mvcResult = this.mvc.perform(get("/").with(httpBasic("user", "password")).session(session)) + .andExpect(status().isNotFound()).andReturn(); assertThat(mvcResult.getRequest().getSession().getId()).isEqualTo(sessionId); } @EnableWebSecurity static class DisableSessionFixationEnableConcurrencyControlConfig extends WebSecurityConfigurerAdapter { + @Override public void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -202,6 +203,7 @@ public class SessionManagementConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test @@ -212,12 +214,9 @@ public class SessionManagementConfigurerTests { String givenSessionId = givenSession.getId(); givenSession.setAttribute("name", "value"); - MockHttpSession resultingSession = (MockHttpSession) - this.mvc.perform(get("/auth") - .session(givenSession) - .with(httpBasic("user", "password"))) - .andExpect(status().isNotFound()) - .andReturn().getRequest().getSession(false); + MockHttpSession resultingSession = (MockHttpSession) this.mvc + .perform(get("/auth").session(givenSession).with(httpBasic("user", "password"))) + .andExpect(status().isNotFound()).andReturn().getRequest().getSession(false); assertThat(givenSessionId).isNotEqualTo(resultingSession.getId()); assertThat(resultingSession.getAttribute("name")).isNull(); @@ -225,6 +224,7 @@ public class SessionManagementConfigurerTests { @EnableWebSecurity static class SFPNewSessionInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -247,47 +247,36 @@ public class SessionManagementConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test public void loginWhenUserLoggedInAndMaxSessionsIsOneThenLoginPrevented() throws Exception { this.spring.register(ConcurrencyControlConfig.class).autowire(); - this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password")); + this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")); - this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/login?error")); + this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")) + .andExpect(status().isFound()).andExpect(redirectedUrl("/login?error")); } @Test public void loginWhenUserSessionExpiredAndMaxSessionsIsOneThenLoggedIn() throws Exception { this.spring.register(ConcurrencyControlConfig.class).autowire(); - MvcResult mvcResult = this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password")) + MvcResult mvcResult = this.mvc + .perform(post("/login").with(csrf()).param("username", "user").param("password", "password")) .andReturn(); HttpSession authenticatedSession = mvcResult.getRequest().getSession(); this.spring.getContext().publishEvent(new HttpSessionDestroyedEvent(authenticatedSession)); - this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/")); + this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")) + .andExpect(status().isFound()).andExpect(redirectedUrl("/")); } @EnableWebSecurity static class ConcurrencyControlConfig extends WebSecurityConfigurerAdapter { + @Override public void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -308,27 +297,22 @@ public class SessionManagementConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test public void loginWhenUserLoggedInAndMaxSessionsOneInLambdaThenLoginPrevented() throws Exception { this.spring.register(ConcurrencyControlInLambdaConfig.class).autowire(); - this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password")); + this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")); - this.mvc.perform(post("/login") - .with(csrf()) - .param("username", "user") - .param("password", "password")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/login?error")); + this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")) + .andExpect(status().isFound()).andExpect(redirectedUrl("/login?error")); } @EnableWebSecurity static class ConcurrencyControlInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override public void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -353,14 +337,14 @@ public class SessionManagementConfigurerTests { .withUser(PasswordEncodedUser.user()); // @formatter:on } + } @Test public void requestWhenSessionCreationPolicyStateLessInLambdaThenNoSessionCreated() throws Exception { this.spring.register(SessionCreationPolicyStateLessInLambdaConfig.class).autowire(); - MvcResult mvcResult = this.mvc.perform(get("/")) - .andReturn(); + MvcResult mvcResult = this.mvc.perform(get("/")).andReturn(); HttpSession session = mvcResult.getRequest().getSession(false); assertThat(session).isNull(); @@ -368,6 +352,7 @@ public class SessionManagementConfigurerTests { @EnableWebSecurity static class SessionCreationPolicyStateLessInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -378,6 +363,7 @@ public class SessionManagementConfigurerTests { ); // @formatter:on } + } @Test @@ -385,8 +371,7 @@ public class SessionManagementConfigurerTests { ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class); this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(SessionManagementFilter.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(SessionManagementFilter.class)); } @Test @@ -394,8 +379,7 @@ public class SessionManagementConfigurerTests { ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class); this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(ConcurrentSessionFilter.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(ConcurrentSessionFilter.class)); } @Test @@ -436,6 +420,7 @@ public class SessionManagementConfigurerTests { @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor; @Override @@ -451,13 +436,16 @@ public class SessionManagementConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } @Test @@ -467,14 +455,14 @@ public class SessionManagementConfigurerTests { when(SharedTrustResolverConfig.TR.isAnonymous(any())).thenReturn(false); this.spring.register(SharedTrustResolverConfig.class).autowire(); - MvcResult mvcResult = this.mvc.perform(get("/")) - .andReturn(); + MvcResult mvcResult = this.mvc.perform(get("/")).andReturn(); assertThat(mvcResult.getRequest().getSession(false)).isNotNull(); } @EnableWebSecurity static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter { + static AuthenticationTrustResolver TR; @Override @@ -484,6 +472,7 @@ public class SessionManagementConfigurerTests { .setSharedObject(AuthenticationTrustResolver.class, TR); // @formatter:on } + } @Test @@ -494,8 +483,7 @@ public class SessionManagementConfigurerTests { MockHttpSession session = new MockHttpSession(this.spring.getContext().getServletContext()); this.mvc.perform(get("/").session(session)); - verify(SessionRegistryOneBeanConfig.SESSION_REGISTRY) - .getSessionInformation(session.getId()); + verify(SessionRegistryOneBeanConfig.SESSION_REGISTRY).getSessionInformation(session.getId()); } @Test @@ -513,6 +501,7 @@ public class SessionManagementConfigurerTests { @EnableWebSecurity static class SessionRegistryOneBeanConfig extends WebSecurityConfigurerAdapter { + private static SessionRegistry SESSION_REGISTRY; @Override @@ -528,10 +517,12 @@ public class SessionManagementConfigurerTests { public SessionRegistry sessionRegistry() { return SESSION_REGISTRY; } + } @EnableWebSecurity static class SessionRegistryTwoBeansConfig extends WebSecurityConfigurerAdapter { + private static SessionRegistry SESSION_REGISTRY_ONE; private static SessionRegistry SESSION_REGISTRY_TWO; @@ -554,5 +545,7 @@ public class SessionManagementConfigurerTests { public SessionRegistry sessionRegistryTwo() { return SESSION_REGISTRY_TWO; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTransientAuthenticationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTransientAuthenticationTests.java index b8f99f009c..4eb2626430 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTransientAuthenticationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTransientAuthenticationTests.java @@ -48,8 +48,7 @@ public class SessionManagementConfigurerTransientAuthenticationTests { public final SpringTestRule spring = new SpringTestRule(); @Test - public void postWhenTransientAuthenticationThenNoSessionCreated() - throws Exception { + public void postWhenTransientAuthenticationThenNoSessionCreated() throws Exception { this.spring.register(WithTransientAuthenticationConfig.class).autowire(); MvcResult result = this.mvc.perform(post("/login")).andReturn(); @@ -57,8 +56,7 @@ public class SessionManagementConfigurerTransientAuthenticationTests { } @Test - public void postWhenTransientAuthenticationThenAlwaysSessionOverrides() - throws Exception { + public void postWhenTransientAuthenticationThenAlwaysSessionOverrides() throws Exception { this.spring.register(AlwaysCreateSessionConfig.class).autowire(); MvcResult result = this.mvc.perform(post("/login")).andReturn(); @@ -67,6 +65,7 @@ public class SessionManagementConfigurerTransientAuthenticationTests { @EnableWebSecurity static class WithTransientAuthenticationConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); @@ -83,10 +82,12 @@ public class SessionManagementConfigurerTransientAuthenticationTests { .authenticationProvider(new TransientAuthenticationProvider()); // @formatter:on } + } @EnableWebSecurity static class AlwaysCreateSessionConfig extends WithTransientAuthenticationConfig { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -94,6 +95,7 @@ public class SessionManagementConfigurerTransientAuthenticationTests { .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS); // @formatter:on } + } static class TransientAuthenticationProvider implements AuthenticationProvider { @@ -107,10 +109,12 @@ public class SessionManagementConfigurerTransientAuthenticationTests { public boolean supports(Class authentication) { return true; } + } @Transient static class SomeTransientAuthentication extends AbstractAuthenticationToken { + SomeTransientAuthentication() { super(null); } @@ -124,5 +128,7 @@ public class SessionManagementConfigurerTransientAuthenticationTests { public Object getPrincipal() { return null; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java index 9b86829ebc..e0ba32d1aa 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java @@ -47,10 +47,13 @@ import static org.assertj.core.api.Assertions.assertThat; * */ public class UrlAuthorizationConfigurerTests { + AnnotationConfigWebApplicationContext context; MockHttpServletRequest request; + MockHttpServletResponse response; + MockFilterChain chain; @Autowired @@ -78,30 +81,28 @@ public class UrlAuthorizationConfigurerTests { this.request.setRequestURI("/path"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); this.request.setRequestURI("/path.html"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); this.request.setServletPath("/path/"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); } @EnableWebSecurity @Configuration @EnableWebMvc static class MvcMatcherConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -122,11 +123,14 @@ public class UrlAuthorizationConfigurerTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Test @@ -137,8 +141,7 @@ public class UrlAuthorizationConfigurerTests { this.request.setRequestURI("/spring/path"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); @@ -146,8 +149,7 @@ public class UrlAuthorizationConfigurerTests { this.request.setRequestURI("/spring/path.html"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); @@ -155,8 +157,7 @@ public class UrlAuthorizationConfigurerTests { this.request.setRequestURI("/spring/path/"); this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); - assertThat(this.response.getStatus()) - .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); setup(); @@ -179,6 +180,7 @@ public class UrlAuthorizationConfigurerTests { @Configuration @EnableWebMvc static class MvcMatcherServletPathConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -199,11 +201,14 @@ public class UrlAuthorizationConfigurerTests { @RestController static class PathController { + @RequestMapping("/path") public String path() { return "path"; } + } + } @Test @@ -214,6 +219,7 @@ public class UrlAuthorizationConfigurerTests { @EnableWebSecurity @Configuration static class AnonymousUrlAuthorizationConfig extends WebSecurityConfigurerAdapter { + @Override public void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -222,14 +228,17 @@ public class UrlAuthorizationConfigurerTests { .anyRequest().anonymous(); // @formatter:on } + } @Configuration static class LegacyMvcMatchingConfig implements WebMvcConfigurer { + @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseSuffixPatternMatch(true); } + } public void loadConfig(Class... configs) { @@ -240,4 +249,5 @@ public class UrlAuthorizationConfigurerTests { this.context.getAutowireCapableBeanFactory().autowireBean(this); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationsTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationsTests.java index 4d5b6523d8..df1c22b3a5 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationsTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationsTests.java @@ -41,7 +41,6 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * * @author Rob Winch * @author Josh Cummings * @@ -61,12 +60,9 @@ public class UrlAuthorizationsTests { public void hasAnyAuthorityWhenAuthoritySpecifiedThenMatchesAuthority() throws Exception { this.spring.register(RoleConfig.class).autowire(); - this.mvc.perform(get("/role-user-authority")) - .andExpect(status().isNotFound()); - this.mvc.perform(get("/role-user")) - .andExpect(status().isNotFound()); - this.mvc.perform(get("/role-admin-authority")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/role-user-authority")).andExpect(status().isNotFound()); + this.mvc.perform(get("/role-user")).andExpect(status().isNotFound()); + this.mvc.perform(get("/role-admin-authority")).andExpect(status().isForbidden()); } @Test @@ -74,12 +70,9 @@ public class UrlAuthorizationsTests { public void hasAnyAuthorityWhenAuthoritiesSpecifiedThenMatchesAuthority() throws Exception { this.spring.register(RoleConfig.class).autowire(); - this.mvc.perform(get("/role-user-admin-authority")) - .andExpect(status().isNotFound()); - this.mvc.perform(get("/role-user-admin")) - .andExpect(status().isNotFound()); - this.mvc.perform(get("/role-user-authority")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/role-user-admin-authority")).andExpect(status().isNotFound()); + this.mvc.perform(get("/role-user-admin")).andExpect(status().isNotFound()); + this.mvc.perform(get("/role-user-authority")).andExpect(status().isForbidden()); } @Test @@ -87,10 +80,8 @@ public class UrlAuthorizationsTests { public void hasAnyRoleWhenRoleSpecifiedThenMatchesRole() throws Exception { this.spring.register(RoleConfig.class).autowire(); - this.mvc.perform(get("/role-user")) - .andExpect(status().isNotFound()); - this.mvc.perform(get("/role-admin")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/role-user")).andExpect(status().isNotFound()); + this.mvc.perform(get("/role-admin")).andExpect(status().isForbidden()); } @Test @@ -98,10 +89,8 @@ public class UrlAuthorizationsTests { public void hasAnyRoleWhenRolesSpecifiedThenMatchesRole() throws Exception { this.spring.register(RoleConfig.class).autowire(); - this.mvc.perform(get("/role-admin-user")) - .andExpect(status().isNotFound()); - this.mvc.perform(get("/role-user")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/role-admin-user")).andExpect(status().isNotFound()); + this.mvc.perform(get("/role-user")).andExpect(status().isForbidden()); } @Test @@ -109,14 +98,13 @@ public class UrlAuthorizationsTests { public void hasAnyRoleWhenRoleSpecifiedThenDoesNotMatchAuthority() throws Exception { this.spring.register(RoleConfig.class).autowire(); - this.mvc.perform(get("/role-user")) - .andExpect(status().isForbidden()); - this.mvc.perform(get("/role-admin")) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/role-user")).andExpect(status().isForbidden()); + this.mvc.perform(get("/role-admin")).andExpect(status().isForbidden()); } @EnableWebSecurity static class RoleConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -130,6 +118,7 @@ public class UrlAuthorizationsTests { .antMatchers("/role-user-admin").hasAnyRole("USER", "ADMIN"); // @formatter:on } + } @Test @@ -138,8 +127,7 @@ public class UrlAuthorizationsTests { FilterSecurityInterceptor interceptor = getFilter(FilterSecurityInterceptor.class); assertThat(interceptor).isNotNull(); - assertThat(interceptor).extracting("accessDecisionManager") - .isInstanceOf(AffirmativeBased.class); + assertThat(interceptor).extracting("accessDecisionManager").isInstanceOf(AffirmativeBased.class); } private T getFilter(Class filterType) { @@ -159,12 +147,12 @@ public class UrlAuthorizationsTests { @Override protected void configure(HttpSecurity http) throws Exception { ApplicationContext context = getApplicationContext(); - UrlAuthorizationConfigurer.StandardInterceptUrlRegistry registry = - http.apply(new UrlAuthorizationConfigurer(context)).getRegistry(); + UrlAuthorizationConfigurer.StandardInterceptUrlRegistry registry = http + .apply(new UrlAuthorizationConfigurer(context)).getRegistry(); - registry - .antMatchers("/a").hasRole("ADMIN") - .anyRequest().hasRole("USER"); + registry.antMatchers("/a").hasRole("ADMIN").anyRequest().hasRole("USER"); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/X509ConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/X509ConfigurerTests.java index f7c24c0013..ab975fc38b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/X509ConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/X509ConfigurerTests.java @@ -61,12 +61,12 @@ public class X509ConfigurerTests { public void configureWhenRegisteringObjectPostProcessorThenInvokedOnX509AuthenticationFilter() { this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(X509AuthenticationFilter.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(X509AuthenticationFilter.class)); } @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class); @Override @@ -81,13 +81,16 @@ public class X509ConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } @Test @@ -95,13 +98,12 @@ public class X509ConfigurerTests { this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire(); X509Certificate certificate = loadCert("rodatexampledotcom.cer"); - this.mvc.perform(get("/") - .with(x509(certificate))) - .andExpect(authenticated().withUsername("rod")); + this.mvc.perform(get("/").with(x509(certificate))).andExpect(authenticated().withUsername("rod")); } @EnableWebSecurity static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -121,6 +123,7 @@ public class X509ConfigurerTests { .withUser("rod").password("password").roles("USER", "ADMIN"); // @formatter:on } + } @Test @@ -128,13 +131,12 @@ public class X509ConfigurerTests { this.spring.register(DefaultsInLambdaConfig.class).autowire(); X509Certificate certificate = loadCert("rod.cer"); - this.mvc.perform(get("/") - .with(x509(certificate))) - .andExpect(authenticated().withUsername("rod")); + this.mvc.perform(get("/").with(x509(certificate))).andExpect(authenticated().withUsername("rod")); } @EnableWebSecurity static class DefaultsInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -151,6 +153,7 @@ public class X509ConfigurerTests { .withUser("rod").password("password").roles("USER", "ADMIN"); // @formatter:on } + } @Test @@ -158,13 +161,12 @@ public class X509ConfigurerTests { this.spring.register(SubjectPrincipalRegexInLambdaConfig.class).autowire(); X509Certificate certificate = loadCert("rodatexampledotcom.cer"); - this.mvc.perform(get("/") - .with(x509(certificate))) - .andExpect(authenticated().withUsername("rod")); + this.mvc.perform(get("/").with(x509(certificate))).andExpect(authenticated().withUsername("rod")); } @EnableWebSecurity static class SubjectPrincipalRegexInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -184,14 +186,17 @@ public class X509ConfigurerTests { .withUser("rod").password("password").roles("USER", "ADMIN"); // @formatter:on } + } private T loadCert(String location) { try (InputStream is = new ClassPathResource(location).getInputStream()) { CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); return (T) certFactory.generateCertificate(is); - } catch (Exception e) { + } + catch (Exception e) { throw new IllegalArgumentException(e); } } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerTests.java index c2944260aa..02e001c1ae 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerTests.java @@ -78,6 +78,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Parikshit Dutta */ public class OAuth2ClientConfigurerTests { + private static ClientRegistrationRepository clientRegistrationRepository; private static OAuth2AuthorizedClientService authorizedClientService; @@ -100,32 +101,25 @@ public class OAuth2ClientConfigurerTests { @Before public void setup() { - this.registration1 = TestClientRegistrations.clientRegistration() - .registrationId("registration-1") - .clientId("client-1") - .clientSecret("secret") - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri("{baseUrl}/client-1") - .scope("user") - .authorizationUri("https://provider.com/oauth2/authorize") - .tokenUri("https://provider.com/oauth2/token") - .userInfoUri("https://provider.com/oauth2/user") - .userNameAttributeName("id") - .clientName("client-1") - .build(); + this.registration1 = TestClientRegistrations.clientRegistration().registrationId("registration-1") + .clientId("client-1").clientSecret("secret") + .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri("{baseUrl}/client-1") + .scope("user").authorizationUri("https://provider.com/oauth2/authorize") + .tokenUri("https://provider.com/oauth2/token").userInfoUri("https://provider.com/oauth2/user") + .userNameAttributeName("id").clientName("client-1").build(); clientRegistrationRepository = new InMemoryClientRegistrationRepository(this.registration1); authorizedClientService = new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository); - authorizedClientRepository = new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService); - authorizationRequestResolver = new DefaultOAuth2AuthorizationRequestResolver( - clientRegistrationRepository, "/oauth2/authorization"); + authorizedClientRepository = new AuthenticatedPrincipalOAuth2AuthorizedClientRepository( + authorizedClientService); + authorizationRequestResolver = new DefaultOAuth2AuthorizationRequestResolver(clientRegistrationRepository, + "/oauth2/authorization"); OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("access-token-1234") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(300) - .build(); + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(300).build(); accessTokenResponseClient = mock(OAuth2AccessTokenResponseClient.class); - when(accessTokenResponseClient.getTokenResponse(any(OAuth2AuthorizationCodeGrantRequest.class))).thenReturn(accessTokenResponse); + when(accessTokenResponseClient.getTokenResponse(any(OAuth2AuthorizationCodeGrantRequest.class))) + .thenReturn(accessTokenResponse); requestCache = mock(RequestCache.class); } @@ -134,12 +128,10 @@ public class OAuth2ClientConfigurerTests { this.spring.register(OAuth2ClientConfig.class).autowire(); MvcResult mvcResult = this.mockMvc.perform(get("/oauth2/authorization/registration-1")) - .andExpect(status().is3xxRedirection()) - .andReturn(); - assertThat(mvcResult.getResponse().getRedirectedUrl()).matches("https://provider.com/oauth2/authorize\\?" + - "response_type=code&client_id=client-1&" + - "scope=user&state=.{15,}&" + - "redirect_uri=http://localhost/client-1"); + .andExpect(status().is3xxRedirection()).andReturn(); + assertThat(mvcResult.getResponse().getRedirectedUrl()) + .matches("https://provider.com/oauth2/authorize\\?" + "response_type=code&client_id=client-1&" + + "scope=user&state=.{15,}&" + "redirect_uri=http://localhost/client-1"); } @Test @@ -147,12 +139,10 @@ public class OAuth2ClientConfigurerTests { this.spring.register(OAuth2ClientInLambdaConfig.class).autowire(); MvcResult mvcResult = this.mockMvc.perform(get("/oauth2/authorization/registration-1")) - .andExpect(status().is3xxRedirection()) - .andReturn(); - assertThat(mvcResult.getResponse().getRedirectedUrl()).matches("https://provider.com/oauth2/authorize\\?" + - "response_type=code&client_id=client-1&" + - "scope=user&state=.{15,}&" + - "redirect_uri=http://localhost/client-1"); + .andExpect(status().is3xxRedirection()).andReturn(); + assertThat(mvcResult.getResponse().getRedirectedUrl()) + .matches("https://provider.com/oauth2/authorize\\?" + "response_type=code&client_id=client-1&" + + "scope=user&state=.{15,}&" + "redirect_uri=http://localhost/client-1"); } @Test @@ -164,14 +154,10 @@ public class OAuth2ClientConfigurerTests { attributes.put(OAuth2ParameterNames.REGISTRATION_ID, this.registration1.getRegistrationId()); OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() .authorizationUri(this.registration1.getProviderDetails().getAuthorizationUri()) - .clientId(this.registration1.getClientId()) - .redirectUri("http://localhost/client-1") - .state("state") - .attributes(attributes) - .build(); + .clientId(this.registration1.getClientId()).redirectUri("http://localhost/client-1").state("state") + .attributes(attributes).build(); - AuthorizationRequestRepository authorizationRequestRepository = - new HttpSessionOAuth2AuthorizationRequestRepository(); + AuthorizationRequestRepository authorizationRequestRepository = new HttpSessionOAuth2AuthorizationRequestRepository(); MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); MockHttpServletResponse response = new MockHttpServletResponse(); authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, request, response); @@ -181,30 +167,25 @@ public class OAuth2ClientConfigurerTests { String principalName = "user1"; TestingAuthenticationToken authentication = new TestingAuthenticationToken(principalName, "password"); - this.mockMvc.perform(get("/client-1") - .param(OAuth2ParameterNames.CODE, "code") - .param(OAuth2ParameterNames.STATE, "state") - .with(authentication(authentication)) - .session(session)) - .andExpect(status().is3xxRedirection()) - .andExpect(redirectedUrl("http://localhost/client-1")); + this.mockMvc.perform(get("/client-1").param(OAuth2ParameterNames.CODE, "code") + .param(OAuth2ParameterNames.STATE, "state").with(authentication(authentication)).session(session)) + .andExpect(status().is3xxRedirection()).andExpect(redirectedUrl("http://localhost/client-1")); - OAuth2AuthorizedClient authorizedClient = authorizedClientRepository.loadAuthorizedClient( - this.registration1.getRegistrationId(), authentication, request); + OAuth2AuthorizedClient authorizedClient = authorizedClientRepository + .loadAuthorizedClient(this.registration1.getRegistrationId(), authentication, request); assertThat(authorizedClient).isNotNull(); } @Test - public void configureWhenRequestCacheProvidedAndClientAuthorizationRequiredExceptionThrownThenRequestCacheUsed() throws Exception { + public void configureWhenRequestCacheProvidedAndClientAuthorizationRequiredExceptionThrownThenRequestCacheUsed() + throws Exception { this.spring.register(OAuth2ClientConfig.class).autowire(); MvcResult mvcResult = this.mockMvc.perform(get("/resource1").with(user("user1"))) - .andExpect(status().is3xxRedirection()) - .andReturn(); - assertThat(mvcResult.getResponse().getRedirectedUrl()).matches("https://provider.com/oauth2/authorize\\?" + - "response_type=code&client_id=client-1&" + - "scope=user&state=.{15,}&" + - "redirect_uri=http://localhost/client-1"); + .andExpect(status().is3xxRedirection()).andReturn(); + assertThat(mvcResult.getResponse().getRedirectedUrl()) + .matches("https://provider.com/oauth2/authorize\\?" + "response_type=code&client_id=client-1&" + + "scope=user&state=.{15,}&" + "redirect_uri=http://localhost/client-1"); verify(requestCache).saveRequest(any(HttpServletRequest.class), any(HttpServletResponse.class)); } @@ -218,14 +199,10 @@ public class OAuth2ClientConfigurerTests { attributes.put(OAuth2ParameterNames.REGISTRATION_ID, this.registration1.getRegistrationId()); OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() .authorizationUri(this.registration1.getProviderDetails().getAuthorizationUri()) - .clientId(this.registration1.getClientId()) - .redirectUri("http://localhost/client-1") - .state("state") - .attributes(attributes) - .build(); + .clientId(this.registration1.getClientId()).redirectUri("http://localhost/client-1").state("state") + .attributes(attributes).build(); - AuthorizationRequestRepository authorizationRequestRepository = - new HttpSessionOAuth2AuthorizationRequestRepository(); + AuthorizationRequestRepository authorizationRequestRepository = new HttpSessionOAuth2AuthorizationRequestRepository(); MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); MockHttpServletResponse response = new MockHttpServletResponse(); authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, request, response); @@ -235,29 +212,26 @@ public class OAuth2ClientConfigurerTests { String principalName = "user1"; TestingAuthenticationToken authentication = new TestingAuthenticationToken(principalName, "password"); - this.mockMvc.perform(get("/client-1") - .param(OAuth2ParameterNames.CODE, "code") - .param(OAuth2ParameterNames.STATE, "state") - .with(authentication(authentication)) - .session(session)) - .andExpect(status().is3xxRedirection()) - .andExpect(redirectedUrl("http://localhost/client-1")); + this.mockMvc.perform(get("/client-1").param(OAuth2ParameterNames.CODE, "code") + .param(OAuth2ParameterNames.STATE, "state").with(authentication(authentication)).session(session)) + .andExpect(status().is3xxRedirection()).andExpect(redirectedUrl("http://localhost/client-1")); verify(requestCache).getRequest(any(HttpServletRequest.class), any(HttpServletResponse.class)); } // gh-5521 @Test - public void configureWhenCustomAuthorizationRequestResolverSetThenAuthorizationRequestIncludesCustomParameters() throws Exception { + public void configureWhenCustomAuthorizationRequestResolverSetThenAuthorizationRequestIncludesCustomParameters() + throws Exception { // Override default resolver OAuth2AuthorizationRequestResolver defaultAuthorizationRequestResolver = authorizationRequestResolver; authorizationRequestResolver = mock(OAuth2AuthorizationRequestResolver.class); - when(authorizationRequestResolver.resolve(any())).thenAnswer(invocation -> defaultAuthorizationRequestResolver.resolve(invocation.getArgument(0))); + when(authorizationRequestResolver.resolve(any())) + .thenAnswer(invocation -> defaultAuthorizationRequestResolver.resolve(invocation.getArgument(0))); this.spring.register(OAuth2ClientConfig.class).autowire(); - this.mockMvc.perform(get("/oauth2/authorization/registration-1")) - .andExpect(status().is3xxRedirection()) + this.mockMvc.perform(get("/oauth2/authorization/registration-1")).andExpect(status().is3xxRedirection()) .andReturn(); verify(authorizationRequestResolver).resolve(any()); @@ -266,6 +240,7 @@ public class OAuth2ClientConfigurerTests { @EnableWebSecurity @EnableWebMvc static class OAuth2ClientConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -295,16 +270,21 @@ public class OAuth2ClientConfigurerTests { @RestController public class ResourceController { + @GetMapping("/resource1") - public String resource1(@RegisteredOAuth2AuthorizedClient("registration-1") OAuth2AuthorizedClient authorizedClient) { + public String resource1( + @RegisteredOAuth2AuthorizedClient("registration-1") OAuth2AuthorizedClient authorizedClient) { return "resource1"; } + } + } @EnableWebSecurity @EnableWebMvc static class OAuth2ClientInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -326,5 +306,7 @@ public class OAuth2ClientConfigurerTests { public OAuth2AuthorizedClientRepository authorizedClientRepository() { return authorizedClientRepository; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java index 7daea6e6c6..130fa378bb 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java @@ -109,12 +109,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. public class OAuth2LoginConfigurerTests { private static final ClientRegistration GOOGLE_CLIENT_REGISTRATION = CommonOAuth2Provider.GOOGLE - .getBuilder("google").clientId("clientId").clientSecret("clientSecret") - .build(); + .getBuilder("google").clientId("clientId").clientSecret("clientSecret").build(); private static final ClientRegistration GITHUB_CLIENT_REGISTRATION = CommonOAuth2Provider.GITHUB - .getBuilder("github").clientId("clientId").clientSecret("clientSecret") - .build(); + .getBuilder("github").clientId("clientId").clientSecret("clientSecret").build(); private ConfigurableApplicationContext context; @@ -134,7 +132,9 @@ public class OAuth2LoginConfigurerTests { MockMvc mvc; private MockHttpServletRequest request; + private MockHttpServletResponse response; + private MockFilterChain filterChain; @Before @@ -159,8 +159,7 @@ public class OAuth2LoginConfigurerTests { // setup authorization request OAuth2AuthorizationRequest authorizationRequest = createOAuth2AuthorizationRequest(); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, this.request, this.response); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, this.request, this.response); // setup authentication parameters this.request.setParameter("code", "code123"); @@ -171,30 +170,27 @@ public class OAuth2LoginConfigurerTests { // assertions Authentication authentication = this.securityContextRepository - .loadContext(new HttpRequestResponseHolder(this.request, this.response)) - .getAuthentication(); + .loadContext(new HttpRequestResponseHolder(this.request, this.response)).getAuthentication(); assertThat(authentication.getAuthorities()).hasSize(1); - assertThat(authentication.getAuthorities()).first() - .isInstanceOf(OAuth2UserAuthority.class).hasToString("ROLE_USER"); + assertThat(authentication.getAuthorities()).first().isInstanceOf(OAuth2UserAuthority.class) + .hasToString("ROLE_USER"); } @Test public void requestWhenOauth2LoginInLambdaThenAuthenticationContainsOauth2UserAuthority() throws Exception { loadConfig(OAuth2LoginInLambdaConfig.class); OAuth2AuthorizationRequest authorizationRequest = createOAuth2AuthorizationRequest(); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, this.request, this.response); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, this.request, this.response); this.request.setParameter("code", "code123"); this.request.setParameter("state", authorizationRequest.getState()); this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); Authentication authentication = this.securityContextRepository - .loadContext(new HttpRequestResponseHolder(this.request, this.response)) - .getAuthentication(); + .loadContext(new HttpRequestResponseHolder(this.request, this.response)).getAuthentication(); assertThat(authentication.getAuthorities()).hasSize(1); - assertThat(authentication.getAuthorities()).first() - .isInstanceOf(OAuth2UserAuthority.class).hasToString("ROLE_USER"); + assertThat(authentication.getAuthorities()).first().isInstanceOf(OAuth2UserAuthority.class) + .hasToString("ROLE_USER"); } // gh-6009 @@ -205,8 +201,7 @@ public class OAuth2LoginConfigurerTests { // setup authorization request OAuth2AuthorizationRequest authorizationRequest = createOAuth2AuthorizationRequest(); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, this.request, this.response); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, this.request, this.response); // setup authentication parameters this.request.setParameter("code", "code123"); @@ -228,8 +223,7 @@ public class OAuth2LoginConfigurerTests { // setup authorization request OAuth2AuthorizationRequest authorizationRequest = createOAuth2AuthorizationRequest(); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, this.request, this.response); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, this.request, this.response); // setup authentication parameters this.request.setParameter("code", "code123"); @@ -240,8 +234,7 @@ public class OAuth2LoginConfigurerTests { // assertions Authentication authentication = this.securityContextRepository - .loadContext(new HttpRequestResponseHolder(this.request, this.response)) - .getAuthentication(); + .loadContext(new HttpRequestResponseHolder(this.request, this.response)).getAuthentication(); assertThat(authentication.getAuthorities()).hasSize(2); assertThat(authentication.getAuthorities()).first().hasToString("ROLE_USER"); assertThat(authentication.getAuthorities()).last().hasToString("ROLE_OAUTH2_USER"); @@ -254,8 +247,7 @@ public class OAuth2LoginConfigurerTests { // setup authorization request OAuth2AuthorizationRequest authorizationRequest = createOAuth2AuthorizationRequest(); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, this.request, this.response); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, this.request, this.response); // setup authentication parameters this.request.setParameter("code", "code123"); @@ -266,8 +258,7 @@ public class OAuth2LoginConfigurerTests { // assertions Authentication authentication = this.securityContextRepository - .loadContext(new HttpRequestResponseHolder(this.request, this.response)) - .getAuthentication(); + .loadContext(new HttpRequestResponseHolder(this.request, this.response)).getAuthentication(); assertThat(authentication.getAuthorities()).hasSize(2); assertThat(authentication.getAuthorities()).first().hasToString("ROLE_USER"); assertThat(authentication.getAuthorities()).last().hasToString("ROLE_OAUTH2_USER"); @@ -280,8 +271,7 @@ public class OAuth2LoginConfigurerTests { // setup authorization request OAuth2AuthorizationRequest authorizationRequest = createOAuth2AuthorizationRequest(); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, this.request, this.response); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, this.request, this.response); // setup authentication parameters this.request.setParameter("code", "code123"); @@ -292,8 +282,7 @@ public class OAuth2LoginConfigurerTests { // assertions Authentication authentication = this.securityContextRepository - .loadContext(new HttpRequestResponseHolder(this.request, this.response)) - .getAuthentication(); + .loadContext(new HttpRequestResponseHolder(this.request, this.response)).getAuthentication(); assertThat(authentication.getAuthorities()).hasSize(2); assertThat(authentication.getAuthorities()).first().hasToString("ROLE_USER"); assertThat(authentication.getAuthorities()).last().hasToString("ROLE_OAUTH2_USER"); @@ -308,8 +297,7 @@ public class OAuth2LoginConfigurerTests { // setup authorization request OAuth2AuthorizationRequest authorizationRequest = createOAuth2AuthorizationRequest(); this.request.setServletPath("/login/oauth2/google"); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, this.request, this.response); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, this.request, this.response); // setup authentication parameters this.request.setParameter("code", "code123"); @@ -320,24 +308,22 @@ public class OAuth2LoginConfigurerTests { // assertions Authentication authentication = this.securityContextRepository - .loadContext(new HttpRequestResponseHolder(this.request, this.response)) - .getAuthentication(); + .loadContext(new HttpRequestResponseHolder(this.request, this.response)).getAuthentication(); assertThat(authentication.getAuthorities()).hasSize(1); - assertThat(authentication.getAuthorities()).first() - .isInstanceOf(OAuth2UserAuthority.class).hasToString("ROLE_USER"); + assertThat(authentication.getAuthorities()).first().isInstanceOf(OAuth2UserAuthority.class) + .hasToString("ROLE_USER"); } // gh-5521 @Test public void oauth2LoginWithCustomAuthorizationRequestParameters() throws Exception { loadConfig(OAuth2LoginConfigCustomAuthorizationRequestResolver.class); - OAuth2AuthorizationRequestResolver resolver = this.context.getBean( - OAuth2LoginConfigCustomAuthorizationRequestResolver.class).resolver; + OAuth2AuthorizationRequestResolver resolver = this.context + .getBean(OAuth2LoginConfigCustomAuthorizationRequestResolver.class).resolver; OAuth2AuthorizationRequest result = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri("https://accounts.google.com/authorize") - .clientId("client-id") - .state("adsfa") - .authorizationRequestUri("https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=clientId&scope=openid+profile+email&state=state&redirect_uri=http%3A%2F%2Flocalhost%2Flogin%2Foauth2%2Fcode%2Fgoogle&custom-param1=custom-value1") + .authorizationUri("https://accounts.google.com/authorize").clientId("client-id").state("adsfa") + .authorizationRequestUri( + "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=clientId&scope=openid+profile+email&state=state&redirect_uri=http%3A%2F%2Flocalhost%2Flogin%2Foauth2%2Fcode%2Fgoogle&custom-param1=custom-value1") .build(); when(resolver.resolve(any())).thenReturn(result); @@ -347,20 +333,20 @@ public class OAuth2LoginConfigurerTests { this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); - assertThat(this.response.getRedirectedUrl()).isEqualTo("https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=clientId&scope=openid+profile+email&state=state&redirect_uri=http%3A%2F%2Flocalhost%2Flogin%2Foauth2%2Fcode%2Fgoogle&custom-param1=custom-value1"); + assertThat(this.response.getRedirectedUrl()).isEqualTo( + "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=clientId&scope=openid+profile+email&state=state&redirect_uri=http%3A%2F%2Flocalhost%2Flogin%2Foauth2%2Fcode%2Fgoogle&custom-param1=custom-value1"); } @Test public void requestWhenOauth2LoginWithCustomAuthorizationRequestParametersThenParametersInRedirectedUrl() throws Exception { loadConfig(OAuth2LoginConfigCustomAuthorizationRequestResolverInLambda.class); - OAuth2AuthorizationRequestResolver resolver = this.context.getBean( - OAuth2LoginConfigCustomAuthorizationRequestResolverInLambda.class).resolver; + OAuth2AuthorizationRequestResolver resolver = this.context + .getBean(OAuth2LoginConfigCustomAuthorizationRequestResolverInLambda.class).resolver; OAuth2AuthorizationRequest result = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri("https://accounts.google.com/authorize") - .clientId("client-id") - .state("adsfa") - .authorizationRequestUri("https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=clientId&scope=openid+profile+email&state=state&redirect_uri=http%3A%2F%2Flocalhost%2Flogin%2Foauth2%2Fcode%2Fgoogle&custom-param1=custom-value1") + .authorizationUri("https://accounts.google.com/authorize").clientId("client-id").state("adsfa") + .authorizationRequestUri( + "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=clientId&scope=openid+profile+email&state=state&redirect_uri=http%3A%2F%2Flocalhost%2Flogin%2Foauth2%2Fcode%2Fgoogle&custom-param1=custom-value1") .build(); when(resolver.resolve(any())).thenReturn(result); @@ -370,7 +356,8 @@ public class OAuth2LoginConfigurerTests { this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); - assertThat(this.response.getRedirectedUrl()).isEqualTo("https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=clientId&scope=openid+profile+email&state=state&redirect_uri=http%3A%2F%2Flocalhost%2Flogin%2Foauth2%2Fcode%2Fgoogle&custom-param1=custom-value1"); + assertThat(this.response.getRedirectedUrl()).isEqualTo( + "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=clientId&scope=openid+profile+email&state=state&redirect_uri=http%3A%2F%2Flocalhost%2Flogin%2Foauth2%2Fcode%2Fgoogle&custom-param1=custom-value1"); } // gh-5347 @@ -389,7 +376,8 @@ public class OAuth2LoginConfigurerTests { // gh-5347 @Test - public void oauth2LoginWithOneClientConfiguredAndRequestFaviconNotAuthenticatedThenRedirectDefaultLoginPage() throws Exception { + public void oauth2LoginWithOneClientConfiguredAndRequestFaviconNotAuthenticatedThenRedirectDefaultLoginPage() + throws Exception { loadConfig(OAuth2LoginConfig.class); String requestUri = "/favicon.ico"; @@ -418,7 +406,8 @@ public class OAuth2LoginConfigurerTests { // gh-6812 @Test - public void oauth2LoginWithOneClientConfiguredAndRequestXHRNotAuthenticatedThenDoesNotRedirectForAuthorization() throws Exception { + public void oauth2LoginWithOneClientConfiguredAndRequestXHRNotAuthenticatedThenDoesNotRedirectForAuthorization() + throws Exception { loadConfig(OAuth2LoginConfig.class); String requestUri = "/"; @@ -464,8 +453,7 @@ public class OAuth2LoginConfigurerTests { // setup authorization request OAuth2AuthorizationRequest authorizationRequest = createOAuth2AuthorizationRequest("openid"); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, this.request, this.response); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, this.request, this.response); // setup authentication parameters this.request.setParameter("code", "code123"); @@ -476,11 +464,10 @@ public class OAuth2LoginConfigurerTests { // assertions Authentication authentication = this.securityContextRepository - .loadContext(new HttpRequestResponseHolder(this.request, this.response)) - .getAuthentication(); + .loadContext(new HttpRequestResponseHolder(this.request, this.response)).getAuthentication(); assertThat(authentication.getAuthorities()).hasSize(1); - assertThat(authentication.getAuthorities()).first() - .isInstanceOf(OidcUserAuthority.class).hasToString("ROLE_USER"); + assertThat(authentication.getAuthorities()).first().isInstanceOf(OidcUserAuthority.class) + .hasToString("ROLE_USER"); } @Test @@ -490,8 +477,7 @@ public class OAuth2LoginConfigurerTests { // setup authorization request OAuth2AuthorizationRequest authorizationRequest = createOAuth2AuthorizationRequest("openid"); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, this.request, this.response); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, this.request, this.response); // setup authentication parameters this.request.setParameter("code", "code123"); @@ -502,11 +488,10 @@ public class OAuth2LoginConfigurerTests { // assertions Authentication authentication = this.securityContextRepository - .loadContext(new HttpRequestResponseHolder(this.request, this.response)) - .getAuthentication(); + .loadContext(new HttpRequestResponseHolder(this.request, this.response)).getAuthentication(); assertThat(authentication.getAuthorities()).hasSize(1); - assertThat(authentication.getAuthorities()).first() - .isInstanceOf(OidcUserAuthority.class).hasToString("ROLE_USER"); + assertThat(authentication.getAuthorities()).first().isInstanceOf(OidcUserAuthority.class) + .hasToString("ROLE_USER"); } @Test @@ -516,8 +501,7 @@ public class OAuth2LoginConfigurerTests { // setup authorization request OAuth2AuthorizationRequest authorizationRequest = createOAuth2AuthorizationRequest("openid"); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, this.request, this.response); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, this.request, this.response); // setup authentication parameters this.request.setParameter("code", "code123"); @@ -528,8 +512,7 @@ public class OAuth2LoginConfigurerTests { // assertions Authentication authentication = this.securityContextRepository - .loadContext(new HttpRequestResponseHolder(this.request, this.response)) - .getAuthentication(); + .loadContext(new HttpRequestResponseHolder(this.request, this.response)).getAuthentication(); assertThat(authentication.getAuthorities()).hasSize(2); assertThat(authentication.getAuthorities()).first().hasToString("ROLE_USER"); assertThat(authentication.getAuthorities()).last().hasToString("ROLE_OIDC_USER"); @@ -542,8 +525,7 @@ public class OAuth2LoginConfigurerTests { // setup authorization request OAuth2AuthorizationRequest authorizationRequest = createOAuth2AuthorizationRequest("openid"); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, this.request, this.response); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, this.request, this.response); // setup authentication parameters this.request.setParameter("code", "code123"); @@ -554,8 +536,7 @@ public class OAuth2LoginConfigurerTests { // assertions Authentication authentication = this.securityContextRepository - .loadContext(new HttpRequestResponseHolder(this.request, this.response)) - .getAuthentication(); + .loadContext(new HttpRequestResponseHolder(this.request, this.response)).getAuthentication(); assertThat(authentication.getAuthorities()).hasSize(2); assertThat(authentication.getAuthorities()).first().hasToString("ROLE_USER"); assertThat(authentication.getAuthorities()).last().hasToString("ROLE_OIDC_USER"); @@ -565,23 +546,19 @@ public class OAuth2LoginConfigurerTests { public void oidcLoginCustomWithNoUniqueJwtDecoderFactory() { assertThatThrownBy(() -> loadConfig(OAuth2LoginConfig.class, NoUniqueJwtDecoderFactoryConfig.class)) .hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class) - .hasMessageContaining("No qualifying bean of type " + - "'org.springframework.security.oauth2.jwt.JwtDecoderFactory' " + - "available: expected single matching bean but found 2: jwtDecoderFactory1,jwtDecoderFactory2"); + .hasMessageContaining("No qualifying bean of type " + + "'org.springframework.security.oauth2.jwt.JwtDecoderFactory' " + + "available: expected single matching bean but found 2: jwtDecoderFactory1,jwtDecoderFactory2"); } @Test public void logoutWhenUsingOidcLogoutHandlerThenRedirects() throws Exception { this.spring.register(OAuth2LoginConfigWithOidcLogoutSuccessHandler.class).autowire(); - OAuth2AuthenticationToken token = new OAuth2AuthenticationToken( - TestOidcUsers.create(), - AuthorityUtils.NO_AUTHORITIES, - "registration-id"); + OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(), + AuthorityUtils.NO_AUTHORITIES, "registration-id"); - this.mvc.perform(post("/logout") - .with(authentication(token)) - .with(csrf())) + this.mvc.perform(post("/logout").with(authentication(token)).with(csrf())) .andExpect(redirectedUrl("https://logout?id_token_hint=id-token")); } @@ -597,22 +574,20 @@ public class OAuth2LoginConfigurerTests { return this.createOAuth2AuthorizationRequest(GOOGLE_CLIENT_REGISTRATION, scopes); } - private OAuth2AuthorizationRequest createOAuth2AuthorizationRequest(ClientRegistration registration, String... scopes) { + private OAuth2AuthorizationRequest createOAuth2AuthorizationRequest(ClientRegistration registration, + String... scopes) { return OAuth2AuthorizationRequest.authorizationCode() .authorizationUri(registration.getProviderDetails().getAuthorizationUri()) - .clientId(registration.getClientId()) - .state("state123") - .redirectUri("http://localhost") - .attributes( - Collections.singletonMap( - OAuth2ParameterNames.REGISTRATION_ID, - registration.getRegistrationId())) - .scope(scopes) - .build(); + .clientId(registration.getClientId()).state("state123").redirectUri("http://localhost") + .attributes(Collections.singletonMap(OAuth2ParameterNames.REGISTRATION_ID, + registration.getRegistrationId())) + .scope(scopes).build(); } @EnableWebSecurity - static class OAuth2LoginConfig extends CommonWebSecurityConfigurerAdapter implements ApplicationListener { + static class OAuth2LoginConfig extends CommonWebSecurityConfigurerAdapter + implements ApplicationListener { + static List EVENTS = new ArrayList<>(); @Override @@ -630,11 +605,13 @@ public class OAuth2LoginConfigurerTests { public void onApplicationEvent(AuthenticationSuccessEvent event) { EVENTS.add(event); } + } @EnableWebSecurity static class OAuth2LoginInLambdaConfig extends CommonLambdaWebSecurityConfigurerAdapter implements ApplicationListener { + static List EVENTS = new ArrayList<>(); @Override @@ -654,10 +631,12 @@ public class OAuth2LoginConfigurerTests { public void onApplicationEvent(AuthenticationSuccessEvent event) { EVENTS.add(event); } + } @EnableWebSecurity static class OAuth2LoginConfigCustomWithConfigurer extends CommonWebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -670,10 +649,12 @@ public class OAuth2LoginConfigurerTests { // @formatter:on super.configure(http); } + } @EnableWebSecurity static class OAuth2LoginConfigCustomWithBeanRegistration extends CommonWebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -692,10 +673,12 @@ public class OAuth2LoginConfigurerTests { GrantedAuthoritiesMapper grantedAuthoritiesMapper() { return createGrantedAuthoritiesMapper(); } + } @EnableWebSecurity static class OAuth2LoginConfigCustomUserServiceBeanRegistration extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -741,10 +724,12 @@ public class OAuth2LoginConfigurerTests { OAuth2UserService oidcUserService() { return createOidcUserService(); } + } @EnableWebSecurity static class OAuth2LoginConfigLoginProcessingUrl extends CommonWebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -756,12 +741,14 @@ public class OAuth2LoginConfigurerTests { // @formatter:on super.configure(http); } + } @EnableWebSecurity static class OAuth2LoginConfigCustomAuthorizationRequestResolver extends CommonWebSecurityConfigurerAdapter { - private ClientRegistrationRepository clientRegistrationRepository = - new InMemoryClientRegistrationRepository(GOOGLE_CLIENT_REGISTRATION); + + private ClientRegistrationRepository clientRegistrationRepository = new InMemoryClientRegistrationRepository( + GOOGLE_CLIENT_REGISTRATION); OAuth2AuthorizationRequestResolver resolver = mock(OAuth2AuthorizationRequestResolver.class); @@ -776,12 +763,15 @@ public class OAuth2LoginConfigurerTests { // @formatter:on super.configure(http); } + } @EnableWebSecurity - static class OAuth2LoginConfigCustomAuthorizationRequestResolverInLambda extends CommonLambdaWebSecurityConfigurerAdapter { - private ClientRegistrationRepository clientRegistrationRepository = - new InMemoryClientRegistrationRepository(GOOGLE_CLIENT_REGISTRATION); + static class OAuth2LoginConfigCustomAuthorizationRequestResolverInLambda + extends CommonLambdaWebSecurityConfigurerAdapter { + + private ClientRegistrationRepository clientRegistrationRepository = new InMemoryClientRegistrationRepository( + GOOGLE_CLIENT_REGISTRATION); OAuth2AuthorizationRequestResolver resolver = mock(OAuth2AuthorizationRequestResolver.class); @@ -800,10 +790,12 @@ public class OAuth2LoginConfigurerTests { // @formatter:on super.configure(http); } + } @EnableWebSecurity static class OAuth2LoginConfigMultipleClients extends CommonWebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -815,10 +807,12 @@ public class OAuth2LoginConfigurerTests { // @formatter:on super.configure(http); } + } @EnableWebSecurity static class OAuth2LoginConfigCustomLoginPage extends CommonWebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -830,10 +824,12 @@ public class OAuth2LoginConfigurerTests { // @formatter:on super.configure(http); } + } @EnableWebSecurity static class OAuth2LoginConfigCustomLoginPageInLambda extends CommonLambdaWebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -847,10 +843,12 @@ public class OAuth2LoginConfigurerTests { // @formatter:on super.configure(http); } + } @EnableWebSecurity static class OAuth2LoginConfigWithOidcLogoutSuccessHandler extends CommonWebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -868,15 +866,15 @@ public class OAuth2LoginConfigurerTests { @Bean ClientRegistrationRepository clientRegistrationRepository() { - Map providerMetadata = - Collections.singletonMap("end_session_endpoint", "https://logout"); - return new InMemoryClientRegistrationRepository( - TestClientRegistrations.clientRegistration() - .providerConfigurationMetadata(providerMetadata).build()); + Map providerMetadata = Collections.singletonMap("end_session_endpoint", "https://logout"); + return new InMemoryClientRegistrationRepository(TestClientRegistrations.clientRegistration() + .providerConfigurationMetadata(providerMetadata).build()); } + } private static abstract class CommonWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -906,9 +904,11 @@ public class OAuth2LoginConfigurerTests { HttpSessionOAuth2AuthorizationRequestRepository oauth2AuthorizationRequestRepository() { return new HttpSessionOAuth2AuthorizationRequestRepository(); } + } private static abstract class CommonLambdaWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -945,6 +945,7 @@ public class OAuth2LoginConfigurerTests { HttpSessionOAuth2AuthorizationRequestRepository oauth2AuthorizationRequestRepository() { return new HttpSessionOAuth2AuthorizationRequestRepository(); } + } @Configuration @@ -966,6 +967,7 @@ public class OAuth2LoginConfigurerTests { when(jwtDecoder.decode(any())).thenReturn(jwt); return jwtDecoder; } + } @Configuration @@ -989,34 +991,29 @@ public class OAuth2LoginConfigurerTests { if (request.getAuthorizationExchange().getAuthorizationRequest().getScopes().contains("openid")) { additionalParameters.put(OidcParameterNames.ID_TOKEN, "token123"); } - return OAuth2AccessTokenResponse.withToken("accessToken123") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .additionalParameters(additionalParameters) - .build(); + return OAuth2AccessTokenResponse.withToken("accessToken123").tokenType(OAuth2AccessToken.TokenType.BEARER) + .additionalParameters(additionalParameters).build(); }; } private static OAuth2UserService createOauth2UserService() { Map userAttributes = Collections.singletonMap("name", "spring"); - return request -> new DefaultOAuth2User( - Collections.singleton(new OAuth2UserAuthority(userAttributes)), + return request -> new DefaultOAuth2User(Collections.singleton(new OAuth2UserAuthority(userAttributes)), userAttributes, "name"); } private static OAuth2UserService createOidcUserService() { OidcIdToken idToken = idToken().build(); - return request -> new DefaultOidcUser( - Collections.singleton(new OidcUserAuthority(idToken)), idToken); + return request -> new DefaultOidcUser(Collections.singleton(new OidcUserAuthority(idToken)), idToken); } private static GrantedAuthoritiesMapper createGrantedAuthoritiesMapper() { return authorities -> { - boolean isOidc = OidcUserAuthority.class - .isInstance(authorities.iterator().next()); + boolean isOidc = OidcUserAuthority.class.isInstance(authorities.iterator().next()); List mappedAuthorities = new ArrayList<>(authorities); - mappedAuthorities.add(new SimpleGrantedAuthority( - isOidc ? "ROLE_OIDC_USER" : "ROLE_OAUTH2_USER")); + mappedAuthorities.add(new SimpleGrantedAuthority(isOidc ? "ROLE_OIDC_USER" : "ROLE_OAUTH2_USER")); return mappedAuthorities; }; } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java index a830d226c1..8c345e5c35 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java @@ -163,20 +163,29 @@ import static org.springframework.web.bind.annotation.RequestMethod.POST; * @author Evgeniy Cheban */ public class OAuth2ResourceServerConfigurerTests { + private static final String JWT_TOKEN = "token"; + private static final String JWT_SUBJECT = "mock-test-subject"; + private static final Map JWT_CLAIMS = Collections.singletonMap(SUB, JWT_SUBJECT); + private static final Jwt JWT = jwt().build(); + private static final String JWK_SET_URI = "https://mock.org"; - private static final JwtAuthenticationToken JWT_AUTHENTICATION_TOKEN = - new JwtAuthenticationToken(JWT, Collections.emptyList()); + + private static final JwtAuthenticationToken JWT_AUTHENTICATION_TOKEN = new JwtAuthenticationToken(JWT, + Collections.emptyList()); private static final String INTROSPECTION_URI = "https://idp.example.com"; + private static final String CLIENT_ID = "client-id"; + private static final String CLIENT_SECRET = "client-secret"; - private static final BearerTokenAuthentication INTROSPECTION_AUTHENTICATION_TOKEN = - new BearerTokenAuthentication(new DefaultOAuth2AuthenticatedPrincipal(JWT_CLAIMS, Collections.emptyList()), - noScopes(), Collections.emptyList()); + + private static final BearerTokenAuthentication INTROSPECTION_AUTHENTICATION_TOKEN = new BearerTokenAuthentication( + new DefaultOAuth2AuthenticatedPrincipal(JWT_CLAIMS, Collections.emptyList()), noScopes(), + Collections.emptyList()); @Autowired(required = false) MockMvc mvc; @@ -188,28 +197,24 @@ public class OAuth2ResourceServerConfigurerTests { public final SpringTestRule spring = new SpringTestRule(); @Test - public void getWhenUsingDefaultsWithValidBearerTokenThenAcceptsRequest() - throws Exception { + public void getWhenUsingDefaultsWithValidBearerTokenThenAcceptsRequest() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/").with(bearerToken(token))) - .andExpect(status().isOk()) + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk()) .andExpect(content().string("ok")); } @Test - public void getWhenUsingDefaultsInLambdaWithValidBearerTokenThenAcceptsRequest() - throws Exception { + public void getWhenUsingDefaultsInLambdaWithValidBearerTokenThenAcceptsRequest() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultInLambdaConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/").with(bearerToken(token))) - .andExpect(status().isOk()) + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk()) .andExpect(content().string("ok")); } @@ -219,8 +224,7 @@ public class OAuth2ResourceServerConfigurerTests { mockWebServer(jwks("Default")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/").with(bearerToken(token))) - .andExpect(status().isOk()) + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk()) .andExpect(content().string("ok")); } @@ -230,115 +234,96 @@ public class OAuth2ResourceServerConfigurerTests { mockWebServer(jwks("Default")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/").with(bearerToken(token))) - .andExpect(status().isOk()) + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk()) .andExpect(content().string("ok")); } @Test - public void getWhenUsingDefaultsWithExpiredBearerTokenThenInvalidToken() - throws Exception { + public void getWhenUsingDefaultsWithExpiredBearerTokenThenInvalidToken() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("Expired"); - this.mvc.perform(get("/").with(bearerToken(token))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized()) .andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt")); } @Test - public void getWhenUsingDefaultsWithBadJwkEndpointThenInvalidToken() - throws Exception { + public void getWhenUsingDefaultsWithBadJwkEndpointThenInvalidToken() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire(); mockRestOperations("malformed"); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/").with(bearerToken(token))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized()) .andExpect(header().string("WWW-Authenticate", "Bearer")); } @Test - public void getWhenUsingDefaultsWithUnavailableJwkEndpointThenInvalidToken() - throws Exception { + public void getWhenUsingDefaultsWithUnavailableJwkEndpointThenInvalidToken() throws Exception { this.spring.register(WebServerConfig.class, JwkSetUriConfig.class).autowire(); this.web.shutdown(); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/").with(bearerToken(token))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized()) .andExpect(header().string("WWW-Authenticate", "Bearer")); } @Test - public void getWhenUsingDefaultsWithMalformedBearerTokenThenInvalidToken() - throws Exception { + public void getWhenUsingDefaultsWithMalformedBearerTokenThenInvalidToken() throws Exception { this.spring.register(JwkSetUriConfig.class).autowire(); - this.mvc.perform(get("/").with(bearerToken("an\"invalid\"token"))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").with(bearerToken("an\"invalid\"token"))).andExpect(status().isUnauthorized()) .andExpect(invalidTokenHeader("Bearer token is malformed")); } @Test - public void getWhenUsingDefaultsWithMalformedPayloadThenInvalidToken() - throws Exception { + public void getWhenUsingDefaultsWithMalformedPayloadThenInvalidToken() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("MalformedPayload"); - this.mvc.perform(get("/").with(bearerToken(token))) - .andExpect(status().isUnauthorized()) - .andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt: Malformed payload")); + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized()).andExpect( + invalidTokenHeader("An error occurred while attempting to decode the Jwt: Malformed payload")); } @Test - public void getWhenUsingDefaultsWithUnsignedBearerTokenThenInvalidToken() - throws Exception { + public void getWhenUsingDefaultsWithUnsignedBearerTokenThenInvalidToken() throws Exception { this.spring.register(JwkSetUriConfig.class).autowire(); String token = this.token("Unsigned"); - this.mvc.perform(get("/").with(bearerToken(token))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized()) .andExpect(invalidTokenHeader("Unsupported algorithm of none")); } @Test - public void getWhenUsingDefaultsWithBearerTokenBeforeNotBeforeThenInvalidToken() - throws Exception { + public void getWhenUsingDefaultsWithBearerTokenBeforeNotBeforeThenInvalidToken() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire(); this.mockRestOperations(jwks("Default")); String token = this.token("TooEarly"); - this.mvc.perform(get("/").with(bearerToken(token))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized()) .andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt")); } @Test - public void getWhenUsingDefaultsWithBearerTokenInTwoPlacesThenInvalidRequest() - throws Exception { + public void getWhenUsingDefaultsWithBearerTokenInTwoPlacesThenInvalidRequest() throws Exception { this.spring.register(JwkSetUriConfig.class).autowire(); - this.mvc.perform(get("/") - .with(bearerToken("token")) - .with(bearerToken("token").asParam())) + this.mvc.perform(get("/").with(bearerToken("token")).with(bearerToken("token").asParam())) .andExpect(status().isBadRequest()) .andExpect(invalidRequestHeader("Found multiple bearer tokens in the request")); } @Test - public void getWhenUsingDefaultsWithBearerTokenInTwoParametersThenInvalidRequest() - throws Exception { + public void getWhenUsingDefaultsWithBearerTokenInTwoParametersThenInvalidRequest() throws Exception { this.spring.register(JwkSetUriConfig.class).autowire(); @@ -346,33 +331,26 @@ public class OAuth2ResourceServerConfigurerTests { params.add("access_token", "token1"); params.add("access_token", "token2"); - this.mvc.perform(get("/") - .params(params)) - .andExpect(status().isBadRequest()) + this.mvc.perform(get("/").params(params)).andExpect(status().isBadRequest()) .andExpect(invalidRequestHeader("Found multiple bearer tokens in the request")); } @Test - public void postWhenUsingDefaultsWithBearerTokenAsFormParameterThenIgnoresToken() - throws Exception { + public void postWhenUsingDefaultsWithBearerTokenAsFormParameterThenIgnoresToken() throws Exception { this.spring.register(JwkSetUriConfig.class).autowire(); this.mvc.perform(post("/") // engage csrf - .with(bearerToken("token").asParam())) - .andExpect(status().isForbidden()) + .with(bearerToken("token").asParam())).andExpect(status().isForbidden()) .andExpect(header().doesNotExist(HttpHeaders.WWW_AUTHENTICATE)); } @Test - public void postWhenCsrfDisabledWithBearerTokenAsFormParameterThenIgnoresToken() - throws Exception { + public void postWhenCsrfDisabledWithBearerTokenAsFormParameterThenIgnoresToken() throws Exception { this.spring.register(CsrfDisabledConfig.class).autowire(); - this.mvc.perform(post("/") - .with(bearerToken("token").asParam())) - .andExpect(status().isUnauthorized()) + this.mvc.perform(post("/").with(bearerToken("token").asParam())).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer")); } @@ -383,279 +361,220 @@ public class OAuth2ResourceServerConfigurerTests { mockRestOperations(jwks("Default")); String token = token("ValidNoScopes"); - this.mvc.perform(get("/authenticated") - .with(bearerToken(token))) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/authenticated").with(bearerToken(token))).andExpect(status().isNotFound()); } @Test - public void getWhenUsingDefaultsWithNoBearerTokenThenUnauthorized() - throws Exception { + public void getWhenUsingDefaultsWithNoBearerTokenThenUnauthorized() throws Exception { this.spring.register(JwkSetUriConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/")).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer")); } @Test - public void getWhenUsingDefaultsWithSufficientlyScopedBearerTokenThenAcceptsRequest() - throws Exception { + public void getWhenUsingDefaultsWithSufficientlyScopedBearerTokenThenAcceptsRequest() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidMessageReadScope"); - this.mvc.perform(get("/requires-read-scope") - .with(bearerToken(token))) - .andExpect(status().isOk()) + this.mvc.perform(get("/requires-read-scope").with(bearerToken(token))).andExpect(status().isOk()) .andExpect(content().string("[SCOPE_message:read]")); } @Test - public void getWhenUsingDefaultsWithInsufficientScopeThenInsufficientScopeError() - throws Exception { + public void getWhenUsingDefaultsWithInsufficientScopeThenInsufficientScopeError() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/requires-read-scope") - .with(bearerToken(token))) - .andExpect(status().isForbidden()) + this.mvc.perform(get("/requires-read-scope").with(bearerToken(token))).andExpect(status().isForbidden()) .andExpect(insufficientScopeHeader()); } @Test - public void getWhenUsingDefaultsWithInsufficientScpThenInsufficientScopeError() - throws Exception { + public void getWhenUsingDefaultsWithInsufficientScpThenInsufficientScopeError() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidMessageWriteScp"); - this.mvc.perform(get("/requires-read-scope") - .with(bearerToken(token))) - .andExpect(status().isForbidden()) + this.mvc.perform(get("/requires-read-scope").with(bearerToken(token))).andExpect(status().isForbidden()) .andExpect(insufficientScopeHeader()); } @Test - public void getWhenUsingDefaultsAndAuthorizationServerHasNoMatchingKeyThenInvalidToken() - throws Exception { + public void getWhenUsingDefaultsAndAuthorizationServerHasNoMatchingKeyThenInvalidToken() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire(); mockRestOperations(jwks("Empty")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/") - .with(bearerToken(token))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized()) .andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt")); } @Test - public void getWhenUsingDefaultsAndAuthorizationServerHasMultipleMatchingKeysThenOk() - throws Exception { + public void getWhenUsingDefaultsAndAuthorizationServerHasMultipleMatchingKeysThenOk() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("TwoKeys")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/authenticated") - .with(bearerToken(token))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken(token))).andExpect(status().isOk()) .andExpect(content().string("test-subject")); } @Test - public void getWhenUsingDefaultsAndKeyMatchesByKidThenOk() - throws Exception { + public void getWhenUsingDefaultsAndKeyMatchesByKidThenOk() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("TwoKeys")); String token = this.token("Kid"); - this.mvc.perform(get("/authenticated") - .with(bearerToken(token))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken(token))).andExpect(status().isOk()) .andExpect(content().string("test-subject")); } // -- Method Security @Test - public void getWhenUsingMethodSecurityWithValidBearerTokenThenAcceptsRequest() - throws Exception { + public void getWhenUsingMethodSecurityWithValidBearerTokenThenAcceptsRequest() throws Exception { this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidMessageReadScope"); - this.mvc.perform(get("/ms-requires-read-scope") - .with(bearerToken(token))) - .andExpect(status().isOk()) + this.mvc.perform(get("/ms-requires-read-scope").with(bearerToken(token))).andExpect(status().isOk()) .andExpect(content().string("[SCOPE_message:read]")); } @Test - public void getWhenUsingMethodSecurityWithValidBearerTokenHavingScpAttributeThenAcceptsRequest() - throws Exception { + public void getWhenUsingMethodSecurityWithValidBearerTokenHavingScpAttributeThenAcceptsRequest() throws Exception { this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidMessageReadScp"); - this.mvc.perform(get("/ms-requires-read-scope") - .with(bearerToken(token))) - .andExpect(status().isOk()) + this.mvc.perform(get("/ms-requires-read-scope").with(bearerToken(token))).andExpect(status().isOk()) .andExpect(content().string("[SCOPE_message:read]")); } @Test - public void getWhenUsingMethodSecurityWithInsufficientScopeThenInsufficientScopeError() - throws Exception { + public void getWhenUsingMethodSecurityWithInsufficientScopeThenInsufficientScopeError() throws Exception { this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/ms-requires-read-scope") - .with(bearerToken(token))) - .andExpect(status().isForbidden()) + this.mvc.perform(get("/ms-requires-read-scope").with(bearerToken(token))).andExpect(status().isForbidden()) .andExpect(insufficientScopeHeader()); } @Test - public void getWhenUsingMethodSecurityWithInsufficientScpThenInsufficientScopeError() - throws Exception { + public void getWhenUsingMethodSecurityWithInsufficientScpThenInsufficientScopeError() throws Exception { this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidMessageWriteScp"); - this.mvc.perform(get("/ms-requires-read-scope") - .with(bearerToken(token))) - .andExpect(status().isForbidden()) + this.mvc.perform(get("/ms-requires-read-scope").with(bearerToken(token))).andExpect(status().isForbidden()) .andExpect(insufficientScopeHeader()); } @Test - public void getWhenUsingMethodSecurityWithDenyAllThenInsufficientScopeError() - throws Exception { + public void getWhenUsingMethodSecurityWithDenyAllThenInsufficientScopeError() throws Exception { this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidMessageReadScope"); - this.mvc.perform(get("/ms-deny") - .with(bearerToken(token))) - .andExpect(status().isForbidden()) + this.mvc.perform(get("/ms-deny").with(bearerToken(token))).andExpect(status().isForbidden()) .andExpect(insufficientScopeHeader()); } // -- Resource Server should not engage csrf @Test - public void postWhenUsingDefaultsWithValidBearerTokenAndNoCsrfTokenThenOk() - throws Exception { + public void postWhenUsingDefaultsWithValidBearerTokenAndNoCsrfTokenThenOk() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - this.mvc.perform(post("/authenticated") - .with(bearerToken(token))) - .andExpect(status().isOk()) + this.mvc.perform(post("/authenticated").with(bearerToken(token))).andExpect(status().isOk()) .andExpect(content().string("test-subject")); } @Test - public void postWhenUsingDefaultsWithNoBearerTokenThenCsrfDenies() - throws Exception { + public void postWhenUsingDefaultsWithNoBearerTokenThenCsrfDenies() throws Exception { this.spring.register(JwkSetUriConfig.class).autowire(); - this.mvc.perform(post("/authenticated")) - .andExpect(status().isForbidden()) + this.mvc.perform(post("/authenticated")).andExpect(status().isForbidden()) .andExpect(header().doesNotExist(HttpHeaders.WWW_AUTHENTICATE)); } @Test - public void postWhenUsingDefaultsWithExpiredBearerTokenAndNoCsrfThenInvalidToken() - throws Exception { + public void postWhenUsingDefaultsWithExpiredBearerTokenAndNoCsrfThenInvalidToken() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("Expired"); - this.mvc.perform(post("/authenticated") - .with(bearerToken(token))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(post("/authenticated").with(bearerToken(token))).andExpect(status().isUnauthorized()) .andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt")); } // -- Resource Server should not create sessions @Test - public void requestWhenDefaultConfiguredThenSessionIsNotCreated() - throws Exception { + public void requestWhenDefaultConfiguredThenSessionIsNotCreated() throws Exception { this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - MvcResult result = this.mvc.perform(get("/") - .with(bearerToken(token))) - .andExpect(status().isOk()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk()).andReturn(); assertThat(result.getRequest().getSession(false)).isNull(); } @Test - public void requestWhenIntrospectionConfiguredThenSessionIsNotCreated() - throws Exception { + public void requestWhenIntrospectionConfiguredThenSessionIsNotCreated() throws Exception { this.spring.register(RestOperationsConfig.class, OpaqueTokenConfig.class, BasicController.class).autowire(); mockRestOperations(json("Active")); - MvcResult result = this.mvc.perform(get("/authenticated") - .with(bearerToken("token"))) - .andExpect(status().isOk()) - .andExpect(content().string("test-subject")) - .andReturn(); + MvcResult result = this.mvc.perform(get("/authenticated").with(bearerToken("token"))).andExpect(status().isOk()) + .andExpect(content().string("test-subject")).andReturn(); assertThat(result.getRequest().getSession(false)).isNull(); } @Test - public void requestWhenUsingDefaultsAndNoBearerTokenThenSessionIsCreated() - throws Exception { + public void requestWhenUsingDefaultsAndNoBearerTokenThenSessionIsCreated() throws Exception { this.spring.register(JwkSetUriConfig.class, BasicController.class).autowire(); - MvcResult result = this.mvc.perform(get("/")) - .andExpect(status().isUnauthorized()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/")).andExpect(status().isUnauthorized()).andReturn(); assertThat(result.getRequest().getSession(false)).isNotNull(); } @Test - public void requestWhenSessionManagementConfiguredThenUserConfigurationOverrides() - throws Exception { + public void requestWhenSessionManagementConfiguredThenUserConfigurationOverrides() throws Exception { - this.spring.register(RestOperationsConfig.class, AlwaysSessionCreationConfig.class, BasicController.class).autowire(); + this.spring.register(RestOperationsConfig.class, AlwaysSessionCreationConfig.class, BasicController.class) + .autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - MvcResult result = this.mvc.perform(get("/") - .with(bearerToken(token))) - .andExpect(status().isOk()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk()).andReturn(); assertThat(result.getRequest().getSession(false)).isNotNull(); } @@ -666,20 +585,16 @@ public class OAuth2ResourceServerConfigurerTests { public void requestWhenBearerTokenResolverAllowsRequestBodyThenEitherHeaderOrRequestBodyIsAccepted() throws Exception { - this.spring.register(AllowBearerTokenInRequestBodyConfig.class, JwtDecoderConfig.class, - BasicController.class).autowire(); + this.spring.register(AllowBearerTokenInRequestBodyConfig.class, JwtDecoderConfig.class, BasicController.class) + .autowire(); JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); when(decoder.decode(anyString())).thenReturn(JWT); - this.mvc.perform(get("/authenticated") - .with(bearerToken(JWT_TOKEN))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk()) .andExpect(content().string(JWT_SUBJECT)); - this.mvc.perform(post("/authenticated") - .param("access_token", JWT_TOKEN)) - .andExpect(status().isOk()) + this.mvc.perform(post("/authenticated").param("access_token", JWT_TOKEN)).andExpect(status().isOk()) .andExpect(content().string(JWT_SUBJECT)); } @@ -687,20 +602,17 @@ public class OAuth2ResourceServerConfigurerTests { public void requestWhenBearerTokenResolverAllowsQueryParameterThenEitherHeaderOrQueryParameterIsAccepted() throws Exception { - this.spring.register(AllowBearerTokenAsQueryParameterConfig.class, JwtDecoderConfig.class, - BasicController.class).autowire(); + this.spring + .register(AllowBearerTokenAsQueryParameterConfig.class, JwtDecoderConfig.class, BasicController.class) + .autowire(); JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); when(decoder.decode(anyString())).thenReturn(JWT); - this.mvc.perform(get("/authenticated") - .with(bearerToken(JWT_TOKEN))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk()) .andExpect(content().string(JWT_SUBJECT)); - this.mvc.perform(get("/authenticated") - .param("access_token", JWT_TOKEN)) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").param("access_token", JWT_TOKEN)).andExpect(status().isOk()) .andExpect(content().string(JWT_SUBJECT)); } @@ -708,16 +620,14 @@ public class OAuth2ResourceServerConfigurerTests { public void requestWhenBearerTokenResolverAllowsRequestBodyAndRequestContainsTwoTokensThenInvalidRequest() throws Exception { - this.spring.register(AllowBearerTokenInRequestBodyConfig.class, JwtDecoderConfig.class, - BasicController.class).autowire(); + this.spring.register(AllowBearerTokenInRequestBodyConfig.class, JwtDecoderConfig.class, BasicController.class) + .autowire(); JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); when(decoder.decode(anyString())).thenReturn(JWT); - this.mvc.perform(post("/authenticated") - .param("access_token", JWT_TOKEN) - .with(bearerToken(JWT_TOKEN)) - .with(csrf())) + this.mvc.perform( + post("/authenticated").param("access_token", JWT_TOKEN).with(bearerToken(JWT_TOKEN)).with(csrf())) .andExpect(status().isBadRequest()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("invalid_request"))); } @@ -726,15 +636,14 @@ public class OAuth2ResourceServerConfigurerTests { public void requestWhenBearerTokenResolverAllowsQueryParameterAndRequestContainsTwoTokensThenInvalidRequest() throws Exception { - this.spring.register(AllowBearerTokenAsQueryParameterConfig.class, JwtDecoderConfig.class, - BasicController.class).autowire(); + this.spring + .register(AllowBearerTokenAsQueryParameterConfig.class, JwtDecoderConfig.class, BasicController.class) + .autowire(); JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); when(decoder.decode(anyString())).thenReturn(JWT); - this.mvc.perform(get("/authenticated") - .with(bearerToken(JWT_TOKEN)) - .param("access_token", JWT_TOKEN)) + this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN)).param("access_token", JWT_TOKEN)) .andExpect(status().isBadRequest()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("invalid_request"))); } @@ -758,10 +667,9 @@ public class OAuth2ResourceServerConfigurerTests { @Test public void getBearerTokenResolverWhenDuplicateResolverBeansThenWiringException() { - assertThatCode(() -> this.spring - .register(MultipleBearerTokenResolverBeansConfig.class, JwtDecoderConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class); + assertThatCode(() -> this.spring.register(MultipleBearerTokenResolverBeansConfig.class, JwtDecoderConfig.class) + .autowire()).isInstanceOf(BeanCreationException.class) + .hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class); } @Test @@ -781,8 +689,7 @@ public class OAuth2ResourceServerConfigurerTests { @Test public void getBearerTokenResolverWhenNoResolverSpecifiedThenTheDefaultIsUsed() { - ApplicationContext context = - this.spring.context(new GenericWebApplicationContext()).getContext(); + ApplicationContext context = this.spring.context(new GenericWebApplicationContext()).getContext(); OAuth2ResourceServerConfigurer oauth2 = new OAuth2ResourceServerConfigurer(context); @@ -792,8 +699,7 @@ public class OAuth2ResourceServerConfigurerTests { // -- custom jwt decoder @Test - public void requestWhenCustomJwtDecoderWiredOnDslThenUsed() - throws Exception { + public void requestWhenCustomJwtDecoderWiredOnDslThenUsed() throws Exception { this.spring.register(CustomJwtDecoderOnDsl.class, BasicController.class).autowire(); @@ -802,15 +708,12 @@ public class OAuth2ResourceServerConfigurerTests { when(decoder.decode(anyString())).thenReturn(JWT); - this.mvc.perform(get("/authenticated") - .with(bearerToken(JWT_TOKEN))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk()) .andExpect(content().string(JWT_SUBJECT)); } @Test - public void requestWhenCustomJwtDecoderInLambdaOnDslThenUsed() - throws Exception { + public void requestWhenCustomJwtDecoderInLambdaOnDslThenUsed() throws Exception { this.spring.register(CustomJwtDecoderInLambdaOnDsl.class, BasicController.class).autowire(); @@ -819,15 +722,12 @@ public class OAuth2ResourceServerConfigurerTests { when(decoder.decode(anyString())).thenReturn(JWT); - this.mvc.perform(get("/authenticated") - .with(bearerToken(JWT_TOKEN))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk()) .andExpect(content().string(JWT_SUBJECT)); } @Test - public void requestWhenCustomJwtDecoderExposedAsBeanThenUsed() - throws Exception { + public void requestWhenCustomJwtDecoderExposedAsBeanThenUsed() throws Exception { this.spring.register(CustomJwtDecoderAsBean.class, BasicController.class).autowire(); @@ -835,9 +735,7 @@ public class OAuth2ResourceServerConfigurerTests { when(decoder.decode(anyString())).thenReturn(JWT); - this.mvc.perform(get("/authenticated") - .with(bearerToken(JWT_TOKEN))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk()) .andExpect(content().string(JWT_SUBJECT)); } @@ -845,8 +743,7 @@ public class OAuth2ResourceServerConfigurerTests { public void getJwtDecoderWhenConfiguredWithDecoderAndJwkSetUriThenLastOneWins() { ApplicationContext context = mock(ApplicationContext.class); - OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = - new OAuth2ResourceServerConfigurer(context).jwt(); + OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = new OAuth2ResourceServerConfigurer(context).jwt(); JwtDecoder decoder = mock(JwtDecoder.class); @@ -855,8 +752,7 @@ public class OAuth2ResourceServerConfigurerTests { assertThat(jwtConfigurer.getJwtDecoder()).isEqualTo(decoder); - jwtConfigurer = - new OAuth2ResourceServerConfigurer(context).jwt(); + jwtConfigurer = new OAuth2ResourceServerConfigurer(context).jwt(); jwtConfigurer.decoder(decoder); jwtConfigurer.jwkSetUri(JWK_SET_URI); @@ -874,8 +770,7 @@ public class OAuth2ResourceServerConfigurerTests { ApplicationContext context = mock(ApplicationContext.class); when(context.getBean(JwtDecoder.class)).thenReturn(decoderBean); - OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = - new OAuth2ResourceServerConfigurer(context).jwt(); + OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = new OAuth2ResourceServerConfigurer(context).jwt(); jwtConfigurer.decoder(decoder); assertThat(jwtConfigurer.getJwtDecoder()).isEqualTo(decoder); @@ -888,8 +783,7 @@ public class OAuth2ResourceServerConfigurerTests { ApplicationContext context = mock(ApplicationContext.class); when(context.getBean(JwtDecoder.class)).thenReturn(decoder); - OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = - new OAuth2ResourceServerConfigurer(context).jwt(); + OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = new OAuth2ResourceServerConfigurer(context).jwt(); jwtConfigurer.jwkSetUri(JWK_SET_URI); @@ -908,8 +802,7 @@ public class OAuth2ResourceServerConfigurerTests { context.registerBean("decoderTwo", JwtDecoder.class, () -> decoderBean); this.spring.context(context).autowire(); - OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = - new OAuth2ResourceServerConfigurer(context).jwt(); + OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = new OAuth2ResourceServerConfigurer(context).jwt(); jwtConfigurer.decoder(decoder); assertThat(jwtConfigurer.getJwtDecoder()).isEqualTo(decoder); @@ -925,41 +818,34 @@ public class OAuth2ResourceServerConfigurerTests { this.spring.context(context).autowire(); - OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = - new OAuth2ResourceServerConfigurer(context).jwt(); + OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = new OAuth2ResourceServerConfigurer(context).jwt(); - assertThatCode(() -> jwtConfigurer.getJwtDecoder()) - .isInstanceOf(NoUniqueBeanDefinitionException.class); + assertThatCode(() -> jwtConfigurer.getJwtDecoder()).isInstanceOf(NoUniqueBeanDefinitionException.class); } // -- exception handling @Test - public void requestWhenRealmNameConfiguredThenUsesOnUnauthenticated() - throws Exception { + public void requestWhenRealmNameConfiguredThenUsesOnUnauthenticated() throws Exception { this.spring.register(RealmNameConfiguredOnEntryPoint.class, JwtDecoderConfig.class).autowire(); JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); when(decoder.decode(anyString())).thenThrow(JwtException.class); - this.mvc.perform(get("/authenticated") - .with(bearerToken("invalid_token"))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/authenticated").with(bearerToken("invalid_token"))).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer realm=\"myRealm\""))); } @Test - public void requestWhenRealmNameConfiguredThenUsesOnAccessDenied() - throws Exception { + public void requestWhenRealmNameConfiguredThenUsesOnAccessDenied() throws Exception { this.spring.register(RealmNameConfiguredOnAccessDeniedHandler.class, JwtDecoderConfig.class).autowire(); JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); when(decoder.decode(anyString())).thenReturn(JWT); - this.mvc.perform(get("/authenticated") - .with(bearerToken("insufficiently_scoped"))) + this.mvc.perform(get("/authenticated").with(bearerToken("insufficiently_scoped"))) .andExpect(status().isForbidden()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer realm=\"myRealm\""))); } @@ -968,89 +854,75 @@ public class OAuth2ResourceServerConfigurerTests { public void authenticationEntryPointWhenGivenNullThenThrowsException() { ApplicationContext context = mock(ApplicationContext.class); OAuth2ResourceServerConfigurer configurer = new OAuth2ResourceServerConfigurer(context); - assertThatCode(() -> configurer.authenticationEntryPoint(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> configurer.authenticationEntryPoint(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void accessDeniedHandlerWhenGivenNullThenThrowsException() { ApplicationContext context = mock(ApplicationContext.class); OAuth2ResourceServerConfigurer configurer = new OAuth2ResourceServerConfigurer(context); - assertThatCode(() -> configurer.accessDeniedHandler(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> configurer.accessDeniedHandler(null)).isInstanceOf(IllegalArgumentException.class); } // -- token validator @Test - public void requestWhenCustomJwtValidatorFailsThenCorrespondingErrorMessage() - throws Exception { + public void requestWhenCustomJwtValidatorFailsThenCorrespondingErrorMessage() throws Exception { this.spring.register(RestOperationsConfig.class, CustomJwtValidatorConfig.class).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - OAuth2TokenValidator jwtValidator = - this.spring.getContext().getBean(CustomJwtValidatorConfig.class) - .getJwtValidator(); + OAuth2TokenValidator jwtValidator = this.spring.getContext().getBean(CustomJwtValidatorConfig.class) + .getJwtValidator(); OAuth2Error error = new OAuth2Error("custom-error", "custom-description", "custom-uri"); when(jwtValidator.validate(any(Jwt.class))).thenReturn(OAuth2TokenValidatorResult.failure(error)); - this.mvc.perform(get("/") - .with(bearerToken(token))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("custom-description"))); } @Test - public void requestWhenClockSkewSetThenTimestampWindowRelaxedAccordingly() - throws Exception { + public void requestWhenClockSkewSetThenTimestampWindowRelaxedAccordingly() throws Exception { - this.spring.register(RestOperationsConfig.class, UnexpiredJwtClockSkewConfig.class, BasicController.class).autowire(); + this.spring.register(RestOperationsConfig.class, UnexpiredJwtClockSkewConfig.class, BasicController.class) + .autowire(); mockRestOperations(jwks("Default")); String token = this.token("ExpiresAt4687177990"); - this.mvc.perform(get("/") - .with(bearerToken(token))) - .andExpect(status().isOk()); + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk()); } @Test - public void requestWhenClockSkewSetButJwtStillTooLateThenReportsExpired() - throws Exception { + public void requestWhenClockSkewSetButJwtStillTooLateThenReportsExpired() throws Exception { - this.spring.register(RestOperationsConfig.class, ExpiredJwtClockSkewConfig.class, BasicController.class).autowire(); + this.spring.register(RestOperationsConfig.class, ExpiredJwtClockSkewConfig.class, BasicController.class) + .autowire(); mockRestOperations(jwks("Default")); String token = this.token("ExpiresAt4687177990"); - this.mvc.perform(get("/") - .with(bearerToken(token))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isUnauthorized()) .andExpect(invalidTokenHeader("Jwt expired at")); } // -- converter @Test - public void requestWhenJwtAuthenticationConverterConfiguredOnDslThenIsUsed() - throws Exception { + public void requestWhenJwtAuthenticationConverterConfiguredOnDslThenIsUsed() throws Exception { this.spring.register(JwtDecoderConfig.class, JwtAuthenticationConverterConfiguredOnDsl.class, BasicController.class).autowire(); - Converter jwtAuthenticationConverter = - this.spring.getContext().getBean(JwtAuthenticationConverterConfiguredOnDsl.class) - .getJwtAuthenticationConverter(); + Converter jwtAuthenticationConverter = this.spring.getContext() + .getBean(JwtAuthenticationConverterConfiguredOnDsl.class).getJwtAuthenticationConverter(); when(jwtAuthenticationConverter.convert(JWT)).thenReturn(JWT_AUTHENTICATION_TOKEN); JwtDecoder jwtDecoder = this.spring.getContext().getBean(JwtDecoder.class); when(jwtDecoder.decode(anyString())).thenReturn(JWT); - this.mvc.perform(get("/") - .with(bearerToken(JWT_TOKEN))) - .andExpect(status().isOk()); + this.mvc.perform(get("/").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk()); verify(jwtAuthenticationConverter).convert(JWT); } @@ -1065,63 +937,49 @@ public class OAuth2ResourceServerConfigurerTests { JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); when(decoder.decode(JWT_TOKEN)).thenReturn(JWT); - this.mvc.perform(get("/requires-read-scope") - .with(bearerToken(JWT_TOKEN))) - .andExpect(status().isOk()); + this.mvc.perform(get("/requires-read-scope").with(bearerToken(JWT_TOKEN))).andExpect(status().isOk()); } // -- single key @Test - public void requestWhenUsingPublicKeyAndValidTokenThenAuthenticates() - throws Exception { + public void requestWhenUsingPublicKeyAndValidTokenThenAuthenticates() throws Exception { this.spring.register(SingleKeyConfig.class, BasicController.class).autowire(); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/") - .with(bearerToken(token))) - .andExpect(status().isOk()); + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(status().isOk()); } @Test - public void requestWhenUsingPublicKeyAndSignatureFailsThenReturnsInvalidToken() - throws Exception { + public void requestWhenUsingPublicKeyAndSignatureFailsThenReturnsInvalidToken() throws Exception { this.spring.register(SingleKeyConfig.class).autowire(); String token = this.token("WrongSignature"); - this.mvc.perform(get("/") - .with(bearerToken(token))) - .andExpect(invalidTokenHeader("signature")); + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(invalidTokenHeader("signature")); } @Test - public void requestWhenUsingPublicKeyAlgorithmDoesNotMatchThenReturnsInvalidToken() - throws Exception { + public void requestWhenUsingPublicKeyAlgorithmDoesNotMatchThenReturnsInvalidToken() throws Exception { this.spring.register(SingleKeyConfig.class).autowire(); String token = this.token("WrongAlgorithm"); - this.mvc.perform(get("/") - .with(bearerToken(token))) - .andExpect(invalidTokenHeader("algorithm")); + this.mvc.perform(get("/").with(bearerToken(token))).andExpect(invalidTokenHeader("algorithm")); } // gh-7793 @Test - public void requestWhenUsingCustomAuthenticationEventPublisherThenUses() throws Exception{ + public void requestWhenUsingCustomAuthenticationEventPublisherThenUses() throws Exception { this.spring.register(CustomAuthenticationEventPublisher.class).autowire(); - when(bean(JwtDecoder.class).decode(anyString())) - .thenThrow(new BadJwtException("problem")); + when(bean(JwtDecoder.class).decode(anyString())).thenThrow(new BadJwtException("problem")); this.mvc.perform(get("/").with(bearerToken("token"))); verifyBean(AuthenticationEventPublisher.class) - .publishAuthenticationFailure( - any(OAuth2AuthenticationException.class), - any(Authentication.class)); + .publishAuthenticationFailure(any(OAuth2AuthenticationException.class), any(Authentication.class)); } @Test @@ -1130,9 +988,7 @@ public class OAuth2ResourceServerConfigurerTests { when(bean(AuthenticationProvider.class).authenticate(any(Authentication.class))) .thenReturn(JWT_AUTHENTICATION_TOKEN); - this.mvc.perform(get("/authenticated") - .with(bearerToken("token"))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken("token"))).andExpect(status().isOk()) .andExpect(content().string("mock-test-subject")); verifyBean(AuthenticationProvider.class).authenticate(any(Authentication.class)); @@ -1140,26 +996,22 @@ public class OAuth2ResourceServerConfigurerTests { // -- opaque - @Test public void getWhenIntrospectingThenOk() throws Exception { this.spring.register(RestOperationsConfig.class, OpaqueTokenConfig.class, BasicController.class).autowire(); mockRestOperations(json("Active")); - this.mvc.perform(get("/authenticated") - .with(bearerToken("token"))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken("token"))).andExpect(status().isOk()) .andExpect(content().string("test-subject")); } @Test public void getWhenOpaqueTokenInLambdaAndIntrospectingThenOk() throws Exception { - this.spring.register(RestOperationsConfig.class, OpaqueTokenInLambdaConfig.class, BasicController.class).autowire(); + this.spring.register(RestOperationsConfig.class, OpaqueTokenInLambdaConfig.class, BasicController.class) + .autowire(); mockRestOperations(json("Active")); - this.mvc.perform(get("/authenticated") - .with(bearerToken("token"))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken("token"))).andExpect(status().isOk()) .andExpect(content().string("test-subject")); } @@ -1168,11 +1020,8 @@ public class OAuth2ResourceServerConfigurerTests { this.spring.register(RestOperationsConfig.class, OpaqueTokenConfig.class).autowire(); mockRestOperations(json("Inactive")); - this.mvc.perform(get("/") - .with(bearerToken("token"))) - .andExpect(status().isUnauthorized()) - .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, - containsString("Provided token isn't active"))); + this.mvc.perform(get("/").with(bearerToken("token"))).andExpect(status().isUnauthorized()).andExpect( + header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("Provided token isn't active"))); } @Test @@ -1180,9 +1029,7 @@ public class OAuth2ResourceServerConfigurerTests { this.spring.register(RestOperationsConfig.class, OpaqueTokenConfig.class).autowire(); mockRestOperations(json("ActiveNoScopes")); - this.mvc.perform(get("/requires-read-scope") - .with(bearerToken("token"))) - .andExpect(status().isForbidden()) + this.mvc.perform(get("/requires-read-scope").with(bearerToken("token"))).andExpect(status().isForbidden()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("scope"))); } @@ -1192,9 +1039,7 @@ public class OAuth2ResourceServerConfigurerTests { when(bean(AuthenticationProvider.class).authenticate(any(Authentication.class))) .thenReturn(INTROSPECTION_AUTHENTICATION_TOKEN); - this.mvc.perform(get("/authenticated") - .with(bearerToken("token"))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken("token"))).andExpect(status().isOk()) .andExpect(content().string("mock-test-subject")); verifyBean(AuthenticationProvider.class).authenticate(any(Authentication.class)); @@ -1206,9 +1051,7 @@ public class OAuth2ResourceServerConfigurerTests { when(bean(AuthenticationProvider.class).authenticate(any(Authentication.class))) .thenReturn(INTROSPECTION_AUTHENTICATION_TOKEN); - this.mvc.perform(get("/authenticated") - .with(bearerToken("token"))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken("token"))).andExpect(status().isOk()) .andExpect(content().string("mock-test-subject")); verifyBean(AuthenticationProvider.class).authenticate(any(Authentication.class)); @@ -1224,8 +1067,8 @@ public class OAuth2ResourceServerConfigurerTests { public void getIntrospectionClientWhenConfiguredWithClientAndIntrospectionUriThenLastOneWins() { ApplicationContext context = mock(ApplicationContext.class); - OAuth2ResourceServerConfigurer.OpaqueTokenConfigurer opaqueTokenConfigurer = - new OAuth2ResourceServerConfigurer(context).opaqueToken(); + OAuth2ResourceServerConfigurer.OpaqueTokenConfigurer opaqueTokenConfigurer = new OAuth2ResourceServerConfigurer( + context).opaqueToken(); OpaqueTokenIntrospector client = mock(OpaqueTokenIntrospector.class); @@ -1235,15 +1078,13 @@ public class OAuth2ResourceServerConfigurerTests { assertThat(opaqueTokenConfigurer.getIntrospector()).isEqualTo(client); - opaqueTokenConfigurer = - new OAuth2ResourceServerConfigurer(context).opaqueToken(); + opaqueTokenConfigurer = new OAuth2ResourceServerConfigurer(context).opaqueToken(); opaqueTokenConfigurer.introspector(client); opaqueTokenConfigurer.introspectionUri(INTROSPECTION_URI); opaqueTokenConfigurer.introspectionClientCredentials(CLIENT_ID, CLIENT_SECRET); - assertThat(opaqueTokenConfigurer.getIntrospector()) - .isInstanceOf(NimbusOpaqueTokenIntrospector.class); + assertThat(opaqueTokenConfigurer.getIntrospector()).isInstanceOf(NimbusOpaqueTokenIntrospector.class); } @@ -1253,8 +1094,8 @@ public class OAuth2ResourceServerConfigurerTests { registerMockBean(context, "introspectionClientOne", OpaqueTokenIntrospector.class); registerMockBean(context, "introspectionClientTwo", OpaqueTokenIntrospector.class); - OAuth2ResourceServerConfigurer.OpaqueTokenConfigurer opaqueToken = - new OAuth2ResourceServerConfigurer(context).opaqueToken(); + OAuth2ResourceServerConfigurer.OpaqueTokenConfigurer opaqueToken = new OAuth2ResourceServerConfigurer(context) + .opaqueToken(); opaqueToken.introspectionUri(INTROSPECTION_URI); opaqueToken.introspectionClientCredentials(CLIENT_ID, CLIENT_SECRET); @@ -1264,93 +1105,73 @@ public class OAuth2ResourceServerConfigurerTests { // -- In combination with other authentication providers @Test - public void requestWhenBasicAndResourceServerEntryPointsThenMatchedByRequest() - throws Exception { + public void requestWhenBasicAndResourceServerEntryPointsThenMatchedByRequest() throws Exception { this.spring.register(BasicAndResourceServerConfig.class, JwtDecoderConfig.class).autowire(); JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); when(decoder.decode(anyString())).thenThrow(JwtException.class); - this.mvc.perform(get("/authenticated") - .with(httpBasic("some", "user"))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/authenticated").with(httpBasic("some", "user"))).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Basic"))); - this.mvc.perform(get("/authenticated")) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/authenticated")).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Basic"))); - this.mvc.perform(get("/authenticated") - .with(bearerToken("invalid_token"))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/authenticated").with(bearerToken("invalid_token"))).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer"))); } @Test - public void requestWhenFormLoginAndResourceServerEntryPointsThenSessionCreatedByRequest() - throws Exception { + public void requestWhenFormLoginAndResourceServerEntryPointsThenSessionCreatedByRequest() throws Exception { this.spring.register(FormAndResourceServerConfig.class, JwtDecoderConfig.class).autowire(); JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); when(decoder.decode(anyString())).thenThrow(JwtException.class); - MvcResult result = - this.mvc.perform(get("/authenticated")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("http://localhost/login")) - .andReturn(); + MvcResult result = this.mvc.perform(get("/authenticated")).andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/login")).andReturn(); assertThat(result.getRequest().getSession(false)).isNotNull(); - result = - this.mvc.perform(get("/authenticated") - .with(bearerToken("token"))) - .andExpect(status().isUnauthorized()) - .andReturn(); + result = this.mvc.perform(get("/authenticated").with(bearerToken("token"))).andExpect(status().isUnauthorized()) + .andReturn(); assertThat(result.getRequest().getSession(false)).isNull(); } @Test - public void requestWhenDefaultAndResourceServerAccessDeniedHandlersThenMatchedByRequest() - throws Exception { + public void requestWhenDefaultAndResourceServerAccessDeniedHandlersThenMatchedByRequest() throws Exception { - this.spring.register(ExceptionHandlingAndResourceServerWithAccessDeniedHandlerConfig.class, - JwtDecoderConfig.class).autowire(); + this.spring + .register(ExceptionHandlingAndResourceServerWithAccessDeniedHandlerConfig.class, JwtDecoderConfig.class) + .autowire(); JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); when(decoder.decode(anyString())).thenReturn(JWT); - this.mvc.perform(get("/authenticated") - .with(httpBasic("basic-user", "basic-password"))) - .andExpect(status().isForbidden()) - .andExpect(header().doesNotExist(HttpHeaders.WWW_AUTHENTICATE)); + this.mvc.perform(get("/authenticated").with(httpBasic("basic-user", "basic-password"))) + .andExpect(status().isForbidden()).andExpect(header().doesNotExist(HttpHeaders.WWW_AUTHENTICATE)); - this.mvc.perform(get("/authenticated") - .with(bearerToken("insufficiently_scoped"))) + this.mvc.perform(get("/authenticated").with(bearerToken("insufficiently_scoped"))) .andExpect(status().isForbidden()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer"))); } @Test - public void getWhenAlsoUsingHttpBasicThenCorrectProviderEngages() - throws Exception { + public void getWhenAlsoUsingHttpBasicThenCorrectProviderEngages() throws Exception { - this.spring.register(RestOperationsConfig.class, BasicAndResourceServerConfig.class, BasicController.class).autowire(); + this.spring.register(RestOperationsConfig.class, BasicAndResourceServerConfig.class, BasicController.class) + .autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/authenticated") - .with(bearerToken(token))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken(token))).andExpect(status().isOk()) .andExpect(content().string("test-subject")); - this.mvc.perform(get("/authenticated") - .with(httpBasic("basic-user", "basic-password"))) - .andExpect(status().isOk()) - .andExpect(content().string("basic-user")); + this.mvc.perform(get("/authenticated").with(httpBasic("basic-user", "basic-password"))) + .andExpect(status().isOk()).andExpect(content().string("basic-user")); } // -- authentication manager @@ -1362,16 +1183,11 @@ public class OAuth2ResourceServerConfigurerTests { OAuth2ResourceServerConfigurer oauth2ResourceServer = new OAuth2ResourceServerConfigurer(context); AuthenticationManager authenticationManager = mock(AuthenticationManager.class); - oauth2ResourceServer - .jwt() - .authenticationManager(authenticationManager) - .decoder(mock(JwtDecoder.class)); + oauth2ResourceServer.jwt().authenticationManager(authenticationManager).decoder(mock(JwtDecoder.class)); assertThat(oauth2ResourceServer.getAuthenticationManager(http)).isSameAs(authenticationManager); oauth2ResourceServer = new OAuth2ResourceServerConfigurer(context); - oauth2ResourceServer - .opaqueToken() - .authenticationManager(authenticationManager) + oauth2ResourceServer.opaqueToken().authenticationManager(authenticationManager) .introspector(mock(OpaqueTokenIntrospector.class)); assertThat(oauth2ResourceServer.getAuthenticationManager(http)).isSameAs(authenticationManager); verify(http, never()).authenticationProvider(any(AuthenticationProvider.class)); @@ -1384,9 +1200,7 @@ public class OAuth2ResourceServerConfigurerTests { this.spring.register(WebServerConfig.class, MultipleIssuersConfig.class, BasicController.class).autowire(); MockWebServer server = this.spring.getContext().getBean(MockWebServer.class); - String metadata = "{\n" - + " \"issuer\": \"%s\", \n" - + " \"jwks_uri\": \"%s/.well-known/jwks.json\" \n" + String metadata = "{\n" + " \"issuer\": \"%s\", \n" + " \"jwks_uri\": \"%s/.well-known/jwks.json\" \n" + "}"; String jwkSet = jwkSet(); String issuerOne = server.url("/issuerOne").toString(); @@ -1399,25 +1213,19 @@ public class OAuth2ResourceServerConfigurerTests { mockWebServer(String.format(metadata, issuerOne, issuerOne)); mockWebServer(jwkSet); - this.mvc.perform(get("/authenticated") - .with(bearerToken(jwtOne))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken(jwtOne))).andExpect(status().isOk()) .andExpect(content().string("test-subject")); mockWebServer(String.format(metadata, issuerTwo, issuerTwo)); mockWebServer(jwkSet); - this.mvc.perform(get("/authenticated") - .with(bearerToken(jwtTwo))) - .andExpect(status().isOk()) + this.mvc.perform(get("/authenticated").with(bearerToken(jwtTwo))).andExpect(status().isOk()) .andExpect(content().string("test-subject")); mockWebServer(String.format(metadata, issuerThree, issuerThree)); mockWebServer(jwkSet); - this.mvc.perform(get("/authenticated") - .with(bearerToken(jwtThree))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/authenticated").with(bearerToken(jwtThree))).andExpect(status().isUnauthorized()) .andExpect(invalidTokenHeader("Invalid issuer")); } @@ -1427,16 +1235,14 @@ public class OAuth2ResourceServerConfigurerTests { public void configuredWhenMissingJwtAuthenticationProviderThenWiringException() { assertThatCode(() -> this.spring.register(JwtlessConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasMessageContaining("neither was found"); + .isInstanceOf(BeanCreationException.class).hasMessageContaining("neither was found"); } @Test public void configureWhenMissingJwkSetUriThenWiringException() { assertThatCode(() -> this.spring.register(JwtHalfConfiguredConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasMessageContaining("No qualifying bean of type"); + .isInstanceOf(BeanCreationException.class).hasMessageContaining("No qualifying bean of type"); } @Test @@ -1449,17 +1255,14 @@ public class OAuth2ResourceServerConfigurerTests { @Test public void configureWhenUsingBothAuthenticationManagerResolverAndOpaqueThenWiringException() { assertThatCode(() -> this.spring.register(AuthenticationManagerResolverPlusOtherConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasMessageContaining("authenticationManagerResolver"); + .isInstanceOf(BeanCreationException.class).hasMessageContaining("authenticationManagerResolver"); } @Test public void getJwtAuthenticationConverterWhenNoConverterSpecifiedThenTheDefaultIsUsed() { - ApplicationContext context = - this.spring.context(new GenericWebApplicationContext()).getContext(); + ApplicationContext context = this.spring.context(new GenericWebApplicationContext()).getContext(); - OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = - new OAuth2ResourceServerConfigurer(context).jwt(); + OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = new OAuth2ResourceServerConfigurer(context).jwt(); assertThat(jwtConfigurer.getJwtAuthenticationConverter()).isInstanceOf(JwtAuthenticationConverter.class); } @@ -1472,8 +1275,7 @@ public class OAuth2ResourceServerConfigurerTests { context.registerBean(JwtAuthenticationConverter.class, () -> converterBean); this.spring.context(context).autowire(); - OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = - new OAuth2ResourceServerConfigurer(context).jwt(); + OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = new OAuth2ResourceServerConfigurer(context).jwt(); assertThat(jwtConfigurer.getJwtAuthenticationConverter()).isEqualTo(converterBean); } @@ -1487,8 +1289,7 @@ public class OAuth2ResourceServerConfigurerTests { context.registerBean(JwtAuthenticationConverter.class, () -> converterBean); this.spring.context(context).autowire(); - OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = - new OAuth2ResourceServerConfigurer(context).jwt(); + OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = new OAuth2ResourceServerConfigurer(context).jwt(); jwtConfigurer.jwtAuthenticationConverter(converter); assertThat(jwtConfigurer.getJwtAuthenticationConverter()).isEqualTo(converter); @@ -1504,8 +1305,7 @@ public class OAuth2ResourceServerConfigurerTests { context.registerBean("converterTwo", JwtAuthenticationConverter.class, () -> converterBean); this.spring.context(context).autowire(); - OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = - new OAuth2ResourceServerConfigurer(context).jwt(); + OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = new OAuth2ResourceServerConfigurer(context).jwt(); jwtConfigurer.jwtAuthenticationConverter(converter); assertThat(jwtConfigurer.getJwtAuthenticationConverter()).isEqualTo(converter); @@ -1520,8 +1320,7 @@ public class OAuth2ResourceServerConfigurerTests { context.registerBean("converterTwo", JwtAuthenticationConverter.class, () -> converterBean); this.spring.context(context).autowire(); - OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = - new OAuth2ResourceServerConfigurer(context).jwt(); + OAuth2ResourceServerConfigurer.JwtConfigurer jwtConfigurer = new OAuth2ResourceServerConfigurer(context).jwt(); assertThatCode(jwtConfigurer::getJwtAuthenticationConverter) .isInstanceOf(NoUniqueBeanDefinitionException.class); @@ -1544,6 +1343,7 @@ public class OAuth2ResourceServerConfigurerTests { .jwt(); // @formatter:on } + } @EnableWebSecurity @@ -1564,10 +1364,12 @@ public class OAuth2ResourceServerConfigurerTests { ); // @formatter:on } + } @EnableWebSecurity static class JwkSetUriConfig extends WebSecurityConfigurerAdapter { + @Value("${mockwebserver.url:https://example.org}") String jwkSetUri; @@ -1584,10 +1386,12 @@ public class OAuth2ResourceServerConfigurerTests { .jwkSetUri(this.jwkSetUri); // @formatter:on } + } @EnableWebSecurity static class JwkSetUriInLambdaConfig extends WebSecurityConfigurerAdapter { + @Value("${mockwebserver.url:https://example.org}") String jwkSetUri; @@ -1609,10 +1413,12 @@ public class OAuth2ResourceServerConfigurerTests { ); // @formatter:on } + } @EnableWebSecurity static class CsrfDisabledConfig extends WebSecurityConfigurerAdapter { + @Value("${mockwebserver.url:https://example.org}") String jwkSetUri; @@ -1630,10 +1436,12 @@ public class OAuth2ResourceServerConfigurerTests { .jwkSetUri(this.jwkSetUri); // @formatter:on } + } @EnableWebSecurity static class AnonymousDisabledConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -1646,11 +1454,13 @@ public class OAuth2ResourceServerConfigurerTests { .jwt(); // @formatter:on } + } @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) static class MethodSecurityConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -1662,10 +1472,12 @@ public class OAuth2ResourceServerConfigurerTests { .jwt(); // @formatter:on } + } @EnableWebSecurity static class JwtlessConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -1676,10 +1488,12 @@ public class OAuth2ResourceServerConfigurerTests { .oauth2ResourceServer(); // @formatter:on } + } @EnableWebSecurity static class RealmNameConfiguredOnEntryPoint extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -1694,15 +1508,16 @@ public class OAuth2ResourceServerConfigurerTests { } AuthenticationEntryPoint authenticationEntryPoint() { - BearerTokenAuthenticationEntryPoint entryPoint = - new BearerTokenAuthenticationEntryPoint(); + BearerTokenAuthenticationEntryPoint entryPoint = new BearerTokenAuthenticationEntryPoint(); entryPoint.setRealmName("myRealm"); return entryPoint; } + } @EnableWebSecurity static class RealmNameConfiguredOnAccessDeniedHandler extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -1717,15 +1532,16 @@ public class OAuth2ResourceServerConfigurerTests { } AccessDeniedHandler accessDeniedHandler() { - BearerTokenAccessDeniedHandler accessDeniedHandler = - new BearerTokenAccessDeniedHandler(); + BearerTokenAccessDeniedHandler accessDeniedHandler = new BearerTokenAccessDeniedHandler(); accessDeniedHandler.setRealmName("myRealm"); return accessDeniedHandler; } + } @EnableWebSecurity static class ExceptionHandlingAndResourceServerWithAccessDeniedHandlerConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -1746,7 +1562,7 @@ public class OAuth2ResourceServerConfigurerTests { @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( - // @formatter:off + // @formatter:off org.springframework.security.core.userdetails.User.withDefaultPasswordEncoder() .username("basic-user") .password("basic-password") @@ -1754,10 +1570,12 @@ public class OAuth2ResourceServerConfigurerTests { .build()); // @formatter:on } + } @EnableWebSecurity static class JwtAuthenticationConverterConfiguredOnDsl extends WebSecurityConfigurerAdapter { + private final Converter jwtAuthenticationConverter = mock(Converter.class); @Override @@ -1776,10 +1594,12 @@ public class OAuth2ResourceServerConfigurerTests { Converter getJwtAuthenticationConverter() { return this.jwtAuthenticationConverter; } + } @EnableWebSecurity static class CustomAuthorityMappingConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -1795,15 +1615,16 @@ public class OAuth2ResourceServerConfigurerTests { Converter getJwtAuthenticationConverter() { JwtAuthenticationConverter converter = new JwtAuthenticationConverter(); - converter.setJwtGrantedAuthoritiesConverter(jwt -> - Collections.singletonList(new SimpleGrantedAuthority("message:read")) - ); + converter.setJwtGrantedAuthoritiesConverter( + jwt -> Collections.singletonList(new SimpleGrantedAuthority("message:read"))); return converter; } + } @EnableWebSecurity static class BasicAndResourceServerConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -1821,7 +1642,7 @@ public class OAuth2ResourceServerConfigurerTests { @Bean public UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager( - // @formatter:off + // @formatter:off org.springframework.security.core.userdetails.User.withDefaultPasswordEncoder() .username("basic-user") .password("basic-password") @@ -1829,10 +1650,12 @@ public class OAuth2ResourceServerConfigurerTests { .build()); // @formatter:on } + } @EnableWebSecurity static class FormAndResourceServerConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -1846,10 +1669,12 @@ public class OAuth2ResourceServerConfigurerTests { .jwt(); // @formatter:on } + } @EnableWebSecurity static class JwtHalfConfiguredConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -1861,10 +1686,12 @@ public class OAuth2ResourceServerConfigurerTests { .jwt(); // missing key configuration, e.g. jwkSetUri // @formatter:on } + } @EnableWebSecurity static class AlwaysSessionCreationConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -1876,10 +1703,12 @@ public class OAuth2ResourceServerConfigurerTests { .jwt(); // @formatter:on } + } @EnableWebSecurity static class AllowBearerTokenInRequestBodyConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -1898,10 +1727,12 @@ public class OAuth2ResourceServerConfigurerTests { resolver.setAllowFormEncodedBodyParameter(true); return resolver; } + } @EnableWebSecurity static class AllowBearerTokenAsQueryParameterConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -1920,10 +1751,12 @@ public class OAuth2ResourceServerConfigurerTests { resolver.setAllowUriQueryParameter(true); return resolver; } + } @EnableWebSecurity static class MultipleBearerTokenResolverBeansConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -1949,10 +1782,12 @@ public class OAuth2ResourceServerConfigurerTests { resolver.setAllowFormEncodedBodyParameter(true); return resolver; } + } @EnableWebSecurity static class CustomJwtDecoderOnDsl extends WebSecurityConfigurerAdapter { + JwtDecoder decoder = mock(JwtDecoder.class); @Override @@ -1971,10 +1806,12 @@ public class OAuth2ResourceServerConfigurerTests { JwtDecoder decoder() { return this.decoder; } + } @EnableWebSecurity static class CustomJwtDecoderInLambdaOnDsl extends WebSecurityConfigurerAdapter { + JwtDecoder decoder = mock(JwtDecoder.class); @Override @@ -1998,10 +1835,12 @@ public class OAuth2ResourceServerConfigurerTests { JwtDecoder decoder() { return this.decoder; } + } @EnableWebSecurity static class CustomJwtDecoderAsBean extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -2018,10 +1857,12 @@ public class OAuth2ResourceServerConfigurerTests { public JwtDecoder decoder() { return mock(JwtDecoder.class); } + } @EnableWebSecurity static class JwtAuthenticationManagerConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -2039,10 +1880,12 @@ public class OAuth2ResourceServerConfigurerTests { public AuthenticationProvider authenticationProvider() { return mock(AuthenticationProvider.class); } + } @EnableWebSecurity static class CustomJwtValidatorConfig extends WebSecurityConfigurerAdapter { + @Autowired NimbusJwtDecoder jwtDecoder; @@ -2062,17 +1905,19 @@ public class OAuth2ResourceServerConfigurerTests { public OAuth2TokenValidator getJwtValidator() { return this.jwtValidator; } + } @EnableWebSecurity static class UnexpiredJwtClockSkewConfig extends WebSecurityConfigurerAdapter { + @Autowired NimbusJwtDecoder jwtDecoder; @Override protected void configure(HttpSecurity http) throws Exception { - Clock nearlyAnHourFromTokenExpiry = - Clock.fixed(Instant.ofEpochMilli(4687181540000L), ZoneId.systemDefault()); + Clock nearlyAnHourFromTokenExpiry = Clock.fixed(Instant.ofEpochMilli(4687181540000L), + ZoneId.systemDefault()); JwtTimestampValidator jwtValidator = new JwtTimestampValidator(Duration.ofHours(1)); jwtValidator.setClock(nearlyAnHourFromTokenExpiry); @@ -2084,17 +1929,19 @@ public class OAuth2ResourceServerConfigurerTests { .jwt(); // @formatter:on } + } @EnableWebSecurity static class ExpiredJwtClockSkewConfig extends WebSecurityConfigurerAdapter { + @Autowired NimbusJwtDecoder jwtDecoder; @Override protected void configure(HttpSecurity http) throws Exception { - Clock justOverOneHourAfterExpiry = - Clock.fixed(Instant.ofEpochMilli(4687181595000L), ZoneId.systemDefault()); + Clock justOverOneHourAfterExpiry = Clock.fixed(Instant.ofEpochMilli(4687181595000L), + ZoneId.systemDefault()); JwtTimestampValidator jwtValidator = new JwtTimestampValidator(Duration.ofHours(1)); jwtValidator.setClock(justOverOneHourAfterExpiry); @@ -2132,14 +1979,16 @@ public class OAuth2ResourceServerConfigurerTests { @Bean JwtDecoder decoder() throws Exception { - RSAPublicKey publicKey = (RSAPublicKey) - KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(this.spec)); + RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA") + .generatePublic(new X509EncodedKeySpec(this.spec)); return withPublicKey(publicKey).build(); } + } @EnableWebSecurity static class CustomAuthenticationEventPublisher extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -2161,10 +2010,12 @@ public class OAuth2ResourceServerConfigurerTests { AuthenticationEventPublisher authenticationEventPublisher() { return mock(AuthenticationEventPublisher.class); } + } @EnableWebSecurity static class OpaqueTokenConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -2177,10 +2028,12 @@ public class OAuth2ResourceServerConfigurerTests { .opaqueToken(); // @formatter:on } + } @EnableWebSecurity static class OpaqueTokenInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -2196,10 +2049,12 @@ public class OAuth2ResourceServerConfigurerTests { ); // @formatter:on } + } @EnableWebSecurity static class OpaqueTokenAuthenticationManagerConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -2217,10 +2072,12 @@ public class OAuth2ResourceServerConfigurerTests { public AuthenticationProvider authenticationProvider() { return mock(AuthenticationProvider.class); } + } @EnableWebSecurity static class OpaqueTokenAuthenticationManagerInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -2243,10 +2100,12 @@ public class OAuth2ResourceServerConfigurerTests { public AuthenticationProvider authenticationProvider() { return mock(AuthenticationProvider.class); } + } @EnableWebSecurity static class OpaqueAndJwtConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -2257,10 +2116,12 @@ public class OAuth2ResourceServerConfigurerTests { .opaqueToken(); // @formatter:on } + } @EnableWebSecurity static class OpaqueTokenHalfConfiguredConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -2273,10 +2134,12 @@ public class OAuth2ResourceServerConfigurerTests { .introspectionUri("https://idp.example.com"); // missing credentials // @formatter:on } + } @EnableWebSecurity static class MultipleIssuersConfig extends WebSecurityConfigurerAdapter { + @Autowired MockWebServer web; @@ -2284,8 +2147,8 @@ public class OAuth2ResourceServerConfigurerTests { protected void configure(HttpSecurity http) throws Exception { String issuerOne = this.web.url("/issuerOne").toString(); String issuerTwo = this.web.url("/issuerTwo").toString(); - JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerAuthenticationManagerResolver(issuerOne, issuerTwo); + JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( + issuerOne, issuerTwo); // @formatter:off http @@ -2293,10 +2156,12 @@ public class OAuth2ResourceServerConfigurerTests { .authenticationManagerResolver(authenticationManagerResolver); // @formatter:on } + } @EnableWebSecurity static class AuthenticationManagerResolverPlusOtherConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -2309,18 +2174,22 @@ public class OAuth2ResourceServerConfigurerTests { .opaqueToken(); // @formatter:on } + } @Configuration static class JwtDecoderConfig { + @Bean public JwtDecoder jwtDecoder() { return mock(JwtDecoder.class); } + } @RestController static class BasicController { + @GetMapping("/") public String get() { return "ok"; @@ -2338,9 +2207,8 @@ public class OAuth2ResourceServerConfigurerTests { @GetMapping("/requires-read-scope") public String requiresReadScope(JwtAuthenticationToken token) { - return token.getAuthorities().stream() - .map(GrantedAuthority::getAuthority) - .collect(Collectors.toList()).toString(); + return token.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()) + .toString(); } @GetMapping("/ms-requires-read-scope") @@ -2354,10 +2222,12 @@ public class OAuth2ResourceServerConfigurerTests { public String deny() { return "hmm, that's odd"; } + } @Configuration static class WebServerConfig implements BeanPostProcessor, EnvironmentAware { + private final MockWebServer server = new MockWebServer(); @PreDestroy @@ -2368,8 +2238,8 @@ public class OAuth2ResourceServerConfigurerTests { @Override public void setEnvironment(Environment environment) { if (environment instanceof ConfigurableEnvironment) { - ((ConfigurableEnvironment) environment) - .getPropertySources().addFirst(new MockWebServerPropertySource()); + ((ConfigurableEnvironment) environment).getPropertySources() + .addFirst(new MockWebServerPropertySource()); } } @@ -2388,15 +2258,19 @@ public class OAuth2ResourceServerConfigurerTests { public Object getProperty(String name) { if ("mockwebserver.url".equals(name)) { return WebServerConfig.this.server.url("/.well-known/jwks.json").toString(); - } else { + } + else { return null; } } + } + } @Configuration static class RestOperationsConfig { + RestOperations rest = mock(RestOperations.class); @Bean @@ -2406,14 +2280,14 @@ public class OAuth2ResourceServerConfigurerTests { @Bean NimbusJwtDecoder jwtDecoder() { - return withJwkSetUri("https://example.org/.well-known/jwks.json") - .restOperations(this.rest).build(); + return withJwkSetUri("https://example.org/.well-known/jwks.json").restOperations(this.rest).build(); } @Bean NimbusOpaqueTokenIntrospector tokenIntrospectionClient() { return new NimbusOpaqueTokenIntrospector("https://example.org/introspect", this.rest); } + } private static void registerMockBean(GenericApplicationContext context, String name, Class clazz) { @@ -2421,6 +2295,7 @@ public class OAuth2ResourceServerConfigurerTests { } private static class BearerTokenRequestPostProcessor implements RequestPostProcessor { + private boolean asRequestParameter; private String token; @@ -2438,12 +2313,14 @@ public class OAuth2ResourceServerConfigurerTests { public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { if (this.asRequestParameter) { request.setParameter("access_token", this.token); - } else { + } + else { request.addHeader("Authorization", "Bearer " + this.token); } return request; } + } private static BearerTokenRequestPostProcessor bearerToken(String token) { @@ -2452,40 +2329,26 @@ public class OAuth2ResourceServerConfigurerTests { private static ResultMatcher invalidRequestHeader(String message) { return header().string(HttpHeaders.WWW_AUTHENTICATE, - AllOf.allOf( - new StringStartsWith("Bearer " + - "error=\"invalid_request\", " + - "error_description=\""), + AllOf.allOf(new StringStartsWith("Bearer " + "error=\"invalid_request\", " + "error_description=\""), new StringContains(message), - new StringEndsWith(", " + - "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"") - ) - ); + new StringEndsWith(", " + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\""))); } private static ResultMatcher invalidTokenHeader(String message) { return header().string(HttpHeaders.WWW_AUTHENTICATE, - AllOf.allOf( - new StringStartsWith("Bearer " + - "error=\"invalid_token\", " + - "error_description=\""), + AllOf.allOf(new StringStartsWith("Bearer " + "error=\"invalid_token\", " + "error_description=\""), new StringContains(message), - new StringEndsWith(", " + - "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"") - ) - ); + new StringEndsWith(", " + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\""))); } private static ResultMatcher insufficientScopeHeader() { - return header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer " + - "error=\"insufficient_scope\"" + - ", error_description=\"The request requires higher privileges than provided by the access token.\"" + - ", error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\""); + return header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer " + "error=\"insufficient_scope\"" + + ", error_description=\"The request requires higher privileges than provided by the access token.\"" + + ", error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\""); } private String jwkSet() { - return new JWKSet(new RSAKey.Builder(TestKeys.DEFAULT_PUBLIC_KEY) - .keyID("1").build()).toString(); + return new JWKSet(new RSAKey.Builder(TestKeys.DEFAULT_PUBLIC_KEY).keyID("1").build()).toString(); } private String jwtFromIssuer(String issuer) throws Exception { @@ -2493,18 +2356,15 @@ public class OAuth2ResourceServerConfigurerTests { claims.put(ISS, issuer); claims.put(SUB, "test-subject"); claims.put("scope", "message:read"); - JWSObject jws = new JWSObject( - new JWSHeader.Builder(JWSAlgorithm.RS256).keyID("1").build(), + JWSObject jws = new JWSObject(new JWSHeader.Builder(JWSAlgorithm.RS256).keyID("1").build(), new Payload(new JSONObject(claims))); jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY)); return jws.serialize(); } private void mockWebServer(String response) { - this.web.enqueue(new MockResponse() - .setResponseCode(200) - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(response)); + this.web.enqueue(new MockResponse().setResponseCode(200) + .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(response)); } private void mockRestOperations(String response) { @@ -2512,8 +2372,7 @@ public class OAuth2ResourceServerConfigurerTests { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); ResponseEntity entity = new ResponseEntity<>(response, headers, HttpStatus.OK); - when(rest.exchange(any(RequestEntity.class), eq(String.class))) - .thenReturn(entity); + when(rest.exchange(any(RequestEntity.class), eq(String.class))).thenReturn(entity); } private T bean(Class beanClass) { @@ -2539,8 +2398,9 @@ public class OAuth2ResourceServerConfigurerTests { private String resource(String suffix) throws IOException { String name = this.getClass().getSimpleName() + "-" + suffix; ClassPathResource resource = new ClassPathResource(name, this.getClass()); - try ( BufferedReader reader = new BufferedReader(new FileReader(resource.getFile())) ) { + try (BufferedReader reader = new BufferedReader(new FileReader(resource.getFile()))) { return reader.lines().collect(Collectors.joining()); } } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/openid/OpenIDLoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/openid/OpenIDLoginConfigurerTests.java index 159c54967e..3774aacf8d 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/openid/OpenIDLoginConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/openid/OpenIDLoginConfigurerTests.java @@ -71,8 +71,7 @@ public class OpenIDLoginConfigurerTests { ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class); this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(OpenIDAuthenticationFilter.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(OpenIDAuthenticationFilter.class)); } @Test @@ -80,12 +79,12 @@ public class OpenIDLoginConfigurerTests { ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class); this.spring.register(ObjectPostProcessorConfig.class).autowire(); - verify(ObjectPostProcessorConfig.objectPostProcessor) - .postProcess(any(OpenIDAuthenticationProvider.class)); + verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(OpenIDAuthenticationProvider.class)); } @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { + static ObjectPostProcessor objectPostProcessor; @Override @@ -100,21 +99,23 @@ public class OpenIDLoginConfigurerTests { static ObjectPostProcessor objectPostProcessor() { return objectPostProcessor; } + } static class ReflectingObjectPostProcessor implements ObjectPostProcessor { + @Override public O postProcess(O object) { return object; } + } @Test public void openidLoginWhenInvokedTwiceThenUsesOriginalLoginPage() throws Exception { this.spring.register(InvokeTwiceDoesNotOverrideConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isFound()) + this.mvc.perform(get("/")).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/login/custom")); } @@ -142,19 +143,20 @@ public class OpenIDLoginConfigurerTests { .openidLogin(); // @formatter:on } + } @Test public void requestWhenOpenIdLoginPageInLambdaThenRedirectsToLoginPAge() throws Exception { this.spring.register(OpenIdLoginPageInLambdaConfig.class).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isFound()) + this.mvc.perform(get("/")).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/login/custom")); } @EnableWebSecurity static class OpenIdLoginPageInLambdaConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -169,6 +171,7 @@ public class OpenIDLoginConfigurerTests { ); // @formatter:on } + } @Test @@ -177,43 +180,41 @@ public class OpenIDLoginConfigurerTests { AuthRequest mockAuthRequest = mock(AuthRequest.class); DiscoveryInformation mockDiscoveryInformation = mock(DiscoveryInformation.class); when(mockAuthRequest.getDestinationUrl(anyBoolean())).thenReturn("mockUrl"); - when(OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER.associate(any())) - .thenReturn(mockDiscoveryInformation); - when(OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(), any())) - .thenReturn(mockAuthRequest); + when(OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER.associate(any())).thenReturn(mockDiscoveryInformation); + when(OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(), + any())).thenReturn(mockAuthRequest); this.spring.register(OpenIdAttributesInLambdaConfig.class).autowire(); - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { String endpoint = server.url("/").toString(); - server.enqueue(new MockResponse() - .addHeader(YADIS_XRDS_LOCATION, endpoint)); + server.enqueue(new MockResponse().addHeader(YADIS_XRDS_LOCATION, endpoint)); server.enqueue(new MockResponse() .setBody(String.format("%s", endpoint))); - MvcResult mvcResult = this.mvc.perform(get("/login/openid") - .param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint)) - .andExpect(status().isFound()) - .andReturn(); + MvcResult mvcResult = this.mvc.perform( + get("/login/openid").param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint)) + .andExpect(status().isFound()).andReturn(); - Object attributeObject = mvcResult.getRequest().getSession().getAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST"); + Object attributeObject = mvcResult.getRequest().getSession() + .getAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST"); assertThat(attributeObject).isInstanceOf(List.class); List attributeList = (List) attributeObject; - assertThat(attributeList.stream().anyMatch(attribute -> - "nickname".equals(attribute.getName()) - && "https://schema.openid.net/namePerson/friendly".equals(attribute.getType()))) - .isTrue(); - assertThat(attributeList.stream().anyMatch(attribute -> - "email".equals(attribute.getName()) + assertThat( + attributeList.stream() + .anyMatch(attribute -> "nickname".equals(attribute.getName()) + && "https://schema.openid.net/namePerson/friendly".equals(attribute.getType()))) + .isTrue(); + assertThat(attributeList.stream() + .anyMatch(attribute -> "email".equals(attribute.getName()) && "https://schema.openid.net/contact/email".equals(attribute.getType()) - && attribute.isRequired() - && attribute.getCount() == 2)) - .isTrue(); + && attribute.isRequired() && attribute.getCount() == 2)).isTrue(); } } @EnableWebSecurity static class OpenIdAttributesInLambdaConfig extends WebSecurityConfigurerAdapter { + static ConsumerManager CONSUMER_MANAGER; @Override @@ -246,35 +247,33 @@ public class OpenIDLoginConfigurerTests { ); // @formatter:on } + } @Test - public void requestWhenAttributeNameNotSpecifiedThenAttributeNameDefaulted() - throws Exception { + public void requestWhenAttributeNameNotSpecifiedThenAttributeNameDefaulted() throws Exception { OpenIdAttributesNullNameConfig.CONSUMER_MANAGER = mock(ConsumerManager.class); AuthRequest mockAuthRequest = mock(AuthRequest.class); DiscoveryInformation mockDiscoveryInformation = mock(DiscoveryInformation.class); when(mockAuthRequest.getDestinationUrl(anyBoolean())).thenReturn("mockUrl"); - when(OpenIdAttributesNullNameConfig.CONSUMER_MANAGER.associate(any())) - .thenReturn(mockDiscoveryInformation); - when(OpenIdAttributesNullNameConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(), any())) - .thenReturn(mockAuthRequest); + when(OpenIdAttributesNullNameConfig.CONSUMER_MANAGER.associate(any())).thenReturn(mockDiscoveryInformation); + when(OpenIdAttributesNullNameConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(), + any())).thenReturn(mockAuthRequest); this.spring.register(OpenIdAttributesNullNameConfig.class).autowire(); - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { String endpoint = server.url("/").toString(); - server.enqueue(new MockResponse() - .addHeader(YADIS_XRDS_LOCATION, endpoint)); + server.enqueue(new MockResponse().addHeader(YADIS_XRDS_LOCATION, endpoint)); server.enqueue(new MockResponse() .setBody(String.format("%s", endpoint))); - MvcResult mvcResult = this.mvc.perform(get("/login/openid") - .param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint)) - .andExpect(status().isFound()) - .andReturn(); + MvcResult mvcResult = this.mvc.perform( + get("/login/openid").param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint)) + .andExpect(status().isFound()).andReturn(); - Object attributeObject = mvcResult.getRequest().getSession().getAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST"); + Object attributeObject = mvcResult.getRequest().getSession() + .getAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST"); assertThat(attributeObject).isInstanceOf(List.class); List attributeList = (List) attributeObject; assertThat(attributeList).hasSize(1); @@ -284,6 +283,7 @@ public class OpenIDLoginConfigurerTests { @EnableWebSecurity static class OpenIdAttributesNullNameConfig extends WebSecurityConfigurerAdapter { + static ConsumerManager CONSUMER_MANAGER; @Override @@ -305,5 +305,7 @@ public class OpenIDLoginConfigurerTests { ); // @formatter:on } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java index 598f5bf09c..18b9e86c4e 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java @@ -102,13 +102,15 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. */ public class Saml2LoginConfigurerTests { - private static final Converter> - AUTHORITIES_EXTRACTOR = a -> Arrays.asList(new SimpleGrantedAuthority("TEST")); - private static final GrantedAuthoritiesMapper AUTHORITIES_MAPPER = - authorities -> Arrays.asList(new SimpleGrantedAuthority("TEST CONVERTED")); + private static final Converter> AUTHORITIES_EXTRACTOR = a -> Arrays + .asList(new SimpleGrantedAuthority("TEST")); + + private static final GrantedAuthoritiesMapper AUTHORITIES_MAPPER = authorities -> Arrays + .asList(new SimpleGrantedAuthority("TEST CONVERTED")); + private static final Duration RESPONSE_TIME_VALIDATION_SKEW = Duration.ZERO; - private static final String SIGNED_RESPONSE = - "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOlJlc3BvbnNlIHhtbG5zOnNhbWwycD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9ycC5leGFtcGxlLm9yZy9hY3MiIElEPSJfYzE3MzM2YTAtNTM1My00MTQ5LWI3MmMtMDNkOWY5YWYzMDdlIiBJc3N1ZUluc3RhbnQ9IjIwMjAtMDgtMDRUMjI6MDQ6NDUuMDE2WiIgVmVyc2lvbj0iMi4wIj48c2FtbDI6SXNzdWVyIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj5hcC1lbnRpdHktaWQ8L3NhbWwyOklzc3Vlcj48ZHM6U2lnbmF0dXJlIHhtbG5zOmRzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj4KPGRzOlNpZ25lZEluZm8+CjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+CjxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNyc2Etc2hhMjU2Ii8+CjxkczpSZWZlcmVuY2UgVVJJPSIjX2MxNzMzNmEwLTUzNTMtNDE0OS1iNzJjLTAzZDlmOWFmMzA3ZSI+CjxkczpUcmFuc2Zvcm1zPgo8ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz4KPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPgo8L2RzOlRyYW5zZm9ybXM+CjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNzaGEyNTYiLz4KPGRzOkRpZ2VzdFZhbHVlPjYzTmlyenFzaDVVa0h1a3NuRWUrM0hWWU5aYWFsQW1OQXFMc1lGMlRuRDA9PC9kczpEaWdlc3RWYWx1ZT4KPC9kczpSZWZlcmVuY2U+CjwvZHM6U2lnbmVkSW5mbz4KPGRzOlNpZ25hdHVyZVZhbHVlPgpLMVlvWWJVUjBTclY4RTdVMkhxTTIvZUNTOTNoV25mOExnNnozeGZWMUlyalgzSXhWYkNvMVlYcnRBSGRwRVdvYTJKKzVOMmFNbFBHJiMxMzsKN2VpbDBZRC9xdUVRamRYbTNwQTBjZmEvY25pa2RuKzVhbnM0ZWQwanU1amo2dkpvZ2w2Smt4Q25LWUpwTU9HNzhtampmb0phengrWCYjMTM7CkM2NktQVStBYUdxeGVwUEQ1ZlhRdTFKSy9Jb3lBaitaa3k4Z2Jwc3VyZHFCSEJLRWxjdnVOWS92UGY0OGtBeFZBKzdtRGhNNUMvL1AmIzEzOwp0L084Y3NZYXB2UjZjdjZrdk45QXZ1N3FRdm9qVk1McHVxZWNJZDJwTUVYb0NSSnE2Nkd4MStNTUVPeHVpMWZZQlRoMEhhYjRmK3JyJiMxMzsKOEY2V1NFRC8xZllVeHliRkJqZ1Q4d2lEWHFBRU8wSVY4ZWRQeEE9PQo8L2RzOlNpZ25hdHVyZVZhbHVlPgo8L2RzOlNpZ25hdHVyZT48c2FtbDI6QXNzZXJ0aW9uIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBJRD0iQWUzZjQ5OGI4LTliMTctNDA3OC05ZDM1LTg2YTA4NDA4NDk5NSIgSXNzdWVJbnN0YW50PSIyMDIwLTA4LTA0VDIyOjA0OjQ1LjA3N1oiIFZlcnNpb249IjIuMCI+PHNhbWwyOklzc3Vlcj5hcC1lbnRpdHktaWQ8L3NhbWwyOklzc3Vlcj48c2FtbDI6U3ViamVjdD48c2FtbDI6TmFtZUlEPnRlc3RAc2FtbC51c2VyPC9zYW1sMjpOYW1lSUQ+PHNhbWwyOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48c2FtbDI6U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgTm90QmVmb3JlPSIyMDIwLTA4LTA0VDIxOjU5OjQ1LjA5MFoiIE5vdE9uT3JBZnRlcj0iMjA0MC0wNy0zMFQyMjowNTowNi4wODhaIiBSZWNpcGllbnQ9Imh0dHBzOi8vcnAuZXhhbXBsZS5vcmcvYWNzIi8+PC9zYW1sMjpTdWJqZWN0Q29uZmlybWF0aW9uPjwvc2FtbDI6U3ViamVjdD48c2FtbDI6Q29uZGl0aW9ucyBOb3RCZWZvcmU9IjIwMjAtMDgtMDRUMjE6NTk6NDUuMDgwWiIgTm90T25PckFmdGVyPSIyMDQwLTA3LTMwVDIyOjA1OjA2LjA4N1oiLz48L3NhbWwyOkFzc2VydGlvbj48L3NhbWwycDpSZXNwb25zZT4="; + + private static final String SIGNED_RESPONSE = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOlJlc3BvbnNlIHhtbG5zOnNhbWwycD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9ycC5leGFtcGxlLm9yZy9hY3MiIElEPSJfYzE3MzM2YTAtNTM1My00MTQ5LWI3MmMtMDNkOWY5YWYzMDdlIiBJc3N1ZUluc3RhbnQ9IjIwMjAtMDgtMDRUMjI6MDQ6NDUuMDE2WiIgVmVyc2lvbj0iMi4wIj48c2FtbDI6SXNzdWVyIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj5hcC1lbnRpdHktaWQ8L3NhbWwyOklzc3Vlcj48ZHM6U2lnbmF0dXJlIHhtbG5zOmRzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj4KPGRzOlNpZ25lZEluZm8+CjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+CjxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNyc2Etc2hhMjU2Ii8+CjxkczpSZWZlcmVuY2UgVVJJPSIjX2MxNzMzNmEwLTUzNTMtNDE0OS1iNzJjLTAzZDlmOWFmMzA3ZSI+CjxkczpUcmFuc2Zvcm1zPgo8ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz4KPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPgo8L2RzOlRyYW5zZm9ybXM+CjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNzaGEyNTYiLz4KPGRzOkRpZ2VzdFZhbHVlPjYzTmlyenFzaDVVa0h1a3NuRWUrM0hWWU5aYWFsQW1OQXFMc1lGMlRuRDA9PC9kczpEaWdlc3RWYWx1ZT4KPC9kczpSZWZlcmVuY2U+CjwvZHM6U2lnbmVkSW5mbz4KPGRzOlNpZ25hdHVyZVZhbHVlPgpLMVlvWWJVUjBTclY4RTdVMkhxTTIvZUNTOTNoV25mOExnNnozeGZWMUlyalgzSXhWYkNvMVlYcnRBSGRwRVdvYTJKKzVOMmFNbFBHJiMxMzsKN2VpbDBZRC9xdUVRamRYbTNwQTBjZmEvY25pa2RuKzVhbnM0ZWQwanU1amo2dkpvZ2w2Smt4Q25LWUpwTU9HNzhtampmb0phengrWCYjMTM7CkM2NktQVStBYUdxeGVwUEQ1ZlhRdTFKSy9Jb3lBaitaa3k4Z2Jwc3VyZHFCSEJLRWxjdnVOWS92UGY0OGtBeFZBKzdtRGhNNUMvL1AmIzEzOwp0L084Y3NZYXB2UjZjdjZrdk45QXZ1N3FRdm9qVk1McHVxZWNJZDJwTUVYb0NSSnE2Nkd4MStNTUVPeHVpMWZZQlRoMEhhYjRmK3JyJiMxMzsKOEY2V1NFRC8xZllVeHliRkJqZ1Q4d2lEWHFBRU8wSVY4ZWRQeEE9PQo8L2RzOlNpZ25hdHVyZVZhbHVlPgo8L2RzOlNpZ25hdHVyZT48c2FtbDI6QXNzZXJ0aW9uIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBJRD0iQWUzZjQ5OGI4LTliMTctNDA3OC05ZDM1LTg2YTA4NDA4NDk5NSIgSXNzdWVJbnN0YW50PSIyMDIwLTA4LTA0VDIyOjA0OjQ1LjA3N1oiIFZlcnNpb249IjIuMCI+PHNhbWwyOklzc3Vlcj5hcC1lbnRpdHktaWQ8L3NhbWwyOklzc3Vlcj48c2FtbDI6U3ViamVjdD48c2FtbDI6TmFtZUlEPnRlc3RAc2FtbC51c2VyPC9zYW1sMjpOYW1lSUQ+PHNhbWwyOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48c2FtbDI6U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgTm90QmVmb3JlPSIyMDIwLTA4LTA0VDIxOjU5OjQ1LjA5MFoiIE5vdE9uT3JBZnRlcj0iMjA0MC0wNy0zMFQyMjowNTowNi4wODhaIiBSZWNpcGllbnQ9Imh0dHBzOi8vcnAuZXhhbXBsZS5vcmcvYWNzIi8+PC9zYW1sMjpTdWJqZWN0Q29uZmlybWF0aW9uPjwvc2FtbDI6U3ViamVjdD48c2FtbDI6Q29uZGl0aW9ucyBOb3RCZWZvcmU9IjIwMjAtMDgtMDRUMjE6NTk6NDUuMDgwWiIgTm90T25PckFmdGVyPSIyMDQwLTA3LTMwVDIyOjA1OjA2LjA4N1oiLz48L3NhbWwyOkFzc2VydGlvbj48L3NhbWwycDpSZXNwb25zZT4="; @Autowired private ConfigurableApplicationContext context; @@ -129,7 +131,9 @@ public class Saml2LoginConfigurerTests { MockMvc mvc; private MockHttpServletRequest request; + private MockHttpServletResponse response; + private MockFilterChain filterChain; @Before @@ -155,7 +159,8 @@ public class Saml2LoginConfigurerTests { } @Test - public void saml2LoginWhenConfiguringAuthenticationDefaultsUsingCustomizerThenTheProviderIsConfigured() throws Exception { + public void saml2LoginWhenConfiguringAuthenticationDefaultsUsingCustomizerThenTheProviderIsConfigured() + throws Exception { // setup application context this.spring.register(Saml2LoginConfigWithAuthenticationDefaultsWithPostProcessor.class).autowire(); validateSaml2WebSsoAuthenticationFilterConfiguration(); @@ -166,12 +171,9 @@ public class Saml2LoginConfigurerTests { this.spring.register(CustomAuthenticationRequestContextResolver.class).autowire(); Saml2AuthenticationRequestContext context = authenticationRequestContext().build(); - Saml2AuthenticationRequestContextResolver resolver = - CustomAuthenticationRequestContextResolver.resolver; - when(resolver.resolve(any(HttpServletRequest.class))) - .thenReturn(context); - this.mvc.perform(get("/saml2/authenticate/registration-id")) - .andExpect(status().isFound()); + Saml2AuthenticationRequestContextResolver resolver = CustomAuthenticationRequestContextResolver.resolver; + when(resolver.resolve(any(HttpServletRequest.class))).thenReturn(context); + this.mvc.perform(get("/saml2/authenticate/registration-id")).andExpect(status().isFound()); verify(resolver).resolve(any(HttpServletRequest.class)); } @@ -179,10 +181,8 @@ public class Saml2LoginConfigurerTests { public void authenticationRequestWhenAuthnRequestConsumerResolverThenUses() throws Exception { this.spring.register(CustomAuthnRequestConsumerResolver.class).autowire(); - MvcResult result = this.mvc.perform(get("/saml2/authenticate/registration-id")) - .andReturn(); - UriComponents components = UriComponentsBuilder - .fromHttpUrl(result.getResponse().getRedirectedUrl()).build(); + MvcResult result = this.mvc.perform(get("/saml2/authenticate/registration-id")).andReturn(); + UriComponents components = UriComponentsBuilder.fromHttpUrl(result.getResponse().getRedirectedUrl()).build(); String samlRequest = components.getQueryParams().getFirst("SAMLRequest"); String decoded = URLDecoder.decode(samlRequest, "UTF-8"); String inflated = samlInflate(samlDecode(decoded)); @@ -193,79 +193,63 @@ public class Saml2LoginConfigurerTests { public void authenticateWhenCustomAuthenticationConverterThenUses() throws Exception { this.spring.register(CustomAuthenticationConverter.class).autowire(); RelyingPartyRegistration relyingPartyRegistration = noCredentials() - .assertingPartyDetails(party -> party - .verificationX509Credentials(c -> c.add(relyingPartyVerifyingCredential())) - ) + .assertingPartyDetails( + party -> party.verificationX509Credentials(c -> c.add(relyingPartyVerifyingCredential()))) .build(); String response = new String(samlDecode(SIGNED_RESPONSE)); when(CustomAuthenticationConverter.authenticationConverter.convert(any(HttpServletRequest.class))) .thenReturn(new Saml2AuthenticationToken(relyingPartyRegistration, response)); - this.mvc.perform(post("/login/saml2/sso/" + relyingPartyRegistration.getRegistrationId()) - .param("SAMLResponse", SIGNED_RESPONSE)) - .andExpect(redirectedUrl("/")); + this.mvc.perform(post("/login/saml2/sso/" + relyingPartyRegistration.getRegistrationId()).param("SAMLResponse", + SIGNED_RESPONSE)).andExpect(redirectedUrl("/")); verify(CustomAuthenticationConverter.authenticationConverter).convert(any(HttpServletRequest.class)); } private void validateSaml2WebSsoAuthenticationFilterConfiguration() { // get the OpenSamlAuthenticationProvider Saml2WebSsoAuthenticationFilter filter = getSaml2SsoFilter(this.springSecurityFilterChain); - AuthenticationManager manager = - (AuthenticationManager) ReflectionTestUtils.getField(filter, "authenticationManager"); + AuthenticationManager manager = (AuthenticationManager) ReflectionTestUtils.getField(filter, + "authenticationManager"); ProviderManager pm = (ProviderManager) manager; - AuthenticationProvider provider = pm.getProviders() - .stream() - .filter(p -> p instanceof OpenSamlAuthenticationProvider) - .findFirst() - .get(); + AuthenticationProvider provider = pm.getProviders().stream() + .filter(p -> p instanceof OpenSamlAuthenticationProvider).findFirst().get(); Assert.assertSame(AUTHORITIES_EXTRACTOR, ReflectionTestUtils.getField(provider, "authoritiesExtractor")); Assert.assertSame(AUTHORITIES_MAPPER, ReflectionTestUtils.getField(provider, "authoritiesMapper")); - Assert.assertSame(RESPONSE_TIME_VALIDATION_SKEW, ReflectionTestUtils.getField(provider, "responseTimeValidationSkew")); + Assert.assertSame(RESPONSE_TIME_VALIDATION_SKEW, + ReflectionTestUtils.getField(provider, "responseTimeValidationSkew")); } private Saml2WebSsoAuthenticationFilter getSaml2SsoFilter(FilterChainProxy chain) { - return (Saml2WebSsoAuthenticationFilter) chain.getFilters("/login/saml2/sso/test") - .stream() - .filter(f -> f instanceof Saml2WebSsoAuthenticationFilter) - .findFirst() - .get(); + return (Saml2WebSsoAuthenticationFilter) chain.getFilters("/login/saml2/sso/test").stream() + .filter(f -> f instanceof Saml2WebSsoAuthenticationFilter).findFirst().get(); } private void performSaml2Login(String expected) throws IOException, ServletException { // setup authentication parameters - this.request.setParameter( - "SAMLResponse", - Base64.getEncoder().encodeToString( - "saml2-xml-response-object".getBytes() - ) - ); - + this.request.setParameter("SAMLResponse", + Base64.getEncoder().encodeToString("saml2-xml-response-object".getBytes())); // perform test this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain); // assertions Authentication authentication = this.securityContextRepository - .loadContext(new HttpRequestResponseHolder(this.request, this.response)) - .getAuthentication(); + .loadContext(new HttpRequestResponseHolder(this.request, this.response)).getAuthentication(); Assert.assertNotNull("Expected a valid authentication object.", authentication); assertThat(authentication.getAuthorities()).hasSize(1); - assertThat(authentication.getAuthorities()).first() - .isInstanceOf(SimpleGrantedAuthority.class).hasToString(expected); + assertThat(authentication.getAuthorities()).first().isInstanceOf(SimpleGrantedAuthority.class) + .hasToString(expected); } - @EnableWebSecurity @Import(Saml2LoginConfigBeans.class) static class Saml2LoginConfigWithCustomAuthenticationManager extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { - http.saml2Login() - .authenticationManager( - getAuthenticationManagerMock("ROLE_AUTH_MANAGER") - ); + http.saml2Login().authenticationManager(getAuthenticationManagerMock("ROLE_AUTH_MANAGER")); super.configure(http); } + } @EnableWebSecurity @@ -274,8 +258,7 @@ public class Saml2LoginConfigurerTests { @Override protected void configure(HttpSecurity http) throws Exception { - ObjectPostProcessor processor - = new ObjectPostProcessor() { + ObjectPostProcessor processor = new ObjectPostProcessor() { @Override public O postProcess(O provider) { provider.setResponseTimeValidationSkew(RESPONSE_TIME_VALIDATION_SKEW); @@ -285,18 +268,18 @@ public class Saml2LoginConfigurerTests { } }; - http.saml2Login() - .addObjectPostProcessor(processor) - ; + http.saml2Login().addObjectPostProcessor(processor); super.configure(http); } + } @EnableWebSecurity @Import(Saml2LoginConfigBeans.class) static class CustomAuthenticationRequestContextResolver extends WebSecurityConfigurerAdapter { - private static final Saml2AuthenticationRequestContextResolver resolver = - mock(Saml2AuthenticationRequestContextResolver.class); + + private static final Saml2AuthenticationRequestContextResolver resolver = mock( + Saml2AuthenticationRequestContextResolver.class); @Override protected void configure(HttpSecurity http) throws Exception { @@ -313,6 +296,7 @@ public class Saml2LoginConfigurerTests { Saml2AuthenticationRequestContextResolver resolver() { return resolver; } + } @EnableWebSecurity @@ -332,47 +316,38 @@ public class Saml2LoginConfigurerTests { @Bean Saml2AuthenticationRequestFactory authenticationRequestFactory() { - OpenSamlAuthenticationRequestFactory authenticationRequestFactory = - new OpenSamlAuthenticationRequestFactory(); - authenticationRequestFactory.setAuthnRequestConsumerResolver( - context -> authnRequest -> authnRequest.setForceAuthn(true)); + OpenSamlAuthenticationRequestFactory authenticationRequestFactory = new OpenSamlAuthenticationRequestFactory(); + authenticationRequestFactory + .setAuthnRequestConsumerResolver(context -> authnRequest -> authnRequest.setForceAuthn(true)); return authenticationRequestFactory; } + } @EnableWebSecurity @Import(Saml2LoginConfigBeans.class) static class CustomAuthenticationConverter extends WebSecurityConfigurerAdapter { + static final AuthenticationConverter authenticationConverter = mock(AuthenticationConverter.class); @Override protected void configure(HttpSecurity http) throws Exception { - http - .authorizeRequests(authz -> authz - .anyRequest().authenticated() - ) - .saml2Login(saml2 -> saml2 - .authenticationConverter(authenticationConverter) - ); + http.authorizeRequests(authz -> authz.anyRequest().authenticated()) + .saml2Login(saml2 -> saml2.authenticationConverter(authenticationConverter)); } + } private static AuthenticationManager getAuthenticationManagerMock(String role) { return new AuthenticationManager() { @Override - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { throw new AuthenticationServiceException("not supported"); } - return new Saml2Authentication( - () -> "auth principal", - "saml2 response", - Collections.singletonList( - new SimpleGrantedAuthority(role) - ) - ); + return new Saml2Authentication(() -> "auth principal", "saml2 response", + Collections.singletonList(new SimpleGrantedAuthority(role))); } public boolean supports(Class authentication) { @@ -391,14 +366,14 @@ public class Saml2LoginConfigurerTests { @Bean RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() { RelyingPartyRegistrationRepository repository = mock(RelyingPartyRegistrationRepository.class); - when(repository.findByRegistrationId(anyString())) - .thenReturn(relyingPartyRegistration().build()); + when(repository.findByRegistrationId(anyString())).thenReturn(relyingPartyRegistration().build()); return repository; } + } - private static org.apache.commons.codec.binary.Base64 BASE64 = - new org.apache.commons.codec.binary.Base64(0, new byte[]{'\n'}); + private static org.apache.commons.codec.binary.Base64 BASE64 = new org.apache.commons.codec.binary.Base64(0, + new byte[] { '\n' }); private static byte[] samlDecode(String s) { return BASE64.decode(s); @@ -416,4 +391,5 @@ public class Saml2LoginConfigurerTests { throw new Saml2Exception("Unable to inflate string", e); } } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/TestSaml2Credentials.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/TestSaml2Credentials.java index 4a6922f4df..4c47cf13fb 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/TestSaml2Credentials.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/TestSaml2Credentials.java @@ -35,82 +35,77 @@ import static org.springframework.security.saml2.credentials.Saml2X509Credential public class TestSaml2Credentials { static Saml2X509Credential verificationCertificate() { - String certificate = "-----BEGIN CERTIFICATE-----\n" + - "MIIEEzCCAvugAwIBAgIJAIc1qzLrv+5nMA0GCSqGSIb3DQEBCwUAMIGfMQswCQYD\n" + - "VQQGEwJVUzELMAkGA1UECAwCQ08xFDASBgNVBAcMC0Nhc3RsZSBSb2NrMRwwGgYD\n" + - "VQQKDBNTYW1sIFRlc3RpbmcgU2VydmVyMQswCQYDVQQLDAJJVDEgMB4GA1UEAwwX\n" + - "c2ltcGxlc2FtbHBocC5jZmFwcHMuaW8xIDAeBgkqhkiG9w0BCQEWEWZoYW5pa0Bw\n" + - "aXZvdGFsLmlvMB4XDTE1MDIyMzIyNDUwM1oXDTI1MDIyMjIyNDUwM1owgZ8xCzAJ\n" + - "BgNVBAYTAlVTMQswCQYDVQQIDAJDTzEUMBIGA1UEBwwLQ2FzdGxlIFJvY2sxHDAa\n" + - "BgNVBAoME1NhbWwgVGVzdGluZyBTZXJ2ZXIxCzAJBgNVBAsMAklUMSAwHgYDVQQD\n" + - "DBdzaW1wbGVzYW1scGhwLmNmYXBwcy5pbzEgMB4GCSqGSIb3DQEJARYRZmhhbmlr\n" + - "QHBpdm90YWwuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4cn62\n" + - "E1xLqpN34PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz\n" + - "2ZivLwZXW+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWW\n" + - "RDodcoHEfDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQ\n" + - "nX8Ttl7hZ6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5\n" + - "cljz0X/TXy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gph\n" + - "iJH3jvZ7I+J5lS8VAgMBAAGjUDBOMB0GA1UdDgQWBBTTyP6Cc5HlBJ5+ucVCwGc5\n" + - "ogKNGzAfBgNVHSMEGDAWgBTTyP6Cc5HlBJ5+ucVCwGc5ogKNGzAMBgNVHRMEBTAD\n" + - "AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAvMS4EQeP/ipV4jOG5lO6/tYCb/iJeAduO\n" + - "nRhkJk0DbX329lDLZhTTL/x/w/9muCVcvLrzEp6PN+VWfw5E5FWtZN0yhGtP9R+v\n" + - "ZnrV+oc2zGD+no1/ySFOe3EiJCO5dehxKjYEmBRv5sU/LZFKZpozKN/BMEa6CqLu\n" + - "xbzb7ykxVr7EVFXwltPxzE9TmL9OACNNyF5eJHWMRMllarUvkcXlh4pux4ks9e6z\n" + - "V9DQBy2zds9f1I3qxg0eX6JnGrXi/ZiCT+lJgVe3ZFXiejiLAiKB04sXW3ti0LW3\n" + - "lx13Y1YlQ4/tlpgTgfIJxKV6nyPiLoK0nywbMd+vpAirDt2Oc+hk\n" + - "-----END CERTIFICATE-----"; - return new Saml2X509Credential( - x509Certificate(certificate), - VERIFICATION - ); + String certificate = "-----BEGIN CERTIFICATE-----\n" + + "MIIEEzCCAvugAwIBAgIJAIc1qzLrv+5nMA0GCSqGSIb3DQEBCwUAMIGfMQswCQYD\n" + + "VQQGEwJVUzELMAkGA1UECAwCQ08xFDASBgNVBAcMC0Nhc3RsZSBSb2NrMRwwGgYD\n" + + "VQQKDBNTYW1sIFRlc3RpbmcgU2VydmVyMQswCQYDVQQLDAJJVDEgMB4GA1UEAwwX\n" + + "c2ltcGxlc2FtbHBocC5jZmFwcHMuaW8xIDAeBgkqhkiG9w0BCQEWEWZoYW5pa0Bw\n" + + "aXZvdGFsLmlvMB4XDTE1MDIyMzIyNDUwM1oXDTI1MDIyMjIyNDUwM1owgZ8xCzAJ\n" + + "BgNVBAYTAlVTMQswCQYDVQQIDAJDTzEUMBIGA1UEBwwLQ2FzdGxlIFJvY2sxHDAa\n" + + "BgNVBAoME1NhbWwgVGVzdGluZyBTZXJ2ZXIxCzAJBgNVBAsMAklUMSAwHgYDVQQD\n" + + "DBdzaW1wbGVzYW1scGhwLmNmYXBwcy5pbzEgMB4GCSqGSIb3DQEJARYRZmhhbmlr\n" + + "QHBpdm90YWwuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4cn62\n" + + "E1xLqpN34PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz\n" + + "2ZivLwZXW+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWW\n" + + "RDodcoHEfDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQ\n" + + "nX8Ttl7hZ6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5\n" + + "cljz0X/TXy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gph\n" + + "iJH3jvZ7I+J5lS8VAgMBAAGjUDBOMB0GA1UdDgQWBBTTyP6Cc5HlBJ5+ucVCwGc5\n" + + "ogKNGzAfBgNVHSMEGDAWgBTTyP6Cc5HlBJ5+ucVCwGc5ogKNGzAMBgNVHRMEBTAD\n" + + "AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAvMS4EQeP/ipV4jOG5lO6/tYCb/iJeAduO\n" + + "nRhkJk0DbX329lDLZhTTL/x/w/9muCVcvLrzEp6PN+VWfw5E5FWtZN0yhGtP9R+v\n" + + "ZnrV+oc2zGD+no1/ySFOe3EiJCO5dehxKjYEmBRv5sU/LZFKZpozKN/BMEa6CqLu\n" + + "xbzb7ykxVr7EVFXwltPxzE9TmL9OACNNyF5eJHWMRMllarUvkcXlh4pux4ks9e6z\n" + + "V9DQBy2zds9f1I3qxg0eX6JnGrXi/ZiCT+lJgVe3ZFXiejiLAiKB04sXW3ti0LW3\n" + + "lx13Y1YlQ4/tlpgTgfIJxKV6nyPiLoK0nywbMd+vpAirDt2Oc+hk\n" + "-----END CERTIFICATE-----"; + return new Saml2X509Credential(x509Certificate(certificate), VERIFICATION); } static X509Certificate x509Certificate(String source) { try { final CertificateFactory factory = CertificateFactory.getInstance("X.509"); - return (X509Certificate) factory.generateCertificate( - new ByteArrayInputStream(source.getBytes(StandardCharsets.UTF_8)) - ); - } catch (Exception e) { + return (X509Certificate) factory + .generateCertificate(new ByteArrayInputStream(source.getBytes(StandardCharsets.UTF_8))); + } + catch (Exception e) { throw new IllegalArgumentException(e); } } static Saml2X509Credential signingCredential() { - String key = "-----BEGIN PRIVATE KEY-----\n" + - "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANG7v8QjQGU3MwQE\n" + - "VUBxvH6Uuiy/MhZT7TV0ZNjyAF2ExA1gpn3aUxx6jYK5UnrpxRRE/KbeLucYbOhK\n" + - "cDECt77Rggz5TStrOta0BQTvfluRyoQtmQ5Nkt6Vqg7O2ZapFt7k64Sal7AftzH6\n" + - "Q2BxWN1y04bLdDrH4jipqRj/2qEFAgMBAAECgYEAj4ExY1jjdN3iEDuOwXuRB+Nn\n" + - "x7pC4TgntE2huzdKvLJdGvIouTArce8A6JM5NlTBvm69mMepvAHgcsiMH1zGr5J5\n" + - "wJz23mGOyhM1veON41/DJTVG+cxq4soUZhdYy3bpOuXGMAaJ8QLMbQQoivllNihd\n" + - "vwH0rNSK8LTYWWPZYIECQQDxct+TFX1VsQ1eo41K0T4fu2rWUaxlvjUGhK6HxTmY\n" + - "8OMJptunGRJL1CUjIb45Uz7SP8TPz5FwhXWsLfS182kRAkEA3l+Qd9C9gdpUh1uX\n" + - "oPSNIxn5hFUrSTW1EwP9QH9vhwb5Vr8Jrd5ei678WYDLjUcx648RjkjhU9jSMzIx\n" + - "EGvYtQJBAMm/i9NR7IVyyNIgZUpz5q4LI21rl1r4gUQuD8vA36zM81i4ROeuCly0\n" + - "KkfdxR4PUfnKcQCX11YnHjk9uTFj75ECQEFY/gBnxDjzqyF35hAzrYIiMPQVfznt\n" + - "YX/sDTE2AdVBVGaMj1Cb51bPHnNC6Q5kXKQnj/YrLqRQND09Q7ParX0CQQC5NxZr\n" + - "9jKqhHj8yQD6PlXTsY4Occ7DH6/IoDenfdEVD5qlet0zmd50HatN2Jiqm5ubN7CM\n" + - "INrtuLp4YHbgk1mi\n" + - "-----END PRIVATE KEY-----"; - String certificate = "-----BEGIN CERTIFICATE-----\n" + - "MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMC\n" + - "VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEjAQBgNVBAcMCVZhbmNvdXZlcjEdMBsG\n" + - "A1UECgwUU3ByaW5nIFNlY3VyaXR5IFNBTUwxCzAJBgNVBAsMAnNwMSAwHgYDVQQD\n" + - "DBdzcC5zcHJpbmcuc2VjdXJpdHkuc2FtbDAeFw0xODA1MTQxNDMwNDRaFw0yODA1\n" + - "MTExNDMwNDRaMIGEMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjES\n" + - "MBAGA1UEBwwJVmFuY291dmVyMR0wGwYDVQQKDBRTcHJpbmcgU2VjdXJpdHkgU0FN\n" + - "TDELMAkGA1UECwwCc3AxIDAeBgNVBAMMF3NwLnNwcmluZy5zZWN1cml0eS5zYW1s\n" + - "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRu7/EI0BlNzMEBFVAcbx+lLos\n" + - "vzIWU+01dGTY8gBdhMQNYKZ92lMceo2CuVJ66cUURPym3i7nGGzoSnAxAre+0YIM\n" + - "+U0razrWtAUE735bkcqELZkOTZLelaoOztmWqRbe5OuEmpewH7cx+kNgcVjdctOG\n" + - "y3Q6x+I4qakY/9qhBQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAAeViTvHOyQopWEi\n" + - "XOfI2Z9eukwrSknDwq/zscR0YxwwqDBMt/QdAODfSwAfnciiYLkmEjlozWRtOeN+\n" + - "qK7UFgP1bRl5qksrYX5S0z2iGJh0GvonLUt3e20Ssfl5tTEDDnAEUMLfBkyaxEHD\n" + - "RZ/nbTJ7VTeZOSyRoVn5XHhpuJ0B\n" + - "-----END CERTIFICATE-----"; + String key = "-----BEGIN PRIVATE KEY-----\n" + + "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANG7v8QjQGU3MwQE\n" + + "VUBxvH6Uuiy/MhZT7TV0ZNjyAF2ExA1gpn3aUxx6jYK5UnrpxRRE/KbeLucYbOhK\n" + + "cDECt77Rggz5TStrOta0BQTvfluRyoQtmQ5Nkt6Vqg7O2ZapFt7k64Sal7AftzH6\n" + + "Q2BxWN1y04bLdDrH4jipqRj/2qEFAgMBAAECgYEAj4ExY1jjdN3iEDuOwXuRB+Nn\n" + + "x7pC4TgntE2huzdKvLJdGvIouTArce8A6JM5NlTBvm69mMepvAHgcsiMH1zGr5J5\n" + + "wJz23mGOyhM1veON41/DJTVG+cxq4soUZhdYy3bpOuXGMAaJ8QLMbQQoivllNihd\n" + + "vwH0rNSK8LTYWWPZYIECQQDxct+TFX1VsQ1eo41K0T4fu2rWUaxlvjUGhK6HxTmY\n" + + "8OMJptunGRJL1CUjIb45Uz7SP8TPz5FwhXWsLfS182kRAkEA3l+Qd9C9gdpUh1uX\n" + + "oPSNIxn5hFUrSTW1EwP9QH9vhwb5Vr8Jrd5ei678WYDLjUcx648RjkjhU9jSMzIx\n" + + "EGvYtQJBAMm/i9NR7IVyyNIgZUpz5q4LI21rl1r4gUQuD8vA36zM81i4ROeuCly0\n" + + "KkfdxR4PUfnKcQCX11YnHjk9uTFj75ECQEFY/gBnxDjzqyF35hAzrYIiMPQVfznt\n" + + "YX/sDTE2AdVBVGaMj1Cb51bPHnNC6Q5kXKQnj/YrLqRQND09Q7ParX0CQQC5NxZr\n" + + "9jKqhHj8yQD6PlXTsY4Occ7DH6/IoDenfdEVD5qlet0zmd50HatN2Jiqm5ubN7CM\n" + "INrtuLp4YHbgk1mi\n" + + "-----END PRIVATE KEY-----"; + String certificate = "-----BEGIN CERTIFICATE-----\n" + + "MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMC\n" + + "VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEjAQBgNVBAcMCVZhbmNvdXZlcjEdMBsG\n" + + "A1UECgwUU3ByaW5nIFNlY3VyaXR5IFNBTUwxCzAJBgNVBAsMAnNwMSAwHgYDVQQD\n" + + "DBdzcC5zcHJpbmcuc2VjdXJpdHkuc2FtbDAeFw0xODA1MTQxNDMwNDRaFw0yODA1\n" + + "MTExNDMwNDRaMIGEMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjES\n" + + "MBAGA1UEBwwJVmFuY291dmVyMR0wGwYDVQQKDBRTcHJpbmcgU2VjdXJpdHkgU0FN\n" + + "TDELMAkGA1UECwwCc3AxIDAeBgNVBAMMF3NwLnNwcmluZy5zZWN1cml0eS5zYW1s\n" + + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRu7/EI0BlNzMEBFVAcbx+lLos\n" + + "vzIWU+01dGTY8gBdhMQNYKZ92lMceo2CuVJ66cUURPym3i7nGGzoSnAxAre+0YIM\n" + + "+U0razrWtAUE735bkcqELZkOTZLelaoOztmWqRbe5OuEmpewH7cx+kNgcVjdctOG\n" + + "y3Q6x+I4qakY/9qhBQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAAeViTvHOyQopWEi\n" + + "XOfI2Z9eukwrSknDwq/zscR0YxwwqDBMt/QdAODfSwAfnciiYLkmEjlozWRtOeN+\n" + + "qK7UFgP1bRl5qksrYX5S0z2iGJh0GvonLUt3e20Ssfl5tTEDDnAEUMLfBkyaxEHD\n" + + "RZ/nbTJ7VTeZOSyRoVn5XHhpuJ0B\n" + "-----END CERTIFICATE-----"; PrivateKey pk = RsaKeyConverters.pkcs8().convert(new ByteArrayInputStream(key.getBytes())); X509Certificate cert = x509Certificate(certificate); return new Saml2X509Credential(pk, cert, SIGNING, DECRYPTION); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistryTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistryTests.java index 1893a4f082..698da20bba 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistryTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistryTests.java @@ -36,6 +36,7 @@ import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class MessageSecurityMetadataSourceRegistryTests { + @Mock private MessageMatcher matcher; @@ -46,11 +47,8 @@ public class MessageSecurityMetadataSourceRegistryTests { @Before public void setup() { messages = new MessageSecurityMetadataSourceRegistry(); - message = MessageBuilder - .withPayload("Hi") - .setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "location") - .setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, - SimpMessageType.MESSAGE).build(); + message = MessageBuilder.withPayload("Hi").setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "location") + .setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.MESSAGE).build(); } // See @@ -58,42 +56,30 @@ public class MessageSecurityMetadataSourceRegistryTests { // https://jira.spring.io/browse/SPR-11660 @Test public void simpDestMatchersCustom() { - message = MessageBuilder - .withPayload("Hi") - .setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, - "price.stock.1.2").build(); - messages.simpDestPathMatcher(new AntPathMatcher(".")) - .simpDestMatchers("price.stock.*").permitAll(); + message = MessageBuilder.withPayload("Hi") + .setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2").build(); + messages.simpDestPathMatcher(new AntPathMatcher(".")).simpDestMatchers("price.stock.*").permitAll(); assertThat(getAttribute()).isNull(); - message = MessageBuilder - .withPayload("Hi") - .setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, - "price.stock.1.2").build(); - messages.simpDestPathMatcher(new AntPathMatcher(".")) - .simpDestMatchers("price.stock.**").permitAll(); + message = MessageBuilder.withPayload("Hi") + .setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2").build(); + messages.simpDestPathMatcher(new AntPathMatcher(".")).simpDestMatchers("price.stock.**").permitAll(); assertThat(getAttribute()).isEqualTo("permitAll"); } @Test public void simpDestMatchersCustomSetAfterMatchersDoesNotMatter() { - message = MessageBuilder - .withPayload("Hi") - .setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, - "price.stock.1.2").build(); - messages.simpDestMatchers("price.stock.*").permitAll() - .simpDestPathMatcher(new AntPathMatcher(".")); + message = MessageBuilder.withPayload("Hi") + .setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2").build(); + messages.simpDestMatchers("price.stock.*").permitAll().simpDestPathMatcher(new AntPathMatcher(".")); assertThat(getAttribute()).isNull(); - message = MessageBuilder - .withPayload("Hi") - .setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, - "price.stock.1.2").build(); - messages.simpDestMatchers("price.stock.**").permitAll() - .simpDestPathMatcher(new AntPathMatcher(".")); + message = MessageBuilder.withPayload("Hi") + .setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "price.stock.1.2").build(); + messages.simpDestMatchers("price.stock.**").permitAll().simpDestPathMatcher(new AntPathMatcher(".")); assertThat(getAttribute()).isEqualTo("permitAll"); } @@ -127,32 +113,29 @@ public class MessageSecurityMetadataSourceRegistryTests { @Test public void simpDestMatchersMulti() { - messages.simpDestMatchers("admin/**", "api/**").hasRole("ADMIN") - .simpDestMatchers("location").permitAll(); + messages.simpDestMatchers("admin/**", "api/**").hasRole("ADMIN").simpDestMatchers("location").permitAll(); assertThat(getAttribute()).isEqualTo("permitAll"); } @Test public void simpDestMatchersRole() { - messages.simpDestMatchers("admin/**", "location/**").hasRole("ADMIN") - .anyMessage().denyAll(); + messages.simpDestMatchers("admin/**", "location/**").hasRole("ADMIN").anyMessage().denyAll(); assertThat(getAttribute()).isEqualTo("hasRole('ROLE_ADMIN')"); } @Test public void simpDestMatchersAnyRole() { - messages.simpDestMatchers("admin/**", "location/**").hasAnyRole("ADMIN", "ROOT") - .anyMessage().denyAll(); + messages.simpDestMatchers("admin/**", "location/**").hasAnyRole("ADMIN", "ROOT").anyMessage().denyAll(); assertThat(getAttribute()).isEqualTo("hasAnyRole('ROLE_ADMIN','ROLE_ROOT')"); } @Test public void simpDestMatchersAuthority() { - messages.simpDestMatchers("admin/**", "location/**").hasAuthority("ROLE_ADMIN") - .anyMessage().fullyAuthenticated(); + messages.simpDestMatchers("admin/**", "location/**").hasAuthority("ROLE_ADMIN").anyMessage() + .fullyAuthenticated(); assertThat(getAttribute()).isEqualTo("hasAuthority('ROLE_ADMIN')"); } @@ -160,48 +143,43 @@ public class MessageSecurityMetadataSourceRegistryTests { @Test public void simpDestMatchersAccess() { String expected = "hasRole('ROLE_ADMIN') and fullyAuthenticated"; - messages.simpDestMatchers("admin/**", "location/**").access(expected) - .anyMessage().denyAll(); + messages.simpDestMatchers("admin/**", "location/**").access(expected).anyMessage().denyAll(); assertThat(getAttribute()).isEqualTo(expected); } @Test public void simpDestMatchersAnyAuthority() { - messages.simpDestMatchers("admin/**", "location/**") - .hasAnyAuthority("ROLE_ADMIN", "ROLE_ROOT").anyMessage().denyAll(); + messages.simpDestMatchers("admin/**", "location/**").hasAnyAuthority("ROLE_ADMIN", "ROLE_ROOT").anyMessage() + .denyAll(); assertThat(getAttribute()).isEqualTo("hasAnyAuthority('ROLE_ADMIN','ROLE_ROOT')"); } @Test public void simpDestMatchersRememberMe() { - messages.simpDestMatchers("admin/**", "location/**").rememberMe().anyMessage() - .denyAll(); + messages.simpDestMatchers("admin/**", "location/**").rememberMe().anyMessage().denyAll(); assertThat(getAttribute()).isEqualTo("rememberMe"); } @Test public void simpDestMatchersAnonymous() { - messages.simpDestMatchers("admin/**", "location/**").anonymous().anyMessage() - .denyAll(); + messages.simpDestMatchers("admin/**", "location/**").anonymous().anyMessage().denyAll(); assertThat(getAttribute()).isEqualTo("anonymous"); } @Test public void simpDestMatchersFullyAuthenticated() { - messages.simpDestMatchers("admin/**", "location/**").fullyAuthenticated() - .anyMessage().denyAll(); + messages.simpDestMatchers("admin/**", "location/**").fullyAuthenticated().anyMessage().denyAll(); assertThat(getAttribute()).isEqualTo("fullyAuthenticated"); } @Test public void simpDestMatchersDenyAll() { - messages.simpDestMatchers("admin/**", "location/**").denyAll().anyMessage() - .permitAll(); + messages.simpDestMatchers("admin/**", "location/**").denyAll().anyMessage().permitAll(); assertThat(getAttribute()).isEqualTo("denyAll"); } @@ -215,29 +193,24 @@ public class MessageSecurityMetadataSourceRegistryTests { @Test public void simpDestMessageMatchersMatch() { - messages.simpMessageDestMatchers("location/**").denyAll().anyMessage() - .permitAll(); + messages.simpMessageDestMatchers("location/**").denyAll().anyMessage().permitAll(); assertThat(getAttribute()).isEqualTo("denyAll"); } @Test public void simpDestSubscribeMatchersNotMatch() { - messages.simpSubscribeDestMatchers("location/**").denyAll().anyMessage() - .permitAll(); + messages.simpSubscribeDestMatchers("location/**").denyAll().anyMessage().permitAll(); assertThat(getAttribute()).isEqualTo("permitAll"); } @Test public void simpDestSubscribeMatchersMatch() { - message = MessageBuilder - .fromMessage(message) - .setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, - SimpMessageType.SUBSCRIBE).build(); + message = MessageBuilder.fromMessage(message) + .setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.SUBSCRIBE).build(); - messages.simpSubscribeDestMatchers("location/**").denyAll().anyMessage() - .permitAll(); + messages.simpSubscribeDestMatchers("location/**").denyAll().anyMessage().permitAll(); assertThat(getAttribute()).isEqualTo("denyAll"); } @@ -251,10 +224,8 @@ public class MessageSecurityMetadataSourceRegistryTests { @Test public void nullDestMatcherMatch() { - message = MessageBuilder - .withPayload("Hi") - .setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, - SimpMessageType.CONNECT).build(); + message = MessageBuilder.withPayload("Hi") + .setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.CONNECT).build(); messages.nullDestMatcher().denyAll().anyMessage().permitAll(); @@ -263,32 +234,29 @@ public class MessageSecurityMetadataSourceRegistryTests { @Test public void simpTypeMatchersMatch() { - messages.simpTypeMatchers(SimpMessageType.MESSAGE).denyAll().anyMessage() - .permitAll(); + messages.simpTypeMatchers(SimpMessageType.MESSAGE).denyAll().anyMessage().permitAll(); assertThat(getAttribute()).isEqualTo("denyAll"); } @Test public void simpTypeMatchersMatchMulti() { - messages.simpTypeMatchers(SimpMessageType.CONNECT, SimpMessageType.MESSAGE) - .denyAll().anyMessage().permitAll(); + messages.simpTypeMatchers(SimpMessageType.CONNECT, SimpMessageType.MESSAGE).denyAll().anyMessage().permitAll(); assertThat(getAttribute()).isEqualTo("denyAll"); } @Test public void simpTypeMatchersNotMatch() { - messages.simpTypeMatchers(SimpMessageType.CONNECT).denyAll().anyMessage() - .permitAll(); + messages.simpTypeMatchers(SimpMessageType.CONNECT).denyAll().anyMessage().permitAll(); assertThat(getAttribute()).isEqualTo("permitAll"); } @Test public void simpTypeMatchersNotMatchMulti() { - messages.simpTypeMatchers(SimpMessageType.CONNECT, SimpMessageType.DISCONNECT) - .denyAll().anyMessage().permitAll(); + messages.simpTypeMatchers(SimpMessageType.CONNECT, SimpMessageType.DISCONNECT).denyAll().anyMessage() + .permitAll(); assertThat(getAttribute()).isEqualTo("permitAll"); } @@ -302,4 +270,5 @@ public class MessageSecurityMetadataSourceRegistryTests { assertThat(attrs).hasSize(1); return attrs.iterator().next().toString(); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurityTests.java index 2c43f59c57..7284955211 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurityTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurityTests.java @@ -79,6 +79,7 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock @RunWith(SpringRunner.class) @SecurityTestExecutionListeners public class EnableWebFluxSecurityTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -89,15 +90,9 @@ public class EnableWebFluxSecurityTests { public void defaultRequiresAuthentication() { this.spring.register(Config.class).autowire(); - WebTestClient client = WebTestClientBuilder - .bindToWebFilters(this.springSecurityFilterChain) - .build(); + WebTestClient client = WebTestClientBuilder.bindToWebFilters(this.springSecurityFilterChain).build(); - client.get() - .uri("/") - .exchange() - .expectStatus().isUnauthorized() - .expectBody().isEmpty(); + client.get().uri("/").exchange().expectStatus().isUnauthorized().expectBody().isEmpty(); } // gh-4831 @@ -105,32 +100,19 @@ public class EnableWebFluxSecurityTests { public void defaultMediaAllThenUnAuthorized() { this.spring.register(Config.class).autowire(); - WebTestClient client = WebTestClientBuilder - .bindToWebFilters(this.springSecurityFilterChain) - .build(); + WebTestClient client = WebTestClientBuilder.bindToWebFilters(this.springSecurityFilterChain).build(); - client.get() - .uri("/") - .accept(MediaType.ALL) - .exchange() - .expectStatus().isUnauthorized() - .expectBody().isEmpty(); + client.get().uri("/").accept(MediaType.ALL).exchange().expectStatus().isUnauthorized().expectBody().isEmpty(); } @Test public void authenticateWhenBasicThenNoSession() { this.spring.register(Config.class).autowire(); - WebTestClient client = WebTestClientBuilder - .bindToWebFilters(this.springSecurityFilterChain) - .build(); + WebTestClient client = WebTestClientBuilder.bindToWebFilters(this.springSecurityFilterChain).build(); - FluxExchangeResult result = client.get() - .headers(headers -> headers.setBasicAuth("user", "password")) - .exchange() - .expectStatus() - .isOk() - .returnResult(String.class); + FluxExchangeResult result = client.get().headers(headers -> headers.setBasicAuth("user", "password")) + .exchange().expectStatus().isOk().returnResult(String.class); result.assertWithDiagnostics(() -> assertThat(result.getResponseCookies().isEmpty())); } @@ -140,46 +122,35 @@ public class EnableWebFluxSecurityTests { Authentication currentPrincipal = new TestingAuthenticationToken("user", "password", "ROLE_USER"); WebSessionServerSecurityContextRepository contextRepository = new WebSessionServerSecurityContextRepository(); SecurityContext context = new SecurityContextImpl(currentPrincipal); - WebTestClient client = WebTestClientBuilder.bindToWebFilters( - (exchange, chain) -> contextRepository.save(exchange, context) - .switchIfEmpty(chain.filter(exchange)) - .flatMap(e -> chain.filter(exchange)), - this.springSecurityFilterChain, - (exchange, chain) -> - ReactiveSecurityContextHolder.getContext() - .map(SecurityContext::getAuthentication) - .flatMap( principal -> exchange.getResponse() - .writeWith(Mono.just(toDataBuffer(principal.getName())))) - ).build(); + WebTestClient client = WebTestClientBuilder + .bindToWebFilters( + (exchange, chain) -> contextRepository.save(exchange, context) + .switchIfEmpty(chain.filter(exchange)).flatMap(e -> chain.filter(exchange)), + this.springSecurityFilterChain, + (exchange, + chain) -> ReactiveSecurityContextHolder.getContext() + .map(SecurityContext::getAuthentication).flatMap(principal -> exchange + .getResponse().writeWith(Mono.just(toDataBuffer(principal.getName()))))) + .build(); - client - .get() - .uri("/") - .exchange() - .expectStatus().isOk() - .expectBody(String.class).consumeWith( result -> assertThat(result.getResponseBody()).isEqualTo(currentPrincipal.getName())); + client.get().uri("/").exchange().expectStatus().isOk().expectBody(String.class) + .consumeWith(result -> assertThat(result.getResponseBody()).isEqualTo(currentPrincipal.getName())); } @Test public void defaultPopulatesReactorContextWhenAuthenticating() { this.spring.register(Config.class).autowire(); - WebTestClient client = WebTestClientBuilder.bindToWebFilters( - this.springSecurityFilterChain, - (exchange, chain) -> - ReactiveSecurityContextHolder.getContext() - .map(SecurityContext::getAuthentication) - .flatMap( principal -> exchange.getResponse() - .writeWith(Mono.just(toDataBuffer(principal.getName())))) - ) - .build(); + WebTestClient client = WebTestClientBuilder + .bindToWebFilters(this.springSecurityFilterChain, + (exchange, + chain) -> ReactiveSecurityContextHolder.getContext() + .map(SecurityContext::getAuthentication).flatMap(principal -> exchange + .getResponse().writeWith(Mono.just(toDataBuffer(principal.getName()))))) + .build(); - client - .get() - .uri("/") - .headers(headers -> headers.setBasicAuth("user", "password")) - .exchange() - .expectStatus().isOk() - .expectBody(String.class).consumeWith( result -> assertThat(result.getResponseBody()).isEqualTo("user")); + client.get().uri("/").headers(headers -> headers.setBasicAuth("user", "password")).exchange().expectStatus() + .isOk().expectBody(String.class) + .consumeWith(result -> assertThat(result.getResponseBody()).isEqualTo("user")); } @Test @@ -187,52 +158,47 @@ public class EnableWebFluxSecurityTests { this.spring.register(Config.class).autowire(); ConfigurableApplicationContext context = this.spring.getContext(); - CsrfRequestDataValueProcessor rdvp = context.getBean(AbstractView.REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME, CsrfRequestDataValueProcessor.class); + CsrfRequestDataValueProcessor rdvp = context.getBean(AbstractView.REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME, + CsrfRequestDataValueProcessor.class); assertThat(rdvp).isNotNull(); } @EnableWebFluxSecurity @Import(ReactiveAuthenticationTestConfiguration.class) static class Config { + } @Test public void passwordEncoderBeanIsUsed() { this.spring.register(CustomPasswordEncoderConfig.class).autowire(); - WebTestClient client = WebTestClientBuilder.bindToWebFilters( - this.springSecurityFilterChain, - (exchange, chain) -> - ReactiveSecurityContextHolder.getContext() - .map(SecurityContext::getAuthentication) - .flatMap( principal -> exchange.getResponse() - .writeWith(Mono.just(toDataBuffer(principal.getName())))) - ) - .build(); + WebTestClient client = WebTestClientBuilder + .bindToWebFilters(this.springSecurityFilterChain, + (exchange, + chain) -> ReactiveSecurityContextHolder.getContext() + .map(SecurityContext::getAuthentication).flatMap(principal -> exchange + .getResponse().writeWith(Mono.just(toDataBuffer(principal.getName()))))) + .build(); - client - .get() - .uri("/") - .headers(headers -> headers.setBasicAuth("user", "password")) - .exchange() - .expectStatus().isOk() - .expectBody(String.class).consumeWith( result -> assertThat(result.getResponseBody()).isEqualTo("user")); + client.get().uri("/").headers(headers -> headers.setBasicAuth("user", "password")).exchange().expectStatus() + .isOk().expectBody(String.class) + .consumeWith(result -> assertThat(result.getResponseBody()).isEqualTo("user")); } @EnableWebFluxSecurity static class CustomPasswordEncoderConfig { + @Bean public ReactiveUserDetailsService userDetailsService(PasswordEncoder encoder) { - return new MapReactiveUserDetailsService(User.withUsername("user") - .password(encoder.encode("password")) - .roles("USER") - .build() - ); + return new MapReactiveUserDetailsService( + User.withUsername("user").password(encoder.encode("password")).roles("USER").build()); } @Bean public static PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } + } @Test @@ -240,12 +206,7 @@ public class EnableWebFluxSecurityTests { this.spring.register(MapReactiveUserDetailsServiceConfig.class).autowire(); WebTestClient client = WebTestClientBuilder.bindToWebFilters(this.springSecurityFilterChain).build(); - client - .get() - .uri("/") - .headers(h -> h.setBasicAuth("user", "password")) - .exchange() - .expectStatus().isOk(); + client.get().uri("/").headers(h -> h.setBasicAuth("user", "password")).exchange().expectStatus().isOk(); ReactiveUserDetailsService users = this.spring.getContext().getBean(ReactiveUserDetailsService.class); assertThat(users.findByUsername("user").block().getPassword()).startsWith("{bcrypt}"); @@ -253,6 +214,7 @@ public class EnableWebFluxSecurityTests { @EnableWebFluxSecurity static class MapReactiveUserDetailsServiceConfig { + @Bean public MapReactiveUserDetailsService userDetailsService() { // @formatter:off @@ -263,33 +225,22 @@ public class EnableWebFluxSecurityTests { // @formatter:on ); } + } @Test public void formLoginWorks() { this.spring.register(Config.class).autowire(); - WebTestClient client = WebTestClientBuilder.bindToWebFilters( - this.springSecurityFilterChain, - (exchange, chain) -> - Mono.subscriberContext() - .flatMap( c -> c.>get(Authentication.class)) - .flatMap( principal -> exchange.getResponse() - .writeWith(Mono.just(toDataBuffer(principal.getName())))) - ) - .build(); - + WebTestClient client = WebTestClientBuilder.bindToWebFilters(this.springSecurityFilterChain, (exchange, + chain) -> Mono.subscriberContext().flatMap(c -> c.>get(Authentication.class)).flatMap( + principal -> exchange.getResponse().writeWith(Mono.just(toDataBuffer(principal.getName()))))) + .build(); MultiValueMap data = new LinkedMultiValueMap<>(); data.add("username", "user"); data.add("password", "password"); - client - .mutateWith(csrf()) - .post() - .uri("/login") - .body(BodyInserters.fromFormData(data)) - .exchange() - .expectStatus().is3xxRedirection() - .expectHeader().valueMatches("Location", "/"); + client.mutateWith(csrf()).post().uri("/login").body(BodyInserters.fromFormData(data)).exchange().expectStatus() + .is3xxRedirection().expectHeader().valueMatches("Location", "/"); } @Test @@ -297,27 +248,20 @@ public class EnableWebFluxSecurityTests { this.spring.register(MultiSecurityHttpConfig.class).autowire(); WebTestClient client = WebTestClientBuilder.bindToWebFilters(this.springSecurityFilterChain).build(); - client.get() - .uri("/api/test") - .exchange() - .expectStatus().isUnauthorized() - .expectBody().isEmpty(); + client.get().uri("/api/test").exchange().expectStatus().isUnauthorized().expectBody().isEmpty(); - client.get() - .uri("/test") - .exchange() - .expectStatus().isOk(); + client.get().uri("/test").exchange().expectStatus().isOk(); } @EnableWebFluxSecurity @Import(ReactiveAuthenticationTestConfiguration.class) static class MultiSecurityHttpConfig { + @Order(Ordered.HIGHEST_PRECEDENCE) @Bean - public SecurityWebFilterChain apiHttpSecurity( - ServerHttpSecurity http) { - http.securityMatcher(new PathPatternParserServerWebExchangeMatcher("/api/**")) - .authorizeExchange().anyExchange().denyAll(); + public SecurityWebFilterChain apiHttpSecurity(ServerHttpSecurity http) { + http.securityMatcher(new PathPatternParserServerWebExchangeMatcher("/api/**")).authorizeExchange() + .anyExchange().denyAll(); return http.build(); } @@ -325,6 +269,7 @@ public class EnableWebFluxSecurityTests { public SecurityWebFilterChain httpSecurity(ServerHttpSecurity http) { return http.build(); } + } @Test @@ -334,14 +279,9 @@ public class EnableWebFluxSecurityTests { WebTestClient client = WebTestClient.bindToApplicationContext(this.spring.getContext()).build(); - client.get() - .uri("/spel") - .exchange() - .expectStatus().isOk() - .expectBody(String.class).isEqualTo("user"); + client.get().uri("/spel").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("user"); } - @EnableWebFluxSecurity @EnableWebFlux @Import(ReactiveAuthenticationTestConfiguration.class) @@ -353,18 +293,23 @@ public class EnableWebFluxSecurityTests { } static class PrincipalBean { + public String username(UserDetails user) { return user.getUsername(); } + } @RestController public static class AuthenticationPrincipalResolver { + @GetMapping("/spel") String username(@AuthenticationPrincipal(expression = "@principalBean.username(#this)") String username) { - return username; + return username; } + } + } private static DataBuffer toDataBuffer(String body) { @@ -386,6 +331,7 @@ public class EnableWebFluxSecurityTests { @EnableWebFluxSecurity @Import(ReactiveAuthenticationTestConfiguration.class) static class BeanProxyEnabledByDefaultConfig { + @Bean public Child child() { return new Child(); @@ -395,6 +341,7 @@ public class EnableWebFluxSecurityTests { public Parent parent() { return new Parent(child()); } + } @Test @@ -411,6 +358,7 @@ public class EnableWebFluxSecurityTests { @EnableWebFluxSecurity @Import(ReactiveAuthenticationTestConfiguration.class) static class BeanProxyDisabledConfig { + @Bean public Child child() { return new Child(); @@ -420,9 +368,11 @@ public class EnableWebFluxSecurityTests { public Parent parent() { return new Parent(child()); } + } static class Parent { + private Child child; Parent(Child child) { @@ -432,29 +382,35 @@ public class EnableWebFluxSecurityTests { public Child getChild() { return child; } + } static class Child { + Child() { } + } @Test // gh-8596 public void resolveAuthenticationPrincipalArgumentResolverFirstDoesNotCauseBeanCurrentlyInCreationException() { - this.spring.register(EnableWebFluxSecurityConfiguration.class, - ReactiveAuthenticationTestConfiguration.class, + this.spring.register(EnableWebFluxSecurityConfiguration.class, ReactiveAuthenticationTestConfiguration.class, DelegatingWebFluxConfiguration.class).autowire(); } @EnableWebFluxSecurity @Configuration(proxyBeanMethods = false) static class EnableWebFluxSecurityConfiguration { + /** - * It is necessary to Autowire AuthenticationPrincipalArgumentResolver because it triggers eager loading of - * AuthenticationPrincipalArgumentResolver bean which causes BeanCurrentlyInCreationException + * It is necessary to Autowire AuthenticationPrincipalArgumentResolver because it + * triggers eager loading of AuthenticationPrincipalArgumentResolver bean which + * causes BeanCurrentlyInCreationException */ @Autowired AuthenticationPrincipalArgumentResolver resolver; + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationBuilder.java b/config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationBuilder.java index f6703a9977..925b4e7552 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationBuilder.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationBuilder.java @@ -27,16 +27,17 @@ import org.springframework.security.core.userdetails.ReactiveUserDetailsService; * @since 5.0 */ public class ServerHttpSecurityConfigurationBuilder { + public static ServerHttpSecurity http() { return new ServerHttpSecurityConfiguration().httpSecurity(); } public static ServerHttpSecurity httpWithDefaultAuthentication() { ReactiveUserDetailsService reactiveUserDetailsService = ReactiveAuthenticationTestConfiguration - .userDetailsService(); + .userDetailsService(); ReactiveAuthenticationManager authenticationManager = new UserDetailsRepositoryReactiveAuthenticationManager( - reactiveUserDetailsService); - return http() - .authenticationManager(authenticationManager); + reactiveUserDetailsService); + return http().authenticationManager(authenticationManager); } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationTests.java index c7ae2e2d78..ae65f87f05 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationTests.java @@ -31,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Eleftheria Stein */ public class ServerHttpSecurityConfigurationTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -54,5 +55,7 @@ public class ServerHttpSecurityConfigurationTests { @Configuration static class SubclassConfig extends ServerHttpSecurityConfiguration { + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfigurationTests.java index 0eeec4140a..1b05578dbe 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfigurationTests.java @@ -31,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Eleftheria Stein */ public class WebFluxSecurityConfigurationTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -54,5 +55,7 @@ public class WebFluxSecurityConfigurationTests { @Configuration static class SubclassConfig extends WebFluxSecurityConfiguration { + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerDocTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerDocTests.java index 2343208681..fa82ac7ebe 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerDocTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerDocTests.java @@ -43,13 +43,13 @@ import org.springframework.web.socket.config.annotation.AbstractWebSocketMessage import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; - import java.util.HashMap; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; public class AbstractSecurityWebSocketMessageBrokerConfigurerDocTests { + AnnotationConfigWebApplicationContext context; TestingAuthenticationToken messageUser; @@ -76,8 +76,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerDocTests { public void securityMappings() { loadConfig(WebSocketSecurityConfig.class); - clientInboundChannel().send( - message("/user/queue/errors", SimpMessageType.SUBSCRIBE)); + clientInboundChannel().send(message("/user/queue/errors", SimpMessageType.SUBSCRIBE)); try { clientInboundChannel().send(message("/denyAll", SimpMessageType.MESSAGE)); @@ -124,11 +123,11 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerDocTests { public void authentication(@AuthenticationPrincipal String un) { // ... do something ... } + } @Configuration - static class WebSocketSecurityConfig extends - AbstractSecurityWebSocketMessageBrokerConfigurer { + static class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer { @Override protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) { @@ -138,12 +137,12 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerDocTests { // <2> .simpDestMatchers("/app/**").hasRole("USER") // <3> - .simpSubscribeDestMatchers("/user/**", "/topic/friends/*") - .hasRole("USER") // <4> + .simpSubscribeDestMatchers("/user/**", "/topic/friends/*").hasRole("USER") // <4> .simpTypeMatchers(MESSAGE, SUBSCRIBE).denyAll() // <5> .anyMessage().denyAll(); // <6> } + } @Configuration @@ -164,13 +163,17 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerDocTests { public MyController myController() { return new MyController(); } + } @Configuration static class SyncExecutorConfig { + @Bean public static SyncExecutorSubscribableChannelPostProcessor postProcessor() { return new SyncExecutorSubscribableChannelPostProcessor(); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerTests.java index 2b4887acd6..00b04811c5 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerTests.java @@ -79,6 +79,7 @@ import org.springframework.web.socket.sockjs.transport.handler.SockJsWebSocketHa import org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession; public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { + AnnotationConfigWebApplicationContext context; TestingAuthenticationToken messageUser; @@ -161,8 +162,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { public void addsCsrfProtectionWhenNoAuthorization() { loadConfig(NoInboundSecurityConfig.class); - SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor - .create(SimpMessageType.CONNECT); + SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT); Message message = message(headers, "/authentication"); MessageChannel messageChannel = clientInboundChannel(); @@ -179,8 +179,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { public void csrfProtectionForConnect() { loadConfig(SockJsSecurityConfig.class); - SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor - .create(SimpMessageType.CONNECT); + SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT); Message message = message(headers, "/authentication"); MessageChannel messageChannel = clientInboundChannel(); @@ -197,8 +196,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { public void csrfProtectionDisabledForConnect() { loadConfig(CsrfDisabledSockJsSecurityConfig.class); - SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor - .create(SimpMessageType.CONNECT); + SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT); Message message = message(headers, "/permitAll/connect"); MessageChannel messageChannel = clientInboundChannel(); @@ -220,8 +218,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { loadConfig(SockJsSecurityConfig.class); - SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor - .create(SimpMessageType.CONNECT); + SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT); Message message = message(headers, "/authentication"); MockHttpServletRequest request = sockjsHttpRequest("/chat"); HttpRequestHandler handler = handler(request); @@ -232,12 +229,10 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { } @Test - public void messagesConnectUseCsrfTokenHandshakeInterceptorMultipleMappings() - throws Exception { + public void messagesConnectUseCsrfTokenHandshakeInterceptorMultipleMappings() throws Exception { loadConfig(SockJsSecurityConfig.class); - SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor - .create(SimpMessageType.CONNECT); + SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT); Message message = message(headers, "/authentication"); MockHttpServletRequest request = sockjsHttpRequest("/other"); HttpRequestHandler handler = handler(request); @@ -248,12 +243,10 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { } @Test - public void messagesConnectWebSocketUseCsrfTokenHandshakeInterceptor() - throws Exception { + public void messagesConnectWebSocketUseCsrfTokenHandshakeInterceptor() throws Exception { loadConfig(WebSocketSecurityConfig.class); - SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor - .create(SimpMessageType.CONNECT); + SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT); Message message = message(headers, "/authentication"); MockHttpServletRequest request = websocketHttpRequest("/websocket"); HttpRequestHandler handler = handler(request); @@ -281,8 +274,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { @Configuration @EnableWebSocketMessageBroker @Import(SyncExecutorConfig.class) - static class MsmsRegistryCustomPatternMatcherConfig extends - AbstractSecurityWebSocketMessageBrokerConfigurer { + static class MsmsRegistryCustomPatternMatcherConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer { // @formatter:off public void registerStompEndpoints(StompEndpointRegistry registry) { @@ -312,6 +304,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { public TestHandshakeHandler testHandshakeHandler() { return new TestHandshakeHandler(); } + } @Test @@ -332,8 +325,8 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { @Configuration @EnableWebSocketMessageBroker @Import(SyncExecutorConfig.class) - static class OverrideMsmsRegistryCustomPatternMatcherConfig extends - AbstractSecurityWebSocketMessageBrokerConfigurer { + static class OverrideMsmsRegistryCustomPatternMatcherConfig + extends AbstractSecurityWebSocketMessageBrokerConfigurer { // @formatter:off public void registerStompEndpoints(StompEndpointRegistry registry) { @@ -343,7 +336,6 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { } // @formatter:on - // @formatter:off @Override protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) { @@ -365,6 +357,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { public TestHandshakeHandler testHandshakeHandler() { return new TestHandshakeHandler(); } + } @Test @@ -385,8 +378,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { @Configuration @EnableWebSocketMessageBroker @Import(SyncExecutorConfig.class) - static class DefaultPatternMatcherConfig extends - AbstractSecurityWebSocketMessageBrokerConfigurer { + static class DefaultPatternMatcherConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer { // @formatter:off public void registerStompEndpoints(StompEndpointRegistry registry) { @@ -415,6 +407,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { public TestHandshakeHandler testHandshakeHandler() { return new TestHandshakeHandler(); } + } @Test @@ -439,8 +432,8 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { loadConfig(SockJsProxylessSecurityConfig.class); ChannelSecurityInterceptor channelSecurityInterceptor = context.getBean(ChannelSecurityInterceptor.class); - MessageSecurityMetadataSource messageSecurityMetadataSource = - context.getBean(MessageSecurityMetadataSource.class); + MessageSecurityMetadataSource messageSecurityMetadataSource = context + .getBean(MessageSecurityMetadataSource.class); assertThat(channelSecurityInterceptor.obtainSecurityMetadataSource()).isSameAs(messageSecurityMetadataSource); } @@ -450,8 +443,8 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { loadConfig(SockJsProxylessSecurityConfig.class); MessageChannel messageChannel = clientInboundChannel(); - SecurityContextChannelInterceptor securityContextChannelInterceptor = - context.getBean(SecurityContextChannelInterceptor.class); + SecurityContextChannelInterceptor securityContextChannelInterceptor = context + .getBean(SecurityContextChannelInterceptor.class); assertThat(((AbstractMessageChannel) messageChannel).getInterceptors()) .contains(securityContextChannelInterceptor); @@ -464,15 +457,13 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { MessageChannel messageChannel = clientInboundChannel(); ChannelSecurityInterceptor inboundChannelSecurity = context.getBean(ChannelSecurityInterceptor.class); - assertThat(((AbstractMessageChannel) messageChannel).getInterceptors()) - .contains(inboundChannelSecurity); + assertThat(((AbstractMessageChannel) messageChannel).getInterceptors()).contains(inboundChannelSecurity); } @Configuration @EnableWebSocketMessageBroker @Import(SyncExecutorConfig.class) - static class CustomExpressionConfig extends - AbstractSecurityWebSocketMessageBrokerConfigurer { + static class CustomExpressionConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer { // @formatter:off public void registerStompEndpoints(StompEndpointRegistry registry) { @@ -494,8 +485,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { public static SecurityExpressionHandler> messageSecurityExpressionHandler() { return new DefaultMessageSecurityExpressionHandler() { @Override - protected SecurityExpressionOperations createSecurityExpressionRoot( - Authentication authentication, + protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, Message invocation) { return new MessageSecurityExpressionRoot(authentication, invocation) { public boolean denyRob() { @@ -517,15 +507,14 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { public TestHandshakeHandler testHandshakeHandler() { return new TestHandshakeHandler(); } + } private void assertHandshake(HttpServletRequest request) { - TestHandshakeHandler handshakeHandler = context - .getBean(TestHandshakeHandler.class); - assertThat(handshakeHandler.attributes.get(CsrfToken.class.getName())).isSameAs( - token); - assertThat(handshakeHandler.attributes.get(sessionAttr)).isEqualTo( - request.getSession().getAttribute(sessionAttr)); + TestHandshakeHandler handshakeHandler = context.getBean(TestHandshakeHandler.class); + assertThat(handshakeHandler.attributes.get(CsrfToken.class.getName())).isSameAs(token); + assertThat(handshakeHandler.attributes.get(sessionAttr)) + .isEqualTo(request.getSession().getAttribute(sessionAttr)); } private HttpRequestHandler handler(HttpServletRequest request) throws Exception { @@ -542,8 +531,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { private MockHttpServletRequest sockjsHttpRequest(String mapping) { MockHttpServletRequest request = new MockHttpServletRequest("GET", ""); request.setMethod("GET"); - request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, - "/289/tpyx6mde/websocket"); + request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/289/tpyx6mde/websocket"); request.setRequestURI(mapping + "/289/tpyx6mde/websocket"); request.getSession().setAttribute(sessionAttr, "sessionValue"); @@ -583,6 +571,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { static class MyController { String authenticationPrincipal; + MyCustomArgument myCustomArgument; @MessageMapping("/authentication") @@ -594,11 +583,14 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { public void myCustom(MyCustomArgument myCustomArgument) { this.myCustomArgument = myCustomArgument; } + } static class MyCustomArgument { + MyCustomArgument(String notDefaultConstr) { } + } static class MyCustomArgumentResolver implements HandlerMethodArgumentResolver { @@ -610,13 +602,14 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { public Object resolveArgument(MethodParameter parameter, Message message) { return new MyCustomArgument(""); } + } static class TestHandshakeHandler implements HandshakeHandler { + Map attributes; - public boolean doHandshake(ServerHttpRequest request, - ServerHttpResponse response, WebSocketHandler wsHandler, + public boolean doHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) throws HandshakeFailureException { this.attributes = attributes; if (wsHandler instanceof SockJsWebSocketHandler) { @@ -628,20 +621,20 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { } return true; } + } @Configuration @EnableWebSocketMessageBroker @Import(SyncExecutorConfig.class) - static class SockJsSecurityConfig extends - AbstractSecurityWebSocketMessageBrokerConfigurer { + static class SockJsSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer { public void registerStompEndpoints(StompEndpointRegistry registry) { - registry.addEndpoint("/other").setHandshakeHandler(testHandshakeHandler()) - .withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor()); + registry.addEndpoint("/other").setHandshakeHandler(testHandshakeHandler()).withSockJS() + .setInterceptors(new HttpSessionHandshakeInterceptor()); - registry.addEndpoint("/chat").setHandshakeHandler(testHandshakeHandler()) - .withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor()); + registry.addEndpoint("/chat").setHandshakeHandler(testHandshakeHandler()).withSockJS() + .setInterceptors(new HttpSessionHandshakeInterceptor()); } // @formatter:off @@ -676,27 +669,27 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { } static class SecurityCheck { + private boolean check; public boolean check() { check = !check; return check; } + } + } @Configuration @EnableWebSocketMessageBroker @Import(SyncExecutorConfig.class) - static class NoInboundSecurityConfig extends - AbstractSecurityWebSocketMessageBrokerConfigurer { + static class NoInboundSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer { public void registerStompEndpoints(StompEndpointRegistry registry) { - registry.addEndpoint("/other").withSockJS() - .setInterceptors(new HttpSessionHandshakeInterceptor()); + registry.addEndpoint("/other").withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor()); - registry.addEndpoint("/chat").withSockJS() - .setInterceptors(new HttpSessionHandshakeInterceptor()); + registry.addEndpoint("/chat").withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor()); } @Override @@ -713,6 +706,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { public MyController myController() { return new MyController(); } + } @Configuration @@ -722,17 +716,16 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { protected boolean sameOriginDisabled() { return true; } + } @Configuration @EnableWebSocketMessageBroker @Import(SyncExecutorConfig.class) - static class WebSocketSecurityConfig extends - AbstractSecurityWebSocketMessageBrokerConfigurer { + static class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer { public void registerStompEndpoints(StompEndpointRegistry registry) { - registry.addEndpoint("/websocket") - .setHandshakeHandler(testHandshakeHandler()) + registry.addEndpoint("/websocket").setHandshakeHandler(testHandshakeHandler()) .addInterceptors(new HttpSessionHandshakeInterceptor()); } @@ -750,19 +743,19 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { public TestHandshakeHandler testHandshakeHandler() { return new TestHandshakeHandler(); } + } @Configuration(proxyBeanMethods = false) @EnableWebSocketMessageBroker @Import(SyncExecutorConfig.class) - static class SockJsProxylessSecurityConfig extends - AbstractSecurityWebSocketMessageBrokerConfigurer { + static class SockJsProxylessSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer { + private ApplicationContext context; public void registerStompEndpoints(StompEndpointRegistry registry) { - registry.addEndpoint("/chat") - .setHandshakeHandler(context.getBean(TestHandshakeHandler.class)) - .withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor()); + registry.addEndpoint("/chat").setHandshakeHandler(context.getBean(TestHandshakeHandler.class)).withSockJS() + .setInterceptors(new HttpSessionHandshakeInterceptor()); } @Autowired @@ -782,13 +775,17 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests { public TestHandshakeHandler testHandshakeHandler() { return new TestHandshakeHandler(); } + } @Configuration static class SyncExecutorConfig { + @Bean public static SyncExecutorSubscribableChannelPostProcessor postProcessor() { return new SyncExecutorSubscribableChannelPostProcessor(); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/socket/SyncExecutorSubscribableChannelPostProcessor.java b/config/src/test/java/org/springframework/security/config/annotation/web/socket/SyncExecutorSubscribableChannelPostProcessor.java index 6f3074f506..0462d5f74b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/socket/SyncExecutorSubscribableChannelPostProcessor.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/socket/SyncExecutorSubscribableChannelPostProcessor.java @@ -24,8 +24,7 @@ import org.springframework.messaging.support.ExecutorSubscribableChannel; */ public class SyncExecutorSubscribableChannelPostProcessor implements BeanPostProcessor { - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof ExecutorSubscribableChannel) { ExecutorSubscribableChannel original = (ExecutorSubscribableChannel) bean; ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel(); @@ -35,8 +34,8 @@ public class SyncExecutorSubscribableChannelPostProcessor implements BeanPostPro return bean; } - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } + } diff --git a/config/src/test/java/org/springframework/security/config/authentication/AuthenticationConfigurationGh3935Tests.java b/config/src/test/java/org/springframework/security/config/authentication/AuthenticationConfigurationGh3935Tests.java index 7b13b8f08e..95006401b7 100644 --- a/config/src/test/java/org/springframework/security/config/authentication/AuthenticationConfigurationGh3935Tests.java +++ b/config/src/test/java/org/springframework/security/config/authentication/AuthenticationConfigurationGh3935Tests.java @@ -48,10 +48,13 @@ import static org.mockito.Mockito.when; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class AuthenticationConfigurationGh3935Tests { + @Autowired FilterChainProxy springSecurityFilterChain; + @Autowired UserDetailsService uds; + @Autowired BootGlobalAuthenticationConfigurationAdapter adapter; @@ -70,8 +73,8 @@ public class AuthenticationConfigurationGh3935Tests { AuthenticationManager authenticationManager = this.adapter.authenticationManager; assertThat(authenticationManager).isNotNull(); - Authentication auth = authenticationManager.authenticate( - new UsernamePasswordAuthenticationToken(username, password)); + Authentication auth = authenticationManager + .authenticate(new UsernamePasswordAuthenticationToken(username, password)); verify(this.uds).loadUserByUsername(username); assertThat(auth.getPrincipal()).isEqualTo(PasswordEncodedUser.user()); @@ -79,10 +82,11 @@ public class AuthenticationConfigurationGh3935Tests { @EnableWebSecurity static class WebSecurity extends WebSecurityConfigurerAdapter { + } - static class BootGlobalAuthenticationConfigurationAdapter - extends GlobalAuthenticationConfigurerAdapter { + static class BootGlobalAuthenticationConfigurationAdapter extends GlobalAuthenticationConfigurerAdapter { + private final ApplicationContext context; private AuthenticationManager authenticationManager; @@ -94,17 +98,17 @@ public class AuthenticationConfigurationGh3935Tests { @Override public void init(AuthenticationManagerBuilder auth) throws Exception { - AuthenticationConfiguration configuration = this.context - .getBean(AuthenticationConfiguration.class); + AuthenticationConfiguration configuration = this.context.getBean(AuthenticationConfiguration.class); this.authenticationManager = configuration.getAuthenticationManager(); } + } @Configuration static class AutoConfig { + @Bean - static BootGlobalAuthenticationConfigurationAdapter adapter( - ApplicationContext context) { + static BootGlobalAuthenticationConfigurationAdapter adapter(ApplicationContext context) { return new BootGlobalAuthenticationConfigurationAdapter(context); } @@ -112,5 +116,7 @@ public class AuthenticationConfigurationGh3935Tests { public UserDetailsService userDetailsService() { return mock(UserDetailsService.class); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParserTests.java index 6d64ca25eb..e82840ad2c 100644 --- a/config/src/test/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParserTests.java @@ -38,37 +38,32 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * * @author Luke Taylor */ public class AuthenticationManagerBeanDefinitionParserTests { - private static final String CONTEXT = "" - + " " + + private static final String CONTEXT = "" + " " + " " + " " - + " " - + " " - + ""; + + " " + " " + ""; + @Rule public final SpringTestRule spring = new SpringTestRule(); @Test // SEC-1225 public void providersAreRegisteredAsTopLevelBeans() { - ConfigurableApplicationContext context = this.spring.context(CONTEXT) - .getContext(); + ConfigurableApplicationContext context = this.spring.context(CONTEXT).getContext(); assertThat(context.getBeansOfType(AuthenticationProvider.class)).hasSize(1); } @Test public void eventsArePublishedByDefault() throws Exception { - ConfigurableApplicationContext appContext = this.spring.context(CONTEXT) - .getContext(); + ConfigurableApplicationContext appContext = this.spring.context(CONTEXT).getContext(); AuthListener listener = new AuthListener(); appContext.addApplicationListener(listener); - ProviderManager pm = (ProviderManager) appContext - .getBeansOfType(ProviderManager.class).values().toArray()[0]; + ProviderManager pm = (ProviderManager) appContext.getBeansOfType(ProviderManager.class).values().toArray()[0]; Object eventPublisher = FieldUtils.getFieldValue(pm, "eventPublisher"); assertThat(eventPublisher).isNotNull(); assertThat(eventPublisher instanceof DefaultAuthenticationEventPublisher).isTrue(); @@ -79,19 +74,16 @@ public class AuthenticationManagerBeanDefinitionParserTests { @Test public void credentialsAreClearedByDefault() { - ConfigurableApplicationContext appContext = this.spring.context(CONTEXT) - .getContext(); - ProviderManager pm = (ProviderManager) appContext - .getBeansOfType(ProviderManager.class).values().toArray()[0]; + ConfigurableApplicationContext appContext = this.spring.context(CONTEXT).getContext(); + ProviderManager pm = (ProviderManager) appContext.getBeansOfType(ProviderManager.class).values().toArray()[0]; assertThat(pm.isEraseCredentialsAfterAuthentication()).isTrue(); } @Test public void clearCredentialsPropertyIsRespected() { - ConfigurableApplicationContext appContext = this.spring.context("") - .getContext(); - ProviderManager pm = (ProviderManager) appContext - .getBeansOfType(ProviderManager.class).values().toArray()[0]; + ConfigurableApplicationContext appContext = this.spring + .context("").getContext(); + ProviderManager pm = (ProviderManager) appContext.getBeansOfType(ProviderManager.class).values().toArray()[0]; assertThat(pm.isEraseCredentialsAfterAuthentication()).isFalse(); } @@ -100,24 +92,23 @@ public class AuthenticationManagerBeanDefinitionParserTests { @Test public void passwordEncoderBeanUsed() throws Exception { - this.spring.context("" - + "" - + " " - + "" - + "") - .mockMvcAfterSpringSecurityOk() - .autowire(); + this.spring.context( + "" + + "" + " " + + "" + "") + .mockMvcAfterSpringSecurityOk().autowire(); - this.mockMvc.perform(get("/").with(httpBasic("user", "password"))) - .andExpect(status().isOk()); + this.mockMvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isOk()); } - private static class AuthListener implements - ApplicationListener { + private static class AuthListener implements ApplicationListener { + List events = new ArrayList<>(); public void onApplicationEvent(AbstractAuthenticationEvent event) { this.events.add(event); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParserTests.java index 968f1f9ae1..cfd024341a 100644 --- a/config/src/test/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParserTests.java @@ -36,9 +36,10 @@ import java.util.List; * @author Luke Taylor */ public class AuthenticationProviderBeanDefinitionParserTests { + private AbstractXmlApplicationContext appContext; - private UsernamePasswordAuthenticationToken bob = new UsernamePasswordAuthenticationToken( - "bob", "bobspassword"); + + private UsernamePasswordAuthenticationToken bob = new UsernamePasswordAuthenticationToken("bob", "bobspassword"); @After public void closeAppContext() { @@ -49,8 +50,7 @@ public class AuthenticationProviderBeanDefinitionParserTests { @Test public void worksWithEmbeddedUserService() { - setContext(" " - + " " + setContext(" " + " " + " " + " " + " "); getProvider().authenticate(bob); @@ -59,10 +59,8 @@ public class AuthenticationProviderBeanDefinitionParserTests { @Test public void externalUserServiceRefWorks() { appContext = new InMemoryXmlApplicationContext( - " " - + " " - + " " - + " " + " " + " " + + " " + " " + " " + " "); getProvider().authenticate(bob); @@ -70,9 +68,7 @@ public class AuthenticationProviderBeanDefinitionParserTests { @Test public void providerWithBCryptPasswordEncoderWorks() { - setContext(" " - + " " - + " " + setContext(" " + " " + " " + " " + " " + " "); @@ -81,55 +77,35 @@ public class AuthenticationProviderBeanDefinitionParserTests { @Test public void providerWithMd5PasswordEncoderWorks() { - appContext = new InMemoryXmlApplicationContext( - " " - + " " - + " " - + " " + appContext = new InMemoryXmlApplicationContext(" " + " " + + " " + " " + " " - + " " - + " " - + " " - + " " - + " " - + " "); + + " " + " " + " " + + " " + + " " + " "); getProvider().authenticate(bob); } @Test public void providerWithShaPasswordEncoderWorks() { - appContext = new InMemoryXmlApplicationContext( - " " - + " " - + " " - + " " + appContext = new InMemoryXmlApplicationContext(" " + " " + + " " + " " + " " - + " " - + " " - + " " - + " "); + + " " + " " + " " + + " "); getProvider().authenticate(bob); } @Test public void passwordIsBase64EncodedWhenBase64IsEnabled() { - appContext = new InMemoryXmlApplicationContext( - " " - + " " - + " " - + " " + appContext = new InMemoryXmlApplicationContext(" " + " " + + " " + " " + " " - + " " - + " " - + " " - + " " - + " " - + " " + + " " + " " + " " + + " " + + " " + " " + " "); getProvider().authenticate(bob); @@ -138,26 +114,25 @@ public class AuthenticationProviderBeanDefinitionParserTests { // SEC-1466 @Test(expected = BeanDefinitionParsingException.class) public void exernalProviderDoesNotSupportChildElements() { - appContext = new InMemoryXmlApplicationContext( - " " - + " " - + " " - + " " - + " " - + " " - + " "); + appContext = new InMemoryXmlApplicationContext(" " + + " " + + " " + " " + + " " + + " " + + " "); } private AuthenticationProvider getProvider() { - List providers = ((ProviderManager) appContext - .getBean(BeanIds.AUTHENTICATION_MANAGER)).getProviders(); + List providers = ((ProviderManager) appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)) + .getProviders(); return providers.get(0); } private void setContext(String context) { - appContext = new InMemoryXmlApplicationContext("" - + context + ""); + appContext = new InMemoryXmlApplicationContext( + "" + context + ""); } + } diff --git a/config/src/test/java/org/springframework/security/config/authentication/JdbcUserServiceBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/authentication/JdbcUserServiceBeanDefinitionParserTests.java index 14b833cd24..30e9cbd29b 100644 --- a/config/src/test/java/org/springframework/security/config/authentication/JdbcUserServiceBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/authentication/JdbcUserServiceBeanDefinitionParserTests.java @@ -22,8 +22,7 @@ import org.w3c.dom.Element; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.ProviderManager; -import org.springframework.security.authentication - .UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.BeanIds; import org.springframework.security.config.util.InMemoryXmlApplicationContext; @@ -41,12 +40,11 @@ import static org.mockito.Mockito.mock; * @author Eddú Meléndez */ public class JdbcUserServiceBeanDefinitionParserTests { + private static String USER_CACHE_XML = ""; private static String DATA_SOURCE = " " - + " " - + " " - + + + " " + " " + " " + " " + " "; @@ -62,23 +60,20 @@ public class JdbcUserServiceBeanDefinitionParserTests { @Test public void beanNameIsCorrect() { - assertThat(JdbcUserDetailsManager.class.getName()).isEqualTo( - new JdbcUserServiceBeanDefinitionParser() - .getBeanClassName(mock(Element.class))); + assertThat(JdbcUserDetailsManager.class.getName()) + .isEqualTo(new JdbcUserServiceBeanDefinitionParser().getBeanClassName(mock(Element.class))); } @Test public void validUsernameIsFound() { setContext("" + DATA_SOURCE); - JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext - .getBean(BeanIds.USER_DETAILS_SERVICE); + JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean(BeanIds.USER_DETAILS_SERVICE); assertThat(mgr.loadUserByUsername("rod")).isNotNull(); } @Test public void beanIdIsParsedCorrectly() { - setContext("" - + DATA_SOURCE); + setContext("" + DATA_SOURCE); assertThat(appContext.getBean("myUserService") instanceof JdbcUserDetailsManager).isTrue(); } @@ -86,12 +81,10 @@ public class JdbcUserServiceBeanDefinitionParserTests { public void usernameAndAuthorityQueriesAreParsedCorrectly() throws Exception { String userQuery = "select username, password, true from users where username = ?"; String authoritiesQuery = "select username, authority from authorities where username = ? and 1 = 1"; - setContext("" + DATA_SOURCE); - JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext - .getBean("myUserService"); + JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService"); assertThat(FieldUtils.getFieldValue(mgr, "usersByUsernameQuery")).isEqualTo(userQuery); assertThat(FieldUtils.getFieldValue(mgr, "authoritiesByUsernameQuery")).isEqualTo(authoritiesQuery); assertThat(mgr.loadUserByUsername("rod") != null).isTrue(); @@ -99,11 +92,9 @@ public class JdbcUserServiceBeanDefinitionParserTests { @Test public void groupQueryIsParsedCorrectly() throws Exception { - setContext("" + DATA_SOURCE); - JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext - .getBean("myUserService"); + JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService"); assertThat(FieldUtils.getFieldValue(mgr, "groupAuthoritiesByUsernameQuery")).isEqualTo("blah blah"); assertThat((Boolean) FieldUtils.getFieldValue(mgr, "enableGroups")).isTrue(); } @@ -113,8 +104,7 @@ public class JdbcUserServiceBeanDefinitionParserTests { setContext("" + DATA_SOURCE + USER_CACHE_XML); CachingUserDetailsService cachingUserService = (CachingUserDetailsService) appContext - .getBean("myUserService" - + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX); + .getBean("myUserService" + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX); assertThat(appContext.getBean("userCache")).isSameAs(cachingUserService.getUserCache()); assertThat(cachingUserService.loadUserByUsername("rod")).isNotNull(); assertThat(cachingUserService.loadUserByUsername("rod")).isNotNull(); @@ -123,43 +113,36 @@ public class JdbcUserServiceBeanDefinitionParserTests { @Test public void isSupportedByAuthenticationProviderElement() { setContext("" + " " - + " " - + " " + "" - + DATA_SOURCE); - AuthenticationManager mgr = (AuthenticationManager) appContext - .getBean(BeanIds.AUTHENTICATION_MANAGER); + + " " + " " + + "" + DATA_SOURCE); + AuthenticationManager mgr = (AuthenticationManager) appContext.getBean(BeanIds.AUTHENTICATION_MANAGER); mgr.authenticate(new UsernamePasswordAuthenticationToken("rod", "koala")); } @Test public void cacheIsInjectedIntoAuthenticationProvider() { - setContext("" - + " " + setContext("" + " " + " " - + " " + "" - + DATA_SOURCE + USER_CACHE_XML); - ProviderManager mgr = (ProviderManager) appContext - .getBean(BeanIds.AUTHENTICATION_MANAGER); - DaoAuthenticationProvider provider = (DaoAuthenticationProvider) mgr - .getProviders().get(0); + + " " + "" + DATA_SOURCE + USER_CACHE_XML); + ProviderManager mgr = (ProviderManager) appContext.getBean(BeanIds.AUTHENTICATION_MANAGER); + DaoAuthenticationProvider provider = (DaoAuthenticationProvider) mgr.getProviders().get(0); assertThat(appContext.getBean("userCache")).isSameAs(provider.getUserCache()); provider.authenticate(new UsernamePasswordAuthenticationToken("rod", "koala")); - assertThat(provider - .getUserCache().getUserFromCache("rod")).isNotNull().withFailMessage("Cache should contain user after authentication"); + assertThat(provider.getUserCache().getUserFromCache("rod")).isNotNull() + .withFailMessage("Cache should contain user after authentication"); } @Test public void rolePrefixIsUsedWhenSet() { setContext("" + DATA_SOURCE); - JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext - .getBean("myUserService"); + JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService"); UserDetails rod = mgr.loadUserByUsername("rod"); - assertThat(AuthorityUtils.authorityListToSet(rod.getAuthorities())) - .contains("PREFIX_ROLE_SUPERVISOR"); + assertThat(AuthorityUtils.authorityListToSet(rod.getAuthorities())).contains("PREFIX_ROLE_SUPERVISOR"); } private void setContext(String context) { appContext = new InMemoryXmlApplicationContext(context); } + } diff --git a/config/src/test/java/org/springframework/security/config/authentication/PasswordEncoderParserTests.java b/config/src/test/java/org/springframework/security/config/authentication/PasswordEncoderParserTests.java index 7f97bfce57..fb4c1412d7 100644 --- a/config/src/test/java/org/springframework/security/config/authentication/PasswordEncoderParserTests.java +++ b/config/src/test/java/org/springframework/security/config/authentication/PasswordEncoderParserTests.java @@ -31,6 +31,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @since 5.0 */ public class PasswordEncoderParserTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -39,22 +40,20 @@ public class PasswordEncoderParserTests { @Test public void passwordEncoderDefaultsToDelegatingPasswordEncoder() throws Exception { - this.spring.configLocations("classpath:org/springframework/security/config/authentication/PasswordEncoderParserTests-default.xml") - .mockMvcAfterSpringSecurityOk() - .autowire(); + this.spring.configLocations( + "classpath:org/springframework/security/config/authentication/PasswordEncoderParserTests-default.xml") + .mockMvcAfterSpringSecurityOk().autowire(); - this.mockMvc.perform(get("/").with(httpBasic("user", "password"))) - .andExpect(status().isOk()); + this.mockMvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isOk()); } @Test public void passwordEncoderDefaultsToPasswordEncoderBean() throws Exception { - this.spring.configLocations("classpath:org/springframework/security/config/authentication/PasswordEncoderParserTests-bean.xml") - .mockMvcAfterSpringSecurityOk() - .autowire(); + this.spring.configLocations( + "classpath:org/springframework/security/config/authentication/PasswordEncoderParserTests-bean.xml") + .mockMvcAfterSpringSecurityOk().autowire(); - this.mockMvc.perform(get("/").with(httpBasic("user", "password"))) - .andExpect(status().isOk()); + this.mockMvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isOk()); } } diff --git a/config/src/test/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParserTests.java index b3791d7f1d..1ad00ea422 100644 --- a/config/src/test/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParserTests.java @@ -30,6 +30,7 @@ import org.junit.After; * @author Luke Taylor */ public class UserServiceBeanDefinitionParserTests { + private AbstractXmlApplicationContext appContext; @After @@ -43,19 +44,16 @@ public class UserServiceBeanDefinitionParserTests { public void userServiceWithValidPropertiesFileWorksSuccessfully() { setContext(""); - UserDetailsService userService = (UserDetailsService) appContext - .getBean("service"); + UserDetailsService userService = (UserDetailsService) appContext.getBean("service"); userService.loadUserByUsername("bob"); userService.loadUserByUsername("joe"); } @Test public void userServiceWithEmbeddedUsersWorksSuccessfully() { - setContext("" - + " " + setContext("" + " " + ""); - UserDetailsService userService = (UserDetailsService) appContext - .getBean("service"); + UserDetailsService userService = (UserDetailsService) appContext.getBean("service"); userService.loadUserByUsername("joe"); } @@ -68,8 +66,7 @@ public class UserServiceBeanDefinitionParserTests { + "" + " " + ""); - UserDetailsService userService = (UserDetailsService) appContext - .getBean("service"); + UserDetailsService userService = (UserDetailsService) appContext.getBean("service"); UserDetails joe = userService.loadUserByUsername("joe"); assertThat(joe.getPassword()).isEqualTo("joespassword"); assertThat(joe.getAuthorities()).hasSize(2); @@ -77,10 +74,8 @@ public class UserServiceBeanDefinitionParserTests { @Test public void embeddedUsersWithNoPasswordIsGivenGeneratedValue() { - setContext("" - + " " + ""); - UserDetailsService userService = (UserDetailsService) appContext - .getBean("service"); + setContext("" + " " + ""); + UserDetailsService userService = (UserDetailsService) appContext.getBean("service"); UserDetails joe = userService.loadUserByUsername("joe"); assertThat(joe.getPassword().length() > 0).isTrue(); Long.parseLong(joe.getPassword()); @@ -88,20 +83,14 @@ public class UserServiceBeanDefinitionParserTests { @Test public void worksWithOpenIDUrlsAsNames() { - setContext("" - + " " + setContext("" + " " + " " + ""); - UserDetailsService userService = (UserDetailsService) appContext - .getBean("service"); - assertThat( - userService.loadUserByUsername("https://joe.myopenid.com/").getUsername()) + UserDetailsService userService = (UserDetailsService) appContext.getBean("service"); + assertThat(userService.loadUserByUsername("https://joe.myopenid.com/").getUsername()) .isEqualTo("https://joe.myopenid.com/"); - assertThat( - userService.loadUserByUsername( - "https://www.google.com/accounts/o8/id?id=MPtOaenBIk5yzW9n7n9") - .getUsername()) - .isEqualTo("https://www.google.com/accounts/o8/id?id=MPtOaenBIk5yzW9n7n9"); + assertThat(userService.loadUserByUsername("https://www.google.com/accounts/o8/id?id=MPtOaenBIk5yzW9n7n9") + .getUsername()).isEqualTo("https://www.google.com/accounts/o8/id?id=MPtOaenBIk5yzW9n7n9"); } @Test @@ -110,8 +99,7 @@ public class UserServiceBeanDefinitionParserTests { + " " + " " + ""); - UserDetailsService userService = (UserDetailsService) appContext - .getBean("service"); + UserDetailsService userService = (UserDetailsService) appContext.getBean("service"); UserDetails joe = userService.loadUserByUsername("joe"); assertThat(joe.isAccountNonLocked()).isFalse(); // Check case-sensitive lookup SEC-1432 @@ -122,10 +110,8 @@ public class UserServiceBeanDefinitionParserTests { @Test(expected = FatalBeanException.class) public void userWithBothPropertiesAndEmbeddedUsersThrowsException() { setContext("" - + " " - + ""); - UserDetailsService userService = (UserDetailsService) appContext - .getBean("service"); + + " " + ""); + UserDetailsService userService = (UserDetailsService) appContext.getBean("service"); userService.loadUserByUsername("Joe"); } @@ -144,4 +130,5 @@ public class UserServiceBeanDefinitionParserTests { private void setContext(String context) { appContext = new InMemoryXmlApplicationContext(context); } + } diff --git a/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java index dcf6e5995f..43b26c9b88 100644 --- a/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java +++ b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java @@ -52,13 +52,17 @@ import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class GrantedAuthorityDefaultsJcTests { + @Autowired FilterChainProxy springSecurityFilterChain; + @Autowired MessageService messageService; MockHttpServletRequest request; + MockHttpServletResponse response; + MockFilterChain chain; @Before @@ -153,7 +157,7 @@ public class GrantedAuthorityDefaultsJcTests { @Configuration @EnableWebSecurity - @EnableGlobalMethodSecurity(prePostEnabled=true, jsr250Enabled=true) + @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true) static class Config extends WebSecurityConfigurerAdapter { @Autowired @@ -183,5 +187,7 @@ public class GrantedAuthorityDefaultsJcTests { public static GrantedAuthorityDefaults grantedAuthorityDefaults() { return new GrantedAuthorityDefaults(""); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests.java b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests.java index 9cd487988d..743c19620f 100644 --- a/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests.java +++ b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests.java @@ -45,13 +45,17 @@ import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class GrantedAuthorityDefaultsXmlTests { + @Autowired FilterChainProxy springSecurityFilterChain; + @Autowired MessageService messageService; MockHttpServletRequest request; + MockHttpServletResponse response; + MockFilterChain chain; @Before @@ -143,4 +147,5 @@ public class GrantedAuthorityDefaultsXmlTests { TestingAuthenticationToken user = new TestingAuthenticationToken("user", "password", role); SecurityContextHolder.getContext().setAuthentication(user); } + } diff --git a/config/src/test/java/org/springframework/security/config/core/HelloWorldMessageService.java b/config/src/test/java/org/springframework/security/config/core/HelloWorldMessageService.java index 59a08a96c7..6813e2050c 100755 --- a/config/src/test/java/org/springframework/security/config/core/HelloWorldMessageService.java +++ b/config/src/test/java/org/springframework/security/config/core/HelloWorldMessageService.java @@ -33,4 +33,5 @@ public class HelloWorldMessageService implements MessageService { public String getJsrMessage() { return "Hello JSR"; } + } diff --git a/config/src/test/java/org/springframework/security/config/core/MessageService.java b/config/src/test/java/org/springframework/security/config/core/MessageService.java index 3ec014e486..ce55bba1f3 100755 --- a/config/src/test/java/org/springframework/security/config/core/MessageService.java +++ b/config/src/test/java/org/springframework/security/config/core/MessageService.java @@ -19,6 +19,9 @@ package org.springframework.security.config.core; * @author Rob Winch */ public interface MessageService { + String getMessage(); + String getJsrMessage(); + } diff --git a/config/src/test/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBeanPropertiesResourceITests.java b/config/src/test/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBeanPropertiesResourceITests.java index 59f75ef5de..df43e2fdb1 100644 --- a/config/src/test/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBeanPropertiesResourceITests.java +++ b/config/src/test/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBeanPropertiesResourceITests.java @@ -16,7 +16,6 @@ package org.springframework.security.config.core.userdetails; - import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -34,7 +33,9 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; */ @RunWith(SpringRunner.class) public class ReactiveUserDetailsServiceResourceFactoryBeanPropertiesResourceITests { - @Autowired ReactiveUserDetailsService users; + + @Autowired + ReactiveUserDetailsService users; @Test public void loadUserByUsernameWhenUserFoundThenNotNull() { @@ -43,9 +44,13 @@ public class ReactiveUserDetailsServiceResourceFactoryBeanPropertiesResourceITes @Configuration static class Config { + @Bean public ReactiveUserDetailsServiceResourceFactoryBean userDetailsService() { - return ReactiveUserDetailsServiceResourceFactoryBean.fromResource(new InMemoryResource("user=password,ROLE_USER")); + return ReactiveUserDetailsServiceResourceFactoryBean + .fromResource(new InMemoryResource("user=password,ROLE_USER")); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBeanPropertiesResourceLocationITests.java b/config/src/test/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBeanPropertiesResourceLocationITests.java index 8ec512ce44..92e530929f 100644 --- a/config/src/test/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBeanPropertiesResourceLocationITests.java +++ b/config/src/test/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBeanPropertiesResourceLocationITests.java @@ -16,7 +16,6 @@ package org.springframework.security.config.core.userdetails; - import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -33,7 +32,9 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; */ @RunWith(SpringRunner.class) public class ReactiveUserDetailsServiceResourceFactoryBeanPropertiesResourceLocationITests { - @Autowired ReactiveUserDetailsService users; + + @Autowired + ReactiveUserDetailsService users; @Test public void loadUserByUsernameWhenUserFoundThenNotNull() { @@ -42,9 +43,12 @@ public class ReactiveUserDetailsServiceResourceFactoryBeanPropertiesResourceLoca @Configuration static class Config { + @Bean public ReactiveUserDetailsServiceResourceFactoryBean userDetailsService() { return ReactiveUserDetailsServiceResourceFactoryBean.fromResourceLocation("classpath:users.properties"); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBeanStringITests.java b/config/src/test/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBeanStringITests.java index d6a19645ca..27c95b980c 100644 --- a/config/src/test/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBeanStringITests.java +++ b/config/src/test/java/org/springframework/security/config/core/userdetails/ReactiveUserDetailsServiceResourceFactoryBeanStringITests.java @@ -16,7 +16,6 @@ package org.springframework.security.config.core.userdetails; - import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -33,7 +32,9 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; */ @RunWith(SpringRunner.class) public class ReactiveUserDetailsServiceResourceFactoryBeanStringITests { - @Autowired ReactiveUserDetailsService users; + + @Autowired + ReactiveUserDetailsService users; @Test public void findByUsernameWhenUserFoundThenNotNull() { @@ -42,9 +43,12 @@ public class ReactiveUserDetailsServiceResourceFactoryBeanStringITests { @Configuration static class Config { + @Bean public ReactiveUserDetailsServiceResourceFactoryBean userDetailsService() { return ReactiveUserDetailsServiceResourceFactoryBean.fromString("user=password,ROLE_USER"); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBeanTests.java b/config/src/test/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBeanTests.java index f02f51d137..574ed3af76 100644 --- a/config/src/test/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBeanTests.java +++ b/config/src/test/java/org/springframework/security/config/core/userdetails/UserDetailsResourceFactoryBeanTests.java @@ -36,6 +36,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; */ @RunWith(MockitoJUnitRunner.class) public class UserDetailsResourceFactoryBeanTests { + @Mock ResourceLoader resourceLoader; @@ -43,18 +44,16 @@ public class UserDetailsResourceFactoryBeanTests { @Test public void setResourceLoaderWhenNullThenThrowsException() { - assertThatThrownBy(() -> factory.setResourceLoader(null) ) - .isInstanceOf(IllegalArgumentException.class) - .hasStackTraceContaining("resourceLoader cannot be null"); + assertThatThrownBy(() -> factory.setResourceLoader(null)).isInstanceOf(IllegalArgumentException.class) + .hasStackTraceContaining("resourceLoader cannot be null"); } @Test public void getObjectWhenPropertiesResourceLocationNullThenThrowsIllegalStateException() { factory.setResourceLoader(resourceLoader); - assertThatThrownBy(() -> factory.getObject() ) - .isInstanceOf(IllegalArgumentException.class) - .hasStackTraceContaining("resource cannot be null if resourceLocation is null"); + assertThatThrownBy(() -> factory.getObject()).isInstanceOf(IllegalArgumentException.class) + .hasStackTraceContaining("resource cannot be null if resourceLocation is null"); } @Test @@ -77,10 +76,8 @@ public class UserDetailsResourceFactoryBeanTests { public void getObjectWhenInvalidUserThenThrowsMeaningfulException() { factory.setResource(new InMemoryResource("user=invalidFormatHere")); - assertThatThrownBy(() -> factory.getObject() ) - .isInstanceOf(IllegalStateException.class) - .hasStackTraceContaining("user") - .hasStackTraceContaining("invalidFormatHere"); + assertThatThrownBy(() -> factory.getObject()).isInstanceOf(IllegalStateException.class) + .hasStackTraceContaining("user").hasStackTraceContaining("invalidFormatHere"); } @Test @@ -100,4 +97,5 @@ public class UserDetailsResourceFactoryBeanTests { // @formatter:on assertThat(users).containsExactly(expectedUser); } + } diff --git a/config/src/test/java/org/springframework/security/config/crypto/RsaKeyConversionServicePostProcessorTests.java b/config/src/test/java/org/springframework/security/config/crypto/RsaKeyConversionServicePostProcessorTests.java index e4bb97ca8e..180983d8f6 100644 --- a/config/src/test/java/org/springframework/security/config/crypto/RsaKeyConversionServicePostProcessorTests.java +++ b/config/src/test/java/org/springframework/security/config/crypto/RsaKeyConversionServicePostProcessorTests.java @@ -45,39 +45,38 @@ import static org.assertj.core.api.Assertions.assertThatCode; */ public class RsaKeyConversionServicePostProcessorTests { - private static final String PKCS8_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" + - "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCMk7CKSTfu3QoV\n" + - "HoPVXxwZO+qweztd36cVWYqGOZinrOR2crWFu50AgR2CsdIH0+cqo7F4Vx7/3O8i\n" + - "RpYYZPe2VoO5sumzJt8P6fS80/TAKjhJDAqgZKRJTgGN8KxCM6p/aJli1ZeDBqiV\n" + - "v7vJJe+ZgJuPGRS+HMNa/wPxEkqqXsglcJcQV1ZEtfKXSHB7jizKpRL38185SyAC\n" + - "pwyjvBu6Cmm1URfhQo88mf239ONh4dZ2HoDfzN1q6Ssu4F4hgutxr9B0DVLDP5u+\n" + - "WFrm3nsJ76zf99uJ+ntMUHJ+bY+gOjSlVWIVBIZeAaEGKCNWRk/knjvjbijpvm3U\n" + - "acGlgdL3AgMBAAECggEACxxxS7zVyu91qI2s5eSKmAQAXMqgup6+2hUluc47nqUv\n" + - "uZz/c/6MPkn2Ryo+65d4IgqmMFjSfm68B/2ER5FTcvoLl1Xo2twrrVpUmcg3BClS\n" + - "IZPuExdhVNnxjYKEWwcyZrehyAoR261fDdcFxLRW588efIUC+rPTTRHzAc7sT+Ln\n" + - "t/uFeYNWJm3LaegOLoOmlMAhJ5puAWSN1F0FxtRf/RVgzbLA9QC975SKHJsfWCSr\n" + - "IZyPsdeaqomKaF65l8nfqlE0Ua2L35gIOGKjUwb7uUE8nI362RWMtYdoi3zDDyoY\n" + - "hSFbgjylCHDM0u6iSh6KfqOHtkYyJ8tUYgVWl787wQKBgQDYO3wL7xuDdD101Lyl\n" + - "AnaDdFB9fxp83FG1cWr+t7LYm9YxGfEUsKHAJXN6TIayDkOOoVwIl+Gz0T3Z06Bm\n" + - "eBGLrB9mrVA7+C7NJwu5gTMlzP6HxUR9zKJIQ/VB1NUGM77LSmvOFbHc9Q0+z8EH\n" + - "X5WO516a3Z7lNtZJcCoPOtu2rwKBgQCmbj41Fh+SSEUApCEKms5ETRpe7LXQlJgx\n" + - "yW7zcJNNuIb1C3vBLPxjiOTMgYKOeMg5rtHTGLT43URHLh9ArjawasjSAr4AM3J4\n" + - "xpoi/sKGDdiKOsuDWIGfzdYL8qyTHSdpZLQsCTMRiRYgAHZFPgNa7SLZRfZicGlr\n" + - "GHN1rJW6OQKBgEjiM/upyrJSWeypUDSmUeAZMpA6aWkwsfHgmtnkfUn5rQa74cDB\n" + - "kKO9e+D7LmOR3z+SL/1NhGwh2SE07dncGr3jdGodfO/ZxZyszozmeaECKcEFwwJM\n" + - "GV8WWPKplGwUwPiwywmZ0mvRxXcoe73KgBS88+xrSwWjqDL0tZiQlEJNAoGATkei\n" + - "GMQMG3jEg9Wu+NbxV6zQT3+U0MNjhl9RQU1c63x0dcNt9OFc4NAdlZcAulRTENaK\n" + - "OHjxffBM0hH+fySx8m53gFfr2BpaqDX5f6ZGBlly1SlsWZ4CchCVsc71nshipi7I\n" + - "k8HL9F5/OpQdDNprJ5RMBNfkWE65Nrcsb1e6oPkCgYAxwgdiSOtNg8PjDVDmAhwT\n" + - "Mxj0Dtwi2fAqQ76RVrrXpNp3uCOIAu4CfruIb5llcJ3uak0ZbnWri32AxSgk80y3\n" + - "EWiRX/WEDu5znejF+5O3pI02atWWcnxifEKGGlxwkcMbQdA67MlrJLFaSnnGpNXo\n" + - "yPfcul058SOqhafIZQMEKQ==\n" + - "-----END PRIVATE KEY-----"; - private static final String X509_PUBLIC_KEY_LOCATION = - "classpath:org/springframework/security/config/annotation/web/configuration/simple.pub"; + private static final String PKCS8_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" + + "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCMk7CKSTfu3QoV\n" + + "HoPVXxwZO+qweztd36cVWYqGOZinrOR2crWFu50AgR2CsdIH0+cqo7F4Vx7/3O8i\n" + + "RpYYZPe2VoO5sumzJt8P6fS80/TAKjhJDAqgZKRJTgGN8KxCM6p/aJli1ZeDBqiV\n" + + "v7vJJe+ZgJuPGRS+HMNa/wPxEkqqXsglcJcQV1ZEtfKXSHB7jizKpRL38185SyAC\n" + + "pwyjvBu6Cmm1URfhQo88mf239ONh4dZ2HoDfzN1q6Ssu4F4hgutxr9B0DVLDP5u+\n" + + "WFrm3nsJ76zf99uJ+ntMUHJ+bY+gOjSlVWIVBIZeAaEGKCNWRk/knjvjbijpvm3U\n" + + "acGlgdL3AgMBAAECggEACxxxS7zVyu91qI2s5eSKmAQAXMqgup6+2hUluc47nqUv\n" + + "uZz/c/6MPkn2Ryo+65d4IgqmMFjSfm68B/2ER5FTcvoLl1Xo2twrrVpUmcg3BClS\n" + + "IZPuExdhVNnxjYKEWwcyZrehyAoR261fDdcFxLRW588efIUC+rPTTRHzAc7sT+Ln\n" + + "t/uFeYNWJm3LaegOLoOmlMAhJ5puAWSN1F0FxtRf/RVgzbLA9QC975SKHJsfWCSr\n" + + "IZyPsdeaqomKaF65l8nfqlE0Ua2L35gIOGKjUwb7uUE8nI362RWMtYdoi3zDDyoY\n" + + "hSFbgjylCHDM0u6iSh6KfqOHtkYyJ8tUYgVWl787wQKBgQDYO3wL7xuDdD101Lyl\n" + + "AnaDdFB9fxp83FG1cWr+t7LYm9YxGfEUsKHAJXN6TIayDkOOoVwIl+Gz0T3Z06Bm\n" + + "eBGLrB9mrVA7+C7NJwu5gTMlzP6HxUR9zKJIQ/VB1NUGM77LSmvOFbHc9Q0+z8EH\n" + + "X5WO516a3Z7lNtZJcCoPOtu2rwKBgQCmbj41Fh+SSEUApCEKms5ETRpe7LXQlJgx\n" + + "yW7zcJNNuIb1C3vBLPxjiOTMgYKOeMg5rtHTGLT43URHLh9ArjawasjSAr4AM3J4\n" + + "xpoi/sKGDdiKOsuDWIGfzdYL8qyTHSdpZLQsCTMRiRYgAHZFPgNa7SLZRfZicGlr\n" + + "GHN1rJW6OQKBgEjiM/upyrJSWeypUDSmUeAZMpA6aWkwsfHgmtnkfUn5rQa74cDB\n" + + "kKO9e+D7LmOR3z+SL/1NhGwh2SE07dncGr3jdGodfO/ZxZyszozmeaECKcEFwwJM\n" + + "GV8WWPKplGwUwPiwywmZ0mvRxXcoe73KgBS88+xrSwWjqDL0tZiQlEJNAoGATkei\n" + + "GMQMG3jEg9Wu+NbxV6zQT3+U0MNjhl9RQU1c63x0dcNt9OFc4NAdlZcAulRTENaK\n" + + "OHjxffBM0hH+fySx8m53gFfr2BpaqDX5f6ZGBlly1SlsWZ4CchCVsc71nshipi7I\n" + + "k8HL9F5/OpQdDNprJ5RMBNfkWE65Nrcsb1e6oPkCgYAxwgdiSOtNg8PjDVDmAhwT\n" + + "Mxj0Dtwi2fAqQ76RVrrXpNp3uCOIAu4CfruIb5llcJ3uak0ZbnWri32AxSgk80y3\n" + + "EWiRX/WEDu5znejF+5O3pI02atWWcnxifEKGGlxwkcMbQdA67MlrJLFaSnnGpNXo\n" + "yPfcul058SOqhafIZQMEKQ==\n" + + "-----END PRIVATE KEY-----"; + + private static final String X509_PUBLIC_KEY_LOCATION = "classpath:org/springframework/security/config/annotation/web/configuration/simple.pub"; + + private final RsaKeyConversionServicePostProcessor postProcessor = new RsaKeyConversionServicePostProcessor(); - private final RsaKeyConversionServicePostProcessor postProcessor = - new RsaKeyConversionServicePostProcessor(); private ConversionService service; @Value("classpath:org/springframework/security/config/annotation/web/configuration/simple.pub") @@ -132,25 +131,30 @@ public class RsaKeyConversionServicePostProcessorTests { @Test public void valueWhenOverridingConversionServiceThenUsed() { - assertThatCode(() -> - this.spring.register(OverrideConversionServiceConfig.class, DefaultConfig.class).autowire()) - .hasRootCauseInstanceOf(IllegalArgumentException.class); + assertThatCode( + () -> this.spring.register(OverrideConversionServiceConfig.class, DefaultConfig.class).autowire()) + .hasRootCauseInstanceOf(IllegalArgumentException.class); } @EnableWebSecurity - static class DefaultConfig { } + static class DefaultConfig { + + } @Configuration static class CustomResourceLoaderConfig { + @Bean BeanFactoryPostProcessor conversionServiceCustomizer() { return beanFactory -> beanFactory.getBean(RsaKeyConversionServicePostProcessor.class) .setResourceLoader(new CustomResourceLoader()); } + } @Configuration static class OverrideConversionServiceConfig { + @Bean ConversionService conversionService() { GenericConversionService service = new GenericConversionService(); @@ -159,16 +163,19 @@ public class RsaKeyConversionServicePostProcessorTests { }); return service; } + } private static class CustomResourceLoader implements ResourceLoader { + private final ResourceLoader delegate = new DefaultResourceLoader(); @Override public Resource getResource(String location) { if (location.startsWith("classpath:")) { return this.delegate.getResource(location); - } else if (location.startsWith("custom:")) { + } + else if (location.startsWith("custom:")) { String[] parts = location.split(":"); return this.delegate.getResource( "classpath:org/springframework/security/config/annotation/web/configuration/" + parts[1]); @@ -180,5 +187,7 @@ public class RsaKeyConversionServicePostProcessorTests { public ClassLoader getClassLoader() { return this.delegate.getClassLoader(); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/debug/AuthProviderDependency.java b/config/src/test/java/org/springframework/security/config/debug/AuthProviderDependency.java index 2482e56434..c5916511f5 100644 --- a/config/src/test/java/org/springframework/security/config/debug/AuthProviderDependency.java +++ b/config/src/test/java/org/springframework/security/config/debug/AuthProviderDependency.java @@ -19,6 +19,7 @@ import org.springframework.stereotype.Component; /** * Fake depenency for {@link TestAuthenticationProvider} + * * @author Rob Winch * */ diff --git a/config/src/test/java/org/springframework/security/config/debug/SecurityDebugBeanFactoryPostProcessorTests.java b/config/src/test/java/org/springframework/security/config/debug/SecurityDebugBeanFactoryPostProcessorTests.java index a721906b21..83626cea07 100644 --- a/config/src/test/java/org/springframework/security/config/debug/SecurityDebugBeanFactoryPostProcessorTests.java +++ b/config/src/test/java/org/springframework/security/config/debug/SecurityDebugBeanFactoryPostProcessorTests.java @@ -37,10 +37,12 @@ public class SecurityDebugBeanFactoryPostProcessorTests { @Test public void contextRefreshWhenInDebugModeAndDependencyHasAutowiredConstructorThenDebugModeStillWorks() { // SEC-1885 - this.spring.configLocations("classpath:org/springframework/security/config/debug/SecurityDebugBeanFactoryPostProcessorTests-context.xml") - .autowire(); + this.spring.configLocations( + "classpath:org/springframework/security/config/debug/SecurityDebugBeanFactoryPostProcessorTests-context.xml") + .autowire(); assertThat(this.spring.getContext().getBean(SPRING_SECURITY_FILTER_CHAIN)).isInstanceOf(DebugFilter.class); assertThat(this.spring.getContext().getBean(FILTER_CHAIN_PROXY)).isInstanceOf(FilterChainProxy.class); } + } diff --git a/config/src/test/java/org/springframework/security/config/debug/TestAuthenticationProvider.java b/config/src/test/java/org/springframework/security/config/debug/TestAuthenticationProvider.java index 1a7a6f8966..26488ee356 100644 --- a/config/src/test/java/org/springframework/security/config/debug/TestAuthenticationProvider.java +++ b/config/src/test/java/org/springframework/security/config/debug/TestAuthenticationProvider.java @@ -15,7 +15,6 @@ */ package org.springframework.security.config.debug; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; @@ -23,7 +22,9 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.stereotype.Service; /** - * An {@link AuthenticationProvider} that has an {@link Autowired} constructor which is necessary to recreate SEC-1885. + * An {@link AuthenticationProvider} that has an {@link Autowired} constructor which is + * necessary to recreate SEC-1885. + * * @author Rob Winch * */ @@ -41,4 +42,5 @@ public class TestAuthenticationProvider implements AuthenticationProvider { public boolean supports(Class authentication) { throw new UnsupportedOperationException(); } + } diff --git a/config/src/test/java/org/springframework/security/config/doc/Attribute.java b/config/src/test/java/org/springframework/security/config/doc/Attribute.java index 85983a5b55..6ee71d6d6e 100644 --- a/config/src/test/java/org/springframework/security/config/doc/Attribute.java +++ b/config/src/test/java/org/springframework/security/config/doc/Attribute.java @@ -16,15 +16,16 @@ package org.springframework.security.config.doc; /** - * Represents a Spring Security XSD Attribute. It is created when parsing the current xsd to compare to the documented appendix. + * Represents a Spring Security XSD Attribute. It is created when parsing the current xsd + * to compare to the documented appendix. * * @author Rob Winch * @author Josh Cummings - * * @see SpringSecurityXsdParser * @see XsdDocumentedTests */ public class Attribute { + private String name; private String desc; @@ -63,4 +64,5 @@ public class Attribute { public String getId() { return String.format("%s-%s", this.elmt.getId(), this.name); } + } diff --git a/config/src/test/java/org/springframework/security/config/doc/Element.java b/config/src/test/java/org/springframework/security/config/doc/Element.java index 368dd5d500..9505c2c30a 100644 --- a/config/src/test/java/org/springframework/security/config/doc/Element.java +++ b/config/src/test/java/org/springframework/security/config/doc/Element.java @@ -21,25 +21,30 @@ import java.util.HashMap; import java.util.Map; /** - * Represents a Spring Security XSD Element. It is created when parsing - * the current xsd to compare to the documented appendix. + * Represents a Spring Security XSD Element. It is created when parsing the current xsd to + * compare to the documented appendix. * * @author Rob Winch * @author Josh Cummings - * * @see SpringSecurityXsdParser * @see XsdDocumentedTests -*/ + */ public class Element { + private String name; + private String desc; + private Collection attrs = new ArrayList<>(); /** - * Contains the elements that extend this element (i.e. any-user-service contains ldap-user-service) + * Contains the elements that extend this element (i.e. any-user-service contains + * ldap-user-service) */ private Collection subGrps = new ArrayList<>(); + private Map childElmts = new HashMap<>(); + private Map parentElmts = new HashMap<>(); public String getId() { @@ -95,25 +100,28 @@ public class Element { } /** - * Gets all the ids related to this Element including attributes, parent elements, and child elements. + * Gets all the ids related to this Element including attributes, parent elements, and + * child elements. * *

    * The expected ids to be found are documented below. *

      - *
    • Elements - any xml element will have the nsa-<element>. For example the http element will have the id - * nsa-http
    • - *
    • Parent Section - Any element with a parent other than beans will have a section named - * nsa-<element>-parents. For example, authentication-provider would have a section id of - * nsa-authentication-provider-parents. The section would then contain a list of links pointing to the - * documentation for each parent element.
    • - *
    • Attributes Section - Any element with attributes will have a section with the id - * nsa-<element>-attributes. For example the http element would require a section with the id - * http-attributes.
    • - *
    • Attribute - Each attribute of an element would have an id of nsa-<element>-<attributeName>. For - * example the attribute create-session for the http attribute would have the id http-create-session.
    • - *
    • Child Section - Any element with a child element will have a section named nsa-<element>-children. - * For example, authentication-provider would have a section id of nsa-authentication-provider-children. The - * section would then contain a list of links pointing to the documentation for each child element.
    • + *
    • Elements - any xml element will have the nsa-<element>. For example the + * http element will have the id nsa-http
    • + *
    • Parent Section - Any element with a parent other than beans will have a section + * named nsa-<element>-parents. For example, authentication-provider would have + * a section id of nsa-authentication-provider-parents. The section would then contain + * a list of links pointing to the documentation for each parent element.
    • + *
    • Attributes Section - Any element with attributes will have a section with the + * id nsa-<element>-attributes. For example the http element would require a + * section with the id http-attributes.
    • + *
    • Attribute - Each attribute of an element would have an id of + * nsa-<element>-<attributeName>. For example the attribute create-session + * for the http attribute would have the id http-create-session.
    • + *
    • Child Section - Any element with a child element will have a section named + * nsa-<element>-children. For example, authentication-provider would have a + * section id of nsa-authentication-provider-children. The section would then contain + * a list of links pointing to the documentation for each child element.
    • *
    * @return */ @@ -121,20 +129,19 @@ public class Element { Collection ids = new ArrayList<>(); ids.add(getId()); - this.childElmts.values() - .forEach(elmt -> ids.add(elmt.getId())); + this.childElmts.values().forEach(elmt -> ids.add(elmt.getId())); this.attrs.forEach(attr -> ids.add(attr.getId())); - if ( !this.childElmts.isEmpty() ) { + if (!this.childElmts.isEmpty()) { ids.add(getId() + "-children"); } - if ( !this.attrs.isEmpty() ) { + if (!this.attrs.isEmpty()) { ids.add(getId() + "-attributes"); } - if ( !this.parentElmts.isEmpty() ) { + if (!this.parentElmts.isEmpty()) { ids.add(getId() + "-parents"); } @@ -144,10 +151,7 @@ public class Element { public Map getAllChildElmts() { Map result = new HashMap<>(); - this.childElmts.values() - .forEach(elmt -> - elmt.subGrps.forEach( - subElmt -> result.put(subElmt.name, subElmt))); + this.childElmts.values().forEach(elmt -> elmt.subGrps.forEach(subElmt -> result.put(subElmt.name, subElmt))); result.putAll(this.childElmts); @@ -157,13 +161,11 @@ public class Element { public Map getAllParentElmts() { Map result = new HashMap<>(); - this.parentElmts.values() - .forEach(elmt -> - elmt.subGrps.forEach( - subElmt -> result.put(subElmt.name, subElmt))); + this.parentElmts.values().forEach(elmt -> elmt.subGrps.forEach(subElmt -> result.put(subElmt.name, subElmt))); result.putAll(this.parentElmts); return result; } + } diff --git a/config/src/test/java/org/springframework/security/config/doc/SpringSecurityXsdParser.java b/config/src/test/java/org/springframework/security/config/doc/SpringSecurityXsdParser.java index 12e1e6b8f3..c2b8d88445 100644 --- a/config/src/test/java/org/springframework/security/config/doc/SpringSecurityXsdParser.java +++ b/config/src/test/java/org/springframework/security/config/doc/SpringSecurityXsdParser.java @@ -27,9 +27,11 @@ import java.util.stream.Stream; * @author Josh Cummings */ public class SpringSecurityXsdParser { + private XmlNode rootElement; private Set attrElmts = new LinkedHashSet<>(); + private Map elementNameToElement = new HashMap<>(); public SpringSecurityXsdParser(XmlNode rootElement) { @@ -38,7 +40,6 @@ public class SpringSecurityXsdParser { /** * Returns a map of the element name to the {@link Element}. - * * @return */ public Map parse() { @@ -48,7 +49,6 @@ public class SpringSecurityXsdParser { /** * Creates a Map of the name to an Element object of all the children of element. - * * @param node * @return */ @@ -59,7 +59,8 @@ public class SpringSecurityXsdParser { if ("element".equals(child.simpleName())) { Element e = elmt(child); elementNameToElement.put(e.getName(), e); - } else { + } + else { elementNameToElement.putAll(elements(child)); } }); @@ -69,7 +70,6 @@ public class SpringSecurityXsdParser { /** * Any children that are attribute will be returned as an Attribute object. - * * @param element * @return a collection of Attribute objects that are children of element. */ @@ -79,8 +79,10 @@ public class SpringSecurityXsdParser { String name = c.simpleName(); if ("attribute".equals(name)) { attrs.add(attr(c)); - } else if ("element".equals(name)) { - } else { + } + else if ("element".equals(name)) { + } + else { attrs.addAll(attrs(c)); } }); @@ -89,8 +91,8 @@ public class SpringSecurityXsdParser { } /** - * Any children will be searched for an attributeGroup, each of its children will be returned as an Attribute - * + * Any children will be searched for an attributeGroup, each of its children will be + * returned as an Attribute * @param element * @return */ @@ -100,15 +102,18 @@ public class SpringSecurityXsdParser { element.children().forEach(c -> { if ("element".equals(c.simpleName())) { - } else if ("attributeGroup".equals(c.simpleName())) { + } + else if ("attributeGroup".equals(c.simpleName())) { if (c.attribute("name") != null) { attrgrp.addAll(attrgrp(c)); - } else { + } + else { String name = c.attribute("ref").split(":")[1]; XmlNode attrGrp = findNode(element, name); attrgrp.addAll(attrgrp(attrGrp)); } - } else { + } + else { attrgrp.addAll(attrgrps(c)); } }); @@ -122,22 +127,20 @@ public class SpringSecurityXsdParser { root = root.parent().get(); } - return expand(root) - .filter(node -> name.equals(node.attribute("name"))) - .findFirst().orElseThrow(IllegalArgumentException::new); + return expand(root).filter(node -> name.equals(node.attribute("name"))).findFirst() + .orElseThrow(IllegalArgumentException::new); } private Stream expand(XmlNode root) { - return Stream.concat( - Stream.of(root), - root.children().flatMap(this::expand)); + return Stream.concat(Stream.of(root), root.children().flatMap(this::expand)); } /** - * Processes an individual attributeGroup by obtaining all the attributes and then looking for more attributeGroup elements and prcessing them. - * + * Processes an individual attributeGroup by obtaining all the attributes and then + * looking for more attributeGroup elements and prcessing them. * @param e - * @return all the attributes for a specific attributeGroup and any child attributeGroups + * @return all the attributes for a specific attributeGroup and any child + * attributeGroups */ private Collection attrgrp(XmlNode e) { Collection attrs = attrs(e); @@ -147,20 +150,16 @@ public class SpringSecurityXsdParser { /** * Obtains the description for a specific element - * * @param element * @return */ private String desc(XmlNode element) { - return element.child("annotation") - .flatMap(annotation -> annotation.child("documentation")) - .map(documentation -> documentation.text()) - .orElse(null); + return element.child("annotation").flatMap(annotation -> annotation.child("documentation")) + .map(documentation -> documentation.text()).orElse(null); } /** * Given an element creates an attribute from it. - * * @param n * @return */ @@ -169,8 +168,8 @@ public class SpringSecurityXsdParser { } /** - * Given an element creates an Element out of it by collecting all its attributes and child elements. - * + * Given an element creates an Element out of it by collecting all its attributes and + * child elements. * @param n * @return */ @@ -178,7 +177,8 @@ public class SpringSecurityXsdParser { String name = n.attribute("ref"); if (StringUtils.isEmpty(name)) { name = n.attribute("name"); - } else { + } + else { name = name.split(":")[1]; n = findNode(n, name); } @@ -195,8 +195,7 @@ public class SpringSecurityXsdParser { e.setAttrs(attrs(n)); e.getAttrs().addAll(attrgrps(n)); e.getAttrs().forEach(attr -> attr.setElmt(e)); - e.getChildElmts().values().forEach(element -> - element.getParentElmts().put(e.getName(), e)); + e.getChildElmts().values().forEach(element -> element.getParentElmts().put(e.getName(), e)); String subGrpName = n.attribute("substitutionGroup"); if (!StringUtils.isEmpty(subGrpName)) { @@ -208,4 +207,5 @@ public class SpringSecurityXsdParser { return e; } + } diff --git a/config/src/test/java/org/springframework/security/config/doc/XmlNode.java b/config/src/test/java/org/springframework/security/config/doc/XmlNode.java index 0de48463f4..fceb0e4a8b 100644 --- a/config/src/test/java/org/springframework/security/config/doc/XmlNode.java +++ b/config/src/test/java/org/springframework/security/config/doc/XmlNode.java @@ -26,6 +26,7 @@ import java.util.stream.Stream; * @author Josh Cummings */ public class XmlNode { + private final Node node; public XmlNode(Node node) { @@ -34,7 +35,7 @@ public class XmlNode { public String simpleName() { String[] parts = this.node.getNodeName().split(":"); - return parts[parts.length-1]; + return parts[parts.length - 1]; } public String text() { @@ -44,30 +45,24 @@ public class XmlNode { public Stream children() { NodeList children = this.node.getChildNodes(); - return IntStream.range(0, children.getLength()) - .mapToObj(children::item) - .map(XmlNode::new); + return IntStream.range(0, children.getLength()).mapToObj(children::item).map(XmlNode::new); } public Optional child(String name) { - return this.children() - .filter(child -> name.equals(child.simpleName())) - .findFirst(); + return this.children().filter(child -> name.equals(child.simpleName())).findFirst(); } public Optional parent() { - return Optional.ofNullable(this.node.getParentNode()) - .map(parent -> new XmlNode(parent)); + return Optional.ofNullable(this.node.getParentNode()).map(parent -> new XmlNode(parent)); } public String attribute(String name) { - return Optional.ofNullable(this.node.getAttributes()) - .map(attrs -> attrs.getNamedItem(name)) - .map(attr -> attr.getTextContent()) - .orElse(null); + return Optional.ofNullable(this.node.getAttributes()).map(attrs -> attrs.getNamedItem(name)) + .map(attr -> attr.getTextContent()).orElse(null); } public Node node() { return this.node; } + } diff --git a/config/src/test/java/org/springframework/security/config/doc/XmlParser.java b/config/src/test/java/org/springframework/security/config/doc/XmlParser.java index ffda4846c0..39a93014cb 100644 --- a/config/src/test/java/org/springframework/security/config/doc/XmlParser.java +++ b/config/src/test/java/org/springframework/security/config/doc/XmlParser.java @@ -27,6 +27,7 @@ import java.io.InputStream; * @author Josh Cummings */ public class XmlParser implements AutoCloseable { + private InputStream xml; public XmlParser(InputStream xml) { @@ -39,7 +40,8 @@ public class XmlParser implements AutoCloseable { DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); return new XmlNode(dBuilder.parse(this.xml)); - } catch ( IOException | ParserConfigurationException | SAXException e ) { + } + catch (IOException | ParserConfigurationException | SAXException e) { throw new IllegalStateException(e); } } @@ -48,4 +50,5 @@ public class XmlParser implements AutoCloseable { public void close() throws IOException { this.xml.close(); } + } diff --git a/config/src/test/java/org/springframework/security/config/doc/XmlSupport.java b/config/src/test/java/org/springframework/security/config/doc/XmlSupport.java index 3e18d00335..fdff20279c 100644 --- a/config/src/test/java/org/springframework/security/config/doc/XmlSupport.java +++ b/config/src/test/java/org/springframework/security/config/doc/XmlSupport.java @@ -26,6 +26,7 @@ import java.util.Map; * @author Josh Cummings */ public class XmlSupport { + private XmlParser parser; public XmlNode parse(String location) throws IOException { @@ -41,8 +42,9 @@ public class XmlSupport { } public void close() throws IOException { - if ( this.parser != null ) { + if (this.parser != null) { this.parser.close(); } } + } diff --git a/config/src/test/java/org/springframework/security/config/doc/XsdDocumentedTests.java b/config/src/test/java/org/springframework/security/config/doc/XsdDocumentedTests.java index cd00c06896..6ac13756a0 100644 --- a/config/src/test/java/org/springframework/security/config/doc/XsdDocumentedTests.java +++ b/config/src/test/java/org/springframework/security/config/doc/XsdDocumentedTests.java @@ -45,23 +45,16 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class XsdDocumentedTests { - Collection ignoredIds = Arrays.asList( - "nsa-any-user-service", - "nsa-any-user-service-parents", - "nsa-authentication", - "nsa-websocket-security", - "nsa-ldap", - "nsa-method-security", - "nsa-web", - // deprecated and for removal - "nsa-frame-options-strategy", - "nsa-frame-options-ref", - "nsa-frame-options-value", - "nsa-frame-options-from-parameter"); + Collection ignoredIds = Arrays.asList("nsa-any-user-service", "nsa-any-user-service-parents", + "nsa-authentication", "nsa-websocket-security", "nsa-ldap", "nsa-method-security", "nsa-web", + // deprecated and for removal + "nsa-frame-options-strategy", "nsa-frame-options-ref", "nsa-frame-options-value", + "nsa-frame-options-from-parameter"); String referenceLocation = "../docs/manual/src/docs/asciidoc/_includes/servlet/appendix/namespace.adoc"; String schema31xDocumentLocation = "org/springframework/security/config/spring-security-3.1.xsd"; + String schemaDocumentLocation = "org/springframework/security/config/spring-security-5.4.xsd"; XmlSupport xml = new XmlSupport(); @@ -72,113 +65,73 @@ public class XsdDocumentedTests { } @Test - public void parseWhenLatestXsdThenAllNamedSecurityFiltersAreDefinedAndOrderedProperly() - throws IOException { + public void parseWhenLatestXsdThenAllNamedSecurityFiltersAreDefinedAndOrderedProperly() throws IOException { XmlNode root = this.xml.parse(this.schemaDocumentLocation); - List nodes = - root.child("schema") - .map(XmlNode::children) - .orElse(Stream.empty()) - .filter(node -> - "simpleType".equals(node.simpleName()) && - "named-security-filter".equals(node.attribute("name"))) - .flatMap(XmlNode::children) - .flatMap(XmlNode::children) - .map(node -> node.attribute("value")) - .filter(StringUtils::isNotEmpty) - .collect(Collectors.toList()); + List nodes = root.child("schema").map(XmlNode::children).orElse(Stream.empty()) + .filter(node -> "simpleType".equals(node.simpleName()) + && "named-security-filter".equals(node.attribute("name"))) + .flatMap(XmlNode::children).flatMap(XmlNode::children).map(node -> node.attribute("value")) + .filter(StringUtils::isNotEmpty).collect(Collectors.toList()); SecurityFiltersAssertions.assertEquals(nodes); } @Test - public void parseWhen31XsdThenAllNamedSecurityFiltersAreDefinedAndOrderedProperly() - throws IOException { + public void parseWhen31XsdThenAllNamedSecurityFiltersAreDefinedAndOrderedProperly() throws IOException { - List expected = Arrays.asList( - "FIRST", - "CHANNEL_FILTER", - "SECURITY_CONTEXT_FILTER", - "CONCURRENT_SESSION_FILTER", - "LOGOUT_FILTER", - "X509_FILTER", - "PRE_AUTH_FILTER", - "CAS_FILTER", - "FORM_LOGIN_FILTER", - "OPENID_FILTER", - "LOGIN_PAGE_FILTER", - "DIGEST_AUTH_FILTER", - "BASIC_AUTH_FILTER", - "REQUEST_CACHE_FILTER", - "SERVLET_API_SUPPORT_FILTER", - "JAAS_API_SUPPORT_FILTER", - "REMEMBER_ME_FILTER", - "ANONYMOUS_FILTER", - "SESSION_MANAGEMENT_FILTER", - "EXCEPTION_TRANSLATION_FILTER", - "FILTER_SECURITY_INTERCEPTOR", - "SWITCH_USER_FILTER", - "LAST" - ); + List expected = Arrays.asList("FIRST", "CHANNEL_FILTER", "SECURITY_CONTEXT_FILTER", + "CONCURRENT_SESSION_FILTER", "LOGOUT_FILTER", "X509_FILTER", "PRE_AUTH_FILTER", "CAS_FILTER", + "FORM_LOGIN_FILTER", "OPENID_FILTER", "LOGIN_PAGE_FILTER", "DIGEST_AUTH_FILTER", "BASIC_AUTH_FILTER", + "REQUEST_CACHE_FILTER", "SERVLET_API_SUPPORT_FILTER", "JAAS_API_SUPPORT_FILTER", "REMEMBER_ME_FILTER", + "ANONYMOUS_FILTER", "SESSION_MANAGEMENT_FILTER", "EXCEPTION_TRANSLATION_FILTER", + "FILTER_SECURITY_INTERCEPTOR", "SWITCH_USER_FILTER", "LAST"); XmlNode root = this.xml.parse(this.schema31xDocumentLocation); - List nodes = - root.child("schema") - .map(XmlNode::children) - .orElse(Stream.empty()) - .filter(node -> - "simpleType".equals(node.simpleName()) && - "named-security-filter".equals(node.attribute("name"))) - .flatMap(XmlNode::children) - .flatMap(XmlNode::children) - .map(node -> node.attribute("value")) - .filter(StringUtils::isNotEmpty) - .collect(Collectors.toList()); + List nodes = root.child("schema").map(XmlNode::children).orElse(Stream.empty()) + .filter(node -> "simpleType".equals(node.simpleName()) + && "named-security-filter".equals(node.attribute("name"))) + .flatMap(XmlNode::children).flatMap(XmlNode::children).map(node -> node.attribute("value")) + .filter(StringUtils::isNotEmpty).collect(Collectors.toList()); assertThat(nodes).isEqualTo(expected); } /** - * This will check to ensure that the expected number of xsd documents are found to ensure that we are validating - * against the current xsd document. If this test fails, all that is needed is to update the schemaDocument - * and the expected size for this test. + * This will check to ensure that the expected number of xsd documents are found to + * ensure that we are validating against the current xsd document. If this test fails, + * all that is needed is to update the schemaDocument and the expected size for this + * test. * @return */ @Test - public void sizeWhenReadingFilesystemThenIsCorrectNumberOfSchemaFiles() - throws IOException { + public void sizeWhenReadingFilesystemThenIsCorrectNumberOfSchemaFiles() throws IOException { ClassPathResource resource = new ClassPathResource(this.schemaDocumentLocation); String[] schemas = resource.getFile().getParentFile().list((dir, name) -> name.endsWith(".xsd")); assertThat(schemas.length).isEqualTo(16) - .withFailMessage("the count is equal to 16, if not then schemaDocument needs updating"); + .withFailMessage("the count is equal to 16, if not then schemaDocument needs updating"); } /** - * This uses a naming convention for the ids of the appendix to ensure that the entire appendix is documented. - * The naming convention for the ids is documented in {@link Element#getIds()}. + * This uses a naming convention for the ids of the appendix to ensure that the entire + * appendix is documented. The naming convention for the ids is documented in + * {@link Element#getIds()}. * @return */ @Test - public void countReferencesWhenReviewingDocumentationThenEntireSchemaIsIncluded() - throws IOException { + public void countReferencesWhenReviewingDocumentationThenEntireSchemaIsIncluded() throws IOException { - Map elementsByElementName = - this.xml.elementsByElementName(this.schemaDocumentLocation); + Map elementsByElementName = this.xml.elementsByElementName(this.schemaDocumentLocation); - List documentIds = - Files.lines(Paths.get(this.referenceLocation)) - .filter(line -> line.matches("\\[\\[(nsa-.*)\\]\\]")) - .map(line -> line.substring(2, line.length() - 2)) + List documentIds = Files.lines(Paths.get(this.referenceLocation)) + .filter(line -> line.matches("\\[\\[(nsa-.*)\\]\\]")).map(line -> line.substring(2, line.length() - 2)) .collect(Collectors.toList()); - Set expectedIds = - elementsByElementName.values().stream() - .flatMap(element -> element.getIds().stream()) + Set expectedIds = elementsByElementName.values().stream().flatMap(element -> element.getIds().stream()) .collect(Collectors.toSet()); documentIds.removeAll(this.ignoredIds); @@ -189,13 +142,12 @@ public class XsdDocumentedTests { } /** - * This test ensures that any element that has children or parents contains a section that has links pointing to that - * documentation. + * This test ensures that any element that has children or parents contains a section + * that has links pointing to that documentation. * @return */ @Test - public void countLinksWhenReviewingDocumentationThenParentsAndChildrenAreCorrectlyLinked() - throws IOException { + public void countLinksWhenReviewingDocumentationThenParentsAndChildrenAreCorrectlyLinked() throws IOException { Map> docAttrNameToChildren = new HashMap<>(); Map> docAttrNameToParents = new HashMap<>(); @@ -204,17 +156,19 @@ public class XsdDocumentedTests { Map> currentDocAttrNameToElmt = null; List lines = Files.readAllLines(Paths.get(this.referenceLocation)); - for ( String line : lines ) { + for (String line : lines) { if (line.matches("^\\[\\[.*\\]\\]$")) { String id = line.substring(2, line.length() - 2); if (id.endsWith("-children")) { docAttrName = id.substring(0, id.length() - 9); currentDocAttrNameToElmt = docAttrNameToChildren; - } else if (id.endsWith("-parents")) { + } + else if (id.endsWith("-parents")) { docAttrName = id.substring(0, id.length() - 8); currentDocAttrNameToElmt = docAttrNameToParents; - } else if (docAttrName != null && !id.startsWith(docAttrName)) { + } + else if (docAttrName != null && !id.startsWith(docAttrName)) { currentDocAttrNameToElmt = null; docAttrName = null; } @@ -224,9 +178,7 @@ public class XsdDocumentedTests { String expression = "^\\* <<(nsa-.*),.*>>$"; if (line.matches(expression)) { String elmtId = line.replaceAll(expression, "$1"); - currentDocAttrNameToElmt - .computeIfAbsent(docAttrName, key -> new ArrayList<>()) - .add(elmtId); + currentDocAttrNameToElmt.computeIfAbsent(docAttrName, key -> new ArrayList<>()).add(elmtId); } } } @@ -236,70 +188,50 @@ public class XsdDocumentedTests { Map> schemaAttrNameToChildren = new HashMap<>(); Map> schemaAttrNameToParents = new HashMap<>(); - elementNameToElement.entrySet().stream() - .forEach(entry -> { - String key = "nsa-" + entry.getKey(); - if (this.ignoredIds.contains(key) ) { - return; - } + elementNameToElement.entrySet().stream().forEach(entry -> { + String key = "nsa-" + entry.getKey(); + if (this.ignoredIds.contains(key)) { + return; + } - List parentIds = - entry.getValue().getAllParentElmts().values().stream() - .filter(element -> !this.ignoredIds.contains(element.getId())) - .map(element -> element.getId()) - .sorted() - .collect(Collectors.toList()); - if ( !parentIds.isEmpty() ) { - schemaAttrNameToParents.put(key, parentIds); - } + List parentIds = entry.getValue().getAllParentElmts().values().stream() + .filter(element -> !this.ignoredIds.contains(element.getId())).map(element -> element.getId()) + .sorted().collect(Collectors.toList()); + if (!parentIds.isEmpty()) { + schemaAttrNameToParents.put(key, parentIds); + } - List childIds = - entry.getValue().getAllChildElmts().values().stream() - .filter(element -> !this.ignoredIds.contains(element.getId())) - .map(element -> element.getId()) - .sorted() - .collect(Collectors.toList()); - if ( !childIds.isEmpty() ) { - schemaAttrNameToChildren.put(key, childIds); - } - }); + List childIds = entry.getValue().getAllChildElmts().values().stream() + .filter(element -> !this.ignoredIds.contains(element.getId())).map(element -> element.getId()) + .sorted().collect(Collectors.toList()); + if (!childIds.isEmpty()) { + schemaAttrNameToChildren.put(key, childIds); + } + }); assertThat(docAttrNameToChildren).isEqualTo(schemaAttrNameToChildren); assertThat(docAttrNameToParents).isEqualTo(schemaAttrNameToParents); } - /** * This test checks each xsd element and ensures there is documentation for it. * @return */ @Test - public void countWhenReviewingDocumentationThenAllElementsDocumented() - throws IOException { + public void countWhenReviewingDocumentationThenAllElementsDocumented() throws IOException { - Map elementNameToElement = - this.xml.elementsByElementName(this.schemaDocumentLocation); + Map elementNameToElement = this.xml.elementsByElementName(this.schemaDocumentLocation); - String notDocElmtIds = - elementNameToElement.values().stream() - .filter(element -> - StringUtils.isEmpty(element.getDesc()) && - !this.ignoredIds.contains(element.getId())) - .map(element -> element.getId()) - .sorted() - .collect(Collectors.joining("\n")); + String notDocElmtIds = elementNameToElement.values().stream() + .filter(element -> StringUtils.isEmpty(element.getDesc()) && !this.ignoredIds.contains(element.getId())) + .map(element -> element.getId()).sorted().collect(Collectors.joining("\n")); - String notDocAttrIds = - elementNameToElement.values().stream() - .flatMap(element -> element.getAttrs().stream()) - .filter(element -> - StringUtils.isEmpty(element.getDesc()) && - !this.ignoredIds.contains(element.getId())) - .map(element -> element.getId()) - .sorted() - .collect(Collectors.joining("\n")); + String notDocAttrIds = elementNameToElement.values().stream().flatMap(element -> element.getAttrs().stream()) + .filter(element -> StringUtils.isEmpty(element.getDesc()) && !this.ignoredIds.contains(element.getId())) + .map(element -> element.getId()).sorted().collect(Collectors.joining("\n")); assertThat(notDocElmtIds).isEmpty(); assertThat(notDocAttrIds).isEmpty(); } + } diff --git a/config/src/test/java/org/springframework/security/config/http/AccessDeniedConfigTests.java b/config/src/test/java/org/springframework/security/config/http/AccessDeniedConfigTests.java index 2762628079..0ee76380c5 100644 --- a/config/src/test/java/org/springframework/security/config/http/AccessDeniedConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/AccessDeniedConfigTests.java @@ -39,15 +39,14 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * * @author Luke Taylor * @author Josh Cummings */ @RunWith(SpringJUnit4ClassRunner.class) @SecurityTestExecutionListeners public class AccessDeniedConfigTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/AccessDeniedConfigTests"; + + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/AccessDeniedConfigTests"; @Autowired MockMvc mvc; @@ -59,28 +58,24 @@ public class AccessDeniedConfigTests { public void configureWhenAccessDeniedHandlerIsMissingLeadingSlashThenException() { SpringTestContext context = this.spring.configLocations(this.xml("NoLeadingSlash")); - assertThatThrownBy(() -> context.autowire()) - .isInstanceOf(BeanCreationException.class) + assertThatThrownBy(() -> context.autowire()).isInstanceOf(BeanCreationException.class) .hasMessageContaining("errorPage must begin with '/'"); } @Test @WithMockUser - public void configureWhenAccessDeniedHandlerRefThenAutowire() - throws Exception { + public void configureWhenAccessDeniedHandlerRefThenAutowire() throws Exception { this.spring.configLocations(this.xml("AccessDeniedHandler")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().is(HttpStatus.GONE_410)); + this.mvc.perform(get("/")).andExpect(status().is(HttpStatus.GONE_410)); } @Test public void configureWhenAccessDeniedHandlerUsesPathAndRefThenException() { SpringTestContext context = this.spring.configLocations(this.xml("UsesPathAndRef")); - assertThatThrownBy(() -> context.autowire()) - .isInstanceOf(BeanDefinitionParsingException.class) + assertThatThrownBy(() -> context.autowire()).isInstanceOf(BeanDefinitionParsingException.class) .hasMessageContaining("attribute error-page cannot be used together with the 'ref' attribute"); } @@ -91,11 +86,12 @@ public class AccessDeniedConfigTests { public static class GoneAccessDeniedHandler implements AccessDeniedHandler { @Override - public void handle(HttpServletRequest request, - HttpServletResponse response, - AccessDeniedException accessDeniedException) { + public void handle(HttpServletRequest request, HttpServletResponse response, + AccessDeniedException accessDeniedException) { response.setStatus(HttpStatus.GONE_410); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/http/CsrfBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/CsrfBeanDefinitionParserTests.java index 145547c52a..f9b8650588 100644 --- a/config/src/test/java/org/springframework/security/config/http/CsrfBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/http/CsrfBeanDefinitionParserTests.java @@ -23,8 +23,8 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; * @author Ankur Pathak */ public class CsrfBeanDefinitionParserTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/CsrfBeanDefinitionParserTests"; + + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/CsrfBeanDefinitionParserTests"; @Test public void registerDataValueProcessorOnlyIfNotRegistered() { @@ -38,4 +38,5 @@ public class CsrfBeanDefinitionParserTests { private String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/CsrfConfigTests.java b/config/src/test/java/org/springframework/security/config/http/CsrfConfigTests.java index fa4b41b400..2621e832ee 100644 --- a/config/src/test/java/org/springframework/security/config/http/CsrfConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/CsrfConfigTests.java @@ -77,15 +77,14 @@ import static org.springframework.web.bind.annotation.RequestMethod.PUT; import static org.springframework.web.bind.annotation.RequestMethod.TRACE; /** - * * @author Rob Winch * @author Josh Cummings */ @RunWith(SpringJUnit4ClassRunner.class) @SecurityTestExecutionListeners public class CsrfConfigTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/CsrfConfigTests"; + + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/CsrfConfigTests"; @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -95,272 +94,183 @@ public class CsrfConfigTests { @Test public void postWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception { - this.spring.configLocations( - this.xml("AutoConfig") - ).autowire(); + this.spring.configLocations(this.xml("AutoConfig")).autowire(); - this.mvc.perform(post("/csrf")) - .andExpect(status().isForbidden()) - .andExpect(csrfCreated()); + this.mvc.perform(post("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated()); } @Test public void putWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception { - this.spring.configLocations( - this.xml("AutoConfig") - ).autowire(); + this.spring.configLocations(this.xml("AutoConfig")).autowire(); - this.mvc.perform(put("/csrf")) - .andExpect(status().isForbidden()) - .andExpect(csrfCreated()); + this.mvc.perform(put("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated()); } @Test public void patchWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception { - this.spring.configLocations( - this.xml("AutoConfig") - ).autowire(); + this.spring.configLocations(this.xml("AutoConfig")).autowire(); - this.mvc.perform(patch("/csrf")) - .andExpect(status().isForbidden()) - .andExpect(csrfCreated()); + this.mvc.perform(patch("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated()); } @Test public void deleteWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception { - this.spring.configLocations( - this.xml("AutoConfig") - ).autowire(); + this.spring.configLocations(this.xml("AutoConfig")).autowire(); - this.mvc.perform(delete("/csrf")) - .andExpect(status().isForbidden()) - .andExpect(csrfCreated()); + this.mvc.perform(delete("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated()); } @Test public void invalidWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception { - this.spring.configLocations( - this.xml("AutoConfig") - ).autowire(); + this.spring.configLocations(this.xml("AutoConfig")).autowire(); - this.mvc.perform(request("INVALID", new URI("/csrf"))) - .andExpect(status().isForbidden()) + this.mvc.perform(request("INVALID", new URI("/csrf"))).andExpect(status().isForbidden()) .andExpect(csrfCreated()); } @Test public void getWhenDefaultConfigurationThenCsrfIsEnabled() throws Exception { - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("AutoConfig") - ).autowire(); + this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire(); - this.mvc.perform(get("/csrf")) - .andExpect(csrfInBody()); + this.mvc.perform(get("/csrf")).andExpect(csrfInBody()); } - @Test public void headWhenDefaultConfigurationThenCsrfIsEnabled() throws Exception { - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("AutoConfig") - ).autowire(); + this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire(); - this.mvc.perform(head("/csrf-in-header")) - .andExpect(csrfInHeader()); + this.mvc.perform(head("/csrf-in-header")).andExpect(csrfInHeader()); } @Test public void traceWhenDefaultConfigurationThenCsrfIsEnabled() throws Exception { - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("AutoConfig") - ).autowire(); + this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire(); - MockMvc traceEnabled = MockMvcBuilders - .webAppContextSetup((WebApplicationContext) this.spring.getContext()) + MockMvc traceEnabled = MockMvcBuilders.webAppContextSetup((WebApplicationContext) this.spring.getContext()) .apply(springSecurity()) .addDispatcherServletCustomizer(dispatcherServlet -> dispatcherServlet.setDispatchTraceRequest(true)) .build(); - traceEnabled.perform(request(HttpMethod.TRACE, "/csrf-in-header")) - .andExpect(csrfInHeader()); + traceEnabled.perform(request(HttpMethod.TRACE, "/csrf-in-header")).andExpect(csrfInHeader()); } @Test public void optionsWhenDefaultConfigurationThenCsrfIsEnabled() throws Exception { - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("AutoConfig") - ).autowire(); + this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire(); - this.mvc.perform(options("/csrf-in-header")) - .andExpect(csrfInHeader()); + this.mvc.perform(options("/csrf-in-header")).andExpect(csrfInHeader()); } @Test public void postWhenCsrfDisabledThenRequestAllowed() throws Exception { - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("CsrfDisabled") - ).autowire(); + this.spring.configLocations(this.xml("shared-controllers"), this.xml("CsrfDisabled")).autowire(); - this.mvc.perform(post("/ok")) - .andExpect(status().isOk()); + this.mvc.perform(post("/ok")).andExpect(status().isOk()); assertThat(getFilter(this.spring, CsrfFilter.class)).isNull(); } @Test public void postWhenCsrfElementEnabledThenForbidden() throws Exception { - this.spring.configLocations( - this.xml("CsrfEnabled") - ).autowire(); + this.spring.configLocations(this.xml("CsrfEnabled")).autowire(); - this.mvc.perform(post("/csrf")) - .andExpect(status().isForbidden()) - .andExpect(csrfCreated()); + this.mvc.perform(post("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated()); } @Test public void putWhenCsrfElementEnabledThenForbidden() throws Exception { - this.spring.configLocations( - this.xml("CsrfEnabled") - ).autowire(); + this.spring.configLocations(this.xml("CsrfEnabled")).autowire(); - this.mvc.perform(put("/csrf")) - .andExpect(status().isForbidden()) - .andExpect(csrfCreated()); + this.mvc.perform(put("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated()); } @Test public void patchWhenCsrfElementEnabledThenForbidden() throws Exception { - this.spring.configLocations( - this.xml("CsrfEnabled") - ).autowire(); + this.spring.configLocations(this.xml("CsrfEnabled")).autowire(); - this.mvc.perform(patch("/csrf")) - .andExpect(status().isForbidden()) - .andExpect(csrfCreated()); + this.mvc.perform(patch("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated()); } @Test public void deleteWhenCsrfElementEnabledThenForbidden() throws Exception { - this.spring.configLocations( - this.xml("CsrfEnabled") - ).autowire(); + this.spring.configLocations(this.xml("CsrfEnabled")).autowire(); - this.mvc.perform(delete("/csrf")) - .andExpect(status().isForbidden()) - .andExpect(csrfCreated()); + this.mvc.perform(delete("/csrf")).andExpect(status().isForbidden()).andExpect(csrfCreated()); } @Test public void invalidWhenCsrfElementEnabledThenForbidden() throws Exception { - this.spring.configLocations( - this.xml("CsrfEnabled") - ).autowire(); + this.spring.configLocations(this.xml("CsrfEnabled")).autowire(); - this.mvc.perform(request("INVALID", new URI("/csrf"))) - .andExpect(status().isForbidden()) + this.mvc.perform(request("INVALID", new URI("/csrf"))).andExpect(status().isForbidden()) .andExpect(csrfCreated()); } @Test public void getWhenCsrfElementEnabledThenOk() throws Exception { - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("CsrfEnabled") - ).autowire(); + this.spring.configLocations(this.xml("shared-controllers"), this.xml("CsrfEnabled")).autowire(); - this.mvc.perform(get("/csrf")) - .andExpect(csrfInBody()); + this.mvc.perform(get("/csrf")).andExpect(csrfInBody()); } @Test public void headWhenCsrfElementEnabledThenOk() throws Exception { - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("CsrfEnabled") - ).autowire(); + this.spring.configLocations(this.xml("shared-controllers"), this.xml("CsrfEnabled")).autowire(); - this.mvc.perform(head("/csrf-in-header")) - .andExpect(csrfInHeader()); + this.mvc.perform(head("/csrf-in-header")).andExpect(csrfInHeader()); } @Test public void traceWhenCsrfElementEnabledThenOk() throws Exception { - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("CsrfEnabled") - ).autowire(); + this.spring.configLocations(this.xml("shared-controllers"), this.xml("CsrfEnabled")).autowire(); - MockMvc traceEnabled = MockMvcBuilders - .webAppContextSetup((WebApplicationContext) this.spring.getContext()) + MockMvc traceEnabled = MockMvcBuilders.webAppContextSetup((WebApplicationContext) this.spring.getContext()) .apply(springSecurity()) .addDispatcherServletCustomizer(dispatcherServlet -> dispatcherServlet.setDispatchTraceRequest(true)) .build(); - traceEnabled.perform(request(HttpMethod.TRACE, "/csrf-in-header")) - .andExpect(csrfInHeader()); + traceEnabled.perform(request(HttpMethod.TRACE, "/csrf-in-header")).andExpect(csrfInHeader()); } @Test public void optionsWhenCsrfElementEnabledThenOk() throws Exception { - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("CsrfEnabled") - ).autowire(); + this.spring.configLocations(this.xml("shared-controllers"), this.xml("CsrfEnabled")).autowire(); - this.mvc.perform(options("/csrf-in-header")) - .andExpect(csrfInHeader()); + this.mvc.perform(options("/csrf-in-header")).andExpect(csrfInHeader()); } @Test public void autowireWhenCsrfElementEnabledThenCreatesCsrfRequestDataValueProcessor() { - this.spring.configLocations( - this.xml("CsrfEnabled") - ).autowire(); + this.spring.configLocations(this.xml("CsrfEnabled")).autowire(); assertThat(this.spring.getContext().getBean(RequestDataValueProcessor.class)).isNotNull(); } @Test - public void postWhenUsingCsrfAndCustomAccessDeniedHandlerThenTheHandlerIsAppropriatelyEngaged() - throws Exception { + public void postWhenUsingCsrfAndCustomAccessDeniedHandlerThenTheHandlerIsAppropriatelyEngaged() throws Exception { - this.spring.configLocations( - this.xml("WithAccessDeniedHandler"), - this.xml("shared-access-denied-handler") - ).autowire(); + this.spring.configLocations(this.xml("WithAccessDeniedHandler"), this.xml("shared-access-denied-handler")) + .autowire(); - this.mvc.perform(post("/ok")) - .andExpect(status().isIAmATeapot()); + this.mvc.perform(post("/ok")).andExpect(status().isIAmATeapot()); } @Test public void postWhenHasCsrfTokenButSessionExpiresThenRequestIsCancelledAfterSuccessfulAuthentication() - throws Exception { + throws Exception { - this.spring.configLocations( - this.xml("CsrfEnabled") - ).autowire(); + this.spring.configLocations(this.xml("CsrfEnabled")).autowire(); // simulates a request that has no authentication (e.g. session time-out) - MvcResult result = this.mvc.perform(post("/authenticated") - .with(csrf())) - .andExpect(redirectedUrl("http://localhost/login")) - .andReturn(); + MvcResult result = this.mvc.perform(post("/authenticated").with(csrf())) + .andExpect(redirectedUrl("http://localhost/login")).andReturn(); MockHttpSession session = (MockHttpSession) result.getRequest().getSession(); - // if the request cache is consulted, then it will redirect back to /some-url, which we don't want - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .session(session) - .with(csrf())) + // if the request cache is consulted, then it will redirect back to /some-url, + // which we don't want + this.mvc.perform( + post("/login").param("username", "user").param("password", "password").session(session).with(csrf())) .andExpect(redirectedUrl("/")); } @@ -368,24 +278,18 @@ public class CsrfConfigTests { public void getWhenHasCsrfTokenButSessionExpiresThenRequestIsRememeberedAfterSuccessfulAuthentication() throws Exception { - this.spring.configLocations( - this.xml("CsrfEnabled") - ).autowire(); + this.spring.configLocations(this.xml("CsrfEnabled")).autowire(); // simulates a request that has no authentication (e.g. session time-out) - MvcResult result = - this.mvc.perform(get("/authenticated")) - .andExpect(redirectedUrl("http://localhost/login")) - .andReturn(); + MvcResult result = this.mvc.perform(get("/authenticated")).andExpect(redirectedUrl("http://localhost/login")) + .andReturn(); MockHttpSession session = (MockHttpSession) result.getRequest().getSession(); - // if the request cache is consulted, then it will redirect back to /some-url, which we do want - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .session(session) - .with(csrf())) + // if the request cache is consulted, then it will redirect back to /some-url, + // which we do want + this.mvc.perform( + post("/login").param("username", "user").param("password", "password").session(session).with(csrf())) .andExpect(redirectedUrl("http://localhost/authenticated")); } @@ -394,33 +298,23 @@ public class CsrfConfigTests { */ @Test public void postWhenUsingCsrfAndCustomSessionManagementAndNoSessionThenStillRedirectsToInvalidSessionUrl() - throws Exception { + throws Exception { - this.spring.configLocations( - this.xml("WithSessionManagement") - ).autowire(); + this.spring.configLocations(this.xml("WithSessionManagement")).autowire(); MvcResult result = this.mvc.perform(post("/ok").param("_csrf", "abc")) - .andExpect(redirectedUrl("/error/sessionError")) - .andReturn(); + .andExpect(redirectedUrl("/error/sessionError")).andReturn(); MockHttpSession session = (MockHttpSession) result.getRequest().getSession(); - this.mvc.perform(post("/csrf") - .session(session)) - .andExpect(status().isForbidden()); + this.mvc.perform(post("/csrf").session(session)).andExpect(status().isForbidden()); } @Test - public void requestWhenUsingCustomRequestMatcherConfiguredThenAppliesAccordingly() - throws Exception { + public void requestWhenUsingCustomRequestMatcherConfiguredThenAppliesAccordingly() throws Exception { - SpringTestContext context = - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("WithRequestMatcher"), - this.xml("mock-request-matcher") - ); + SpringTestContext context = this.spring.configLocations(this.xml("shared-controllers"), + this.xml("WithRequestMatcher"), this.xml("mock-request-matcher")); context.autowire(); @@ -435,84 +329,56 @@ public class CsrfConfigTests { } @Test - public void getWhenDefaultConfigurationThenSessionNotImmediatelyCreated() - throws Exception { + public void getWhenDefaultConfigurationThenSessionNotImmediatelyCreated() throws Exception { - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("AutoConfig") - ).autowire(); + this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire(); - MvcResult result = this.mvc.perform(get("/ok")) - .andExpect(status().isOk()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/ok")).andExpect(status().isOk()).andReturn(); assertThat(result.getRequest().getSession(false)).isNull(); } @Test @WithMockUser - public void postWhenCsrfMismatchesThenForbidden() - throws Exception { + public void postWhenCsrfMismatchesThenForbidden() throws Exception { - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("AutoConfig") - ).autowire(); + this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire(); MvcResult result = this.mvc.perform(get("/ok")).andReturn(); MockHttpSession session = (MockHttpSession) result.getRequest().getSession(); - this.mvc.perform(post("/ok") - .session(session) - .with(csrf().useInvalidToken())) - .andExpect(status().isForbidden()); + this.mvc.perform(post("/ok").session(session).with(csrf().useInvalidToken())).andExpect(status().isForbidden()); } @Test - public void loginWhenDefaultConfigurationThenCsrfCleared() - throws Exception { + public void loginWhenDefaultConfigurationThenCsrfCleared() throws Exception { - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("AutoConfig") - ).autowire(); + this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire(); MvcResult result = this.mvc.perform(get("/csrf")).andReturn(); MockHttpSession session = (MockHttpSession) result.getRequest().getSession(); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .session(session) - .with(csrf())) - .andExpect(status().isFound()); - - this.mvc.perform(get("/csrf").session(session)) - .andExpect(csrfChanged(result)); - } - - @Test - public void logoutWhenDefaultConfigurationThenCsrfCleared() - throws Exception { - - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("AutoConfig") - ).autowire(); - - MvcResult result = this.mvc.perform(get("/csrf")).andReturn(); - - MockHttpSession session = (MockHttpSession) result.getRequest().getSession(); - - this.mvc.perform(post("/logout").session(session) - .with(csrf())) + this.mvc.perform( + post("/login").param("username", "user").param("password", "password").session(session).with(csrf())) .andExpect(status().isFound()); - this.mvc.perform(get("/csrf").session(session)) - .andExpect(csrfChanged(result)); + this.mvc.perform(get("/csrf").session(session)).andExpect(csrfChanged(result)); + } + + @Test + public void logoutWhenDefaultConfigurationThenCsrfCleared() throws Exception { + + this.spring.configLocations(this.xml("shared-controllers"), this.xml("AutoConfig")).autowire(); + + MvcResult result = this.mvc.perform(get("/csrf")).andReturn(); + + MockHttpSession session = (MockHttpSession) result.getRequest().getSession(); + + this.mvc.perform(post("/logout").session(session).with(csrf())).andExpect(status().isFound()); + + this.mvc.perform(get("/csrf").session(session)).andExpect(csrfChanged(result)); } /** @@ -520,16 +386,15 @@ public class CsrfConfigTests { */ @Test @WithMockUser - public void logoutWhenDefaultConfigurationThenDisabled() - throws Exception { + public void logoutWhenDefaultConfigurationThenDisabled() throws Exception { - this.spring.configLocations( - this.xml("shared-controllers"), - this.xml("CsrfEnabled") - ).autowire(); + this.spring.configLocations(this.xml("shared-controllers"), this.xml("CsrfEnabled")).autowire(); - this.mvc.perform(get("/logout")) - .andExpect(status().isOk()); // renders form to log out but does not perform a redirect + this.mvc.perform(get("/logout")).andExpect(status().isOk()); // renders form to + // log out but + // does not + // perform a + // redirect // still logged in this.mvc.perform(get("/authenticated")).andExpect(status().isOk()); @@ -540,8 +405,8 @@ public class CsrfConfigTests { List filters = chain.getFilters("/any"); - for ( Filter filter : filters ) { - if ( type.isAssignableFrom(filter.getClass()) ) { + for (Filter filter : filters) { + if (type.isAssignableFrom(filter.getClass())) { return (T) filter; } } @@ -555,6 +420,7 @@ public class CsrfConfigTests { @Controller public static class RootController { + @RequestMapping(value = "/csrf-in-header", method = { HEAD, TRACE, OPTIONS }) @ResponseBody String csrfInHeaderAndBody(CsrfToken token, HttpServletResponse response) { @@ -579,18 +445,18 @@ public class CsrfConfigTests { String authenticated() { return "authenticated"; } + } private static class TeapotAccessDeniedHandler implements AccessDeniedHandler { @Override - public void handle( - HttpServletRequest request, - HttpServletResponse response, + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) { response.setStatus(HttpStatus.IM_A_TEAPOT_418); } + } ResultMatcher csrfChanged(MvcResult first) { @@ -616,19 +482,24 @@ public class CsrfConfigTests { @FunctionalInterface interface ExceptionalFunction { + OUT apply(IN in) throws Exception; + } static class CsrfCreatedResultMatcher implements ResultMatcher { + @Override public void match(MvcResult result) { MockHttpServletRequest request = result.getRequest(); CsrfToken token = WebTestUtils.getCsrfTokenRepository(request).loadToken(request); assertThat(token).isNotNull(); } + } static class CsrfReturnedResultMatcher implements ResultMatcher { + ExceptionalFunction token; CsrfReturnedResultMatcher(ExceptionalFunction token) { @@ -642,6 +513,7 @@ public class CsrfConfigTests { assertThat(token).isNotNull(); assertThat(token.getToken()).isEqualTo(this.token.apply(result)); } + } } diff --git a/config/src/test/java/org/springframework/security/config/http/DefaultFilterChainValidatorTests.java b/config/src/test/java/org/springframework/security/config/http/DefaultFilterChainValidatorTests.java index 2e87b07360..51b870b019 100644 --- a/config/src/test/java/org/springframework/security/config/http/DefaultFilterChainValidatorTests.java +++ b/config/src/test/java/org/springframework/security/config/http/DefaultFilterChainValidatorTests.java @@ -44,17 +44,21 @@ import org.springframework.security.web.authentication.LoginUrlAuthenticationEnt import org.springframework.security.web.util.matcher.AnyRequestMatcher; /** - * * @author Rob Winch */ @RunWith(MockitoJUnitRunner.class) public class DefaultFilterChainValidatorTests { + private DefaultFilterChainValidator validator; + private FilterChainProxy fcp; + @Mock private Log logger; + @Mock private DefaultFilterInvocationSecurityMetadataSource metadataSource; + @Mock private AccessDecisionManager accessDecisionManager; @@ -66,12 +70,10 @@ public class DefaultFilterChainValidatorTests { fsi = new FilterSecurityInterceptor(); fsi.setAccessDecisionManager(accessDecisionManager); fsi.setSecurityMetadataSource(metadataSource); - AuthenticationEntryPoint authenticationEntryPoint = new LoginUrlAuthenticationEntryPoint( - "/login"); - ExceptionTranslationFilter etf = new ExceptionTranslationFilter( - authenticationEntryPoint); - DefaultSecurityFilterChain securityChain = new DefaultSecurityFilterChain( - AnyRequestMatcher.INSTANCE, aaf, etf, fsi); + AuthenticationEntryPoint authenticationEntryPoint = new LoginUrlAuthenticationEntryPoint("/login"); + ExceptionTranslationFilter etf = new ExceptionTranslationFilter(authenticationEntryPoint); + DefaultSecurityFilterChain securityChain = new DefaultSecurityFilterChain(AnyRequestMatcher.INSTANCE, aaf, etf, + fsi); fcp = new FilterChainProxy(securityChain); validator = new DefaultFilterChainValidator(); @@ -82,24 +84,25 @@ public class DefaultFilterChainValidatorTests { @SuppressWarnings("unchecked") @Test public void validateCheckLoginPageIsntProtectedThrowsIllegalArgumentException() { - IllegalArgumentException toBeThrown = new IllegalArgumentException( - "failed to eval expression"); - doThrow(toBeThrown).when(accessDecisionManager).decide(any(Authentication.class), - anyObject(), any(Collection.class)); + IllegalArgumentException toBeThrown = new IllegalArgumentException("failed to eval expression"); + doThrow(toBeThrown).when(accessDecisionManager).decide(any(Authentication.class), anyObject(), + any(Collection.class)); validator.validate(fcp); - verify(logger) - .info("Unable to check access to the login page to determine if anonymous access is allowed. This might be an error, but can happen under normal circumstances.", - toBeThrown); + verify(logger).info( + "Unable to check access to the login page to determine if anonymous access is allowed. This might be an error, but can happen under normal circumstances.", + toBeThrown); } // SEC-1957 @Test public void validateCustomMetadataSource() { - FilterInvocationSecurityMetadataSource customMetaDataSource = mock(FilterInvocationSecurityMetadataSource.class); + FilterInvocationSecurityMetadataSource customMetaDataSource = mock( + FilterInvocationSecurityMetadataSource.class); fsi.setSecurityMetadataSource(customMetaDataSource); validator.validate(fcp); verify(customMetaDataSource).getAttributes(any()); } + } diff --git a/config/src/test/java/org/springframework/security/config/http/FilterSecurityMetadataSourceBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/FilterSecurityMetadataSourceBeanDefinitionParserTests.java index 29164a0f8c..91124dd40a 100644 --- a/config/src/test/java/org/springframework/security/config/http/FilterSecurityMetadataSourceBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/http/FilterSecurityMetadataSourceBeanDefinitionParserTests.java @@ -59,12 +59,10 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests { @Test public void parsingMinimalConfigurationIsSuccessful() { setContext("" - + " " - + ""); + + " " + ""); DefaultFilterInvocationSecurityMetadataSource fids = (DefaultFilterInvocationSecurityMetadataSource) this.appContext .getBean("fids"); - Collection cad = fids - .getAttributes(createFilterInvocation("/anything", "GET")); + Collection cad = fids.getAttributes(createFilterInvocation("/anything", "GET")); assertThat(cad).contains(new SecurityConfig("ROLE_A")); } @@ -76,8 +74,7 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests { ExpressionBasedFilterInvocationSecurityMetadataSource fids = (ExpressionBasedFilterInvocationSecurityMetadataSource) this.appContext .getBean("fids"); - ConfigAttribute[] cad = fids - .getAttributes(createFilterInvocation("/anything", "GET")) + ConfigAttribute[] cad = fids.getAttributes(createFilterInvocation("/anything", "GET")) .toArray(new ConfigAttribute[0]); assertThat(cad).hasSize(1); assertThat(cad[0].toString()).isEqualTo("hasRole('ROLE_A')"); @@ -88,15 +85,13 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests { public void interceptUrlsSupportPropertyPlaceholders() { System.setProperty("secure.url", "/secure"); System.setProperty("secure.role", "ROLE_A"); - setContext( - "" - + "" - + " " - + ""); + setContext("" + + "" + + " " + + ""); DefaultFilterInvocationSecurityMetadataSource fids = (DefaultFilterInvocationSecurityMetadataSource) this.appContext .getBean("fids"); - Collection cad = fids - .getAttributes(createFilterInvocation("/secure", "GET")); + Collection cad = fids.getAttributes(createFilterInvocation("/secure", "GET")); assertThat(cad).containsExactly(new SecurityConfig("ROLE_A")); } @@ -110,16 +105,15 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests { + " " + " " + " " + " " - + " " + "" - + ConfigTestUtils.AUTH_PROVIDER_XML); + + " " + + "" + ConfigTestUtils.AUTH_PROVIDER_XML); } @Test(expected = BeanDefinitionParsingException.class) public void parsingInterceptUrlServletPathFails() { setContext("" - + " " - + ""); + + " " + + ""); } private FilterInvocation createFilterInvocation(String path, String method) { @@ -129,7 +123,7 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests { request.setServletPath(path); - return new FilterInvocation(request, new MockHttpServletResponse(), - new MockFilterChain()); + return new FilterInvocation(request, new MockHttpServletResponse(), new MockFilterChain()); } + } diff --git a/config/src/test/java/org/springframework/security/config/http/FormLoginBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/FormLoginBeanDefinitionParserTests.java index 4bef5265fa..f8e3f1ecdc 100644 --- a/config/src/test/java/org/springframework/security/config/http/FormLoginBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/http/FormLoginBeanDefinitionParserTests.java @@ -32,15 +32,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - /** - * * @author Luke Taylor * @author Josh Cummings */ public class FormLoginBeanDefinitionParserTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/FormLoginBeanDefinitionParserTests"; + + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/FormLoginBeanDefinitionParserTests"; @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -49,86 +47,63 @@ public class FormLoginBeanDefinitionParserTests { MockMvc mvc; @Test - public void getLoginWhenAutoConfigThenShowsDefaultLoginPage() - throws Exception { + public void getLoginWhenAutoConfigThenShowsDefaultLoginPage() throws Exception { this.spring.configLocations(this.xml("Simple")).autowire(); - String expectedContent = - "\n" - + "\n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " Please sign in\n" - + " \n" - + " \n" - + " \n" - + " \n" - + "
    \n" - + "
    \n" - + " \n" - + "

    \n" - + " \n" - + " \n" - + "

    \n" - + "

    \n" - + " \n" - + " \n" - + "

    \n" - + " \n" - + "
    \n" - + "
    \n" - + ""; + String expectedContent = "\n" + "\n" + " \n" + + " \n" + + " \n" + + " \n" + " \n" + + " Please sign in\n" + + " \n" + + " \n" + + " \n" + " \n" + "
    \n" + + "
    \n" + + " \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + + " \n" + + "
    \n" + "
    \n" + ""; this.mvc.perform(get("/login")).andExpect(content().string(expectedContent)); } @Test - public void getLogoutWhenAutoConfigThenShowsDefaultLogoutPage() - throws Exception { + public void getLogoutWhenAutoConfigThenShowsDefaultLogoutPage() throws Exception { this.spring.configLocations(this.xml("AutoConfig")).autowire(); - this.mvc.perform(get("/logout")) - .andExpect(content().string(containsString("action=\"/logout\""))); + this.mvc.perform(get("/logout")).andExpect(content().string(containsString("action=\"/logout\""))); } @Test - public void getLoginWhenConfiguredWithCustomAttributesThenLoginPageReflects() - throws Exception { + public void getLoginWhenConfiguredWithCustomAttributesThenLoginPageReflects() throws Exception { this.spring.configLocations(this.xml("WithCustomAttributes")).autowire(); - String expectedContent = - "\n" - + "\n" + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " Please sign in\n" - + " \n" - + " \n" - + " \n" - + " \n" - + "
    \n" - + "
    \n" - + " \n" - + "

    \n" - + " \n" - + " \n" - + "

    \n" - + "

    \n" - + " \n" - + " \n" - + "

    \n" - + " \n" - + "
    \n" - + "
    \n" - + ""; + String expectedContent = "\n" + "\n" + " \n" + + " \n" + + " \n" + + " \n" + " \n" + + " Please sign in\n" + + " \n" + + " \n" + + " \n" + " \n" + "
    \n" + + "
    \n" + + " \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + + " \n" + + "
    \n" + "
    \n" + ""; this.mvc.perform(get("/login")).andExpect(content().string(expectedContent)); @@ -136,121 +111,94 @@ public class FormLoginBeanDefinitionParserTests { } @Test - public void getLoginWhenConfiguredForOpenIdThenLoginPageReflects() - throws Exception { + public void getLoginWhenConfiguredForOpenIdThenLoginPageReflects() throws Exception { this.spring.configLocations(this.xml("WithOpenId")).autowire(); - String expectedContent = - "\n" + "\n" + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " Please sign in\n" - + " \n" - + " \n" - + " \n" - + " \n" - + "
    \n" - + "
    \n" - + " \n" - + "

    \n" - + " \n" - + " \n" - + "

    \n" - + "

    \n" - + " \n" - + " \n" - + "

    \n" - + " \n" - + "
    \n" - + "
    \n" - + " \n" - + "

    \n" - + " \n" - + " \n" - + "

    \n" - + " \n" - + "
    \n" - + "
    \n" - + ""; + String expectedContent = "\n" + "\n" + " \n" + + " \n" + + " \n" + + " \n" + " \n" + + " Please sign in\n" + + " \n" + + " \n" + + " \n" + " \n" + "
    \n" + + "
    \n" + + " \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + + " \n" + + "
    \n" + + "
    \n" + + " \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + + " \n" + + "
    \n" + "
    \n" + ""; this.mvc.perform(get("/login")).andExpect(content().string(expectedContent)); } @Test - public void getLoginWhenConfiguredForOpenIdWithCustomAttributesThenLoginPageReflects() - throws Exception { + public void getLoginWhenConfiguredForOpenIdWithCustomAttributesThenLoginPageReflects() throws Exception { this.spring.configLocations(this.xml("WithOpenIdCustomAttributes")).autowire(); - String expectedContent = - "\n" + "\n" + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " Please sign in\n" - + " \n" - + " \n" - + " \n" - + " \n" - + "
    \n" - + "
    \n" - + " \n" - + "

    \n" - + " \n" - + " \n" - + "

    \n" - + "

    \n" - + " \n" - + " \n" - + "

    \n" - + " \n" - + "
    \n" - + "
    \n" - + " \n" - + "

    \n" - + " \n" - + " \n" - + "

    \n" - + " \n" - + "
    \n" - + "
    \n" - + ""; + String expectedContent = "\n" + "\n" + " \n" + + " \n" + + " \n" + + " \n" + " \n" + + " Please sign in\n" + + " \n" + + " \n" + + " \n" + " \n" + "
    \n" + + "
    \n" + + " \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + + " \n" + + "
    \n" + + "
    \n" + + " \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + + " \n" + + "
    \n" + "
    \n" + ""; this.mvc.perform(get("/login")).andExpect(content().string(expectedContent)); } @Test - public void failedLoginWhenConfiguredWithCustomAuthenticationFailureThenForwardsAccordingly() - throws Exception { + public void failedLoginWhenConfiguredWithCustomAuthenticationFailureThenForwardsAccordingly() throws Exception { this.spring.configLocations(this.xml("WithAuthenticationFailureForwardUrl")).autowire(); - this.mvc.perform(post("/login") - .param("username", "bob") - .param("password", "invalidpassword")) - .andExpect(status().isOk()) - .andExpect(forwardedUrl("/failure_forward_url")) + this.mvc.perform(post("/login").param("username", "bob").param("password", "invalidpassword")) + .andExpect(status().isOk()).andExpect(forwardedUrl("/failure_forward_url")) .andExpect(request().attribute(WebAttributes.AUTHENTICATION_EXCEPTION, not(nullValue()))); } @Test - public void successfulLoginWhenConfiguredWithCustomAuthenticationSuccessThenForwardsAccordingly() - throws Exception { + public void successfulLoginWhenConfiguredWithCustomAuthenticationSuccessThenForwardsAccordingly() throws Exception { this.spring.configLocations(this.xml("WithAuthenticationSuccessForwardUrl")).autowire(); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password")) - .andExpect(status().isOk()) - .andExpect(forwardedUrl("/success_forward_url")); + this.mvc.perform(post("/login").param("username", "user").param("password", "password")) + .andExpect(status().isOk()).andExpect(forwardedUrl("/success_forward_url")); } private String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java b/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java index 56bbe0b062..392632c023 100644 --- a/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java @@ -48,13 +48,12 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * * @author Luke Taylor * @author Josh Cummings */ public class FormLoginConfigTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/FormLoginConfigTests"; + + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/FormLoginConfigTests"; @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -63,48 +62,34 @@ public class FormLoginConfigTests { MockMvc mvc; @Test - public void getProtectedPageWhenFormLoginConfiguredThenRedirectsToDefaultLoginPage() - throws Exception { + public void getProtectedPageWhenFormLoginConfiguredThenRedirectsToDefaultLoginPage() throws Exception { this.spring.configLocations(this.xml("WithAntRequestMatcher")).autowire(); - this.mvc.perform(get("/")) - .andExpect(redirectedUrl("http://localhost/login")); + this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/login")); } @Test - public void authenticateWhenDefaultTargetUrlConfiguredThenRedirectsAccordingly() - throws Exception { + public void authenticateWhenDefaultTargetUrlConfiguredThenRedirectsAccordingly() throws Exception { this.spring.configLocations(this.xml("WithDefaultTargetUrl")).autowire(); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .with(csrf())) + this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf())) .andExpect(redirectedUrl("/default")); } @Test - public void authenticateWhenConfiguredWithSpelThenRedirectsAccordingly() - throws Exception { + public void authenticateWhenConfiguredWithSpelThenRedirectsAccordingly() throws Exception { this.spring.configLocations(this.xml("UsingSpel")).autowire(); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .with(csrf())) + this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf())) .andExpect(redirectedUrl(WebConfigUtilsTests.URL + "/default")); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "wrong") - .with(csrf())) + this.mvc.perform(post("/login").param("username", "user").param("password", "wrong").with(csrf())) .andExpect(redirectedUrl(WebConfigUtilsTests.URL + "/failure")); - this.mvc.perform(get("/")) - .andExpect(redirectedUrl("http://localhost" + WebConfigUtilsTests.URL + "/login")); + this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost" + WebConfigUtilsTests.URL + "/login")); } @Test @@ -122,35 +107,23 @@ public class FormLoginConfigTests { } @Test - public void authenticateWhenCustomHandlerBeansConfiguredThenInvokesAccordingly() - throws Exception { + public void authenticateWhenCustomHandlerBeansConfiguredThenInvokesAccordingly() throws Exception { this.spring.configLocations(this.xml("WithSuccessAndFailureHandlers")).autowire(); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .with(csrf())) + this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf())) .andExpect(status().isIAmATeapot()); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "wrong") - .with(csrf())) + this.mvc.perform(post("/login").param("username", "user").param("password", "wrong").with(csrf())) .andExpect(status().isIAmATeapot()); } - @Test - public void authenticateWhenCustomUsernameAndPasswordParametersThenSucceeds() - throws Exception { + public void authenticateWhenCustomUsernameAndPasswordParametersThenSucceeds() throws Exception { this.spring.configLocations(this.xml("WithUsernameAndPasswordParameters")).autowire(); - this.mvc.perform(post("/login") - .param("xname", "user") - .param("xpass", "password") - .with(csrf())) + this.mvc.perform(post("/login").param("xname", "user").param("xpass", "password").with(csrf())) .andExpect(redirectedUrl("/")); } @@ -159,85 +132,74 @@ public class FormLoginConfigTests { */ @Test public void autowireWhenCustomLoginPageIsSlashLoginThenNoDefaultLoginPageGeneratingFilterIsWired() - throws Exception { + throws Exception { this.spring.configLocations(this.xml("ForSec2919")).autowire(); - this.mvc.perform(get("/login")) - .andExpect(content().string("teapot")); + this.mvc.perform(get("/login")).andExpect(content().string("teapot")); assertThat(getFilter(this.spring.getContext(), DefaultLoginPageGeneratingFilter.class)).isNull(); } @Test - public void authenticateWhenCsrfIsEnabledThenRequiresToken() - throws Exception { + public void authenticateWhenCsrfIsEnabledThenRequiresToken() throws Exception { this.spring.configLocations(this.xml("WithCsrfEnabled")).autowire(); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password")) + this.mvc.perform(post("/login").param("username", "user").param("password", "password")) .andExpect(status().isForbidden()); } @Test - public void authenticateWhenCsrfIsDisabledThenDoesNotRequireToken() - throws Exception { + public void authenticateWhenCsrfIsDisabledThenDoesNotRequireToken() throws Exception { this.spring.configLocations(this.xml("WithCsrfDisabled")).autowire(); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password")) + this.mvc.perform(post("/login").param("username", "user").param("password", "password")) .andExpect(status().isFound()); } /** - * SEC-3147: authentication-failure-url should be contained "error" parameter if login-page="/login" + * SEC-3147: authentication-failure-url should be contained "error" parameter if + * login-page="/login" */ @Test public void authenticateWhenLoginPageIsSlashLoginAndAuthenticationFailsThenRedirectContainsErrorParameter() - throws Exception { + throws Exception { this.spring.configLocations(this.xml("ForSec3147")).autowire(); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "wrong") - .with(csrf())) + this.mvc.perform(post("/login").param("username", "user").param("password", "wrong").with(csrf())) .andExpect(redirectedUrl("/login?error")); } @RestController public static class LoginController { + @GetMapping("/login") public String ok() { return "teapot"; } + } - public static class TeapotAuthenticationHandler implements - AuthenticationSuccessHandler, - AuthenticationFailureHandler { + public static class TeapotAuthenticationHandler + implements AuthenticationSuccessHandler, AuthenticationFailureHandler { @Override - public void onAuthenticationFailure( - HttpServletRequest request, - HttpServletResponse response, + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) { response.setStatus(HttpStatus.I_AM_A_TEAPOT.value()); } @Override - public void onAuthenticationSuccess( - HttpServletRequest request, - HttpServletResponse response, + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { response.setStatus(HttpStatus.I_AM_A_TEAPOT.value()); } + } private Filter getFilter(ApplicationContext context, Class filterClass) { @@ -245,8 +207,8 @@ public class FormLoginConfigTests { List filters = filterChain.getFilters("/any"); - for ( Filter filter : filters ) { - if ( filter.getClass() == filterClass ) { + for (Filter filter : filters) { + if (filter.getClass() == filterClass) { return filter; } } @@ -257,4 +219,5 @@ public class FormLoginConfigTests { private String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/HttpConfigTests.java b/config/src/test/java/org/springframework/security/config/http/HttpConfigTests.java index f0da65eac7..ff369f8a9b 100644 --- a/config/src/test/java/org/springframework/security/config/http/HttpConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/HttpConfigTests.java @@ -34,14 +34,12 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * * @author Rob Winch * @author Josh Cummings */ public class HttpConfigTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/HttpConfigTests"; + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/HttpConfigTests"; @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -50,19 +48,15 @@ public class HttpConfigTests { MockMvc mvc; @Test - public void getWhenUsingMinimalConfigurationThenRedirectsToLogin() - throws Exception { + public void getWhenUsingMinimalConfigurationThenRedirectsToLogin() throws Exception { this.spring.configLocations(this.xml("Minimal")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("http://localhost/login")); + this.mvc.perform(get("/")).andExpect(status().isFound()).andExpect(redirectedUrl("http://localhost/login")); } @Test - public void getWhenUsingMinimalConfigurationThenPreventsSessionAsUrlParameter() - throws Exception { + public void getWhenUsingMinimalConfigurationThenPreventsSessionAsUrlParameter() throws Exception { this.spring.configLocations(this.xml("Minimal")).autowire(); @@ -71,17 +65,14 @@ public class HttpConfigTests { FilterChainProxy proxy = this.spring.getContext().getBean(FilterChainProxy.class); - proxy.doFilter( - request, - new EncodeUrlDenyingHttpServletResponseWrapper(response), - (req, resp) -> {}); + proxy.doFilter(request, new EncodeUrlDenyingHttpServletResponseWrapper(response), (req, resp) -> { + }); assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_MOVED_TEMPORARILY); assertThat(response.getRedirectedUrl()).isEqualTo("http://localhost/login"); } - private static class EncodeUrlDenyingHttpServletResponseWrapper - extends HttpServletResponseWrapper { + private static class EncodeUrlDenyingHttpServletResponseWrapper extends HttpServletResponseWrapper { EncodeUrlDenyingHttpServletResponseWrapper(HttpServletResponse response) { super(response); @@ -106,9 +97,11 @@ public class HttpConfigTests { public String encodeRedirectUrl(String url) { throw new RuntimeException("Unexpected invocation of encodeURL"); } + } private String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/HttpCorsConfigTests.java b/config/src/test/java/org/springframework/security/config/http/HttpCorsConfigTests.java index 2ba0044db8..c50130375b 100644 --- a/config/src/test/java/org/springframework/security/config/http/HttpCorsConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/HttpCorsConfigTests.java @@ -41,15 +41,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * * @author Rob Winch * @author Tim Ysewyn * @author Josh Cummings */ public class HttpCorsConfigTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/HttpCorsConfigTests"; + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/HttpCorsConfigTests"; @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -59,78 +57,68 @@ public class HttpCorsConfigTests { @Test public void autowireWhenMissingMvcThenGivesInformativeError() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("RequiresMvc")).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasMessageContaining("Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext"); + assertThatThrownBy(() -> this.spring.configLocations(this.xml("RequiresMvc")).autowire()) + .isInstanceOf(BeanCreationException.class).hasMessageContaining( + "Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext"); } @Test - public void getWhenUsingCorsThenDoesSpringSecurityCorsHandshake() - throws Exception { + public void getWhenUsingCorsThenDoesSpringSecurityCorsHandshake() throws Exception { this.spring.configLocations(this.xml("WithCors")).autowire(); - this.mvc.perform(get("/").with(this.approved())) - .andExpect(corsResponseHeaders()) + this.mvc.perform(get("/").with(this.approved())).andExpect(corsResponseHeaders()) .andExpect((status().isIAmATeapot())); - this.mvc.perform(options("/").with(this.preflight())) - .andExpect(corsResponseHeaders()) + this.mvc.perform(options("/").with(this.preflight())).andExpect(corsResponseHeaders()) .andExpect(status().isOk()); } @Test - public void getWhenUsingCustomCorsConfigurationSourceThenDoesSpringSecurityCorsHandshake() - throws Exception { + public void getWhenUsingCustomCorsConfigurationSourceThenDoesSpringSecurityCorsHandshake() throws Exception { this.spring.configLocations(this.xml("WithCorsConfigurationSource")).autowire(); - this.mvc.perform(get("/").with(this.approved())) - .andExpect(corsResponseHeaders()) + this.mvc.perform(get("/").with(this.approved())).andExpect(corsResponseHeaders()) .andExpect((status().isIAmATeapot())); - this.mvc.perform(options("/").with(this.preflight())) - .andExpect(corsResponseHeaders()) + this.mvc.perform(options("/").with(this.preflight())).andExpect(corsResponseHeaders()) .andExpect(status().isOk()); } @Test - public void getWhenUsingCustomCorsFilterThenDoesSPringSecurityCorsHandshake() - throws Exception { + public void getWhenUsingCustomCorsFilterThenDoesSPringSecurityCorsHandshake() throws Exception { this.spring.configLocations(this.xml("WithCorsFilter")).autowire(); - this.mvc.perform(get("/").with(this.approved())) - .andExpect(corsResponseHeaders()) + this.mvc.perform(get("/").with(this.approved())).andExpect(corsResponseHeaders()) .andExpect((status().isIAmATeapot())); - this.mvc.perform(options("/").with(this.preflight())) - .andExpect(corsResponseHeaders()) + this.mvc.perform(options("/").with(this.preflight())).andExpect(corsResponseHeaders()) .andExpect(status().isOk()); } @RestController - @CrossOrigin(methods = { - RequestMethod.GET, RequestMethod.POST - }) + @CrossOrigin(methods = { RequestMethod.GET, RequestMethod.POST }) static class CorsController { + @RequestMapping("/") String hello() { return "Hello"; } + } static class MyCorsConfigurationSource extends UrlBasedCorsConfigurationSource { + MyCorsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("*")); configuration.setAllowedMethods(Arrays.asList(RequestMethod.GET.name(), RequestMethod.POST.name())); - super.registerCorsConfiguration( - "/**", - configuration); + super.registerCorsConfiguration("/**", configuration); } + } private String xml(String configName) { @@ -149,7 +137,7 @@ public class HttpCorsConfigTests { return (request) -> { request.addHeader(HttpHeaders.ORIGIN, "https://example.com"); - if ( preflight ) { + if (preflight) { request.setMethod(HttpMethod.OPTIONS.name()); request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name()); } diff --git a/config/src/test/java/org/springframework/security/config/http/HttpHeadersConfigTests.java b/config/src/test/java/org/springframework/security/config/http/HttpHeadersConfigTests.java index 2df097e589..9e582be23d 100644 --- a/config/src/test/java/org/springframework/security/config/http/HttpHeadersConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/HttpHeadersConfigTests.java @@ -41,7 +41,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * * @author Rob Winch * @author Tim Ysewyn * @author Josh Cummings @@ -49,19 +48,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. */ public class HttpHeadersConfigTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/HttpHeadersConfigTests"; + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/HttpHeadersConfigTests"; - static final Map defaultHeaders = - ImmutableMap.builder() - .put("X-Content-Type-Options", "nosniff") - .put("X-Frame-Options", "DENY") - .put("Strict-Transport-Security", "max-age=31536000 ; includeSubDomains") - .put("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate") - .put("Expires", "0") - .put("Pragma", "no-cache") - .put("X-XSS-Protection", "1; mode=block") - .build(); + static final Map defaultHeaders = ImmutableMap.builder() + .put("X-Content-Type-Options", "nosniff").put("X-Frame-Options", "DENY") + .put("Strict-Transport-Security", "max-age=31536000 ; includeSubDomains") + .put("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate").put("Expires", "0") + .put("Pragma", "no-cache").put("X-XSS-Protection", "1; mode=block").build(); @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -70,97 +63,75 @@ public class HttpHeadersConfigTests { MockMvc mvc; @Test - public void requestWhenHeadersDisabledThenResponseExcludesAllSecureHeaders() - throws Exception { + public void requestWhenHeadersDisabledThenResponseExcludesAllSecureHeaders() throws Exception { this.spring.configLocations(this.xml("HeadersDisabled")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(excludesDefaults()); + this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(excludesDefaults()); } @Test - public void requestWhenHeadersDisabledViaPlaceholderThenResponseExcludesAllSecureHeaders() - throws Exception { + public void requestWhenHeadersDisabledViaPlaceholderThenResponseExcludesAllSecureHeaders() throws Exception { System.setProperty("security.headers.disabled", "true"); this.spring.configLocations(this.xml("DisabledWithPlaceholder")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(excludesDefaults()); + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(excludesDefaults()); } @Test - public void requestWhenHeadersEnabledViaPlaceholderThenResponseIncludesAllSecureHeaders() - throws Exception { + public void requestWhenHeadersEnabledViaPlaceholderThenResponseIncludesAllSecureHeaders() throws Exception { System.setProperty("security.headers.disabled", "false"); this.spring.configLocations(this.xml("DisabledWithPlaceholder")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includesDefaults()); + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includesDefaults()); } @Test - public void requestWhenHeadersDisabledRefMissingPlaceholderThenResponseIncludesAllSecureHeaders() - throws Exception { + public void requestWhenHeadersDisabledRefMissingPlaceholderThenResponseIncludesAllSecureHeaders() throws Exception { System.clearProperty("security.headers.disabled"); this.spring.configLocations(this.xml("DisabledWithPlaceholder")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includesDefaults()); + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includesDefaults()); } @Test public void configureWhenHeadersDisabledHavingChildElementThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("HeadersDisabledHavingChildElement")).autowire()) + assertThatThrownBy(() -> this.spring.configLocations(this.xml("HeadersDisabledHavingChildElement")).autowire()) .isInstanceOf(BeanDefinitionParsingException.class) .hasMessageContaining("Cannot specify with child elements"); } @Test - public void requestWhenHeadersEnabledThenResponseContainsAllSecureHeaders() - throws Exception { + public void requestWhenHeadersEnabledThenResponseContainsAllSecureHeaders() throws Exception { this.spring.configLocations(this.xml("DefaultConfig")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includesDefaults()); + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includesDefaults()); } @Test - public void requestWhenHeadersElementUsedThenResponseContainsAllSecureHeaders() - throws Exception { + public void requestWhenHeadersElementUsedThenResponseContainsAllSecureHeaders() throws Exception { this.spring.configLocations(this.xml("HeadersEnabled")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includesDefaults()); + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includesDefaults()); } @Test - public void requestWhenFrameOptionsConfiguredThenIncludesHeader() - throws Exception { + public void requestWhenFrameOptionsConfiguredThenIncludesHeader() throws Exception { Map headers = new HashMap(defaultHeaders); headers.put("X-Frame-Options", "SAMEORIGIN"); this.spring.configLocations(this.xml("WithFrameOptions")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includes(headers)); + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(headers)); } // -- defaults disabled @@ -169,506 +140,412 @@ public class HttpHeadersConfigTests { * gh-3986 */ @Test - public void requestWhenDefaultsDisabledWithNoOverrideThenExcludesAllSecureHeaders() - throws Exception { + public void requestWhenDefaultsDisabledWithNoOverrideThenExcludesAllSecureHeaders() throws Exception { this.spring.configLocations(this.xml("DefaultsDisabledWithNoOverride")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(excludesDefaults()); + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(excludesDefaults()); } @Test - public void requestWhenDefaultsDisabledWithPlaceholderTrueThenExcludesAllSecureHeaders() - throws Exception { + public void requestWhenDefaultsDisabledWithPlaceholderTrueThenExcludesAllSecureHeaders() throws Exception { System.setProperty("security.headers.defaults.disabled", "true"); this.spring.configLocations(this.xml("DefaultsDisabledWithPlaceholder")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(excludesDefaults()); + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(excludesDefaults()); } @Test - public void requestWhenDefaultsDisabledWithPlaceholderFalseThenIncludeAllSecureHeaders() - throws Exception { + public void requestWhenDefaultsDisabledWithPlaceholderFalseThenIncludeAllSecureHeaders() throws Exception { System.setProperty("security.headers.defaults.disabled", "false"); this.spring.configLocations(this.xml("DefaultsDisabledWithPlaceholder")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includesDefaults()); + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includesDefaults()); } @Test - public void requestWhenDefaultsDisabledWithPlaceholderMissingThenIncludeAllSecureHeaders() - throws Exception { + public void requestWhenDefaultsDisabledWithPlaceholderMissingThenIncludeAllSecureHeaders() throws Exception { System.clearProperty("security.headers.defaults.disabled"); this.spring.configLocations(this.xml("DefaultsDisabledWithPlaceholder")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includesDefaults()); + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includesDefaults()); } @Test - public void requestWhenUsingContentTypeOptionsThenDefaultsToNoSniff() - throws Exception { + public void requestWhenUsingContentTypeOptionsThenDefaultsToNoSniff() throws Exception { Set excludedHeaders = new HashSet<>(defaultHeaders.keySet()); excludedHeaders.remove("X-Content-Type-Options"); this.spring.configLocations(this.xml("DefaultsDisabledWithContentTypeOptions")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(header().string("X-Content-Type-Options", "nosniff")) - .andExpect(excludes(excludedHeaders)); + this.mvc.perform(get("/")).andExpect(status().isOk()) + .andExpect(header().string("X-Content-Type-Options", "nosniff")).andExpect(excludes(excludedHeaders)); } @Test - public void requestWhenUsingFrameOptionsThenDefaultsToDeny() - throws Exception { + public void requestWhenUsingFrameOptionsThenDefaultsToDeny() throws Exception { Set excludedHeaders = new HashSet<>(defaultHeaders.keySet()); excludedHeaders.remove("X-Frame-Options"); this.spring.configLocations(this.xml("DefaultsDisabledWithFrameOptions")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(header().string("X-Frame-Options", "DENY")) + this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(header().string("X-Frame-Options", "DENY")) .andExpect(excludes(excludedHeaders)); } @Test - public void requestWhenUsingFrameOptionsDenyThenRespondsWithDeny() - throws Exception { + public void requestWhenUsingFrameOptionsDenyThenRespondsWithDeny() throws Exception { Set excludedHeaders = new HashSet<>(defaultHeaders.keySet()); excludedHeaders.remove("X-Frame-Options"); this.spring.configLocations(this.xml("DefaultsDisabledWithFrameOptionsDeny")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(header().string("X-Frame-Options", "DENY")) + this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(header().string("X-Frame-Options", "DENY")) .andExpect(excludes(excludedHeaders)); } @Test - public void requestWhenUsingFrameOptionsSameOriginThenRespondsWithSameOrigin() - throws Exception { + public void requestWhenUsingFrameOptionsSameOriginThenRespondsWithSameOrigin() throws Exception { Set excludedHeaders = new HashSet<>(defaultHeaders.keySet()); excludedHeaders.remove("X-Frame-Options"); this.spring.configLocations(this.xml("DefaultsDisabledWithFrameOptionsSameOrigin")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(header().string("X-Frame-Options", "SAMEORIGIN")) - .andExpect(excludes(excludedHeaders)); + this.mvc.perform(get("/")).andExpect(status().isOk()) + .andExpect(header().string("X-Frame-Options", "SAMEORIGIN")).andExpect(excludes(excludedHeaders)); } @Test public void configureWhenUsingFrameOptionsAllowFromNoOriginThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("DefaultsDisabledWithFrameOptionsAllowFromNoOrigin")).autowire()) - .isInstanceOf(BeanDefinitionParsingException.class) - .hasMessageContaining("Strategy requires a 'value' to be set."); // FIXME better error message? + assertThatThrownBy(() -> this.spring + .configLocations(this.xml("DefaultsDisabledWithFrameOptionsAllowFromNoOrigin")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class) + .hasMessageContaining("Strategy requires a 'value' to be set."); // FIXME + // better + // error + // message? } @Test public void configureWhenUsingFrameOptionsAllowFromBlankOriginThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("DefaultsDisabledWithFrameOptionsAllowFromBlankOrigin")).autowire()) - .isInstanceOf(BeanDefinitionParsingException.class) - .hasMessageContaining("Strategy requires a 'value' to be set."); // FIXME better error message? + assertThatThrownBy(() -> this.spring + .configLocations(this.xml("DefaultsDisabledWithFrameOptionsAllowFromBlankOrigin")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class) + .hasMessageContaining("Strategy requires a 'value' to be set."); // FIXME + // better + // error + // message? } @Test - public void requestWhenUsingFrameOptionsAllowFromThenRespondsWithAllowFrom() - throws Exception { + public void requestWhenUsingFrameOptionsAllowFromThenRespondsWithAllowFrom() throws Exception { Set excludedHeaders = new HashSet<>(defaultHeaders.keySet()); excludedHeaders.remove("X-Frame-Options"); this.spring.configLocations(this.xml("DefaultsDisabledWithFrameOptionsAllowFrom")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) + this.mvc.perform(get("/")).andExpect(status().isOk()) .andExpect(header().string("X-Frame-Options", "ALLOW-FROM https://example.org")) .andExpect(excludes(excludedHeaders)); } @Test - public void requestWhenUsingFrameOptionsAllowFromWhitelistThenRespondsWithAllowFrom() - throws Exception { + public void requestWhenUsingFrameOptionsAllowFromWhitelistThenRespondsWithAllowFrom() throws Exception { Set excludedHeaders = new HashSet<>(defaultHeaders.keySet()); excludedHeaders.remove("X-Frame-Options"); this.spring.configLocations(this.xml("DefaultsDisabledWithFrameOptionsAllowFromWhitelist")).autowire(); - this.mvc.perform(get("/").param("from", "https://example.org")) - .andExpect(status().isOk()) + this.mvc.perform(get("/").param("from", "https://example.org")).andExpect(status().isOk()) .andExpect(header().string("X-Frame-Options", "ALLOW-FROM https://example.org")) .andExpect(excludes(excludedHeaders)); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(header().string("X-Frame-Options", "DENY")) + this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(header().string("X-Frame-Options", "DENY")) .andExpect(excludes(excludedHeaders)); } @Test - public void requestWhenUsingCustomHeaderThenRespondsWithThatHeader() - throws Exception { + public void requestWhenUsingCustomHeaderThenRespondsWithThatHeader() throws Exception { this.spring.configLocations(this.xml("DefaultsDisabledWithCustomHeader")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(header().string("a", "b")) - .andExpect(header().string("c", "d")) - .andExpect(excludesDefaults()); + this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(header().string("a", "b")) + .andExpect(header().string("c", "d")).andExpect(excludesDefaults()); } @Test - public void requestWhenUsingCustomHeaderWriterThenRespondsWithThatHeader() - throws Exception { + public void requestWhenUsingCustomHeaderWriterThenRespondsWithThatHeader() throws Exception { this.spring.configLocations(this.xml("DefaultsDisabledWithCustomHeaderWriter")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(header().string("abc", "def")) + this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(header().string("abc", "def")) .andExpect(excludesDefaults()); } @Test public void configureWhenUsingCustomHeaderNameOnlyThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("DefaultsDisabledWithOnlyHeaderName")).autowire()) + assertThatThrownBy(() -> this.spring.configLocations(this.xml("DefaultsDisabledWithOnlyHeaderName")).autowire()) .isInstanceOf(BeanCreationException.class); } @Test public void configureWhenUsingCustomHeaderValueOnlyThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("DefaultsDisabledWithOnlyHeaderValue")).autowire()) - .isInstanceOf(BeanCreationException.class); + assertThatThrownBy( + () -> this.spring.configLocations(this.xml("DefaultsDisabledWithOnlyHeaderValue")).autowire()) + .isInstanceOf(BeanCreationException.class); } @Test - public void requestWhenUsingXssProtectionThenDefaultsToModeBlock() - throws Exception { + public void requestWhenUsingXssProtectionThenDefaultsToModeBlock() throws Exception { Set excludedHeaders = new HashSet<>(defaultHeaders.keySet()); excludedHeaders.remove("X-XSS-Protection"); this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtection")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(header().string("X-XSS-Protection", "1; mode=block")) - .andExpect(excludes(excludedHeaders)); + this.mvc.perform(get("/")).andExpect(status().isOk()) + .andExpect(header().string("X-XSS-Protection", "1; mode=block")).andExpect(excludes(excludedHeaders)); } @Test - public void requestWhenEnablingXssProtectionThenDefaultsToModeBlock() - throws Exception { + public void requestWhenEnablingXssProtectionThenDefaultsToModeBlock() throws Exception { Set excludedHeaders = new HashSet<>(defaultHeaders.keySet()); excludedHeaders.remove("X-XSS-Protection"); this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionEnabled")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(header().string("X-XSS-Protection", "1; mode=block")) - .andExpect(excludes(excludedHeaders)); + this.mvc.perform(get("/")).andExpect(status().isOk()) + .andExpect(header().string("X-XSS-Protection", "1; mode=block")).andExpect(excludes(excludedHeaders)); } @Test - public void requestWhenDisablingXssProtectionThenDefaultsToZero() - throws Exception { + public void requestWhenDisablingXssProtectionThenDefaultsToZero() throws Exception { Set excludedHeaders = new HashSet<>(defaultHeaders.keySet()); excludedHeaders.remove("X-XSS-Protection"); this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionDisabled")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(header().string("X-XSS-Protection", "0")) + this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(header().string("X-XSS-Protection", "0")) .andExpect(excludes(excludedHeaders)); } @Test public void configureWhenXssProtectionDisabledAndBlockSetThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionDisabledAndBlockSet")).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasMessageContaining("Cannot set block to true with enabled false"); + assertThatThrownBy(() -> this.spring + .configLocations(this.xml("DefaultsDisabledWithXssProtectionDisabledAndBlockSet")).autowire()) + .isInstanceOf(BeanCreationException.class) + .hasMessageContaining("Cannot set block to true with enabled false"); } @Test - public void requestWhenUsingCacheControlThenRespondsWithCorrespondingHeaders() - throws Exception { + public void requestWhenUsingCacheControlThenRespondsWithCorrespondingHeaders() throws Exception { Map includedHeaders = ImmutableMap.builder() - .put("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate") - .put("Expires", "0") - .put("Pragma", "no-cache") - .build(); + .put("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate").put("Expires", "0") + .put("Pragma", "no-cache").build(); this.spring.configLocations(this.xml("DefaultsDisabledWithCacheControl")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(includes(includedHeaders)); + this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(includes(includedHeaders)); } @Test - public void requestWhenUsingHstsThenRespondsWithHstsHeader() - throws Exception { + public void requestWhenUsingHstsThenRespondsWithHstsHeader() throws Exception { Set excludedHeaders = new HashSet<>(defaultHeaders.keySet()); excludedHeaders.remove("Strict-Transport-Security"); this.spring.configLocations(this.xml("DefaultsDisabledWithHsts")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()) .andExpect(header().string("Strict-Transport-Security", "max-age=31536000 ; includeSubDomains")) .andExpect(excludes(excludedHeaders)); } @Test - public void insecureRequestWhenUsingHstsThenExcludesHstsHeader() - throws Exception { + public void insecureRequestWhenUsingHstsThenExcludesHstsHeader() throws Exception { this.spring.configLocations(this.xml("DefaultsDisabledWithHsts")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(excludesDefaults()); + this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(excludesDefaults()); } @Test - public void insecureRequestWhenUsingCustomHstsRequestMatcherThenIncludesHstsHeader() - throws Exception { + public void insecureRequestWhenUsingCustomHstsRequestMatcherThenIncludesHstsHeader() throws Exception { Set excludedHeaders = new HashSet<>(defaultHeaders.keySet()); excludedHeaders.remove("Strict-Transport-Security"); this.spring.configLocations(this.xml("DefaultsDisabledWithCustomHstsRequestMatcher")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) + this.mvc.perform(get("/")).andExpect(status().isOk()) .andExpect(header().string("Strict-Transport-Security", "max-age=1")) .andExpect(excludes(excludedHeaders)); } @Test public void configureWhenUsingHpkpWithoutPinsThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("DefaultsDisabledWithEmptyHpkp")).autowire()) + assertThatThrownBy(() -> this.spring.configLocations(this.xml("DefaultsDisabledWithEmptyHpkp")).autowire()) .isInstanceOf(XmlBeanDefinitionStoreException.class) .hasMessageContaining("The content of element 'hpkp' is not complete"); } @Test public void configureWhenUsingHpkpWithEmptyPinsThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("DefaultsDisabledWithEmptyPins")).autowire()) + assertThatThrownBy(() -> this.spring.configLocations(this.xml("DefaultsDisabledWithEmptyPins")).autowire()) .isInstanceOf(XmlBeanDefinitionStoreException.class) .hasMessageContaining("The content of element 'pins' is not complete"); } @Test - public void requestWhenUsingHpkpThenIncludesHpkpHeader() - throws Exception { + public void requestWhenUsingHpkpThenIncludesHpkpHeader() throws Exception { this.spring.configLocations(this.xml("DefaultsDisabledWithHpkp")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(header().string( - "Public-Key-Pins-Report-Only", + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()) + .andExpect(header().string("Public-Key-Pins-Report-Only", "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\"")) .andExpect(excludesDefaults()); } @Test - public void requestWhenUsingHpkpDefaultsThenIncludesHpkpHeaderUsingSha256() - throws Exception { + public void requestWhenUsingHpkpDefaultsThenIncludesHpkpHeaderUsingSha256() throws Exception { this.spring.configLocations(this.xml("DefaultsDisabledWithHpkpDefaults")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(header().string( - "Public-Key-Pins-Report-Only", + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()) + .andExpect(header().string("Public-Key-Pins-Report-Only", "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\"")) .andExpect(excludesDefaults()); } @Test - public void insecureRequestWhenUsingHpkpThenExcludesHpkpHeader() - throws Exception { + public void insecureRequestWhenUsingHpkpThenExcludesHpkpHeader() throws Exception { this.spring.configLocations(this.xml("DefaultsDisabledWithHpkpDefaults")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(header().doesNotExist("Public-Key-Pins-Report-Only")) - .andExpect(excludesDefaults()); + this.mvc.perform(get("/")).andExpect(status().isOk()) + .andExpect(header().doesNotExist("Public-Key-Pins-Report-Only")).andExpect(excludesDefaults()); } @Test - public void requestWhenUsingHpkpCustomMaxAgeThenIncludesHpkpHeaderAccordingly() - throws Exception { + public void requestWhenUsingHpkpCustomMaxAgeThenIncludesHpkpHeaderAccordingly() throws Exception { this.spring.configLocations(this.xml("DefaultsDisabledWithHpkpMaxAge")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(header().string( - "Public-Key-Pins-Report-Only", + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()) + .andExpect(header().string("Public-Key-Pins-Report-Only", "max-age=604800 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\"")) .andExpect(excludesDefaults()); } @Test - public void requestWhenUsingHpkpReportThenIncludesHpkpHeaderAccordingly() - throws Exception { + public void requestWhenUsingHpkpReportThenIncludesHpkpHeaderAccordingly() throws Exception { this.spring.configLocations(this.xml("DefaultsDisabledWithHpkpReport")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(header().string( - "Public-Key-Pins", + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()) + .andExpect(header().string("Public-Key-Pins", "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\"")) .andExpect(excludesDefaults()); } @Test - public void requestWhenUsingHpkpIncludeSubdomainsThenIncludesHpkpHeaderAccordingly() - throws Exception { + public void requestWhenUsingHpkpIncludeSubdomainsThenIncludesHpkpHeaderAccordingly() throws Exception { this.spring.configLocations(this.xml("DefaultsDisabledWithHpkpIncludeSubdomains")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(header().string( - "Public-Key-Pins-Report-Only", - "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; includeSubDomains")) + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(header().string( + "Public-Key-Pins-Report-Only", + "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; includeSubDomains")) .andExpect(excludesDefaults()); } @Test - public void requestWhenUsingHpkpReportUriThenIncludesHpkpHeaderAccordingly() - throws Exception { + public void requestWhenUsingHpkpReportUriThenIncludesHpkpHeaderAccordingly() throws Exception { this.spring.configLocations(this.xml("DefaultsDisabledWithHpkpReportUri")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(header().string( - "Public-Key-Pins-Report-Only", - "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\"")) + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(header().string( + "Public-Key-Pins-Report-Only", + "max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\"")) .andExpect(excludesDefaults()); } // -- single-header disabled @Test - public void requestWhenCacheControlDisabledThenExcludesHeader() - throws Exception { + public void requestWhenCacheControlDisabledThenExcludesHeader() throws Exception { Collection cacheControl = Arrays.asList("Cache-Control", "Expires", "Pragma"); Map allButCacheControl = remove(defaultHeaders, cacheControl); this.spring.configLocations(this.xml("CacheControlDisabled")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includes(allButCacheControl)) + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(allButCacheControl)) .andExpect(excludes(cacheControl)); } @Test - public void requestWhenContentTypeOptionsDisabledThenExcludesHeader() - throws Exception { + public void requestWhenContentTypeOptionsDisabledThenExcludesHeader() throws Exception { Collection contentTypeOptions = Arrays.asList("X-Content-Type-Options"); Map allButContentTypeOptions = remove(defaultHeaders, contentTypeOptions); this.spring.configLocations(this.xml("ContentTypeOptionsDisabled")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includes(allButContentTypeOptions)) + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(allButContentTypeOptions)) .andExpect(excludes(contentTypeOptions)); } @Test - public void requestWhenHstsDisabledThenExcludesHeader() - throws Exception { + public void requestWhenHstsDisabledThenExcludesHeader() throws Exception { Collection hsts = Arrays.asList("Strict-Transport-Security"); Map allButHsts = remove(defaultHeaders, hsts); this.spring.configLocations(this.xml("HstsDisabled")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includes(allButHsts)) + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(allButHsts)) .andExpect(excludes(hsts)); } @Test - public void requestWhenHpkpDisabledThenExcludesHeader() - throws Exception { + public void requestWhenHpkpDisabledThenExcludesHeader() throws Exception { this.spring.configLocations(this.xml("HpkpDisabled")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includesDefaults()); + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includesDefaults()); } @Test - public void requestWhenFrameOptionsDisabledThenExcludesHeader() - throws Exception { + public void requestWhenFrameOptionsDisabledThenExcludesHeader() throws Exception { Collection frameOptions = Arrays.asList("X-Frame-Options"); Map allButFrameOptions = remove(defaultHeaders, frameOptions); this.spring.configLocations(this.xml("FrameOptionsDisabled")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includes(allButFrameOptions)) + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(allButFrameOptions)) .andExpect(excludes(frameOptions)); } @Test - public void requestWhenXssProtectionDisabledThenExcludesHeader() - throws Exception { + public void requestWhenXssProtectionDisabledThenExcludesHeader() throws Exception { Collection xssProtection = Arrays.asList("X-XSS-Protection"); Map allButXssProtection = remove(defaultHeaders, xssProtection); this.spring.configLocations(this.xml("XssProtectionDisabled")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includes(allButXssProtection)) + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(allButXssProtection)) .andExpect(excludes(xssProtection)); } @@ -676,139 +553,119 @@ public class HttpHeadersConfigTests { @Test public void configureWhenHstsDisabledAndIncludeSubdomainsSpecifiedThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("HstsDisabledSpecifyingIncludeSubdomains")).autowire()) - .isInstanceOf(BeanDefinitionParsingException.class) - .hasMessageContaining("include-subdomains"); + assertThatThrownBy( + () -> this.spring.configLocations(this.xml("HstsDisabledSpecifyingIncludeSubdomains")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class).hasMessageContaining("include-subdomains"); } @Test public void configureWhenHstsDisabledAndMaxAgeSpecifiedThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("HstsDisabledSpecifyingMaxAge")).autowire()) - .isInstanceOf(BeanDefinitionParsingException.class) - .hasMessageContaining("max-age"); + assertThatThrownBy(() -> this.spring.configLocations(this.xml("HstsDisabledSpecifyingMaxAge")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class).hasMessageContaining("max-age"); } @Test public void configureWhenHstsDisabledAndRequestMatcherSpecifiedThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("HstsDisabledSpecifyingRequestMatcher")).autowire()) - .isInstanceOf(BeanDefinitionParsingException.class) - .hasMessageContaining("request-matcher-ref"); + assertThatThrownBy( + () -> this.spring.configLocations(this.xml("HstsDisabledSpecifyingRequestMatcher")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class).hasMessageContaining("request-matcher-ref"); } @Test public void configureWhenXssProtectionDisabledAndEnabledThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("XssProtectionDisabledAndEnabled")).autowire()) - .isInstanceOf(BeanDefinitionParsingException.class) - .hasMessageContaining("enabled"); + assertThatThrownBy(() -> this.spring.configLocations(this.xml("XssProtectionDisabledAndEnabled")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class).hasMessageContaining("enabled"); } @Test public void configureWhenXssProtectionDisabledAndBlockSpecifiedThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("XssProtectionDisabledSpecifyingBlock")).autowire()) - .isInstanceOf(BeanDefinitionParsingException.class) - .hasMessageContaining("block"); + assertThatThrownBy( + () -> this.spring.configLocations(this.xml("XssProtectionDisabledSpecifyingBlock")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class).hasMessageContaining("block"); } @Test public void configureWhenFrameOptionsDisabledAndPolicySpecifiedThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("FrameOptionsDisabledSpecifyingPolicy")).autowire()) - .isInstanceOf(BeanDefinitionParsingException.class) - .hasMessageContaining("policy"); + assertThatThrownBy( + () -> this.spring.configLocations(this.xml("FrameOptionsDisabledSpecifyingPolicy")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class).hasMessageContaining("policy"); } @Test - public void requestWhenContentSecurityPolicyDirectivesConfiguredThenIncludesDirectives() - throws Exception { + public void requestWhenContentSecurityPolicyDirectivesConfiguredThenIncludesDirectives() throws Exception { Map includedHeaders = new HashMap<>(defaultHeaders); includedHeaders.put("Content-Security-Policy", "default-src 'self'"); this.spring.configLocations(this.xml("ContentSecurityPolicyWithPolicyDirectives")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includes(includedHeaders)); + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(includedHeaders)); } @Test - public void requestWhenHeadersDisabledAndContentSecurityPolicyConfiguredThenExcludesHeader() - throws Exception { + public void requestWhenHeadersDisabledAndContentSecurityPolicyConfiguredThenExcludesHeader() throws Exception { this.spring.configLocations(this.xml("HeadersDisabledWithContentSecurityPolicy")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(excludesDefaults()) + this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(excludesDefaults()) .andExpect(excludes("Content-Security-Policy")); } @Test - public void requestWhenDefaultsDisabledAndContentSecurityPolicyConfiguredThenIncludesHeader() - throws Exception { + public void requestWhenDefaultsDisabledAndContentSecurityPolicyConfiguredThenIncludesHeader() throws Exception { this.spring.configLocations(this.xml("DefaultsDisabledWithContentSecurityPolicy")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(excludesDefaults()) + this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(excludesDefaults()) .andExpect(header().string("Content-Security-Policy", "default-src 'self'")); } @Test public void configureWhenContentSecurityPolicyConfiguredWithEmptyDirectivesThenAutowireFails() { - assertThatThrownBy(() -> - this.spring.configLocations(this.xml("ContentSecurityPolicyWithEmptyDirectives")).autowire()) - .isInstanceOf(BeanDefinitionParsingException.class); + assertThatThrownBy( + () -> this.spring.configLocations(this.xml("ContentSecurityPolicyWithEmptyDirectives")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class); } @Test public void requestWhenContentSecurityPolicyConfiguredWithReportOnlyThenIncludesReportOnlyHeader() - throws Exception { + throws Exception { Map includedHeaders = new HashMap<>(defaultHeaders); - includedHeaders.put("Content-Security-Policy-Report-Only", "default-src https:; report-uri https://example.org/"); + includedHeaders.put("Content-Security-Policy-Report-Only", + "default-src https:; report-uri https://example.org/"); this.spring.configLocations(this.xml("ContentSecurityPolicyWithReportOnly")).autowire(); - this.mvc.perform(get("/").secure(true)) - .andExpect(status().isOk()) - .andExpect(includes(includedHeaders)); + this.mvc.perform(get("/").secure(true)).andExpect(status().isOk()).andExpect(includes(includedHeaders)); } @Test - public void requestWhenReferrerPolicyConfiguredThenResponseDefaultsToNoReferrer() - throws Exception { + public void requestWhenReferrerPolicyConfiguredThenResponseDefaultsToNoReferrer() throws Exception { this.spring.configLocations(this.xml("DefaultsDisabledWithReferrerPolicy")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(excludesDefaults()) + this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(excludesDefaults()) .andExpect(header().string("Referrer-Policy", "no-referrer")); } @Test - public void requestWhenReferrerPolicyConfiguredWithSameOriginThenRespondsWithSameOrigin() - throws Exception { + public void requestWhenReferrerPolicyConfiguredWithSameOriginThenRespondsWithSameOrigin() throws Exception { this.spring.configLocations(this.xml("DefaultsDisabledWithReferrerPolicySameOrigin")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isOk()) - .andExpect(excludesDefaults()) + this.mvc.perform(get("/")).andExpect(status().isOk()).andExpect(excludesDefaults()) .andExpect(header().string("Referrer-Policy", "same-origin")); } @RestController public static class SimpleController { + @GetMapping("/") - public String ok() { return "ok"; } + public String ok() { + return "ok"; + } + } private static ResultMatcher includesDefaults() { @@ -817,7 +674,7 @@ public class HttpHeadersConfigTests { private static ResultMatcher includes(Map headers) { return result -> { - for ( Map.Entry header : headers.entrySet() ) { + for (Map.Entry header : headers.entrySet()) { header().string(header.getKey(), header.getValue()).match(result); } }; @@ -829,7 +686,7 @@ public class HttpHeadersConfigTests { private static ResultMatcher excludes(Collection headers) { return result -> { - for ( String name : headers ) { + for (String name : headers) { header().doesNotExist(name).match(result); } }; @@ -842,7 +699,7 @@ public class HttpHeadersConfigTests { private static Map remove(Map map, Collection keys) { Map copy = new HashMap<>(map); - for ( K key : keys ) { + for (K key : keys) { copy.remove(key); } @@ -852,4 +709,5 @@ public class HttpHeadersConfigTests { private String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/HttpInterceptUrlTests.java b/config/src/test/java/org/springframework/security/config/http/HttpInterceptUrlTests.java index e1b9ac6ca3..7befacbb8b 100644 --- a/config/src/test/java/org/springframework/security/config/http/HttpInterceptUrlTests.java +++ b/config/src/test/java/org/springframework/security/config/http/HttpInterceptUrlTests.java @@ -31,6 +31,7 @@ import org.springframework.web.context.ConfigurableWebApplicationContext; import org.springframework.web.context.support.XmlWebApplicationContext; public class HttpInterceptUrlTests { + ConfigurableWebApplicationContext context; MockMvc mockMvc; @@ -46,18 +47,15 @@ public class HttpInterceptUrlTests { public void interceptUrlWhenRequestMatcherRefThenWorks() throws Exception { loadConfig("interceptUrlWhenRequestMatcherRefThenWorks.xml"); - mockMvc.perform(get("/foo")) - .andExpect(status().isUnauthorized()); + mockMvc.perform(get("/foo")).andExpect(status().isUnauthorized()); - mockMvc.perform(get("/FOO")) - .andExpect(status().isUnauthorized()); + mockMvc.perform(get("/FOO")).andExpect(status().isUnauthorized()); - mockMvc.perform(get("/other")) - .andExpect(status().isOk()); + mockMvc.perform(get("/other")).andExpect(status().isOk()); } private void loadConfig(String... configLocations) { - for (int i=0; i> answer = invocation -> - Collections.singletonMap("spring", registration); + Answer> answer = invocation -> Collections.singletonMap("spring", + registration); when(servletContext.getServletRegistrations()).thenAnswer(answer); return servletContext; } @@ -290,4 +243,5 @@ public class InterceptUrlConfigTests { private String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java b/config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java index 4049067b0f..0ae303e831 100644 --- a/config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java @@ -127,15 +127,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - /** - * * @author Luke Taylor * @author Rob Winch */ public class MiscHttpConfigTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/MiscHttpConfigTests"; + + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/MiscHttpConfigTests"; @Autowired MockMvc mvc; @@ -161,192 +159,139 @@ public class MiscHttpConfigTests { } @Test - public void requestWhenUsingDebugFilterAndPatternIsNotConfigureForSecurityThenRespondsOk() - throws Exception { + public void requestWhenUsingDebugFilterAndPatternIsNotConfigureForSecurityThenRespondsOk() throws Exception { this.spring.configLocations(xml("NoSecurityForPattern")).autowire(); - this.mvc.perform(get("/unprotected")) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/unprotected")).andExpect(status().isNotFound()); - this.mvc.perform(get("/nomatch")) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/nomatch")).andExpect(status().isNotFound()); } @Test - public void requestWhenHttpPatternUsesRegexMatchingThenMatchesAccordingly() - throws Exception { + public void requestWhenHttpPatternUsesRegexMatchingThenMatchesAccordingly() throws Exception { this.spring.configLocations(xml("RegexSecurityPattern")).autowire(); - this.mvc.perform(get("/protected")) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/protected")).andExpect(status().isUnauthorized()); - this.mvc.perform(get("/unprotected")) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/unprotected")).andExpect(status().isNotFound()); } @Test - public void requestWhenHttpPatternUsesCiRegexMatchingThenMatchesAccordingly() - throws Exception { + public void requestWhenHttpPatternUsesCiRegexMatchingThenMatchesAccordingly() throws Exception { this.spring.configLocations(xml("CiRegexSecurityPattern")).autowire(); - this.mvc.perform(get("/ProTectEd")) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/ProTectEd")).andExpect(status().isUnauthorized()); - this.mvc.perform(get("/UnProTectEd")) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/UnProTectEd")).andExpect(status().isNotFound()); } @Test - public void requestWhenHttpPatternUsesCustomRequestMatcherThenMatchesAccordingly() - throws Exception { + public void requestWhenHttpPatternUsesCustomRequestMatcherThenMatchesAccordingly() throws Exception { this.spring.configLocations(xml("CustomRequestMatcher")).autowire(); - this.mvc.perform(get("/protected")) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/protected")).andExpect(status().isUnauthorized()); - this.mvc.perform(get("/unprotected")) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/unprotected")).andExpect(status().isNotFound()); } /** * SEC-1152 */ @Test - public void requestWhenUsingMinimalConfigurationThenHonorsAnonymousEndpoints() - throws Exception { + public void requestWhenUsingMinimalConfigurationThenHonorsAnonymousEndpoints() throws Exception { this.spring.configLocations(xml("AnonymousEndpoints")).autowire(); - this.mvc.perform(get("/protected")) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/protected")).andExpect(status().isUnauthorized()); - this.mvc.perform(get("/unprotected")) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/unprotected")).andExpect(status().isNotFound()); assertThat(getFilter(AnonymousAuthenticationFilter.class)).isNotNull(); } @Test - public void requestWhenAnonymousIsDisabledThenRejectsAnonymousEndpoints() - throws Exception { + public void requestWhenAnonymousIsDisabledThenRejectsAnonymousEndpoints() throws Exception { this.spring.configLocations(xml("AnonymousDisabled")).autowire(); - this.mvc.perform(get("/protected")) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/protected")).andExpect(status().isUnauthorized()); - this.mvc.perform(get("/unprotected")) - .andExpect(status().isUnauthorized()); + this.mvc.perform(get("/unprotected")).andExpect(status().isUnauthorized()); assertThat(getFilter(AnonymousAuthenticationFilter.class)).isNull(); } @Test - public void requestWhenAnonymousUsesCustomAttributesThenRespondsWithThoseAttributes() - throws Exception { + public void requestWhenAnonymousUsesCustomAttributesThenRespondsWithThoseAttributes() throws Exception { this.spring.configLocations(xml("AnonymousCustomAttributes")).autowire(); - this.mvc.perform(get("/protected") - .with(httpBasic("user", "password"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/protected").with(httpBasic("user", "password"))).andExpect(status().isForbidden()); - this.mvc.perform(get("/protected")) - .andExpect(status().isOk()) - .andExpect(content().string("josh")); + this.mvc.perform(get("/protected")).andExpect(status().isOk()).andExpect(content().string("josh")); - this.mvc.perform(get("/customKey")) - .andExpect(status().isOk()) + this.mvc.perform(get("/customKey")).andExpect(status().isOk()) .andExpect(content().string(String.valueOf("myCustomKey".hashCode()))); } @Test - public void requestWhenAnonymousUsesMultipleGrantedAuthoritiesThenRespondsWithThoseAttributes() - throws Exception { + public void requestWhenAnonymousUsesMultipleGrantedAuthoritiesThenRespondsWithThoseAttributes() throws Exception { this.spring.configLocations(xml("AnonymousMultipleAuthorities")).autowire(); - this.mvc.perform(get("/protected") - .with(httpBasic("user", "password"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/protected").with(httpBasic("user", "password"))).andExpect(status().isForbidden()); - this.mvc.perform(get("/protected")) - .andExpect(status().isOk()) - .andExpect(content().string("josh")); + this.mvc.perform(get("/protected")).andExpect(status().isOk()).andExpect(content().string("josh")); - this.mvc.perform(get("/customKey")) - .andExpect(status().isOk()) + this.mvc.perform(get("/customKey")).andExpect(status().isOk()) .andExpect(content().string(String.valueOf("myCustomKey".hashCode()))); } @Test - public void requestWhenInterceptUrlMatchesMethodThenSecuresAccordingly() - throws Exception { + public void requestWhenInterceptUrlMatchesMethodThenSecuresAccordingly() throws Exception { this.spring.configLocations(xml("InterceptUrlMethod")).autowire(); - this.mvc.perform(get("/protected") - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/protected").with(httpBasic("user", "password"))).andExpect(status().isOk()); - this.mvc.perform(post("/protected") - .with(httpBasic("user", "password"))) - .andExpect(status().isForbidden()); + this.mvc.perform(post("/protected").with(httpBasic("user", "password"))).andExpect(status().isForbidden()); - this.mvc.perform(post("/protected") - .with(httpBasic("poster", "password"))) - .andExpect(status().isOk()); + this.mvc.perform(post("/protected").with(httpBasic("poster", "password"))).andExpect(status().isOk()); - this.mvc.perform(delete("/protected") - .with(httpBasic("poster", "password"))) - .andExpect(status().isForbidden()); + this.mvc.perform(delete("/protected").with(httpBasic("poster", "password"))).andExpect(status().isForbidden()); - this.mvc.perform(delete("/protected") - .with(httpBasic("admin", "password"))) - .andExpect(status().isOk()); + this.mvc.perform(delete("/protected").with(httpBasic("admin", "password"))).andExpect(status().isOk()); } @Test - public void requestWhenInterceptUrlMatchesMethodAndRequiresHttpsThenSecuresAccordingly() - throws Exception { + public void requestWhenInterceptUrlMatchesMethodAndRequiresHttpsThenSecuresAccordingly() throws Exception { this.spring.configLocations(xml("InterceptUrlMethodRequiresHttps")).autowire(); - this.mvc.perform(post("/protected").with(csrf())) - .andExpect(status().isOk()); + this.mvc.perform(post("/protected").with(csrf())).andExpect(status().isOk()); - this.mvc.perform(get("/protected") - .secure(true) - .with(httpBasic("user", "password"))) + this.mvc.perform(get("/protected").secure(true).with(httpBasic("user", "password"))) .andExpect(status().isForbidden()); - this.mvc.perform(get("/protected") - .secure(true) - .with(httpBasic("admin", "password"))) + this.mvc.perform(get("/protected").secure(true).with(httpBasic("admin", "password"))) .andExpect(status().isOk()); } @Test - public void requestWhenInterceptUrlMatchesAnyPatternAndRequiresHttpsThenSecuresAccordingly() - throws Exception { + public void requestWhenInterceptUrlMatchesAnyPatternAndRequiresHttpsThenSecuresAccordingly() throws Exception { this.spring.configLocations(xml("InterceptUrlMethodRequiresHttpsAny")).autowire(); - this.mvc.perform(post("/protected").with(csrf())) - .andExpect(status().isOk()); + this.mvc.perform(post("/protected").with(csrf())).andExpect(status().isOk()); - this.mvc.perform(get("/protected") - .secure(true) - .with(httpBasic("user", "password"))) + this.mvc.perform(get("/protected").secure(true).with(httpBasic("user", "password"))) .andExpect(status().isForbidden()); - this.mvc.perform(get("/protected") - .secure(true) - .with(httpBasic("admin", "password"))) + this.mvc.perform(get("/protected").secure(true).with(httpBasic("admin", "password"))) .andExpect(status().isOk()); } @@ -359,18 +304,16 @@ public class MiscHttpConfigTests { } @Test - public void requestWhenCustomHttpBasicEntryPointRefThenInvokesOnCommence() - throws Exception { + public void requestWhenCustomHttpBasicEntryPointRefThenInvokesOnCommence() throws Exception { this.spring.configLocations(xml("CustomHttpBasicEntryPointRef")).autowire(); AuthenticationEntryPoint entryPoint = this.spring.getContext().getBean(AuthenticationEntryPoint.class); - this.mvc.perform(get("/protected")) - .andExpect(status().isOk()); + this.mvc.perform(get("/protected")).andExpect(status().isOk()); - verify(entryPoint).commence( - any(HttpServletRequest.class), any(HttpServletResponse.class), any(AuthenticationException.class)); + verify(entryPoint).commence(any(HttpServletRequest.class), any(HttpServletResponse.class), + any(AuthenticationException.class)); } @Test @@ -396,12 +339,9 @@ public class MiscHttpConfigTests { Class userFilterClass = this.spring.getContext().getBean("userFilter").getClass(); - assertThat(filters) - .extracting((Extractor>) filter -> filter.getClass()) - .containsSubsequence( - userFilterClass, userFilterClass, - SecurityContextPersistenceFilter.class, LogoutFilter.class, - userFilterClass); + assertThat(filters).extracting((Extractor>) filter -> filter.getClass()).containsSubsequence( + userFilterClass, userFilterClass, SecurityContextPersistenceFilter.class, LogoutFilter.class, + userFilterClass); } @Test @@ -414,13 +354,11 @@ public class MiscHttpConfigTests { public void configureWhenUsingX509ThenAddsX509FilterCorrectly() { this.spring.configLocations(xml("X509")).autowire(); - assertThat(getFilters("/")) - .extracting((Extractor>) filter -> filter.getClass()) - .containsSubsequence( - CsrfFilter.class, X509AuthenticationFilter.class, ExceptionTranslationFilter.class); + assertThat(getFilters("/")).extracting((Extractor>) filter -> filter.getClass()) + .containsSubsequence(CsrfFilter.class, X509AuthenticationFilter.class, + ExceptionTranslationFilter.class); } - @Test public void getWhenUsingX509AndPropertyPlaceholderThenSubjectPrincipalRegexIsConfigured() throws Exception { System.setProperty("subject_principal_regex", "OU=(.*?)(?:,|$)"); @@ -441,8 +379,7 @@ public class MiscHttpConfigTests { public void logoutWhenSpecifyingCookiesToDeleteThenSetCookieAdded() throws Exception { this.spring.configLocations(xml("DeleteCookies")).autowire(); - MvcResult result = - this.mvc.perform(post("/logout").with(csrf())).andReturn(); + MvcResult result = this.mvc.perform(post("/logout").with(csrf())).andReturn(); List values = result.getResponse().getHeaders("Set-Cookie"); assertThat(values.size()).isEqualTo(2); @@ -453,8 +390,7 @@ public class MiscHttpConfigTests { public void logoutWhenSpecifyingSuccessHandlerRefThenResponseHandledAccordingly() throws Exception { this.spring.configLocations(xml("LogoutSuccessHandlerRef")).autowire(); - this.mvc.perform(post("/logout").with(csrf())) - .andExpect(redirectedUrl("/logoutSuccessEndpoint")); + this.mvc.perform(post("/logout").with(csrf())).andExpect(redirectedUrl("/logoutSuccessEndpoint")); } @Test @@ -476,28 +412,25 @@ public class MiscHttpConfigTests { this.mvc.perform(get("/")); - verify(entryPoint).commence( - any(HttpServletRequest.class), - any(HttpServletResponse.class), + verify(entryPoint).commence(any(HttpServletRequest.class), any(HttpServletResponse.class), any(AuthenticationException.class)); } /** - * See SEC-750. If the http security post processor causes beans to be instantiated too eagerly, they way miss - * additional processing. In this method we have a UserDetailsService which is referenced from the namespace - * and also has a post processor registered which will modify it. + * See SEC-750. If the http security post processor causes beans to be instantiated + * too eagerly, they way miss additional processing. In this method we have a + * UserDetailsService which is referenced from the namespace and also has a post + * processor registered which will modify it. */ @Test public void configureWhenUsingCustomUserDetailsServiceThenBeanPostProcessorsAreStillApplied() { this.spring.configLocations(xml("Sec750")).autowire(); - BeanNameCollectingPostProcessor postProcessor = - this.spring.getContext().getBean(BeanNameCollectingPostProcessor.class); + BeanNameCollectingPostProcessor postProcessor = this.spring.getContext() + .getBean(BeanNameCollectingPostProcessor.class); - assertThat(postProcessor.getBeforeInitPostProcessedBeans()) - .contains("authenticationProvider", "userService"); - assertThat(postProcessor.getAfterInitPostProcessedBeans()) - .contains("authenticationProvider", "userService"); + assertThat(postProcessor.getBeforeInitPostProcessedBeans()).contains("authenticationProvider", "userService"); + assertThat(postProcessor.getAfterInitPostProcessedBeans()).contains("authenticationProvider", "userService"); } @@ -506,13 +439,9 @@ public class MiscHttpConfigTests { public void getWhenUsingTwoIdenticalInterceptUrlsThenTheSecondTakesPrecedence() throws Exception { this.spring.configLocations(xml("Sec934")).autowire(); - this.mvc.perform(get("/protected") - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/protected").with(httpBasic("user", "password"))).andExpect(status().isOk()); - this.mvc.perform(get("/protected") - .with(httpBasic("admin", "password"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/protected").with(httpBasic("admin", "password"))).andExpect(status().isForbidden()); } @Test @@ -523,17 +452,12 @@ public class MiscHttpConfigTests { SecurityContext context = new SecurityContextImpl(new TestingAuthenticationToken("user", "password")); when(repository.loadContext(any(HttpRequestResponseHolder.class))).thenReturn(context); - MvcResult result = - this.mvc.perform(get("/protected") - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/protected").with(httpBasic("user", "password"))) + .andExpect(status().isOk()).andReturn(); assertThat(result.getRequest().getSession(false)).isNotNull(); - verify(repository, atLeastOnce()).saveContext( - any(SecurityContext.class), - any(HttpServletRequest.class), + verify(repository, atLeastOnce()).saveContext(any(SecurityContext.class), any(HttpServletRequest.class), any(HttpServletResponse.class)); } @@ -541,17 +465,11 @@ public class MiscHttpConfigTests { public void getWhenUsingInterceptUrlExpressionsThenAuthorizesAccordingly() throws Exception { this.spring.configLocations(xml("InterceptUrlExpressions")).autowire(); - this.mvc.perform(get("/protected") - .with(httpBasic("admin", "password"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/protected").with(httpBasic("admin", "password"))).andExpect(status().isOk()); - this.mvc.perform(get("/protected") - .with(httpBasic("user", "password"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/protected").with(httpBasic("user", "password"))).andExpect(status().isForbidden()); - this.mvc.perform(get("/unprotected") - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/unprotected").with(httpBasic("user", "password"))).andExpect(status().isOk()); } @@ -563,9 +481,7 @@ public class MiscHttpConfigTests { when(permissionEvaluator.hasPermission(any(Authentication.class), any(Object.class), any(Object.class))) .thenReturn(false); - this.mvc.perform(get("/") - .with(httpBasic("user", "password"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isForbidden()); verify(permissionEvaluator).hasPermission(any(Authentication.class), any(Object.class), any(Object.class)); } @@ -591,10 +507,8 @@ public class MiscHttpConfigTests { FilterChainProxy proxy = this.spring.getContext().getBean(FilterChainProxy.class); - proxy.doFilter( - request, - new EncodeUrlDenyingHttpServletResponseWrapper(response), - (req, resp) -> {}); + proxy.doFilter(request, new EncodeUrlDenyingHttpServletResponseWrapper(response), (req, resp) -> { + }); assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_MOVED_TEMPORARILY); assertThat(response.getRedirectedUrl()).isEqualTo("http://localhost/login"); @@ -605,11 +519,11 @@ public class MiscHttpConfigTests { assertThatCode(() -> this.spring.configLocations(this.xml("MissingUserDetailsService")).autowire()) .isInstanceOf(BeansException.class); - try ( XmlWebApplicationContext parent = new XmlWebApplicationContext() ) { + try (XmlWebApplicationContext parent = new XmlWebApplicationContext()) { parent.setConfigLocations(this.xml("AutoConfig")); parent.refresh(); - try ( XmlWebApplicationContext child = new XmlWebApplicationContext() ) { + try (XmlWebApplicationContext child = new XmlWebApplicationContext()) { child.setParent(parent); child.setConfigLocation(this.xml("MissingUserDetailsService")); child.refresh(); @@ -623,9 +537,7 @@ public class MiscHttpConfigTests { this.spring.configLocations(xml("NoInternalAuthenticationProviders")).autowire(); - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password")) + this.mvc.perform(post("/login").param("username", "user").param("password", "password")) .andExpect(redirectedUrl("/")); } @@ -633,20 +545,16 @@ public class MiscHttpConfigTests { public void loginWhenUsingDefaultsThenErasesCredentialsAfterAuthentication() throws Exception { this.spring.configLocations(xml("HttpBasic")).autowire(); - this.mvc.perform(get("/password") - .with(httpBasic("user", "password"))) - .andExpect(content().string("")); + this.mvc.perform(get("/password").with(httpBasic("user", "password"))).andExpect(content().string("")); } @Test public void loginWhenAuthenticationManagerConfiguredToEraseCredentialsThenErasesCredentialsAfterAuthentication() - throws Exception { + throws Exception { this.spring.configLocations(xml("AuthenticationManagerEraseCredentials")).autowire(); - this.mvc.perform(get("/password") - .with(httpBasic("user", "password"))) - .andExpect(content().string("")); + this.mvc.perform(get("/password").with(httpBasic("user", "password"))).andExpect(content().string("")); } /** @@ -654,24 +562,20 @@ public class MiscHttpConfigTests { */ @Test public void loginWhenAuthenticationManagerRefConfiguredToKeepCredentialsThenKeepsCredentialsAfterAuthentication() - throws Exception { + throws Exception { this.spring.configLocations(xml("AuthenticationManagerRefKeepCredentials")).autowire(); - this.mvc.perform(get("/password") - .with(httpBasic("user", "password"))) - .andExpect(content().string("password")); + this.mvc.perform(get("/password").with(httpBasic("user", "password"))).andExpect(content().string("password")); } @Test public void loginWhenAuthenticationManagerRefIsNotAProviderManagerThenKeepsCredentialsAccordingly() - throws Exception { + throws Exception { this.spring.configLocations(xml("AuthenticationManagerRefNotProviderManager")).autowire(); - this.mvc.perform(get("/password") - .with(httpBasic("user", "password"))) - .andExpect(content().string("password")); + this.mvc.perform(get("/password").with(httpBasic("user", "password"))).andExpect(content().string("password")); } @Test @@ -681,20 +585,17 @@ public class MiscHttpConfigTests { Principal user = mock(Principal.class); when(user.getName()).thenReturn("joe"); - this.mvc.perform(get("/roles") - .principal(user) - .with(request -> { - request.addUserRole("admin"); - request.addUserRole("user"); - request.addUserRole("unmapped"); - return request; - })) - .andExpect(content().string("ROLE_admin,ROLE_user")); + this.mvc.perform(get("/roles").principal(user).with(request -> { + request.addUserRole("admin"); + request.addUserRole("user"); + request.addUserRole("unmapped"); + return request; + })).andExpect(content().string("ROLE_admin,ROLE_user")); } @Test public void loginWhenUsingCustomAuthenticationDetailsSourceRefThenAuthenticationSourcesDetailsAccordingly() - throws Exception { + throws Exception { this.spring.configLocations(xml("CustomAuthenticationDetailsSourceRef")).autowire(); @@ -702,24 +603,18 @@ public class MiscHttpConfigTests { AuthenticationDetailsSource source = this.spring.getContext().getBean(AuthenticationDetailsSource.class); when(source.buildDetails(any(Object.class))).thenReturn(details); - this.mvc.perform(get("/details") - .with(httpBasic("user", "password"))) + this.mvc.perform(get("/details").with(httpBasic("user", "password"))) .andExpect(content().string(details.getClass().getName())); this.mvc.perform(get("/details") .with(x509("classpath:org/springframework/security/config/http/MiscHttpConfigTests-certificate.pem"))) .andExpect(content().string(details.getClass().getName())); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .with(csrf())) - .andReturn().getRequest().getSession(false); + MockHttpSession session = (MockHttpSession) this.mvc + .perform(post("/login").param("username", "user").param("password", "password").with(csrf())) + .andReturn().getRequest().getSession(false); - this.mvc.perform(get("/details") - .session(session)) - .andExpect(content().string(details.getClass().getName())); + this.mvc.perform(get("/details").session(session)).andExpect(content().string(details.getClass().getName())); assertThat(getField(getFilter(OpenIDAuthenticationFilter.class), "authenticationDetailsSource")) .isEqualTo(source); @@ -732,9 +627,7 @@ public class MiscHttpConfigTests { AuthorityGranter granter = this.spring.getContext().getBean(AuthorityGranter.class); when(granter.grant(any(Principal.class))).thenReturn(new HashSet<>(Arrays.asList("USER"))); - this.mvc.perform(get("/username") - .with(httpBasic("user", "password"))) - .andExpect(content().string("user")); + this.mvc.perform(get("/username").with(httpBasic("user", "password"))).andExpect(content().string("user")); } @Test @@ -743,7 +636,8 @@ public class MiscHttpConfigTests { FirewalledRequest request = new FirewalledRequest(new MockHttpServletRequest()) { @Override - public void reset() { } + public void reset() { + } }; HttpServletResponse response = new MockHttpServletResponse(); @@ -775,9 +669,7 @@ public class MiscHttpConfigTests { public void getWhenUsingCustomAccessDecisionManagerThenAuthorizesAccordingly() throws Exception { this.spring.configLocations(xml("CustomAccessDecisionManager")).autowire(); - this.mvc.perform(get("/unprotected") - .with(httpBasic("user", "password"))) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/unprotected").with(httpBasic("user", "password"))).andExpect(status().isForbidden()); } /** @@ -787,27 +679,22 @@ public class MiscHttpConfigTests { public void authenticateWhenUsingPortMapperThenRedirectsAppropriately() throws Exception { this.spring.configLocations(xml("PortsMappedRequiresHttps")).autowire(); - MockHttpSession session = (MockHttpSession) - this.mvc.perform(get("https://localhost:9080/protected")) - .andExpect(redirectedUrl("https://localhost:9443/login")) - .andReturn().getRequest().getSession(false); + MockHttpSession session = (MockHttpSession) this.mvc.perform(get("https://localhost:9080/protected")) + .andExpect(redirectedUrl("https://localhost:9443/login")).andReturn().getRequest().getSession(false); - session = (MockHttpSession) - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .session(session) - .with(csrf())) - .andExpect(redirectedUrl("https://localhost:9443/protected")) - .andReturn().getRequest().getSession(false); + session = (MockHttpSession) this.mvc + .perform(post("/login").param("username", "user").param("password", "password").session(session) + .with(csrf())) + .andExpect(redirectedUrl("https://localhost:9443/protected")).andReturn().getRequest() + .getSession(false); - this.mvc.perform(get("http://localhost:9080/protected") - .session(session)) + this.mvc.perform(get("http://localhost:9080/protected").session(session)) .andExpect(redirectedUrl("https://localhost:9443/protected")); } @RestController static class BasicController { + @RequestMapping("/unprotected") public String unprotected() { return "ok"; @@ -817,27 +704,28 @@ public class MiscHttpConfigTests { public String protectedMethod(@AuthenticationPrincipal String name) { return name; } + } @RestController static class CustomKeyController { + @GetMapping("/customKey") public String customKey() { - Authentication authentication = - SecurityContextHolder.getContext().getAuthentication(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if ( authentication != null && - authentication instanceof AnonymousAuthenticationToken ) { - return String.valueOf( - ((AnonymousAuthenticationToken) authentication).getKeyHash()); + if (authentication != null && authentication instanceof AnonymousAuthenticationToken) { + return String.valueOf(((AnonymousAuthenticationToken) authentication).getKeyHash()); } return null; } + } @RestController static class AuthenticationController { + @GetMapping("/password") public String password(@AuthenticationPrincipal Authentication authentication) { return (String) authentication.getCredentials(); @@ -845,8 +733,7 @@ public class MiscHttpConfigTests { @GetMapping("/roles") public String roles(@AuthenticationPrincipal Authentication authentication) { - return authentication.getAuthorities().stream() - .map(GrantedAuthority::getAuthority) + return authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority) .collect(Collectors.joining(",")); } @@ -854,22 +741,27 @@ public class MiscHttpConfigTests { public String details(@AuthenticationPrincipal Authentication authentication) { return authentication.getDetails().getClass().getName(); } + } @RestController static class JaasController { + @GetMapping("/username") public String username() { Subject subject = Subject.getSubject(AccessController.getContext()); return subject.getPrincipals().iterator().next().getName(); } + } public static class JaasLoginModule implements LoginModule { + private Subject subject; @Override - public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { + public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, + Map options) { this.subject = subject; } @@ -892,12 +784,14 @@ public class MiscHttpConfigTests { public boolean logout() { return true; } + } static class MockAccessDecisionManager implements AccessDecisionManager { @Override - public void decide(Authentication authentication, Object object, Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { + public void decide(Authentication authentication, Object object, Collection configAttributes) + throws AccessDeniedException, InsufficientAuthenticationException { throw new AccessDeniedException("teapot"); } @@ -910,18 +804,19 @@ public class MiscHttpConfigTests { public boolean supports(Class clazz) { return true; } + } static class MockAuthenticationManager implements AuthenticationManager { + public Authentication authenticate(Authentication authentication) { - return new TestingAuthenticationToken(authentication.getPrincipal(), - authentication.getCredentials(), + return new TestingAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), AuthorityUtils.createAuthorityList("ROLE_USER")); } + } - static class EncodeUrlDenyingHttpServletResponseWrapper - extends HttpServletResponseWrapper { + static class EncodeUrlDenyingHttpServletResponseWrapper extends HttpServletResponseWrapper { EncodeUrlDenyingHttpServletResponseWrapper(HttpServletResponse response) { super(response); @@ -946,6 +841,7 @@ public class MiscHttpConfigTests { public String encodeRedirectUrl(String url) { throw new RuntimeException("Unexpected invocation of encodeURL"); } + } private void redirectLogsTo(OutputStream os, Class clazz) { @@ -1000,4 +896,5 @@ public class MiscHttpConfigTests { private static String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/MultiHttpBlockConfigTests.java b/config/src/test/java/org/springframework/security/config/http/MultiHttpBlockConfigTests.java index 9e33b67e2e..d3e8929d0d 100644 --- a/config/src/test/java/org/springframework/security/config/http/MultiHttpBlockConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/MultiHttpBlockConfigTests.java @@ -40,8 +40,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Luke Taylor */ public class MultiHttpBlockConfigTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/MultiHttpBlockConfigTests"; + + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/MultiHttpBlockConfigTests"; @Autowired MockMvc mvc; @@ -50,35 +50,27 @@ public class MultiHttpBlockConfigTests { public final SpringTestRule spring = new SpringTestRule(); @Test - public void requestWhenUsingMutuallyExclusiveHttpElementsThenIsRoutedAccordingly() - throws Exception { + public void requestWhenUsingMutuallyExclusiveHttpElementsThenIsRoutedAccordingly() throws Exception { this.spring.configLocations(this.xml("DistinctHttpElements")).autowire(); - this.mvc.perform(MockMvcRequestBuilders.get("/first") - .with(httpBasic("user", "password"))) + this.mvc.perform(MockMvcRequestBuilders.get("/first").with(httpBasic("user", "password"))) .andExpect(status().isOk()); - this.mvc.perform(post("/second/login") - .param("username", "user") - .param("password", "password") - .with(csrf())) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/")); + this.mvc.perform(post("/second/login").param("username", "user").param("password", "password").with(csrf())) + .andExpect(status().isFound()).andExpect(redirectedUrl("/")); } @Test public void configureWhenUsingDuplicateHttpElementsThenThrowsWiringException() { assertThatCode(() -> this.spring.configLocations(this.xml("IdenticalHttpElements")).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasCauseInstanceOf(IllegalArgumentException.class); + .isInstanceOf(BeanCreationException.class).hasCauseInstanceOf(IllegalArgumentException.class); } @Test public void configureWhenUsingIndenticallyPatternedHttpElementsThenThrowsWiringException() { assertThatCode(() -> this.spring.configLocations(this.xml("IdenticallyPatternedHttpElements")).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasCauseInstanceOf(IllegalArgumentException.class); + .isInstanceOf(BeanCreationException.class).hasCauseInstanceOf(IllegalArgumentException.class); } /** @@ -90,27 +82,24 @@ public class MultiHttpBlockConfigTests { this.spring.configLocations(this.xml("Sec1937")).autowire(); - this.mvc.perform(get("/first") - .with(httpBasic("first", "password")) - .with(csrf())) - .andExpect(status().isOk()); + this.mvc.perform(get("/first").with(httpBasic("first", "password")).with(csrf())).andExpect(status().isOk()); - this.mvc.perform(post("/second/login") - .param("username", "second") - .param("password", "password") - .with(csrf())) + this.mvc.perform(post("/second/login").param("username", "second").param("password", "password").with(csrf())) .andExpect(redirectedUrl("/")); } @Controller static class BasicController { + @GetMapping("/first") public String first() { return "ok"; } + } private String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/NamespaceHttpBasicTests.java b/config/src/test/java/org/springframework/security/config/http/NamespaceHttpBasicTests.java index 6aecdb0335..028ccf8f6a 100644 --- a/config/src/test/java/org/springframework/security/config/http/NamespaceHttpBasicTests.java +++ b/config/src/test/java/org/springframework/security/config/http/NamespaceHttpBasicTests.java @@ -39,11 +39,14 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Rob Winch */ public class NamespaceHttpBasicTests { + @Mock Method method; MockHttpServletRequest request; + MockHttpServletResponse response; + MockFilterChain chain; ConfigurableApplicationContext context; @@ -114,7 +117,7 @@ public class NamespaceHttpBasicTests { private void loadContext(String context) { this.context = new InMemoryXmlApplicationContext(context); - this.springSecurityFilterChain = this.context.getBean("springSecurityFilterChain", - Filter.class); + this.springSecurityFilterChain = this.context.getBean("springSecurityFilterChain", Filter.class); } + } diff --git a/config/src/test/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserTests.java index c146779731..8054abe785 100644 --- a/config/src/test/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserTests.java @@ -68,6 +68,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @RunWith(SpringJUnit4ClassRunner.class) @SecurityTestExecutionListeners public class OAuth2ClientBeanDefinitionParserTests { + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserTests"; @Rule @@ -98,13 +99,11 @@ public class OAuth2ClientBeanDefinitionParserTests { public void requestWhenAuthorizeThenRedirect() throws Exception { this.spring.configLocations(xml("Minimal")).autowire(); - MvcResult result = this.mvc.perform(get("/oauth2/authorization/google")) - .andExpect(status().is3xxRedirection()) + MvcResult result = this.mvc.perform(get("/oauth2/authorization/google")).andExpect(status().is3xxRedirection()) .andReturn(); assertThat(result.getResponse().getRedirectedUrl()).matches( - "https://accounts.google.com/o/oauth2/v2/auth\\?" + - "response_type=code&client_id=google-client-id&" + - "scope=scope1%20scope2&state=.{15,}&redirect_uri=http://localhost/callback/google"); + "https://accounts.google.com/o/oauth2/v2/auth\\?" + "response_type=code&client_id=google-client-id&" + + "scope=scope1%20scope2&state=.{15,}&redirect_uri=http://localhost/callback/google"); } @Test @@ -112,20 +111,15 @@ public class OAuth2ClientBeanDefinitionParserTests { this.spring.configLocations(xml("CustomClientRegistrationRepository")).autowire(); ClientRegistration clientRegistration = CommonOAuth2Provider.GOOGLE.getBuilder("google") - .clientId("google-client-id") - .clientSecret("google-client-secret") - .redirectUri("http://localhost/callback/google") - .scope("scope1", "scope2") - .build(); + .clientId("google-client-id").clientSecret("google-client-secret") + .redirectUri("http://localhost/callback/google").scope("scope1", "scope2").build(); when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(clientRegistration); - MvcResult result = this.mvc.perform(get("/oauth2/authorization/google")) - .andExpect(status().is3xxRedirection()) + MvcResult result = this.mvc.perform(get("/oauth2/authorization/google")).andExpect(status().is3xxRedirection()) .andReturn(); assertThat(result.getResponse().getRedirectedUrl()).matches( - "https://accounts.google.com/o/oauth2/v2/auth\\?" + - "response_type=code&client_id=google-client-id&" + - "scope=scope1%20scope2&state=.{15,}&redirect_uri=http://localhost/callback/google"); + "https://accounts.google.com/o/oauth2/v2/auth\\?" + "response_type=code&client_id=google-client-id&" + + "scope=scope1%20scope2&state=.{15,}&redirect_uri=http://localhost/callback/google"); verify(this.clientRegistrationRepository).findByRegistrationId(any()); } @@ -139,12 +133,10 @@ public class OAuth2ClientBeanDefinitionParserTests { OAuth2AuthorizationRequest authorizationRequest = createAuthorizationRequest(clientRegistration); when(this.authorizationRequestResolver.resolve(any())).thenReturn(authorizationRequest); - this.mvc.perform(get("/oauth2/authorization/google")) - .andExpect(status().is3xxRedirection()) - .andExpect(redirectedUrl( - "https://accounts.google.com/o/oauth2/v2/auth?" + - "response_type=code&client_id=google-client-id&" + - "scope=scope1%20scope2&state=state&redirect_uri=http://localhost/callback/google")); + this.mvc.perform(get("/oauth2/authorization/google")).andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("https://accounts.google.com/o/oauth2/v2/auth?" + + "response_type=code&client_id=google-client-id&" + + "scope=scope1%20scope2&state=state&redirect_uri=http://localhost/callback/google")); verify(this.authorizationRequestResolver).resolve(any()); } @@ -156,8 +148,7 @@ public class OAuth2ClientBeanDefinitionParserTests { ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("google"); OAuth2AuthorizationRequest authorizationRequest = createAuthorizationRequest(clientRegistration); - when(this.authorizationRequestRepository.loadAuthorizationRequest(any())) - .thenReturn(authorizationRequest); + when(this.authorizationRequestRepository.loadAuthorizationRequest(any())).thenReturn(authorizationRequest); when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())) .thenReturn(authorizationRequest); @@ -168,13 +159,12 @@ public class OAuth2ClientBeanDefinitionParserTests { params.add("code", "code123"); params.add("state", authorizationRequest.getState()); this.mvc.perform(get(authorizationRequest.getRedirectUri()).params(params)) - .andExpect(status().is3xxRedirection()) - .andExpect(redirectedUrl(authorizationRequest.getRedirectUri())); + .andExpect(status().is3xxRedirection()).andExpect(redirectedUrl(authorizationRequest.getRedirectUri())); - ArgumentCaptor authorizedClientCaptor = - ArgumentCaptor.forClass(OAuth2AuthorizedClient.class); - verify(this.authorizedClientRepository).saveAuthorizedClient( - authorizedClientCaptor.capture(), any(), any(), any()); + ArgumentCaptor authorizedClientCaptor = ArgumentCaptor + .forClass(OAuth2AuthorizedClient.class); + verify(this.authorizedClientRepository).saveAuthorizedClient(authorizedClientCaptor.capture(), any(), any(), + any()); OAuth2AuthorizedClient authorizedClient = authorizedClientCaptor.getValue(); assertThat(authorizedClient.getClientRegistration()).isEqualTo(clientRegistration); assertThat(authorizedClient.getAccessToken()).isEqualTo(accessTokenResponse.getAccessToken()); @@ -188,8 +178,7 @@ public class OAuth2ClientBeanDefinitionParserTests { ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("google"); OAuth2AuthorizationRequest authorizationRequest = createAuthorizationRequest(clientRegistration); - when(this.authorizationRequestRepository.loadAuthorizationRequest(any())) - .thenReturn(authorizationRequest); + when(this.authorizationRequestRepository.loadAuthorizationRequest(any())).thenReturn(authorizationRequest); when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())) .thenReturn(authorizationRequest); @@ -200,8 +189,7 @@ public class OAuth2ClientBeanDefinitionParserTests { params.add("code", "code123"); params.add("state", authorizationRequest.getState()); this.mvc.perform(get(authorizationRequest.getRedirectUri()).params(params)) - .andExpect(status().is3xxRedirection()) - .andExpect(redirectedUrl(authorizationRequest.getRedirectUri())); + .andExpect(status().is3xxRedirection()).andExpect(redirectedUrl(authorizationRequest.getRedirectUri())); verify(this.authorizedClientService).saveAuthorizedClient(any(), any()); } @@ -213,23 +201,22 @@ public class OAuth2ClientBeanDefinitionParserTests { ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("google"); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - clientRegistration, "user", TestOAuth2AccessTokens.noScopes()); - when(this.authorizedClientRepository.loadAuthorizedClient(any(), any(), any())) - .thenReturn(authorizedClient); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(clientRegistration, "user", + TestOAuth2AccessTokens.noScopes()); + when(this.authorizedClientRepository.loadAuthorizedClient(any(), any(), any())).thenReturn(authorizedClient); - this.mvc.perform(get("/authorized-client")) - .andExpect(status().isOk()) - .andExpect(content().string("resolved")); + this.mvc.perform(get("/authorized-client")).andExpect(status().isOk()).andExpect(content().string("resolved")); } @RestController static class AuthorizedClientController { @GetMapping("/authorized-client") - String authorizedClient(Model model, @RegisteredOAuth2AuthorizedClient("google") OAuth2AuthorizedClient authorizedClient) { + String authorizedClient(Model model, + @RegisteredOAuth2AuthorizedClient("google") OAuth2AuthorizedClient authorizedClient) { return authorizedClient != null ? "resolved" : "not-resolved"; } + } private static OAuth2AuthorizationRequest createAuthorizationRequest(ClientRegistration clientRegistration) { @@ -237,15 +224,12 @@ public class OAuth2ClientBeanDefinitionParserTests { attributes.put(OAuth2ParameterNames.REGISTRATION_ID, clientRegistration.getRegistrationId()); return OAuth2AuthorizationRequest.authorizationCode() .authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()) - .clientId(clientRegistration.getClientId()) - .redirectUri(clientRegistration.getRedirectUri()) - .scopes(clientRegistration.getScopes()) - .state("state") - .attributes(attributes) - .build(); + .clientId(clientRegistration.getClientId()).redirectUri(clientRegistration.getRedirectUri()) + .scopes(clientRegistration.getScopes()).state("state").attributes(attributes).build(); } private static String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParserTests.java index 3c0c793b25..489c5d1761 100644 --- a/config/src/test/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParserTests.java @@ -92,6 +92,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @RunWith(SpringJUnit4ClassRunner.class) @SecurityTestExecutionListeners public class OAuth2LoginBeanDefinitionParserTests { + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/OAuth2LoginBeanDefinitionParserTests"; @Rule @@ -143,9 +144,7 @@ public class OAuth2LoginBeanDefinitionParserTests { public void requestLoginWhenMultiClientRegistrationThenReturnLoginPageWithClients() throws Exception { this.spring.configLocations(this.xml("MultiClientRegistration")).autowire(); - MvcResult result = this.mvc.perform(get("/login")) - .andExpect(status().is2xxSuccessful()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/login")).andExpect(status().is2xxSuccessful()).andReturn(); assertThat(result.getResponse().getContentAsString()) .contains("Google"); @@ -158,8 +157,7 @@ public class OAuth2LoginBeanDefinitionParserTests { public void requestWhenSingleClientRegistrationThenAutoRedirect() throws Exception { this.spring.configLocations(this.xml("SingleClientRegistration")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().is3xxRedirection()) + this.mvc.perform(get("/")).andExpect(status().is3xxRedirection()) .andExpect(redirectedUrl("http://localhost/oauth2/authorization/google-login")); verify(requestCache).saveRequest(any(), any()); @@ -171,8 +169,7 @@ public class OAuth2LoginBeanDefinitionParserTests { throws Exception { this.spring.configLocations(this.xml("SingleClientRegistration")).autowire(); - this.mvc.perform(get("/favicon.ico").accept(new MediaType("image", "*"))) - .andExpect(status().is3xxRedirection()) + this.mvc.perform(get("/favicon.ico").accept(new MediaType("image", "*"))).andExpect(status().is3xxRedirection()) .andExpect(redirectedUrl("http://localhost/login")); } @@ -182,8 +179,7 @@ public class OAuth2LoginBeanDefinitionParserTests { throws Exception { this.spring.configLocations(this.xml("SingleClientRegistration")).autowire(); - this.mvc.perform(get("/").header("X-Requested-With", "XMLHttpRequest")) - .andExpect(status().is3xxRedirection()) + this.mvc.perform(get("/").header("X-Requested-With", "XMLHttpRequest")).andExpect(status().is3xxRedirection()) .andExpect(redirectedUrl("http://localhost/login")); } @@ -214,7 +210,8 @@ public class OAuth2LoginBeanDefinitionParserTests { attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "github-login"); OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.request() .attributes(attributes).build(); - when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authorizationRequest); + when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())) + .thenReturn(authorizationRequest); OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); @@ -225,8 +222,7 @@ public class OAuth2LoginBeanDefinitionParserTests { MultiValueMap params = new LinkedMultiValueMap<>(); params.add("code", "code123"); params.add("state", authorizationRequest.getState()); - this.mvc.perform(get("/login/oauth2/code/github-login").params(params)) - .andExpect(status().is2xxSuccessful()); + this.mvc.perform(get("/login/oauth2/code/github-login").params(params)).andExpect(status().is2xxSuccessful()); ArgumentCaptor authenticationCaptor = ArgumentCaptor.forClass(Authentication.class); verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), authenticationCaptor.capture()); @@ -243,7 +239,8 @@ public class OAuth2LoginBeanDefinitionParserTests { attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "github-login"); OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.request() .attributes(attributes).build(); - when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authorizationRequest); + when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())) + .thenReturn(authorizationRequest); OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); @@ -268,7 +265,8 @@ public class OAuth2LoginBeanDefinitionParserTests { attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "google-login"); OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.oidcRequest() .attributes(attributes).build(); - when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authorizationRequest); + when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())) + .thenReturn(authorizationRequest); OAuth2AccessTokenResponse accessTokenResponse = oidcAccessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); @@ -279,8 +277,7 @@ public class OAuth2LoginBeanDefinitionParserTests { MultiValueMap params = new LinkedMultiValueMap<>(); params.add("code", "code123"); params.add("state", authorizationRequest.getState()); - this.mvc.perform(get("/login/oauth2/code/google-login").params(params)) - .andExpect(status().is3xxRedirection()) + this.mvc.perform(get("/login/oauth2/code/google-login").params(params)).andExpect(status().is3xxRedirection()) .andExpect(redirectedUrl("/")); verify(this.jwtDecoderFactory).createDecoder(any()); @@ -296,7 +293,8 @@ public class OAuth2LoginBeanDefinitionParserTests { attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "github-login"); OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.request() .attributes(attributes).build(); - when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authorizationRequest); + when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())) + .thenReturn(authorizationRequest); OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); @@ -304,14 +302,13 @@ public class OAuth2LoginBeanDefinitionParserTests { OAuth2User oauth2User = TestOAuth2Users.create(); when(this.oauth2UserService.loadUser(any())).thenReturn(oauth2User); - when(this.userAuthoritiesMapper.mapAuthorities(any())).thenReturn( - (Collection) AuthorityUtils.createAuthorityList("ROLE_OAUTH2_USER")); + when(this.userAuthoritiesMapper.mapAuthorities(any())) + .thenReturn((Collection) AuthorityUtils.createAuthorityList("ROLE_OAUTH2_USER")); MultiValueMap params = new LinkedMultiValueMap<>(); params.add("code", "code123"); params.add("state", authorizationRequest.getState()); - this.mvc.perform(get("/login/oauth2/code/github-login").params(params)) - .andExpect(status().is2xxSuccessful()); + this.mvc.perform(get("/login/oauth2/code/github-login").params(params)).andExpect(status().is2xxSuccessful()); ArgumentCaptor authenticationCaptor = ArgumentCaptor.forClass(Authentication.class); verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), authenticationCaptor.capture()); @@ -324,9 +321,9 @@ public class OAuth2LoginBeanDefinitionParserTests { // re-setup for OIDC test attributes = new HashMap<>(); attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "google-login"); - authorizationRequest = TestOAuth2AuthorizationRequests.oidcRequest() - .attributes(attributes).build(); - when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authorizationRequest); + authorizationRequest = TestOAuth2AuthorizationRequests.oidcRequest().attributes(attributes).build(); + when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())) + .thenReturn(authorizationRequest); accessTokenResponse = oidcAccessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); @@ -337,8 +334,7 @@ public class OAuth2LoginBeanDefinitionParserTests { when(this.userAuthoritiesMapper.mapAuthorities(any())) .thenReturn((Collection) AuthorityUtils.createAuthorityList("ROLE_OIDC_USER")); - this.mvc.perform(get("/login/oauth2/code/google-login").params(params)) - .andExpect(status().is2xxSuccessful()); + this.mvc.perform(get("/login/oauth2/code/google-login").params(params)).andExpect(status().is2xxSuccessful()); authenticationCaptor = ArgumentCaptor.forClass(Authentication.class); verify(authenticationSuccessHandler, times(2)).onAuthenticationSuccess(any(), any(), @@ -359,7 +355,8 @@ public class OAuth2LoginBeanDefinitionParserTests { attributes.put(OAuth2ParameterNames.REGISTRATION_ID, "github-login"); OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.request() .attributes(attributes).build(); - when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authorizationRequest); + when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())) + .thenReturn(authorizationRequest); OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); @@ -370,8 +367,7 @@ public class OAuth2LoginBeanDefinitionParserTests { MultiValueMap params = new LinkedMultiValueMap<>(); params.add("code", "code123"); params.add("state", authorizationRequest.getState()); - this.mvc.perform(get("/login/oauth2/github-login").params(params)) - .andExpect(status().is2xxSuccessful()); + this.mvc.perform(get("/login/oauth2/github-login").params(params)).andExpect(status().is2xxSuccessful()); ArgumentCaptor authenticationCaptor = ArgumentCaptor.forClass(Authentication.class); verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), authenticationCaptor.capture()); @@ -385,8 +381,7 @@ public class OAuth2LoginBeanDefinitionParserTests { this.spring.configLocations(this.xml("SingleClientRegistration-WithCustomAuthorizationRequestResolver")) .autowire(); - this.mvc.perform(get("/oauth2/authorization/google-login")) - .andExpect(status().is3xxRedirection()); + this.mvc.perform(get("/oauth2/authorization/google-login")).andExpect(status().is3xxRedirection()); verify(authorizationRequestResolver).resolve(any()); } @@ -396,8 +391,7 @@ public class OAuth2LoginBeanDefinitionParserTests { public void requestWhenMultiClientRegistrationThenRedirectDefaultLoginPage() throws Exception { this.spring.configLocations(this.xml("MultiClientRegistration")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().is3xxRedirection()) + this.mvc.perform(get("/")).andExpect(status().is3xxRedirection()) .andExpect(redirectedUrl("http://localhost/login")); } @@ -405,8 +399,7 @@ public class OAuth2LoginBeanDefinitionParserTests { public void requestWhenCustomLoginPageThenRedirectCustomLoginPage() throws Exception { this.spring.configLocations(this.xml("SingleClientRegistration-WithCustomLoginPage")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().is3xxRedirection()) + this.mvc.perform(get("/")).andExpect(status().is3xxRedirection()) .andExpect(redirectedUrl("http://localhost/custom-login")); } @@ -416,8 +409,7 @@ public class OAuth2LoginBeanDefinitionParserTests { throws Exception { this.spring.configLocations(this.xml("SingleClientRegistration-WithFormLogin")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().is3xxRedirection()) + this.mvc.perform(get("/")).andExpect(status().is3xxRedirection()) .andExpect(redirectedUrl("http://localhost/login")); } @@ -432,7 +424,8 @@ public class OAuth2LoginBeanDefinitionParserTests { attributes.put(OAuth2ParameterNames.REGISTRATION_ID, clientRegistration.getRegistrationId()); OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.request() .attributes(attributes).build(); - when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authorizationRequest); + when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())) + .thenReturn(authorizationRequest); OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); @@ -459,7 +452,8 @@ public class OAuth2LoginBeanDefinitionParserTests { attributes.put(OAuth2ParameterNames.REGISTRATION_ID, clientRegistration.getRegistrationId()); OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.request() .attributes(attributes).build(); - when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authorizationRequest); + when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())) + .thenReturn(authorizationRequest); OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); @@ -486,7 +480,8 @@ public class OAuth2LoginBeanDefinitionParserTests { attributes.put(OAuth2ParameterNames.REGISTRATION_ID, clientRegistration.getRegistrationId()); OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.request() .attributes(attributes).build(); - when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())).thenReturn(authorizationRequest); + when(this.authorizationRequestRepository.removeAuthorizationRequest(any(), any())) + .thenReturn(authorizationRequest); OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); @@ -509,26 +504,26 @@ public class OAuth2LoginBeanDefinitionParserTests { ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("google-login"); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - clientRegistration, "user", TestOAuth2AccessTokens.noScopes()); - when(this.authorizedClientRepository.loadAuthorizedClient(any(), any(), any())) - .thenReturn(authorizedClient); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(clientRegistration, "user", + TestOAuth2AccessTokens.noScopes()); + when(this.authorizedClientRepository.loadAuthorizedClient(any(), any(), any())).thenReturn(authorizedClient); - this.mvc.perform(get("/authorized-client")) - .andExpect(status().isOk()) - .andExpect(content().string("resolved")); + this.mvc.perform(get("/authorized-client")).andExpect(status().isOk()).andExpect(content().string("resolved")); } @RestController static class AuthorizedClientController { @GetMapping("/authorized-client") - String authorizedClient(Model model, @RegisteredOAuth2AuthorizedClient("google") OAuth2AuthorizedClient authorizedClient) { + String authorizedClient(Model model, + @RegisteredOAuth2AuthorizedClient("google") OAuth2AuthorizedClient authorizedClient) { return authorizedClient != null ? "resolved" : "not-resolved"; } + } private String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests.java index 15186e0b7e..55affd3d0c 100644 --- a/config/src/test/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests.java @@ -118,14 +118,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * * @author Josh Cummings */ @RunWith(SpringJUnit4ClassRunner.class) @SecurityTestExecutionListeners public class OAuth2ResourceServerBeanDefinitionParserTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests"; + + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests"; @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -142,9 +141,7 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/") - .header("Authorization", "Bearer " + token)) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isNotFound()); } @Test @@ -153,119 +150,96 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { mockWebServer(jwks("Default")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/") - .header("Authorization", "Bearer " + token)) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isNotFound()); } @Test - public void getWhenExpiredBearerTokenThenInvalidToken() - throws Exception { + public void getWhenExpiredBearerTokenThenInvalidToken() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire(); mockRestOperations(jwks("Default")); String token = this.token("Expired"); - this.mvc.perform(get("/") - .header("Authorization", "Bearer " + token)) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized()) .andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt")); } @Test - public void getWhenBadJwkEndpointThenInvalidToken() - throws Exception { + public void getWhenBadJwkEndpointThenInvalidToken() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire(); mockRestOperations("malformed"); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/") - .header("Authorization", "Bearer " + token)) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized()) .andExpect(header().string("WWW-Authenticate", "Bearer")); } @Test - public void getWhenUnavailableJwkEndpointThenInvalidToken() - throws Exception { + public void getWhenUnavailableJwkEndpointThenInvalidToken() throws Exception { this.spring.configLocations(xml("WebServer"), xml("JwkSetUri")).autowire(); this.web.shutdown(); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/") - .header("Authorization", "Bearer " + token)) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized()) .andExpect(header().string("WWW-Authenticate", "Bearer")); } @Test - public void getWhenMalformedBearerTokenThenInvalidToken() - throws Exception { + public void getWhenMalformedBearerTokenThenInvalidToken() throws Exception { this.spring.configLocations(xml("JwkSetUri")).autowire(); - this.mvc.perform(get("/") - .header("Authorization", "Bearer an\"invalid\"token")) - .andExpect(status().isUnauthorized()) - .andExpect(invalidTokenHeader("Bearer token is malformed")); + this.mvc.perform(get("/").header("Authorization", "Bearer an\"invalid\"token")) + .andExpect(status().isUnauthorized()).andExpect(invalidTokenHeader("Bearer token is malformed")); } @Test - public void getWhenMalformedPayloadThenInvalidToken() - throws Exception { + public void getWhenMalformedPayloadThenInvalidToken() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire(); mockRestOperations(jwks("Default")); String token = this.token("MalformedPayload"); - this.mvc.perform(get("/").header("Authorization", "Bearer " + token)) - .andExpect(status().isUnauthorized()) - .andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt: Malformed payload")); + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized()) + .andExpect( + invalidTokenHeader("An error occurred while attempting to decode the Jwt: Malformed payload")); } @Test - public void getWhenUnsignedBearerTokenThenInvalidToken() - throws Exception { + public void getWhenUnsignedBearerTokenThenInvalidToken() throws Exception { this.spring.configLocations(xml("JwkSetUri")).autowire(); String token = this.token("Unsigned"); - this.mvc.perform(get("/").header("Authorization", "Bearer " + token)) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized()) .andExpect(invalidTokenHeader("Unsupported algorithm of none")); } @Test - public void getWhenBearerTokenBeforeNotBeforeThenInvalidToken() - throws Exception { + public void getWhenBearerTokenBeforeNotBeforeThenInvalidToken() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire(); this.mockRestOperations(jwks("Default")); String token = this.token("TooEarly"); - this.mvc.perform(get("/").header("Authorization", "Bearer " + token)) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized()) .andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt")); } @Test - public void getWhenBearerTokenInTwoPlacesThenInvalidRequest() - throws Exception { + public void getWhenBearerTokenInTwoPlacesThenInvalidRequest() throws Exception { this.spring.configLocations(xml("JwkSetUri")).autowire(); - this.mvc.perform(get("/") - .header("Authorization", "Bearer token") - .param("access_token", "token")) + this.mvc.perform(get("/").header("Authorization", "Bearer token").param("access_token", "token")) .andExpect(status().isBadRequest()) .andExpect(invalidRequestHeader("Found multiple bearer tokens in the request")); } @Test - public void getWhenBearerTokenInTwoParametersThenInvalidRequest() - throws Exception { + public void getWhenBearerTokenInTwoParametersThenInvalidRequest() throws Exception { this.spring.configLocations(xml("JwkSetUri")).autowire(); @@ -273,152 +247,129 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { params.add("access_token", "token1"); params.add("access_token", "token2"); - this.mvc.perform(get("/") - .params(params)) - .andExpect(status().isBadRequest()) + this.mvc.perform(get("/").params(params)).andExpect(status().isBadRequest()) .andExpect(invalidRequestHeader("Found multiple bearer tokens in the request")); } @Test - public void postWhenBearerTokenAsFormParameterThenIgnoresToken() - throws Exception { + public void postWhenBearerTokenAsFormParameterThenIgnoresToken() throws Exception { this.spring.configLocations(xml("JwkSetUri")).autowire(); this.mvc.perform(post("/") // engage csrf - .param("access_token", "token")) - .andExpect(status().isForbidden()) - .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer")); // different from DSL + .param("access_token", "token")).andExpect(status().isForbidden()) + .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer")); // different + // from + // DSL } @Test - public void getWhenNoBearerTokenThenUnauthorized() - throws Exception { + public void getWhenNoBearerTokenThenUnauthorized() throws Exception { this.spring.configLocations(xml("JwkSetUri")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/")).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer")); } @Test - public void getWhenSufficientlyScopedBearerTokenThenAcceptsRequest() - throws Exception { + public void getWhenSufficientlyScopedBearerTokenThenAcceptsRequest() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidMessageReadScope"); - this.mvc.perform(get("/requires-read-scope") - .header("Authorization", "Bearer " + token)) + this.mvc.perform(get("/requires-read-scope").header("Authorization", "Bearer " + token)) .andExpect(status().isNotFound()); } @Test - public void getWhenInsufficientScopeThenInsufficientScopeError() - throws Exception { + public void getWhenInsufficientScopeThenInsufficientScopeError() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/requires-read-scope") - .header("Authorization", "Bearer " + token)) - .andExpect(status().isForbidden()) - .andExpect(insufficientScopeHeader()); + this.mvc.perform(get("/requires-read-scope").header("Authorization", "Bearer " + token)) + .andExpect(status().isForbidden()).andExpect(insufficientScopeHeader()); } @Test - public void getWhenInsufficientScpThenInsufficientScopeError() - throws Exception { + public void getWhenInsufficientScpThenInsufficientScopeError() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidMessageWriteScp"); - this.mvc.perform(get("/requires-read-scope") - .header("Authorization", "Bearer " + token)) - .andExpect(status().isForbidden()) - .andExpect(insufficientScopeHeader()); + this.mvc.perform(get("/requires-read-scope").header("Authorization", "Bearer " + token)) + .andExpect(status().isForbidden()).andExpect(insufficientScopeHeader()); } @Test - public void getWhenAuthorizationServerHasNoMatchingKeyThenInvalidToken() - throws Exception { + public void getWhenAuthorizationServerHasNoMatchingKeyThenInvalidToken() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire(); mockRestOperations(jwks("Empty")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/") - .header("Authorization", "Bearer " + token)) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized()) .andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt")); } @Test - public void getWhenAuthorizationServerHasMultipleMatchingKeysThenOk() - throws Exception { + public void getWhenAuthorizationServerHasMultipleMatchingKeysThenOk() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire(); mockRestOperations(jwks("TwoKeys")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer " + token)) + this.mvc.perform(get("/authenticated").header("Authorization", "Bearer " + token)) .andExpect(status().isNotFound()); } @Test - public void getWhenKeyMatchesByKidThenOk() - throws Exception { + public void getWhenKeyMatchesByKidThenOk() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire(); mockRestOperations(jwks("TwoKeys")); String token = this.token("Kid"); - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer " + token)) + this.mvc.perform(get("/authenticated").header("Authorization", "Bearer " + token)) .andExpect(status().isNotFound()); } // -- Resource Server should not engage csrf @Test - public void postWhenValidBearerTokenAndNoCsrfTokenThenOk() - throws Exception { + public void postWhenValidBearerTokenAndNoCsrfTokenThenOk() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - this.mvc.perform(post("/authenticated") - .header("Authorization", "Bearer " + token)) + this.mvc.perform(post("/authenticated").header("Authorization", "Bearer " + token)) .andExpect(status().isNotFound()); } @Test - public void postWhenNoBearerTokenThenCsrfDenies() - throws Exception { + public void postWhenNoBearerTokenThenCsrfDenies() throws Exception { this.spring.configLocations(xml("JwkSetUri")).autowire(); - this.mvc.perform(post("/authenticated")) - .andExpect(status().isForbidden()) - .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer")); // different from DSL + this.mvc.perform(post("/authenticated")).andExpect(status().isForbidden()) + .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer")); // different + // from + // DSL } @Test - public void postWhenExpiredBearerTokenAndNoCsrfThenInvalidToken() - throws Exception { + public void postWhenExpiredBearerTokenAndNoCsrfThenInvalidToken() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire(); mockRestOperations(jwks("Default")); String token = this.token("Expired"); - this.mvc.perform(post("/authenticated") - .header("Authorization", "Bearer " + token)) + this.mvc.perform(post("/authenticated").header("Authorization", "Bearer " + token)) .andExpect(status().isUnauthorized()) .andExpect(invalidTokenHeader("An error occurred while attempting to decode the Jwt")); } @@ -426,61 +377,49 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { // -- Resource Server should not create sessions @Test - public void requestWhenJwtThenSessionIsNotCreated() - throws Exception { + public void requestWhenJwtThenSessionIsNotCreated() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("Jwt")).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - MvcResult result = this.mvc.perform(get("/") - .header("Authorization", "Bearer " + token)) - .andExpect(status().isNotFound()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/").header("Authorization", "Bearer " + token)) + .andExpect(status().isNotFound()).andReturn(); assertThat(result.getRequest().getSession(false)).isNull(); } @Test - public void requestWhenIntrospectionThenSessionIsNotCreated() - throws Exception { + public void requestWhenIntrospectionThenSessionIsNotCreated() throws Exception { this.spring.configLocations(xml("WebServer"), xml("IntrospectionUri")).autowire(); mockWebServer(json("Active")); - MvcResult result = this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer token")) - .andExpect(status().isNotFound()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/authenticated").header("Authorization", "Bearer token")) + .andExpect(status().isNotFound()).andReturn(); assertThat(result.getRequest().getSession(false)).isNull(); } @Test - public void requestWhenNoBearerTokenThenSessionIsCreated() - throws Exception { + public void requestWhenNoBearerTokenThenSessionIsCreated() throws Exception { this.spring.configLocations(xml("JwkSetUri")).autowire(); - MvcResult result = this.mvc.perform(get("/")) - .andExpect(status().isUnauthorized()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/")).andExpect(status().isUnauthorized()).andReturn(); assertThat(result.getRequest().getSession(false)).isNotNull(); } @Test - public void requestWhenSessionManagementConfiguredThenUses() - throws Exception { + public void requestWhenSessionManagementConfiguredThenUses() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("AlwaysSessionCreation")).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - MvcResult result = this.mvc.perform(get("/") - .header("Authorization", "Bearer " + token)) - .andExpect(status().isNotFound()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/").header("Authorization", "Bearer " + token)) + .andExpect(status().isNotFound()).andReturn(); assertThat(result.getRequest().getSession(false)).isNotNull(); } @@ -489,18 +428,16 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { @Test public void getWhenCustomBearerTokenResolverThenUses() throws Exception { - this.spring.configLocations(xml("MockBearerTokenResolver"), xml("MockJwtDecoder"), - xml("BearerTokenResolver")).autowire(); + this.spring.configLocations(xml("MockBearerTokenResolver"), xml("MockJwtDecoder"), xml("BearerTokenResolver")) + .autowire(); JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); when(decoder.decode("token")).thenReturn(jwt().build()); BearerTokenResolver bearerTokenResolver = this.spring.getContext().getBean(BearerTokenResolver.class); - when(bearerTokenResolver.resolve(any(HttpServletRequest.class))) - .thenReturn("token"); + when(bearerTokenResolver.resolve(any(HttpServletRequest.class))).thenReturn("token"); - this.mvc.perform(get("/")) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/")).andExpect(status().isNotFound()); verify(decoder).decode("token"); verify(bearerTokenResolver).resolve(any(HttpServletRequest.class)); @@ -515,13 +452,10 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); when(decoder.decode(anyString())).thenReturn(jwt().build()); - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer token")) + this.mvc.perform(get("/authenticated").header("Authorization", "Bearer token")) .andExpect(status().isNotFound()); - this.mvc.perform(post("/authenticated") - .param("access_token", "token")) - .andExpect(status().isNotFound()); + this.mvc.perform(post("/authenticated").param("access_token", "token")).andExpect(status().isNotFound()); } @Test @@ -533,13 +467,10 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); Mockito.when(decoder.decode(anyString())).thenReturn(jwt().build()); - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer token")) + this.mvc.perform(get("/authenticated").header("Authorization", "Bearer token")) .andExpect(status().isNotFound()); - this.mvc.perform(get("/authenticated") - .param("access_token", "token")) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/authenticated").param("access_token", "token")).andExpect(status().isNotFound()); verify(decoder, times(2)).decode("token"); } @@ -550,11 +481,8 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { this.spring.configLocations(xml("MockJwtDecoder"), xml("AllowBearerTokenInBody")).autowire(); - this.mvc.perform(post("/authenticated") - .param("access_token", "token") - .header("Authorization", "Bearer token") - .with(csrf())) - .andExpect(status().isBadRequest()) + this.mvc.perform(post("/authenticated").param("access_token", "token").header("Authorization", "Bearer token") + .with(csrf())).andExpect(status().isBadRequest()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("invalid_request"))); } @@ -564,29 +492,23 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { this.spring.configLocations(xml("MockJwtDecoder"), xml("AllowBearerTokenInQuery")).autowire(); - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer token") - .param("access_token", "token")) + this.mvc.perform(get("/authenticated").header("Authorization", "Bearer token").param("access_token", "token")) .andExpect(status().isBadRequest()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("invalid_request"))); } @Test public void getBearerTokenResolverWhenNoResolverSpecifiedThenTheDefaultIsUsed() { - OAuth2ResourceServerBeanDefinitionParser oauth2 = - new OAuth2ResourceServerBeanDefinitionParser - (mock(BeanReference.class), mock(List.class), mock(Map.class), - mock(Map.class), mock(List.class)); + OAuth2ResourceServerBeanDefinitionParser oauth2 = new OAuth2ResourceServerBeanDefinitionParser( + mock(BeanReference.class), mock(List.class), mock(Map.class), mock(Map.class), mock(List.class)); - assertThat(oauth2.getBearerTokenResolver(mock(Element.class))) - .isInstanceOf(RootBeanDefinition.class); + assertThat(oauth2.getBearerTokenResolver(mock(Element.class))).isInstanceOf(RootBeanDefinition.class); } // -- custom jwt decoder @Test - public void requestWhenCustomJwtDecoderThenUsed() - throws Exception { + public void requestWhenCustomJwtDecoderThenUsed() throws Exception { this.spring.configLocations(xml("MockJwtDecoder"), xml("Jwt")).autowire(); @@ -594,8 +516,7 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { when(decoder.decode(anyString())).thenReturn(jwt().build()); - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer token")) + this.mvc.perform(get("/authenticated").header("Authorization", "Bearer token")) .andExpect(status().isNotFound()); verify(decoder).decode("token"); @@ -610,31 +531,27 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { // -- exception handling @Test - public void requestWhenRealmNameConfiguredThenUsesOnUnauthenticated() - throws Exception { + public void requestWhenRealmNameConfiguredThenUsesOnUnauthenticated() throws Exception { this.spring.configLocations(xml("MockJwtDecoder"), xml("AuthenticationEntryPoint")).autowire(); JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); Mockito.when(decoder.decode(anyString())).thenThrow(JwtException.class); - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer invalid_token")) + this.mvc.perform(get("/authenticated").header("Authorization", "Bearer invalid_token")) .andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer realm=\"myRealm\""))); } @Test - public void requestWhenRealmNameConfiguredThenUsesOnAccessDenied() - throws Exception { + public void requestWhenRealmNameConfiguredThenUsesOnAccessDenied() throws Exception { this.spring.configLocations(xml("MockJwtDecoder"), xml("AccessDeniedHandler")).autowire(); JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); Mockito.when(decoder.decode(anyString())).thenReturn(jwt().build()); - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer insufficiently_scoped")) + this.mvc.perform(get("/authenticated").header("Authorization", "Bearer insufficiently_scoped")) .andExpect(status().isForbidden()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer realm=\"myRealm\""))); } @@ -642,72 +559,60 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { // -- token validator @Test - public void requestWhenCustomJwtValidatorFailsThenCorrespondingErrorMessage() - throws Exception { + public void requestWhenCustomJwtValidatorFailsThenCorrespondingErrorMessage() throws Exception { this.spring.configLocations(xml("MockJwtValidator"), xml("Jwt")).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - OAuth2TokenValidator jwtValidator = - this.spring.getContext().getBean(OAuth2TokenValidator.class); + OAuth2TokenValidator jwtValidator = this.spring.getContext().getBean(OAuth2TokenValidator.class); OAuth2Error error = new OAuth2Error("custom-error", "custom-description", "custom-uri"); when(jwtValidator.validate(any(Jwt.class))).thenReturn(OAuth2TokenValidatorResult.failure(error)); - this.mvc.perform(get("/") - .header("Authorization", "Bearer " + token)) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("custom-description"))); } @Test - public void requestWhenClockSkewSetThenTimestampWindowRelaxedAccordingly() - throws Exception { + public void requestWhenClockSkewSetThenTimestampWindowRelaxedAccordingly() throws Exception { this.spring.configLocations(xml("UnexpiredJwtClockSkew"), xml("Jwt")).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ExpiresAt4687177990"); - this.mvc.perform(get("/") - .header("Authorization", "Bearer " + token)) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isNotFound()); } @Test - public void requestWhenClockSkewSetButJwtStillTooLateThenReportsExpired() - throws Exception { + public void requestWhenClockSkewSetButJwtStillTooLateThenReportsExpired() throws Exception { this.spring.configLocations(xml("ExpiredJwtClockSkew"), xml("Jwt")).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ExpiresAt4687177990"); - this.mvc.perform(get("/") - .header("Authorization", "Bearer " + token)) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isUnauthorized()) .andExpect(invalidTokenHeader("Jwt expired at")); } // -- converter @Test - public void requestWhenJwtAuthenticationConverterThenUsed() - throws Exception { + public void requestWhenJwtAuthenticationConverterThenUsed() throws Exception { - this.spring.configLocations(xml("MockJwtDecoder"), xml("MockJwtAuthenticationConverter"), xml("JwtAuthenticationConverter")).autowire(); + this.spring.configLocations(xml("MockJwtDecoder"), xml("MockJwtAuthenticationConverter"), + xml("JwtAuthenticationConverter")).autowire(); - Converter jwtAuthenticationConverter = - (Converter) this.spring.getContext().getBean("jwtAuthenticationConverter"); + Converter jwtAuthenticationConverter = (Converter) this.spring + .getContext().getBean("jwtAuthenticationConverter"); when(jwtAuthenticationConverter.convert(any(Jwt.class))) .thenReturn(new JwtAuthenticationToken(jwt().build(), Collections.emptyList())); JwtDecoder jwtDecoder = this.spring.getContext().getBean(JwtDecoder.class); Mockito.when(jwtDecoder.decode(anyString())).thenReturn(jwt().build()); - this.mvc.perform(get("/") - .header("Authorization", "Bearer token")) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/").header("Authorization", "Bearer token")).andExpect(status().isNotFound()); verify(jwtAuthenticationConverter).convert(any(Jwt.class)); } @@ -715,38 +620,31 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { // -- single key @Test - public void requestWhenUsingPublicKeyAndValidTokenThenAuthenticates() - throws Exception { + public void requestWhenUsingPublicKeyAndValidTokenThenAuthenticates() throws Exception { this.spring.configLocations(xml("SingleKey"), xml("Jwt")).autowire(); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/") - .header("Authorization", "Bearer " + token)) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)).andExpect(status().isNotFound()); } @Test - public void requestWhenUsingPublicKeyAndSignatureFailsThenReturnsInvalidToken() - throws Exception { + public void requestWhenUsingPublicKeyAndSignatureFailsThenReturnsInvalidToken() throws Exception { this.spring.configLocations(xml("SingleKey"), xml("Jwt")).autowire(); String token = this.token("WrongSignature"); - this.mvc.perform(get("/") - .header("Authorization", "Bearer " + token)) + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)) .andExpect(invalidTokenHeader("signature")); } @Test - public void requestWhenUsingPublicKeyAlgorithmDoesNotMatchThenReturnsInvalidToken() - throws Exception { + public void requestWhenUsingPublicKeyAlgorithmDoesNotMatchThenReturnsInvalidToken() throws Exception { this.spring.configLocations(xml("SingleKey"), xml("Jwt")).autowire(); String token = this.token("WrongAlgorithm"); - this.mvc.perform(get("/") - .header("Authorization", "Bearer " + token)) + this.mvc.perform(get("/").header("Authorization", "Bearer " + token)) .andExpect(invalidTokenHeader("algorithm")); } @@ -757,8 +655,7 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { this.spring.configLocations(xml("OpaqueTokenRestOperations"), xml("OpaqueToken")).autowire(); mockRestOperations(json("Active")); - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer token")) + this.mvc.perform(get("/authenticated").header("Authorization", "Bearer token")) .andExpect(status().isNotFound()); } @@ -767,11 +664,9 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { this.spring.configLocations(xml("OpaqueTokenRestOperations"), xml("OpaqueToken")).autowire(); mockRestOperations(json("Inactive")); - this.mvc.perform(get("/") - .header("Authorization", "Bearer token")) - .andExpect(status().isUnauthorized()) - .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, - containsString("Provided token isn't active"))); + this.mvc.perform(get("/").header("Authorization", "Bearer token")).andExpect(status().isUnauthorized()) + .andExpect( + header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("Provided token isn't active"))); } @Test @@ -779,8 +674,7 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { this.spring.configLocations(xml("OpaqueTokenRestOperations"), xml("OpaqueToken")).autowire(); mockRestOperations(json("ActiveNoScopes")); - this.mvc.perform(get("/requires-read-scope") - .header("Authorization", "Bearer token")) + this.mvc.perform(get("/requires-read-scope").header("Authorization", "Bearer token")) .andExpect(status().isForbidden()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("scope"))); } @@ -803,14 +697,12 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { public void getWhenAuthenticationManagerResolverThenUses() throws Exception { this.spring.configLocations(xml("AuthenticationManagerResolver")).autowire(); - AuthenticationManagerResolver authenticationManagerResolver = - this.spring.getContext().getBean(AuthenticationManagerResolver.class); + AuthenticationManagerResolver authenticationManagerResolver = this.spring.getContext() + .getBean(AuthenticationManagerResolver.class); when(authenticationManagerResolver.resolve(any(HttpServletRequest.class))) .thenReturn(authentication -> new JwtAuthenticationToken(jwt().build(), Collections.emptyList())); - this.mvc.perform(get("/") - .header("Authorization", "Bearer token")) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/").header("Authorization", "Bearer token")).andExpect(status().isNotFound()); verify(authenticationManagerResolver).resolve(any(HttpServletRequest.class)); } @@ -820,9 +712,7 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { this.spring.configLocations(xml("WebServer"), xml("MultipleIssuers")).autowire(); MockWebServer server = this.spring.getContext().getBean(MockWebServer.class); - String metadata = "{\n" - + " \"issuer\": \"%s\", \n" - + " \"jwks_uri\": \"%s/.well-known/jwks.json\" \n" + String metadata = "{\n" + " \"issuer\": \"%s\", \n" + " \"jwks_uri\": \"%s/.well-known/jwks.json\" \n" + "}"; String jwkSet = jwkSet(); String issuerOne = server.url("/issuerOne").toString(); @@ -835,92 +725,76 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { mockWebServer(String.format(metadata, issuerOne, issuerOne)); mockWebServer(jwkSet); - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer " + jwtOne)) + this.mvc.perform(get("/authenticated").header("Authorization", "Bearer " + jwtOne)) .andExpect(status().isNotFound()); mockWebServer(String.format(metadata, issuerTwo, issuerTwo)); mockWebServer(jwkSet); - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer " + jwtTwo)) + this.mvc.perform(get("/authenticated").header("Authorization", "Bearer " + jwtTwo)) .andExpect(status().isNotFound()); mockWebServer(String.format(metadata, issuerThree, issuerThree)); mockWebServer(jwkSet); - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer " + jwtThree)) - .andExpect(status().isUnauthorized()) - .andExpect(invalidTokenHeader("Invalid issuer")); + this.mvc.perform(get("/authenticated").header("Authorization", "Bearer " + jwtThree)) + .andExpect(status().isUnauthorized()).andExpect(invalidTokenHeader("Invalid issuer")); } // -- In combination with other authentication providers @Test - public void requestWhenBasicAndResourceServerEntryPointsThenBearerTokenPresides() - throws Exception { // different from DSL + public void requestWhenBasicAndResourceServerEntryPointsThenBearerTokenPresides() throws Exception { // different + // from + // DSL this.spring.configLocations(xml("MockJwtDecoder"), xml("BasicAndResourceServer")).autowire(); JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); when(decoder.decode(anyString())).thenThrow(JwtException.class); - this.mvc.perform(get("/authenticated") - .with(httpBasic("some", "user"))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/authenticated").with(httpBasic("some", "user"))).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Basic"))); - this.mvc.perform(get("/authenticated")) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/authenticated")).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer"))); - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer invalid_token")) + this.mvc.perform(get("/authenticated").header("Authorization", "Bearer invalid_token")) .andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer"))); } @Test - public void requestWhenFormLoginAndResourceServerEntryPointsThenSessionCreatedByRequest() - throws Exception { // different from DSL + public void requestWhenFormLoginAndResourceServerEntryPointsThenSessionCreatedByRequest() throws Exception { // different + // from + // DSL this.spring.configLocations(xml("MockJwtDecoder"), xml("FormAndResourceServer")).autowire(); JwtDecoder decoder = this.spring.getContext().getBean(JwtDecoder.class); when(decoder.decode(anyString())).thenThrow(JwtException.class); - MvcResult result = - this.mvc.perform(get("/authenticated")) - .andExpect(status().isUnauthorized()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/authenticated")).andExpect(status().isUnauthorized()).andReturn(); assertThat(result.getRequest().getSession(false)).isNotNull(); - result = - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer token")) - .andExpect(status().isUnauthorized()) - .andReturn(); + result = this.mvc.perform(get("/authenticated").header("Authorization", "Bearer token")) + .andExpect(status().isUnauthorized()).andReturn(); assertThat(result.getRequest().getSession(false)).isNull(); } @Test - public void getWhenAlsoUsingHttpBasicThenCorrectProviderEngages() - throws Exception { + public void getWhenAlsoUsingHttpBasicThenCorrectProviderEngages() throws Exception { this.spring.configLocations(xml("JwtRestOperations"), xml("BasicAndResourceServer")).autowire(); mockRestOperations(jwks("Default")); String token = this.token("ValidNoScopes"); - this.mvc.perform(get("/authenticated") - .header("Authorization", "Bearer " + token)) + this.mvc.perform(get("/authenticated").header("Authorization", "Bearer " + token)) .andExpect(status().isNotFound()); - this.mvc.perform(get("/authenticated") - .with(httpBasic("user", "password"))) - .andExpect(status().isNotFound()); + this.mvc.perform(get("/authenticated").with(httpBasic("user", "password"))).andExpect(status().isNotFound()); } // -- Incorrect Configuration @@ -928,28 +802,27 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { @Test public void configuredWhenMissingJwtAuthenticationProviderThenWiringException() { assertThatCode(() -> this.spring.configLocations(xml("Jwtless")).autowire()) - .isInstanceOf(BeanDefinitionParsingException.class) - .hasMessageContaining("Please select one"); + .isInstanceOf(BeanDefinitionParsingException.class).hasMessageContaining("Please select one"); } @Test public void configureWhenMissingJwkSetUriThenWiringException() { assertThatCode(() -> this.spring.configLocations(xml("JwtHalfConfigured")).autowire()) - .isInstanceOf(BeanDefinitionParsingException.class) - .hasMessageContaining("Please specify either"); + .isInstanceOf(BeanDefinitionParsingException.class).hasMessageContaining("Please specify either"); } @Test public void configureWhenUsingBothAuthenticationManagerResolverAndJwtThenException() { - assertThatCode(() -> this.spring.configLocations(xml("AuthenticationManagerResolverPlusOtherConfig")).autowire()) - .isInstanceOf(BeanDefinitionParsingException.class) - .hasMessageContaining("authentication-manager-resolver-ref"); + assertThatCode( + () -> this.spring.configLocations(xml("AuthenticationManagerResolverPlusOtherConfig")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class) + .hasMessageContaining("authentication-manager-resolver-ref"); } @Test public void validateConfigurationWhenMoreThanOneResourceServerModeThenError() { - OAuth2ResourceServerBeanDefinitionParser parser = new OAuth2ResourceServerBeanDefinitionParser - (null, null, null, null, null); + OAuth2ResourceServerBeanDefinitionParser parser = new OAuth2ResourceServerBeanDefinitionParser(null, null, null, + null, null); Element element = mock(Element.class); when(element.hasAttribute(AUTHENTICATION_MANAGER_RESOLVER_REF)).thenReturn(true); Element child = mock(Element.class); @@ -965,8 +838,8 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { @Test public void validateConfigurationWhenNoResourceServerModeThenError() { - OAuth2ResourceServerBeanDefinitionParser parser = new OAuth2ResourceServerBeanDefinitionParser - (null, null, null, null, null); + OAuth2ResourceServerBeanDefinitionParser parser = new OAuth2ResourceServerBeanDefinitionParser(null, null, null, + null, null); Element element = mock(Element.class); when(element.hasAttribute(AUTHENTICATION_MANAGER_RESOLVER_REF)).thenReturn(false); ParserContext pc = new ParserContext(mock(XmlReaderContext.class), mock(BeanDefinitionParserDelegate.class)); @@ -1019,8 +892,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { } static class JwtDecoderFactoryBean implements FactoryBean { + private RestOperations rest; + private RSAPublicKey key; + private OAuth2TokenValidator jwtValidator; @Override @@ -1028,9 +904,9 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { NimbusJwtDecoder decoder; if (this.key != null) { decoder = NimbusJwtDecoder.withPublicKey(this.key).build(); - } else { - decoder = NimbusJwtDecoder.withJwkSetUri("https://idp.example.org") - .restOperations(this.rest).build(); + } + else { + decoder = NimbusJwtDecoder.withJwkSetUri("https://idp.example.org").restOperations(this.rest).build(); } if (this.jwtValidator != null) { decoder.setJwtValidator(this.jwtValidator); @@ -1054,9 +930,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { public void setRest(RestOperations rest) { this.rest = rest; } + } static class OpaqueTokenIntrospectorFactoryBean implements FactoryBean { + private RestOperations rest; @Override @@ -1072,9 +950,11 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { public void setRest(RestOperations rest) { this.rest = rest; } + } static class MockWebServerFactoryBean implements FactoryBean, DisposableBean { + private final MockWebServer web = new MockWebServer(); @Override @@ -1091,10 +971,10 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { public Class getObjectType() { return MockWebServer.class; } + } - static class MockWebServerPropertiesFactoryBean - implements FactoryBean, DisposableBean { + static class MockWebServerPropertiesFactoryBean implements FactoryBean, DisposableBean { MockWebServer web; @@ -1121,10 +1001,10 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { public void destroy() throws Exception { this.web.shutdown(); } + } - static class ClockFactoryBean - implements FactoryBean { + static class ClockFactoryBean implements FactoryBean { Clock clock; @@ -1141,44 +1021,31 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { public void setMillis(long millis) { this.clock = Clock.fixed(Instant.ofEpochMilli(millis), ZoneId.systemDefault()); } + } private static ResultMatcher invalidRequestHeader(String message) { return header().string(HttpHeaders.WWW_AUTHENTICATE, - AllOf.allOf( - new StringStartsWith("Bearer " + - "error=\"invalid_request\", " + - "error_description=\""), + AllOf.allOf(new StringStartsWith("Bearer " + "error=\"invalid_request\", " + "error_description=\""), new StringContains(message), - new StringEndsWith(", " + - "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"") - ) - ); + new StringEndsWith(", " + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\""))); } private static ResultMatcher invalidTokenHeader(String message) { return header().string(HttpHeaders.WWW_AUTHENTICATE, - AllOf.allOf( - new StringStartsWith("Bearer " + - "error=\"invalid_token\", " + - "error_description=\""), + AllOf.allOf(new StringStartsWith("Bearer " + "error=\"invalid_token\", " + "error_description=\""), new StringContains(message), - new StringEndsWith(", " + - "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"") - ) - ); + new StringEndsWith(", " + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\""))); } private static ResultMatcher insufficientScopeHeader() { - return header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer " + - "error=\"insufficient_scope\"" + - ", error_description=\"The request requires higher privileges than provided by the access token.\"" + - ", error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\""); + return header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer " + "error=\"insufficient_scope\"" + + ", error_description=\"The request requires higher privileges than provided by the access token.\"" + + ", error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\""); } private String jwkSet() { - return new JWKSet(new RSAKey.Builder(TestKeys.DEFAULT_PUBLIC_KEY) - .keyID("1").build()).toString(); + return new JWKSet(new RSAKey.Builder(TestKeys.DEFAULT_PUBLIC_KEY).keyID("1").build()).toString(); } private String jwtFromIssuer(String issuer) throws Exception { @@ -1186,18 +1053,15 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { claims.put(ISS, issuer); claims.put(SUB, "test-subject"); claims.put("scope", "message:read"); - JWSObject jws = new JWSObject( - new JWSHeader.Builder(JWSAlgorithm.RS256).keyID("1").build(), + JWSObject jws = new JWSObject(new JWSHeader.Builder(JWSAlgorithm.RS256).keyID("1").build(), new Payload(new JSONObject(claims))); jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY)); return jws.serialize(); } private void mockWebServer(String response) { - this.web.enqueue(new MockResponse() - .setResponseCode(200) - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(response)); + this.web.enqueue(new MockResponse().setResponseCode(200) + .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(response)); } private void mockRestOperations(String response) { @@ -1205,8 +1069,7 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); ResponseEntity entity = new ResponseEntity<>(response, headers, HttpStatus.OK); - Mockito.when(rest.exchange(any(RequestEntity.class), eq(String.class))) - .thenReturn(entity); + Mockito.when(rest.exchange(any(RequestEntity.class), eq(String.class))).thenReturn(entity); } private String json(String name) throws IOException { @@ -1224,7 +1087,7 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { private String resource(String suffix) throws IOException { String name = this.getClass().getSimpleName() + "-" + suffix; ClassPathResource resource = new ClassPathResource(name, this.getClass()); - try ( BufferedReader reader = new BufferedReader(new FileReader(resource.getFile())) ) { + try (BufferedReader reader = new BufferedReader(new FileReader(resource.getFile()))) { return reader.lines().collect(Collectors.joining()); } } @@ -1236,4 +1099,5 @@ public class OAuth2ResourceServerBeanDefinitionParserTests { private String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/OpenIDConfigTests.java b/config/src/test/java/org/springframework/security/config/http/OpenIDConfigTests.java index b13678789c..930a991a2a 100644 --- a/config/src/test/java/org/springframework/security/config/http/OpenIDConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/OpenIDConfigTests.java @@ -59,8 +59,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Luke Taylor */ public class OpenIDConfigTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/OpenIDConfigTests"; + + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/OpenIDConfigTests"; @Autowired MockMvc mvc; @@ -69,37 +69,29 @@ public class OpenIDConfigTests { public final SpringTestRule spring = new SpringTestRule(); @Test - public void requestWhenOpenIDAndFormLoginBothConfiguredThenRedirectsToGeneratedLoginPage() - throws Exception { + public void requestWhenOpenIDAndFormLoginBothConfiguredThenRedirectsToGeneratedLoginPage() throws Exception { this.spring.configLocations(this.xml("WithFormLogin")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("http://localhost/login")); + this.mvc.perform(get("/")).andExpect(status().isFound()).andExpect(redirectedUrl("http://localhost/login")); assertThat(getFilter(DefaultLoginPageGeneratingFilter.class)).isNotNull(); } @Test - public void requestWhenOpenIDAndFormLoginWithFormLoginPageConfiguredThenFormLoginPageWins() - throws Exception { + public void requestWhenOpenIDAndFormLoginWithFormLoginPageConfiguredThenFormLoginPageWins() throws Exception { this.spring.configLocations(this.xml("WithFormLoginPage")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("http://localhost/form-page")); + this.mvc.perform(get("/")).andExpect(status().isFound()).andExpect(redirectedUrl("http://localhost/form-page")); } @Test - public void requestWhenOpenIDAndFormLoginWithOpenIDLoginPageConfiguredThenOpenIDLoginPageWins() - throws Exception { + public void requestWhenOpenIDAndFormLoginWithOpenIDLoginPageConfiguredThenOpenIDLoginPageWins() throws Exception { this.spring.configLocations(this.xml("WithOpenIDLoginPageAndFormLogin")).autowire(); - this.mvc.perform(get("/")) - .andExpect(status().isFound()) + this.mvc.perform(get("/")).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/openid-page")); } @@ -111,8 +103,7 @@ public class OpenIDConfigTests { } @Test - public void requestWhenOpenIDAndRememberMeConfiguredThenRememberMePassedToIdp() - throws Exception { + public void requestWhenOpenIDAndRememberMeConfiguredThenRememberMePassedToIdp() throws Exception { this.spring.configLocations(this.xml("WithRememberMe")).autowire(); @@ -129,27 +120,21 @@ public class OpenIDConfigTests { openIDFilter.setConsumer(consumer); String expectedReturnTo = new StringBuilder("http://localhost/login/openid").append("?") - .append(AbstractRememberMeServices.DEFAULT_PARAMETER) - .append("=").append("on").toString(); + .append(AbstractRememberMeServices.DEFAULT_PARAMETER).append("=").append("on").toString(); - this.mvc.perform(get("/")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("http://localhost/login")); + this.mvc.perform(get("/")).andExpect(status().isFound()).andExpect(redirectedUrl("http://localhost/login")); - this.mvc.perform(get("/login")) - .andExpect(status().isOk()) + this.mvc.perform(get("/login")).andExpect(status().isOk()) .andExpect(content().string(containsString(AbstractRememberMeServices.DEFAULT_PARAMETER))); this.mvc.perform(get("/login/openid") .param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, "https://ww1.openid.com") - .param(AbstractRememberMeServices.DEFAULT_PARAMETER, "on")) - .andExpect(status().isFound()) + .param(AbstractRememberMeServices.DEFAULT_PARAMETER, "on")).andExpect(status().isFound()) .andExpect(redirectedUrl(openIdEndpointUrl + expectedReturnTo)); } @Test - public void requestWhenAttributeExchangeConfiguredThenFetchAttributesPassedToIdp() - throws Exception { + public void requestWhenAttributeExchangeConfiguredThenFetchAttributesPassedToIdp() throws Exception { this.spring.configLocations(this.xml("WithOpenIDAttributes")).autowire(); @@ -158,25 +143,21 @@ public class OpenIDConfigTests { ConsumerManager manager = getFieldValue(consumer, "consumerManager"); manager.setMaxAssocAttempts(0); - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { String endpoint = server.url("/").toString(); + server.enqueue(new MockResponse().addHeader(YADIS_XRDS_LOCATION, endpoint)); server.enqueue(new MockResponse() - .addHeader(YADIS_XRDS_LOCATION, endpoint)); - server.enqueue(new MockResponse() - .setBody(String.format( - "%s", - endpoint))); + .setBody(String.format("%s", endpoint))); - this.mvc.perform(get("/login/openid") - .param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint)) + this.mvc.perform( + get("/login/openid").param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint)) .andExpect(status().isFound()) .andExpect(result -> result.getResponse().getRedirectedUrl().endsWith( - "openid.ext1.type.nickname=http%3A%2F%2Fschema.openid.net%2FnamePerson%2Ffriendly&" + - "openid.ext1.if_available=nickname&" + - "openid.ext1.type.email=http%3A%2F%2Fschema.openid.net%2Fcontact%2Femail&" + - "openid.ext1.required=email&" + - "openid.ext1.count.email=2")); + "openid.ext1.type.nickname=http%3A%2F%2Fschema.openid.net%2FnamePerson%2Ffriendly&" + + "openid.ext1.if_available=nickname&" + + "openid.ext1.type.email=http%3A%2F%2Fschema.openid.net%2Fcontact%2Femail&" + + "openid.ext1.required=email&" + "openid.ext1.count.email=2")); } } @@ -191,25 +172,22 @@ public class OpenIDConfigTests { assertThat(getFilter(DefaultLoginPageGeneratingFilter.class)).isNull(); - this.mvc.perform(get("/login")) - .andExpect(status().isOk()) - .andExpect(content().string("a custom login page")); + this.mvc.perform(get("/login")).andExpect(status().isOk()).andExpect(content().string("a custom login page")); } @RestController static class CustomLoginController { + @GetMapping("/login") public String custom() { return "a custom login page"; } + } private T getFilter(Class clazz) { FilterChainProxy filterChain = this.spring.getContext().getBean(FilterChainProxy.class); - return (T) filterChain.getFilters("/").stream() - .filter(clazz::isInstance) - .findFirst() - .orElse(null); + return (T) filterChain.getFilters("/").stream().filter(clazz::isInstance).findFirst().orElse(null); } private String xml(String configName) { @@ -219,4 +197,5 @@ public class OpenIDConfigTests { private static T getFieldValue(Object bean, String fieldName) throws IllegalAccessException { return (T) FieldUtils.getFieldValue(bean, fieldName); } + } diff --git a/config/src/test/java/org/springframework/security/config/http/PlaceHolderAndELConfigTests.java b/config/src/test/java/org/springframework/security/config/http/PlaceHolderAndELConfigTests.java index e887545055..b41595c926 100644 --- a/config/src/test/java/org/springframework/security/config/http/PlaceHolderAndELConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/PlaceHolderAndELConfigTests.java @@ -40,8 +40,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @SecurityTestExecutionListeners public class PlaceHolderAndELConfigTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/PlaceHolderAndELConfigTests"; + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/PlaceHolderAndELConfigTests"; @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -50,23 +49,20 @@ public class PlaceHolderAndELConfigTests { MockMvc mvc; @Test - public void getWhenUsingPlaceholderThenUnsecuredPatternCorrectlyConfigured() - throws Exception { + public void getWhenUsingPlaceholderThenUnsecuredPatternCorrectlyConfigured() throws Exception { System.setProperty("pattern.nofilters", "/unsecured"); this.spring.configLocations(this.xml("UnsecuredPattern")).autowire(); - this.mvc.perform(get("/unsecured")) - .andExpect(status().isOk()); + this.mvc.perform(get("/unsecured")).andExpect(status().isOk()); } /** * SEC-1201 */ @Test - public void loginWhenUsingPlaceholderThenInterceptUrlsAndFormLoginWorks() - throws Exception { + public void loginWhenUsingPlaceholderThenInterceptUrlsAndFormLoginWorks() throws Exception { System.setProperty("secure.Url", "/secured"); System.setProperty("secure.role", "ROLE_NUNYA"); @@ -78,22 +74,17 @@ public class PlaceHolderAndELConfigTests { // login-page setting - this.mvc.perform(get("/secured")) - .andExpect(redirectedUrl("http://localhost/loginPage")); + this.mvc.perform(get("/secured")).andExpect(redirectedUrl("http://localhost/loginPage")); // login-processing-url setting // default-target-url setting - this.mvc.perform(post("/loginPage") - .param("username", "user") - .param("password", "password")) + this.mvc.perform(post("/loginPage").param("username", "user").param("password", "password")) .andExpect(redirectedUrl("/defaultTarget")); // authentication-failure-url setting - this.mvc.perform(post("/loginPage") - .param("username", "user") - .param("password", "wrong")) + this.mvc.perform(post("/loginPage").param("username", "user").param("password", "wrong")) .andExpect(redirectedUrl("/authFailure")); } @@ -101,8 +92,7 @@ public class PlaceHolderAndELConfigTests { * SEC-1309 */ @Test - public void loginWhenUsingSpELThenInterceptUrlsAndFormLoginWorks() - throws Exception { + public void loginWhenUsingSpELThenInterceptUrlsAndFormLoginWorks() throws Exception { System.setProperty("secure.url", "/secured"); System.setProperty("secure.role", "ROLE_NUNYA"); @@ -110,91 +100,77 @@ public class PlaceHolderAndELConfigTests { System.setProperty("default.target", "/defaultTarget"); System.setProperty("auth.failure", "/authFailure"); - this.spring.configLocations( - this.xml("InterceptUrlAndFormLoginWithSpEL")).autowire(); + this.spring.configLocations(this.xml("InterceptUrlAndFormLoginWithSpEL")).autowire(); // login-page setting - this.mvc.perform(get("/secured")) - .andExpect(redirectedUrl("http://localhost/loginPage")); + this.mvc.perform(get("/secured")).andExpect(redirectedUrl("http://localhost/loginPage")); // login-processing-url setting // default-target-url setting - this.mvc.perform(post("/loginPage") - .param("username", "user") - .param("password", "password")) + this.mvc.perform(post("/loginPage").param("username", "user").param("password", "password")) .andExpect(redirectedUrl("/defaultTarget")); // authentication-failure-url setting - this.mvc.perform(post("/loginPage") - .param("username", "user") - .param("password", "wrong")) + this.mvc.perform(post("/loginPage").param("username", "user").param("password", "wrong")) .andExpect(redirectedUrl("/authFailure")); } @Test @WithMockUser - public void requestWhenUsingPlaceholderOrSpELThenPortMapperWorks() - throws Exception { + public void requestWhenUsingPlaceholderOrSpELThenPortMapperWorks() throws Exception { System.setProperty("http", "9080"); System.setProperty("https", "9443"); this.spring.configLocations(this.xml("PortMapping")).autowire(); - this.mvc.perform(get("http://localhost:9080/secured")) - .andExpect(status().isFound()) + this.mvc.perform(get("http://localhost:9080/secured")).andExpect(status().isFound()) .andExpect(redirectedUrl("https://localhost:9443/secured")); - this.mvc.perform(get("https://localhost:9443/unsecured")) - .andExpect(status().isFound()) + this.mvc.perform(get("https://localhost:9443/unsecured")).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost:9080/unsecured")); } @Test @WithMockUser - public void requestWhenUsingPlaceholderThenRequiresChannelWorks() - throws Exception { + public void requestWhenUsingPlaceholderThenRequiresChannelWorks() throws Exception { System.setProperty("secure.url", "/secured"); System.setProperty("required.channel", "https"); this.spring.configLocations(this.xml("RequiresChannel")).autowire(); - this.mvc.perform(get("http://localhost/secured")) - .andExpect(status().isFound()) + this.mvc.perform(get("http://localhost/secured")).andExpect(status().isFound()) .andExpect(redirectedUrl("https://localhost/secured")); } @Test @WithMockUser - public void requestWhenUsingPlaceholderThenAccessDeniedPageWorks() - throws Exception { + public void requestWhenUsingPlaceholderThenAccessDeniedPageWorks() throws Exception { System.setProperty("accessDenied", "/go-away"); this.spring.configLocations(this.xml("AccessDeniedPage")).autowire(); - this.mvc.perform(get("/secured")) - .andExpect(forwardedUrl("/go-away")); + this.mvc.perform(get("/secured")).andExpect(forwardedUrl("/go-away")); } @Test @WithMockUser - public void requestWhenUsingSpELThenAccessDeniedPageWorks() - throws Exception { + public void requestWhenUsingSpELThenAccessDeniedPageWorks() throws Exception { this.spring.configLocations(this.xml("AccessDeniedPageWithSpEL")).autowire(); - this.mvc.perform(get("/secured")) - .andExpect(forwardedUrl("/go-away")); + this.mvc.perform(get("/secured")).andExpect(forwardedUrl("/go-away")); } @RestController static class SimpleController { + @GetMapping("/unsecured") String unsecured() { return "unsecured"; @@ -204,9 +180,11 @@ public class PlaceHolderAndELConfigTests { String secured() { return "secured"; } + } private String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/RememberMeConfigTests.java b/config/src/test/java/org/springframework/security/config/http/RememberMeConfigTests.java index 0854316af8..9cd61b0640 100644 --- a/config/src/test/java/org/springframework/security/config/http/RememberMeConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/RememberMeConfigTests.java @@ -52,14 +52,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * * @author Luke Taylor * @author Rob Winch * @author Oliver Becker */ public class RememberMeConfigTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/RememberMeConfigTests"; + + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/RememberMeConfigTests"; @Autowired MockMvc mvc; @@ -68,20 +67,16 @@ public class RememberMeConfigTests { public final SpringTestRule spring = new SpringTestRule(); @Test - public void requestWithRememberMeWhenUsingCustomTokenRepositoryThenAutomaticallyReauthenticates() - throws Exception { + public void requestWithRememberMeWhenUsingCustomTokenRepositoryThenAutomaticallyReauthenticates() throws Exception { this.spring.configLocations(this.xml("WithTokenRepository")).autowire(); MvcResult result = this.rememberAuthentication("user", "password") - .andExpect(cookie().secure(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false)) - .andReturn(); + .andExpect(cookie().secure(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false)).andReturn(); Cookie cookie = rememberMeCookie(result); - this.mvc.perform(get("/authenticated") - .cookie(cookie)) - .andExpect(status().isOk()); + this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(status().isOk()); JdbcTemplate template = this.spring.getContext().getBean(JdbcTemplate.class); int count = template.queryForObject("select count(*) from persistent_logins", int.class); @@ -89,8 +84,7 @@ public class RememberMeConfigTests { } @Test - public void requestWithRememberMeWhenUsingCustomDataSourceThenAutomaticallyReauthenticates() - throws Exception { + public void requestWithRememberMeWhenUsingCustomDataSourceThenAutomaticallyReauthenticates() throws Exception { this.spring.configLocations(this.xml("WithDataSource")).autowire(); @@ -99,22 +93,18 @@ public class RememberMeConfigTests { template.execute(CREATE_TABLE_SQL); MvcResult result = this.rememberAuthentication("user", "password") - .andExpect(cookie().secure(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false)) - .andReturn(); + .andExpect(cookie().secure(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false)).andReturn(); Cookie cookie = rememberMeCookie(result); - this.mvc.perform(get("/authenticated") - .cookie(cookie)) - .andExpect(status().isOk()); + this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(status().isOk()); int count = template.queryForObject("select count(*) from persistent_logins", int.class); assertThat(count).isEqualTo(1); } @Test - public void requestWithRememberMeWhenUsingAuthenticationSuccessHandlerThenInvokesHandler() - throws Exception { + public void requestWithRememberMeWhenUsingAuthenticationSuccessHandlerThenInvokesHandler() throws Exception { this.spring.configLocations(this.xml("WithAuthenticationSuccessHandler")).autowire(); @@ -123,47 +113,36 @@ public class RememberMeConfigTests { template.execute(CREATE_TABLE_SQL); MvcResult result = this.rememberAuthentication("user", "password") - .andExpect(cookie().secure(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false)) - .andReturn(); + .andExpect(cookie().secure(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false)).andReturn(); Cookie cookie = rememberMeCookie(result); - this.mvc.perform(get("/authenticated") - .cookie(cookie)) - .andExpect(redirectedUrl("/target")); + this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(redirectedUrl("/target")); int count = template.queryForObject("select count(*) from persistent_logins", int.class); assertThat(count).isEqualTo(1); } @Test - public void requestWithRememberMeWhenUsingCustomRememberMeServicesThenAuthenticates() - throws Exception { + public void requestWithRememberMeWhenUsingCustomRememberMeServicesThenAuthenticates() throws Exception { // SEC-1281 - using key with external services this.spring.configLocations(this.xml("WithServicesRef")).autowire(); MvcResult result = this.rememberAuthentication("user", "password") .andExpect(cookie().secure(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, false)) - .andExpect(cookie().maxAge(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 5000)) - .andReturn(); + .andExpect(cookie().maxAge(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 5000)).andReturn(); Cookie cookie = rememberMeCookie(result); - this.mvc.perform(get("/authenticated") - .cookie(cookie)) - .andExpect(status().isOk()); + this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(status().isOk()); // SEC-909 - this.mvc.perform(post("/logout") - .cookie(cookie) - .with(csrf())) - .andExpect(cookie().maxAge(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 0)) - .andReturn(); + this.mvc.perform(post("/logout").cookie(cookie).with(csrf())) + .andExpect(cookie().maxAge(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 0)).andReturn(); } @Test - public void logoutWhenUsingRememberMeDefaultsThenCookieIsCancelled() - throws Exception { + public void logoutWhenUsingRememberMeDefaultsThenCookieIsCancelled() throws Exception { this.spring.configLocations(this.xml("DefaultConfig")).autowire(); @@ -171,9 +150,7 @@ public class RememberMeConfigTests { Cookie cookie = rememberMeCookie(result); - this.mvc.perform(post("/logout") - .cookie(cookie) - .with(csrf())) + this.mvc.perform(post("/logout").cookie(cookie).with(csrf())) .andExpect(cookie().maxAge(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 0)); } @@ -184,19 +161,15 @@ public class RememberMeConfigTests { this.spring.configLocations(this.xml("TokenValidity")).autowire(); MvcResult result = this.rememberAuthentication("user", "password") - .andExpect(cookie().maxAge(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 10000)) - .andReturn(); + .andExpect(cookie().maxAge(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 10000)).andReturn(); Cookie cookie = rememberMeCookie(result); - this.mvc.perform(get("/authenticated") - .cookie(cookie)) - .andExpect(status().isOk()); + this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(status().isOk()); } @Test - public void requestWithRememberMeWhenTokenValidityIsNegativeThenCookieReflectsCorrectExpiration() - throws Exception { + public void requestWithRememberMeWhenTokenValidityIsNegativeThenCookieReflectsCorrectExpiration() throws Exception { this.spring.configLocations(this.xml("NegativeTokenValidity")).autowire(); @@ -204,11 +177,10 @@ public class RememberMeConfigTests { .andExpect(cookie().maxAge(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, -1)); } - @Test public void configureWhenUsingDataSourceAndANegativeTokenValidityThenThrowsWiringException() { assertThatCode(() -> this.spring.configLocations(this.xml("NegativeTokenValidityWithDataSource")).autowire()) - .isInstanceOf(FatalBeanException.class); + .isInstanceOf(FatalBeanException.class); } @Test @@ -222,8 +194,7 @@ public class RememberMeConfigTests { } @Test - public void requestWithRememberMeWhenUseSecureCookieIsTrueThenCookieIsSecure() - throws Exception { + public void requestWithRememberMeWhenUseSecureCookieIsTrueThenCookieIsSecure() throws Exception { this.spring.configLocations(this.xml("SecureCookie")).autowire(); @@ -235,8 +206,7 @@ public class RememberMeConfigTests { * SEC-1827 */ @Test - public void requestWithRememberMeWhenUseSecureCookieIsFalseThenCookieIsNotSecure() - throws Exception { + public void requestWithRememberMeWhenUseSecureCookieIsFalseThenCookieIsNotSecure() throws Exception { this.spring.configLocations(this.xml("Sec1827")).autowire(); @@ -246,8 +216,9 @@ public class RememberMeConfigTests { @Test public void configureWhenUsingPersistentTokenRepositoryAndANegativeTokenValidityThenThrowsWiringException() { - assertThatCode(() -> this.spring.configLocations(this.xml("NegativeTokenValidityWithPersistentRepository")).autowire()) - .isInstanceOf(BeanDefinitionParsingException.class); + assertThatCode( + () -> this.spring.configLocations(this.xml("NegativeTokenValidityWithPersistentRepository")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class); } @Test @@ -256,16 +227,14 @@ public class RememberMeConfigTests { this.spring.configLocations(this.xml("WithUserDetailsService")).autowire(); UserDetailsService userDetailsService = this.spring.getContext().getBean(UserDetailsService.class); - when(userDetailsService.loadUserByUsername("user")).thenAnswer((invocation) -> - new User("user", "{noop}password", Collections.emptyList())); + when(userDetailsService.loadUserByUsername("user")) + .thenAnswer((invocation) -> new User("user", "{noop}password", Collections.emptyList())); MvcResult result = this.rememberAuthentication("user", "password").andReturn(); Cookie cookie = rememberMeCookie(result); - this.mvc.perform(get("/authenticated") - .cookie(cookie)) - .andExpect(status().isOk()); + this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(status().isOk()); verify(userDetailsService, atLeastOnce()).loadUserByUsername("user"); } @@ -274,46 +243,33 @@ public class RememberMeConfigTests { * SEC-742 */ @Test - public void requestWithRememberMeWhenExcludingBasicAuthenticationFilterThenStillReauthenticates() - throws Exception { + public void requestWithRememberMeWhenExcludingBasicAuthenticationFilterThenStillReauthenticates() throws Exception { this.spring.configLocations(this.xml("Sec742")).autowire(); - MvcResult result = - this.mvc.perform(login("user", "password") - .param("remember-me", "true") - .with(csrf())) - .andExpect(redirectedUrl("/messageList.html")) - .andReturn(); + MvcResult result = this.mvc.perform(login("user", "password").param("remember-me", "true").with(csrf())) + .andExpect(redirectedUrl("/messageList.html")).andReturn(); Cookie cookie = rememberMeCookie(result); - this.mvc.perform(get("/authenticated") - .cookie(cookie)) - .andExpect(status().isOk()); + this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(status().isOk()); } /** * SEC-2119 */ @Test - public void requestWithRememberMeWhenUsingCustomRememberMeParameterThenReauthenticates() - throws Exception { + public void requestWithRememberMeWhenUsingCustomRememberMeParameterThenReauthenticates() throws Exception { this.spring.configLocations(this.xml("WithRememberMeParameter")).autowire(); - MvcResult result = - this.mvc.perform(login("user", "password") - .param("custom-remember-me-parameter", "true") - .with(csrf())) - .andExpect(redirectedUrl("/")) - .andReturn(); + MvcResult result = this.mvc + .perform(login("user", "password").param("custom-remember-me-parameter", "true").with(csrf())) + .andExpect(redirectedUrl("/")).andReturn(); Cookie cookie = rememberMeCookie(result); - this.mvc.perform(get("/authenticated") - .cookie(cookie)) - .andExpect(status().isOk()); + this.mvc.perform(get("/authenticated").cookie(cookie)).andExpect(status().isOk()); } @Test @@ -326,13 +282,11 @@ public class RememberMeConfigTests { * SEC-2826 */ @Test - public void authenticateWhenUsingCustomRememberMeCookieNameThenIssuesCookieWithThatName() - throws Exception { + public void authenticateWhenUsingCustomRememberMeCookieNameThenIssuesCookieWithThatName() throws Exception { this.spring.configLocations(this.xml("WithRememberMeCookie")).autowire(); - this.rememberAuthentication("user", "password") - .andExpect(cookie().exists("custom-remember-me-cookie")); + this.rememberAuthentication("user", "password").andExpect(cookie().exists("custom-remember-me-cookie")); } /** @@ -341,26 +295,25 @@ public class RememberMeConfigTests { @Test public void configureWhenUsingRememberMeCookieAndServicesRefThenThrowsWiringException() { assertThatCode(() -> this.spring.configLocations(this.xml("WithRememberMeCookieAndServicesRef")).autowire()) - .isInstanceOf(BeanDefinitionParsingException.class) - .hasMessageContaining("Configuration problem: services-ref can't be used in combination with attributes " + - "token-repository-ref,data-source-ref, user-service-ref, token-validity-seconds, use-secure-cookie, " + - "remember-me-parameter or remember-me-cookie"); + .isInstanceOf(BeanDefinitionParsingException.class).hasMessageContaining( + "Configuration problem: services-ref can't be used in combination with attributes " + + "token-repository-ref,data-source-ref, user-service-ref, token-validity-seconds, use-secure-cookie, " + + "remember-me-parameter or remember-me-cookie"); } @RestController static class BasicController { + @GetMapping("/authenticated") String ok() { return "ok"; } + } - private ResultActions rememberAuthentication(String username, String password) - throws Exception { + private ResultActions rememberAuthentication(String username, String password) throws Exception { - return this.mvc.perform(login(username, password) - .param(DEFAULT_PARAMETER, "true") - .with(csrf())) + return this.mvc.perform(login(username, password).param(DEFAULT_PARAMETER, "true").with(csrf())) .andExpect(redirectedUrl("/")); } @@ -375,4 +328,5 @@ public class RememberMeConfigTests { private String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests.java b/config/src/test/java/org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests.java index 9f57135a89..d64f331191 100644 --- a/config/src/test/java/org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests.java @@ -46,7 +46,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * * @author Rob Winch * @author Josh Cummings */ @@ -54,8 +53,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @SecurityTestExecutionListeners public class SecurityContextHolderAwareRequestConfigTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests"; + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests"; @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -64,30 +62,24 @@ public class SecurityContextHolderAwareRequestConfigTests { private MockMvc mvc; @Test - public void servletLoginWhenUsingDefaultConfigurationThenUsesSpringSecurity() - throws Exception { + public void servletLoginWhenUsingDefaultConfigurationThenUsesSpringSecurity() throws Exception { this.spring.configLocations(this.xml("Simple")).autowire(); - this.mvc.perform(get("/good-login")) - .andExpect(status().isOk()) - .andExpect(content().string("user")); + this.mvc.perform(get("/good-login")).andExpect(status().isOk()).andExpect(content().string("user")); } @Test - public void servletAuthenticateWhenUsingDefaultConfigurationThenUsesSpringSecurity() - throws Exception { + public void servletAuthenticateWhenUsingDefaultConfigurationThenUsesSpringSecurity() throws Exception { this.spring.configLocations(this.xml("Simple")).autowire(); - this.mvc.perform(get("/authenticate")) - .andExpect(status().isFound()) + this.mvc.perform(get("/authenticate")).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/login")); } @Test - public void servletLogoutWhenUsingDefaultConfigurationThenUsesSpringSecurity() - throws Exception { + public void servletLogoutWhenUsingDefaultConfigurationThenUsesSpringSecurity() throws Exception { this.spring.configLocations(this.xml("Simple")).autowire(); @@ -97,10 +89,8 @@ public class SecurityContextHolderAwareRequestConfigTests { assertThat(session).isNotNull(); - result = this.mvc.perform(get("/do-logout").session(session)) - .andExpect(status().isOk()) - .andExpect(content().string("")) - .andReturn(); + result = this.mvc.perform(get("/do-logout").session(session)).andExpect(status().isOk()) + .andExpect(content().string("")).andReturn(); session = (MockHttpSession) result.getRequest().getSession(false); @@ -108,61 +98,48 @@ public class SecurityContextHolderAwareRequestConfigTests { } @Test - public void servletAuthenticateWhenUsingHttpBasicThenUsesSpringSecurity() - throws Exception { + public void servletAuthenticateWhenUsingHttpBasicThenUsesSpringSecurity() throws Exception { this.spring.configLocations(this.xml("HttpBasic")).autowire(); - this.mvc.perform(get("/authenticate")) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/authenticate")).andExpect(status().isUnauthorized()) .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, containsString("discworld"))); } @Test - public void servletAuthenticateWhenUsingFormLoginThenUsesSpringSecurity() - throws Exception { + public void servletAuthenticateWhenUsingFormLoginThenUsesSpringSecurity() throws Exception { this.spring.configLocations(this.xml("FormLogin")).autowire(); - this.mvc.perform(get("/authenticate")) - .andExpect(status().isFound()) + this.mvc.perform(get("/authenticate")).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/login")); } @Test - public void servletLoginWhenUsingMultipleHttpConfigsThenUsesSpringSecurity() - throws Exception { + public void servletLoginWhenUsingMultipleHttpConfigsThenUsesSpringSecurity() throws Exception { this.spring.configLocations(this.xml("MultiHttp")).autowire(); - this.mvc.perform(get("/good-login")) - .andExpect(status().isOk()) - .andExpect(content().string("user")); + this.mvc.perform(get("/good-login")).andExpect(status().isOk()).andExpect(content().string("user")); - this.mvc.perform(get("/v2/good-login")) - .andExpect(status().isOk()) - .andExpect(content().string("user2")); + this.mvc.perform(get("/v2/good-login")).andExpect(status().isOk()).andExpect(content().string("user2")); } @Test - public void servletAuthenticateWhenUsingMultipleHttpConfigsThenUsesSpringSecurity() - throws Exception { + public void servletAuthenticateWhenUsingMultipleHttpConfigsThenUsesSpringSecurity() throws Exception { this.spring.configLocations(this.xml("MultiHttp")).autowire(); - this.mvc.perform(get("/authenticate")) - .andExpect(status().isFound()) + this.mvc.perform(get("/authenticate")).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/login")); - this.mvc.perform(get("/v2/authenticate")) - .andExpect(status().isFound()) + this.mvc.perform(get("/v2/authenticate")).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/login2")); } @Test - public void servletLogoutWhenUsingMultipleHttpConfigsThenUsesSpringSecurity() - throws Exception { + public void servletLogoutWhenUsingMultipleHttpConfigsThenUsesSpringSecurity() throws Exception { this.spring.configLocations(this.xml("MultiHttp")).autowire(); @@ -172,10 +149,8 @@ public class SecurityContextHolderAwareRequestConfigTests { assertThat(session).isNotNull(); - result = this.mvc.perform(get("/do-logout").session(session)) - .andExpect(status().isOk()) - .andExpect(content().string("")) - .andReturn(); + result = this.mvc.perform(get("/do-logout").session(session)).andExpect(status().isOk()) + .andExpect(content().string("")).andReturn(); session = (MockHttpSession) result.getRequest().getSession(false); @@ -187,10 +162,8 @@ public class SecurityContextHolderAwareRequestConfigTests { assertThat(session).isNotNull(); - result = this.mvc.perform(get("/v2/do-logout").session(session)) - .andExpect(status().isOk()) - .andExpect(content().string("")) - .andReturn(); + result = this.mvc.perform(get("/v2/do-logout").session(session)).andExpect(status().isOk()) + .andExpect(content().string("")).andReturn(); session = (MockHttpSession) result.getRequest().getSession(false); @@ -198,13 +171,11 @@ public class SecurityContextHolderAwareRequestConfigTests { } @Test - public void servletLogoutWhenUsingCustomLogoutThenUsesSpringSecurity() - throws Exception { + public void servletLogoutWhenUsingCustomLogoutThenUsesSpringSecurity() throws Exception { this.spring.configLocations(this.xml("Logout")).autowire(); - this.mvc.perform(get("/authenticate")) - .andExpect(status().isFound()) + this.mvc.perform(get("/authenticate")).andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/signin")); MvcResult result = this.mvc.perform(get("/good-login")).andReturn(); @@ -213,11 +184,8 @@ public class SecurityContextHolderAwareRequestConfigTests { assertThat(session).isNotNull(); - result = this.mvc.perform(get("/do-logout").session(session)) - .andExpect(status().isOk()) - .andExpect(content().string("")) - .andExpect(cookie().maxAge("JSESSIONID", 0)) - .andReturn(); + result = this.mvc.perform(get("/do-logout").session(session)).andExpect(status().isOk()) + .andExpect(content().string("")).andExpect(cookie().maxAge("JSESSIONID", 0)).andReturn(); session = (MockHttpSession) result.getRequest().getSession(false); @@ -229,8 +197,7 @@ public class SecurityContextHolderAwareRequestConfigTests { */ @Test @WithMockUser - public void servletIsUserInRoleWhenUsingDefaultConfigThenRoleIsSet() - throws Exception { + public void servletIsUserInRoleWhenUsingDefaultConfigThenRoleIsSet() throws Exception { this.spring.configLocations(this.xml("Simple")).autowire(); @@ -239,6 +206,7 @@ public class SecurityContextHolderAwareRequestConfigTests { @RestController public static class ServletAuthenticatedController { + @GetMapping("/v2/good-login") public String v2Login(HttpServletRequest request) throws ServletException { @@ -289,14 +257,16 @@ public class SecurityContextHolderAwareRequestConfigTests { } private String principal() { - if ( SecurityContextHolder.getContext().getAuthentication() != null ) { + if (SecurityContextHolder.getContext().getAuthentication() != null) { return SecurityContextHolder.getContext().getAuthentication().getName(); } return null; } + } private String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/SecurityFiltersAssertions.java b/config/src/test/java/org/springframework/security/config/http/SecurityFiltersAssertions.java index 776cb49a92..7b9da04b9e 100644 --- a/config/src/test/java/org/springframework/security/config/http/SecurityFiltersAssertions.java +++ b/config/src/test/java/org/springframework/security/config/http/SecurityFiltersAssertions.java @@ -23,18 +23,19 @@ import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; /** - * Assertions for tests that rely on confirming behavior of the package-private SecurityFilters enum + * Assertions for tests that rely on confirming behavior of the package-private + * SecurityFilters enum * * @author Josh Cummings */ public class SecurityFiltersAssertions { + private static Collection ordered = Arrays.asList(SecurityFilters.values()); public static void assertEquals(List filters) { - List expected = ordered.stream() - .map(SecurityFilters::name) - .collect(Collectors.toList()); + List expected = ordered.stream().map(SecurityFilters::name).collect(Collectors.toList()); assertThat(filters).isEqualTo(expected); } + } diff --git a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigServlet31Tests.java b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigServlet31Tests.java index 7ced0f768a..1f7c2107e0 100644 --- a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigServlet31Tests.java +++ b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigServlet31Tests.java @@ -48,17 +48,18 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @PrepareForTest({ ReflectionUtils.class, Method.class }) @PowerMockIgnore({ "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", "javax.xml.parsers.*" }) public class SessionManagementConfigServlet31Tests { - private static final String XML_AUTHENTICATION_MANAGER = "" - + " " + " " - + " " - + " " + " " - + ""; + + private static final String XML_AUTHENTICATION_MANAGER = "" + " " + + " " + " " + + " " + " " + ""; @Mock Method method; MockHttpServletRequest request; + MockHttpServletResponse response; + MockFilterChain chain; ConfigurableApplicationContext context; @@ -92,13 +93,11 @@ public class SessionManagementConfigServlet31Tests { String id = request.getSession().getId(); - loadContext("\n" + " \n" - + " \n" + " \n" - + " " + XML_AUTHENTICATION_MANAGER); + loadContext("\n" + " \n" + " \n" + + " \n" + " " + XML_AUTHENTICATION_MANAGER); springSecurityFilterChain.doFilter(request, response, chain); - assertThat(request.getSession().getId()).isNotEqualTo(id); assertThat(request.getSession().getAttribute("attribute1")).isEqualTo("value1"); } @@ -115,11 +114,9 @@ public class SessionManagementConfigServlet31Tests { String id = request.getSession().getId(); - loadContext("\n" - + " \n" + loadContext("\n" + " \n" + " \n" - + " \n" + " " - + XML_AUTHENTICATION_MANAGER); + + " \n" + " " + XML_AUTHENTICATION_MANAGER); springSecurityFilterChain.doFilter(request, response, chain); @@ -129,19 +126,17 @@ public class SessionManagementConfigServlet31Tests { private void loadContext(String context) { this.context = new InMemoryXmlApplicationContext(context); - this.springSecurityFilterChain = this.context.getBean( - "springSecurityFilterChain", Filter.class); + this.springSecurityFilterChain = this.context.getBean("springSecurityFilterChain", Filter.class); } private void login(Authentication auth) { HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository(); - HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder( - request, response); + HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response); repo.loadContext(requestResponseHolder); SecurityContextImpl securityContextImpl = new SecurityContextImpl(); securityContextImpl.setAuthentication(auth); - repo.saveContext(securityContextImpl, requestResponseHolder.getRequest(), - requestResponseHolder.getResponse()); + repo.saveContext(securityContextImpl, requestResponseHolder.getRequest(), requestResponseHolder.getResponse()); } + } diff --git a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTests.java b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTests.java index 141ac51b75..b91007a29a 100644 --- a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTests.java @@ -69,7 +69,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** - * Tests session-related functionality for the <http> namespace element and <session-management> + * Tests session-related functionality for the <http> namespace element and + * <session-management> * * @author Luke Taylor * @author Rob Winch @@ -77,8 +78,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Onur Kagan Ozcan */ public class SessionManagementConfigTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/SessionManagementConfigTests"; + + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/SessionManagementConfigTests"; @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -87,8 +88,7 @@ public class SessionManagementConfigTests { MockMvc mvc; @Test - public void requestWhenCreateSessionAlwaysThenAlwaysCreatesSession() - throws Exception { + public void requestWhenCreateSessionAlwaysThenAlwaysCreatesSession() throws Exception { this.spring.configLocations(this.xml("CreateSessionAlways")).autowire(); MockHttpServletRequest request = get("/").buildRequest(this.servletContext()); @@ -99,8 +99,7 @@ public class SessionManagementConfigTests { } @Test - public void requestWhenCreateSessionIsSetToNeverThenDoesNotCreateSessionOnLoginChallenge() - throws Exception { + public void requestWhenCreateSessionIsSetToNeverThenDoesNotCreateSessionOnLoginChallenge() throws Exception { this.spring.configLocations(this.xml("CreateSessionNever")).autowire(); @@ -112,14 +111,11 @@ public class SessionManagementConfigTests { } @Test - public void requestWhenCreateSessionIsSetToNeverThenDoesNotCreateSessionOnLogin() - throws Exception { + public void requestWhenCreateSessionIsSetToNeverThenDoesNotCreateSessionOnLogin() throws Exception { this.spring.configLocations(this.xml("CreateSessionNever")).autowire(); - MockHttpServletRequest request = post("/login") - .param("username", "user") - .param("password", "password") + MockHttpServletRequest request = post("/login").param("username", "user").param("password", "password") .buildRequest(this.servletContext()); request = csrf().postProcessRequest(request); MockHttpServletResponse response = request(request, this.spring.getContext()); @@ -129,14 +125,11 @@ public class SessionManagementConfigTests { } @Test - public void requestWhenCreateSessionIsSetToNeverThenUsesExistingSession() - throws Exception { + public void requestWhenCreateSessionIsSetToNeverThenUsesExistingSession() throws Exception { this.spring.configLocations(this.xml("CreateSessionNever")).autowire(); - MockHttpServletRequest request = post("/login") - .param("username", "user") - .param("password", "password") + MockHttpServletRequest request = post("/login").param("username", "user").param("password", "password") .buildRequest(this.servletContext()); request = csrf().postProcessRequest(request); MockHttpSession session = new MockHttpSession(); @@ -145,59 +138,41 @@ public class SessionManagementConfigTests { assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_MOVED_TEMPORARILY); assertThat(request.getSession(false)).isNotNull(); - assertThat(request.getSession(false).getAttribute(SPRING_SECURITY_CONTEXT_KEY)) - .isNotNull(); + assertThat(request.getSession(false).getAttribute(SPRING_SECURITY_CONTEXT_KEY)).isNotNull(); } @Test - public void requestWhenCreateSessionIsSetToStatelessThenDoesNotCreateSessionOnLoginChallenge() - throws Exception { + public void requestWhenCreateSessionIsSetToStatelessThenDoesNotCreateSessionOnLoginChallenge() throws Exception { this.spring.configLocations(this.xml("CreateSessionStateless")).autowire(); - this.mvc.perform(get("/auth")) - .andExpect(status().isFound()) - .andExpect(session().exists(false)); + this.mvc.perform(get("/auth")).andExpect(status().isFound()).andExpect(session().exists(false)); } @Test - public void requestWhenCreateSessionIsSetToStatelessThenDoesNotCreateSessionOnLogin() - throws Exception { + public void requestWhenCreateSessionIsSetToStatelessThenDoesNotCreateSessionOnLogin() throws Exception { this.spring.configLocations(this.xml("CreateSessionStateless")).autowire(); - - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .with(csrf())) - .andExpect(status().isFound()) - .andExpect(session().exists(false)); + this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf())) + .andExpect(status().isFound()).andExpect(session().exists(false)); } @Test - public void requestWhenCreateSessionIsSetToStatelessThenIgnoresExistingSession() - throws Exception { + public void requestWhenCreateSessionIsSetToStatelessThenIgnoresExistingSession() throws Exception { this.spring.configLocations(this.xml("CreateSessionStateless")).autowire(); - MvcResult result = - this.mvc.perform(post("/login") - .param("username", "user") - .param("password", "password") - .session(new MockHttpSession()) - .with(csrf())) - .andExpect(status().isFound()) - .andExpect(session()) - .andReturn(); + MvcResult result = this.mvc + .perform(post("/login").param("username", "user").param("password", "password") + .session(new MockHttpSession()).with(csrf())) + .andExpect(status().isFound()).andExpect(session()).andReturn(); - assertThat(result.getRequest().getSession(false).getAttribute(SPRING_SECURITY_CONTEXT_KEY)) - .isNull(); + assertThat(result.getRequest().getSession(false).getAttribute(SPRING_SECURITY_CONTEXT_KEY)).isNull(); } @Test - public void requestWhenCreateSessionIsSetToIfRequiredThenDoesNotCreateSessionOnPublicInvocation() - throws Exception { + public void requestWhenCreateSessionIsSetToIfRequiredThenDoesNotCreateSessionOnPublicInvocation() throws Exception { this.spring.configLocations(this.xml("CreateSessionIfRequired")).autowire(); @@ -210,8 +185,7 @@ public class SessionManagementConfigTests { } @Test - public void requestWhenCreateSessionIsSetToIfRequiredThenCreatesSessionOnLoginChallenge() - throws Exception { + public void requestWhenCreateSessionIsSetToIfRequiredThenCreatesSessionOnLoginChallenge() throws Exception { this.spring.configLocations(this.xml("CreateSessionIfRequired")).autowire(); @@ -224,15 +198,12 @@ public class SessionManagementConfigTests { } @Test - public void requestWhenCreateSessionIsSetToIfRequiredThenCreatesSessionOnLogin() - throws Exception { + public void requestWhenCreateSessionIsSetToIfRequiredThenCreatesSessionOnLogin() throws Exception { this.spring.configLocations(this.xml("CreateSessionIfRequired")).autowire(); ServletContext servletContext = this.mvc.getDispatcherServlet().getServletContext(); - MockHttpServletRequest request = post("/login") - .param("username", "user") - .param("password", "password") + MockHttpServletRequest request = post("/login").param("username", "user").param("password", "password") .buildRequest(servletContext); request = csrf().postProcessRequest(request); MockHttpServletResponse response = request(request, this.spring.getContext()); @@ -245,19 +216,14 @@ public class SessionManagementConfigTests { * SEC-1208 */ @Test - public void requestWhenRejectingUserBasedOnMaxSessionsExceededThenDoesNotCreateSession() - throws Exception { + public void requestWhenRejectingUserBasedOnMaxSessionsExceededThenDoesNotCreateSession() throws Exception { this.spring.configLocations(this.xml("Sec1208")).autowire(); - this.mvc.perform(get("/auth") - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()) + this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isOk()) .andExpect(session()); - this.mvc.perform(get("/auth") - .with(httpBasic("user", "password"))) - .andExpect(status().isUnauthorized()) + this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isUnauthorized()) .andExpect(session().exists(false)); } @@ -271,10 +237,7 @@ public class SessionManagementConfigTests { this.spring.configLocations(this.xml("Sec2137")).autowire(); MockHttpSession session = new MockHttpSession(); - this.mvc.perform(get("/auth") - .session(session) - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()) + this.mvc.perform(get("/auth").session(session).with(httpBasic("user", "password"))).andExpect(status().isOk()) .andExpect(session().id(session.getId())); } @@ -286,16 +249,12 @@ public class SessionManagementConfigTests { } @Test - public void requestWhenExpiredUrlIsSetThenInvalidatesSessionAndRedirects() - throws Exception { + public void requestWhenExpiredUrlIsSetThenInvalidatesSessionAndRedirects() throws Exception { this.spring.configLocations(this.xml("ConcurrencyControlExpiredUrl")).autowire(); - this.mvc.perform(get("/auth") - .session(this.expiredSession()) - .with(httpBasic("user", "password"))) - .andExpect(redirectedUrl("/expired")) - .andExpect(session().exists(false)); + this.mvc.perform(get("/auth").session(this.expiredSession()).with(httpBasic("user", "password"))) + .andExpect(redirectedUrl("/expired")).andExpect(session().exists(false)); } @Test @@ -304,26 +263,18 @@ public class SessionManagementConfigTests { this.spring.configLocations(this.xml("ConcurrencyControlLogoutAndRememberMeHandlers")).autowire(); - this.mvc.perform(get("/auth") - .session(this.expiredSession()) - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()) - .andExpect(cookie().maxAge("testCookie", 0)) - .andExpect(cookie().exists("rememberMeCookie")) - .andExpect(session().valid(true)); + this.mvc.perform(get("/auth").session(this.expiredSession()).with(httpBasic("user", "password"))) + .andExpect(status().isOk()).andExpect(cookie().maxAge("testCookie", 0)) + .andExpect(cookie().exists("rememberMeCookie")).andExpect(session().valid(true)); } @Test - public void requestWhenConcurrencyControlAndRememberMeAreSetThenInvokedWhenSessionExpires() - throws Exception { + public void requestWhenConcurrencyControlAndRememberMeAreSetThenInvokedWhenSessionExpires() throws Exception { this.spring.configLocations(this.xml("ConcurrencyControlRememberMeHandler")).autowire(); - this.mvc.perform(get("/auth") - .session(this.expiredSession()) - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()) - .andExpect(cookie().exists("rememberMeCookie")) + this.mvc.perform(get("/auth").session(this.expiredSession()).with(httpBasic("user", "password"))) + .andExpect(status().isOk()).andExpect(cookie().exists("rememberMeCookie")) .andExpect(session().exists(false)); } @@ -331,49 +282,37 @@ public class SessionManagementConfigTests { * SEC-2057 */ @Test - public void autowireWhenConcurrencyControlIsSetThenLogoutHandlersGetAuthenticationObject() - throws Exception { + public void autowireWhenConcurrencyControlIsSetThenLogoutHandlersGetAuthenticationObject() throws Exception { this.spring.configLocations(this.xml("ConcurrencyControlCustomLogoutHandler")).autowire(); - MvcResult result = - this.mvc.perform(get("/auth") - .with(httpBasic("user", "password"))) - .andExpect(session()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(session()) + .andReturn(); MockHttpSession session = (MockHttpSession) result.getRequest().getSession(false); SessionRegistry sessionRegistry = this.spring.getContext().getBean(SessionRegistry.class); sessionRegistry.getSessionInformation(session.getId()).expireNow(); - this.mvc.perform(get("/auth") - .session(session)) - .andExpect(header().string("X-Username", "user")); + this.mvc.perform(get("/auth").session(session)).andExpect(header().string("X-Username", "user")); } @Test - public void requestWhenConcurrencyControlIsSetThenDefaultsToResponseBodyExpirationResponse() - throws Exception { + public void requestWhenConcurrencyControlIsSetThenDefaultsToResponseBodyExpirationResponse() throws Exception { this.spring.configLocations(this.xml("ConcurrencyControlSessionRegistryAlias")).autowire(); - this.mvc.perform(get("/auth") - .session(this.expiredSession()) - .with(httpBasic("user", "password"))) + this.mvc.perform(get("/auth").session(this.expiredSession()).with(httpBasic("user", "password"))) .andExpect(content().string("This session has been expired (possibly due to multiple concurrent " + "logins being attempted as the same user).")); } @Test - public void requestWhenCustomSessionAuthenticationStrategyThenInvokesOnAuthentication() - throws Exception { + public void requestWhenCustomSessionAuthenticationStrategyThenInvokesOnAuthentication() throws Exception { this.spring.configLocations(this.xml("SessionAuthenticationStrategyRef")).autowire(); - this.mvc.perform(get("/auth") - .with(httpBasic("user", "password"))) - .andExpect(status().isIAmATeapot()); + this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isIAmATeapot()); } @Test @@ -384,22 +323,15 @@ public class SessionManagementConfigTests { } @Test - public void requestWhenMaxSessionsIsSetThenErrorsWhenExceeded() - throws Exception { + public void requestWhenMaxSessionsIsSetThenErrorsWhenExceeded() throws Exception { this.spring.configLocations(this.xml("ConcurrencyControlMaxSessions")).autowire(); - this.mvc.perform(get("/auth") - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isOk()); - this.mvc.perform(get("/auth") - .with(httpBasic("user", "password"))) - .andExpect(status().isOk()); + this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isOk()); - this.mvc.perform(get("/auth") - .with(httpBasic("user", "password"))) - .andExpect(redirectedUrl("/max-exceeded")); + this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(redirectedUrl("/max-exceeded")); } @Test @@ -411,35 +343,27 @@ public class SessionManagementConfigTests { } @Test - public void requestWhenSessionFixationProtectionIsNoneThenSessionNotInvalidated() - throws Exception { + public void requestWhenSessionFixationProtectionIsNoneThenSessionNotInvalidated() throws Exception { this.spring.configLocations(this.xml("SessionFixationProtectionNone")).autowire(); MockHttpSession session = new MockHttpSession(); String sessionId = session.getId(); - this.mvc.perform(get("/auth") - .session(session) - .with(httpBasic("user", "password"))) + this.mvc.perform(get("/auth").session(session).with(httpBasic("user", "password"))) .andExpect(session().id(sessionId)); } @Test - public void requestWhenSessionFixationProtectionIsMigrateSessionThenSessionIsReplaced() - throws Exception { + public void requestWhenSessionFixationProtectionIsMigrateSessionThenSessionIsReplaced() throws Exception { this.spring.configLocations(this.xml("SessionFixationProtectionMigrateSession")).autowire(); MockHttpSession session = new MockHttpSession(); String sessionId = session.getId(); - MvcResult result = - this.mvc.perform(get("/auth") - .session(session) - .with(httpBasic("user", "password"))) - .andExpect(session()) - .andReturn(); + MvcResult result = this.mvc.perform(get("/auth").session(session).with(httpBasic("user", "password"))) + .andExpect(session()).andReturn(); assertThat(result.getRequest().getSession(false).getId()).isNotEqualTo(sessionId); } @@ -450,13 +374,11 @@ public class SessionManagementConfigTests { this.spring.configLocations(this.xml("SessionFixationProtectionNoneWithInvalidSessionUrl")).autowire(); - this.mvc.perform(get("/auth") - .with(request -> { - request.setRequestedSessionId("1"); - request.setRequestedSessionIdValid(false); - return request; - })) - .andExpect(redirectedUrl("/timeoutUrl")); + this.mvc.perform(get("/auth").with(request -> { + request.setRequestedSessionId("1"); + request.setRequestedSessionIdValid(false); + return request; + })).andExpect(redirectedUrl("/timeoutUrl")); } /** @@ -488,16 +410,16 @@ public class SessionManagementConfigTests { static class TeapotSessionAuthenticationStrategy implements SessionAuthenticationStrategy { @Override - public void onAuthentication( - Authentication authentication, - HttpServletRequest request, + public void onAuthentication(Authentication authentication, HttpServletRequest request, HttpServletResponse response) throws SessionAuthenticationException { response.setStatus(org.springframework.http.HttpStatus.I_AM_A_TEAPOT.value()); } + } static class CustomRememberMeServices implements RememberMeServices, LogoutHandler { + @Override public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) { return null; @@ -509,7 +431,8 @@ public class SessionManagementConfigTests { } @Override - public void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) { + public void loginSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication successfulAuthentication) { } @@ -517,10 +440,12 @@ public class SessionManagementConfigTests { public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { response.addHeader("X-Username", authentication.getName()); } + } @RestController static class BasicController { + @GetMapping("/") public String ok() { return "ok"; @@ -530,21 +455,21 @@ public class SessionManagementConfigTests { public String auth(Principal principal) { return principal.getName(); } + } private void sessionRegistryIsValid() { - SessionRegistry sessionRegistry = this.spring.getContext() - .getBean("sessionRegistry", SessionRegistry.class); + SessionRegistry sessionRegistry = this.spring.getContext().getBean("sessionRegistry", SessionRegistry.class); assertThat(sessionRegistry).isNotNull(); - assertThat(this.getFilter(ConcurrentSessionFilter.class)) - .returns(sessionRegistry, this::extractSessionRegistry); - assertThat(this.getFilter(UsernamePasswordAuthenticationFilter.class)) - .returns(sessionRegistry, this::extractSessionRegistry); + assertThat(this.getFilter(ConcurrentSessionFilter.class)).returns(sessionRegistry, + this::extractSessionRegistry); + assertThat(this.getFilter(UsernamePasswordAuthenticationFilter.class)).returns(sessionRegistry, + this::extractSessionRegistry); // SEC-1143 - assertThat(this.getFilter(SessionManagementFilter.class)) - .returns(sessionRegistry, this::extractSessionRegistry); + assertThat(this.getFilter(SessionManagementFilter.class)).returns(sessionRegistry, + this::extractSessionRegistry); } private SessionRegistry extractSessionRegistry(ConcurrentSessionFilter filter) { @@ -566,7 +491,8 @@ public class SessionManagementConfigTests { private T getFieldValue(Object target, String fieldName) { try { return (T) FieldUtils.getFieldValue(target, fieldName); - } catch (Exception e) { + } + catch (Exception e) { throw new RuntimeException(e); } } @@ -576,8 +502,11 @@ public class SessionManagementConfigTests { } private static class SessionResultMatcher implements ResultMatcher { + private String id; + private Boolean valid; + private Boolean exists = true; public ResultMatcher exists(boolean exists) { @@ -609,7 +538,8 @@ public class SessionManagementConfigTests { if (this.valid != null) { if (this.valid) { assertThat(session.isInvalid()).isFalse(); - } else { + } + else { assertThat(session.isInvalid()).isTrue(); } } @@ -618,27 +548,23 @@ public class SessionManagementConfigTests { assertThat(session.getId()).isEqualTo(this.id); } } + } - private static MockHttpServletResponse request( - MockHttpServletRequest request, - ApplicationContext context) + private static MockHttpServletResponse request(MockHttpServletRequest request, ApplicationContext context) throws IOException, ServletException { MockHttpServletResponse response = new MockHttpServletResponse(); FilterChainProxy proxy = context.getBean(FilterChainProxy.class); - proxy.doFilter( - request, - new EncodeUrlDenyingHttpServletResponseWrapper(response), - (req, resp) -> {}); + proxy.doFilter(request, new EncodeUrlDenyingHttpServletResponseWrapper(response), (req, resp) -> { + }); return response; } - private static class EncodeUrlDenyingHttpServletResponseWrapper - extends HttpServletResponseWrapper { + private static class EncodeUrlDenyingHttpServletResponseWrapper extends HttpServletResponseWrapper { EncodeUrlDenyingHttpServletResponseWrapper(HttpServletResponse response) { super(response); @@ -663,6 +589,7 @@ public class SessionManagementConfigTests { public String encodeRedirectUrl(String url) { throw new RuntimeException("Unexpected invocation of encodeURL"); } + } private MockHttpSession expiredSession() { @@ -674,10 +601,7 @@ public class SessionManagementConfigTests { } private T getFilter(Class filterClass) { - return (T) getFilters().stream() - .filter(filterClass::isInstance) - .findFirst() - .orElse(null); + return (T) getFilters().stream().filter(filterClass::isInstance).findFirst().orElse(null); } private List getFilters() { @@ -694,4 +618,5 @@ public class SessionManagementConfigTests { private String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTransientAuthenticationTests.java b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTransientAuthenticationTests.java index e13801ba58..fe909288bc 100644 --- a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTransientAuthenticationTests.java +++ b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTransientAuthenticationTests.java @@ -35,8 +35,8 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder * @author Josh Cummings */ public class SessionManagementConfigTransientAuthenticationTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/http/SessionManagementConfigTransientAuthenticationTests"; + + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/SessionManagementConfigTransientAuthenticationTests"; @Autowired MockMvc mvc; @@ -45,8 +45,7 @@ public class SessionManagementConfigTransientAuthenticationTests { public final SpringTestRule spring = new SpringTestRule(); @Test - public void postWhenTransientAuthenticationThenNoSessionCreated() - throws Exception { + public void postWhenTransientAuthenticationThenNoSessionCreated() throws Exception { this.spring.configLocations(this.xml("WithTransientAuthentication")).autowire(); MvcResult result = this.mvc.perform(post("/login")).andReturn(); @@ -54,8 +53,7 @@ public class SessionManagementConfigTransientAuthenticationTests { } @Test - public void postWhenTransientAuthenticationThenAlwaysSessionOverrides() - throws Exception { + public void postWhenTransientAuthenticationThenAlwaysSessionOverrides() throws Exception { this.spring.configLocations(this.xml("CreateSessionAlwaysWithTransientAuthentication")).autowire(); MvcResult result = this.mvc.perform(post("/login")).andReturn(); @@ -73,10 +71,12 @@ public class SessionManagementConfigTransientAuthenticationTests { public boolean supports(Class authentication) { return true; } + } @Transient static class SomeTransientAuthentication extends AbstractAuthenticationToken { + SomeTransientAuthentication() { super(null); } @@ -90,9 +90,11 @@ public class SessionManagementConfigTransientAuthenticationTests { public Object getPrincipal() { return null; } + } private String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/http/WebConfigUtilsTests.java b/config/src/test/java/org/springframework/security/config/http/WebConfigUtilsTests.java index 532fea1706..50d8501a01 100644 --- a/config/src/test/java/org/springframework/security/config/http/WebConfigUtilsTests.java +++ b/config/src/test/java/org/springframework/security/config/http/WebConfigUtilsTests.java @@ -27,6 +27,7 @@ import org.springframework.beans.factory.xml.ParserContext; @RunWith(PowerMockRunner.class) @PrepareOnlyThisForTest(ParserContext.class) public class WebConfigUtilsTests { + public final static String URL = "/url"; @Mock @@ -35,9 +36,9 @@ public class WebConfigUtilsTests { // SEC-1980 @Test public void validateHttpRedirectSpELNoParserWarning() { - WebConfigUtils.validateHttpRedirect( - "#{T(org.springframework.security.config.http.WebConfigUtilsTest).URL}", + WebConfigUtils.validateHttpRedirect("#{T(org.springframework.security.config.http.WebConfigUtilsTest).URL}", parserContext, "fakeSource"); verifyZeroInteractions(parserContext); } + } \ No newline at end of file diff --git a/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomConfigurer.java b/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomConfigurer.java index cf2f5bace0..c3ee15d29f 100644 --- a/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomConfigurer.java +++ b/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomConfigurer.java @@ -33,8 +33,12 @@ public class CustomConfigurer extends SecurityConfigurerAdapter" - + "" - + "" - + " " - + "" - + ""); + setContext( + "" + + "" + "" + + " " + "" + + ""); PostProcessedMockUserDetailsService service = (PostProcessedMockUserDetailsService) appContext .getBean("myUserService"); @@ -143,17 +141,13 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { public void worksWithAspectJAutoproxy() { setContext("" + " " - + "" + + " access='ROLE_SOMETHING' />" + "" + "" + "" + "" - + " " - + ""); + + " " + "
    "); - UserDetailsService service = (UserDetailsService) appContext - .getBean("myUserService"); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "Test", "Password", + UserDetailsService service = (UserDetailsService) appContext.getBean("myUserService"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE")); SecurityContextHolder.getContext().setAuthentication(token); @@ -167,8 +161,8 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { + " " + " " + "" + ConfigTestUtils.AUTH_PROVIDER_XML); - SecurityContextHolder.getContext().setAuthentication( - new UsernamePasswordAuthenticationToken("user", "password")); + SecurityContextHolder.getContext() + .setAuthentication(new UsernamePasswordAuthenticationToken("user", "password")); target = (BusinessService) appContext.getBean("target"); // someOther(int) should not be matched by someOther(String), but should require // ROLE_USER @@ -186,13 +180,10 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { @Test public void supportsBooleanPointcutExpressions() { setContext("" - + "" - + " " + " " - + "" - + AUTH_PROVIDER_XML); + + " access='ROLE_USER'/>" + "" + AUTH_PROVIDER_XML); target = (BusinessService) appContext.getBean("target"); // String method should not be protected target.someOther("somestring"); @@ -205,8 +196,8 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { catch (AuthenticationCredentialsNotFoundException expected) { } - SecurityContextHolder.getContext().setAuthentication( - new UsernamePasswordAuthenticationToken("user", "password")); + SecurityContextHolder.getContext() + .setAuthentication(new UsernamePasswordAuthenticationToken("user", "password")); target.someOther(0); } @@ -224,8 +215,7 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { + " " + "" + AUTH_PROVIDER_XML); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "Test", "Password", + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE")); SecurityContextHolder.getContext().setAuthentication(token); target = (BusinessService) appContext.getBean("businessService"); @@ -236,24 +226,19 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { @SuppressWarnings("unchecked") @Test - public void expressionVoterAndAfterInvocationProviderUseSameExpressionHandlerInstance() - throws Exception { - setContext("" - + AUTH_PROVIDER_XML); - AffirmativeBased adm = (AffirmativeBased) appContext - .getBeansOfType(AffirmativeBased.class).values().toArray()[0]; - List voters = (List) FieldUtils.getFieldValue(adm, "decisionVoters"); - PreInvocationAuthorizationAdviceVoter mev = (PreInvocationAuthorizationAdviceVoter) voters - .get(0); - MethodSecurityMetadataSourceAdvisor msi = (MethodSecurityMetadataSourceAdvisor) appContext - .getBeansOfType(MethodSecurityMetadataSourceAdvisor.class).values() + public void expressionVoterAndAfterInvocationProviderUseSameExpressionHandlerInstance() throws Exception { + setContext("" + AUTH_PROVIDER_XML); + AffirmativeBased adm = (AffirmativeBased) appContext.getBeansOfType(AffirmativeBased.class).values() .toArray()[0]; + List voters = (List) FieldUtils.getFieldValue(adm, "decisionVoters"); + PreInvocationAuthorizationAdviceVoter mev = (PreInvocationAuthorizationAdviceVoter) voters.get(0); + MethodSecurityMetadataSourceAdvisor msi = (MethodSecurityMetadataSourceAdvisor) appContext + .getBeansOfType(MethodSecurityMetadataSourceAdvisor.class).values().toArray()[0]; AfterInvocationProviderManager pm = (AfterInvocationProviderManager) ((MethodSecurityInterceptor) msi .getAdvice()).getAfterInvocationManager(); - PostInvocationAdviceProvider aip = (PostInvocationAdviceProvider) pm - .getProviders().get(0); - assertThat(FieldUtils.getFieldValue(mev, "preAdvice.expressionHandler")).isSameAs(FieldUtils - .getFieldValue(aip, "postAdvice.expressionHandler")); + PostInvocationAdviceProvider aip = (PostInvocationAdviceProvider) pm.getProviders().get(0); + assertThat(FieldUtils.getFieldValue(mev, "preAdvice.expressionHandler")) + .isSameAs(FieldUtils.getFieldValue(aip, "postAdvice.expressionHandler")); } @Test(expected = AccessDeniedException.class) @@ -269,8 +254,7 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { @Test public void beanNameExpressionPropertyIsSupported() { setContext("" - + "" - + " " + + "" + " " + "" + "" + AUTH_PROVIDER_XML); @@ -316,11 +300,9 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { @Test public void customPermissionEvaluatorIsSupported() { setContext("" - + " " - + "" + + " " + "" + "" - + " " - + "" + + " " + "" + "" + AUTH_PROVIDER_XML); } @@ -329,10 +311,11 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { @Test(expected = AuthenticationException.class) @SuppressWarnings("unchecked") public void genericsAreMatchedByProtectPointcut() { - setContext("" - + "" - + " " - + "" + AUTH_PROVIDER_XML); + setContext( + "" + + "" + + " " + + "" + AUTH_PROVIDER_XML); Foo foo = (Foo) appContext.getBean("target"); foo.foo(new SecurityConfig("A")); } @@ -342,8 +325,7 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { @SuppressWarnings("unchecked") public void genericsMethodArgumentNamesAreResolved() { setContext("" - + "" - + AUTH_PROVIDER_XML); + + "" + AUTH_PROVIDER_XML); SecurityContextHolder.getContext().setAuthentication(bob); Foo foo = (Foo) appContext.getBean("target"); foo.foo(new SecurityConfig("A")); @@ -357,26 +339,19 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { parent.registerSingleton("runAsMgr", RunAsManagerImpl.class, props); parent.refresh(); - setContext("" - + AUTH_PROVIDER_XML, parent); + setContext("" + AUTH_PROVIDER_XML, parent); RunAsManagerImpl ram = (RunAsManagerImpl) appContext.getBean("runAsMgr"); MethodSecurityMetadataSourceAdvisor msi = (MethodSecurityMetadataSourceAdvisor) appContext - .getBeansOfType(MethodSecurityMetadataSourceAdvisor.class).values() - .toArray()[0]; + .getBeansOfType(MethodSecurityMetadataSourceAdvisor.class).values().toArray()[0]; assertThat(ram).isSameAs(FieldUtils.getFieldValue(msi.getAdvice(), "runAsManager")); } @Test @SuppressWarnings("unchecked") public void supportsExternalMetadataSource() { - setContext("" - + "" - + " " - + "" + setContext("" + + "" + " " + "" + "" + AUTH_PROVIDER_XML); // External MDS should take precedence over PreAuthorize @@ -388,25 +363,19 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { } catch (AccessDeniedException expected) { } - SecurityContextHolder.getContext().setAuthentication( - new UsernamePasswordAuthenticationToken("admin", "password")); + SecurityContextHolder.getContext() + .setAuthentication(new UsernamePasswordAuthenticationToken("admin", "password")); foo.foo(new SecurityConfig("A")); } @Test public void supportsCustomAuthenticationManager() { - setContext("" - + "" - + " " - + "" + setContext("" + + "" + " " + "" + "" + "" - + " " + "" - + AUTH_PROVIDER_XML); + + " " + "" + AUTH_PROVIDER_XML); SecurityContextHolder.getContext().setAuthentication(bob); Foo foo = (Foo) appContext.getBean("target"); try { @@ -415,22 +384,22 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { } catch (AccessDeniedException expected) { } - SecurityContextHolder.getContext().setAuthentication( - new UsernamePasswordAuthenticationToken("admin", "password")); + SecurityContextHolder.getContext() + .setAuthentication(new UsernamePasswordAuthenticationToken("admin", "password")); foo.foo(new SecurityConfig("A")); } - static class CustomAuthManager implements AuthenticationManager, - ApplicationContextAware { + static class CustomAuthManager implements AuthenticationManager, ApplicationContextAware { + private String beanName; + private AuthenticationManager authenticationManager; CustomAuthManager(String beanName) { this.beanName = beanName; } - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { return authenticationManager.authenticate(authentication); } @@ -441,11 +410,10 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { * org.springframework.context.ApplicationContextAware#setApplicationContext(org * .springframework.context.ApplicationContext) */ - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.authenticationManager = applicationContext.getBean(beanName, - AuthenticationManager.class); + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.authenticationManager = applicationContext.getBean(beanName, AuthenticationManager.class); } + } private void setContext(String context) { @@ -457,13 +425,17 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { } interface Foo { + void foo(T action); + } public static class ConcreteFoo implements Foo { + @PreAuthorize("#action.attribute == 'A'") public void foo(SecurityConfig action) { } + } } diff --git a/config/src/test/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecoratorTests.java b/config/src/test/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecoratorTests.java index 087d0e1bdc..b7a2907633 100644 --- a/config/src/test/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecoratorTests.java +++ b/config/src/test/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecoratorTests.java @@ -42,14 +42,16 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:org/springframework/security/config/method-security.xml") -public class InterceptMethodsBeanDefinitionDecoratorTests implements - ApplicationContextAware { +public class InterceptMethodsBeanDefinitionDecoratorTests implements ApplicationContextAware { + @Autowired @Qualifier("target") private TestBusinessBean target; + @Autowired @Qualifier("transactionalTarget") private TestBusinessBean transactionalTarget; + private ApplicationContext appContext; @BeforeClass @@ -67,8 +69,7 @@ public class InterceptMethodsBeanDefinitionDecoratorTests implements public void targetDoesntLoseApplicationListenerInterface() { assertThat(appContext.getBeansOfType(ApplicationListener.class)).hasSize(1); assertThat(appContext.getBeanNamesForType(ApplicationListener.class)).hasSize(1); - appContext.publishEvent(new AuthenticationSuccessEvent( - new TestingAuthenticationToken("user", ""))); + appContext.publishEvent(new AuthenticationSuccessEvent(new TestingAuthenticationToken("user", ""))); assertThat(target).isInstanceOf(ApplicationListener.class); } @@ -85,8 +86,8 @@ public class InterceptMethodsBeanDefinitionDecoratorTests implements @Test public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "Test", "Password", AuthorityUtils.createAuthorityList("ROLE_USER")); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", + AuthorityUtils.createAuthorityList("ROLE_USER")); SecurityContextHolder.getContext().setAuthentication(token); target.doSomething(); @@ -94,8 +95,7 @@ public class InterceptMethodsBeanDefinitionDecoratorTests implements @Test(expected = AccessDeniedException.class) public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "Test", "Password", + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE")); SecurityContextHolder.getContext().setAuthentication(token); @@ -107,8 +107,8 @@ public class InterceptMethodsBeanDefinitionDecoratorTests implements transactionalTarget.doSomething(); } - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.appContext = applicationContext; } + } diff --git a/config/src/test/java/org/springframework/security/config/method/Jsr250AnnotationDrivenBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/method/Jsr250AnnotationDrivenBeanDefinitionParserTests.java index c84bd208cb..5c61525e03 100644 --- a/config/src/test/java/org/springframework/security/config/method/Jsr250AnnotationDrivenBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/method/Jsr250AnnotationDrivenBeanDefinitionParserTests.java @@ -31,6 +31,7 @@ import org.springframework.security.core.context.SecurityContextHolder; * @author Luke Taylor */ public class Jsr250AnnotationDrivenBeanDefinitionParserTests { + private InMemoryXmlApplicationContext appContext; private BusinessService target; @@ -39,8 +40,7 @@ public class Jsr250AnnotationDrivenBeanDefinitionParserTests { public void loadContext() { appContext = new InMemoryXmlApplicationContext( "" - + "" - + ConfigTestUtils.AUTH_PROVIDER_XML); + + "" + ConfigTestUtils.AUTH_PROVIDER_XML); target = (BusinessService) appContext.getBean("target"); } @@ -59,8 +59,8 @@ public class Jsr250AnnotationDrivenBeanDefinitionParserTests { @Test public void permitAllShouldBeDefaultAttribute() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "Test", "Password", AuthorityUtils.createAuthorityList("ROLE_USER")); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", + AuthorityUtils.createAuthorityList("ROLE_USER")); SecurityContextHolder.getContext().setAuthentication(token); target.someOther(0); @@ -68,8 +68,8 @@ public class Jsr250AnnotationDrivenBeanDefinitionParserTests { @Test public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "Test", "Password", AuthorityUtils.createAuthorityList("ROLE_USER")); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", + AuthorityUtils.createAuthorityList("ROLE_USER")); SecurityContextHolder.getContext().setAuthentication(token); target.someUserMethod1(); @@ -77,8 +77,7 @@ public class Jsr250AnnotationDrivenBeanDefinitionParserTests { @Test(expected = AccessDeniedException.class) public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "Test", "Password", + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", AuthorityUtils.createAuthorityList("ROLE_SOMEOTHERROLE")); SecurityContextHolder.getContext().setAuthentication(token); @@ -87,10 +86,11 @@ public class Jsr250AnnotationDrivenBeanDefinitionParserTests { @Test public void hasAnyRoleAddsDefaultPrefix() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "Test", "Password", AuthorityUtils.createAuthorityList("ROLE_USER")); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", + AuthorityUtils.createAuthorityList("ROLE_USER")); SecurityContextHolder.getContext().setAuthentication(token); target.rolesAllowedUser(); } + } diff --git a/config/src/test/java/org/springframework/security/config/method/PreAuthorizeServiceImpl.java b/config/src/test/java/org/springframework/security/config/method/PreAuthorizeServiceImpl.java index 48e9e24ba2..bac5904bb5 100644 --- a/config/src/test/java/org/springframework/security/config/method/PreAuthorizeServiceImpl.java +++ b/config/src/test/java/org/springframework/security/config/method/PreAuthorizeServiceImpl.java @@ -22,9 +22,11 @@ package org.springframework.security.config.method; public class PreAuthorizeServiceImpl { @PreAuthorizeAdminRole - public void preAuthorizeAdminRole() {} + public void preAuthorizeAdminRole() { + } @ContactPermission - public void contactPermission(Contact contact) {} + public void contactPermission(Contact contact) { + } } \ No newline at end of file diff --git a/config/src/test/java/org/springframework/security/config/method/PreAuthorizeTests.java b/config/src/test/java/org/springframework/security/config/method/PreAuthorizeTests.java index 676c31314c..67ebb43bac 100644 --- a/config/src/test/java/org/springframework/security/config/method/PreAuthorizeTests.java +++ b/config/src/test/java/org/springframework/security/config/method/PreAuthorizeTests.java @@ -26,13 +26,13 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** - * * @author Rob Winch * */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class PreAuthorizeTests { + @Autowired PreAuthorizeServiceImpl service; @@ -43,25 +43,30 @@ public class PreAuthorizeTests { @Test(expected = AccessDeniedException.class) public void preAuthorizeAdminRoleDenied() { - SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_USER")); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_USER")); service.preAuthorizeAdminRole(); } @Test public void preAuthorizeAdminRoleGranted() { - SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN")); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN")); service.preAuthorizeAdminRole(); } @Test public void preAuthorizeContactPermissionGranted() { - SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN")); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN")); service.contactPermission(new Contact("user")); } @Test(expected = AccessDeniedException.class) public void preAuthorizeContactPermissionDenied() { - SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN")); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN")); service.contactPermission(new Contact("admin")); } + } \ No newline at end of file diff --git a/config/src/test/java/org/springframework/security/config/method/Sec2196Tests.java b/config/src/test/java/org/springframework/security/config/method/Sec2196Tests.java index 6e1c38aade..9a3bf2be91 100644 --- a/config/src/test/java/org/springframework/security/config/method/Sec2196Tests.java +++ b/config/src/test/java/org/springframework/security/config/method/Sec2196Tests.java @@ -37,8 +37,8 @@ public class Sec2196Tests { loadContext("" + ""); - SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken("test", "pass", "ROLE_USER")); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("test", "pass", "ROLE_USER")); Service service = context.getBean(Service.class); service.save(new User()); } @@ -48,8 +48,8 @@ public class Sec2196Tests { loadContext("" + ""); - SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken("test", "pass", "saveUsers")); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("test", "pass", "saveUsers")); Service service = context.getBean(Service.class); service.save(new User()); } @@ -68,12 +68,16 @@ public class Sec2196Tests { } public static class Service { + @PreAuthorize("hasAuthority('saveUsers')") public T save(T dto) { return dto; } + } static class User { + } + } diff --git a/config/src/test/java/org/springframework/security/config/method/SecuredAdminRole.java b/config/src/test/java/org/springframework/security/config/method/SecuredAdminRole.java index 8140450c86..31c98e9592 100644 --- a/config/src/test/java/org/springframework/security/config/method/SecuredAdminRole.java +++ b/config/src/test/java/org/springframework/security/config/method/SecuredAdminRole.java @@ -26,4 +26,6 @@ import org.springframework.security.access.annotation.Secured; */ @Retention(RetentionPolicy.RUNTIME) @Secured("ROLE_ADMIN") -public @interface SecuredAdminRole { } \ No newline at end of file +public @interface SecuredAdminRole { + +} \ No newline at end of file diff --git a/config/src/test/java/org/springframework/security/config/method/SecuredAnnotationDrivenBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/method/SecuredAnnotationDrivenBeanDefinitionParserTests.java index 0f9af88507..998ff9fe65 100644 --- a/config/src/test/java/org/springframework/security/config/method/SecuredAnnotationDrivenBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/method/SecuredAnnotationDrivenBeanDefinitionParserTests.java @@ -38,6 +38,7 @@ import org.springframework.security.core.context.SecurityContextHolder; * @author Ben Alex */ public class SecuredAnnotationDrivenBeanDefinitionParserTests { + private InMemoryXmlApplicationContext appContext; private BusinessService target; @@ -67,8 +68,8 @@ public class SecuredAnnotationDrivenBeanDefinitionParserTests { @Test public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "Test", "Password", AuthorityUtils.createAuthorityList("ROLE_USER")); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", + AuthorityUtils.createAuthorityList("ROLE_USER")); SecurityContextHolder.getContext().setAuthentication(token); target.someUserMethod1(); @@ -76,8 +77,8 @@ public class SecuredAnnotationDrivenBeanDefinitionParserTests { @Test(expected = AccessDeniedException.class) public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "Test", "Password", AuthorityUtils.createAuthorityList("ROLE_SOMEOTHER")); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", + AuthorityUtils.createAuthorityList("ROLE_SOMEOTHER")); SecurityContextHolder.getContext().setAuthentication(token); target.someAdminMethod(); @@ -97,15 +98,13 @@ public class SecuredAnnotationDrivenBeanDefinitionParserTests { } catch (AuthenticationCredentialsNotFoundException expected) { } - SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken("u", "p", "ROLE_A")); + SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("u", "p", "ROLE_A")); BusinessService chompedTarget = (BusinessService) serializeAndDeserialize(target); chompedTarget.someAdminMethod(); } - private Object serializeAndDeserialize(Object o) throws IOException, - ClassNotFoundException { + private Object serializeAndDeserialize(Object o) throws IOException, ClassNotFoundException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(o); diff --git a/config/src/test/java/org/springframework/security/config/method/SecuredServiceImpl.java b/config/src/test/java/org/springframework/security/config/method/SecuredServiceImpl.java index 5dd48e224b..c5a5d4547e 100644 --- a/config/src/test/java/org/springframework/security/config/method/SecuredServiceImpl.java +++ b/config/src/test/java/org/springframework/security/config/method/SecuredServiceImpl.java @@ -16,11 +16,13 @@ package org.springframework.security.config.method; /** -* -* @author Rob Winch -* -*/ + * @author Rob Winch + * + */ public class SecuredServiceImpl { + @SecuredAdminRole - public void securedAdminRole() {} + public void securedAdminRole() { + } + } diff --git a/config/src/test/java/org/springframework/security/config/method/SecuredTests.java b/config/src/test/java/org/springframework/security/config/method/SecuredTests.java index 01788afc0b..21fd98e0ee 100644 --- a/config/src/test/java/org/springframework/security/config/method/SecuredTests.java +++ b/config/src/test/java/org/springframework/security/config/method/SecuredTests.java @@ -26,13 +26,13 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** - * * @author Rob Winch * */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class SecuredTests { + @Autowired SecuredServiceImpl service; @@ -43,13 +43,16 @@ public class SecuredTests { @Test(expected = AccessDeniedException.class) public void securedAdminRoleDenied() { - SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_USER")); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_USER")); service.securedAdminRole(); } @Test public void securedAdminRoleGranted() { - SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN")); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN")); service.securedAdminRole(); } + } \ No newline at end of file diff --git a/config/src/test/java/org/springframework/security/config/method/TestPermissionEvaluator.java b/config/src/test/java/org/springframework/security/config/method/TestPermissionEvaluator.java index 087250407b..9f804f4f15 100644 --- a/config/src/test/java/org/springframework/security/config/method/TestPermissionEvaluator.java +++ b/config/src/test/java/org/springframework/security/config/method/TestPermissionEvaluator.java @@ -22,13 +22,12 @@ import org.springframework.security.core.Authentication; public class TestPermissionEvaluator implements PermissionEvaluator { - public boolean hasPermission(Authentication authentication, - Object targetDomainObject, Object permission) { + public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) { return false; } - public boolean hasPermission(Authentication authentication, Serializable targetId, - String targetType, Object permission) { + public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, + Object permission) { return false; } diff --git a/config/src/test/java/org/springframework/security/config/method/configuration/Gh4020GlobalMethodSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/method/configuration/Gh4020GlobalMethodSecurityConfigurationTests.java index 4dcb611c12..ac1bc7b814 100644 --- a/config/src/test/java/org/springframework/security/config/method/configuration/Gh4020GlobalMethodSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/method/configuration/Gh4020GlobalMethodSecurityConfigurationTests.java @@ -39,6 +39,7 @@ import static org.mockito.Mockito.mock; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class Gh4020GlobalMethodSecurityConfigurationTests { + @Autowired DenyAllService denyAll; @@ -51,6 +52,7 @@ public class Gh4020GlobalMethodSecurityConfigurationTests { @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) static class SecurityConfig { + @Bean PermissionEvaluator permissionEvaluator() { return mock(PermissionEvaluator.class); @@ -68,19 +70,25 @@ public class Gh4020GlobalMethodSecurityConfigurationTests { @Autowired DenyAllService denyAll; + } @Configuration static class ServiceConfig { + @Bean DenyAllService denyAllService() { return new DenyAllService(); } + } @PreAuthorize("denyAll") static class DenyAllService { + void denyAll() { } + } + } diff --git a/config/src/test/java/org/springframework/security/config/method/sec2136/JpaPermissionEvaluator.java b/config/src/test/java/org/springframework/security/config/method/sec2136/JpaPermissionEvaluator.java index d664cd6956..275ac42e6f 100644 --- a/config/src/test/java/org/springframework/security/config/method/sec2136/JpaPermissionEvaluator.java +++ b/config/src/test/java/org/springframework/security/config/method/sec2136/JpaPermissionEvaluator.java @@ -24,11 +24,11 @@ import org.springframework.security.access.PermissionEvaluator; import org.springframework.security.core.Authentication; /** - * * @author Rob Winch * */ public class JpaPermissionEvaluator implements PermissionEvaluator { + @Autowired private EntityManager entityManager; @@ -36,13 +36,13 @@ public class JpaPermissionEvaluator implements PermissionEvaluator { System.out.println("initializing " + this); } - public boolean hasPermission(Authentication authentication, - Object targetDomainObject, Object permission) { + public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) { return true; } - public boolean hasPermission(Authentication authentication, Serializable targetId, - String targetType, Object permission) { + public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, + Object permission) { return true; } + } diff --git a/config/src/test/java/org/springframework/security/config/method/sec2136/Sec2136Tests.java b/config/src/test/java/org/springframework/security/config/method/sec2136/Sec2136Tests.java index e921086911..dee9f84914 100644 --- a/config/src/test/java/org/springframework/security/config/method/sec2136/Sec2136Tests.java +++ b/config/src/test/java/org/springframework/security/config/method/sec2136/Sec2136Tests.java @@ -21,7 +21,6 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** - * * @author Rob Winch * @since 3.2 */ @@ -33,4 +32,5 @@ public class Sec2136Tests { public void configurationLoads() { } + } diff --git a/config/src/test/java/org/springframework/security/config/method/sec2499/Sec2499Tests.java b/config/src/test/java/org/springframework/security/config/method/sec2499/Sec2499Tests.java index 2fb5200bbb..429579f946 100644 --- a/config/src/test/java/org/springframework/security/config/method/sec2499/Sec2499Tests.java +++ b/config/src/test/java/org/springframework/security/config/method/sec2499/Sec2499Tests.java @@ -20,11 +20,11 @@ import org.junit.Test; import org.springframework.context.support.GenericXmlApplicationContext; /** - * * @author Rob Winch * */ public class Sec2499Tests { + private GenericXmlApplicationContext parent; private GenericXmlApplicationContext child; @@ -41,11 +41,11 @@ public class Sec2499Tests { @Test public void methodExpressionHandlerInParentContextLoads() { - parent = new GenericXmlApplicationContext( - "org/springframework/security/config/method/sec2499/parent.xml"); + parent = new GenericXmlApplicationContext("org/springframework/security/config/method/sec2499/parent.xml"); child = new GenericXmlApplicationContext(); child.load("org/springframework/security/config/method/sec2499/child.xml"); child.setParent(parent); child.refresh(); } + } \ No newline at end of file diff --git a/config/src/test/java/org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParserTests.java index 6378f6a0ce..fccad498bc 100644 --- a/config/src/test/java/org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParserTests.java @@ -41,79 +41,42 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Ruby Hartono */ public class ClientRegistrationsBeanDefinitionParserTests { + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/oauth2/client/ClientRegistrationsBeanDefinitionParserTests"; - private static final String ISSUER_URI_XML_CONFIG = "\n" + - "\n" + - "\t\n" + - "\t\t\n" + - "\t\t\n" + - "\t\n" + - "\n" + - "\n"; + private static final String ISSUER_URI_XML_CONFIG = "\n" + "\n" + + "\t\n" + + "\t\t\n" + + "\t\t\n" + "\t\n" + + "\n" + "\n"; - private static final String OIDC_DISCOVERY_RESPONSE = - "{\n" + private static final String OIDC_DISCOVERY_RESPONSE = "{\n" + " \"authorization_endpoint\": \"https://example.com/o/oauth2/v2/auth\", \n" - + " \"claims_supported\": [\n" - + " \"aud\", \n" - + " \"email\", \n" - + " \"email_verified\", \n" - + " \"exp\", \n" - + " \"family_name\", \n" - + " \"given_name\", \n" - + " \"iat\", \n" - + " \"iss\", \n" - + " \"locale\", \n" - + " \"name\", \n" - + " \"picture\", \n" - + " \"sub\"\n" - + " ], \n" - + " \"code_challenge_methods_supported\": [\n" - + " \"plain\", \n" - + " \"S256\"\n" - + " ], \n" - + " \"id_token_signing_alg_values_supported\": [\n" - + " \"RS256\"\n" - + " ], \n" - + " \"issuer\": \"${issuer-uri}\", \n" - + " \"jwks_uri\": \"https://example.com/oauth2/v3/certs\", \n" - + " \"response_types_supported\": [\n" - + " \"code\", \n" - + " \"token\", \n" - + " \"id_token\", \n" - + " \"code token\", \n" - + " \"code id_token\", \n" - + " \"token id_token\", \n" - + " \"code token id_token\", \n" - + " \"none\"\n" - + " ], \n" - + " \"revocation_endpoint\": \"https://example.com/o/oauth2/revoke\", \n" - + " \"scopes_supported\": [\n" - + " \"openid\", \n" - + " \"email\", \n" - + " \"profile\"\n" - + " ], \n" - + " \"subject_types_supported\": [\n" - + " \"public\"\n" - + " ], \n" - + " \"grant_types_supported\" : [\"authorization_code\"], \n" + + " \"claims_supported\": [\n" + " \"aud\", \n" + " \"email\", \n" + + " \"email_verified\", \n" + " \"exp\", \n" + " \"family_name\", \n" + + " \"given_name\", \n" + " \"iat\", \n" + " \"iss\", \n" + " \"locale\", \n" + + " \"name\", \n" + " \"picture\", \n" + " \"sub\"\n" + " ], \n" + + " \"code_challenge_methods_supported\": [\n" + " \"plain\", \n" + " \"S256\"\n" + + " ], \n" + " \"id_token_signing_alg_values_supported\": [\n" + " \"RS256\"\n" + " ], \n" + + " \"issuer\": \"${issuer-uri}\", \n" + " \"jwks_uri\": \"https://example.com/oauth2/v3/certs\", \n" + + " \"response_types_supported\": [\n" + " \"code\", \n" + " \"token\", \n" + + " \"id_token\", \n" + " \"code token\", \n" + " \"code id_token\", \n" + + " \"token id_token\", \n" + " \"code token id_token\", \n" + " \"none\"\n" + + " ], \n" + " \"revocation_endpoint\": \"https://example.com/o/oauth2/revoke\", \n" + + " \"scopes_supported\": [\n" + " \"openid\", \n" + " \"email\", \n" + + " \"profile\"\n" + " ], \n" + " \"subject_types_supported\": [\n" + " \"public\"\n" + + " ], \n" + " \"grant_types_supported\" : [\"authorization_code\"], \n" + " \"token_endpoint\": \"https://example.com/oauth2/v4/token\", \n" - + " \"token_endpoint_auth_methods_supported\": [\n" - + " \"client_secret_post\", \n" - + " \"client_secret_basic\", \n" - + " \"none\"\n" - + " ], \n" - + " \"userinfo_endpoint\": \"https://example.com/oauth2/v3/userinfo\"\n" - + "}"; + + " \"token_endpoint_auth_methods_supported\": [\n" + " \"client_secret_post\", \n" + + " \"client_secret_basic\", \n" + " \"none\"\n" + " ], \n" + + " \"userinfo_endpoint\": \"https://example.com/oauth2/v3/userinfo\"\n" + "}"; @Autowired private ClientRegistrationRepository clientRegistrationRepository; @@ -152,7 +115,8 @@ public class ClientRegistrationsBeanDefinitionParserTests { assertThat(googleRegistration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.BASIC); assertThat(googleRegistration.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); assertThat(googleRegistration.getRedirectUri()).isEqualTo("{baseUrl}/{action}/oauth2/code/{registrationId}"); - assertThat(googleRegistration.getScopes()).isEqualTo(StringUtils.commaDelimitedListToSet("openid,profile,email")); + assertThat(googleRegistration.getScopes()) + .isEqualTo(StringUtils.commaDelimitedListToSet("openid,profile,email")); assertThat(googleRegistration.getClientName()).isEqualTo(serverUrl); ProviderDetails googleProviderDetails = googleRegistration.getProviderDetails(); @@ -182,7 +146,8 @@ public class ClientRegistrationsBeanDefinitionParserTests { assertThat(googleRegistration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.BASIC); assertThat(googleRegistration.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); assertThat(googleRegistration.getRedirectUri()).isEqualTo("{baseUrl}/login/oauth2/code/{registrationId}"); - assertThat(googleRegistration.getScopes()).isEqualTo(StringUtils.commaDelimitedListToSet("openid,profile,email")); + assertThat(googleRegistration.getScopes()) + .isEqualTo(StringUtils.commaDelimitedListToSet("openid,profile,email")); assertThat(googleRegistration.getClientName()).isEqualTo("Google"); ProviderDetails googleProviderDetails = googleRegistration.getProviderDetails(); @@ -206,7 +171,8 @@ public class ClientRegistrationsBeanDefinitionParserTests { assertThat(githubRegistration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.BASIC); assertThat(githubRegistration.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); assertThat(githubRegistration.getRedirectUri()).isEqualTo("{baseUrl}/login/oauth2/code/{registrationId}"); - assertThat(googleRegistration.getScopes()).isEqualTo(StringUtils.commaDelimitedListToSet("openid,profile,email")); + assertThat(googleRegistration.getScopes()) + .isEqualTo(StringUtils.commaDelimitedListToSet("openid,profile,email")); assertThat(githubRegistration.getClientName()).isEqualTo("Github"); ProviderDetails githubProviderDetails = githubRegistration.getProviderDetails(); @@ -220,12 +186,11 @@ public class ClientRegistrationsBeanDefinitionParserTests { } private static MockResponse jsonResponse(String json) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json); + return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } private static String xml(String configName) { return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; } + } diff --git a/config/src/test/java/org/springframework/security/config/oauth2/client/CommonOAuth2ProviderTests.java b/config/src/test/java/org/springframework/security/config/oauth2/client/CommonOAuth2ProviderTests.java index ad18946aca..d896bbe8b2 100644 --- a/config/src/test/java/org/springframework/security/config/oauth2/client/CommonOAuth2ProviderTests.java +++ b/config/src/test/java/org/springframework/security/config/oauth2/client/CommonOAuth2ProviderTests.java @@ -37,22 +37,15 @@ public class CommonOAuth2ProviderTests { public void getBuilderWhenGoogleShouldHaveGoogleSettings() { ClientRegistration registration = build(CommonOAuth2Provider.GOOGLE); ProviderDetails providerDetails = registration.getProviderDetails(); - assertThat(providerDetails.getAuthorizationUri()) - .isEqualTo("https://accounts.google.com/o/oauth2/v2/auth"); - assertThat(providerDetails.getTokenUri()) - .isEqualTo("https://www.googleapis.com/oauth2/v4/token"); + assertThat(providerDetails.getAuthorizationUri()).isEqualTo("https://accounts.google.com/o/oauth2/v2/auth"); + assertThat(providerDetails.getTokenUri()).isEqualTo("https://www.googleapis.com/oauth2/v4/token"); assertThat(providerDetails.getUserInfoEndpoint().getUri()) - .isEqualTo("https://www.googleapis.com/oauth2/v3/userinfo"); - assertThat(providerDetails.getUserInfoEndpoint().getUserNameAttributeName()) - .isEqualTo(IdTokenClaimNames.SUB); - assertThat(providerDetails.getJwkSetUri()) - .isEqualTo("https://www.googleapis.com/oauth2/v3/certs"); - assertThat(providerDetails.getIssuerUri()) - .isEqualTo("https://accounts.google.com"); - assertThat(registration.getClientAuthenticationMethod()) - .isEqualTo(ClientAuthenticationMethod.BASIC); - assertThat(registration.getAuthorizationGrantType()) - .isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); + .isEqualTo("https://www.googleapis.com/oauth2/v3/userinfo"); + assertThat(providerDetails.getUserInfoEndpoint().getUserNameAttributeName()).isEqualTo(IdTokenClaimNames.SUB); + assertThat(providerDetails.getJwkSetUri()).isEqualTo("https://www.googleapis.com/oauth2/v3/certs"); + assertThat(providerDetails.getIssuerUri()).isEqualTo("https://accounts.google.com"); + assertThat(registration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.BASIC); + assertThat(registration.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); assertThat(registration.getRedirectUri()).isEqualTo(DEFAULT_REDIRECT_URL); assertThat(registration.getScopes()).containsOnly("openid", "profile", "email"); assertThat(registration.getClientName()).isEqualTo("Google"); @@ -63,19 +56,13 @@ public class CommonOAuth2ProviderTests { public void getBuilderWhenGitHubShouldHaveGitHubSettings() { ClientRegistration registration = build(CommonOAuth2Provider.GITHUB); ProviderDetails providerDetails = registration.getProviderDetails(); - assertThat(providerDetails.getAuthorizationUri()) - .isEqualTo("https://github.com/login/oauth/authorize"); - assertThat(providerDetails.getTokenUri()) - .isEqualTo("https://github.com/login/oauth/access_token"); - assertThat(providerDetails.getUserInfoEndpoint().getUri()) - .isEqualTo("https://api.github.com/user"); - assertThat(providerDetails.getUserInfoEndpoint().getUserNameAttributeName()) - .isEqualTo("id"); + assertThat(providerDetails.getAuthorizationUri()).isEqualTo("https://github.com/login/oauth/authorize"); + assertThat(providerDetails.getTokenUri()).isEqualTo("https://github.com/login/oauth/access_token"); + assertThat(providerDetails.getUserInfoEndpoint().getUri()).isEqualTo("https://api.github.com/user"); + assertThat(providerDetails.getUserInfoEndpoint().getUserNameAttributeName()).isEqualTo("id"); assertThat(providerDetails.getJwkSetUri()).isNull(); - assertThat(registration.getClientAuthenticationMethod()) - .isEqualTo(ClientAuthenticationMethod.BASIC); - assertThat(registration.getAuthorizationGrantType()) - .isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); + assertThat(registration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.BASIC); + assertThat(registration.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); assertThat(registration.getRedirectUri()).isEqualTo(DEFAULT_REDIRECT_URL); assertThat(registration.getScopes()).containsOnly("read:user"); assertThat(registration.getClientName()).isEqualTo("GitHub"); @@ -86,19 +73,14 @@ public class CommonOAuth2ProviderTests { public void getBuilderWhenFacebookShouldHaveFacebookSettings() { ClientRegistration registration = build(CommonOAuth2Provider.FACEBOOK); ProviderDetails providerDetails = registration.getProviderDetails(); - assertThat(providerDetails.getAuthorizationUri()) - .isEqualTo("https://www.facebook.com/v2.8/dialog/oauth"); - assertThat(providerDetails.getTokenUri()) - .isEqualTo("https://graph.facebook.com/v2.8/oauth/access_token"); + assertThat(providerDetails.getAuthorizationUri()).isEqualTo("https://www.facebook.com/v2.8/dialog/oauth"); + assertThat(providerDetails.getTokenUri()).isEqualTo("https://graph.facebook.com/v2.8/oauth/access_token"); assertThat(providerDetails.getUserInfoEndpoint().getUri()) - .isEqualTo("https://graph.facebook.com/me?fields=id,name,email"); - assertThat(providerDetails.getUserInfoEndpoint().getUserNameAttributeName()) - .isEqualTo("id"); + .isEqualTo("https://graph.facebook.com/me?fields=id,name,email"); + assertThat(providerDetails.getUserInfoEndpoint().getUserNameAttributeName()).isEqualTo("id"); assertThat(providerDetails.getJwkSetUri()).isNull(); - assertThat(registration.getClientAuthenticationMethod()) - .isEqualTo(ClientAuthenticationMethod.POST); - assertThat(registration.getAuthorizationGrantType()) - .isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); + assertThat(registration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.POST); + assertThat(registration.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); assertThat(registration.getRedirectUri()).isEqualTo(DEFAULT_REDIRECT_URL); assertThat(registration.getScopes()).containsOnly("public_profile", "email"); assertThat(registration.getClientName()).isEqualTo("Facebook"); @@ -108,22 +90,16 @@ public class CommonOAuth2ProviderTests { @Test public void getBuilderWhenOktaShouldHaveOktaSettings() { ClientRegistration registration = builder(CommonOAuth2Provider.OKTA) - .authorizationUri("https://example.com/auth") - .tokenUri("https://example.com/token") - .userInfoUri("https://example.com/info") - .jwkSetUri("https://example.com/jwkset").build(); + .authorizationUri("https://example.com/auth").tokenUri("https://example.com/token") + .userInfoUri("https://example.com/info").jwkSetUri("https://example.com/jwkset").build(); ProviderDetails providerDetails = registration.getProviderDetails(); - assertThat(providerDetails.getAuthorizationUri()) - .isEqualTo("https://example.com/auth"); + assertThat(providerDetails.getAuthorizationUri()).isEqualTo("https://example.com/auth"); assertThat(providerDetails.getTokenUri()).isEqualTo("https://example.com/token"); assertThat(providerDetails.getUserInfoEndpoint().getUri()).isEqualTo("https://example.com/info"); - assertThat(providerDetails.getUserInfoEndpoint().getUserNameAttributeName()) - .isEqualTo(IdTokenClaimNames.SUB); + assertThat(providerDetails.getUserInfoEndpoint().getUserNameAttributeName()).isEqualTo(IdTokenClaimNames.SUB); assertThat(providerDetails.getJwkSetUri()).isEqualTo("https://example.com/jwkset"); - assertThat(registration.getClientAuthenticationMethod()) - .isEqualTo(ClientAuthenticationMethod.BASIC); - assertThat(registration.getAuthorizationGrantType()) - .isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); + assertThat(registration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.BASIC); + assertThat(registration.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); assertThat(registration.getRedirectUri()).isEqualTo(DEFAULT_REDIRECT_URL); assertThat(registration.getScopes()).containsOnly("openid", "profile", "email"); assertThat(registration.getClientName()).isEqualTo("Okta"); @@ -135,9 +111,7 @@ public class CommonOAuth2ProviderTests { } private ClientRegistration.Builder builder(CommonOAuth2Provider provider) { - return provider.getBuilder("123") - .clientId("abcd") - .clientSecret("secret"); + return provider.getBuilder("123").clientId("abcd").clientSecret("secret"); } } diff --git a/config/src/test/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBeanPropertiesResourceITests.java b/config/src/test/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBeanPropertiesResourceITests.java index 5548c5df46..818e469c66 100644 --- a/config/src/test/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBeanPropertiesResourceITests.java +++ b/config/src/test/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBeanPropertiesResourceITests.java @@ -16,7 +16,6 @@ package org.springframework.security.config.provisioning; - import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -34,6 +33,7 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; */ @RunWith(SpringRunner.class) public class UserDetailsManagerResourceFactoryBeanPropertiesResourceITests { + @Autowired UserDetailsManager users; @@ -44,9 +44,12 @@ public class UserDetailsManagerResourceFactoryBeanPropertiesResourceITests { @Configuration static class Config { + @Bean public UserDetailsManagerResourceFactoryBean userDetailsService() { return UserDetailsManagerResourceFactoryBean.fromResource(new InMemoryResource("user=password,ROLE_USER")); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBeanPropertiesResourceLocationITests.java b/config/src/test/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBeanPropertiesResourceLocationITests.java index 3c524961ce..a42b5638d1 100644 --- a/config/src/test/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBeanPropertiesResourceLocationITests.java +++ b/config/src/test/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBeanPropertiesResourceLocationITests.java @@ -16,7 +16,6 @@ package org.springframework.security.config.provisioning; - import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -33,6 +32,7 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; */ @RunWith(SpringRunner.class) public class UserDetailsManagerResourceFactoryBeanPropertiesResourceLocationITests { + @Autowired UserDetailsManager users; @@ -43,9 +43,12 @@ public class UserDetailsManagerResourceFactoryBeanPropertiesResourceLocationITes @Configuration static class Config { + @Bean public UserDetailsManagerResourceFactoryBean userDetailsService() { return UserDetailsManagerResourceFactoryBean.fromResourceLocation("classpath:users.properties"); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBeanStringITests.java b/config/src/test/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBeanStringITests.java index 1a3cab08f1..b7840124c0 100644 --- a/config/src/test/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBeanStringITests.java +++ b/config/src/test/java/org/springframework/security/config/provisioning/UserDetailsManagerResourceFactoryBeanStringITests.java @@ -16,7 +16,6 @@ package org.springframework.security.config.provisioning; - import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -33,6 +32,7 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; */ @RunWith(SpringRunner.class) public class UserDetailsManagerResourceFactoryBeanStringITests { + @Autowired UserDetailsManager users; @@ -43,9 +43,12 @@ public class UserDetailsManagerResourceFactoryBeanStringITests { @Configuration static class Config { + @Bean public UserDetailsManagerResourceFactoryBean userDetailsService() { return UserDetailsManagerResourceFactoryBean.fromString("user=password,ROLE_USER"); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/test/SpringTestContext.java b/config/src/test/java/org/springframework/security/config/test/SpringTestContext.java index 09d580acc7..9fab61c74e 100644 --- a/config/src/test/java/org/springframework/security/config/test/SpringTestContext.java +++ b/config/src/test/java/org/springframework/security/config/test/SpringTestContext.java @@ -48,6 +48,7 @@ import static org.springframework.security.test.web.servlet.setup.SecurityMockMv * @since 5.0 */ public class SpringTestContext implements Closeable { + private Object test; private ConfigurableWebApplicationContext context; @@ -62,7 +63,9 @@ public class SpringTestContext implements Closeable { public void close() { try { this.context.close(); - } catch(Exception e) {} + } + catch (Exception e) { + } } public SpringTestContext context(ConfigurableWebApplicationContext context) { @@ -79,8 +82,7 @@ public class SpringTestContext implements Closeable { public SpringTestContext testConfigLocations(String... configLocations) { GenericXmlWebContextLoader loader = new GenericXmlWebContextLoader(); - String[] locations = loader.processLocations(this.test.getClass(), - configLocations); + String[] locations = loader.processLocations(this.test.getClass(), configLocations); return configLocations(locations); } @@ -100,8 +102,8 @@ public class SpringTestContext implements Closeable { public SpringTestContext mockMvcAfterSpringSecurityOk() { return addFilter(new OncePerRequestFilter() { @Override - protected void doFilterInternal(HttpServletRequest request, - HttpServletResponse response, FilterChain filterChain) { + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain filterChain) { response.setStatus(HttpServletResponse.SC_OK); } }); @@ -127,11 +129,9 @@ public class SpringTestContext implements Closeable { this.context.refresh(); if (this.context.containsBean(SPRING_SECURITY_FILTER_CHAIN)) { - MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context) - .apply(springSecurity()) - .apply(new AddFilter()).build(); - this.context.getBeanFactory() - .registerResolvableDependency(MockMvc.class, mockMvc); + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).apply(springSecurity()) + .apply(new AddFilter()).build(); + this.context.getBeanFactory().registerResolvableDependency(MockMvc.class, mockMvc); } AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); @@ -140,10 +140,13 @@ public class SpringTestContext implements Closeable { } private class AddFilter implements MockMvcConfigurer { - public RequestPostProcessor beforeMockMvcCreated( - ConfigurableMockMvcBuilder builder, WebApplicationContext context) { + + public RequestPostProcessor beforeMockMvcCreated(ConfigurableMockMvcBuilder builder, + WebApplicationContext context) { builder.addFilters(SpringTestContext.this.filters.toArray(new Filter[0])); return null; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/test/SpringTestRule.java b/config/src/test/java/org/springframework/security/config/test/SpringTestRule.java index 192830f5b5..ae746dc5a3 100644 --- a/config/src/test/java/org/springframework/security/config/test/SpringTestRule.java +++ b/config/src/test/java/org/springframework/security/config/test/SpringTestRule.java @@ -26,19 +26,21 @@ import org.springframework.security.test.context.TestSecurityContextHolder; * @since 5.0 */ public class SpringTestRule extends SpringTestContext implements MethodRule { + @Override - public Statement apply(Statement base, FrameworkMethod method, - Object target) { + public Statement apply(Statement base, FrameworkMethod method, Object target) { return new Statement() { public void evaluate() throws Throwable { setTest(target); try { base.evaluate(); - } finally { + } + finally { TestSecurityContextHolder.clearContext(); close(); } } }; } + } diff --git a/config/src/test/java/org/springframework/security/config/users/AuthenticationTestConfiguration.java b/config/src/test/java/org/springframework/security/config/users/AuthenticationTestConfiguration.java index d00036b61f..c8960e2dc6 100644 --- a/config/src/test/java/org/springframework/security/config/users/AuthenticationTestConfiguration.java +++ b/config/src/test/java/org/springframework/security/config/users/AuthenticationTestConfiguration.java @@ -28,8 +28,10 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager; */ @Configuration public class AuthenticationTestConfiguration { + @Bean public static UserDetailsService userDetailsService() { return new InMemoryUserDetailsManager(PasswordEncodedUser.user(), PasswordEncodedUser.admin()); } + } diff --git a/config/src/test/java/org/springframework/security/config/users/ReactiveAuthenticationTestConfiguration.java b/config/src/test/java/org/springframework/security/config/users/ReactiveAuthenticationTestConfiguration.java index 27862b5294..c32addfc41 100644 --- a/config/src/test/java/org/springframework/security/config/users/ReactiveAuthenticationTestConfiguration.java +++ b/config/src/test/java/org/springframework/security/config/users/ReactiveAuthenticationTestConfiguration.java @@ -28,8 +28,10 @@ import org.springframework.security.core.userdetails.ReactiveUserDetailsService; */ @Configuration public class ReactiveAuthenticationTestConfiguration { + @Bean public static ReactiveUserDetailsService userDetailsService() { return new MapReactiveUserDetailsService(PasswordEncodedUser.user(), PasswordEncodedUser.admin()); } + } diff --git a/config/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java b/config/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java index ac7b485f75..bb324e3491 100644 --- a/config/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java +++ b/config/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java @@ -26,6 +26,7 @@ import org.springframework.security.util.InMemoryResource; * @author Eddú Meléndez */ public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext { + static final String BEANS_OPENING = "\n" + xml + BEANS_CLOSE; inMemoryXml = new InMemoryResource(fullXml); setAllowBeanDefinitionOverriding(true); @@ -75,4 +75,5 @@ public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext protected Resource[] getConfigResources() { return new Resource[] { inMemoryXml }; } + } diff --git a/config/src/test/java/org/springframework/security/config/util/InMemoryXmlWebApplicationContext.java b/config/src/test/java/org/springframework/security/config/util/InMemoryXmlWebApplicationContext.java index 96c8e758f1..affe2e9d50 100644 --- a/config/src/test/java/org/springframework/security/config/util/InMemoryXmlWebApplicationContext.java +++ b/config/src/test/java/org/springframework/security/config/util/InMemoryXmlWebApplicationContext.java @@ -31,6 +31,7 @@ import static org.springframework.security.config.util.InMemoryXmlApplicationCon * @author Joe Grandja */ public class InMemoryXmlWebApplicationContext extends AbstractRefreshableWebApplicationContext { + private Resource inMemoryXml; public InMemoryXmlWebApplicationContext(String xml) { @@ -41,8 +42,7 @@ public class InMemoryXmlWebApplicationContext extends AbstractRefreshableWebAppl this(xml, SPRING_SECURITY_VERSION, parent); } - public InMemoryXmlWebApplicationContext(String xml, String secVersion, - ApplicationContext parent) { + public InMemoryXmlWebApplicationContext(String xml, String secVersion, ApplicationContext parent) { String fullXml = BEANS_OPENING + secVersion + ".xsd'>\n" + xml + BEANS_CLOSE; inMemoryXml = new InMemoryResource(fullXml); setAllowBeanDefinitionOverriding(true); diff --git a/config/src/test/java/org/springframework/security/config/web/server/AuthorizeExchangeSpecTests.java b/config/src/test/java/org/springframework/security/config/web/server/AuthorizeExchangeSpecTests.java index d19e5e953f..99541aab43 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/AuthorizeExchangeSpecTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/AuthorizeExchangeSpecTests.java @@ -27,140 +27,81 @@ import org.springframework.test.web.reactive.server.WebTestClient; * @since 5.0 */ public class AuthorizeExchangeSpecTests { + ServerHttpSecurity http = ServerHttpSecurityConfigurationBuilder.httpWithDefaultAuthentication(); @Test public void antMatchersWhenMethodAndPatternsThenDiscriminatesByMethod() { - this.http - .csrf().disable() - .authorizeExchange() - .pathMatchers(HttpMethod.POST, "/a", "/b").denyAll() - .anyExchange().permitAll(); + this.http.csrf().disable().authorizeExchange().pathMatchers(HttpMethod.POST, "/a", "/b").denyAll().anyExchange() + .permitAll(); WebTestClient client = buildClient(); - client.get() - .uri("/a") - .exchange() - .expectStatus().isOk(); + client.get().uri("/a").exchange().expectStatus().isOk(); - client.get() - .uri("/b") - .exchange() - .expectStatus().isOk(); + client.get().uri("/b").exchange().expectStatus().isOk(); - client.post() - .uri("/a") - .exchange() - .expectStatus().isUnauthorized(); + client.post().uri("/a").exchange().expectStatus().isUnauthorized(); - client.post() - .uri("/b") - .exchange() - .expectStatus().isUnauthorized(); + client.post().uri("/b").exchange().expectStatus().isUnauthorized(); } - @Test public void antMatchersWhenPatternsThenAnyMethod() { - this.http - .csrf().disable() - .authorizeExchange() - .pathMatchers("/a", "/b").denyAll() - .anyExchange().permitAll(); + this.http.csrf().disable().authorizeExchange().pathMatchers("/a", "/b").denyAll().anyExchange().permitAll(); WebTestClient client = buildClient(); - client.get() - .uri("/a") - .exchange() - .expectStatus().isUnauthorized(); + client.get().uri("/a").exchange().expectStatus().isUnauthorized(); - client.get() - .uri("/b") - .exchange() - .expectStatus().isUnauthorized(); + client.get().uri("/b").exchange().expectStatus().isUnauthorized(); - client.post() - .uri("/a") - .exchange() - .expectStatus().isUnauthorized(); + client.post().uri("/a").exchange().expectStatus().isUnauthorized(); - client.post() - .uri("/b") - .exchange() - .expectStatus().isUnauthorized(); + client.post().uri("/b").exchange().expectStatus().isUnauthorized(); } @Test public void antMatchersWhenPatternsInLambdaThenAnyMethod() { - this.http - .csrf(ServerHttpSecurity.CsrfSpec::disable) - .authorizeExchange(exchanges -> - exchanges - .pathMatchers("/a", "/b").denyAll() - .anyExchange().permitAll() - ); + this.http.csrf(ServerHttpSecurity.CsrfSpec::disable) + .authorizeExchange(exchanges -> exchanges.pathMatchers("/a", "/b").denyAll().anyExchange().permitAll()); WebTestClient client = buildClient(); - client.get() - .uri("/a") - .exchange() - .expectStatus().isUnauthorized(); + client.get().uri("/a").exchange().expectStatus().isUnauthorized(); - client.get() - .uri("/b") - .exchange() - .expectStatus().isUnauthorized(); + client.get().uri("/b").exchange().expectStatus().isUnauthorized(); - client.post() - .uri("/a") - .exchange() - .expectStatus().isUnauthorized(); + client.post().uri("/a").exchange().expectStatus().isUnauthorized(); - client.post() - .uri("/b") - .exchange() - .expectStatus().isUnauthorized(); + client.post().uri("/b").exchange().expectStatus().isUnauthorized(); } @Test(expected = IllegalStateException.class) public void antMatchersWhenNoAccessAndAnotherMatcherThenThrowsException() { - this.http - .authorizeExchange() - .pathMatchers("/incomplete"); - this.http - .authorizeExchange() - .pathMatchers("/throws-exception"); + this.http.authorizeExchange().pathMatchers("/incomplete"); + this.http.authorizeExchange().pathMatchers("/throws-exception"); } @Test(expected = IllegalStateException.class) public void anyExchangeWhenFollowedByMatcherThenThrowsException() { - this.http - .authorizeExchange().anyExchange().denyAll() - .pathMatchers("/never-reached"); + this.http.authorizeExchange().anyExchange().denyAll().pathMatchers("/never-reached"); } @Test(expected = IllegalStateException.class) public void buildWhenMatcherDefinedWithNoAccessThenThrowsException() { - this.http - .authorizeExchange() - .pathMatchers("/incomplete"); + this.http.authorizeExchange().pathMatchers("/incomplete"); this.http.build(); } @Test(expected = IllegalStateException.class) public void buildWhenMatcherDefinedWithNoAccessInLambdaThenThrowsException() { - this.http - .authorizeExchange(exchanges -> - exchanges - .pathMatchers("/incomplete") - ); + this.http.authorizeExchange(exchanges -> exchanges.pathMatchers("/incomplete")); this.http.build(); } private WebTestClient buildClient() { return WebTestClientBuilder.bindToWebFilters(this.http.build()).build(); } + } diff --git a/config/src/test/java/org/springframework/security/config/web/server/CorsSpecTests.java b/config/src/test/java/org/springframework/security/config/web/server/CorsSpecTests.java index 9cac1da459..d41c7679ff 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/CorsSpecTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/CorsSpecTests.java @@ -46,8 +46,10 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class CorsSpecTests { + @Mock private CorsConfigurationSource source; + @Mock private ApplicationContext context; @@ -59,8 +61,7 @@ public class CorsSpecTests { @Before public void setup() { - this.http = new TestingServerHttpSecurity() - .applicationContext(this.context); + this.http = new TestingServerHttpSecurity().applicationContext(this.context); CorsConfiguration value = new CorsConfiguration(); value.setAllowedOrigins(Arrays.asList("*")); when(this.source.getCorsConfiguration(any())).thenReturn(value); @@ -84,7 +85,8 @@ public class CorsSpecTests { @Test public void corsWhenCorsConfigurationSourceBeanThenAccessControlAllowOriginAndSecurityHeaders() { - when(this.context.getBeanNamesForType(any(ResolvableType.class))).thenReturn(new String[] {"source"}, new String[0]); + when(this.context.getBeanNamesForType(any(ResolvableType.class))).thenReturn(new String[] { "source" }, + new String[0]); when(this.context.getBean("source")).thenReturn(this.source); this.expectedHeaders.set("Access-Control-Allow-Origin", "*"); this.expectedHeaders.set("X-Frame-Options", "DENY"); @@ -100,17 +102,13 @@ public class CorsSpecTests { private void assertHeaders() { WebTestClient client = buildClient(); - FluxExchangeResult response = client.get() - .uri("https://example.com/") - .headers(h -> h.setOrigin("https://origin.example.com")) - .exchange() - .returnResult(String.class); + FluxExchangeResult response = client.get().uri("https://example.com/") + .headers(h -> h.setOrigin("https://origin.example.com")).exchange().returnResult(String.class); Map> responseHeaders = response.getResponseHeaders(); if (!this.expectedHeaders.isEmpty()) { - assertThat(responseHeaders).describedAs(response.toString()) - .containsAllEntriesOf(this.expectedHeaders); + assertThat(responseHeaders).describedAs(response.toString()).containsAllEntriesOf(this.expectedHeaders); } if (!this.headerNamesNotPresent.isEmpty()) { assertThat(responseHeaders.keySet()).doesNotContainAnyElementsOf(this.headerNamesNotPresent); @@ -118,8 +116,7 @@ public class CorsSpecTests { } private WebTestClient buildClient() { - return WebTestClientBuilder - .bindToWebFilters(this.http.build()) - .build(); + return WebTestClientBuilder.bindToWebFilters(this.http.build()).build(); } + } diff --git a/config/src/test/java/org/springframework/security/config/web/server/ExceptionHandlingSpecTests.java b/config/src/test/java/org/springframework/security/config/web/server/ExceptionHandlingSpecTests.java index beae57c576..c4bf90d8c2 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/ExceptionHandlingSpecTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/ExceptionHandlingSpecTests.java @@ -33,197 +33,102 @@ import static org.springframework.security.config.Customizer.withDefaults; * @since 5.0.5 */ public class ExceptionHandlingSpecTests { + private ServerHttpSecurity http = ServerHttpSecurityConfigurationBuilder.httpWithDefaultAuthentication(); @Test public void defaultAuthenticationEntryPoint() { - SecurityWebFilterChain securityWebFilter = this.http - .csrf().disable() - .authorizeExchange() - .anyExchange().authenticated() - .and() - .exceptionHandling() - .and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.csrf().disable().authorizeExchange().anyExchange() + .authenticated().and().exceptionHandling().and().build(); - WebTestClient client = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient client = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - client - .get() - .uri("/test") - .exchange() - .expectStatus().isUnauthorized() - .expectHeader().valueMatches("WWW-Authenticate", "Basic.*"); + client.get().uri("/test").exchange().expectStatus().isUnauthorized().expectHeader() + .valueMatches("WWW-Authenticate", "Basic.*"); } @Test public void requestWhenExceptionHandlingWithDefaultsInLambdaThenDefaultAuthenticationEntryPointUsed() { SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange(exchanges -> - exchanges - .anyExchange().authenticated() - ) - .exceptionHandling(withDefaults()) - .build(); + .authorizeExchange(exchanges -> exchanges.anyExchange().authenticated()) + .exceptionHandling(withDefaults()).build(); - WebTestClient client = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient client = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - client - .get() - .uri("/test") - .exchange() - .expectStatus().isUnauthorized() - .expectHeader().valueMatches("WWW-Authenticate", "Basic.*"); + client.get().uri("/test").exchange().expectStatus().isUnauthorized().expectHeader() + .valueMatches("WWW-Authenticate", "Basic.*"); } @Test public void customAuthenticationEntryPoint() { - SecurityWebFilterChain securityWebFilter = this.http - .csrf().disable() - .authorizeExchange() - .anyExchange().authenticated() - .and() - .exceptionHandling() - .authenticationEntryPoint(redirectServerAuthenticationEntryPoint("/auth")) - .and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.csrf().disable().authorizeExchange().anyExchange() + .authenticated().and().exceptionHandling() + .authenticationEntryPoint(redirectServerAuthenticationEntryPoint("/auth")).and().build(); - WebTestClient client = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient client = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - client - .get() - .uri("/test") - .exchange() - .expectStatus().isFound() - .expectHeader().valueMatches("Location", ".*"); + client.get().uri("/test").exchange().expectStatus().isFound().expectHeader().valueMatches("Location", ".*"); } @Test public void requestWhenCustomAuthenticationEntryPointInLambdaThenCustomAuthenticationEntryPointUsed() { SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange(exchanges -> - exchanges - .anyExchange().authenticated() - ) - .exceptionHandling(exceptionHandling -> - exceptionHandling - .authenticationEntryPoint(redirectServerAuthenticationEntryPoint("/auth")) - ) + .authorizeExchange(exchanges -> exchanges.anyExchange().authenticated()) + .exceptionHandling(exceptionHandling -> exceptionHandling + .authenticationEntryPoint(redirectServerAuthenticationEntryPoint("/auth"))) .build(); - WebTestClient client = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient client = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - client - .get() - .uri("/test") - .exchange() - .expectStatus().isFound() - .expectHeader().valueMatches("Location", ".*"); + client.get().uri("/test").exchange().expectStatus().isFound().expectHeader().valueMatches("Location", ".*"); } @Test public void defaultAccessDeniedHandler() { - SecurityWebFilterChain securityWebFilter = this.http - .csrf().disable() - .httpBasic().and() - .authorizeExchange() - .anyExchange().hasRole("ADMIN") - .and() - .exceptionHandling() - .and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.csrf().disable().httpBasic().and().authorizeExchange() + .anyExchange().hasRole("ADMIN").and().exceptionHandling().and().build(); - WebTestClient client = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient client = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - client - .get() - .uri("/admin") - .headers(headers -> headers.setBasicAuth("user", "password")) - .exchange() - .expectStatus().isForbidden(); + client.get().uri("/admin").headers(headers -> headers.setBasicAuth("user", "password")).exchange() + .expectStatus().isForbidden(); } @Test public void requestWhenExceptionHandlingWithDefaultsInLambdaThenDefaultAccessDeniedHandlerUsed() { - SecurityWebFilterChain securityWebFilter = this.http - .httpBasic(withDefaults()) - .authorizeExchange(exchanges -> - exchanges - .anyExchange().hasRole("ADMIN") - ) - .exceptionHandling(withDefaults()) - .build(); + SecurityWebFilterChain securityWebFilter = this.http.httpBasic(withDefaults()) + .authorizeExchange(exchanges -> exchanges.anyExchange().hasRole("ADMIN")) + .exceptionHandling(withDefaults()).build(); - WebTestClient client = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient client = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - client - .get() - .uri("/admin") - .headers(headers -> headers.setBasicAuth("user", "password")) - .exchange() + client.get().uri("/admin").headers(headers -> headers.setBasicAuth("user", "password")).exchange() .expectStatus().isForbidden(); } @Test public void customAccessDeniedHandler() { - SecurityWebFilterChain securityWebFilter = this.http - .csrf().disable() - .httpBasic().and() - .authorizeExchange() - .anyExchange().hasRole("ADMIN") - .and() - .exceptionHandling() - .accessDeniedHandler(httpStatusServerAccessDeniedHandler(HttpStatus.BAD_REQUEST)) - .and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.csrf().disable().httpBasic().and().authorizeExchange() + .anyExchange().hasRole("ADMIN").and().exceptionHandling() + .accessDeniedHandler(httpStatusServerAccessDeniedHandler(HttpStatus.BAD_REQUEST)).and().build(); - WebTestClient client = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient client = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - client - .get() - .uri("/admin") - .headers(headers -> headers.setBasicAuth("user", "password")) - .exchange() - .expectStatus().isBadRequest(); + client.get().uri("/admin").headers(headers -> headers.setBasicAuth("user", "password")).exchange() + .expectStatus().isBadRequest(); } @Test public void requestWhenCustomAccessDeniedHandlerInLambdaThenCustomAccessDeniedHandlerUsed() { - SecurityWebFilterChain securityWebFilter = this.http - .httpBasic(withDefaults()) - .authorizeExchange(exchanges -> - exchanges - .anyExchange().hasRole("ADMIN") - ) - .exceptionHandling(exceptionHandling -> - exceptionHandling - .accessDeniedHandler(httpStatusServerAccessDeniedHandler(HttpStatus.BAD_REQUEST)) - ) + SecurityWebFilterChain securityWebFilter = this.http.httpBasic(withDefaults()) + .authorizeExchange(exchanges -> exchanges.anyExchange().hasRole("ADMIN")) + .exceptionHandling(exceptionHandling -> exceptionHandling + .accessDeniedHandler(httpStatusServerAccessDeniedHandler(HttpStatus.BAD_REQUEST))) .build(); - WebTestClient client = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient client = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - client - .get() - .uri("/admin") - .headers(headers -> headers.setBasicAuth("user", "password")) - .exchange() + client.get().uri("/admin").headers(headers -> headers.setBasicAuth("user", "password")).exchange() .expectStatus().isBadRequest(); } @@ -234,4 +139,5 @@ public class ExceptionHandlingSpecTests { private ServerAccessDeniedHandler httpStatusServerAccessDeniedHandler(HttpStatus httpStatus) { return new HttpStatusServerAccessDeniedHandler(httpStatus); } + } diff --git a/config/src/test/java/org/springframework/security/config/web/server/FormLoginTests.java b/config/src/test/java/org/springframework/security/config/web/server/FormLoginTests.java index c0f1ff8938..29684c9bff 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/FormLoginTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/FormLoginTests.java @@ -62,121 +62,70 @@ import static org.springframework.security.config.Customizer.withDefaults; * @since 5.0 */ public class FormLoginTests { + private ServerHttpSecurity http = ServerHttpSecurityConfigurationBuilder.httpWithDefaultAuthentication(); @Test public void defaultLoginPage() { - SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange() - .anyExchange().authenticated() - .and() - .formLogin().and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.authorizeExchange().anyExchange().authenticated().and() + .formLogin().and().build(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - DefaultLoginPage loginPage = HomePage.to(driver, DefaultLoginPage.class) - .assertAt(); + DefaultLoginPage loginPage = HomePage.to(driver, DefaultLoginPage.class).assertAt(); - loginPage = loginPage.loginForm() - .username("user") - .password("invalid") - .submit(DefaultLoginPage.class) - .assertError(); + loginPage = loginPage.loginForm().username("user").password("invalid").submit(DefaultLoginPage.class) + .assertError(); - HomePage homePage = loginPage.loginForm() - .username("user") - .password("password") - .submit(HomePage.class); + HomePage homePage = loginPage.loginForm().username("user").password("password").submit(HomePage.class); homePage.assertAt(); - loginPage = DefaultLogoutPage.to(driver) - .assertAt() - .logout(); + loginPage = DefaultLogoutPage.to(driver).assertAt().logout(); - loginPage - .assertAt() - .assertLogout(); + loginPage.assertAt().assertLogout(); } @Test public void formLoginWhenDefaultsInLambdaThenCreatesDefaultLoginPage() { SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange(exchanges -> - exchanges - .anyExchange().authenticated() - ) - .formLogin(withDefaults()) - .build(); + .authorizeExchange(exchanges -> exchanges.anyExchange().authenticated()).formLogin(withDefaults()) + .build(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - DefaultLoginPage loginPage = HomePage.to(driver, DefaultLoginPage.class) - .assertAt(); + DefaultLoginPage loginPage = HomePage.to(driver, DefaultLoginPage.class).assertAt(); - loginPage = loginPage.loginForm() - .username("user") - .password("invalid") - .submit(DefaultLoginPage.class) - .assertError(); + loginPage = loginPage.loginForm().username("user").password("invalid").submit(DefaultLoginPage.class) + .assertError(); - HomePage homePage = loginPage.loginForm() - .username("user") - .password("password") - .submit(HomePage.class); + HomePage homePage = loginPage.loginForm().username("user").password("password").submit(HomePage.class); homePage.assertAt(); - loginPage = DefaultLogoutPage.to(driver) - .assertAt() - .logout(); + loginPage = DefaultLogoutPage.to(driver).assertAt().logout(); - loginPage - .assertAt() - .assertLogout(); + loginPage.assertAt().assertLogout(); } @Test public void customLoginPage() { - SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange() - .pathMatchers("/login").permitAll() - .anyExchange().authenticated() - .and() - .formLogin() - .loginPage("/login") - .and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.authorizeExchange().pathMatchers("/login").permitAll() + .anyExchange().authenticated().and().formLogin().loginPage("/login").and().build(); WebTestClient webTestClient = WebTestClient - .bindToController(new CustomLoginPageController(), new WebTestClientBuilder.Http200RestController()) - .webFilter(new WebFilterChainProxy(securityWebFilter)) - .build(); + .bindToController(new CustomLoginPageController(), new WebTestClientBuilder.Http200RestController()) + .webFilter(new WebFilterChainProxy(securityWebFilter)).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - CustomLoginPage loginPage = HomePage.to(driver, CustomLoginPage.class) - .assertAt(); + CustomLoginPage loginPage = HomePage.to(driver, CustomLoginPage.class).assertAt(); - HomePage homePage = loginPage.loginForm() - .username("user") - .password("password") - .submit(HomePage.class); + HomePage homePage = loginPage.loginForm().username("user").password("password").submit(HomePage.class); homePage.assertAt(); } @@ -184,87 +133,49 @@ public class FormLoginTests { @Test public void formLoginWhenCustomLoginPageInLambdaThenUsed() { SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange(exchanges -> - exchanges - .pathMatchers("/login").permitAll() - .anyExchange().authenticated() - ) - .formLogin(formLogin -> - formLogin - .loginPage("/login") - ) - .build(); + .authorizeExchange( + exchanges -> exchanges.pathMatchers("/login").permitAll().anyExchange().authenticated()) + .formLogin(formLogin -> formLogin.loginPage("/login")).build(); WebTestClient webTestClient = WebTestClient - .bindToController(new CustomLoginPageController(), new WebTestClientBuilder.Http200RestController()) - .webFilter(new WebFilterChainProxy(securityWebFilter)) - .build(); + .bindToController(new CustomLoginPageController(), new WebTestClientBuilder.Http200RestController()) + .webFilter(new WebFilterChainProxy(securityWebFilter)).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - CustomLoginPage loginPage = HomePage.to(driver, CustomLoginPage.class) - .assertAt(); + CustomLoginPage loginPage = HomePage.to(driver, CustomLoginPage.class).assertAt(); - HomePage homePage = loginPage.loginForm() - .username("user") - .password("password") - .submit(HomePage.class); + HomePage homePage = loginPage.loginForm().username("user").password("password").submit(HomePage.class); homePage.assertAt(); } @Test public void formLoginWhenCustomAuthenticationFailureHandlerThenUsed() { - SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange() - .pathMatchers("/login", "/failure").permitAll() - .anyExchange().authenticated() - .and() - .formLogin() - .authenticationFailureHandler(new RedirectServerAuthenticationFailureHandler("/failure")) - .and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.authorizeExchange().pathMatchers("/login", "/failure") + .permitAll().anyExchange().authenticated().and().formLogin() + .authenticationFailureHandler(new RedirectServerAuthenticationFailureHandler("/failure")).and().build(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - DefaultLoginPage loginPage = HomePage.to(driver, DefaultLoginPage.class) - .assertAt(); + DefaultLoginPage loginPage = HomePage.to(driver, DefaultLoginPage.class).assertAt(); - loginPage.loginForm() - .username("invalid") - .password("invalid") - .submit(HomePage.class); + loginPage.loginForm().username("invalid").password("invalid").submit(HomePage.class); assertThat(driver.getCurrentUrl()).endsWith("/failure"); } @Test public void formLoginWhenCustomRequiresAuthenticationMatcherThenUsed() { - SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange() - .pathMatchers("/login", "/sign-in").permitAll() - .anyExchange().authenticated() - .and() - .formLogin() - .requiresAuthenticationMatcher(new PathPatternParserServerWebExchangeMatcher("/sign-in")) - .and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.authorizeExchange().pathMatchers("/login", "/sign-in") + .permitAll().anyExchange().authenticated().and().formLogin() + .requiresAuthenticationMatcher(new PathPatternParserServerWebExchangeMatcher("/sign-in")).and().build(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); driver.get("http://localhost/sign-in"); @@ -273,30 +184,17 @@ public class FormLoginTests { @Test public void authenticationSuccess() { - SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange() - .anyExchange().authenticated() - .and() - .formLogin() - .authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("/custom")) - .and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.authorizeExchange().anyExchange().authenticated().and() + .formLogin().authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("/custom")) + .and().build(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - DefaultLoginPage loginPage = DefaultLoginPage.to(driver) - .assertAt(); + DefaultLoginPage loginPage = DefaultLoginPage.to(driver).assertAt(); - HomePage homePage = loginPage.loginForm() - .username("user") - .password("password") - .submit(HomePage.class); + HomePage homePage = loginPage.loginForm().username("user").password("password").submit(HomePage.class); assertThat(driver.getCurrentUrl()).endsWith("/custom"); } @@ -306,31 +204,21 @@ public class FormLoginTests { ReactiveAuthenticationManager defaultAuthenticationManager = mock(ReactiveAuthenticationManager.class); ReactiveAuthenticationManager customAuthenticationManager = mock(ReactiveAuthenticationManager.class); - given(defaultAuthenticationManager.authenticate(any())).willThrow(new RuntimeException("should not interact with default auth manager")); - given(customAuthenticationManager.authenticate(any())).willReturn(Mono.just(new TestingAuthenticationToken("user", "password", "ROLE_USER", "ROLE_ADMIN"))); + given(defaultAuthenticationManager.authenticate(any())) + .willThrow(new RuntimeException("should not interact with default auth manager")); + given(customAuthenticationManager.authenticate(any())) + .willReturn(Mono.just(new TestingAuthenticationToken("user", "password", "ROLE_USER", "ROLE_ADMIN"))); - SecurityWebFilterChain securityWebFilter = this.http - .authenticationManager(defaultAuthenticationManager) - .formLogin() - .authenticationManager(customAuthenticationManager) - .and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.authenticationManager(defaultAuthenticationManager) + .formLogin().authenticationManager(customAuthenticationManager).and().build(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - DefaultLoginPage loginPage = DefaultLoginPage.to(driver) - .assertAt(); + DefaultLoginPage loginPage = DefaultLoginPage.to(driver).assertAt(); - HomePage homePage = loginPage.loginForm() - .username("user") - .password("password") - .submit(HomePage.class); + HomePage homePage = loginPage.loginForm().username("user").password("password").submit(HomePage.class); homePage.assertAt(); @@ -349,31 +237,17 @@ public class FormLoginTests { given(formLoginSecContextRepository.save(any(), any())).willReturn(Mono.empty()); given(formLoginSecContextRepository.load(any())).willReturn(authentication(token)); - SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange() - .anyExchange().authenticated() - .and() - .securityContextRepository(defaultSecContextRepository) - .formLogin() - .securityContextRepository(formLoginSecContextRepository) - .and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.authorizeExchange().anyExchange().authenticated().and() + .securityContextRepository(defaultSecContextRepository).formLogin() + .securityContextRepository(formLoginSecContextRepository).and().build(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - DefaultLoginPage loginPage = DefaultLoginPage.to(driver) - .assertAt(); + DefaultLoginPage loginPage = DefaultLoginPage.to(driver).assertAt(); - HomePage homePage = loginPage.loginForm() - .username("user") - .password("password") - .submit(HomePage.class); + HomePage homePage = loginPage.loginForm().username("user").password("password").submit(HomePage.class); homePage.assertAt(); @@ -402,9 +276,13 @@ public class FormLoginTests { } public static class LoginForm { + private WebDriver driver; + private WebElement username; + private WebElement password; + @FindBy(css = "button[type=submit]") private WebElement submit; @@ -426,12 +304,15 @@ public class FormLoginTests { this.submit.click(); return PageFactory.initElements(this.driver, page); } + } + } public static class DefaultLoginPage { private WebDriver driver; + @FindBy(css = "div[role=alert]") private WebElement alert; @@ -463,8 +344,7 @@ public class FormLoginTests { } public DefaultLoginPage assertLoginFormNotPresent() { - assertThatThrownBy(() -> loginForm().username("")) - .isInstanceOf(NoSuchElementException.class); + assertThatThrownBy(() -> loginForm().username("")).isInstanceOf(NoSuchElementException.class); return this; } @@ -485,9 +365,13 @@ public class FormLoginTests { } public static class LoginForm { + private WebDriver driver; + private WebElement username; + private WebElement password; + @FindBy(css = "button[type=submit]") private WebElement submit; @@ -509,28 +393,32 @@ public class FormLoginTests { this.submit.click(); return PageFactory.initElements(this.driver, page); } + } public class OAuth2Login { + public WebElement findClientRegistrationByName(String clientName) { return DefaultLoginPage.this.driver.findElement(By.linkText(clientName)); } public OAuth2Login assertClientRegistrationByName(String clientName) { - assertThatCode(() -> findClientRegistrationByName(clientName)) - .doesNotThrowAnyException(); + assertThatCode(() -> findClientRegistrationByName(clientName)).doesNotThrowAnyException(); return this; } public DefaultLoginPage and() { return DefaultLoginPage.this; } + } + } public static class DefaultLogoutPage { private WebDriver driver; + @FindBy(css = "button[type=submit]") private WebElement submit; @@ -554,7 +442,9 @@ public class FormLoginTests { } } + public static class HomePage { + private WebDriver driver; @FindBy(tagName = "body") @@ -572,43 +462,32 @@ public class FormLoginTests { driver.get("http://localhost/"); return PageFactory.initElements(driver, page); } + } @Controller public static class CustomLoginPageController { + @ResponseBody @GetMapping("/login") public Mono login(ServerWebExchange exchange) { Mono token = exchange.getAttributeOrDefault(CsrfToken.class.getName(), Mono.empty()); - return token.map(t -> - "\n" - + "\n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " Custom Log In Page\n" - + " \n" - + " \n" - + "
    \n" - + "
    \n" - + "

    Please sign in

    \n" - + "

    \n" - + " \n" - + " \n" - + "

    \n" - + "

    \n" - + " \n" - + " \n" - + "

    \n" - + " \n" - + " \n" - + "
    \n" - + "
    \n" - + " \n" - + ""); + return token.map(t -> "\n" + "\n" + " \n" + + " \n" + + " \n" + + " \n" + " \n" + + " Custom Log In Page\n" + " \n" + " \n" + "
    \n" + + "
    \n" + "

    Please sign in

    \n" + + "

    \n" + " \n" + + " \n" + + "

    \n" + "

    \n" + + " \n" + + " \n" + + "

    \n" + " \n" + " \n" + "
    \n" + + "
    \n" + " \n" + ""); } + } Mono authentication(Authentication authentication) { @@ -616,4 +495,5 @@ public class FormLoginTests { context.setAuthentication(authentication); return Mono.just(context); } + } diff --git a/config/src/test/java/org/springframework/security/config/web/server/HeaderSpecTests.java b/config/src/test/java/org/springframework/security/config/web/server/HeaderSpecTests.java index ea16551349..5d113d3af8 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/HeaderSpecTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/HeaderSpecTests.java @@ -51,7 +51,9 @@ import static org.springframework.security.config.Customizer.withDefaults; * @since 5.0 */ public class HeaderSpecTests { + private final static String CUSTOM_HEADER = "CUSTOM-HEADER"; + private final static String CUSTOM_VALUE = "CUSTOM-VALUE"; private ServerHttpSecurity http = ServerHttpSecurity.http(); @@ -62,15 +64,14 @@ public class HeaderSpecTests { @Before public void setup() { - this.expectedHeaders.add(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains"); + this.expectedHeaders.add(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY, + "max-age=31536000 ; includeSubDomains"); this.expectedHeaders.add(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate"); this.expectedHeaders.add(HttpHeaders.PRAGMA, "no-cache"); this.expectedHeaders.add(HttpHeaders.EXPIRES, "0"); - this.expectedHeaders - .add(ContentTypeOptionsServerHttpHeadersWriter.X_CONTENT_OPTIONS, "nosniff"); + this.expectedHeaders.add(ContentTypeOptionsServerHttpHeadersWriter.X_CONTENT_OPTIONS, "nosniff"); this.expectedHeaders.add(XFrameOptionsServerHttpHeadersWriter.X_FRAME_OPTIONS, "DENY"); - this.expectedHeaders - .add(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1 ; mode=block"); + this.expectedHeaders.add(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1 ; mode=block"); } @Test @@ -93,8 +94,7 @@ public class HeaderSpecTests { @Test public void headersWhenDisableAndInvokedExplicitlyThenDefautsUsed() { - this.http.headers().disable() - .headers(); + this.http.headers().disable().headers(); assertHeaders(); } @@ -121,14 +121,10 @@ public class HeaderSpecTests { assertHeaders(); } - @Test public void headersWhenCacheDisableInLambdaThenCacheNotWritten() { expectHeaderNamesNotPresent(HttpHeaders.CACHE_CONTROL, HttpHeaders.PRAGMA, HttpHeaders.EXPIRES); - this.http - .headers(headers -> - headers.cache(cache -> cache.disable()) - ); + this.http.headers(headers -> headers.cache(cache -> cache.disable())); assertHeaders(); } @@ -144,10 +140,7 @@ public class HeaderSpecTests { @Test public void headersWhenContentOptionsDisableInLambdaThenContentTypeOptionsNotWritten() { expectHeaderNamesNotPresent(ContentTypeOptionsServerHttpHeadersWriter.X_CONTENT_OPTIONS); - this.http - .headers(headers -> - headers.contentTypeOptions(contentTypeOptions -> contentTypeOptions.disable()) - ); + this.http.headers(headers -> headers.contentTypeOptions(contentTypeOptions -> contentTypeOptions.disable())); assertHeaders(); } @@ -163,10 +156,7 @@ public class HeaderSpecTests { @Test public void headersWhenHstsDisableInLambdaThenHstsNotWritten() { expectHeaderNamesNotPresent(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY); - this.http - .headers(headers -> - headers.hsts(hsts -> hsts.disable()) - ); + this.http.headers(headers -> headers.hsts(hsts -> hsts.disable())); assertHeaders(); } @@ -174,10 +164,9 @@ public class HeaderSpecTests { @Test public void headersWhenHstsCustomThenCustomHstsWritten() { this.expectedHeaders.remove(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY); - this.expectedHeaders.add(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY, "max-age=60"); - this.http.headers().hsts() - .maxAge(Duration.ofSeconds(60)) - .includeSubdomains(false); + this.expectedHeaders.add(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY, + "max-age=60"); + this.http.headers().hsts().maxAge(Duration.ofSeconds(60)).includeSubdomains(false); assertHeaders(); } @@ -185,16 +174,10 @@ public class HeaderSpecTests { @Test public void headersWhenHstsCustomInLambdaThenCustomHstsWritten() { this.expectedHeaders.remove(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY); - this.expectedHeaders.add(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY, "max-age=60"); + this.expectedHeaders.add(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY, + "max-age=60"); this.http - .headers(headers -> - headers - .hsts(hsts -> - hsts - .maxAge(Duration.ofSeconds(60)) - .includeSubdomains(false) - ) - ); + .headers(headers -> headers.hsts(hsts -> hsts.maxAge(Duration.ofSeconds(60)).includeSubdomains(false))); assertHeaders(); } @@ -202,10 +185,9 @@ public class HeaderSpecTests { @Test public void headersWhenHstsCustomWithPreloadThenCustomHstsWritten() { this.expectedHeaders.remove(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY); - this.expectedHeaders.add(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY, "max-age=60 ; includeSubDomains ; preload"); - this.http.headers().hsts() - .maxAge(Duration.ofSeconds(60)) - .preload(true); + this.expectedHeaders.add(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY, + "max-age=60 ; includeSubDomains ; preload"); + this.http.headers().hsts().maxAge(Duration.ofSeconds(60)).preload(true); assertHeaders(); } @@ -213,16 +195,9 @@ public class HeaderSpecTests { @Test public void headersWhenHstsCustomWithPreloadInLambdaThenCustomHstsWritten() { this.expectedHeaders.remove(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY); - this.expectedHeaders.add(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY, "max-age=60 ; includeSubDomains ; preload"); - this.http - .headers(headers -> - headers - .hsts(hsts -> - hsts - .maxAge(Duration.ofSeconds(60)) - .preload(true) - ) - ); + this.expectedHeaders.add(StrictTransportSecurityServerHttpHeadersWriter.STRICT_TRANSPORT_SECURITY, + "max-age=60 ; includeSubDomains ; preload"); + this.http.headers(headers -> headers.hsts(hsts -> hsts.maxAge(Duration.ofSeconds(60)).preload(true))); assertHeaders(); } @@ -238,10 +213,7 @@ public class HeaderSpecTests { @Test public void headersWhenFrameOptionsDisableInLambdaThenFrameOptionsNotWritten() { expectHeaderNamesNotPresent(XFrameOptionsServerHttpHeadersWriter.X_FRAME_OPTIONS); - this.http - .headers(headers -> - headers.frameOptions(frameOptions -> frameOptions.disable()) - ); + this.http.headers(headers -> headers.frameOptions(frameOptions -> frameOptions.disable())); assertHeaders(); } @@ -249,9 +221,7 @@ public class HeaderSpecTests { @Test public void headersWhenFrameOptionsModeThenFrameOptionsCustomMode() { this.expectedHeaders.set(XFrameOptionsServerHttpHeadersWriter.X_FRAME_OPTIONS, "SAMEORIGIN"); - this.http.headers() - .frameOptions() - .mode(XFrameOptionsServerHttpHeadersWriter.Mode.SAMEORIGIN); + this.http.headers().frameOptions().mode(XFrameOptionsServerHttpHeadersWriter.Mode.SAMEORIGIN); assertHeaders(); } @@ -259,14 +229,8 @@ public class HeaderSpecTests { @Test public void headersWhenFrameOptionsModeInLambdaThenFrameOptionsCustomMode() { this.expectedHeaders.set(XFrameOptionsServerHttpHeadersWriter.X_FRAME_OPTIONS, "SAMEORIGIN"); - this.http - .headers(headers -> - headers - .frameOptions(frameOptions -> - frameOptions - .mode(XFrameOptionsServerHttpHeadersWriter.Mode.SAMEORIGIN) - ) - ); + this.http.headers(headers -> headers + .frameOptions(frameOptions -> frameOptions.mode(XFrameOptionsServerHttpHeadersWriter.Mode.SAMEORIGIN))); assertHeaders(); } @@ -282,10 +246,7 @@ public class HeaderSpecTests { @Test public void headersWhenXssProtectionDisableInLambdaThenXssProtectionNotWritten() { expectHeaderNamesNotPresent("X-Xss-Protection"); - this.http - .headers(headers -> - headers.xssProtection(xssProtection -> xssProtection.disable()) - ); + this.http.headers(headers -> headers.xssProtection(xssProtection -> xssProtection.disable())); assertHeaders(); } @@ -293,8 +254,7 @@ public class HeaderSpecTests { @Test public void headersWhenFeaturePolicyEnabledThenFeaturePolicyWritten() { String policyDirectives = "Feature-Policy"; - this.expectedHeaders.add(FeaturePolicyServerHttpHeadersWriter.FEATURE_POLICY, - policyDirectives); + this.expectedHeaders.add(FeaturePolicyServerHttpHeadersWriter.FEATURE_POLICY, policyDirectives); this.http.headers().featurePolicy(policyDirectives); @@ -318,10 +278,7 @@ public class HeaderSpecTests { this.expectedHeaders.add(ContentSecurityPolicyServerHttpHeadersWriter.CONTENT_SECURITY_POLICY, expectedPolicyDirectives); - this.http - .headers(headers -> - headers.contentSecurityPolicy(withDefaults()) - ); + this.http.headers(headers -> headers.contentSecurityPolicy(withDefaults())); assertHeaders(); } @@ -332,14 +289,8 @@ public class HeaderSpecTests { this.expectedHeaders.add(ContentSecurityPolicyServerHttpHeadersWriter.CONTENT_SECURITY_POLICY, policyDirectives); - this.http - .headers(headers -> - headers - .contentSecurityPolicy(contentSecurityPolicy -> - contentSecurityPolicy - .policyDirectives(policyDirectives) - ) - ); + this.http.headers(headers -> headers.contentSecurityPolicy( + contentSecurityPolicy -> contentSecurityPolicy.policyDirectives(policyDirectives))); assertHeaders(); } @@ -357,11 +308,7 @@ public class HeaderSpecTests { public void headersWhenReferrerPolicyEnabledInLambdaThenReferrerPolicyWritten() { this.expectedHeaders.add(ReferrerPolicyServerHttpHeadersWriter.REFERRER_POLICY, ReferrerPolicy.NO_REFERRER.getPolicy()); - this.http - .headers(headers -> - headers - .referrerPolicy(withDefaults()) - ); + this.http.headers(headers -> headers.referrerPolicy(withDefaults())); assertHeaders(); } @@ -379,14 +326,8 @@ public class HeaderSpecTests { public void headersWhenReferrerPolicyCustomEnabledInLambdaThenCustomReferrerPolicyWritten() { this.expectedHeaders.add(ReferrerPolicyServerHttpHeadersWriter.REFERRER_POLICY, ReferrerPolicy.NO_REFERRER_WHEN_DOWNGRADE.getPolicy()); - this.http - .headers(headers -> - headers - .referrerPolicy(referrerPolicy -> - referrerPolicy - .policy(ReferrerPolicy.NO_REFERRER_WHEN_DOWNGRADE) - ) - ); + this.http.headers(headers -> headers + .referrerPolicy(referrerPolicy -> referrerPolicy.policy(ReferrerPolicy.NO_REFERRER_WHEN_DOWNGRADE))); assertHeaders(); } @@ -395,10 +336,9 @@ public class HeaderSpecTests { public void headersWhenCustomHeadersWriter() { this.expectedHeaders.add(CUSTOM_HEADER, CUSTOM_VALUE); this.http.headers(headers -> headers.writer(exchange -> { - return Mono.just(exchange) - .doOnNext(it -> { - it.getResponse().getHeaders().add(CUSTOM_HEADER, CUSTOM_VALUE); - }).then(); + return Mono.just(exchange).doOnNext(it -> { + it.getResponse().getHeaders().add(CUSTOM_HEADER, CUSTOM_VALUE); + }).then(); })); @@ -414,16 +354,13 @@ public class HeaderSpecTests { private void assertHeaders() { WebTestClient client = buildClient(); - FluxExchangeResult response = client.get() - .uri("https://example.com/") - .exchange() - .returnResult(String.class); + FluxExchangeResult response = client.get().uri("https://example.com/").exchange() + .returnResult(String.class); Map> responseHeaders = response.getResponseHeaders(); if (!this.expectedHeaders.isEmpty()) { - assertThat(responseHeaders).describedAs(response.toString()) - .containsAllEntriesOf(this.expectedHeaders); + assertThat(responseHeaders).describedAs(response.toString()).containsAllEntriesOf(this.expectedHeaders); } if (!this.headerNamesNotPresent.isEmpty()) { assertThat(responseHeaders.keySet()).doesNotContainAnyElementsOf(this.headerNamesNotPresent); @@ -433,4 +370,5 @@ public class HeaderSpecTests { private WebTestClient buildClient() { return WebTestClientBuilder.bindToWebFilters(this.http.build()).build(); } + } diff --git a/config/src/test/java/org/springframework/security/config/web/server/HttpsRedirectSpecTests.java b/config/src/test/java/org/springframework/security/config/web/server/HttpsRedirectSpecTests.java index fa0f89940d..f935125a03 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/HttpsRedirectSpecTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/HttpsRedirectSpecTests.java @@ -41,6 +41,7 @@ import static org.springframework.security.config.Customizer.withDefaults; * @author Josh Cummings */ public class HttpsRedirectSpecTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -55,64 +56,43 @@ public class HttpsRedirectSpecTests { public void getWhenSecureThenDoesNotRedirect() { this.spring.register(RedirectToHttpConfig.class).autowire(); - this.client.get() - .uri("https://localhost") - .exchange() - .expectStatus().isNotFound(); + this.client.get().uri("https://localhost").exchange().expectStatus().isNotFound(); } @Test public void getWhenInsecureThenRespondsWithRedirectToSecure() { this.spring.register(RedirectToHttpConfig.class).autowire(); - this.client.get() - .uri("http://localhost") - .exchange() - .expectStatus().isFound() - .expectHeader().valueEquals(HttpHeaders.LOCATION, "https://localhost"); + this.client.get().uri("http://localhost").exchange().expectStatus().isFound().expectHeader() + .valueEquals(HttpHeaders.LOCATION, "https://localhost"); } @Test public void getWhenInsecureAndRedirectConfiguredInLambdaThenRespondsWithRedirectToSecure() { this.spring.register(RedirectToHttpsInLambdaConfig.class).autowire(); - this.client.get() - .uri("http://localhost") - .exchange() - .expectStatus().isFound() - .expectHeader().valueEquals(HttpHeaders.LOCATION, "https://localhost"); + this.client.get().uri("http://localhost").exchange().expectStatus().isFound().expectHeader() + .valueEquals(HttpHeaders.LOCATION, "https://localhost"); } @Test public void getWhenInsecureAndPathRequiresTransportSecurityThenRedirects() { this.spring.register(SometimesRedirectToHttpsConfig.class).autowire(); - this.client.get() - .uri("http://localhost:8080") - .exchange() - .expectStatus().isNotFound(); + this.client.get().uri("http://localhost:8080").exchange().expectStatus().isNotFound(); - this.client.get() - .uri("http://localhost:8080/secure") - .exchange() - .expectStatus().isFound() - .expectHeader().valueEquals(HttpHeaders.LOCATION, "https://localhost:8443/secure"); + this.client.get().uri("http://localhost:8080/secure").exchange().expectStatus().isFound().expectHeader() + .valueEquals(HttpHeaders.LOCATION, "https://localhost:8443/secure"); } @Test public void getWhenInsecureAndPathRequiresTransportSecurityInLambdaThenRedirects() { this.spring.register(SometimesRedirectToHttpsInLambdaConfig.class).autowire(); - this.client.get() - .uri("http://localhost:8080") - .exchange() - .expectStatus().isNotFound(); + this.client.get().uri("http://localhost:8080").exchange().expectStatus().isNotFound(); - this.client.get() - .uri("http://localhost:8080/secure") - .exchange() - .expectStatus().isFound() - .expectHeader().valueEquals(HttpHeaders.LOCATION, "https://localhost:8443/secure"); + this.client.get().uri("http://localhost:8080/secure").exchange().expectStatus().isFound().expectHeader() + .valueEquals(HttpHeaders.LOCATION, "https://localhost:8443/secure"); } @Test @@ -122,11 +102,8 @@ public class HttpsRedirectSpecTests { PortMapper portMapper = this.spring.getContext().getBean(PortMapper.class); when(portMapper.lookupHttpsPort(4080)).thenReturn(4443); - this.client.get() - .uri("http://localhost:4080") - .exchange() - .expectStatus().isFound() - .expectHeader().valueEquals(HttpHeaders.LOCATION, "https://localhost:4443"); + this.client.get().uri("http://localhost:4080").exchange().expectStatus().isFound().expectHeader() + .valueEquals(HttpHeaders.LOCATION, "https://localhost:4443"); } @Test @@ -136,16 +113,14 @@ public class HttpsRedirectSpecTests { PortMapper portMapper = this.spring.getContext().getBean(PortMapper.class); when(portMapper.lookupHttpsPort(4080)).thenReturn(4443); - this.client.get() - .uri("http://localhost:4080") - .exchange() - .expectStatus().isFound() - .expectHeader().valueEquals(HttpHeaders.LOCATION, "https://localhost:4443"); + this.client.get().uri("http://localhost:4080").exchange().expectStatus().isFound().expectHeader() + .valueEquals(HttpHeaders.LOCATION, "https://localhost:4443"); } @EnableWebFlux @EnableWebFluxSecurity static class RedirectToHttpConfig { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -155,12 +130,13 @@ public class HttpsRedirectSpecTests { return http.build(); } - } + } @EnableWebFlux @EnableWebFluxSecurity static class RedirectToHttpsInLambdaConfig { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -170,11 +146,13 @@ public class HttpsRedirectSpecTests { return http.build(); } + } @EnableWebFlux @EnableWebFluxSecurity static class SometimesRedirectToHttpsConfig { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -185,12 +163,13 @@ public class HttpsRedirectSpecTests { return http.build(); } - } + } @EnableWebFlux @EnableWebFluxSecurity static class SometimesRedirectToHttpsInLambdaConfig { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -203,11 +182,13 @@ public class HttpsRedirectSpecTests { return http.build(); } + } @EnableWebFlux @EnableWebFluxSecurity static class RedirectToHttpsViaCustomPortsConfig { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -223,11 +204,13 @@ public class HttpsRedirectSpecTests { public PortMapper portMapper() { return mock(PortMapper.class); } + } @EnableWebFlux @EnableWebFluxSecurity static class RedirectToHttpsViaCustomPortsInLambdaConfig { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -245,5 +228,7 @@ public class HttpsRedirectSpecTests { public PortMapper portMapper() { return mock(PortMapper.class); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/web/server/LogoutSpecTests.java b/config/src/test/java/org/springframework/security/config/web/server/LogoutSpecTests.java index 723251e4cf..b403afdefc 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/LogoutSpecTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/LogoutSpecTests.java @@ -38,209 +38,127 @@ public class LogoutSpecTests { @Test public void defaultLogout() { - SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange() - .anyExchange().authenticated() - .and() - .formLogin().and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.authorizeExchange().anyExchange().authenticated().and() + .formLogin().and().build(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - FormLoginTests.DefaultLoginPage loginPage = FormLoginTests.HomePage.to(driver, FormLoginTests.DefaultLoginPage.class) - .assertAt(); + FormLoginTests.DefaultLoginPage loginPage = FormLoginTests.HomePage + .to(driver, FormLoginTests.DefaultLoginPage.class).assertAt(); - loginPage = loginPage.loginForm() - .username("user") - .password("invalid") - .submit(FormLoginTests.DefaultLoginPage.class) - .assertError(); + loginPage = loginPage.loginForm().username("user").password("invalid") + .submit(FormLoginTests.DefaultLoginPage.class).assertError(); - FormLoginTests.HomePage homePage = loginPage.loginForm() - .username("user") - .password("password") - .submit(FormLoginTests.HomePage.class); + FormLoginTests.HomePage homePage = loginPage.loginForm().username("user").password("password") + .submit(FormLoginTests.HomePage.class); homePage.assertAt(); - loginPage = FormLoginTests.DefaultLogoutPage.to(driver) - .assertAt() - .logout(); + loginPage = FormLoginTests.DefaultLogoutPage.to(driver).assertAt().logout(); - loginPage - .assertAt() - .assertLogout(); + loginPage.assertAt().assertLogout(); } @Test public void customLogout() { - SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange() - .anyExchange().authenticated() - .and() - .formLogin().and() - .logout() - .requiresLogout(ServerWebExchangeMatchers.pathMatchers("/custom-logout")) - .and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.authorizeExchange().anyExchange().authenticated().and() + .formLogin().and().logout().requiresLogout(ServerWebExchangeMatchers.pathMatchers("/custom-logout")) + .and().build(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - FormLoginTests.DefaultLoginPage loginPage = FormLoginTests.HomePage.to(driver, FormLoginTests.DefaultLoginPage.class) - .assertAt(); + FormLoginTests.DefaultLoginPage loginPage = FormLoginTests.HomePage + .to(driver, FormLoginTests.DefaultLoginPage.class).assertAt(); - loginPage = loginPage.loginForm() - .username("user") - .password("invalid") - .submit(FormLoginTests.DefaultLoginPage.class) - .assertError(); + loginPage = loginPage.loginForm().username("user").password("invalid") + .submit(FormLoginTests.DefaultLoginPage.class).assertError(); - FormLoginTests.HomePage homePage = loginPage.loginForm() - .username("user") - .password("password") - .submit(FormLoginTests.HomePage.class); + FormLoginTests.HomePage homePage = loginPage.loginForm().username("user").password("password") + .submit(FormLoginTests.HomePage.class); homePage.assertAt(); driver.get("http://localhost/custom-logout"); - FormLoginTests.DefaultLoginPage.create(driver) - .assertAt() - .assertLogout(); + FormLoginTests.DefaultLoginPage.create(driver).assertAt().assertLogout(); } @Test public void logoutWhenCustomLogoutInLambdaThenCustomLogoutUsed() { SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange(authorizeExchange -> - authorizeExchange - .anyExchange().authenticated() - ) - .formLogin(withDefaults()) - .logout(logout -> - logout - .requiresLogout(ServerWebExchangeMatchers.pathMatchers("/custom-logout")) - ) - .build(); + .authorizeExchange(authorizeExchange -> authorizeExchange.anyExchange().authenticated()) + .formLogin(withDefaults()) + .logout(logout -> logout.requiresLogout(ServerWebExchangeMatchers.pathMatchers("/custom-logout"))) + .build(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - FormLoginTests.DefaultLoginPage loginPage = FormLoginTests.HomePage.to(driver, FormLoginTests.DefaultLoginPage.class) - .assertAt(); + FormLoginTests.DefaultLoginPage loginPage = FormLoginTests.HomePage + .to(driver, FormLoginTests.DefaultLoginPage.class).assertAt(); - loginPage = loginPage.loginForm() - .username("user") - .password("invalid") - .submit(FormLoginTests.DefaultLoginPage.class) - .assertError(); + loginPage = loginPage.loginForm().username("user").password("invalid") + .submit(FormLoginTests.DefaultLoginPage.class).assertError(); - FormLoginTests.HomePage homePage = loginPage.loginForm() - .username("user") - .password("password") - .submit(FormLoginTests.HomePage.class); + FormLoginTests.HomePage homePage = loginPage.loginForm().username("user").password("password") + .submit(FormLoginTests.HomePage.class); homePage.assertAt(); driver.get("http://localhost/custom-logout"); - FormLoginTests.DefaultLoginPage.create(driver) - .assertAt() - .assertLogout(); + FormLoginTests.DefaultLoginPage.create(driver).assertAt().assertLogout(); } @Test public void logoutWhenDisabledThenPostToLogoutDoesNothing() { - SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange() - .anyExchange().authenticated() - .and() - .formLogin().and() - .logout().disable() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.authorizeExchange().anyExchange().authenticated().and() + .formLogin().and().logout().disable().build(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - FormLoginTests.DefaultLoginPage loginPage = FormLoginTests.HomePage.to(driver, FormLoginTests.DefaultLoginPage.class) - .assertAt(); + FormLoginTests.DefaultLoginPage loginPage = FormLoginTests.HomePage + .to(driver, FormLoginTests.DefaultLoginPage.class).assertAt(); - FormLoginTests.HomePage homePage = loginPage.loginForm() - .username("user") - .password("password") + FormLoginTests.HomePage homePage = loginPage.loginForm().username("user").password("password") .submit(FormLoginTests.HomePage.class); homePage.assertAt(); - FormLoginTests.DefaultLogoutPage.to(driver) - .assertAt() - .logout(); + FormLoginTests.DefaultLogoutPage.to(driver).assertAt().logout(); - homePage - .assertAt(); + homePage.assertAt(); } - @Test public void logoutWhenCustomSecurityContextRepositoryThenLogsOut() { WebSessionServerSecurityContextRepository repository = new WebSessionServerSecurityContextRepository(); repository.setSpringSecurityContextAttrName("CUSTOM_CONTEXT_ATTR"); - SecurityWebFilterChain securityWebFilter = this.http - .securityContextRepository(repository) - .authorizeExchange() - .anyExchange().authenticated() - .and() - .formLogin() - .and() - .logout() - .and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.securityContextRepository(repository).authorizeExchange() + .anyExchange().authenticated().and().formLogin().and().logout().and().build(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(securityWebFilter) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(securityWebFilter).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - FormLoginTests.DefaultLoginPage loginPage = FormLoginTests.HomePage.to(driver, FormLoginTests.DefaultLoginPage.class) - .assertAt(); + FormLoginTests.DefaultLoginPage loginPage = FormLoginTests.HomePage + .to(driver, FormLoginTests.DefaultLoginPage.class).assertAt(); - FormLoginTests.HomePage homePage = loginPage.loginForm() - .username("user") - .password("password") + FormLoginTests.HomePage homePage = loginPage.loginForm().username("user").password("password") .submit(FormLoginTests.HomePage.class); homePage.assertAt(); - FormLoginTests.DefaultLogoutPage.to(driver) - .assertAt() - .logout(); + FormLoginTests.DefaultLogoutPage.to(driver).assertAt().logout(); - FormLoginTests.HomePage.to(driver, FormLoginTests.DefaultLoginPage.class) - .assertAt(); + FormLoginTests.HomePage.to(driver, FormLoginTests.DefaultLoginPage.class).assertAt(); } + } diff --git a/config/src/test/java/org/springframework/security/config/web/server/OAuth2ClientSpecTests.java b/config/src/test/java/org/springframework/security/config/web/server/OAuth2ClientSpecTests.java index 11cc82e2d6..30a69bd0c3 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/OAuth2ClientSpecTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/OAuth2ClientSpecTests.java @@ -71,6 +71,7 @@ import static org.mockito.Mockito.when; @RunWith(SpringRunner.class) @SecurityTestExecutionListeners public class OAuth2ClientSpecTests { + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -89,13 +90,13 @@ public class OAuth2ClientSpecTests { this.spring.register(Config.class, AuthorizedClientController.class).autowire(); ReactiveClientRegistrationRepository repository = this.spring.getContext() .getBean(ReactiveClientRegistrationRepository.class); - ServerOAuth2AuthorizedClientRepository authorizedClientRepository = this.spring.getContext().getBean(ServerOAuth2AuthorizedClientRepository.class); - when(repository.findByRegistrationId(any())).thenReturn(Mono.just(TestClientRegistrations.clientRegistration().build())); + ServerOAuth2AuthorizedClientRepository authorizedClientRepository = this.spring.getContext() + .getBean(ServerOAuth2AuthorizedClientRepository.class); + when(repository.findByRegistrationId(any())) + .thenReturn(Mono.just(TestClientRegistrations.clientRegistration().build())); when(authorizedClientRepository.loadAuthorizedClient(any(), any(), any())).thenReturn(Mono.empty()); - this.client.get().uri("/") - .exchange() - .expectStatus().is3xxRedirection(); + this.client.get().uri("/").exchange().expectStatus().is3xxRedirection(); } @Test @@ -103,18 +104,19 @@ public class OAuth2ClientSpecTests { this.spring.register(Config.class, AuthorizedClientController.class).autowire(); ReactiveClientRegistrationRepository repository = this.spring.getContext() .getBean(ReactiveClientRegistrationRepository.class); - ServerOAuth2AuthorizedClientRepository authorizedClientRepository = this.spring.getContext().getBean(ServerOAuth2AuthorizedClientRepository.class); - when(repository.findByRegistrationId(any())).thenReturn(Mono.just(TestClientRegistrations.clientRegistration().build())); + ServerOAuth2AuthorizedClientRepository authorizedClientRepository = this.spring.getContext() + .getBean(ServerOAuth2AuthorizedClientRepository.class); + when(repository.findByRegistrationId(any())) + .thenReturn(Mono.just(TestClientRegistrations.clientRegistration().build())); when(authorizedClientRepository.loadAuthorizedClient(any(), any(), any())).thenReturn(Mono.empty()); - this.client.get().uri("/") - .exchange() - .expectStatus().is3xxRedirection(); + this.client.get().uri("/").exchange().expectStatus().is3xxRedirection(); } @EnableWebFlux @EnableWebFluxSecurity static class Config { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -133,19 +135,23 @@ public class OAuth2ClientSpecTests { ServerOAuth2AuthorizedClientRepository authorizedClientRepository() { return mock(ServerOAuth2AuthorizedClientRepository.class); } + } @RestController static class AuthorizedClientController { + @GetMapping("/") String home(@RegisteredOAuth2AuthorizedClient("github") OAuth2AuthorizedClient authorizedClient) { return "home"; } + } @Test public void oauth2ClientWhenCustomObjectsThenUsed() { - this.spring.register(ClientRegistrationConfig.class, OAuth2ClientCustomConfig.class, AuthorizedClientController.class).autowire(); + this.spring.register(ClientRegistrationConfig.class, OAuth2ClientCustomConfig.class, + AuthorizedClientController.class).autowire(); OAuth2ClientCustomConfig config = this.spring.getContext().getBean(OAuth2ClientCustomConfig.class); @@ -155,31 +161,27 @@ public class OAuth2ClientSpecTests { ServerRequestCache requestCache = config.requestCache; OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.request() - .redirectUri("/authorize/oauth2/code/registration-id") - .build(); + .redirectUri("/authorize/oauth2/code/registration-id").build(); OAuth2AuthorizationResponse authorizationResponse = TestOAuth2AuthorizationResponses.success() - .redirectUri("/authorize/oauth2/code/registration-id") - .build(); - OAuth2AuthorizationExchange authorizationExchange = - new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse); + .redirectUri("/authorize/oauth2/code/registration-id").build(); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, + authorizationResponse); OAuth2AccessToken accessToken = TestOAuth2AccessTokens.noScopes(); OAuth2AuthorizationCodeAuthenticationToken result = new OAuth2AuthorizationCodeAuthenticationToken( this.registration, authorizationExchange, accessToken); - when(authorizationRequestRepository.loadAuthorizationRequest(any())).thenReturn(Mono.just(authorizationRequest)); + when(authorizationRequestRepository.loadAuthorizationRequest(any())) + .thenReturn(Mono.just(authorizationRequest)); when(converter.convert(any())).thenReturn(Mono.just(new TestingAuthenticationToken("a", "b", "c"))); when(manager.authenticate(any())).thenReturn(Mono.just(result)); when(requestCache.getRedirectUri(any())).thenReturn(Mono.just(URI.create("/saved-request"))); this.client.get() - .uri(uriBuilder -> - uriBuilder.path("/authorize/oauth2/code/registration-id") - .queryParam(OAuth2ParameterNames.CODE, "code") - .queryParam(OAuth2ParameterNames.STATE, "state") + .uri(uriBuilder -> uriBuilder.path("/authorize/oauth2/code/registration-id") + .queryParam(OAuth2ParameterNames.CODE, "code").queryParam(OAuth2ParameterNames.STATE, "state") .build()) - .exchange() - .expectStatus().is3xxRedirection(); + .exchange().expectStatus().is3xxRedirection(); verify(converter).convert(any()); verify(manager).authenticate(any()); @@ -189,22 +191,25 @@ public class OAuth2ClientSpecTests { @EnableWebFlux @EnableWebFluxSecurity static class ClientRegistrationConfig { - private ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration() - .build(); + + private ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); @Bean InMemoryReactiveClientRegistrationRepository clientRegistrationRepository() { return new InMemoryReactiveClientRegistrationRepository(this.clientRegistration); } + } @Configuration static class OAuth2ClientCustomConfig { + ReactiveAuthenticationManager manager = mock(ReactiveAuthenticationManager.class); ServerAuthenticationConverter authenticationConverter = mock(ServerAuthenticationConverter.class); - ServerAuthorizationRequestRepository authorizationRequestRepository = mock(ServerAuthorizationRequestRepository.class); + ServerAuthorizationRequestRepository authorizationRequestRepository = mock( + ServerAuthorizationRequestRepository.class); ServerRequestCache requestCache = mock(ServerRequestCache.class); @@ -221,13 +226,16 @@ public class OAuth2ClientSpecTests { // @formatter:on return http.build(); } + } @Test public void oauth2ClientWhenCustomObjectsInLambdaThenUsed() { - this.spring.register(ClientRegistrationConfig.class, OAuth2ClientInLambdaCustomConfig.class, AuthorizedClientController.class).autowire(); + this.spring.register(ClientRegistrationConfig.class, OAuth2ClientInLambdaCustomConfig.class, + AuthorizedClientController.class).autowire(); - OAuth2ClientInLambdaCustomConfig config = this.spring.getContext().getBean(OAuth2ClientInLambdaCustomConfig.class); + OAuth2ClientInLambdaCustomConfig config = this.spring.getContext() + .getBean(OAuth2ClientInLambdaCustomConfig.class); ServerAuthenticationConverter converter = config.authenticationConverter; ReactiveAuthenticationManager manager = config.manager; @@ -235,31 +243,27 @@ public class OAuth2ClientSpecTests { ServerRequestCache requestCache = config.requestCache; OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.request() - .redirectUri("/authorize/oauth2/code/registration-id") - .build(); + .redirectUri("/authorize/oauth2/code/registration-id").build(); OAuth2AuthorizationResponse authorizationResponse = TestOAuth2AuthorizationResponses.success() - .redirectUri("/authorize/oauth2/code/registration-id") - .build(); - OAuth2AuthorizationExchange authorizationExchange = - new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse); + .redirectUri("/authorize/oauth2/code/registration-id").build(); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, + authorizationResponse); OAuth2AccessToken accessToken = TestOAuth2AccessTokens.noScopes(); OAuth2AuthorizationCodeAuthenticationToken result = new OAuth2AuthorizationCodeAuthenticationToken( this.registration, authorizationExchange, accessToken); - when(authorizationRequestRepository.loadAuthorizationRequest(any())).thenReturn(Mono.just(authorizationRequest)); + when(authorizationRequestRepository.loadAuthorizationRequest(any())) + .thenReturn(Mono.just(authorizationRequest)); when(converter.convert(any())).thenReturn(Mono.just(new TestingAuthenticationToken("a", "b", "c"))); when(manager.authenticate(any())).thenReturn(Mono.just(result)); when(requestCache.getRedirectUri(any())).thenReturn(Mono.just(URI.create("/saved-request"))); this.client.get() - .uri(uriBuilder -> - uriBuilder.path("/authorize/oauth2/code/registration-id") - .queryParam(OAuth2ParameterNames.CODE, "code") - .queryParam(OAuth2ParameterNames.STATE, "state") + .uri(uriBuilder -> uriBuilder.path("/authorize/oauth2/code/registration-id") + .queryParam(OAuth2ParameterNames.CODE, "code").queryParam(OAuth2ParameterNames.STATE, "state") .build()) - .exchange() - .expectStatus().is3xxRedirection(); + .exchange().expectStatus().is3xxRedirection(); verify(converter).convert(any()); verify(manager).authenticate(any()); @@ -268,11 +272,13 @@ public class OAuth2ClientSpecTests { @Configuration static class OAuth2ClientInLambdaCustomConfig { + ReactiveAuthenticationManager manager = mock(ReactiveAuthenticationManager.class); ServerAuthenticationConverter authenticationConverter = mock(ServerAuthenticationConverter.class); - ServerAuthorizationRequestRepository authorizationRequestRepository = mock(ServerAuthorizationRequestRepository.class); + ServerAuthorizationRequestRepository authorizationRequestRepository = mock( + ServerAuthorizationRequestRepository.class); ServerRequestCache requestCache = mock(ServerRequestCache.class); @@ -289,5 +295,7 @@ public class OAuth2ClientSpecTests { // @formatter:on return http.build(); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/web/server/OAuth2LoginTests.java b/config/src/test/java/org/springframework/security/config/web/server/OAuth2LoginTests.java index d8ab7c8481..902290964e 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/OAuth2LoginTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/OAuth2LoginTests.java @@ -124,23 +124,16 @@ public class OAuth2LoginTests { @Autowired private WebFilterChainProxy springSecurity; - private static ClientRegistration github = CommonOAuth2Provider.GITHUB - .getBuilder("github") - .clientId("client") - .clientSecret("secret") - .build(); + private static ClientRegistration github = CommonOAuth2Provider.GITHUB.getBuilder("github").clientId("client") + .clientSecret("secret").build(); - private static ClientRegistration google = CommonOAuth2Provider.GOOGLE - .getBuilder("google") - .clientId("client") - .clientSecret("secret") - .build(); + private static ClientRegistration google = CommonOAuth2Provider.GOOGLE.getBuilder("google").clientId("client") + .clientSecret("secret").build(); @Autowired public void setApplicationContext(ApplicationContext context) { if (context.getBeanNamesForType(WebHandler.class).length > 0) { - this.client = WebTestClient.bindToApplicationContext(context) - .build(); + this.client = WebTestClient.bindToApplicationContext(context).build(); } } @@ -148,42 +141,33 @@ public class OAuth2LoginTests { public void defaultLoginPageWithMultipleClientRegistrationsThenLinks() { this.spring.register(OAuth2LoginWithMultipleClientRegistrations.class).autowire(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(this.springSecurity) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(this.springSecurity).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); FormLoginTests.DefaultLoginPage loginPage = FormLoginTests.HomePage - .to(driver, FormLoginTests.DefaultLoginPage.class) - .assertAt() - .assertLoginFormNotPresent() - .oauth2Login() - .assertClientRegistrationByName(this.github.getClientName()) - .and(); + .to(driver, FormLoginTests.DefaultLoginPage.class).assertAt().assertLoginFormNotPresent().oauth2Login() + .assertClientRegistrationByName(this.github.getClientName()).and(); } @EnableWebFluxSecurity static class OAuth2LoginWithMultipleClientRegistrations { + @Bean InMemoryReactiveClientRegistrationRepository clientRegistrationRepository() { return new InMemoryReactiveClientRegistrationRepository(github, google); } + } @Test public void defaultLoginPageWithSingleClientRegistrationThenRedirect() { this.spring.register(OAuth2LoginWithSingleClientRegistrations.class).autowire(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(new GitHubWebFilter(), this.springSecurity) + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(new GitHubWebFilter(), this.springSecurity) .build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); driver.get("http://localhost/"); @@ -195,32 +179,32 @@ public class OAuth2LoginTests { public void defaultLoginPageWithSingleClientRegistrationAndXhrRequestThenDoesNotRedirectForAuthorization() { this.spring.register(OAuth2LoginWithSingleClientRegistrations.class, WebFluxConfig.class).autowire(); - this.client.get() - .uri("/") - .header("X-Requested-With", "XMLHttpRequest") - .exchange() - .expectStatus().is3xxRedirection() - .expectHeader().valueEquals(HttpHeaders.LOCATION, "/login"); + this.client.get().uri("/").header("X-Requested-With", "XMLHttpRequest").exchange().expectStatus() + .is3xxRedirection().expectHeader().valueEquals(HttpHeaders.LOCATION, "/login"); } @EnableWebFlux - static class WebFluxConfig { } + static class WebFluxConfig { + + } @EnableWebFluxSecurity static class OAuth2LoginWithSingleClientRegistrations { + @Bean InMemoryReactiveClientRegistrationRepository clientRegistrationRepository() { return new InMemoryReactiveClientRegistrationRepository(github); } + } @Test public void oauth2AuthorizeWhenCustomObjectsThenUsed() { - this.spring.register(OAuth2LoginWithSingleClientRegistrations.class, - OAuth2AuthorizeWithMockObjectsConfig.class, + this.spring.register(OAuth2LoginWithSingleClientRegistrations.class, OAuth2AuthorizeWithMockObjectsConfig.class, AuthorizedClientController.class).autowire(); - OAuth2AuthorizeWithMockObjectsConfig config = this.spring.getContext().getBean(OAuth2AuthorizeWithMockObjectsConfig.class); + OAuth2AuthorizeWithMockObjectsConfig config = this.spring.getContext() + .getBean(OAuth2AuthorizeWithMockObjectsConfig.class); ServerOAuth2AuthorizedClientRepository authorizedClientRepository = config.authorizedClientRepository; ServerAuthorizationRequestRepository authorizationRequestRepository = config.authorizationRequestRepository; @@ -231,10 +215,7 @@ public class OAuth2LoginTests { when(requestCache.removeMatchingRequest(any())).thenReturn(Mono.empty()); when(requestCache.saveRequest(any())).thenReturn(Mono.empty()); - this.client.get() - .uri("/") - .exchange() - .expectStatus().is3xxRedirection(); + this.client.get().uri("/").exchange().expectStatus().is3xxRedirection(); verify(authorizedClientRepository).loadAuthorizedClient(any(), any(), any()); verify(authorizationRequestRepository).saveAuthorizationRequest(any(), any()); @@ -243,11 +224,12 @@ public class OAuth2LoginTests { @EnableWebFlux static class OAuth2AuthorizeWithMockObjectsConfig { - ServerOAuth2AuthorizedClientRepository authorizedClientRepository = - mock(ServerOAuth2AuthorizedClientRepository.class); - ServerAuthorizationRequestRepository authorizationRequestRepository = - mock(ServerAuthorizationRequestRepository.class); + ServerOAuth2AuthorizedClientRepository authorizedClientRepository = mock( + ServerOAuth2AuthorizedClientRepository.class); + + ServerAuthorizationRequestRepository authorizationRequestRepository = mock( + ServerAuthorizationRequestRepository.class); ServerRequestCache requestCache = mock(ServerRequestCache.class); @@ -268,14 +250,17 @@ public class OAuth2LoginTests { ServerOAuth2AuthorizedClientRepository authorizedClientRepository() { return this.authorizedClientRepository; } + } @RestController static class AuthorizedClientController { + @GetMapping("/") String home(@RegisteredOAuth2AuthorizedClient("github") OAuth2AuthorizedClient authorizedClient) { return "home"; } + } @Test @@ -285,9 +270,7 @@ public class OAuth2LoginTests { String redirectLocation = "/custom-redirect-location"; - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(this.springSecurity) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(this.springSecurity).build(); OAuth2LoginMockAuthenticationManagerConfig config = this.spring.getContext() .getBean(OAuth2LoginMockAuthenticationManagerConfig.class); @@ -301,7 +284,8 @@ public class OAuth2LoginTests { OAuth2User user = TestOAuth2Users.create(); OAuth2AccessToken accessToken = TestOAuth2AccessTokens.noScopes(); - OAuth2LoginAuthenticationToken result = new OAuth2LoginAuthenticationToken(github, exchange, user, user.getAuthorities(), accessToken); + OAuth2LoginAuthenticationToken result = new OAuth2LoginAuthenticationToken(github, exchange, user, + user.getAuthorities(), accessToken); when(converter.convert(any())).thenReturn(Mono.just(new TestingAuthenticationToken("a", "b", "c"))); when(manager.authenticate(any())).thenReturn(Mono.just(result)); @@ -315,11 +299,8 @@ public class OAuth2LoginTests { .onAuthenticationSuccess(webFilterExchange, authentication); }); - webTestClient.get() - .uri("/login/oauth2/code/github") - .exchange() - .expectStatus().is3xxRedirection() - .expectHeader().valueEquals("Location", redirectLocation); + webTestClient.get().uri("/login/oauth2/code/github").exchange().expectStatus().is3xxRedirection().expectHeader() + .valueEquals("Location", redirectLocation); verify(converter).convert(any()); verify(manager).authenticate(any()); @@ -336,9 +317,7 @@ public class OAuth2LoginTests { String redirectLocation = "/custom-redirect-location"; String failureRedirectLocation = "/failure-redirect-location"; - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(this.springSecurity) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(this.springSecurity).build(); OAuth2LoginMockAuthenticationManagerConfig config = this.spring.getContext() .getBean(OAuth2LoginMockAuthenticationManagerConfig.class); @@ -350,7 +329,8 @@ public class OAuth2LoginTests { ServerAuthenticationFailureHandler failureHandler = config.failureHandler; when(converter.convert(any())).thenReturn(Mono.just(new TestingAuthenticationToken("a", "b", "c"))); - when(manager.authenticate(any())).thenReturn(Mono.error(new OAuth2AuthenticationException(new OAuth2Error("error"), "message"))); + when(manager.authenticate(any())) + .thenReturn(Mono.error(new OAuth2AuthenticationException(new OAuth2Error("error"), "message"))); when(matcher.matches(any())).thenReturn(ServerWebExchangeMatcher.MatchResult.match()); when(resolver.resolve(any())).thenReturn(Mono.empty()); when(successHandler.onAuthenticationSuccess(any(), any())).thenAnswer((Answer>) invocation -> { @@ -368,11 +348,8 @@ public class OAuth2LoginTests { .onAuthenticationFailure(webFilterExchange, authenticationException); }); - webTestClient.get() - .uri("/login/oauth2/code/github") - .exchange() - .expectStatus().is3xxRedirection() - .expectHeader().valueEquals("Location", failureRedirectLocation); + webTestClient.get().uri("/login/oauth2/code/github").exchange().expectStatus().is3xxRedirection().expectHeader() + .valueEquals("Location", failureRedirectLocation); verify(converter).convert(any()); verify(manager).authenticate(any()); @@ -383,6 +360,7 @@ public class OAuth2LoginTests { @Configuration static class OAuth2LoginMockAuthenticationManagerConfig { + ReactiveAuthenticationManager manager = mock(ReactiveAuthenticationManager.class); ServerAuthenticationConverter authenticationConverter = mock(ServerAuthenticationConverter.class); @@ -412,6 +390,7 @@ public class OAuth2LoginTests { // @formatter:on return http.build(); } + } @Test @@ -421,9 +400,7 @@ public class OAuth2LoginTests { String redirectLocation = "/custom-redirect-location"; - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(this.springSecurity) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(this.springSecurity).build(); OAuth2LoginMockAuthenticationManagerInLambdaConfig config = this.spring.getContext() .getBean(OAuth2LoginMockAuthenticationManagerInLambdaConfig.class); @@ -437,7 +414,8 @@ public class OAuth2LoginTests { OAuth2User user = TestOAuth2Users.create(); OAuth2AccessToken accessToken = TestOAuth2AccessTokens.noScopes(); - OAuth2LoginAuthenticationToken result = new OAuth2LoginAuthenticationToken(github, exchange, user, user.getAuthorities(), accessToken); + OAuth2LoginAuthenticationToken result = new OAuth2LoginAuthenticationToken(github, exchange, user, + user.getAuthorities(), accessToken); when(converter.convert(any())).thenReturn(Mono.just(new TestingAuthenticationToken("a", "b", "c"))); when(manager.authenticate(any())).thenReturn(Mono.just(result)); @@ -451,11 +429,8 @@ public class OAuth2LoginTests { .onAuthenticationSuccess(webFilterExchange, authentication); }); - webTestClient.get() - .uri("/login/oauth2/code/github") - .exchange() - .expectStatus().is3xxRedirection() - .expectHeader().valueEquals("Location", redirectLocation); + webTestClient.get().uri("/login/oauth2/code/github").exchange().expectStatus().is3xxRedirection().expectHeader() + .valueEquals("Location", redirectLocation); verify(converter).convert(any()); verify(manager).authenticate(any()); @@ -466,6 +441,7 @@ public class OAuth2LoginTests { @Configuration static class OAuth2LoginMockAuthenticationManagerInLambdaConfig { + ReactiveAuthenticationManager manager = mock(ReactiveAuthenticationManager.class); ServerAuthenticationConverter authenticationConverter = mock(ServerAuthenticationConverter.class); @@ -495,16 +471,15 @@ public class OAuth2LoginTests { // @formatter:on return http.build(); } + } @Test public void oauth2LoginWhenCustomBeansThenUsed() { - this.spring.register(OAuth2LoginWithMultipleClientRegistrations.class, - OAuth2LoginWithCustomBeansConfig.class).autowire(); + this.spring.register(OAuth2LoginWithMultipleClientRegistrations.class, OAuth2LoginWithCustomBeansConfig.class) + .autowire(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(this.springSecurity) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(this.springSecurity).build(); OAuth2LoginWithCustomBeansConfig config = this.spring.getContext() .getBean(OAuth2LoginWithCustomBeansConfig.class); @@ -513,7 +488,8 @@ public class OAuth2LoginTests { OAuth2AuthorizationResponse response = TestOAuth2AuthorizationResponses.success().build(); OAuth2AuthorizationExchange exchange = new OAuth2AuthorizationExchange(request, response); OAuth2AccessToken accessToken = TestOAuth2AccessTokens.scopes("openid"); - OAuth2AuthorizationCodeAuthenticationToken token = new OAuth2AuthorizationCodeAuthenticationToken(google, exchange, accessToken); + OAuth2AuthorizationCodeAuthenticationToken token = new OAuth2AuthorizationCodeAuthenticationToken(google, + exchange, accessToken); ServerAuthenticationConverter converter = config.authenticationConverter; when(converter.convert(any())).thenReturn(Mono.just(token)); @@ -525,10 +501,8 @@ public class OAuth2LoginTests { Map additionalParameters = new HashMap<>(); additionalParameters.put(OidcParameterNames.ID_TOKEN, "id-token"); OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken(accessToken.getTokenValue()) - .tokenType(accessToken.getTokenType()) - .scopes(accessToken.getScopes()) - .additionalParameters(additionalParameters) - .build(); + .tokenType(accessToken.getTokenType()).scopes(accessToken.getScopes()) + .additionalParameters(additionalParameters).build(); ReactiveOAuth2AccessTokenResponseClient tokenResponseClient = config.tokenResponseClient; when(tokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); @@ -536,10 +510,7 @@ public class OAuth2LoginTests { ReactiveOAuth2UserService userService = config.userService; when(userService.loadUser(any())).thenReturn(Mono.just(user)); - webTestClient.get() - .uri("/login/oauth2/code/google") - .exchange() - .expectStatus().is3xxRedirection(); + webTestClient.get().uri("/login/oauth2/code/google").exchange().expectStatus().is3xxRedirection(); verify(config.jwtDecoderFactory).createDecoder(any()); verify(tokenResponseClient).getTokenResponse(any()); @@ -549,20 +520,20 @@ public class OAuth2LoginTests { // gh-5562 @Test public void oauth2LoginWhenAccessTokenRequestFailsThenDefaultRedirectToLogin() { - this.spring.register(OAuth2LoginWithMultipleClientRegistrations.class, - OAuth2LoginWithCustomBeansConfig.class).autowire(); + this.spring.register(OAuth2LoginWithMultipleClientRegistrations.class, OAuth2LoginWithCustomBeansConfig.class) + .autowire(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(this.springSecurity) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(this.springSecurity).build(); OAuth2AuthorizationRequest request = TestOAuth2AuthorizationRequests.request().scope("openid").build(); OAuth2AuthorizationResponse response = TestOAuth2AuthorizationResponses.success().build(); OAuth2AuthorizationExchange exchange = new OAuth2AuthorizationExchange(request, response); OAuth2AccessToken accessToken = TestOAuth2AccessTokens.scopes("openid"); - OAuth2AuthorizationCodeAuthenticationToken authenticationToken = new OAuth2AuthorizationCodeAuthenticationToken(google, exchange, accessToken); + OAuth2AuthorizationCodeAuthenticationToken authenticationToken = new OAuth2AuthorizationCodeAuthenticationToken( + google, exchange, accessToken); - OAuth2LoginWithCustomBeansConfig config = this.spring.getContext().getBean(OAuth2LoginWithCustomBeansConfig.class); + OAuth2LoginWithCustomBeansConfig config = this.spring.getContext() + .getBean(OAuth2LoginWithCustomBeansConfig.class); ServerAuthenticationConverter converter = config.authenticationConverter; when(converter.convert(any())).thenReturn(Mono.just(authenticationToken)); @@ -571,32 +542,27 @@ public class OAuth2LoginTests { OAuth2Error oauth2Error = new OAuth2Error("invalid_request", "Invalid request", null); when(tokenResponseClient.getTokenResponse(any())).thenThrow(new OAuth2AuthenticationException(oauth2Error)); - webTestClient.get() - .uri("/login/oauth2/code/google") - .exchange() - .expectStatus() - .is3xxRedirection() - .expectHeader() - .valueEquals("Location", "/login?error"); + webTestClient.get().uri("/login/oauth2/code/google").exchange().expectStatus().is3xxRedirection().expectHeader() + .valueEquals("Location", "/login?error"); } // gh-6484 @Test public void oauth2LoginWhenIdTokenValidationFailsThenDefaultRedirectToLogin() { - this.spring.register(OAuth2LoginWithMultipleClientRegistrations.class, - OAuth2LoginWithCustomBeansConfig.class).autowire(); + this.spring.register(OAuth2LoginWithMultipleClientRegistrations.class, OAuth2LoginWithCustomBeansConfig.class) + .autowire(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(this.springSecurity) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(this.springSecurity).build(); - OAuth2LoginWithCustomBeansConfig config = this.spring.getContext().getBean(OAuth2LoginWithCustomBeansConfig.class); + OAuth2LoginWithCustomBeansConfig config = this.spring.getContext() + .getBean(OAuth2LoginWithCustomBeansConfig.class); OAuth2AuthorizationRequest request = TestOAuth2AuthorizationRequests.request().scope("openid").build(); OAuth2AuthorizationResponse response = TestOAuth2AuthorizationResponses.success().build(); OAuth2AuthorizationExchange exchange = new OAuth2AuthorizationExchange(request, response); OAuth2AccessToken accessToken = TestOAuth2AccessTokens.scopes("openid"); - OAuth2AuthorizationCodeAuthenticationToken authenticationToken = new OAuth2AuthorizationCodeAuthenticationToken(google, exchange, accessToken); + OAuth2AuthorizationCodeAuthenticationToken authenticationToken = new OAuth2AuthorizationCodeAuthenticationToken( + google, exchange, accessToken); ServerAuthenticationConverter converter = config.authenticationConverter; when(converter.convert(any())).thenReturn(Mono.just(authenticationToken)); @@ -604,25 +570,18 @@ public class OAuth2LoginTests { Map additionalParameters = new HashMap<>(); additionalParameters.put(OidcParameterNames.ID_TOKEN, "id-token"); OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken(accessToken.getTokenValue()) - .tokenType(accessToken.getTokenType()) - .scopes(accessToken.getScopes()) - .additionalParameters(additionalParameters) - .build(); + .tokenType(accessToken.getTokenType()).scopes(accessToken.getScopes()) + .additionalParameters(additionalParameters).build(); ReactiveOAuth2AccessTokenResponseClient tokenResponseClient = config.tokenResponseClient; when(tokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); ReactiveJwtDecoderFactory jwtDecoderFactory = config.jwtDecoderFactory; OAuth2Error oauth2Error = new OAuth2Error("invalid_id_token", "Invalid ID Token", null); - when(jwtDecoderFactory.createDecoder(any())).thenReturn(token -> - Mono.error(new JwtValidationException("ID Token validation failed", Collections.singleton(oauth2Error)))); + when(jwtDecoderFactory.createDecoder(any())).thenReturn(token -> Mono + .error(new JwtValidationException("ID Token validation failed", Collections.singleton(oauth2Error)))); - webTestClient.get() - .uri("/login/oauth2/code/google") - .exchange() - .expectStatus() - .is3xxRedirection() - .expectHeader() - .valueEquals("Location", "/login?error"); + webTestClient.get().uri("/login/oauth2/code/google").exchange().expectStatus().is3xxRedirection().expectHeader() + .valueEquals("Location", "/login?error"); } @Configuration @@ -630,8 +589,8 @@ public class OAuth2LoginTests { ServerAuthenticationConverter authenticationConverter = mock(ServerAuthenticationConverter.class); - ReactiveOAuth2AccessTokenResponseClient tokenResponseClient = - mock(ReactiveOAuth2AccessTokenResponseClient.class); + ReactiveOAuth2AccessTokenResponseClient tokenResponseClient = mock( + ReactiveOAuth2AccessTokenResponseClient.class); ReactiveOAuth2UserService userService = mock(ReactiveOAuth2UserService.class); @@ -655,8 +614,8 @@ public class OAuth2LoginTests { } private ReactiveAuthenticationManager authenticationManager() { - OidcAuthorizationCodeReactiveAuthenticationManager oidc = - new OidcAuthorizationCodeReactiveAuthenticationManager(tokenResponseClient, userService); + OidcAuthorizationCodeReactiveAuthenticationManager oidc = new OidcAuthorizationCodeReactiveAuthenticationManager( + tokenResponseClient, userService); oidc.setJwtDecoderFactory(jwtDecoderFactory()); return oidc; } @@ -689,35 +648,34 @@ public class OAuth2LoginTests { return Mono.just(jwt); }; } + } + } @Test public void logoutWhenUsingOidcLogoutHandlerThenRedirects() { this.spring.register(OAuth2LoginConfigWithOidcLogoutSuccessHandler.class).autowire(); - OAuth2AuthenticationToken token = new OAuth2AuthenticationToken( - TestOidcUsers.create(), - AuthorityUtils.NO_AUTHORITIES, - getBean(ClientRegistration.class).getRegistrationId()); + OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(), + AuthorityUtils.NO_AUTHORITIES, getBean(ClientRegistration.class).getRegistrationId()); ServerSecurityContextRepository repository = getBean(ServerSecurityContextRepository.class); when(repository.load(any())).thenReturn(authentication(token)); - this.client.post().uri("/logout") - .exchange() - .expectHeader().valueEquals("Location", "https://logout?id_token_hint=id-token"); + this.client.post().uri("/logout").exchange().expectHeader().valueEquals("Location", + "https://logout?id_token_hint=id-token"); } @EnableWebFlux @EnableWebFluxSecurity static class OAuth2LoginConfigWithOidcLogoutSuccessHandler { - private final ServerSecurityContextRepository repository = - mock(ServerSecurityContextRepository.class); - private final ClientRegistration withLogout = - TestClientRegistrations.clientRegistration() - .providerConfigurationMetadata(Collections.singletonMap( - "end_session_endpoint", "https://logout")).build(); + + private final ServerSecurityContextRepository repository = mock(ServerSecurityContextRepository.class); + + private final ClientRegistration withLogout = TestClientRegistrations.clientRegistration() + .providerConfigurationMetadata(Collections.singletonMap("end_session_endpoint", "https://logout")) + .build(); @Bean public SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { @@ -745,6 +703,7 @@ public class OAuth2LoginTests { ClientRegistration clientRegistration() { return this.withLogout; } + } // gh-8609 @@ -752,16 +711,9 @@ public class OAuth2LoginTests { public void oauth2LoginWhenAuthenticationConverterFailsThenDefaultRedirectToLogin() { this.spring.register(OAuth2LoginWithMultipleClientRegistrations.class).autowire(); - WebTestClient webTestClient = WebTestClientBuilder - .bindToWebFilters(this.springSecurity) - .build(); + WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(this.springSecurity).build(); - webTestClient.get() - .uri("/login/oauth2/code/google") - .exchange() - .expectStatus() - .is3xxRedirection() - .expectHeader() + webTestClient.get().uri("/login/oauth2/code/google").exchange().expectStatus().is3xxRedirection().expectHeader() .valueEquals("Location", "/login?error"); } @@ -774,6 +726,7 @@ public class OAuth2LoginTests { } return chain.filter(exchange); } + } Mono authentication(Authentication authentication) { diff --git a/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java b/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java index f0e1f3765a..aa1d2cdc47 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java @@ -88,10 +88,12 @@ import static org.mockito.Mockito.when; import static org.springframework.security.oauth2.jwt.TestJwts.jwt; /** - * Tests for {@link org.springframework.security.config.web.server.ServerHttpSecurity.OAuth2ResourceServerSpec} + * Tests for + * {@link org.springframework.security.config.web.server.ServerHttpSecurity.OAuth2ResourceServerSpec} */ @RunWith(SpringRunner.class) public class OAuth2ResourceServerSpecTests { + private String expired = "eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE1MzUwMzc4OTd9.jqZDDjfc2eysX44lHXEIr9XFd2S8vjIZHCccZU-dRWMRJNsQ1QN5VNnJGklqJBXJR4qgla6cmVqPOLkUHDb0sL0nxM5XuzQaG5ZzKP81RV88shFyAiT0fD-6nl1k-Fai-Fu-VkzSpNXgeONoTxDaYhdB-yxmgrgsApgmbOTE_9AcMk-FQDXQ-pL9kynccFGV0lZx4CA7cyknKN7KBxUilfIycvXODwgKCjj_1WddLTCNGYogJJSg__7NoxzqbyWd3udbHVjqYq7GsMMrGB4_2kBD4CkghOSNcRHbT_DIXowxfAVT7PAg7Q0E5ruZsr2zPZacEUDhJ6-wbvlA0FAOUg"; private String messageReadToken = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJtb2NrLXN1YmplY3QiLCJzY29wZSI6Im1lc3NhZ2U6cmVhZCIsImV4cCI6NDY4ODY0MTQxM30.cRl1bv_dDYcAN5U4NlIVKj8uu4mLMwjABF93P4dShiq-GQ-owzaqTSlB4YarNFgV3PKQvT9wxN1jBpGribvISljakoC0E8wDV-saDi8WxN-qvImYsn1zLzYFiZXCfRIxCmonJpydeiAPRxMTPtwnYDS9Ib0T_iA80TBGd-INhyxUUfrwRW5sqKRbjUciRJhpp7fW2ZYXmi9iPt3HDjRQA4IloJZ7f4-spt5Q9wl5HcQTv1t4XrX4eqhVbE5cCoIkFQnKPOc-jhVM44_eazLU6Xk-CCXP8C_UT5pX0luRS2cJrVFfHp2IR_AWxC-shItg6LNEmNFD4Zc-JLZcr0Q86Q"; @@ -100,35 +102,23 @@ public class OAuth2ResourceServerSpecTests { private String unsignedToken = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJleHAiOi0yMDMzMjI0OTcsImp0aSI6IjEyMyIsInR5cCI6IkpXVCJ9."; - private String jwkSet = "{\n" + - " \"keys\":[\n" + - " {\n" + - " \"kty\":\"RSA\",\n" + - " \"e\":\"AQAB\",\n" + - " \"use\":\"sig\",\n" + - " \"kid\":\"one\",\n" + - " \"n\":\"0IUjrPZDz-3z0UE4ppcKU36v7hnh8FJjhu3lbJYj0qj9eZiwEJxi9HHUfSK1DhUQG7mJBbYTK1tPYCgre5EkfKh-64VhYUa-vz17zYCmuB8fFj4XHE3MLkWIG-AUn8hNbPzYYmiBTjfGnMKxLHjsbdTiF4mtn-85w366916R6midnAuiPD4HjZaZ1PAsuY60gr8bhMEDtJ8unz81hoQrozpBZJ6r8aR1PrsWb1OqPMloK9kAIutJNvWYKacp8WYAp2WWy72PxQ7Fb0eIA1br3A5dnp-Cln6JROJcZUIRJ-QvS6QONWeS2407uQmS-i-lybsqaH0ldYC7NBEBA5inPQ\"\n" + - " }\n" + - " ]\n" + - "}\n"; + private String jwkSet = "{\n" + " \"keys\":[\n" + " {\n" + " \"kty\":\"RSA\",\n" + + " \"e\":\"AQAB\",\n" + " \"use\":\"sig\",\n" + " \"kid\":\"one\",\n" + + " \"n\":\"0IUjrPZDz-3z0UE4ppcKU36v7hnh8FJjhu3lbJYj0qj9eZiwEJxi9HHUfSK1DhUQG7mJBbYTK1tPYCgre5EkfKh-64VhYUa-vz17zYCmuB8fFj4XHE3MLkWIG-AUn8hNbPzYYmiBTjfGnMKxLHjsbdTiF4mtn-85w366916R6midnAuiPD4HjZaZ1PAsuY60gr8bhMEDtJ8unz81hoQrozpBZJ6r8aR1PrsWb1OqPMloK9kAIutJNvWYKacp8WYAp2WWy72PxQ7Fb0eIA1br3A5dnp-Cln6JROJcZUIRJ-QvS6QONWeS2407uQmS-i-lybsqaH0ldYC7NBEBA5inPQ\"\n" + + " }\n" + " ]\n" + "}\n"; private Jwt jwt = jwt().build(); private String clientId = "client"; - private String clientSecret = "secret"; - private String active = "{\n" + - " \"active\": true,\n" + - " \"client_id\": \"l238j323ds-23ij4\",\n" + - " \"username\": \"jdoe\",\n" + - " \"scope\": \"read write dolphin\",\n" + - " \"sub\": \"Z5O3upPC88QrAjx00dis\",\n" + - " \"aud\": \"https://protected.example.net/resource\",\n" + - " \"iss\": \"https://server.example.com/\",\n" + - " \"exp\": 1419356238,\n" + - " \"iat\": 1419350238,\n" + - " \"extension_field\": \"twenty-seven\"\n" + - " }"; + private String clientSecret = "secret"; + + private String active = "{\n" + " \"active\": true,\n" + " \"client_id\": \"l238j323ds-23ij4\",\n" + + " \"username\": \"jdoe\",\n" + " \"scope\": \"read write dolphin\",\n" + + " \"sub\": \"Z5O3upPC88QrAjx00dis\",\n" + + " \"aud\": \"https://protected.example.net/resource\",\n" + + " \"iss\": \"https://server.example.com/\",\n" + " \"exp\": 1419356238,\n" + + " \"iat\": 1419350238,\n" + " \"extension_field\": \"twenty-seven\"\n" + " }"; @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -144,74 +134,60 @@ public class OAuth2ResourceServerSpecTests { public void getWhenValidThenReturnsOk() { this.spring.register(PublicKeyConfig.class, RootController.class).autowire(); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.messageReadToken)) - .exchange() - .expectStatus().isOk(); + this.client.get().headers(headers -> headers.setBearerAuth(this.messageReadToken)).exchange().expectStatus() + .isOk(); } @Test public void getWhenExpiredThenReturnsInvalidToken() { this.spring.register(PublicKeyConfig.class).autowire(); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.expired)) - .exchange() - .expectStatus().isUnauthorized() - .expectHeader().value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"invalid_token\"")); + this.client.get().headers(headers -> headers.setBearerAuth(this.expired)).exchange().expectStatus() + .isUnauthorized().expectHeader() + .value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"invalid_token\"")); } @Test public void getWhenUnsignedThenReturnsInvalidToken() { this.spring.register(PublicKeyConfig.class).autowire(); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.unsignedToken)) - .exchange() - .expectStatus().isUnauthorized() - .expectHeader().value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"invalid_token\"")); + this.client.get().headers(headers -> headers.setBearerAuth(this.unsignedToken)).exchange().expectStatus() + .isUnauthorized().expectHeader() + .value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"invalid_token\"")); } @Test public void getWhenEmptyBearerTokenThenReturnsInvalidToken() { this.spring.register(PublicKeyConfig.class).autowire(); - this.client.get() - .headers(headers -> headers.add("Authorization", "Bearer ")) - .exchange() - .expectStatus().isUnauthorized() - .expectHeader().value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"invalid_token\"")); + this.client.get().headers(headers -> headers.add("Authorization", "Bearer ")).exchange().expectStatus() + .isUnauthorized().expectHeader() + .value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"invalid_token\"")); } @Test public void getWhenValidTokenAndPublicKeyInLambdaThenReturnsOk() { this.spring.register(PublicKeyInLambdaConfig.class, RootController.class).autowire(); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.messageReadToken)) - .exchange() - .expectStatus().isOk(); + this.client.get().headers(headers -> headers.setBearerAuth(this.messageReadToken)).exchange().expectStatus() + .isOk(); } @Test public void getWhenExpiredTokenAndPublicKeyInLambdaThenReturnsInvalidToken() { this.spring.register(PublicKeyInLambdaConfig.class).autowire(); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.expired)) - .exchange() - .expectStatus().isUnauthorized() - .expectHeader().value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"invalid_token\"")); + this.client.get().headers(headers -> headers.setBearerAuth(this.expired)).exchange().expectStatus() + .isUnauthorized().expectHeader() + .value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"invalid_token\"")); } @Test public void getWhenValidUsingPlaceholderThenReturnsOk() { this.spring.register(PlaceholderConfig.class, RootController.class).autowire(); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.messageReadToken)) - .exchange() - .expectStatus().isOk(); + this.client.get().headers(headers -> headers.setBearerAuth(this.messageReadToken)).exchange().expectStatus() + .isOk(); } @Test @@ -221,10 +197,7 @@ public class OAuth2ResourceServerSpecTests { ReactiveJwtDecoder jwtDecoder = this.spring.getContext().getBean(ReactiveJwtDecoder.class); when(jwtDecoder.decode(anyString())).thenReturn(Mono.just(this.jwt)); - this.client.get() - .headers(headers -> headers.setBearerAuth("token")) - .exchange() - .expectStatus().isOk(); + this.client.get().headers(headers -> headers.setBearerAuth("token")).exchange().expectStatus().isOk(); verify(jwtDecoder).decode(anyString()); } @@ -236,9 +209,7 @@ public class OAuth2ResourceServerSpecTests { MockWebServer mockWebServer = this.spring.getContext().getBean(MockWebServer.class); mockWebServer.enqueue(new MockResponse().setBody(this.jwkSet)); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.messageReadTokenWithKid)) - .exchange() + this.client.get().headers(headers -> headers.setBearerAuth(this.messageReadTokenWithKid)).exchange() .expectStatus().isOk(); } @@ -249,9 +220,7 @@ public class OAuth2ResourceServerSpecTests { MockWebServer mockWebServer = this.spring.getContext().getBean(MockWebServer.class); mockWebServer.enqueue(new MockResponse().setBody(this.jwkSet)); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.messageReadTokenWithKid)) - .exchange() + this.client.get().headers(headers -> headers.setBearerAuth(this.messageReadTokenWithKid)).exchange() .expectStatus().isOk(); } @@ -259,125 +228,102 @@ public class OAuth2ResourceServerSpecTests { public void getWhenUsingCustomAuthenticationManagerThenUsesItAccordingly() { this.spring.register(CustomAuthenticationManagerConfig.class).autowire(); - ReactiveAuthenticationManager authenticationManager = this.spring.getContext().getBean( - ReactiveAuthenticationManager.class); + ReactiveAuthenticationManager authenticationManager = this.spring.getContext() + .getBean(ReactiveAuthenticationManager.class); when(authenticationManager.authenticate(any(Authentication.class))) .thenReturn(Mono.error(new OAuth2AuthenticationException(new OAuth2Error("mock-failure")))); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.messageReadToken)) - .exchange() - .expectStatus().isUnauthorized() - .expectHeader().value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"mock-failure\"")); + this.client.get().headers(headers -> headers.setBearerAuth(this.messageReadToken)).exchange().expectStatus() + .isUnauthorized().expectHeader() + .value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"mock-failure\"")); } @Test public void getWhenUsingCustomAuthenticationManagerInLambdaThenUsesItAccordingly() { this.spring.register(CustomAuthenticationManagerInLambdaConfig.class).autowire(); - ReactiveAuthenticationManager authenticationManager = this.spring.getContext().getBean( - ReactiveAuthenticationManager.class); + ReactiveAuthenticationManager authenticationManager = this.spring.getContext() + .getBean(ReactiveAuthenticationManager.class); when(authenticationManager.authenticate(any(Authentication.class))) .thenReturn(Mono.error(new OAuth2AuthenticationException(new OAuth2Error("mock-failure")))); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.messageReadToken)) - .exchange() - .expectStatus().isUnauthorized() - .expectHeader().value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"mock-failure\"")); + this.client.get().headers(headers -> headers.setBearerAuth(this.messageReadToken)).exchange().expectStatus() + .isUnauthorized().expectHeader() + .value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"mock-failure\"")); } @Test public void getWhenUsingCustomAuthenticationManagerResolverThenUsesItAccordingly() { this.spring.register(CustomAuthenticationManagerResolverConfig.class).autowire(); - ReactiveAuthenticationManagerResolver authenticationManagerResolver = - this.spring.getContext().getBean(ReactiveAuthenticationManagerResolver.class); + ReactiveAuthenticationManagerResolver authenticationManagerResolver = this.spring + .getContext().getBean(ReactiveAuthenticationManagerResolver.class); - ReactiveAuthenticationManager authenticationManager = - this.spring.getContext().getBean(ReactiveAuthenticationManager.class); + ReactiveAuthenticationManager authenticationManager = this.spring.getContext() + .getBean(ReactiveAuthenticationManager.class); when(authenticationManagerResolver.resolve(any(ServerWebExchange.class))) - .thenReturn(Mono.just(authenticationManager)); + .thenReturn(Mono.just(authenticationManager)); when(authenticationManager.authenticate(any(Authentication.class))) - .thenReturn(Mono.error(new OAuth2AuthenticationException(new OAuth2Error("mock-failure")))); + .thenReturn(Mono.error(new OAuth2AuthenticationException(new OAuth2Error("mock-failure")))); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.messageReadToken)) - .exchange() - .expectStatus().isUnauthorized() - .expectHeader().value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"mock-failure\"")); + this.client.get().headers(headers -> headers.setBearerAuth(this.messageReadToken)).exchange().expectStatus() + .isUnauthorized().expectHeader() + .value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"mock-failure\"")); } @Test public void postWhenSignedThenReturnsOk() { this.spring.register(PublicKeyConfig.class, RootController.class).autowire(); - this.client.post() - .headers(headers -> headers.setBearerAuth(this.messageReadToken)) - .exchange() - .expectStatus().isOk(); + this.client.post().headers(headers -> headers.setBearerAuth(this.messageReadToken)).exchange().expectStatus() + .isOk(); } @Test public void getWhenTokenHasInsufficientScopeThenReturnsInsufficientScope() { this.spring.register(DenyAllConfig.class, RootController.class).autowire(); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.messageReadToken)) - .exchange() - .expectStatus().isForbidden() - .expectHeader().value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"insufficient_scope\"")); + this.client.get().headers(headers -> headers.setBearerAuth(this.messageReadToken)).exchange().expectStatus() + .isForbidden().expectHeader() + .value(HttpHeaders.WWW_AUTHENTICATE, startsWith("Bearer error=\"insufficient_scope\"")); } @Test public void postWhenMissingTokenThenReturnsForbidden() { this.spring.register(PublicKeyConfig.class, RootController.class).autowire(); - this.client.post() - .exchange() - .expectStatus().isForbidden(); + this.client.post().exchange().expectStatus().isForbidden(); } @Test public void getWhenCustomBearerTokenServerAuthenticationConverterThenResponds() { this.spring.register(CustomBearerTokenServerAuthenticationConverter.class, RootController.class).autowire(); - this.client.get() - .cookie("TOKEN", this.messageReadToken) - .exchange() - .expectStatus().isOk(); + this.client.get().cookie("TOKEN", this.messageReadToken).exchange().expectStatus().isOk(); } @Test public void getWhenSignedAndCustomConverterThenConverts() { this.spring.register(CustomJwtAuthenticationConverterConfig.class, RootController.class).autowire(); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.messageReadToken)) - .exchange() - .expectStatus().isOk(); + this.client.get().headers(headers -> headers.setBearerAuth(this.messageReadToken)).exchange().expectStatus() + .isOk(); } @Test public void getWhenCustomBearerTokenEntryPointThenResponds() { this.spring.register(CustomErrorHandlingConfig.class).autowire(); - this.client.get() - .uri("/authenticated") - .exchange() - .expectStatus().isEqualTo(HttpStatus.I_AM_A_TEAPOT); + this.client.get().uri("/authenticated").exchange().expectStatus().isEqualTo(HttpStatus.I_AM_A_TEAPOT); } @Test public void getWhenCustomBearerTokenDeniedHandlerThenResponds() { this.spring.register(CustomErrorHandlingConfig.class).autowire(); - this.client.get() - .uri("/unobtainable") - .headers(headers -> headers.setBearerAuth(this.messageReadToken)) - .exchange() - .expectStatus().isEqualTo(HttpStatus.BANDWIDTH_LIMIT_EXCEEDED); + this.client.get().uri("/unobtainable").headers(headers -> headers.setBearerAuth(this.messageReadToken)) + .exchange().expectStatus().isEqualTo(HttpStatus.BANDWIDTH_LIMIT_EXCEEDED); } @Test @@ -425,8 +371,7 @@ public class OAuth2ResourceServerSpecTests { ServerHttpSecurity.OAuth2ResourceServerSpec.JwtSpec jwt = http.oauth2ResourceServer().jwt(); - assertThatCode(() -> jwt.getJwtDecoder()) - .isInstanceOf(NoUniqueBeanDefinitionException.class); + assertThatCode(() -> jwt.getJwtDecoder()).isInstanceOf(NoUniqueBeanDefinitionException.class); } @Test @@ -437,8 +382,7 @@ public class OAuth2ResourceServerSpecTests { ServerHttpSecurity.OAuth2ResourceServerSpec.JwtSpec jwt = http.oauth2ResourceServer().jwt(); - assertThatCode(() -> jwt.getJwtDecoder()) - .isInstanceOf(NoSuchBeanDefinitionException.class); + assertThatCode(() -> jwt.getJwtDecoder()).isInstanceOf(NoSuchBeanDefinitionException.class); } @Test @@ -447,10 +391,8 @@ public class OAuth2ResourceServerSpecTests { this.spring.getContext().getBean(MockWebServer.class) .setDispatcher(requiresAuth(clientId, clientSecret, active)); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.messageReadToken)) - .exchange() - .expectStatus().isOk(); + this.client.get().headers(headers -> headers.setBearerAuth(this.messageReadToken)).exchange().expectStatus() + .isOk(); } @Test @@ -459,22 +401,20 @@ public class OAuth2ResourceServerSpecTests { this.spring.getContext().getBean(MockWebServer.class) .setDispatcher(requiresAuth(clientId, clientSecret, active)); - this.client.get() - .headers(headers -> headers.setBearerAuth(this.messageReadToken)) - .exchange() - .expectStatus().isOk(); + this.client.get().headers(headers -> headers.setBearerAuth(this.messageReadToken)).exchange().expectStatus() + .isOk(); } @Test public void configureWhenUsingBothAuthenticationManagerResolverAndOpaqueThenWiringException() { assertThatCode(() -> this.spring.register(AuthenticationManagerResolverPlusOtherConfig.class).autowire()) - .isInstanceOf(BeanCreationException.class) - .hasMessageContaining("authenticationManagerResolver"); + .isInstanceOf(BeanCreationException.class).hasMessageContaining("authenticationManagerResolver"); } @EnableWebFlux @EnableWebFluxSecurity static class PublicKeyConfig { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -488,11 +428,13 @@ public class OAuth2ResourceServerSpecTests { // @formatter:on return http.build(); } + } @EnableWebFlux @EnableWebFluxSecurity static class PublicKeyInLambdaConfig { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -511,11 +453,13 @@ public class OAuth2ResourceServerSpecTests { // @formatter:on return http.build(); } + } @EnableWebFlux @EnableWebFluxSecurity static class PlaceholderConfig { + @Value("${classpath:org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests-simple.pub}") RSAPublicKey key; @@ -532,11 +476,13 @@ public class OAuth2ResourceServerSpecTests { // @formatter:on return http.build(); } + } @EnableWebFlux @EnableWebFluxSecurity static class JwkSetUriConfig { + private MockWebServer mockWebServer = new MockWebServer(); @Bean @@ -562,11 +508,13 @@ public class OAuth2ResourceServerSpecTests { void shutdown() throws IOException { this.mockWebServer.shutdown(); } + } @EnableWebFlux @EnableWebFluxSecurity static class JwkSetUriInLambdaConfig { + private MockWebServer mockWebServer = new MockWebServer(); @Bean @@ -596,11 +544,13 @@ public class OAuth2ResourceServerSpecTests { void shutdown() throws IOException { this.mockWebServer.shutdown(); } + } @EnableWebFlux @EnableWebFluxSecurity static class CustomDecoderConfig { + ReactiveJwtDecoder jwtDecoder = mock(ReactiveJwtDecoder.class); @Bean @@ -618,11 +568,13 @@ public class OAuth2ResourceServerSpecTests { ReactiveJwtDecoder jwtDecoder() { return this.jwtDecoder; } + } @EnableWebFlux @EnableWebFluxSecurity static class DenyAllConfig { + @Bean SecurityWebFilterChain authorization(ServerHttpSecurity http) { // @formatter:off @@ -637,11 +589,13 @@ public class OAuth2ResourceServerSpecTests { return http.build(); } + } @EnableWebFlux @EnableWebFluxSecurity static class CustomAuthenticationManagerConfig { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -658,11 +612,13 @@ public class OAuth2ResourceServerSpecTests { ReactiveAuthenticationManager authenticationManager() { return mock(ReactiveAuthenticationManager.class); } + } @EnableWebFlux @EnableWebFluxSecurity static class CustomAuthenticationManagerInLambdaConfig { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -683,11 +639,13 @@ public class OAuth2ResourceServerSpecTests { ReactiveAuthenticationManager authenticationManager() { return mock(ReactiveAuthenticationManager.class); } + } @EnableWebFlux @EnableWebFluxSecurity static class CustomAuthenticationManagerResolverConfig { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -711,11 +669,13 @@ public class OAuth2ResourceServerSpecTests { ReactiveAuthenticationManager authenticationManager() { return mock(ReactiveAuthenticationManager.class); } + } @EnableWebFlux @EnableWebFluxSecurity static class CustomBearerTokenServerAuthenticationConverter { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -737,11 +697,13 @@ public class OAuth2ResourceServerSpecTests { return exchange -> Mono.justOrEmpty(exchange.getRequest().getCookies().getFirst("TOKEN").getValue()) .map(BearerTokenAuthenticationToken::new); } + } @EnableWebFlux @EnableWebFluxSecurity static class CustomJwtAuthenticationConverterConfig { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -763,17 +725,19 @@ public class OAuth2ResourceServerSpecTests { JwtAuthenticationConverter converter = new JwtAuthenticationConverter(); converter.setJwtGrantedAuthoritiesConverter(jwt -> { - String[] claims = ((String) jwt.getClaims().get("scope")).split(" "); - return Stream.of(claims).map(SimpleGrantedAuthority::new).collect(Collectors.toList()); - }); + String[] claims = ((String) jwt.getClaims().get("scope")).split(" "); + return Stream.of(claims).map(SimpleGrantedAuthority::new).collect(Collectors.toList()); + }); return new ReactiveJwtAuthenticationConverterAdapter(converter); } + } @EnableWebFlux @EnableWebFluxSecurity static class CustomErrorHandlingConfig { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -791,11 +755,13 @@ public class OAuth2ResourceServerSpecTests { return http.build(); } + } @EnableWebFlux @EnableWebFluxSecurity static class IntrospectionConfig { + private MockWebServer mockWebServer = new MockWebServer(); @Bean @@ -822,11 +788,13 @@ public class OAuth2ResourceServerSpecTests { void shutdown() throws IOException { this.mockWebServer.shutdown(); } + } @EnableWebFlux @EnableWebFluxSecurity static class IntrospectionInLambdaConfig { + private MockWebServer mockWebServer = new MockWebServer(); @Bean @@ -857,11 +825,13 @@ public class OAuth2ResourceServerSpecTests { void shutdown() throws IOException { this.mockWebServer.shutdown(); } + } @EnableWebFlux @EnableWebFluxSecurity static class AuthenticationManagerResolverPlusOtherConfig { + @Bean SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { // @formatter:off @@ -876,10 +846,12 @@ public class OAuth2ResourceServerSpecTests { return http.build(); } + } @RestController static class RootController { + @GetMapping Mono get() { return Mono.just("ok"); @@ -889,6 +861,7 @@ public class OAuth2ResourceServerSpecTests { Mono post() { return Mono.just("ok"); } + } private static Dispatcher requiresAuth(String username, String password, String response) { @@ -896,10 +869,8 @@ public class OAuth2ResourceServerSpecTests { @Override public MockResponse dispatch(RecordedRequest request) { String authorization = request.getHeader(org.springframework.http.HttpHeaders.AUTHORIZATION); - return Optional.ofNullable(authorization) - .filter(a -> isAuthorized(authorization, username, password)) - .map(a -> ok(response)) - .orElse(unauthorized()); + return Optional.ofNullable(authorization).filter(a -> isAuthorized(authorization, username, password)) + .map(a -> ok(response)).orElse(unauthorized()); } }; } @@ -910,8 +881,8 @@ public class OAuth2ResourceServerSpecTests { } private static MockResponse ok(String response) { - return new MockResponse().setBody(response) - .setHeader(org.springframework.http.HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + return new MockResponse().setBody(response).setHeader(org.springframework.http.HttpHeaders.CONTENT_TYPE, + MediaType.APPLICATION_JSON_VALUE); } private static MockResponse unauthorized() { @@ -927,7 +898,8 @@ public class OAuth2ResourceServerSpecTests { try { KeyFactory factory = KeyFactory.getInstance("RSA"); rsaPublicKey = (RSAPublicKey) factory.generatePublic(spec); - } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + } + catch (NoSuchAlgorithmException | InvalidKeySpecException e) { e.printStackTrace(); } return rsaPublicKey; @@ -939,4 +911,5 @@ public class OAuth2ResourceServerSpecTests { this.spring.context(context).autowire(); return (GenericWebApplicationContext) this.spring.getContext(); } + } diff --git a/config/src/test/java/org/springframework/security/config/web/server/RequestCacheTests.java b/config/src/test/java/org/springframework/security/config/web/server/RequestCacheTests.java index 9f0d9a09ec..2cc9464701 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/RequestCacheTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/RequestCacheTests.java @@ -41,65 +41,41 @@ import static org.springframework.security.config.Customizer.withDefaults; * @since 5.0 */ public class RequestCacheTests { + private ServerHttpSecurity http = ServerHttpSecurityConfigurationBuilder.httpWithDefaultAuthentication(); @Test public void defaultFormLoginRequestCache() { - SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange() - .anyExchange().authenticated() - .and() - .formLogin().and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.authorizeExchange().anyExchange().authenticated().and() + .formLogin().and().build(); WebTestClient webTestClient = WebTestClient - .bindToController(new SecuredPageController(), new WebTestClientBuilder.Http200RestController()) - .webFilter(new WebFilterChainProxy(securityWebFilter)) - .build(); + .bindToController(new SecuredPageController(), new WebTestClientBuilder.Http200RestController()) + .webFilter(new WebFilterChainProxy(securityWebFilter)).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - DefaultLoginPage loginPage = SecuredPage.to(driver, DefaultLoginPage.class) - .assertAt(); + DefaultLoginPage loginPage = SecuredPage.to(driver, DefaultLoginPage.class).assertAt(); - SecuredPage securedPage = loginPage.loginForm() - .username("user") - .password("password") - .submit(SecuredPage.class); + SecuredPage securedPage = loginPage.loginForm().username("user").password("password").submit(SecuredPage.class); securedPage.assertAt(); } @Test public void requestCacheNoOp() { - SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange() - .anyExchange().authenticated() - .and() - .formLogin().and() - .requestCache() - .requestCache(NoOpServerRequestCache.getInstance()) - .and() - .build(); + SecurityWebFilterChain securityWebFilter = this.http.authorizeExchange().anyExchange().authenticated().and() + .formLogin().and().requestCache().requestCache(NoOpServerRequestCache.getInstance()).and().build(); WebTestClient webTestClient = WebTestClient - .bindToController(new SecuredPageController(), new WebTestClientBuilder.Http200RestController()) - .webFilter(new WebFilterChainProxy(securityWebFilter)) - .build(); + .bindToController(new SecuredPageController(), new WebTestClientBuilder.Http200RestController()) + .webFilter(new WebFilterChainProxy(securityWebFilter)).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - DefaultLoginPage loginPage = SecuredPage.to(driver, DefaultLoginPage.class) - .assertAt(); + DefaultLoginPage loginPage = SecuredPage.to(driver, DefaultLoginPage.class).assertAt(); - HomePage securedPage = loginPage.loginForm() - .username("user") - .password("password") - .submit(HomePage.class); + HomePage securedPage = loginPage.loginForm().username("user").password("password").submit(HomePage.class); securedPage.assertAt(); } @@ -107,38 +83,25 @@ public class RequestCacheTests { @Test public void requestWhenCustomRequestCacheInLambdaThenCustomCacheUsed() { SecurityWebFilterChain securityWebFilter = this.http - .authorizeExchange(authorizeExchange -> - authorizeExchange - .anyExchange().authenticated() - ) - .formLogin(withDefaults()) - .requestCache(requestCache -> - requestCache - .requestCache(NoOpServerRequestCache.getInstance()) - ) - .build(); + .authorizeExchange(authorizeExchange -> authorizeExchange.anyExchange().authenticated()) + .formLogin(withDefaults()) + .requestCache(requestCache -> requestCache.requestCache(NoOpServerRequestCache.getInstance())).build(); WebTestClient webTestClient = WebTestClient - .bindToController(new SecuredPageController(), new WebTestClientBuilder.Http200RestController()) - .webFilter(new WebFilterChainProxy(securityWebFilter)) - .build(); + .bindToController(new SecuredPageController(), new WebTestClientBuilder.Http200RestController()) + .webFilter(new WebFilterChainProxy(securityWebFilter)).build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient) - .build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); - DefaultLoginPage loginPage = SecuredPage.to(driver, DefaultLoginPage.class) - .assertAt(); + DefaultLoginPage loginPage = SecuredPage.to(driver, DefaultLoginPage.class).assertAt(); - HomePage securedPage = loginPage.loginForm() - .username("user") - .password("password") - .submit(HomePage.class); + HomePage securedPage = loginPage.loginForm().username("user").password("password").submit(HomePage.class); securedPage.assertAt(); } public static class SecuredPage { + private WebDriver driver; public SecuredPage(WebDriver driver) { @@ -153,23 +116,19 @@ public class RequestCacheTests { driver.get("http://localhost/secured"); return PageFactory.initElements(driver, page); } + } @Controller public static class SecuredPageController { + @ResponseBody @GetMapping("/secured") public String login(ServerWebExchange exchange) { - return - "\n" - + "\n" - + " \n" - + " Secured\n" - + " \n" - + " \n" - + "

    Secured

    \n" - + " \n" - + ""; + return "\n" + "\n" + " \n" + " Secured\n" + + " \n" + " \n" + "

    Secured

    \n" + " \n" + ""; } + } + } diff --git a/config/src/test/java/org/springframework/security/config/web/server/ServerHttpSecurityTests.java b/config/src/test/java/org/springframework/security/config/web/server/ServerHttpSecurityTests.java index 052b6629a4..e63bbf13e5 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/ServerHttpSecurityTests.java +++ b/config/src/test/java/org/springframework/security/config/web/server/ServerHttpSecurityTests.java @@ -89,10 +89,13 @@ import org.springframework.security.web.server.authentication.HttpBasicServerAut */ @RunWith(MockitoJUnitRunner.class) public class ServerHttpSecurityTests { + @Mock private ServerSecurityContextRepository contextRepository; + @Mock private ReactiveAuthenticationManager authenticationManager; + @Mock private ServerCsrfTokenRepository csrfTokenRepository; @@ -100,8 +103,7 @@ public class ServerHttpSecurityTests { @Before public void setup() { - this.http = ServerHttpSecurityConfigurationBuilder.http() - .authenticationManager(this.authenticationManager); + this.http = ServerHttpSecurityConfigurationBuilder.http().authenticationManager(this.authenticationManager); } @Test @@ -112,11 +114,8 @@ public class ServerHttpSecurityTests { WebTestClient client = buildClient(); - FluxExchangeResult result = client.get() - .uri("/") - .exchange() - .expectHeader().valueMatches(HttpHeaders.CACHE_CONTROL, ".+") - .returnResult(String.class); + FluxExchangeResult result = client.get().uri("/").exchange().expectHeader() + .valueMatches(HttpHeaders.CACHE_CONTROL, ".+").returnResult(String.class); assertThat(result.getResponseCookies()).isEmpty(); // there is no need to try and load the SecurityContext by default @@ -125,7 +124,8 @@ public class ServerHttpSecurityTests { @Test public void basic() { - given(this.authenticationManager.authenticate(any())).willReturn(Mono.just(new TestingAuthenticationToken("rob", "rob", "ROLE_USER", "ROLE_ADMIN"))); + given(this.authenticationManager.authenticate(any())) + .willReturn(Mono.just(new TestingAuthenticationToken("rob", "rob", "ROLE_USER", "ROLE_ADMIN"))); this.http.httpBasic(); this.http.authenticationManager(this.authenticationManager); @@ -134,21 +134,18 @@ public class ServerHttpSecurityTests { WebTestClient client = buildClient(); - EntityExchangeResult result = client.get() - .uri("/") - .headers(headers -> headers.setBasicAuth("rob", "rob")) - .exchange() - .expectStatus().isOk() - .expectHeader().valueMatches(HttpHeaders.CACHE_CONTROL, ".+") - .expectBody(String.class).consumeWith(b -> assertThat(b.getResponseBody()).isEqualTo("ok")) - .returnResult(); + EntityExchangeResult result = client.get().uri("/") + .headers(headers -> headers.setBasicAuth("rob", "rob")).exchange().expectStatus().isOk().expectHeader() + .valueMatches(HttpHeaders.CACHE_CONTROL, ".+").expectBody(String.class) + .consumeWith(b -> assertThat(b.getResponseBody()).isEqualTo("ok")).returnResult(); assertThat(result.getResponseCookies().getFirst("SESSION")).isNull(); } @Test public void basicWithGlobalWebSessionServerSecurityContextRepository() { - given(this.authenticationManager.authenticate(any())).willReturn(Mono.just(new TestingAuthenticationToken("rob", "rob", "ROLE_USER", "ROLE_ADMIN"))); + given(this.authenticationManager.authenticate(any())) + .willReturn(Mono.just(new TestingAuthenticationToken("rob", "rob", "ROLE_USER", "ROLE_ADMIN"))); this.http.securityContextRepository(new WebSessionServerSecurityContextRepository()); this.http.httpBasic(); @@ -158,14 +155,10 @@ public class ServerHttpSecurityTests { WebTestClient client = buildClient(); - EntityExchangeResult result = client.get() - .uri("/") - .headers(headers -> headers.setBasicAuth("rob", "rob")) - .exchange() - .expectStatus().isOk() - .expectHeader().valueMatches(HttpHeaders.CACHE_CONTROL, ".+") - .expectBody(String.class).consumeWith(b -> assertThat(b.getResponseBody()).isEqualTo("ok")) - .returnResult(); + EntityExchangeResult result = client.get().uri("/") + .headers(headers -> headers.setBasicAuth("rob", "rob")).exchange().expectStatus().isOk().expectHeader() + .valueMatches(HttpHeaders.CACHE_CONTROL, ".+").expectBody(String.class) + .consumeWith(b -> assertThat(b.getResponseBody()).isEqualTo("ok")).returnResult(); assertThat(result.getResponseCookies().getFirst("SESSION")).isNotNull(); } @@ -175,13 +168,8 @@ public class ServerHttpSecurityTests { this.http.authorizeExchange().anyExchange().authenticated(); WebTestClient client = buildClient(); - client - .get() - .uri("/") - .exchange() - .expectStatus().isUnauthorized() - .expectHeader().valueMatches(HttpHeaders.CACHE_CONTROL, ".+") - .expectBody().isEmpty(); + client.get().uri("/").exchange().expectStatus().isUnauthorized().expectHeader() + .valueMatches(HttpHeaders.CACHE_CONTROL, ".+").expectBody().isEmpty(); } @Test @@ -189,105 +177,93 @@ public class ServerHttpSecurityTests { SecurityWebFilterChain filter = this.http.build(); WebTestClient client = WebTestClient.bindToController(new SubscriberContextController()) - .webFilter(new WebFilterChainProxy(filter)) - .build(); + .webFilter(new WebFilterChainProxy(filter)).build(); - client.get().uri("/foo/bar") - .exchange() - .expectBody(String.class).isEqualTo("/foo/bar"); + client.get().uri("/foo/bar").exchange().expectBody(String.class).isEqualTo("/foo/bar"); } @Test public void csrfServerLogoutHandlerNotAppliedIfCsrfIsntEnabled() { SecurityWebFilterChain securityWebFilterChain = this.http.csrf().disable().build(); - assertThat(getWebFilter(securityWebFilterChain, CsrfWebFilter.class)) - .isNotPresent(); + assertThat(getWebFilter(securityWebFilterChain, CsrfWebFilter.class)).isNotPresent(); Optional logoutHandler = getWebFilter(securityWebFilterChain, LogoutWebFilter.class) - .map(logoutWebFilter -> (ServerLogoutHandler) getField(logoutWebFilter, LogoutWebFilter.class, "logoutHandler")); + .map(logoutWebFilter -> (ServerLogoutHandler) getField(logoutWebFilter, LogoutWebFilter.class, + "logoutHandler")); - assertThat(logoutHandler) - .get() - .isExactlyInstanceOf(SecurityContextServerLogoutHandler.class); + assertThat(logoutHandler).get().isExactlyInstanceOf(SecurityContextServerLogoutHandler.class); } @Test public void csrfServerLogoutHandlerAppliedIfCsrfIsEnabled() { - SecurityWebFilterChain securityWebFilterChain = this.http.csrf().csrfTokenRepository(this.csrfTokenRepository).and().build(); + SecurityWebFilterChain securityWebFilterChain = this.http.csrf().csrfTokenRepository(this.csrfTokenRepository) + .and().build(); - assertThat(getWebFilter(securityWebFilterChain, CsrfWebFilter.class)) - .get() + assertThat(getWebFilter(securityWebFilterChain, CsrfWebFilter.class)).get() .extracting(csrfWebFilter -> getField(csrfWebFilter, "csrfTokenRepository")) .isEqualTo(this.csrfTokenRepository); Optional logoutHandler = getWebFilter(securityWebFilterChain, LogoutWebFilter.class) - .map(logoutWebFilter -> (ServerLogoutHandler) getField(logoutWebFilter, LogoutWebFilter.class, "logoutHandler")); + .map(logoutWebFilter -> (ServerLogoutHandler) getField(logoutWebFilter, LogoutWebFilter.class, + "logoutHandler")); - assertThat(logoutHandler) - .get() - .isExactlyInstanceOf(DelegatingServerLogoutHandler.class) - .extracting(delegatingLogoutHandler -> - ((List) getField(delegatingLogoutHandler, DelegatingServerLogoutHandler.class, "delegates")).stream() - .map(ServerLogoutHandler::getClass) + assertThat(logoutHandler).get().isExactlyInstanceOf(DelegatingServerLogoutHandler.class) + .extracting(delegatingLogoutHandler -> ((List) getField(delegatingLogoutHandler, + DelegatingServerLogoutHandler.class, "delegates")).stream().map(ServerLogoutHandler::getClass) .collect(Collectors.toList())) .isEqualTo(Arrays.asList(SecurityContextServerLogoutHandler.class, CsrfServerLogoutHandler.class)); } @Test @SuppressWarnings("unchecked") - public void addFilterAfterIsApplied(){ - SecurityWebFilterChain securityWebFilterChain = this.http.addFilterAfter(new TestWebFilter(), SecurityWebFiltersOrder.SECURITY_CONTEXT_SERVER_WEB_EXCHANGE).build(); + public void addFilterAfterIsApplied() { + SecurityWebFilterChain securityWebFilterChain = this.http + .addFilterAfter(new TestWebFilter(), SecurityWebFiltersOrder.SECURITY_CONTEXT_SERVER_WEB_EXCHANGE) + .build(); List filters = securityWebFilterChain.getWebFilters().map(WebFilter::getClass).collectList().block(); - assertThat(filters).isNotNull() - .isNotEmpty() - .containsSequence(SecurityContextServerWebExchangeWebFilter.class, TestWebFilter.class); + assertThat(filters).isNotNull().isNotEmpty().containsSequence(SecurityContextServerWebExchangeWebFilter.class, + TestWebFilter.class); } @Test @SuppressWarnings("unchecked") - public void addFilterBeforeIsApplied(){ - SecurityWebFilterChain securityWebFilterChain = this.http.addFilterBefore(new TestWebFilter(), SecurityWebFiltersOrder.SECURITY_CONTEXT_SERVER_WEB_EXCHANGE).build(); + public void addFilterBeforeIsApplied() { + SecurityWebFilterChain securityWebFilterChain = this.http + .addFilterBefore(new TestWebFilter(), SecurityWebFiltersOrder.SECURITY_CONTEXT_SERVER_WEB_EXCHANGE) + .build(); List filters = securityWebFilterChain.getWebFilters().map(WebFilter::getClass).collectList().block(); - assertThat(filters).isNotNull() - .isNotEmpty() - .containsSequence(TestWebFilter.class, SecurityContextServerWebExchangeWebFilter.class); + assertThat(filters).isNotNull().isNotEmpty().containsSequence(TestWebFilter.class, + SecurityContextServerWebExchangeWebFilter.class); } @Test - public void anonymous(){ + public void anonymous() { SecurityWebFilterChain securityFilterChain = this.http.anonymous().and().build(); - WebTestClient client = WebTestClientBuilder.bindToControllerAndWebFilters(AnonymousAuthenticationWebFilterTests.HttpMeController.class, - securityFilterChain).build(); + WebTestClient client = WebTestClientBuilder.bindToControllerAndWebFilters( + AnonymousAuthenticationWebFilterTests.HttpMeController.class, securityFilterChain).build(); - client.get() - .uri("/me") - .exchange() - .expectStatus().isOk() - .expectBody(String.class).isEqualTo("anonymousUser"); + client.get().uri("/me").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("anonymousUser"); } @Test public void getWhenAnonymousConfiguredThenAuthenticationIsAnonymous() { SecurityWebFilterChain securityFilterChain = this.http.anonymous(withDefaults()).build(); - WebTestClient client = WebTestClientBuilder.bindToControllerAndWebFilters(AnonymousAuthenticationWebFilterTests.HttpMeController.class, - securityFilterChain).build(); + WebTestClient client = WebTestClientBuilder.bindToControllerAndWebFilters( + AnonymousAuthenticationWebFilterTests.HttpMeController.class, securityFilterChain).build(); - client.get() - .uri("/me") - .exchange() - .expectStatus().isOk() - .expectBody(String.class).isEqualTo("anonymousUser"); + client.get().uri("/me").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("anonymousUser"); } @Test public void basicWithAnonymous() { - given(this.authenticationManager.authenticate(any())).willReturn(Mono.just(new TestingAuthenticationToken("rob", "rob", "ROLE_USER", "ROLE_ADMIN"))); + given(this.authenticationManager.authenticate(any())) + .willReturn(Mono.just(new TestingAuthenticationToken("rob", "rob", "ROLE_USER", "ROLE_ADMIN"))); this.http.httpBasic().and().anonymous(); this.http.authenticationManager(this.authenticationManager); @@ -296,14 +272,10 @@ public class ServerHttpSecurityTests { WebTestClient client = buildClient(); - EntityExchangeResult result = client.get() - .uri("/") - .headers(headers -> headers.setBasicAuth("rob", "rob")) - .exchange() - .expectStatus().isOk() - .expectHeader().valueMatches(HttpHeaders.CACHE_CONTROL, ".+") - .expectBody(String.class).consumeWith(b -> assertThat(b.getResponseBody()).isEqualTo("ok")) - .returnResult(); + EntityExchangeResult result = client.get().uri("/") + .headers(headers -> headers.setBasicAuth("rob", "rob")).exchange().expectStatus().isOk().expectHeader() + .valueMatches(HttpHeaders.CACHE_CONTROL, ".+").expectBody(String.class) + .consumeWith(b -> assertThat(b.getResponseBody()).isEqualTo("ok")).returnResult(); assertThat(result.getResponseCookies().getFirst("SESSION")).isNull(); } @@ -320,13 +292,9 @@ public class ServerHttpSecurityTests { WebTestClient client = buildClient(); - EntityExchangeResult result = client.get() - .uri("/") - .exchange() - .expectStatus().isUnauthorized() + EntityExchangeResult result = client.get().uri("/").exchange().expectStatus().isUnauthorized() .expectHeader().value(HttpHeaders.WWW_AUTHENTICATE, value -> assertThat(value).contains("myrealm")) - .expectBody(String.class) - .returnResult(); + .expectBody(String.class).returnResult(); assertThat(result.getResponseCookies().getFirst("SESSION")).isNull(); } @@ -336,22 +304,16 @@ public class ServerHttpSecurityTests { this.http.securityContextRepository(new WebSessionServerSecurityContextRepository()); HttpBasicServerAuthenticationEntryPoint authenticationEntryPoint = new HttpBasicServerAuthenticationEntryPoint(); authenticationEntryPoint.setRealm("myrealm"); - this.http.httpBasic(httpBasic -> - httpBasic.authenticationEntryPoint(authenticationEntryPoint) - ); + this.http.httpBasic(httpBasic -> httpBasic.authenticationEntryPoint(authenticationEntryPoint)); this.http.authenticationManager(this.authenticationManager); ServerHttpSecurity.AuthorizeExchangeSpec authorize = this.http.authorizeExchange(); authorize.anyExchange().authenticated(); WebTestClient client = buildClient(); - EntityExchangeResult result = client.get() - .uri("/") - .exchange() - .expectStatus().isUnauthorized() + EntityExchangeResult result = client.get().uri("/").exchange().expectStatus().isUnauthorized() .expectHeader().value(HttpHeaders.WWW_AUTHENTICATE, value -> assertThat(value).contains("myrealm")) - .expectBody(String.class) - .returnResult(); + .expectBody(String.class).returnResult(); assertThat(result.getResponseCookies().getFirst("SESSION")).isNull(); } @@ -359,17 +321,15 @@ public class ServerHttpSecurityTests { @Test public void basicWithCustomAuthenticationManager() { ReactiveAuthenticationManager customAuthenticationManager = mock(ReactiveAuthenticationManager.class); - given(customAuthenticationManager.authenticate(any())).willReturn(Mono.just(new TestingAuthenticationToken("rob", "rob", "ROLE_USER", "ROLE_ADMIN"))); + given(customAuthenticationManager.authenticate(any())) + .willReturn(Mono.just(new TestingAuthenticationToken("rob", "rob", "ROLE_USER", "ROLE_ADMIN"))); - SecurityWebFilterChain securityFilterChain = this.http.httpBasic().authenticationManager(customAuthenticationManager).and().build(); + SecurityWebFilterChain securityFilterChain = this.http.httpBasic() + .authenticationManager(customAuthenticationManager).and().build(); WebFilterChainProxy springSecurityFilterChain = new WebFilterChainProxy(securityFilterChain); WebTestClient client = WebTestClientBuilder.bindToWebFilters(springSecurityFilterChain).build(); - client.get() - .uri("/") - .headers(headers -> headers.setBasicAuth("rob", "rob")) - .exchange() - .expectStatus().isOk() + client.get().uri("/").headers(headers -> headers.setBasicAuth("rob", "rob")).exchange().expectStatus().isOk() .expectBody(String.class).consumeWith(b -> assertThat(b.getResponseBody()).isEqualTo("ok")); verifyZeroInteractions(this.authenticationManager); @@ -382,18 +342,11 @@ public class ServerHttpSecurityTests { .willReturn(Mono.just(new TestingAuthenticationToken("rob", "rob", "ROLE_USER", "ROLE_ADMIN"))); SecurityWebFilterChain securityFilterChain = this.http - .httpBasic(httpBasic -> - httpBasic.authenticationManager(customAuthenticationManager) - ) - .build(); + .httpBasic(httpBasic -> httpBasic.authenticationManager(customAuthenticationManager)).build(); WebFilterChainProxy springSecurityFilterChain = new WebFilterChainProxy(securityFilterChain); WebTestClient client = WebTestClientBuilder.bindToWebFilters(springSecurityFilterChain).build(); - client.get() - .uri("/") - .headers(headers -> headers.setBasicAuth("rob", "rob")) - .exchange() - .expectStatus().isOk() + client.get().uri("/").headers(headers -> headers.setBasicAuth("rob", "rob")).exchange().expectStatus().isOk() .expectBody(String.class).consumeWith(b -> assertThat(b.getResponseBody()).isEqualTo("ok")); verifyZeroInteractions(this.authenticationManager); @@ -406,10 +359,7 @@ public class ServerHttpSecurityTests { X509PrincipalExtractor mockExtractor = mock(X509PrincipalExtractor.class); ReactiveAuthenticationManager mockAuthenticationManager = mock(ReactiveAuthenticationManager.class); - this.http.x509() - .principalExtractor(mockExtractor) - .authenticationManager(mockAuthenticationManager) - .and(); + this.http.x509().principalExtractor(mockExtractor).authenticationManager(mockAuthenticationManager).and(); SecurityWebFilterChain securityWebFilterChain = this.http.build(); WebFilter x509WebFilter = securityWebFilterChain.getWebFilters().filter(this::isX509Filter).blockFirst(); @@ -422,11 +372,7 @@ public class ServerHttpSecurityTests { X509PrincipalExtractor mockExtractor = mock(X509PrincipalExtractor.class); ReactiveAuthenticationManager mockAuthenticationManager = mock(ReactiveAuthenticationManager.class); - this.http.x509(x509 -> - x509 - .principalExtractor(mockExtractor) - .authenticationManager(mockAuthenticationManager) - ); + this.http.x509(x509 -> x509.principalExtractor(mockExtractor).authenticationManager(mockAuthenticationManager)); SecurityWebFilterChain securityWebFilterChain = this.http.build(); WebFilter x509WebFilter = securityWebFilterChain.getWebFilters().filter(this::isX509Filter).blockFirst(); @@ -460,10 +406,7 @@ public class ServerHttpSecurityTests { WebFilterChainProxy springSecurityFilterChain = new WebFilterChainProxy(securityFilterChain); WebTestClient client = WebTestClientBuilder.bindToWebFilters(springSecurityFilterChain).build(); - client.post() - .uri("/") - .exchange() - .expectStatus().isOk(); + client.post().uri("/").exchange().expectStatus().isOk(); } @Test @@ -471,15 +414,11 @@ public class ServerHttpSecurityTests { ServerCsrfTokenRepository customServerCsrfTokenRepository = mock(ServerCsrfTokenRepository.class); when(customServerCsrfTokenRepository.loadToken(any(ServerWebExchange.class))).thenReturn(Mono.empty()); SecurityWebFilterChain securityFilterChain = this.http - .csrf(csrf -> csrf.csrfTokenRepository(customServerCsrfTokenRepository)) - .build(); + .csrf(csrf -> csrf.csrfTokenRepository(customServerCsrfTokenRepository)).build(); WebFilterChainProxy springSecurityFilterChain = new WebFilterChainProxy(securityFilterChain); WebTestClient client = WebTestClientBuilder.bindToWebFilters(springSecurityFilterChain).build(); - client.post() - .uri("/") - .exchange() - .expectStatus().isForbidden(); + client.post().uri("/").exchange().expectStatus().isForbidden(); verify(customServerCsrfTokenRepository).loadToken(any()); } @@ -487,16 +426,12 @@ public class ServerHttpSecurityTests { @Test public void shouldConfigureRequestCacheForOAuth2LoginAuthenticationEntryPointAndSuccessHandler() { ServerRequestCache requestCache = spy(new WebSessionServerRequestCache()); - ReactiveClientRegistrationRepository clientRegistrationRepository = mock(ReactiveClientRegistrationRepository.class); + ReactiveClientRegistrationRepository clientRegistrationRepository = mock( + ReactiveClientRegistrationRepository.class); - SecurityWebFilterChain securityFilterChain = this.http - .oauth2Login() - .clientRegistrationRepository(clientRegistrationRepository) - .and() - .authorizeExchange().anyExchange().authenticated() - .and() - .requestCache(c -> c.requestCache(requestCache)) - .build(); + SecurityWebFilterChain securityFilterChain = this.http.oauth2Login() + .clientRegistrationRepository(clientRegistrationRepository).and().authorizeExchange().anyExchange() + .authenticated().and().requestCache(c -> c.requestCache(requestCache)).build(); WebTestClient client = WebTestClientBuilder.bindToWebFilters(securityFilterChain).build(); client.get().uri("/test").exchange(); @@ -504,28 +439,27 @@ public class ServerHttpSecurityTests { verify(requestCache).saveRequest(captor.capture()); assertThat(captor.getValue().getRequest().getURI().toString()).isEqualTo("/test"); - - OAuth2LoginAuthenticationWebFilter authenticationWebFilter = - getWebFilter(securityFilterChain, OAuth2LoginAuthenticationWebFilter.class).get(); + OAuth2LoginAuthenticationWebFilter authenticationWebFilter = getWebFilter(securityFilterChain, + OAuth2LoginAuthenticationWebFilter.class).get(); Object handler = getField(authenticationWebFilter, "authenticationSuccessHandler"); assertThat(getField(handler, "requestCache")).isSameAs(requestCache); } @Test public void shouldConfigureAuthorizationRequestRepositoryForOAuth2Login() { - ServerAuthorizationRequestRepository authorizationRequestRepository = mock(ServerAuthorizationRequestRepository.class); - ReactiveClientRegistrationRepository clientRegistrationRepository = mock(ReactiveClientRegistrationRepository.class); + ServerAuthorizationRequestRepository authorizationRequestRepository = mock( + ServerAuthorizationRequestRepository.class); + ReactiveClientRegistrationRepository clientRegistrationRepository = mock( + ReactiveClientRegistrationRepository.class); OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.request().build(); - when(authorizationRequestRepository.removeAuthorizationRequest(any())).thenReturn(Mono.just(authorizationRequest)); + when(authorizationRequestRepository.removeAuthorizationRequest(any())) + .thenReturn(Mono.just(authorizationRequest)); - SecurityWebFilterChain securityFilterChain = this.http - .oauth2Login() + SecurityWebFilterChain securityFilterChain = this.http.oauth2Login() .clientRegistrationRepository(clientRegistrationRepository) - .authorizationRequestRepository(authorizationRequestRepository) - .and() - .build(); + .authorizationRequestRepository(authorizationRequestRepository).and().build(); WebTestClient client = WebTestClientBuilder.bindToWebFilters(securityFilterChain).build(); client.get().uri("/login/oauth2/code/registration-id").exchange(); @@ -537,41 +471,42 @@ public class ServerHttpSecurityTests { try { Object converter = getField(filter, "authenticationConverter"); return converter.getClass().isAssignableFrom(ServerX509AuthenticationConverter.class); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { // field doesn't exist return false; } } private Optional getWebFilter(SecurityWebFilterChain filterChain, Class filterClass) { - return (Optional) filterChain.getWebFilters() - .filter(Objects::nonNull) - .filter(filter -> filter.getClass().isAssignableFrom(filterClass)) - .singleOrEmpty() - .blockOptional(); + return (Optional) filterChain.getWebFilters().filter(Objects::nonNull) + .filter(filter -> filter.getClass().isAssignableFrom(filterClass)).singleOrEmpty().blockOptional(); } private WebTestClient buildClient() { - WebFilterChainProxy springSecurityFilterChain = new WebFilterChainProxy( - this.http.build()); + WebFilterChainProxy springSecurityFilterChain = new WebFilterChainProxy(this.http.build()); return WebTestClientBuilder.bindToWebFilters(springSecurityFilterChain).build(); } @RestController private static class SubscriberContextController { + @GetMapping("/**") Mono pathWithinApplicationFromContext() { - return Mono.subscriberContext() - .filter(c -> c.hasKey(ServerWebExchange.class)) - .map(c -> c.get(ServerWebExchange.class)) - .map(e -> e.getRequest().getPath().pathWithinApplication().value()); + return Mono.subscriberContext().filter(c -> c.hasKey(ServerWebExchange.class)) + .map(c -> c.get(ServerWebExchange.class)) + .map(e -> e.getRequest().getPath().pathWithinApplication().value()); } + } private static class TestWebFilter implements WebFilter { + @Override public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { return chain.filter(exchange); } + } + } diff --git a/config/src/test/java/org/springframework/security/config/web/server/TestingServerHttpSecurity.java b/config/src/test/java/org/springframework/security/config/web/server/TestingServerHttpSecurity.java index 50d2a3020d..60a997a9c3 100644 --- a/config/src/test/java/org/springframework/security/config/web/server/TestingServerHttpSecurity.java +++ b/config/src/test/java/org/springframework/security/config/web/server/TestingServerHttpSecurity.java @@ -24,9 +24,10 @@ import org.springframework.context.ApplicationContext; * @since 5.1 */ public class TestingServerHttpSecurity extends ServerHttpSecurity { - public TestingServerHttpSecurity applicationContext(ApplicationContext applicationContext) - throws BeansException { + + public TestingServerHttpSecurity applicationContext(ApplicationContext applicationContext) throws BeansException { super.setApplicationContext(applicationContext); return this; } + } diff --git a/config/src/test/java/org/springframework/security/config/websocket/MessageSecurityPostProcessorTests.java b/config/src/test/java/org/springframework/security/config/websocket/MessageSecurityPostProcessorTests.java index cf8a615684..76e58d366e 100644 --- a/config/src/test/java/org/springframework/security/config/websocket/MessageSecurityPostProcessorTests.java +++ b/config/src/test/java/org/springframework/security/config/websocket/MessageSecurityPostProcessorTests.java @@ -22,8 +22,8 @@ import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry; public class MessageSecurityPostProcessorTests { - private WebSocketMessageBrokerSecurityBeanDefinitionParser.MessageSecurityPostProcessor postProcessor = - new WebSocketMessageBrokerSecurityBeanDefinitionParser.MessageSecurityPostProcessor("id", false); + private WebSocketMessageBrokerSecurityBeanDefinitionParser.MessageSecurityPostProcessor postProcessor = new WebSocketMessageBrokerSecurityBeanDefinitionParser.MessageSecurityPostProcessor( + "id", false); @Test public void handlesBeansWithoutClass() { @@ -31,4 +31,5 @@ public class MessageSecurityPostProcessorTests { registry.registerBeanDefinition("beanWithoutClass", new GenericBeanDefinition()); postProcessor.postProcessBeanDefinitionRegistry(registry); } + } diff --git a/config/src/test/java/org/springframework/security/config/websocket/WebSocketMessageBrokerConfigTests.java b/config/src/test/java/org/springframework/security/config/websocket/WebSocketMessageBrokerConfigTests.java index a693eaf96a..f4e3df8af9 100644 --- a/config/src/test/java/org/springframework/security/config/websocket/WebSocketMessageBrokerConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/websocket/WebSocketMessageBrokerConfigTests.java @@ -75,8 +75,8 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder @RunWith(SpringJUnit4ClassRunner.class) @SecurityTestExecutionListeners public class WebSocketMessageBrokerConfigTests { - private static final String CONFIG_LOCATION_PREFIX = - "classpath:org/springframework/security/config/websocket/WebSocketMessageBrokerConfigTests"; + + private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/websocket/WebSocketMessageBrokerConfigTests"; @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -112,8 +112,7 @@ public class WebSocketMessageBrokerConfigTests { SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT); headers.setNativeHeader(this.token.getHeaderName(), this.token.getToken()); - assertThatCode(() -> this.clientInboundChannel.send(message("/permitAll", headers))) - .doesNotThrowAnyException(); + assertThatCode(() -> this.clientInboundChannel.send(message("/permitAll", headers))).doesNotThrowAnyException(); } @Test @@ -244,56 +243,49 @@ public class WebSocketMessageBrokerConfigTests { @Test public void configureWhenUsingConnectMessageTypeThenAutowireFails() { - ThrowingCallable bad = () -> - this.spring.configLocations(xml("ConnectInterceptTypeConfig")).autowire(); + ThrowingCallable bad = () -> this.spring.configLocations(xml("ConnectInterceptTypeConfig")).autowire(); assertThatThrownBy(bad).isInstanceOf(BeanDefinitionParsingException.class); } @Test public void configureWhenUsingConnectAckMessageTypeThenAutowireFails() { - ThrowingCallable bad = () -> - this.spring.configLocations(xml("ConnectAckInterceptTypeConfig")).autowire(); + ThrowingCallable bad = () -> this.spring.configLocations(xml("ConnectAckInterceptTypeConfig")).autowire(); assertThatThrownBy(bad).isInstanceOf(BeanDefinitionParsingException.class); } @Test public void configureWhenUsingDisconnectMessageTypeThenAutowireFails() { - ThrowingCallable bad = () -> - this.spring.configLocations(xml("DisconnectInterceptTypeConfig")).autowire(); + ThrowingCallable bad = () -> this.spring.configLocations(xml("DisconnectInterceptTypeConfig")).autowire(); assertThatThrownBy(bad).isInstanceOf(BeanDefinitionParsingException.class); } @Test public void configureWhenUsingDisconnectAckMessageTypeThenAutowireFails() { - ThrowingCallable bad = () -> - this.spring.configLocations(xml("DisconnectAckInterceptTypeConfig")).autowire(); + ThrowingCallable bad = () -> this.spring.configLocations(xml("DisconnectAckInterceptTypeConfig")).autowire(); assertThatThrownBy(bad).isInstanceOf(BeanDefinitionParsingException.class); } @Test public void configureWhenUsingHeartbeatMessageTypeThenAutowireFails() { - ThrowingCallable bad = () -> - this.spring.configLocations(xml("HeartbeatInterceptTypeConfig")).autowire(); + ThrowingCallable bad = () -> this.spring.configLocations(xml("HeartbeatInterceptTypeConfig")).autowire(); assertThatThrownBy(bad).isInstanceOf(BeanDefinitionParsingException.class); } @Test public void configureWhenUsingOtherMessageTypeThenAutowireFails() { - ThrowingCallable bad = () -> - this.spring.configLocations(xml("OtherInterceptTypeConfig")).autowire(); + ThrowingCallable bad = () -> this.spring.configLocations(xml("OtherInterceptTypeConfig")).autowire(); assertThatThrownBy(bad).isInstanceOf(BeanDefinitionParsingException.class); } @Test public void configureWhenUsingUnsubscribeMessageTypeThenAutowireFails() { - ThrowingCallable bad = () -> - this.spring.configLocations(xml("UnsubscribeInterceptTypeConfig")).autowire(); + ThrowingCallable bad = () -> this.spring.configLocations(xml("UnsubscribeInterceptTypeConfig")).autowire(); assertThatThrownBy(bad).isInstanceOf(BeanDefinitionParsingException.class); } @@ -317,17 +309,14 @@ public class WebSocketMessageBrokerConfigTests { String csrfAttributeName = CsrfToken.class.getName(); String customAttributeName = this.getClass().getName(); - MvcResult result = mvc.perform(get("/app") - .requestAttr(csrfAttributeName, this.token) - .sessionAttr(customAttributeName, "attributeValue")) - .andReturn(); + MvcResult result = mvc.perform(get("/app").requestAttr(csrfAttributeName, this.token) + .sessionAttr(customAttributeName, "attributeValue")).andReturn(); CsrfToken handshakeToken = (CsrfToken) this.testHandshakeHandler.attributes.get(csrfAttributeName); String handshakeValue = (String) this.testHandshakeHandler.attributes.get(customAttributeName); String sessionValue = (String) result.getRequest().getSession().getAttribute(customAttributeName); - assertThat(handshakeToken).isEqualTo(this.token) - .withFailMessage("CsrfToken is populated"); + assertThat(handshakeToken).isEqualTo(this.token).withFailMessage("CsrfToken is populated"); assertThat(handshakeValue).isEqualTo(sessionValue) .withFailMessage("Explicitly listed session variables are not overridden"); @@ -343,17 +332,14 @@ public class WebSocketMessageBrokerConfigTests { String csrfAttributeName = CsrfToken.class.getName(); String customAttributeName = this.getClass().getName(); - MvcResult result = mvc.perform(get("/app/289/tpyx6mde/websocket") - .requestAttr(csrfAttributeName, this.token) - .sessionAttr(customAttributeName, "attributeValue")) - .andReturn(); + MvcResult result = mvc.perform(get("/app/289/tpyx6mde/websocket").requestAttr(csrfAttributeName, this.token) + .sessionAttr(customAttributeName, "attributeValue")).andReturn(); CsrfToken handshakeToken = (CsrfToken) this.testHandshakeHandler.attributes.get(csrfAttributeName); String handshakeValue = (String) this.testHandshakeHandler.attributes.get(customAttributeName); String sessionValue = (String) result.getRequest().getSession().getAttribute(customAttributeName); - assertThat(handshakeToken).isEqualTo(this.token) - .withFailMessage("CsrfToken is populated"); + assertThat(handshakeToken).isEqualTo(this.token).withFailMessage("CsrfToken is populated"); assertThat(handshakeValue).isEqualTo(sessionValue) .withFailMessage("Explicitly listed session variables are not overridden"); @@ -452,28 +438,33 @@ public class WebSocketMessageBrokerConfigTests { @Controller static class MessageController { + String username; @MessageMapping("/message") public void authentication(@AuthenticationPrincipal String username) { this.username = username; } + } @Controller static class MessageWithArgumentController { + MessageArgument messageArgument; @MessageMapping("/message-with-argument") public void myCustom(MessageArgument messageArgument) { this.messageArgument = messageArgument; } + } - static class MessageArgument { + MessageArgument(String notDefaultConstructor) { } + } static class MessageArgumentResolver implements HandlerMethodArgumentResolver { @@ -487,22 +478,23 @@ public class WebSocketMessageBrokerConfigTests { public Object resolveArgument(MethodParameter parameter, Message message) { return new MessageArgument(""); } + } static class TestHandshakeHandler implements HandshakeHandler { + Map attributes; @Override - public boolean doHandshake( - ServerHttpRequest request, - org.springframework.http.server.ServerHttpResponse response, - WebSocketHandler wsHandler, + public boolean doHandshake(ServerHttpRequest request, + org.springframework.http.server.ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) throws HandshakeFailureException { this.attributes = attributes; return true; } + } static class InboundExecutorPostProcessor implements BeanDefinitionRegistryPostProcessor { @@ -510,14 +502,15 @@ public class WebSocketMessageBrokerConfigTests { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { BeanDefinition inbound = registry.getBeanDefinition("clientInboundChannel"); - inbound.getConstructorArgumentValues() - .addIndexedArgumentValue(0, new RootBeanDefinition(SyncTaskExecutor.class)); + inbound.getConstructorArgumentValues().addIndexedArgumentValue(0, + new RootBeanDefinition(SyncTaskExecutor.class)); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } + } static class ExceptingInterceptor extends ChannelInterceptorAdapter { @@ -526,14 +519,13 @@ public class WebSocketMessageBrokerConfigTests { public Message preSend(Message message, MessageChannel channel) { throw new UnsupportedOperationException("no"); } + } - static class DenyNileMessageSecurityExpressionHandler - extends DefaultMessageSecurityExpressionHandler { + static class DenyNileMessageSecurityExpressionHandler extends DefaultMessageSecurityExpressionHandler { @Override - protected SecurityExpressionOperations createSecurityExpressionRoot( - Authentication authentication, + protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, Message invocation) { return new MessageSecurityExpressionRoot(authentication, invocation) { @@ -543,5 +535,7 @@ public class WebSocketMessageBrokerConfigTests { } }; } + } + } diff --git a/config/src/test/java/org/springframework/security/htmlunit/server/HtmlUnitWebTestClient.java b/config/src/test/java/org/springframework/security/htmlunit/server/HtmlUnitWebTestClient.java index 4543deaae4..408f3240a3 100644 --- a/config/src/test/java/org/springframework/security/htmlunit/server/HtmlUnitWebTestClient.java +++ b/config/src/test/java/org/springframework/security/htmlunit/server/HtmlUnitWebTestClient.java @@ -55,21 +55,15 @@ final class HtmlUnitWebTestClient { Assert.notNull(webClient, "WebClient must not be null"); Assert.notNull(webTestClient, "WebTestClient must not be null"); this.webClient = webClient; - this.webTestClient = webTestClient.mutate() - .filter(new FollowRedirects()) - .filter(new CookieManager()) - .build(); + this.webTestClient = webTestClient.mutate().filter(new FollowRedirects()).filter(new CookieManager()).build(); } public FluxExchangeResult getResponse(WebRequest webRequest) { - WebTestClient.RequestBodySpec request = this.webTestClient - .method(httpMethod(webRequest)) - .uri(uri(webRequest)); + WebTestClient.RequestBodySpec request = this.webTestClient.method(httpMethod(webRequest)).uri(uri(webRequest)); contentType(request, webRequest); cookies(request, webRequest); headers(request, webRequest); - return content(request, webRequest).exchange().returnResult(String.class); } @@ -87,7 +81,7 @@ final class HtmlUnitWebTestClient { private MultiValueMap formData(List params) { MultiValueMap result = new LinkedMultiValueMap<>(params.size()); - params.forEach( pair -> result.add(pair.getName(), pair.getValue())); + params.forEach(pair -> result.add(pair.getName(), pair.getValue())); return result; } @@ -109,9 +103,8 @@ final class HtmlUnitWebTestClient { StringTokenizer tokens = new StringTokenizer(cookieHeaderValue, "=;"); while (tokens.hasMoreTokens()) { String cookieName = tokens.nextToken().trim(); - Assert.isTrue(tokens.hasMoreTokens(), - () -> "Expected value for cookie name '" + cookieName + - "': full cookie header was [" + cookieHeaderValue + "]"); + Assert.isTrue(tokens.hasMoreTokens(), () -> "Expected value for cookie name '" + cookieName + + "': full cookie header was [" + cookieHeaderValue + "]"); String cookieValue = tokens.nextToken().trim(); request.cookie(cookieName, cookieValue); } @@ -129,7 +122,7 @@ final class HtmlUnitWebTestClient { } private void headers(WebTestClient.RequestBodySpec request, WebRequest webRequest) { - webRequest.getAdditionalHeaders().forEach( (name, value) -> request.header(name, value)); + webRequest.getAdditionalHeaders().forEach((name, value) -> request.header(name, value)); } private HttpMethod httpMethod(WebRequest webRequest) { @@ -143,66 +136,67 @@ final class HtmlUnitWebTestClient { } static class FollowRedirects implements ExchangeFilterFunction { + @Override public Mono filter(ClientRequest request, ExchangeFunction next) { - return next.exchange(request) - .flatMap( response -> redirectIfNecessary(request, next, response)); + return next.exchange(request).flatMap(response -> redirectIfNecessary(request, next, response)); } - private Mono redirectIfNecessary(ClientRequest request, ExchangeFunction next, ClientResponse response) { + private Mono redirectIfNecessary(ClientRequest request, ExchangeFunction next, + ClientResponse response) { URI location = response.headers().asHttpHeaders().getLocation(); String host = request.url().getHost(); String scheme = request.url().getScheme(); if (location != null) { String redirectUrl = location.toASCIIString(); if (location.getHost() == null) { - redirectUrl = scheme+ "://" + host + location.toASCIIString(); + redirectUrl = scheme + "://" + host + location.toASCIIString(); } ClientRequest redirect = ClientRequest.method(HttpMethod.GET, URI.create(redirectUrl)) - .headers(headers -> headers.addAll(request.headers())) - .cookies(cookies -> cookies.addAll(request.cookies())) - .attributes(attributes -> attributes.putAll(request.attributes())) - .build(); + .headers(headers -> headers.addAll(request.headers())) + .cookies(cookies -> cookies.addAll(request.cookies())) + .attributes(attributes -> attributes.putAll(request.attributes())).build(); - return next.exchange(redirect).flatMap( r -> redirectIfNecessary(request, next, r)); + return next.exchange(redirect).flatMap(r -> redirectIfNecessary(request, next, r)); } return Mono.just(response); } + } static class CookieManager implements ExchangeFilterFunction { + private Map cookies = new HashMap<>(); @Override public Mono filter(ClientRequest request, ExchangeFunction next) { - return next.exchange(withClientCookies(request)) - .doOnSuccess( response -> { - response.cookies().values().forEach( cookies -> { - cookies.forEach( cookie -> { - if (cookie.getMaxAge().isZero()) { - this.cookies.remove(cookie.getName()); - } else { - this.cookies.put(cookie.getName(), cookie); - } - }); + return next.exchange(withClientCookies(request)).doOnSuccess(response -> { + response.cookies().values().forEach(cookies -> { + cookies.forEach(cookie -> { + if (cookie.getMaxAge().isZero()) { + this.cookies.remove(cookie.getName()); + } + else { + this.cookies.put(cookie.getName(), cookie); + } }); }); + }); } private ClientRequest withClientCookies(ClientRequest request) { - return ClientRequest.from(request) - .cookies( c -> { - c.addAll(clientCookies()); - }).build(); + return ClientRequest.from(request).cookies(c -> { + c.addAll(clientCookies()); + }).build(); } private MultiValueMap clientCookies() { MultiValueMap result = new LinkedMultiValueMap<>(this.cookies.size()); - this.cookies.values().forEach( cookie -> - result.add(cookie.getName(), cookie.getValue()) - ); + this.cookies.values().forEach(cookie -> result.add(cookie.getName(), cookie.getValue())); return result; } + } + } diff --git a/config/src/test/java/org/springframework/security/htmlunit/server/MockWebResponseBuilder.java b/config/src/test/java/org/springframework/security/htmlunit/server/MockWebResponseBuilder.java index 15022b4596..f693f4258f 100644 --- a/config/src/test/java/org/springframework/security/htmlunit/server/MockWebResponseBuilder.java +++ b/config/src/test/java/org/springframework/security/htmlunit/server/MockWebResponseBuilder.java @@ -35,13 +35,13 @@ import org.springframework.util.Assert; * @since 5.0 */ final class MockWebResponseBuilder { + private final long startTime; private final WebRequest webRequest; private final FluxExchangeResult exchangeResult; - MockWebResponseBuilder(long startTime, WebRequest webRequest, FluxExchangeResult exchangeResult) { Assert.notNull(webRequest, "WebRequest must not be null"); Assert.notNull(exchangeResult, "FluxExchangeResult must not be null"); @@ -50,7 +50,6 @@ final class MockWebResponseBuilder { this.exchangeResult = exchangeResult; } - public WebResponse build() throws IOException { WebResponseData webResponseData = webResponseData(); long endTime = System.currentTimeMillis(); @@ -60,17 +59,15 @@ final class MockWebResponseBuilder { private WebResponseData webResponseData() { List responseHeaders = responseHeaders(); HttpStatus status = this.exchangeResult.getStatus(); - return new WebResponseData(this.exchangeResult.getResponseBodyContent(), status.value(), status.getReasonPhrase(), responseHeaders); + return new WebResponseData(this.exchangeResult.getResponseBodyContent(), status.value(), + status.getReasonPhrase(), responseHeaders); } private List responseHeaders() { HttpHeaders responseHeaders = this.exchangeResult.getResponseHeaders(); List result = new ArrayList<>(responseHeaders.size()); - responseHeaders.forEach( (headerName, headerValues) -> - headerValues.forEach( headerValue -> - result.add(new NameValuePair(headerName, headerValue)) - ) - ); + responseHeaders.forEach((headerName, headerValues) -> headerValues + .forEach(headerValue -> result.add(new NameValuePair(headerName, headerValue)))); return result; } diff --git a/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientHtmlUnitDriverBuilder.java b/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientHtmlUnitDriverBuilder.java index ae345738c6..5a671b6b4e 100644 --- a/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientHtmlUnitDriverBuilder.java +++ b/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientHtmlUnitDriverBuilder.java @@ -30,6 +30,7 @@ import org.springframework.test.web.servlet.htmlunit.webdriver.WebConnectionHtml * @since 5.0 */ public class WebTestClientHtmlUnitDriverBuilder { + private final WebTestClient webTestClient; private WebTestClientHtmlUnitDriverBuilder(WebTestClient webTestClient) { @@ -40,7 +41,8 @@ public class WebTestClientHtmlUnitDriverBuilder { WebConnectionHtmlUnitDriver driver = new WebConnectionHtmlUnitDriver(); WebClient webClient = driver.getWebClient(); WebTestClientWebConnection webClientConnection = new WebTestClientWebConnection(this.webTestClient, webClient); - WebConnection connection = new DelegatingWebConnection(driver.getWebConnection(), new DelegateWebConnection(new HostRequestMatcher("localhost"), webClientConnection)); + WebConnection connection = new DelegatingWebConnection(driver.getWebConnection(), + new DelegateWebConnection(new HostRequestMatcher("localhost"), webClientConnection)); driver.setWebConnection(connection); return driver; } @@ -48,4 +50,5 @@ public class WebTestClientHtmlUnitDriverBuilder { public static WebTestClientHtmlUnitDriverBuilder webTestClientSetup(WebTestClient webTestClient) { return new WebTestClientHtmlUnitDriverBuilder(webTestClient); } + } diff --git a/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientHtmlUnitDriverBuilderTests.java b/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientHtmlUnitDriverBuilderTests.java index 023b1fc7dc..d0d074a978 100644 --- a/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientHtmlUnitDriverBuilderTests.java +++ b/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientHtmlUnitDriverBuilderTests.java @@ -43,11 +43,8 @@ public class WebTestClientHtmlUnitDriverBuilderTests { @Test public void helloWorld() { - WebTestClient webTestClient = WebTestClient - .bindToController(new HelloWorldController()) - .build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient).build(); + WebTestClient webTestClient = WebTestClient.bindToController(new HelloWorldController()).build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); driver.get("http://localhost/"); @@ -60,27 +57,20 @@ public class WebTestClientHtmlUnitDriverBuilderTests { */ @Controller class HelloWorldController { + @ResponseBody @GetMapping(produces = MediaType.TEXT_HTML_VALUE) public String index() { - return "\n" - + "\n" - + "Hello World\n" - + "\n" - + "\n" - + "

    Hello World

    \n" - + "\n" - + ""; + return "\n" + "\n" + "Hello World\n" + "\n" + "\n" + + "

    Hello World

    \n" + "\n" + ""; } + } @Test public void cookies() { - WebTestClient webTestClient = WebTestClient - .bindToController(new CookieController()) - .build(); - WebDriver driver = WebTestClientHtmlUnitDriverBuilder - .webTestClientSetup(webTestClient).build(); + WebTestClient webTestClient = WebTestClient.bindToController(new CookieController()).build(); + WebDriver driver = WebTestClientHtmlUnitDriverBuilder.webTestClientSetup(webTestClient).build(); driver.get("http://localhost/cookie"); @@ -94,16 +84,11 @@ public class WebTestClientHtmlUnitDriverBuilderTests { @Controller @ResponseBody class CookieController { + @GetMapping(path = "/", produces = MediaType.TEXT_HTML_VALUE) public String view(@CookieValue(required = false) String cookieName) { - return "\n" - + "\n" - + "Hello World\n" - + "\n" - + "\n" - + "

    " + TextEscapeUtils.escapeEntities(cookieName) + "

    \n" - + "\n" - + ""; + return "\n" + "\n" + "Hello World\n" + "\n" + "\n" + "

    " + + TextEscapeUtils.escapeEntities(cookieName) + "

    \n" + "\n" + ""; } @GetMapping("/cookie") @@ -120,9 +105,10 @@ public class WebTestClientHtmlUnitDriverBuilderTests { @GetMapping("/cookie/delete") public Mono deleteCookie(ServerHttpResponse response) { - response.addCookie( - ResponseCookie.from("cookieName", "").maxAge(Duration.ofSeconds(0)).build()); + response.addCookie(ResponseCookie.from("cookieName", "").maxAge(Duration.ofSeconds(0)).build()); return redirect(response); } + } + } diff --git a/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientWebConnection.java b/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientWebConnection.java index c5d6828c03..f7dd640175 100644 --- a/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientWebConnection.java +++ b/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientWebConnection.java @@ -37,11 +37,11 @@ public class WebTestClientWebConnection implements WebConnection { private final WebTestClient webTestClient; private final String contextPath; + private final HtmlUnitWebTestClient requestBuilder; private WebClient webClient; - public WebTestClientWebConnection(WebTestClient webTestClient, WebClient webClient) { this(webTestClient, webClient, ""); } @@ -59,10 +59,11 @@ public class WebTestClientWebConnection implements WebConnection { /** * Validate the supplied {@code contextPath}. - *

    If the value is not {@code null}, it must conform to - * {@link javax.servlet.http.HttpServletRequest#getContextPath()} which - * states that it can be an empty string and otherwise must start with - * a "/" character and not end with a "/" character. + *

    + * If the value is not {@code null}, it must conform to + * {@link javax.servlet.http.HttpServletRequest#getContextPath()} which states that it + * can be an empty string and otherwise must start with a "/" character and not end + * with a "/" character. * @param contextPath the path to validate */ static void validateContextPath(@Nullable String contextPath) { @@ -73,7 +74,6 @@ public class WebTestClientWebConnection implements WebConnection { Assert.isTrue(!contextPath.endsWith("/"), () -> "contextPath '" + contextPath + "' must not end with '/'."); } - public void setWebClient(WebClient webClient) { Assert.notNull(webClient, "WebClient must not be null"); this.webClient = webClient; @@ -89,5 +89,7 @@ public class WebTestClientWebConnection implements WebConnection { } @Override - public void close() {} + public void close() { + } + } diff --git a/config/src/test/java/org/springframework/security/intercept/method/aopalliance/MethodSecurityInterceptorWithAopConfigTests.java b/config/src/test/java/org/springframework/security/intercept/method/aopalliance/MethodSecurityInterceptorWithAopConfigTests.java index e77dfc900f..334d0ebc18 100644 --- a/config/src/test/java/org/springframework/security/intercept/method/aopalliance/MethodSecurityInterceptorWithAopConfigTests.java +++ b/config/src/test/java/org/springframework/security/intercept/method/aopalliance/MethodSecurityInterceptorWithAopConfigTests.java @@ -33,13 +33,12 @@ import org.springframework.security.core.context.SecurityContextHolder; * @author Ben Alex */ public class MethodSecurityInterceptorWithAopConfigTests { - static final String AUTH_PROVIDER_XML = "" - + " " + + static final String AUTH_PROVIDER_XML = "" + " " + " " + " " + " " - + " " + " " - + ""; + + " " + " " + ""; static final String ACCESS_MANAGER_XML = "" + " " @@ -48,14 +47,11 @@ public class MethodSecurityInterceptorWithAopConfigTests { static final String TARGET_BEAN_AND_INTERCEPTOR = "" + "" - + " " - + " " + + " " + " " + " " + " " + " " - + " " - + " " - + ""; + + " " + " " + ""; private AbstractXmlApplicationContext appContext; @@ -77,9 +73,8 @@ public class MethodSecurityInterceptorWithAopConfigTests { public void securityInterceptorIsAppliedWhenUsedWithAopConfig() { setContext("" + " " - + " " - + "" + TARGET_BEAN_AND_INTERCEPTOR + AUTH_PROVIDER_XML - + ACCESS_MANAGER_XML); + + " " + "" + + TARGET_BEAN_AND_INTERCEPTOR + AUTH_PROVIDER_XML + ACCESS_MANAGER_XML); ITargetObject target = (ITargetObject) appContext.getBean("target"); @@ -96,20 +91,14 @@ public class MethodSecurityInterceptorWithAopConfigTests { @Test(expected = AuthenticationCredentialsNotFoundException.class) public void securityInterceptorIsAppliedWhenUsedWithBeanNameAutoProxyCreator() { - setContext("" - + " " - + " " - + " securityInterceptor" - + " " - + " " - + " " - + " " - + " target" - + " " - + " " - + " " - + "" - + TARGET_BEAN_AND_INTERCEPTOR + AUTH_PROVIDER_XML + ACCESS_MANAGER_XML); + setContext( + "" + + " " + " " + + " securityInterceptor" + " " + " " + + " " + " " + " target" + + " " + " " + + " " + "" + + TARGET_BEAN_AND_INTERCEPTOR + AUTH_PROVIDER_XML + ACCESS_MANAGER_XML); ITargetObject target = (ITargetObject) appContext.getBean("target"); @@ -127,4 +116,5 @@ public class MethodSecurityInterceptorWithAopConfigTests { private void setContext(String context) { appContext = new InMemoryXmlApplicationContext(context); } + } diff --git a/core/src/main/java/org/springframework/security/access/AccessDecisionManager.java b/core/src/main/java/org/springframework/security/access/AccessDecisionManager.java index 298c754b1b..6fff3153cc 100644 --- a/core/src/main/java/org/springframework/security/access/AccessDecisionManager.java +++ b/core/src/main/java/org/springframework/security/access/AccessDecisionManager.java @@ -27,25 +27,23 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ public interface AccessDecisionManager { + // ~ Methods // ======================================================================================================== /** * Resolves an access control decision for the passed parameters. - * * @param authentication the caller invoking the method (not null) * @param object the secured object being called * @param configAttributes the configuration attributes associated with the secured * object being invoked - * * @throws AccessDeniedException if access is denied as the authentication does not * hold a required authority or ACL privilege * @throws InsufficientAuthenticationException if access is denied as the * authentication does not provide a sufficient level of trust */ - void decide(Authentication authentication, Object object, - Collection configAttributes) throws AccessDeniedException, - InsufficientAuthenticationException; + void decide(Authentication authentication, Object object, Collection configAttributes) + throws AccessDeniedException, InsufficientAuthenticationException; /** * Indicates whether this AccessDecisionManager is able to process @@ -56,10 +54,8 @@ public interface AccessDecisionManager { * AccessDecisionManager and/or RunAsManager and/or * AfterInvocationManager. *

    - * * @param attribute a configuration attribute that has been configured against the * AbstractSecurityInterceptor - * * @return true if this AccessDecisionManager can support the passed * configuration attribute */ @@ -68,10 +64,9 @@ public interface AccessDecisionManager { /** * Indicates whether the AccessDecisionManager implementation is able to * provide access control decisions for the indicated secured object type. - * * @param clazz the class that is being queried - * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); + } diff --git a/core/src/main/java/org/springframework/security/access/AccessDecisionVoter.java b/core/src/main/java/org/springframework/security/access/AccessDecisionVoter.java index bf4af5ba6a..1abb45b2ce 100644 --- a/core/src/main/java/org/springframework/security/access/AccessDecisionVoter.java +++ b/core/src/main/java/org/springframework/security/access/AccessDecisionVoter.java @@ -30,11 +30,14 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ public interface AccessDecisionVoter { + // ~ Static fields/initializers // ===================================================================================== int ACCESS_GRANTED = 1; + int ACCESS_ABSTAIN = 0; + int ACCESS_DENIED = -1; // ~ Methods @@ -47,10 +50,8 @@ public interface AccessDecisionVoter { * This allows the {@code AbstractSecurityInterceptor} to check every configuration * attribute can be consumed by the configured {@code AccessDecisionManager} and/or * {@code RunAsManager} and/or {@code AfterInvocationManager}. - * * @param attribute a configuration attribute that has been configured against the * {@code AbstractSecurityInterceptor} - * * @return true if this {@code AccessDecisionVoter} can support the passed * configuration attribute */ @@ -59,9 +60,7 @@ public interface AccessDecisionVoter { /** * Indicates whether the {@code AccessDecisionVoter} implementation is able to provide * access control votes for the indicated secured object type. - * * @param clazz the class that is being queried - * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); @@ -87,14 +86,12 @@ public interface AccessDecisionVoter { * parameter to maximise flexibility in making access control decisions, implementing * classes should not modify it or cause the represented invocation to take place (for * example, by calling {@code MethodInvocation.proceed()}). - * * @param authentication the caller making the invocation * @param object the secured object being invoked * @param attributes the configuration attributes associated with the secured object - * * @return either {@link #ACCESS_GRANTED}, {@link #ACCESS_ABSTAIN} or * {@link #ACCESS_DENIED} */ - int vote(Authentication authentication, S object, - Collection attributes); + int vote(Authentication authentication, S object, Collection attributes); + } diff --git a/core/src/main/java/org/springframework/security/access/AccessDeniedException.java b/core/src/main/java/org/springframework/security/access/AccessDeniedException.java index 8429d92a16..1fe26e846f 100644 --- a/core/src/main/java/org/springframework/security/access/AccessDeniedException.java +++ b/core/src/main/java/org/springframework/security/access/AccessDeniedException.java @@ -23,12 +23,12 @@ package org.springframework.security.access; * @author Ben Alex */ public class AccessDeniedException extends RuntimeException { + // ~ Constructors // =================================================================================================== /** * Constructs an AccessDeniedException with the specified message. - * * @param msg the detail message */ public AccessDeniedException(String msg) { @@ -38,11 +38,11 @@ public class AccessDeniedException extends RuntimeException { /** * Constructs an AccessDeniedException with the specified message and * root cause. - * * @param msg the detail message * @param t root cause */ public AccessDeniedException(String msg, Throwable t) { super(msg, t); } + } diff --git a/core/src/main/java/org/springframework/security/access/AfterInvocationProvider.java b/core/src/main/java/org/springframework/security/access/AfterInvocationProvider.java index bca38afa57..febbc6b8ba 100644 --- a/core/src/main/java/org/springframework/security/access/AfterInvocationProvider.java +++ b/core/src/main/java/org/springframework/security/access/AfterInvocationProvider.java @@ -28,12 +28,12 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ public interface AfterInvocationProvider { + // ~ Methods // ======================================================================================================== - Object decide(Authentication authentication, Object object, - Collection attributes, Object returnedObject) - throws AccessDeniedException; + Object decide(Authentication authentication, Object object, Collection attributes, + Object returnedObject) throws AccessDeniedException; /** * Indicates whether this AfterInvocationProvider is able to participate @@ -44,10 +44,8 @@ public interface AfterInvocationProvider { * AccessDecisionManager and/or RunAsManager and/or * AccessDecisionManager. *

    - * * @param attribute a configuration attribute that has been configured against the * AbstractSecurityInterceptor - * * @return true if this AfterInvocationProvider can support the passed * configuration attribute */ @@ -56,10 +54,9 @@ public interface AfterInvocationProvider { /** * Indicates whether the AfterInvocationProvider is able to provide * "after invocation" processing for the indicated secured object type. - * * @param clazz the class of secure object that is being queried - * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); + } diff --git a/core/src/main/java/org/springframework/security/access/AuthorizationServiceException.java b/core/src/main/java/org/springframework/security/access/AuthorizationServiceException.java index 920849a1e0..87fc2dc7a5 100644 --- a/core/src/main/java/org/springframework/security/access/AuthorizationServiceException.java +++ b/core/src/main/java/org/springframework/security/access/AuthorizationServiceException.java @@ -25,13 +25,13 @@ package org.springframework.security.access; * @author Ben Alex */ public class AuthorizationServiceException extends AccessDeniedException { + // ~ Constructors // =================================================================================================== /** * Constructs an AuthorizationServiceException with the specified * message. - * * @param msg the detail message */ public AuthorizationServiceException(String msg) { @@ -41,11 +41,11 @@ public class AuthorizationServiceException extends AccessDeniedException { /** * Constructs an AuthorizationServiceException with the specified message * and root cause. - * * @param msg the detail message * @param t root cause */ public AuthorizationServiceException(String msg, Throwable t) { super(msg, t); } + } diff --git a/core/src/main/java/org/springframework/security/access/ConfigAttribute.java b/core/src/main/java/org/springframework/security/access/ConfigAttribute.java index 91212036d6..d85cd30abb 100644 --- a/core/src/main/java/org/springframework/security/access/ConfigAttribute.java +++ b/core/src/main/java/org/springframework/security/access/ConfigAttribute.java @@ -37,6 +37,7 @@ import org.springframework.security.access.intercept.RunAsManager; * @author Ben Alex */ public interface ConfigAttribute extends Serializable { + // ~ Methods // ======================================================================================================== @@ -52,10 +53,10 @@ public interface ConfigAttribute extends Serializable { * null will require any relying classes to specifically support the * ConfigAttribute implementation, so returning null should * be avoided unless actually required. - * * @return a representation of the configuration attribute (or null if * the configuration attribute cannot be expressed as a String with * sufficient precision). */ String getAttribute(); + } diff --git a/core/src/main/java/org/springframework/security/access/PermissionCacheOptimizer.java b/core/src/main/java/org/springframework/security/access/PermissionCacheOptimizer.java index d27ebfc141..6af5c19e5f 100644 --- a/core/src/main/java/org/springframework/security/access/PermissionCacheOptimizer.java +++ b/core/src/main/java/org/springframework/security/access/PermissionCacheOptimizer.java @@ -27,14 +27,15 @@ import org.springframework.security.core.Authentication; * @since 3.1 */ public interface PermissionCacheOptimizer extends AopInfrastructureBean { + /** * Optimises the permission cache for anticipated operation on the supplied collection * of objects. Usually this will entail batch loading of permissions for the objects * in the collection. - * * @param a the user for whom permissions should be obtained. * @param objects the (non-null) collection of domain objects for which permissions * should be retrieved. */ void cachePermissionsFor(Authentication a, Collection objects); + } diff --git a/core/src/main/java/org/springframework/security/access/PermissionEvaluator.java b/core/src/main/java/org/springframework/security/access/PermissionEvaluator.java index 58ea8f145a..7c73b6a2a9 100644 --- a/core/src/main/java/org/springframework/security/access/PermissionEvaluator.java +++ b/core/src/main/java/org/springframework/security/access/PermissionEvaluator.java @@ -24,13 +24,12 @@ import org.springframework.security.core.Authentication; * Strategy used in expression evaluation to determine whether a user has a permission or * permissions for a given domain object. * - * * @author Luke Taylor * @since 3.0 */ public interface PermissionEvaluator extends AopInfrastructureBean { + /** - * * @param authentication represents the user in question. Should not be null. * @param targetDomainObject the domain object for which permissions should be * checked. May be null in which case implementations should return false, as the null @@ -39,13 +38,11 @@ public interface PermissionEvaluator extends AopInfrastructureBean { * expression system. Not null. * @return true if the permission is granted, false otherwise */ - boolean hasPermission(Authentication authentication, Object targetDomainObject, - Object permission); + boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission); /** * Alternative method for evaluating a permission where only the identifier of the * target object is available, rather than the target instance itself. - * * @param authentication represents the user in question. Should not be null. * @param targetId the identifier for the object instance (usually a Long) * @param targetType a String representing the target's type (usually a Java @@ -54,6 +51,6 @@ public interface PermissionEvaluator extends AopInfrastructureBean { * expression system. Not null. * @return true if the permission is granted, false otherwise */ - boolean hasPermission(Authentication authentication, Serializable targetId, - String targetType, Object permission); + boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission); + } diff --git a/core/src/main/java/org/springframework/security/access/SecurityConfig.java b/core/src/main/java/org/springframework/security/access/SecurityConfig.java index 67823dfc15..6b5545e77d 100644 --- a/core/src/main/java/org/springframework/security/access/SecurityConfig.java +++ b/core/src/main/java/org/springframework/security/access/SecurityConfig.java @@ -28,6 +28,7 @@ import org.springframework.util.StringUtils; * @author Ben Alex */ public class SecurityConfig implements ConfigAttribute { + // ~ Instance fields // ================================================================================================ @@ -76,8 +77,7 @@ public class SecurityConfig implements ConfigAttribute { public static List createList(String... attributeNames) { Assert.notNull(attributeNames, "You must supply an array of attribute names"); - List attributes = new ArrayList<>( - attributeNames.length); + List attributes = new ArrayList<>(attributeNames.length); for (String attribute : attributeNames) { attributes.add(new SecurityConfig(attribute.trim())); @@ -85,4 +85,5 @@ public class SecurityConfig implements ConfigAttribute { return attributes; } + } diff --git a/core/src/main/java/org/springframework/security/access/SecurityMetadataSource.java b/core/src/main/java/org/springframework/security/access/SecurityMetadataSource.java index 381d2c5875..27a9b1d3ed 100644 --- a/core/src/main/java/org/springframework/security/access/SecurityMetadataSource.java +++ b/core/src/main/java/org/springframework/security/access/SecurityMetadataSource.java @@ -28,22 +28,19 @@ import org.springframework.security.access.intercept.AbstractSecurityInterceptor * @author Ben Alex */ public interface SecurityMetadataSource extends AopInfrastructureBean { + // ~ Methods // ======================================================================================================== /** * Accesses the {@code ConfigAttribute}s that apply to a given secure object. - * * @param object the object being secured - * * @return the attributes that apply to the passed in secured object. Should return an * empty collection if there are no applicable attributes. - * * @throws IllegalArgumentException if the passed object is not of a type supported by * the SecurityMetadataSource implementation */ - Collection getAttributes(Object object) - throws IllegalArgumentException; + Collection getAttributes(Object object) throws IllegalArgumentException; /** * If available, returns all of the {@code ConfigAttribute}s defined by the @@ -51,7 +48,6 @@ public interface SecurityMetadataSource extends AopInfrastructureBean { *

    * This is used by the {@link AbstractSecurityInterceptor} to perform startup time * validation of each {@code ConfigAttribute} configured against it. - * * @return the {@code ConfigAttribute}s or {@code null} if unsupported */ Collection getAllConfigAttributes(); @@ -59,10 +55,9 @@ public interface SecurityMetadataSource extends AopInfrastructureBean { /** * Indicates whether the {@code SecurityMetadataSource} implementation is able to * provide {@code ConfigAttribute}s for the indicated secure object type. - * * @param clazz the class that is being queried - * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); + } diff --git a/core/src/main/java/org/springframework/security/access/annotation/AnnotationMetadataExtractor.java b/core/src/main/java/org/springframework/security/access/annotation/AnnotationMetadataExtractor.java index 8f4544b99b..e226562314 100644 --- a/core/src/main/java/org/springframework/security/access/annotation/AnnotationMetadataExtractor.java +++ b/core/src/main/java/org/springframework/security/access/annotation/AnnotationMetadataExtractor.java @@ -31,4 +31,5 @@ import java.util.*; public interface AnnotationMetadataExtractor { Collection extractAttributes(A securityAnnotation); + } diff --git a/core/src/main/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSource.java b/core/src/main/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSource.java index 6772ccdff0..71dc67b443 100644 --- a/core/src/main/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSource.java +++ b/core/src/main/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSource.java @@ -36,8 +36,7 @@ import org.springframework.security.access.method.AbstractFallbackMethodSecurity * @author Ben Alex * @since 2.0 */ -public class Jsr250MethodSecurityMetadataSource extends - AbstractFallbackMethodSecurityMetadataSource { +public class Jsr250MethodSecurityMetadataSource extends AbstractFallbackMethodSecurityMetadataSource { private String defaultRolePrefix = "ROLE_"; @@ -51,7 +50,6 @@ public class Jsr250MethodSecurityMetadataSource extends *

    * If null or empty, then no default role prefix is used. *

    - * * @param defaultRolePrefix the default prefix to add to roles. Default "ROLE_". */ public void setDefaultRolePrefix(String defaultRolePrefix) { @@ -62,8 +60,7 @@ public class Jsr250MethodSecurityMetadataSource extends return processAnnotations(clazz.getAnnotations()); } - protected Collection findAttributes(Method method, - Class targetClass) { + protected Collection findAttributes(Method method, Class targetClass) { return processAnnotations(AnnotationUtils.getAnnotations(method)); } @@ -111,4 +108,5 @@ public class Jsr250MethodSecurityMetadataSource extends } return defaultRolePrefix + role; } + } diff --git a/core/src/main/java/org/springframework/security/access/annotation/Jsr250SecurityConfig.java b/core/src/main/java/org/springframework/security/access/annotation/Jsr250SecurityConfig.java index 25bab456ee..4456eaf14b 100644 --- a/core/src/main/java/org/springframework/security/access/annotation/Jsr250SecurityConfig.java +++ b/core/src/main/java/org/springframework/security/access/annotation/Jsr250SecurityConfig.java @@ -27,10 +27,10 @@ import javax.annotation.security.DenyAll; * @since 2.0 */ public class Jsr250SecurityConfig extends SecurityConfig { - public static final Jsr250SecurityConfig PERMIT_ALL_ATTRIBUTE = new Jsr250SecurityConfig( - PermitAll.class.getName()); - public static final Jsr250SecurityConfig DENY_ALL_ATTRIBUTE = new Jsr250SecurityConfig( - DenyAll.class.getName()); + + public static final Jsr250SecurityConfig PERMIT_ALL_ATTRIBUTE = new Jsr250SecurityConfig(PermitAll.class.getName()); + + public static final Jsr250SecurityConfig DENY_ALL_ATTRIBUTE = new Jsr250SecurityConfig(DenyAll.class.getName()); public Jsr250SecurityConfig(String role) { super(role); diff --git a/core/src/main/java/org/springframework/security/access/annotation/Jsr250Voter.java b/core/src/main/java/org/springframework/security/access/annotation/Jsr250Voter.java index 9fb6f194e7..9a15090653 100644 --- a/core/src/main/java/org/springframework/security/access/annotation/Jsr250Voter.java +++ b/core/src/main/java/org/springframework/security/access/annotation/Jsr250Voter.java @@ -33,7 +33,6 @@ public class Jsr250Voter implements AccessDecisionVoter { /** * The specified config attribute is supported if its an instance of a * {@link Jsr250SecurityConfig}. - * * @param configAttribute The config attribute. * @return whether the config attribute is supported. */ @@ -43,7 +42,6 @@ public class Jsr250Voter implements AccessDecisionVoter { /** * All classes are supported. - * * @param clazz the class. * @return true */ @@ -56,14 +54,12 @@ public class Jsr250Voter implements AccessDecisionVoter { *

    * If no JSR-250 attributes are found, it will abstain, otherwise it will grant or * deny access based on the attributes that are found. - * * @param authentication The authentication object. * @param object The access object. * @param definition The configuration definition. * @return The vote. */ - public int vote(Authentication authentication, Object object, - Collection definition) { + public int vote(Authentication authentication, Object object, Collection definition) { boolean jsr250AttributeFound = false; for (ConfigAttribute attribute : definition) { @@ -88,4 +84,5 @@ public class Jsr250Voter implements AccessDecisionVoter { return jsr250AttributeFound ? ACCESS_DENIED : ACCESS_ABSTAIN; } + } diff --git a/core/src/main/java/org/springframework/security/access/annotation/Secured.java b/core/src/main/java/org/springframework/security/access/annotation/Secured.java index 28d509ed16..e8640e0af5 100644 --- a/core/src/main/java/org/springframework/security/access/annotation/Secured.java +++ b/core/src/main/java/org/springframework/security/access/annotation/Secured.java @@ -50,10 +50,12 @@ import java.lang.annotation.Target; @Inherited @Documented public @interface Secured { + /** - * Returns the list of security configuration attributes (e.g. ROLE_USER, ROLE_ADMIN). - * + * Returns the list of security configuration attributes (e.g. ROLE_USER, + * ROLE_ADMIN). * @return String[] The secure method attributes */ String[] value(); + } diff --git a/core/src/main/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java b/core/src/main/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java index e74300bb0a..eb8c1d3cb8 100644 --- a/core/src/main/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java +++ b/core/src/main/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSource.java @@ -38,22 +38,21 @@ import org.springframework.util.Assert; * @author Luke Taylor */ @SuppressWarnings({ "unchecked" }) -public class SecuredAnnotationSecurityMetadataSource extends - AbstractFallbackMethodSecurityMetadataSource { +public class SecuredAnnotationSecurityMetadataSource extends AbstractFallbackMethodSecurityMetadataSource { + private AnnotationMetadataExtractor annotationExtractor; + private Class annotationType; public SecuredAnnotationSecurityMetadataSource() { this(new SecuredAnnotationMetadataExtractor()); } - public SecuredAnnotationSecurityMetadataSource( - AnnotationMetadataExtractor annotationMetadataExtractor) { + public SecuredAnnotationSecurityMetadataSource(AnnotationMetadataExtractor annotationMetadataExtractor) { Assert.notNull(annotationMetadataExtractor, "annotationMetadataExtractor cannot be null"); annotationExtractor = annotationMetadataExtractor; annotationType = (Class) GenericTypeResolver - .resolveTypeArgument(annotationExtractor.getClass(), - AnnotationMetadataExtractor.class); + .resolveTypeArgument(annotationExtractor.getClass(), AnnotationMetadataExtractor.class); Assert.notNull(annotationType, () -> annotationExtractor.getClass().getName() + " must supply a generic parameter for AnnotationMetadataExtractor"); } @@ -62,8 +61,7 @@ public class SecuredAnnotationSecurityMetadataSource extends return processAnnotation(AnnotationUtils.findAnnotation(clazz, annotationType)); } - protected Collection findAttributes(Method method, - Class targetClass) { + protected Collection findAttributes(Method method, Class targetClass) { return processAnnotation(AnnotationUtils.findAnnotation(method, annotationType)); } @@ -78,14 +76,14 @@ public class SecuredAnnotationSecurityMetadataSource extends return annotationExtractor.extractAttributes(a); } + } class SecuredAnnotationMetadataExtractor implements AnnotationMetadataExtractor { public Collection extractAttributes(Secured secured) { String[] attributeTokens = secured.value(); - List attributes = new ArrayList<>( - attributeTokens.length); + List attributes = new ArrayList<>(attributeTokens.length); for (String token : attributeTokens) { attributes.add(new SecurityConfig(token)); @@ -93,4 +91,5 @@ class SecuredAnnotationMetadataExtractor implements AnnotationMetadataExtractor< return attributes; } + } diff --git a/core/src/main/java/org/springframework/security/access/event/AbstractAuthorizationEvent.java b/core/src/main/java/org/springframework/security/access/event/AbstractAuthorizationEvent.java index 0e902f7ba5..6bde97aa2a 100644 --- a/core/src/main/java/org/springframework/security/access/event/AbstractAuthorizationEvent.java +++ b/core/src/main/java/org/springframework/security/access/event/AbstractAuthorizationEvent.java @@ -24,15 +24,16 @@ import org.springframework.context.ApplicationEvent; * @author Ben Alex */ public abstract class AbstractAuthorizationEvent extends ApplicationEvent { + // ~ Constructors // =================================================================================================== /** * Construct the event, passing in the secure object being intercepted. - * * @param secureObject the secure object */ public AbstractAuthorizationEvent(Object secureObject) { super(secureObject); } + } diff --git a/core/src/main/java/org/springframework/security/access/event/AuthenticationCredentialsNotFoundEvent.java b/core/src/main/java/org/springframework/security/access/event/AuthenticationCredentialsNotFoundEvent.java index a853f02a94..c60b2095cb 100644 --- a/core/src/main/java/org/springframework/security/access/event/AuthenticationCredentialsNotFoundEvent.java +++ b/core/src/main/java/org/springframework/security/access/event/AuthenticationCredentialsNotFoundEvent.java @@ -28,10 +28,12 @@ import org.springframework.security.authentication.AuthenticationCredentialsNotF * @author Ben Alex */ public class AuthenticationCredentialsNotFoundEvent extends AbstractAuthorizationEvent { + // ~ Instance fields // ================================================================================================ private AuthenticationCredentialsNotFoundException credentialsNotFoundException; + private Collection configAttribs; // ~ Constructors @@ -39,21 +41,18 @@ public class AuthenticationCredentialsNotFoundEvent extends AbstractAuthorizatio /** * Construct the event. - * * @param secureObject the secure object * @param attributes that apply to the secure object * @param credentialsNotFoundException exception returned to the caller (contains * reason) * */ - public AuthenticationCredentialsNotFoundEvent(Object secureObject, - Collection attributes, + public AuthenticationCredentialsNotFoundEvent(Object secureObject, Collection attributes, AuthenticationCredentialsNotFoundException credentialsNotFoundException) { super(secureObject); if ((attributes == null) || (credentialsNotFoundException == null)) { - throw new IllegalArgumentException( - "All parameters are required and cannot be null"); + throw new IllegalArgumentException("All parameters are required and cannot be null"); } this.configAttribs = attributes; @@ -70,4 +69,5 @@ public class AuthenticationCredentialsNotFoundEvent extends AbstractAuthorizatio public AuthenticationCredentialsNotFoundException getCredentialsNotFoundException() { return credentialsNotFoundException; } + } diff --git a/core/src/main/java/org/springframework/security/access/event/AuthorizationFailureEvent.java b/core/src/main/java/org/springframework/security/access/event/AuthorizationFailureEvent.java index 902df7a86d..26374e65f6 100644 --- a/core/src/main/java/org/springframework/security/access/event/AuthorizationFailureEvent.java +++ b/core/src/main/java/org/springframework/security/access/event/AuthorizationFailureEvent.java @@ -35,11 +35,14 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ public class AuthorizationFailureEvent extends AbstractAuthorizationEvent { + // ~ Instance fields // ================================================================================================ private AccessDeniedException accessDeniedException; + private Authentication authentication; + private Collection configAttributes; // ~ Constructors @@ -47,24 +50,19 @@ public class AuthorizationFailureEvent extends AbstractAuthorizationEvent { /** * Construct the event. - * * @param secureObject the secure object * @param attributes that apply to the secure object * @param authentication that was found in the SecurityContextHolder * @param accessDeniedException that was returned by the * AccessDecisionManager - * * @throws IllegalArgumentException if any null arguments are presented. */ - public AuthorizationFailureEvent(Object secureObject, - Collection attributes, Authentication authentication, - AccessDeniedException accessDeniedException) { + public AuthorizationFailureEvent(Object secureObject, Collection attributes, + Authentication authentication, AccessDeniedException accessDeniedException) { super(secureObject); - if ((attributes == null) || (authentication == null) - || (accessDeniedException == null)) { - throw new IllegalArgumentException( - "All parameters are required and cannot be null"); + if ((attributes == null) || (authentication == null) || (accessDeniedException == null)) { + throw new IllegalArgumentException("All parameters are required and cannot be null"); } this.configAttributes = attributes; @@ -86,4 +84,5 @@ public class AuthorizationFailureEvent extends AbstractAuthorizationEvent { public Collection getConfigAttributes() { return configAttributes; } + } diff --git a/core/src/main/java/org/springframework/security/access/event/AuthorizedEvent.java b/core/src/main/java/org/springframework/security/access/event/AuthorizedEvent.java index 43a4fc3c4d..da8846c7d7 100644 --- a/core/src/main/java/org/springframework/security/access/event/AuthorizedEvent.java +++ b/core/src/main/java/org/springframework/security/access/event/AuthorizedEvent.java @@ -30,10 +30,12 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ public class AuthorizedEvent extends AbstractAuthorizationEvent { + // ~ Instance fields // ================================================================================================ private Authentication authentication; + private Collection configAttributes; // ~ Constructors @@ -41,19 +43,16 @@ public class AuthorizedEvent extends AbstractAuthorizationEvent { /** * Construct the event. - * * @param secureObject the secure object * @param attributes that apply to the secure object * @param authentication that successfully called the secure object * */ - public AuthorizedEvent(Object secureObject, Collection attributes, - Authentication authentication) { + public AuthorizedEvent(Object secureObject, Collection attributes, Authentication authentication) { super(secureObject); if ((attributes == null) || (authentication == null)) { - throw new IllegalArgumentException( - "All parameters are required and cannot be null"); + throw new IllegalArgumentException("All parameters are required and cannot be null"); } this.configAttributes = attributes; @@ -70,4 +69,5 @@ public class AuthorizedEvent extends AbstractAuthorizationEvent { public Collection getConfigAttributes() { return configAttributes; } + } diff --git a/core/src/main/java/org/springframework/security/access/event/LoggerListener.java b/core/src/main/java/org/springframework/security/access/event/LoggerListener.java index ed05cf8248..ce0d7c3f04 100644 --- a/core/src/main/java/org/springframework/security/access/event/LoggerListener.java +++ b/core/src/main/java/org/springframework/security/access/event/LoggerListener.java @@ -30,6 +30,7 @@ import org.springframework.context.ApplicationListener; * @author Ben Alex */ public class LoggerListener implements ApplicationListener { + // ~ Static fields/initializers // ===================================================================================== @@ -43,10 +44,8 @@ public class LoggerListener implements ApplicationListener implements - SecurityExpressionHandler, ApplicationContextAware { +public abstract class AbstractSecurityExpressionHandler + implements SecurityExpressionHandler, ApplicationContextAware { + private ExpressionParser expressionParser = new SpelExpressionParser(); + private BeanResolver br; + private RoleHierarchy roleHierarchy; + private PermissionEvaluator permissionEvaluator = new DenyAllPermissionEvaluator(); public final ExpressionParser getExpressionParser() { @@ -55,18 +59,14 @@ public abstract class AbstractSecurityExpressionHandler implements /** * Invokes the internal template methods to create {@code StandardEvaluationContext} * and {@code SecurityExpressionRoot} objects. - * * @param authentication the current authentication object * @param invocation the invocation (filter, method, channel) * @return the context object for use in evaluating the expression, populated with a * suitable root object. */ - public final EvaluationContext createEvaluationContext(Authentication authentication, - T invocation) { - SecurityExpressionOperations root = createSecurityExpressionRoot(authentication, - invocation); - StandardEvaluationContext ctx = createEvaluationContextInternal(authentication, - invocation); + public final EvaluationContext createEvaluationContext(Authentication authentication, T invocation) { + SecurityExpressionOperations root = createSecurityExpressionRoot(authentication, invocation); + StandardEvaluationContext ctx = createEvaluationContextInternal(authentication, invocation); ctx.setBeanResolver(br); ctx.setRootObject(root); @@ -79,27 +79,24 @@ public abstract class AbstractSecurityExpressionHandler implements * The returned object will have a {@code SecurityExpressionRootPropertyAccessor} * added, allowing beans in the {@code ApplicationContext} to be accessed via * expression properties. - * * @param authentication the current authentication object * @param invocation the invocation (filter, method, channel) * @return A {@code StandardEvaluationContext} or potentially a custom subclass if * overridden. */ - protected StandardEvaluationContext createEvaluationContextInternal( - Authentication authentication, T invocation) { + protected StandardEvaluationContext createEvaluationContextInternal(Authentication authentication, T invocation) { return new StandardEvaluationContext(); } /** * Implement in order to create a root object of the correct type for the supported * invocation type. - * * @param authentication the current authentication object * @param invocation the invocation (filter, method, channel) * @return the object wh */ - protected abstract SecurityExpressionOperations createSecurityExpressionRoot( - Authentication authentication, T invocation); + protected abstract SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, + T invocation); protected RoleHierarchy getRoleHierarchy() { return roleHierarchy; @@ -120,4 +117,5 @@ public abstract class AbstractSecurityExpressionHandler implements public void setApplicationContext(ApplicationContext applicationContext) { br = new BeanFactoryResolver(applicationContext); } + } diff --git a/core/src/main/java/org/springframework/security/access/expression/DenyAllPermissionEvaluator.java b/core/src/main/java/org/springframework/security/access/expression/DenyAllPermissionEvaluator.java index 4d9708ea14..97858f229b 100644 --- a/core/src/main/java/org/springframework/security/access/expression/DenyAllPermissionEvaluator.java +++ b/core/src/main/java/org/springframework/security/access/expression/DenyAllPermissionEvaluator.java @@ -36,20 +36,19 @@ public class DenyAllPermissionEvaluator implements PermissionEvaluator { /** * @return false always */ - public boolean hasPermission(Authentication authentication, Object target, - Object permission) { - logger.warn("Denying user " + authentication.getName() + " permission '" - + permission + "' on object " + target); + public boolean hasPermission(Authentication authentication, Object target, Object permission) { + logger.warn( + "Denying user " + authentication.getName() + " permission '" + permission + "' on object " + target); return false; } /** * @return false always */ - public boolean hasPermission(Authentication authentication, Serializable targetId, - String targetType, Object permission) { - logger.warn("Denying user " + authentication.getName() + " permission '" - + permission + "' on object with Id '" + targetId); + public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, + Object permission) { + logger.warn("Denying user " + authentication.getName() + " permission '" + permission + "' on object with Id '" + + targetId); return false; } diff --git a/core/src/main/java/org/springframework/security/access/expression/ExpressionUtils.java b/core/src/main/java/org/springframework/security/access/expression/ExpressionUtils.java index 70cf8ab5a5..8a3a272eca 100644 --- a/core/src/main/java/org/springframework/security/access/expression/ExpressionUtils.java +++ b/core/src/main/java/org/springframework/security/access/expression/ExpressionUtils.java @@ -26,8 +26,8 @@ public final class ExpressionUtils { return expr.getValue(ctx, Boolean.class); } catch (EvaluationException e) { - throw new IllegalArgumentException("Failed to evaluate expression '" - + expr.getExpressionString() + "'", e); + throw new IllegalArgumentException("Failed to evaluate expression '" + expr.getExpressionString() + "'", e); } } + } diff --git a/core/src/main/java/org/springframework/security/access/expression/SecurityExpressionHandler.java b/core/src/main/java/org/springframework/security/access/expression/SecurityExpressionHandler.java index 73f5ac1636..23cb59bd66 100644 --- a/core/src/main/java/org/springframework/security/access/expression/SecurityExpressionHandler.java +++ b/core/src/main/java/org/springframework/security/access/expression/SecurityExpressionHandler.java @@ -28,6 +28,7 @@ import org.springframework.security.core.Authentication; * @since 3.1 */ public interface SecurityExpressionHandler extends AopInfrastructureBean { + /** * @return an expression parser for the expressions used by the implementation. */ @@ -38,4 +39,5 @@ public interface SecurityExpressionHandler extends AopInfrastructureBean { * invocation type. */ EvaluationContext createEvaluationContext(Authentication authentication, T invocation); + } diff --git a/core/src/main/java/org/springframework/security/access/expression/SecurityExpressionOperations.java b/core/src/main/java/org/springframework/security/access/expression/SecurityExpressionOperations.java index 01ace0e04a..95805ec65b 100644 --- a/core/src/main/java/org/springframework/security/access/expression/SecurityExpressionOperations.java +++ b/core/src/main/java/org/springframework/security/access/expression/SecurityExpressionOperations.java @@ -59,7 +59,6 @@ public interface SecurityExpressionOperations { * implementation may convert it to use "ROLE_USER" instead. The way in which the role * is converted may depend on the implementation settings. *

    - * * @param role the authority to test (i.e. "USER") * @return true if the authority is found, else false */ @@ -71,12 +70,11 @@ public interface SecurityExpressionOperations { * within {@link Authentication#getAuthorities()}. *

    *

    - * This is a similar to hasAnyAuthority except that this method implies - * that the String passed in is a role. For example, if "USER" is passed in the - * implementation may convert it to use "ROLE_USER" instead. The way in which the role - * is converted may depend on the implementation settings. + * This is a similar to hasAnyAuthority except that this method implies that the + * String passed in is a role. For example, if "USER" is passed in the implementation + * may convert it to use "ROLE_USER" instead. The way in which the role is converted + * may depend on the implementation settings. *

    - * * @param roles the authorities to test (i.e. "USER", "ADMIN") * @return true if any of the authorities is found, else false */ diff --git a/core/src/main/java/org/springframework/security/access/expression/SecurityExpressionRoot.java b/core/src/main/java/org/springframework/security/access/expression/SecurityExpressionRoot.java index 97b201d085..9e37c514cb 100644 --- a/core/src/main/java/org/springframework/security/access/expression/SecurityExpressionRoot.java +++ b/core/src/main/java/org/springframework/security/access/expression/SecurityExpressionRoot.java @@ -33,10 +33,15 @@ import org.springframework.security.core.authority.AuthorityUtils; * @since 3.0 */ public abstract class SecurityExpressionRoot implements SecurityExpressionOperations { + protected final Authentication authentication; + private AuthenticationTrustResolver trustResolver; + private RoleHierarchy roleHierarchy; + private Set roles; + private String defaultRolePrefix = "ROLE_"; /** Allows "permitAll" expression */ @@ -44,11 +49,17 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat /** Allows "denyAll" expression */ public final boolean denyAll = false; + private PermissionEvaluator permissionEvaluator; + public final String read = "read"; + public final String write = "write"; + public final String create = "create"; + public final String delete = "delete"; + public final String admin = "administration"; /** @@ -116,8 +127,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat } public final boolean isFullyAuthenticated() { - return !trustResolver.isAnonymous(authentication) - && !trustResolver.isRememberMe(authentication); + return !trustResolver.isAnonymous(authentication) && !trustResolver.isRememberMe(authentication); } /** @@ -148,7 +158,6 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat *

    * If null or empty, then no default role prefix is used. *

    - * * @param defaultRolePrefix the default prefix to add to roles. Default "ROLE_". */ public void setDefaultRolePrefix(String defaultRolePrefix) { @@ -157,12 +166,10 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat private Set getAuthoritySet() { if (roles == null) { - Collection userAuthorities = authentication - .getAuthorities(); + Collection userAuthorities = authentication.getAuthorities(); if (roleHierarchy != null) { - userAuthorities = roleHierarchy - .getReachableGrantedAuthorities(userAuthorities); + userAuthorities = roleHierarchy.getReachableGrantedAuthorities(userAuthorities); } roles = AuthorityUtils.authorityListToSet(userAuthorities); @@ -176,8 +183,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat } public boolean hasPermission(Object targetId, String targetType, Object permission) { - return permissionEvaluator.hasPermission(authentication, (Serializable) targetId, - targetType, permission); + return permissionEvaluator.hasPermission(authentication, (Serializable) targetId, targetType, permission); } public void setPermissionEvaluator(PermissionEvaluator permissionEvaluator) { @@ -187,7 +193,6 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat /** * Prefixes role with defaultRolePrefix if defaultRolePrefix is non-null and if role * does not already start with defaultRolePrefix. - * * @param defaultRolePrefix * @param role * @return @@ -204,4 +209,5 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat } return defaultRolePrefix + role; } + } diff --git a/core/src/main/java/org/springframework/security/access/expression/method/AbstractExpressionBasedMethodConfigAttribute.java b/core/src/main/java/org/springframework/security/access/expression/method/AbstractExpressionBasedMethodConfigAttribute.java index cafad53385..8a5c8ed2d1 100644 --- a/core/src/main/java/org/springframework/security/access/expression/method/AbstractExpressionBasedMethodConfigAttribute.java +++ b/core/src/main/java/org/springframework/security/access/expression/method/AbstractExpressionBasedMethodConfigAttribute.java @@ -33,30 +33,29 @@ import org.springframework.util.Assert; * @since 3.0 */ abstract class AbstractExpressionBasedMethodConfigAttribute implements ConfigAttribute { + private final Expression filterExpression; + private final Expression authorizeExpression; /** * Parses the supplied expressions as Spring-EL. */ - AbstractExpressionBasedMethodConfigAttribute(String filterExpression, - String authorizeExpression) throws ParseException { + AbstractExpressionBasedMethodConfigAttribute(String filterExpression, String authorizeExpression) + throws ParseException { Assert.isTrue(filterExpression != null || authorizeExpression != null, "Filter and authorization Expressions cannot both be null"); SpelExpressionParser parser = new SpelExpressionParser(); - this.filterExpression = filterExpression == null ? null : parser - .parseExpression(filterExpression); - this.authorizeExpression = authorizeExpression == null ? null : parser - .parseExpression(authorizeExpression); + this.filterExpression = filterExpression == null ? null : parser.parseExpression(filterExpression); + this.authorizeExpression = authorizeExpression == null ? null : parser.parseExpression(authorizeExpression); } - AbstractExpressionBasedMethodConfigAttribute(Expression filterExpression, - Expression authorizeExpression) throws ParseException { + AbstractExpressionBasedMethodConfigAttribute(Expression filterExpression, Expression authorizeExpression) + throws ParseException { Assert.isTrue(filterExpression != null || authorizeExpression != null, "Filter and authorization Expressions cannot both be null"); this.filterExpression = filterExpression == null ? null : filterExpression; - this.authorizeExpression = authorizeExpression == null ? null - : authorizeExpression; + this.authorizeExpression = authorizeExpression == null ? null : authorizeExpression; } Expression getFilterExpression() { @@ -70,4 +69,5 @@ abstract class AbstractExpressionBasedMethodConfigAttribute implements ConfigAtt public String getAttribute() { return null; } + } diff --git a/core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java b/core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java index 26bdbf154a..233d364a76 100644 --- a/core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java +++ b/core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java @@ -49,15 +49,17 @@ import org.springframework.util.Assert; * @author Luke Taylor * @since 3.0 */ -public class DefaultMethodSecurityExpressionHandler extends - AbstractSecurityExpressionHandler implements - MethodSecurityExpressionHandler { +public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpressionHandler + implements MethodSecurityExpressionHandler { protected final Log logger = LogFactory.getLog(getClass()); private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); + private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultSecurityParameterNameDiscoverer(); + private PermissionCacheOptimizer permissionCacheOptimizer = null; + private String defaultRolePrefix = "ROLE_"; public DefaultMethodSecurityExpressionHandler() { @@ -67,18 +69,16 @@ public class DefaultMethodSecurityExpressionHandler extends * Uses a {@link MethodSecurityEvaluationContext} as the EvaluationContext * implementation. */ - public StandardEvaluationContext createEvaluationContextInternal(Authentication auth, - MethodInvocation mi) { + public StandardEvaluationContext createEvaluationContextInternal(Authentication auth, MethodInvocation mi) { return new MethodSecurityEvaluationContext(auth, mi, getParameterNameDiscoverer()); } /** * Creates the root object for expression evaluation. */ - protected MethodSecurityExpressionOperations createSecurityExpressionRoot( - Authentication authentication, MethodInvocation invocation) { - MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot( - authentication); + protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, + MethodInvocation invocation) { + MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(authentication); root.setThis(invocation.getThis()); root.setPermissionEvaluator(getPermissionEvaluator()); root.setTrustResolver(getTrustResolver()); @@ -89,24 +89,22 @@ public class DefaultMethodSecurityExpressionHandler extends } /** - * Filters the {@code filterTarget} object (which must be either a collection, array, map - * or stream), by evaluating the supplied expression. + * Filters the {@code filterTarget} object (which must be either a collection, array, + * map or stream), by evaluating the supplied expression. *

    - * If a {@code Collection} or {@code Map} is used, the original instance will be modified to contain - * the elements for which the permission expression evaluates to {@code true}. For an - * array, a new array instance will be returned. + * If a {@code Collection} or {@code Map} is used, the original instance will be + * modified to contain the elements for which the permission expression evaluates to + * {@code true}. For an array, a new array instance will be returned. */ @SuppressWarnings("unchecked") - public Object filter(Object filterTarget, Expression filterExpression, - EvaluationContext ctx) { - MethodSecurityExpressionOperations rootObject = (MethodSecurityExpressionOperations) ctx - .getRootObject().getValue(); + public Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx) { + MethodSecurityExpressionOperations rootObject = (MethodSecurityExpressionOperations) ctx.getRootObject() + .getValue(); final boolean debug = logger.isDebugEnabled(); List retainList; if (debug) { - logger.debug("Filtering with expression: " - + filterExpression.getExpressionString()); + logger.debug("Filtering with expression: " + filterExpression.getExpressionString()); } if (filterTarget instanceof Collection) { @@ -114,13 +112,11 @@ public class DefaultMethodSecurityExpressionHandler extends retainList = new ArrayList(collection.size()); if (debug) { - logger.debug("Filtering collection with " + collection.size() - + " elements"); + logger.debug("Filtering collection with " + collection.size() + " elements"); } if (permissionCacheOptimizer != null) { - permissionCacheOptimizer.cachePermissionsFor( - rootObject.getAuthentication(), collection); + permissionCacheOptimizer.cachePermissionsFor(rootObject.getAuthentication(), collection); } for (Object filterObject : (Collection) filterTarget) { @@ -150,8 +146,7 @@ public class DefaultMethodSecurityExpressionHandler extends } if (permissionCacheOptimizer != null) { - permissionCacheOptimizer.cachePermissionsFor( - rootObject.getAuthentication(), Arrays.asList(array)); + permissionCacheOptimizer.cachePermissionsFor(rootObject.getAuthentication(), Arrays.asList(array)); } for (Object o : array) { @@ -166,8 +161,8 @@ public class DefaultMethodSecurityExpressionHandler extends logger.debug("Retaining elements: " + retainList); } - Object[] filtered = (Object[]) Array.newInstance(filterTarget.getClass() - .getComponentType(), retainList.size()); + Object[] filtered = (Object[]) Array.newInstance(filterTarget.getClass().getComponentType(), + retainList.size()); for (int i = 0; i < retainList.size(); i++) { filtered[i] = retainList.get(i); } @@ -207,19 +202,16 @@ public class DefaultMethodSecurityExpressionHandler extends return original.filter(filterObject -> { rootObject.setFilterObject(filterObject); return ExpressionUtils.evaluateAsBoolean(filterExpression, ctx); - }) - .onClose(original::close); + }).onClose(original::close); } throw new IllegalArgumentException( - "Filter target must be a collection, array, map or stream type, but was " - + filterTarget); + "Filter target must be a collection, array, map or stream type, but was " + filterTarget); } /** * Sets the {@link AuthenticationTrustResolver} to be used. The default is * {@link AuthenticationTrustResolverImpl}. - * * @param trustResolver the {@link AuthenticationTrustResolver} to use. Cannot be * null. */ @@ -230,7 +222,7 @@ public class DefaultMethodSecurityExpressionHandler extends /** * @return The current {@link AuthenticationTrustResolver} - */ + */ protected AuthenticationTrustResolver getTrustResolver() { return trustResolver; } @@ -246,33 +238,32 @@ public class DefaultMethodSecurityExpressionHandler extends /** * @return The current {@link ParameterNameDiscoverer} - */ + */ protected ParameterNameDiscoverer getParameterNameDiscoverer() { return parameterNameDiscoverer; } - public void setPermissionCacheOptimizer( - PermissionCacheOptimizer permissionCacheOptimizer) { + public void setPermissionCacheOptimizer(PermissionCacheOptimizer permissionCacheOptimizer) { this.permissionCacheOptimizer = permissionCacheOptimizer; } public void setReturnObject(Object returnObject, EvaluationContext ctx) { - ((MethodSecurityExpressionOperations) ctx.getRootObject().getValue()) - .setReturnObject(returnObject); + ((MethodSecurityExpressionOperations) ctx.getRootObject().getValue()).setReturnObject(returnObject); } /** *

    - * Sets the default prefix to be added to {@link org.springframework.security.access.expression.SecurityExpressionRoot#hasAnyRole(String...)} or - * {@link org.springframework.security.access.expression.SecurityExpressionRoot#hasRole(String)}. For example, if hasRole("ADMIN") or hasRole("ROLE_ADMIN") - * is passed in, then the role ROLE_ADMIN will be used when the defaultRolePrefix is - * "ROLE_" (default). + * Sets the default prefix to be added to + * {@link org.springframework.security.access.expression.SecurityExpressionRoot#hasAnyRole(String...)} + * or + * {@link org.springframework.security.access.expression.SecurityExpressionRoot#hasRole(String)}. + * For example, if hasRole("ADMIN") or hasRole("ROLE_ADMIN") is passed in, then the + * role ROLE_ADMIN will be used when the defaultRolePrefix is "ROLE_" (default). *

    * *

    * If null or empty, then no default role prefix is used. *

    - * * @param defaultRolePrefix the default prefix to add to roles. Default "ROLE_". */ public void setDefaultRolePrefix(String defaultRolePrefix) { @@ -281,8 +272,9 @@ public class DefaultMethodSecurityExpressionHandler extends /** * @return The default role prefix - */ + */ protected String getDefaultRolePrefix() { return defaultRolePrefix; } + } diff --git a/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java b/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java index 2d96262dfa..e12ea859da 100644 --- a/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java +++ b/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedAnnotationAttributeFactory.java @@ -30,53 +30,49 @@ import org.springframework.security.access.prepost.PrePostInvocationAttributeFac * @author Rob Winch * @since 3.0 */ -public class ExpressionBasedAnnotationAttributeFactory implements - PrePostInvocationAttributeFactory { +public class ExpressionBasedAnnotationAttributeFactory implements PrePostInvocationAttributeFactory { + private final Object parserLock = new Object(); + private ExpressionParser parser; + private MethodSecurityExpressionHandler handler; - public ExpressionBasedAnnotationAttributeFactory( - MethodSecurityExpressionHandler handler) { + public ExpressionBasedAnnotationAttributeFactory(MethodSecurityExpressionHandler handler) { this.handler = handler; } - public PreInvocationAttribute createPreInvocationAttribute(String preFilterAttribute, - String filterObject, String preAuthorizeAttribute) { + public PreInvocationAttribute createPreInvocationAttribute(String preFilterAttribute, String filterObject, + String preAuthorizeAttribute) { try { // TODO: Optimization of permitAll ExpressionParser parser = getParser(); - Expression preAuthorizeExpression = preAuthorizeAttribute == null ? parser - .parseExpression("permitAll") : parser - .parseExpression(preAuthorizeAttribute); - Expression preFilterExpression = preFilterAttribute == null ? null : parser - .parseExpression(preFilterAttribute); - return new PreInvocationExpressionAttribute(preFilterExpression, - filterObject, preAuthorizeExpression); + Expression preAuthorizeExpression = preAuthorizeAttribute == null ? parser.parseExpression("permitAll") + : parser.parseExpression(preAuthorizeAttribute); + Expression preFilterExpression = preFilterAttribute == null ? null + : parser.parseExpression(preFilterAttribute); + return new PreInvocationExpressionAttribute(preFilterExpression, filterObject, preAuthorizeExpression); } catch (ParseException e) { - throw new IllegalArgumentException("Failed to parse expression '" - + e.getExpressionString() + "'", e); + throw new IllegalArgumentException("Failed to parse expression '" + e.getExpressionString() + "'", e); } } - public PostInvocationAttribute createPostInvocationAttribute( - String postFilterAttribute, String postAuthorizeAttribute) { + public PostInvocationAttribute createPostInvocationAttribute(String postFilterAttribute, + String postAuthorizeAttribute) { try { ExpressionParser parser = getParser(); Expression postAuthorizeExpression = postAuthorizeAttribute == null ? null : parser.parseExpression(postAuthorizeAttribute); - Expression postFilterExpression = postFilterAttribute == null ? null : parser - .parseExpression(postFilterAttribute); + Expression postFilterExpression = postFilterAttribute == null ? null + : parser.parseExpression(postFilterAttribute); if (postFilterExpression != null || postAuthorizeExpression != null) { - return new PostInvocationExpressionAttribute(postFilterExpression, - postAuthorizeExpression); + return new PostInvocationExpressionAttribute(postFilterExpression, postAuthorizeExpression); } } catch (ParseException e) { - throw new IllegalArgumentException("Failed to parse expression '" - + e.getExpressionString() + "'", e); + throw new IllegalArgumentException("Failed to parse expression '" + e.getExpressionString() + "'", e); } return null; @@ -84,7 +80,6 @@ public class ExpressionBasedAnnotationAttributeFactory implements /** * Delay the lookup of the {@link ExpressionParser} to prevent SEC-2136 - * * @return */ private ExpressionParser getParser() { @@ -97,4 +92,5 @@ public class ExpressionBasedAnnotationAttributeFactory implements } return this.parser; } + } diff --git a/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPostInvocationAdvice.java b/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPostInvocationAdvice.java index 8dd739804f..54c0c88911 100644 --- a/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPostInvocationAdvice.java +++ b/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPostInvocationAdvice.java @@ -27,27 +27,23 @@ import org.springframework.security.access.prepost.PostInvocationAuthorizationAd import org.springframework.security.core.Authentication; /** - * * @author Luke Taylor * @since 3.0 */ -public class ExpressionBasedPostInvocationAdvice implements - PostInvocationAuthorizationAdvice { +public class ExpressionBasedPostInvocationAdvice implements PostInvocationAuthorizationAdvice { + protected final Log logger = LogFactory.getLog(getClass()); private final MethodSecurityExpressionHandler expressionHandler; - public ExpressionBasedPostInvocationAdvice( - MethodSecurityExpressionHandler expressionHandler) { + public ExpressionBasedPostInvocationAdvice(MethodSecurityExpressionHandler expressionHandler) { this.expressionHandler = expressionHandler; } - public Object after(Authentication authentication, MethodInvocation mi, - PostInvocationAttribute postAttr, Object returnedObject) - throws AccessDeniedException { + public Object after(Authentication authentication, MethodInvocation mi, PostInvocationAttribute postAttr, + Object returnedObject) throws AccessDeniedException { PostInvocationExpressionAttribute pia = (PostInvocationExpressionAttribute) postAttr; - EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, - mi); + EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, mi); Expression postFilter = pia.getFilterExpression(); Expression postAuthorize = pia.getAuthorizeExpression(); @@ -57,8 +53,7 @@ public class ExpressionBasedPostInvocationAdvice implements } if (returnedObject != null) { - returnedObject = expressionHandler - .filter(returnedObject, postFilter, ctx); + returnedObject = expressionHandler.filter(returnedObject, postFilter, ctx); } else { if (logger.isDebugEnabled()) { @@ -69,8 +64,7 @@ public class ExpressionBasedPostInvocationAdvice implements expressionHandler.setReturnObject(returnedObject, ctx); - if (postAuthorize != null - && !ExpressionUtils.evaluateAsBoolean(postAuthorize, ctx)) { + if (postAuthorize != null && !ExpressionUtils.evaluateAsBoolean(postAuthorize, ctx)) { if (logger.isDebugEnabled()) { logger.debug("PostAuthorize expression rejected access"); } @@ -79,4 +73,5 @@ public class ExpressionBasedPostInvocationAdvice implements return returnedObject; } + } diff --git a/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java b/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java index c4f11aa6f8..477c6ab361 100644 --- a/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java +++ b/core/src/main/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdvice.java @@ -34,15 +34,13 @@ import org.springframework.security.core.Authentication; * @author Luke Taylor * @since 3.0 */ -public class ExpressionBasedPreInvocationAdvice implements - PreInvocationAuthorizationAdvice { +public class ExpressionBasedPreInvocationAdvice implements PreInvocationAuthorizationAdvice { + private MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); - public boolean before(Authentication authentication, MethodInvocation mi, - PreInvocationAttribute attr) { + public boolean before(Authentication authentication, MethodInvocation mi, PreInvocationAttribute attr) { PreInvocationExpressionAttribute preAttr = (PreInvocationExpressionAttribute) attr; - EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, - mi); + EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, mi); Expression preFilter = preAttr.getFilterExpression(); Expression preAuthorize = preAttr.getAuthorizeExpression(); @@ -59,16 +57,14 @@ public class ExpressionBasedPreInvocationAdvice implements return ExpressionUtils.evaluateAsBoolean(preAuthorize, ctx); } - private Object findFilterTarget(String filterTargetName, EvaluationContext ctx, - MethodInvocation mi) { + private Object findFilterTarget(String filterTargetName, EvaluationContext ctx, MethodInvocation mi) { Object filterTarget = null; if (filterTargetName.length() > 0) { filterTarget = ctx.lookupVariable(filterTargetName); if (filterTarget == null) { throw new IllegalArgumentException( - "Filter target was null, or no argument with name " - + filterTargetName + " found in method"); + "Filter target was null, or no argument with name " + filterTargetName + " found in method"); } } else if (mi.getArguments().length == 1) { @@ -77,19 +73,18 @@ public class ExpressionBasedPreInvocationAdvice implements filterTarget = arg; } if (filterTarget == null) { - throw new IllegalArgumentException( - "A PreFilter expression was set but the method argument type" - + arg.getClass() + " is not filterable"); + throw new IllegalArgumentException("A PreFilter expression was set but the method argument type" + + arg.getClass() + " is not filterable"); } - } else if (mi.getArguments().length > 1) { + } + else if (mi.getArguments().length > 1) { throw new IllegalArgumentException( "Unable to determine the method argument for filtering. Specify the filter target."); } if (filterTarget.getClass().isArray()) { throw new IllegalArgumentException( - "Pre-filtering on array types is not supported. " - + "Using a Collection will solve this problem"); + "Pre-filtering on array types is not supported. " + "Using a Collection will solve this problem"); } return filterTarget; @@ -98,4 +93,5 @@ public class ExpressionBasedPreInvocationAdvice implements public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) { this.expressionHandler = expressionHandler; } + } diff --git a/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContext.java b/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContext.java index 5ce94731e7..fe26a6fded 100644 --- a/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContext.java +++ b/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContext.java @@ -37,8 +37,8 @@ import org.springframework.security.core.parameters.DefaultSecurityParameterName * @since 3.0 */ class MethodSecurityEvaluationContext extends MethodBasedEvaluationContext { - private static final Log logger = LogFactory - .getLog(MethodSecurityEvaluationContext.class); + + private static final Log logger = LogFactory.getLog(MethodSecurityEvaluationContext.class); /** * Intended for testing. Don't use in practice as it creates a new parameter resolver @@ -57,4 +57,5 @@ class MethodSecurityEvaluationContext extends MethodBasedEvaluationContext { private static Method getSpecificMethod(MethodInvocation mi) { return AopUtils.getMostSpecificMethod(mi.getMethod(), AopProxyUtils.ultimateTargetClass(mi.getThis())); } + } diff --git a/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionHandler.java b/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionHandler.java index efebcca9b4..bd0a09c1e7 100644 --- a/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionHandler.java +++ b/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionHandler.java @@ -27,11 +27,10 @@ import org.springframework.security.access.expression.SecurityExpressionHandler; * @author Luke Taylor * @since 3.0 */ -public interface MethodSecurityExpressionHandler extends - SecurityExpressionHandler { +public interface MethodSecurityExpressionHandler extends SecurityExpressionHandler { + /** * Filters a target collection or array. Only applies to method invocations. - * * @param filterTarget the array or collection to be filtered. * @param filterExpression the expression which should be used as the filter * condition. If it returns false on evaluation, the object will be removed from the @@ -45,7 +44,6 @@ public interface MethodSecurityExpressionHandler extends /** * Used to inform the expression system of the return object for the given evaluation * context. Only applies to method invocations. - * * @param returnObject the return object value * @param ctx the context within which the object should be set (as created through a * call to diff --git a/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionOperations.java b/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionOperations.java index 24863d6bed..e3af4e1e82 100644 --- a/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionOperations.java +++ b/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionOperations.java @@ -25,6 +25,7 @@ import org.springframework.security.access.expression.SecurityExpressionOperatio * @since 3.1.1 */ public interface MethodSecurityExpressionOperations extends SecurityExpressionOperations { + void setFilterObject(Object filterObject); Object getFilterObject(); @@ -34,4 +35,5 @@ public interface MethodSecurityExpressionOperations extends SecurityExpressionOp Object getReturnObject(); Object getThis(); + } diff --git a/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java b/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java index 0e8c47c7a5..7c3f52b881 100644 --- a/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java +++ b/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java @@ -24,10 +24,12 @@ import org.springframework.security.core.Authentication; * @author Luke Taylor * @since 3.0 */ -class MethodSecurityExpressionRoot extends SecurityExpressionRoot implements - MethodSecurityExpressionOperations { +class MethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations { + private Object filterObject; + private Object returnObject; + private Object target; MethodSecurityExpressionRoot(Authentication a) { @@ -54,7 +56,6 @@ class MethodSecurityExpressionRoot extends SecurityExpressionRoot implements * Sets the "this" property for use in expressions. Typically this will be the "this" * property of the {@code JoinPoint} representing the method invocation which is being * protected. - * * @param target the target object on which the method in is being invoked. */ void setThis(Object target) { @@ -64,4 +65,5 @@ class MethodSecurityExpressionRoot extends SecurityExpressionRoot implements public Object getThis() { return target; } + } diff --git a/core/src/main/java/org/springframework/security/access/expression/method/PostInvocationExpressionAttribute.java b/core/src/main/java/org/springframework/security/access/expression/method/PostInvocationExpressionAttribute.java index d308dcb13f..dc1463ca5c 100644 --- a/core/src/main/java/org/springframework/security/access/expression/method/PostInvocationExpressionAttribute.java +++ b/core/src/main/java/org/springframework/security/access/expression/method/PostInvocationExpressionAttribute.java @@ -20,20 +20,18 @@ import org.springframework.expression.ParseException; import org.springframework.security.access.prepost.PostInvocationAttribute; /** - * * @author Luke Taylor * @since 3.0 */ -class PostInvocationExpressionAttribute extends - AbstractExpressionBasedMethodConfigAttribute implements PostInvocationAttribute { +class PostInvocationExpressionAttribute extends AbstractExpressionBasedMethodConfigAttribute + implements PostInvocationAttribute { - PostInvocationExpressionAttribute(String filterExpression, String authorizeExpression) - throws ParseException { + PostInvocationExpressionAttribute(String filterExpression, String authorizeExpression) throws ParseException { super(filterExpression, authorizeExpression); } - PostInvocationExpressionAttribute(Expression filterExpression, - Expression authorizeExpression) throws ParseException { + PostInvocationExpressionAttribute(Expression filterExpression, Expression authorizeExpression) + throws ParseException { super(filterExpression, authorizeExpression); } @@ -42,11 +40,9 @@ class PostInvocationExpressionAttribute extends StringBuilder sb = new StringBuilder(); Expression authorize = getAuthorizeExpression(); Expression filter = getFilterExpression(); - sb.append("[authorize: '").append( - authorize == null ? "null" : authorize.getExpressionString()); - sb.append("', filter: '") - .append(filter == null ? "null" : filter.getExpressionString()) - .append("']"); + sb.append("[authorize: '").append(authorize == null ? "null" : authorize.getExpressionString()); + sb.append("', filter: '").append(filter == null ? "null" : filter.getExpressionString()).append("']"); return sb.toString(); } + } diff --git a/core/src/main/java/org/springframework/security/access/expression/method/PreInvocationExpressionAttribute.java b/core/src/main/java/org/springframework/security/access/expression/method/PreInvocationExpressionAttribute.java index be871fa633..950998a785 100644 --- a/core/src/main/java/org/springframework/security/access/expression/method/PreInvocationExpressionAttribute.java +++ b/core/src/main/java/org/springframework/security/access/expression/method/PreInvocationExpressionAttribute.java @@ -20,24 +20,23 @@ import org.springframework.expression.ParseException; import org.springframework.security.access.prepost.PreInvocationAttribute; /** - * * @author Luke Taylor * @since 3.0 */ -class PreInvocationExpressionAttribute extends - AbstractExpressionBasedMethodConfigAttribute implements PreInvocationAttribute { +class PreInvocationExpressionAttribute extends AbstractExpressionBasedMethodConfigAttribute + implements PreInvocationAttribute { private final String filterTarget; - PreInvocationExpressionAttribute(String filterExpression, String filterTarget, - String authorizeExpression) throws ParseException { + PreInvocationExpressionAttribute(String filterExpression, String filterTarget, String authorizeExpression) + throws ParseException { super(filterExpression, authorizeExpression); this.filterTarget = filterTarget; } - PreInvocationExpressionAttribute(Expression filterExpression, String filterTarget, - Expression authorizeExpression) throws ParseException { + PreInvocationExpressionAttribute(Expression filterExpression, String filterTarget, Expression authorizeExpression) + throws ParseException { super(filterExpression, authorizeExpression); this.filterTarget = filterTarget; @@ -46,7 +45,6 @@ class PreInvocationExpressionAttribute extends /** * The parameter name of the target argument (must be a Collection) to which filtering * will be applied. - * * @return the method parameter name */ String getFilterTarget() { @@ -58,11 +56,10 @@ class PreInvocationExpressionAttribute extends StringBuilder sb = new StringBuilder(); Expression authorize = getAuthorizeExpression(); Expression filter = getFilterExpression(); - sb.append("[authorize: '").append( - authorize == null ? "null" : authorize.getExpressionString()); - sb.append("', filter: '").append( - filter == null ? "null" : filter.getExpressionString()); + sb.append("[authorize: '").append(authorize == null ? "null" : authorize.getExpressionString()); + sb.append("', filter: '").append(filter == null ? "null" : filter.getExpressionString()); sb.append("', filterTarget: '").append(filterTarget).append("']"); return sb.toString(); } + } diff --git a/core/src/main/java/org/springframework/security/access/expression/method/package-info.java b/core/src/main/java/org/springframework/security/access/expression/method/package-info.java index 5c0e30b7b9..901c4278cc 100644 --- a/core/src/main/java/org/springframework/security/access/expression/method/package-info.java +++ b/core/src/main/java/org/springframework/security/access/expression/method/package-info.java @@ -19,4 +19,3 @@ * @since 3.0 */ package org.springframework.security.access.expression.method; - diff --git a/core/src/main/java/org/springframework/security/access/expression/package-info.java b/core/src/main/java/org/springframework/security/access/expression/package-info.java index c96ea42988..5926dc9be7 100644 --- a/core/src/main/java/org/springframework/security/access/expression/package-info.java +++ b/core/src/main/java/org/springframework/security/access/expression/package-info.java @@ -14,10 +14,11 @@ * limitations under the License. */ /** - * Expression handling code to support the use of Spring-EL based expressions in {@code @PreAuthorize}, {@code @PreFilter}, - * {@code @PostAuthorize} and {@code @PostFilter} annotations. Mainly for internal framework use and liable to change. + * Expression handling code to support the use of Spring-EL based expressions in + * {@code @PreAuthorize}, {@code @PreFilter}, {@code @PostAuthorize} and + * {@code @PostFilter} annotations. Mainly for internal framework use and liable to + * change. * * @since 3.0 */ package org.springframework.security.access.expression; - diff --git a/core/src/main/java/org/springframework/security/access/hierarchicalroles/NullRoleHierarchy.java b/core/src/main/java/org/springframework/security/access/hierarchicalroles/NullRoleHierarchy.java index d29d307f4f..fe2b652571 100644 --- a/core/src/main/java/org/springframework/security/access/hierarchicalroles/NullRoleHierarchy.java +++ b/core/src/main/java/org/springframework/security/access/hierarchicalroles/NullRoleHierarchy.java @@ -20,7 +20,6 @@ import java.util.Collection; import org.springframework.security.core.GrantedAuthority; /** - * * @author Luke Taylor * @since 3.0 */ diff --git a/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchy.java b/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchy.java index 5ab09dda7b..3316786513 100755 --- a/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchy.java +++ b/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchy.java @@ -36,7 +36,6 @@ public interface RoleHierarchy { * Role hierarchy: ROLE_A > ROLE_B > ROLE_C.
    * Directly assigned authority: ROLE_A.
    * Reachable authorities: ROLE_A, ROLE_B, ROLE_C. - * * @param authorities - List of the directly assigned authorities. * @return List of all reachable authorities given the assigned authorities. */ diff --git a/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyAuthoritiesMapper.java b/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyAuthoritiesMapper.java index 9619d47500..7a35f967ba 100644 --- a/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyAuthoritiesMapper.java +++ b/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyAuthoritiesMapper.java @@ -24,14 +24,15 @@ import java.util.*; * @author Luke Taylor */ public class RoleHierarchyAuthoritiesMapper implements GrantedAuthoritiesMapper { + private final RoleHierarchy roleHierarchy; public RoleHierarchyAuthoritiesMapper(RoleHierarchy roleHierarchy) { this.roleHierarchy = roleHierarchy; } - public Collection mapAuthorities( - Collection authorities) { + public Collection mapAuthorities(Collection authorities) { return roleHierarchy.getReachableGrantedAuthorities(authorities); } + } diff --git a/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java b/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java index 0a51abe2de..042752da98 100755 --- a/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java +++ b/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java @@ -34,7 +34,8 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; * This class defines a role hierarchy for use with various access checking components. * *

    - * Here is an example configuration of a role hierarchy (hint: read the ">" sign as "includes"): + * Here is an example configuration of a role hierarchy (hint: read the ">" sign as + * "includes"): * *

      *     <property name="hierarchy">
    @@ -49,25 +50,26 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
      * 

    * Explanation of the above: *

      - *
    • In effect every user with ROLE_A also has ROLE_B, ROLE_AUTHENTICATED and ROLE_UNAUTHENTICATED;
    • + *
    • In effect every user with ROLE_A also has ROLE_B, ROLE_AUTHENTICATED and + * ROLE_UNAUTHENTICATED;
    • *
    • every user with ROLE_B also has ROLE_AUTHENTICATED and ROLE_UNAUTHENTICATED;
    • *
    • every user with ROLE_AUTHENTICATED also has ROLE_UNAUTHENTICATED.
    • *
    * *

    - * Hierarchical Roles will dramatically shorten your access rules (and also make the access rules - * much more elegant). + * Hierarchical Roles will dramatically shorten your access rules (and also make the + * access rules much more elegant). * *

    - * Consider this access rule for Spring Security's RoleVoter (background: every user that is - * authenticated should be able to log out): + * Consider this access rule for Spring Security's RoleVoter (background: every user that + * is authenticated should be able to log out): *

    /logout.html=ROLE_A,ROLE_B,ROLE_AUTHENTICATED
    * * With hierarchical roles this can now be shortened to: *
    /logout.html=ROLE_AUTHENTICATED
    * - * In addition to shorter rules this will also make your access rules more readable and your - * intentions clearer. + * In addition to shorter rules this will also make your access rules more readable and + * your intentions clearer. * * @author Michael Mayr */ @@ -76,20 +78,21 @@ public class RoleHierarchyImpl implements RoleHierarchy { private static final Log logger = LogFactory.getLog(RoleHierarchyImpl.class); /** - * Raw hierarchy configuration where each line represents single or multiple level role chain. + * Raw hierarchy configuration where each line represents single or multiple level + * role chain. */ private String roleHierarchyStringRepresentation = null; /** - * {@code rolesReachableInOneStepMap} is a Map that under the key of a specific role name - * contains a set of all roles reachable from this role in 1 step - * (i.e. parsed {@link #roleHierarchyStringRepresentation} grouped by the higher role) + * {@code rolesReachableInOneStepMap} is a Map that under the key of a specific role + * name contains a set of all roles reachable from this role in 1 step (i.e. parsed + * {@link #roleHierarchyStringRepresentation} grouped by the higher role) */ private Map> rolesReachableInOneStepMap = null; /** - * {@code rolesReachableInOneOrMoreStepsMap} is a Map that under the key of a specific role - * name contains a set of all roles reachable from this role in 1 or more steps + * {@code rolesReachableInOneOrMoreStepsMap} is a Map that under the key of a specific + * role name contains a set of all roles reachable from this role in 1 or more steps * (i.e. fully resolved hierarchy from {@link #rolesReachableInOneStepMap}) */ private Map> rolesReachableInOneOrMoreStepsMap = null; @@ -100,15 +103,13 @@ public class RoleHierarchyImpl implements RoleHierarchy { * is done for performance reasons (reachable roles can then be calculated in O(1) * time). During pre-calculation, cycles in role hierarchy are detected and will cause * a CycleInRoleHierarchyException to be thrown. - * * @param roleHierarchyStringRepresentation - String definition of the role hierarchy. */ public void setHierarchy(String roleHierarchyStringRepresentation) { this.roleHierarchyStringRepresentation = roleHierarchyStringRepresentation; if (logger.isDebugEnabled()) { - logger.debug("setHierarchy() - The following role hierarchy was set: " - + roleHierarchyStringRepresentation); + logger.debug("setHierarchy() - The following role hierarchy was set: " + roleHierarchyStringRepresentation); } buildRolesReachableInOneStepMap(); @@ -150,9 +151,8 @@ public class RoleHierarchyImpl implements RoleHierarchy { } if (logger.isDebugEnabled()) { - logger.debug("getReachableGrantedAuthorities() - From the roles " - + authorities + " one can reach " + reachableRoles - + " in zero or more steps."); + logger.debug("getReachableGrantedAuthorities() - From the roles " + authorities + " one can reach " + + reachableRoles + " in zero or more steps."); } List reachableRoleList = new ArrayList<>(reachableRoles.size()); @@ -179,14 +179,15 @@ public class RoleHierarchyImpl implements RoleHierarchy { if (!this.rolesReachableInOneStepMap.containsKey(higherRole)) { rolesReachableInOneStepSet = new HashSet<>(); this.rolesReachableInOneStepMap.put(higherRole, rolesReachableInOneStepSet); - } else { + } + else { rolesReachableInOneStepSet = this.rolesReachableInOneStepMap.get(higherRole); } rolesReachableInOneStepSet.add(lowerRole); if (logger.isDebugEnabled()) { - logger.debug("buildRolesReachableInOneStepMap() - From role " + higherRole - + " one can reach role " + lowerRole + " in one step."); + logger.debug("buildRolesReachableInOneStepMap() - From role " + higherRole + " one can reach role " + + lowerRole + " in one step."); } } } @@ -209,18 +210,19 @@ public class RoleHierarchyImpl implements RoleHierarchy { // take a role from the rolesToVisit set GrantedAuthority lowerRole = rolesToVisitSet.iterator().next(); rolesToVisitSet.remove(lowerRole); - if (!visitedRolesSet.add(lowerRole) || - !this.rolesReachableInOneStepMap.containsKey(lowerRole.getAuthority())) { + if (!visitedRolesSet.add(lowerRole) + || !this.rolesReachableInOneStepMap.containsKey(lowerRole.getAuthority())) { continue; // Already visited role or role with missing hierarchy - } else if (roleName.equals(lowerRole.getAuthority())) { + } + else if (roleName.equals(lowerRole.getAuthority())) { throw new CycleInRoleHierarchyException(); } rolesToVisitSet.addAll(this.rolesReachableInOneStepMap.get(lowerRole.getAuthority())); } this.rolesReachableInOneOrMoreStepsMap.put(roleName, visitedRolesSet); - logger.debug("buildRolesReachableInOneOrMoreStepsMap() - From role " + roleName - + " one can reach " + visitedRolesSet + " in one or more steps."); + logger.debug("buildRolesReachableInOneOrMoreStepsMap() - From role " + roleName + " one can reach " + + visitedRolesSet + " in one or more steps."); } } diff --git a/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyUtils.java b/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyUtils.java index 6b7e4afcbe..e8d08f3966 100644 --- a/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyUtils.java +++ b/core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyUtils.java @@ -35,13 +35,13 @@ public final class RoleHierarchyUtils { /** * Converts the supplied {@link Map} of role name to implied role name(s) to a string - * representation understood by {@link RoleHierarchyImpl#setHierarchy(String)}. - * The map key is the role name and the map value is a {@link List} of implied role name(s). - * + * representation understood by {@link RoleHierarchyImpl#setHierarchy(String)}. The + * map key is the role name and the map value is a {@link List} of implied role + * name(s). * @param roleHierarchyMap the mapping(s) of role name to implied role name(s) * @return a string representation of a role hierarchy - * @throws IllegalArgumentException if roleHierarchyMap is null or empty or if a role name is null or - * empty or if an implied role name(s) is null or empty + * @throws IllegalArgumentException if roleHierarchyMap is null or empty or if a role + * name is null or empty or if an implied role name(s) is null or empty * */ public static String roleHierarchyFromMap(Map> roleHierarchyMap) { diff --git a/core/src/main/java/org/springframework/security/access/hierarchicalroles/package-info.java b/core/src/main/java/org/springframework/security/access/hierarchicalroles/package-info.java index bbcb668705..a893032c17 100644 --- a/core/src/main/java/org/springframework/security/access/hierarchicalroles/package-info.java +++ b/core/src/main/java/org/springframework/security/access/hierarchicalroles/package-info.java @@ -17,4 +17,3 @@ * Role hierarchy implementation. */ package org.springframework.security.access.hierarchicalroles; - diff --git a/core/src/main/java/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java b/core/src/main/java/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java index 2f3d9e7b76..40a34d6260 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java +++ b/core/src/main/java/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java @@ -54,7 +54,8 @@ import org.springframework.util.Assert; * configuration of the security interceptor. It will also implement the proper handling * of secure object invocations, namely: *
      - *
    1. Obtain the {@link Authentication} object from the {@link SecurityContextHolder}.
    2. + *
    3. Obtain the {@link Authentication} object from the + * {@link SecurityContextHolder}.
    4. *
    5. Determine if the request relates to a secured or public invocation by looking up * the secure object request against the {@link SecurityMetadataSource}.
    6. *
    7. For an invocation that is secured (there is a list of ConfigAttributes @@ -100,8 +101,9 @@ import org.springframework.util.Assert; * @author Ben Alex * @author Rob Winch */ -public abstract class AbstractSecurityInterceptor implements InitializingBean, - ApplicationEventPublisherAware, MessageSourceAware { +public abstract class AbstractSecurityInterceptor + implements InitializingBean, ApplicationEventPublisherAware, MessageSourceAware { + // ~ Static fields/initializers // ===================================================================================== @@ -111,49 +113,49 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, // ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); + private ApplicationEventPublisher eventPublisher; + private AccessDecisionManager accessDecisionManager; + private AfterInvocationManager afterInvocationManager; + private AuthenticationManager authenticationManager = new NoOpAuthenticationManager(); + private RunAsManager runAsManager = new NullRunAsManager(); private boolean alwaysReauthenticate = false; + private boolean rejectPublicInvocations = false; + private boolean validateConfigAttributes = true; + private boolean publishAuthorizationSuccess = false; // ~ Methods // ======================================================================================================== public void afterPropertiesSet() { - Assert.notNull(getSecureObjectClass(), - "Subclass must provide a non-null response to getSecureObjectClass()"); + Assert.notNull(getSecureObjectClass(), "Subclass must provide a non-null response to getSecureObjectClass()"); Assert.notNull(this.messages, "A message source must be set"); Assert.notNull(this.authenticationManager, "An AuthenticationManager is required"); Assert.notNull(this.accessDecisionManager, "An AccessDecisionManager is required"); Assert.notNull(this.runAsManager, "A RunAsManager is required"); - Assert.notNull(this.obtainSecurityMetadataSource(), - "An SecurityMetadataSource is required"); - Assert.isTrue(this.obtainSecurityMetadataSource() - .supports(getSecureObjectClass()), - () -> "SecurityMetadataSource does not support secure object class: " - + getSecureObjectClass()); + Assert.notNull(this.obtainSecurityMetadataSource(), "An SecurityMetadataSource is required"); + Assert.isTrue(this.obtainSecurityMetadataSource().supports(getSecureObjectClass()), + () -> "SecurityMetadataSource does not support secure object class: " + getSecureObjectClass()); Assert.isTrue(this.runAsManager.supports(getSecureObjectClass()), - () -> "RunAsManager does not support secure object class: " - + getSecureObjectClass()); + () -> "RunAsManager does not support secure object class: " + getSecureObjectClass()); Assert.isTrue(this.accessDecisionManager.supports(getSecureObjectClass()), - () -> "AccessDecisionManager does not support secure object class: " - + getSecureObjectClass()); + () -> "AccessDecisionManager does not support secure object class: " + getSecureObjectClass()); if (this.afterInvocationManager != null) { Assert.isTrue(this.afterInvocationManager.supports(getSecureObjectClass()), - () -> "AfterInvocationManager does not support secure object class: " - + getSecureObjectClass()); + () -> "AfterInvocationManager does not support secure object class: " + getSecureObjectClass()); } if (this.validateConfigAttributes) { - Collection attributeDefs = this - .obtainSecurityMetadataSource().getAllConfigAttributes(); + Collection attributeDefs = this.obtainSecurityMetadataSource().getAllConfigAttributes(); if (attributeDefs == null) { logger.warn("Could not validate configuration attributes as the SecurityMetadataSource did not return " @@ -164,17 +166,14 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, Set unsupportedAttrs = new HashSet<>(); for (ConfigAttribute attr : attributeDefs) { - if (!this.runAsManager.supports(attr) - && !this.accessDecisionManager.supports(attr) - && ((this.afterInvocationManager == null) || !this.afterInvocationManager - .supports(attr))) { + if (!this.runAsManager.supports(attr) && !this.accessDecisionManager.supports(attr) + && ((this.afterInvocationManager == null) || !this.afterInvocationManager.supports(attr))) { unsupportedAttrs.add(attr); } } if (unsupportedAttrs.size() != 0) { - throw new IllegalArgumentException( - "Unsupported configuration attributes: " + unsupportedAttrs); + throw new IllegalArgumentException("Unsupported configuration attributes: " + unsupportedAttrs); } logger.debug("Validated configuration attributes"); @@ -186,24 +185,19 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, final boolean debug = logger.isDebugEnabled(); if (!getSecureObjectClass().isAssignableFrom(object.getClass())) { - throw new IllegalArgumentException( - "Security invocation attempted for object " - + object.getClass().getName() - + " but AbstractSecurityInterceptor only configured to support secure objects of type: " - + getSecureObjectClass()); + throw new IllegalArgumentException("Security invocation attempted for object " + object.getClass().getName() + + " but AbstractSecurityInterceptor only configured to support secure objects of type: " + + getSecureObjectClass()); } - Collection attributes = this.obtainSecurityMetadataSource() - .getAttributes(object); + Collection attributes = this.obtainSecurityMetadataSource().getAttributes(object); if (attributes == null || attributes.isEmpty()) { if (rejectPublicInvocations) { - throw new IllegalArgumentException( - "Secure object invocation " - + object - + " was denied as public invocations are not allowed via this interceptor. " - + "This indicates a configuration error because the " - + "rejectPublicInvocations property is set to 'true'"); + throw new IllegalArgumentException("Secure object invocation " + object + + " was denied as public invocations are not allowed via this interceptor. " + + "This indicates a configuration error because the " + + "rejectPublicInvocations property is set to 'true'"); } if (debug) { @@ -220,10 +214,8 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, } if (SecurityContextHolder.getContext().getAuthentication() == null) { - credentialsNotFound(messages.getMessage( - "AbstractSecurityInterceptor.authenticationNotFound", - "An Authentication object was not found in the SecurityContext"), - object, attributes); + credentialsNotFound(messages.getMessage("AbstractSecurityInterceptor.authenticationNotFound", + "An Authentication object was not found in the SecurityContext"), object, attributes); } Authentication authenticated = authenticateIfRequired(); @@ -233,8 +225,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, this.accessDecisionManager.decide(authenticated, object, attributes); } catch (AccessDeniedException accessDeniedException) { - publishEvent(new AuthorizationFailureEvent(object, attributes, authenticated, - accessDeniedException)); + publishEvent(new AuthorizationFailureEvent(object, attributes, authenticated, accessDeniedException)); throw accessDeniedException; } @@ -248,8 +239,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, } // Attempt to run as a different user - Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, - attributes); + Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attributes); if (runAs == null) { if (debug) { @@ -257,8 +247,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, } // no further work post-invocation - return new InterceptorStatusToken(SecurityContextHolder.getContext(), false, - attributes, object); + return new InterceptorStatusToken(SecurityContextHolder.getContext(), false, attributes, object); } else { if (debug) { @@ -279,14 +268,12 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, * object invocation has been completed. This method should be invoked after the * secure object invocation and before afterInvocation regardless of the secure object * invocation returning successfully (i.e. it should be done in a finally block). - * * @param token as returned by the {@link #beforeInvocation(Object)} method */ protected void finallyInvocation(InterceptorStatusToken token) { if (token != null && token.isContextHolderRefreshRequired()) { if (logger.isDebugEnabled()) { - logger.debug("Reverting to original Authentication: " - + token.getSecurityContext().getAuthentication()); + logger.debug("Reverting to original Authentication: " + token.getSecurityContext().getAuthentication()); } SecurityContextHolder.setContext(token.getSecurityContext()); @@ -296,7 +283,6 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, /** * Completes the work of the AbstractSecurityInterceptor after the secure * object invocation has been completed. - * * @param token as returned by the {@link #beforeInvocation(Object)} method * @param returnedObject any object returned from the secure object invocation (may be * null) @@ -314,15 +300,12 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, if (afterInvocationManager != null) { // Attempt after invocation handling try { - returnedObject = afterInvocationManager.decide(token.getSecurityContext() - .getAuthentication(), token.getSecureObject(), token - .getAttributes(), returnedObject); + returnedObject = afterInvocationManager.decide(token.getSecurityContext().getAuthentication(), + token.getSecureObject(), token.getAttributes(), returnedObject); } catch (AccessDeniedException accessDeniedException) { - AuthorizationFailureEvent event = new AuthorizationFailureEvent( - token.getSecureObject(), token.getAttributes(), token - .getSecurityContext().getAuthentication(), - accessDeniedException); + AuthorizationFailureEvent event = new AuthorizationFailureEvent(token.getSecureObject(), + token.getAttributes(), token.getSecurityContext().getAuthentication(), accessDeniedException); publishEvent(event); throw accessDeniedException; @@ -336,12 +319,10 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, * Checks the current authentication token and passes it to the AuthenticationManager * if {@link org.springframework.security.core.Authentication#isAuthenticated()} * returns false or the property alwaysReauthenticate has been set to true. - * * @return an authenticated Authentication object. */ private Authentication authenticateIfRequired() { - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication.isAuthenticated() && !alwaysReauthenticate) { if (logger.isDebugEnabled()) { @@ -369,18 +350,15 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, * publishes an event to the application context. *

      * Always throws an exception. - * * @param reason to be provided in the exception detail * @param secureObject that was being called * @param configAttribs that were defined for the secureObject */ - private void credentialsNotFound(String reason, Object secureObject, - Collection configAttribs) { - AuthenticationCredentialsNotFoundException exception = new AuthenticationCredentialsNotFoundException( - reason); + private void credentialsNotFound(String reason, Object secureObject, Collection configAttribs) { + AuthenticationCredentialsNotFoundException exception = new AuthenticationCredentialsNotFoundException(reason); - AuthenticationCredentialsNotFoundEvent event = new AuthenticationCredentialsNotFoundEvent( - secureObject, configAttribs, exception); + AuthenticationCredentialsNotFoundEvent event = new AuthenticationCredentialsNotFoundEvent(secureObject, + configAttribs, exception); publishEvent(event); throw exception; @@ -406,7 +384,6 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, * Indicates the type of secure objects the subclass will be presenting to the * abstract parent for processing. This is used to ensure collaborators wired to the * {@code AbstractSecurityInterceptor} all support the indicated secure object class. - * * @return the type of secure object the subclass provides services for */ public abstract Class getSecureObjectClass(); @@ -439,7 +416,6 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, * meaning by default the Authentication.isAuthenticated() property is * trusted and re-authentication will not occur if the principal has already been * authenticated. - * * @param alwaysReauthenticate true to force * AbstractSecurityInterceptor to disregard the value of * Authentication.isAuthenticated() and always re-authenticate the @@ -449,8 +425,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, this.alwaysReauthenticate = alwaysReauthenticate; } - public void setApplicationEventPublisher( - ApplicationEventPublisher applicationEventPublisher) { + public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.eventPublisher = applicationEventPublisher; } @@ -465,7 +440,6 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, /** * Only {@code AuthorizationFailureEvent} will be published. If you set this property * to {@code true}, {@code AuthorizedEvent}s will also be published. - * * @param publishAuthorizationSuccess default value is {@code false} */ public void setPublishAuthorizationSuccess(boolean publishAuthorizationSuccess) { @@ -481,7 +455,6 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, * IllegalArgumentException will be thrown by the * AbstractSecurityInterceptor if you set this property to true and * an attempt is made to invoke a secure object that has no configuration attributes. - * * @param rejectPublicInvocations set to true to reject invocations of * secure objects that have no configuration attributes (by default it is * false which treats undeclared secure objects as "public" or @@ -507,10 +480,10 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean, private static class NoOpAuthenticationManager implements AuthenticationManager { - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { - throw new AuthenticationServiceException("Cannot authenticate " - + authentication); + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + throw new AuthenticationServiceException("Cannot authenticate " + authentication); } + } + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/AfterInvocationManager.java b/core/src/main/java/org/springframework/security/access/intercept/AfterInvocationManager.java index eae4f139fe..7c11320a00 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/AfterInvocationManager.java +++ b/core/src/main/java/org/springframework/security/access/intercept/AfterInvocationManager.java @@ -43,6 +43,7 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ public interface AfterInvocationManager { + // ~ Methods // ======================================================================================================== @@ -50,24 +51,20 @@ public interface AfterInvocationManager { * Given the details of a secure object invocation including its returned * Object, make an access control decision or optionally modify the * returned Object. - * * @param authentication the caller that invoked the method * @param object the secured object that was called * @param attributes the configuration attributes associated with the secured object * that was invoked * @param returnedObject the Object that was returned from the secure * object invocation - * * @return the Object that will ultimately be returned to the caller (if * an implementation does not wish to modify the object to be returned to the caller, * the implementation should simply return the same object it was passed by the * returnedObject method argument) - * * @throws AccessDeniedException if access is denied */ - Object decide(Authentication authentication, Object object, - Collection attributes, Object returnedObject) - throws AccessDeniedException; + Object decide(Authentication authentication, Object object, Collection attributes, + Object returnedObject) throws AccessDeniedException; /** * Indicates whether this AfterInvocationManager is able to process @@ -78,10 +75,8 @@ public interface AfterInvocationManager { * AccessDecisionManager and/or RunAsManager and/or * AfterInvocationManager. *

      - * * @param attribute a configuration attribute that has been configured against the * AbstractSecurityInterceptor - * * @return true if this AfterInvocationManager can support the passed * configuration attribute */ @@ -90,10 +85,9 @@ public interface AfterInvocationManager { /** * Indicates whether the AfterInvocationManager implementation is able to * provide access control decisions for the indicated secured object type. - * * @param clazz the class that is being queried - * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/AfterInvocationProviderManager.java b/core/src/main/java/org/springframework/security/access/intercept/AfterInvocationProviderManager.java index bc8bea7fb3..c223186b9d 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/AfterInvocationProviderManager.java +++ b/core/src/main/java/org/springframework/security/access/intercept/AfterInvocationProviderManager.java @@ -45,13 +45,12 @@ import org.springframework.util.Assert; * * @author Ben Alex */ -public class AfterInvocationProviderManager implements AfterInvocationManager, - InitializingBean { +public class AfterInvocationProviderManager implements AfterInvocationManager, InitializingBean { + // ~ Static fields/initializers // ===================================================================================== - protected static final Log logger = LogFactory - .getLog(AfterInvocationProviderManager.class); + protected static final Log logger = LogFactory.getLog(AfterInvocationProviderManager.class); // ~ Instance fields // ================================================================================================ @@ -67,14 +66,12 @@ public class AfterInvocationProviderManager implements AfterInvocationManager, private void checkIfValidList(List listToCheck) { if ((listToCheck == null) || (listToCheck.size() == 0)) { - throw new IllegalArgumentException( - "A list of AfterInvocationProviders is required"); + throw new IllegalArgumentException("A list of AfterInvocationProviders is required"); } } - public Object decide(Authentication authentication, Object object, - Collection config, Object returnedObject) - throws AccessDeniedException { + public Object decide(Authentication authentication, Object object, Collection config, + Object returnedObject) throws AccessDeniedException { Object result = returnedObject; @@ -94,9 +91,8 @@ public class AfterInvocationProviderManager implements AfterInvocationManager, providers = new ArrayList<>(newList.size()); for (Object currentObject : newList) { - Assert.isInstanceOf(AfterInvocationProvider.class, currentObject, - () -> "AfterInvocationProvider " + currentObject.getClass().getName() - + " must implement AfterInvocationProvider"); + Assert.isInstanceOf(AfterInvocationProvider.class, currentObject, () -> "AfterInvocationProvider " + + currentObject.getClass().getName() + " must implement AfterInvocationProvider"); providers.add((AfterInvocationProvider) currentObject); } } @@ -121,9 +117,7 @@ public class AfterInvocationProviderManager implements AfterInvocationManager, *

      * If one or more providers cannot support the presented class, false is * returned. - * * @param clazz the secure object class being queries - * * @return if the AfterInvocationProviderManager can support the secure * object class, which requires every one of its AfterInvocationProviders * to support the secure object class @@ -137,4 +131,5 @@ public class AfterInvocationProviderManager implements AfterInvocationManager, return true; } + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/InterceptorStatusToken.java b/core/src/main/java/org/springframework/security/access/intercept/InterceptorStatusToken.java index fbe6f7acc6..74ea128212 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/InterceptorStatusToken.java +++ b/core/src/main/java/org/springframework/security/access/intercept/InterceptorStatusToken.java @@ -31,20 +31,23 @@ import org.springframework.security.core.context.SecurityContext; * @author Ben Alex */ public class InterceptorStatusToken { + // ~ Instance fields // ================================================================================================ private SecurityContext securityContext; + private Collection attr; + private Object secureObject; + private boolean contextHolderRefreshRequired; // ~ Constructors // =================================================================================================== - public InterceptorStatusToken(SecurityContext securityContext, - boolean contextHolderRefreshRequired, Collection attributes, - Object secureObject) { + public InterceptorStatusToken(SecurityContext securityContext, boolean contextHolderRefreshRequired, + Collection attributes, Object secureObject) { this.securityContext = securityContext; this.contextHolderRefreshRequired = contextHolderRefreshRequired; this.attr = attributes; @@ -69,4 +72,5 @@ public class InterceptorStatusToken { public boolean isContextHolderRefreshRequired() { return contextHolderRefreshRequired; } + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/MethodInvocationPrivilegeEvaluator.java b/core/src/main/java/org/springframework/security/access/intercept/MethodInvocationPrivilegeEvaluator.java index e8551ca0ae..2438fe293c 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/MethodInvocationPrivilegeEvaluator.java +++ b/core/src/main/java/org/springframework/security/access/intercept/MethodInvocationPrivilegeEvaluator.java @@ -43,11 +43,11 @@ import org.springframework.util.Assert; * @author Ben Alex */ public class MethodInvocationPrivilegeEvaluator implements InitializingBean { + // ~ Static fields/initializers // ===================================================================================== - protected static final Log logger = LogFactory - .getLog(MethodInvocationPrivilegeEvaluator.class); + protected static final Log logger = LogFactory.getLog(MethodInvocationPrivilegeEvaluator.class); // ~ Instance fields // ================================================================================================ @@ -63,11 +63,9 @@ public class MethodInvocationPrivilegeEvaluator implements InitializingBean { public boolean isAllowed(MethodInvocation mi, Authentication authentication) { Assert.notNull(mi, "MethodInvocation required"); - Assert.notNull(mi.getMethod(), - "MethodInvocation must provide a non-null getMethod()"); + Assert.notNull(mi.getMethod(), "MethodInvocation must provide a non-null getMethod()"); - Collection attrs = securityInterceptor - .obtainSecurityMetadataSource().getAttributes(mi); + Collection attrs = securityInterceptor.obtainSecurityMetadataSource().getAttributes(mi); if (attrs == null) { if (securityInterceptor.isRejectPublicInvocations()) { @@ -82,13 +80,11 @@ public class MethodInvocationPrivilegeEvaluator implements InitializingBean { } try { - securityInterceptor.getAccessDecisionManager().decide(authentication, mi, - attrs); + securityInterceptor.getAccessDecisionManager().decide(authentication, mi, attrs); } catch (AccessDeniedException unauthorized) { if (logger.isDebugEnabled()) { - logger.debug(mi.toString() + " denied for " + authentication.toString(), - unauthorized); + logger.debug(mi.toString() + " denied for " + authentication.toString(), unauthorized); } return false; @@ -99,11 +95,11 @@ public class MethodInvocationPrivilegeEvaluator implements InitializingBean { public void setSecurityInterceptor(AbstractSecurityInterceptor securityInterceptor) { Assert.notNull(securityInterceptor, "AbstractSecurityInterceptor cannot be null"); - Assert.isTrue( - MethodInvocation.class.equals(securityInterceptor.getSecureObjectClass()), + Assert.isTrue(MethodInvocation.class.equals(securityInterceptor.getSecureObjectClass()), "AbstractSecurityInterceptor does not support MethodInvocations"); Assert.notNull(securityInterceptor.getAccessDecisionManager(), "AbstractSecurityInterceptor must provide a non-null AccessDecisionManager"); this.securityInterceptor = securityInterceptor; } + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/NullRunAsManager.java b/core/src/main/java/org/springframework/security/access/intercept/NullRunAsManager.java index 2aca1ad642..77fb80cd3a 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/NullRunAsManager.java +++ b/core/src/main/java/org/springframework/security/access/intercept/NullRunAsManager.java @@ -30,11 +30,11 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ final class NullRunAsManager implements RunAsManager { + // ~ Methods // ======================================================================================================== - public Authentication buildRunAs(Authentication authentication, Object object, - Collection config) { + public Authentication buildRunAs(Authentication authentication, Object object, Collection config) { return null; } @@ -45,4 +45,5 @@ final class NullRunAsManager implements RunAsManager { public boolean supports(Class clazz) { return true; } + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java b/core/src/main/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java index 4a1096a1eb..805ae2d814 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java +++ b/core/src/main/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java @@ -43,32 +43,30 @@ import org.springframework.util.Assert; * If the key does not match, a BadCredentialsException is thrown. *

      */ -public class RunAsImplAuthenticationProvider implements InitializingBean, - AuthenticationProvider, MessageSourceAware { +public class RunAsImplAuthenticationProvider implements InitializingBean, AuthenticationProvider, MessageSourceAware { + // ~ Instance fields // ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); + private String key; // ~ Methods // ======================================================================================================== public void afterPropertiesSet() { - Assert.notNull(key, - "A Key is required and should match that configured for the RunAsManagerImpl"); + Assert.notNull(key, "A Key is required and should match that configured for the RunAsManagerImpl"); } - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { RunAsUserToken token = (RunAsUserToken) authentication; if (token.getKeyHash() == key.hashCode()) { return authentication; } else { - throw new BadCredentialsException(messages.getMessage( - "RunAsImplAuthenticationProvider.incorrectKey", + throw new BadCredentialsException(messages.getMessage("RunAsImplAuthenticationProvider.incorrectKey", "The presented RunAsUserToken does not contain the expected key")); } } @@ -88,4 +86,5 @@ public class RunAsImplAuthenticationProvider implements InitializingBean, public boolean supports(Class authentication) { return RunAsUserToken.class.isAssignableFrom(authentication); } + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/RunAsManager.java b/core/src/main/java/org/springframework/security/access/intercept/RunAsManager.java index 8fa6bee9fe..a244177a21 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/RunAsManager.java +++ b/core/src/main/java/org/springframework/security/access/intercept/RunAsManager.java @@ -59,24 +59,22 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ public interface RunAsManager { + // ~ Methods // ======================================================================================================== /** * Returns a replacement Authentication object for the current secure * object invocation, or null if replacement not required. - * * @param authentication the caller invoking the secure object * @param object the secured object being called * @param attributes the configuration attributes associated with the secure object * being invoked - * * @return a replacement object to be used for duration of the secure object * invocation, or null if the Authentication should be left * as is */ - Authentication buildRunAs(Authentication authentication, Object object, - Collection attributes); + Authentication buildRunAs(Authentication authentication, Object object, Collection attributes); /** * Indicates whether this RunAsManager is able to process the passed @@ -87,10 +85,8 @@ public interface RunAsManager { * AccessDecisionManager and/or RunAsManager and/or * AfterInvocationManager. *

      - * * @param attribute a configuration attribute that has been configured against the * AbstractSecurityInterceptor - * * @return true if this RunAsManager can support the passed * configuration attribute */ @@ -99,10 +95,9 @@ public interface RunAsManager { /** * Indicates whether the RunAsManager implementation is able to provide * run-as replacement for the indicated secure object type. - * * @param clazz the class that is being queried - * * @return true if the implementation can process the indicated class */ boolean supports(Class clazz); + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/RunAsManagerImpl.java b/core/src/main/java/org/springframework/security/access/intercept/RunAsManagerImpl.java index 5efcd78d40..8f2794dea5 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/RunAsManagerImpl.java +++ b/core/src/main/java/org/springframework/security/access/intercept/RunAsManagerImpl.java @@ -54,18 +54,19 @@ import org.springframework.util.Assert; * @author colin sampaleanu */ public class RunAsManagerImpl implements RunAsManager, InitializingBean { + // ~ Instance fields // ================================================================================================ private String key; + private String rolePrefix = "ROLE_"; // ~ Methods // ======================================================================================================== public void afterPropertiesSet() { - Assert.notNull( - key, + Assert.notNull(key, "A Key is required and should match that configured for the RunAsImplAuthenticationProvider"); } @@ -88,9 +89,8 @@ public class RunAsManagerImpl implements RunAsManager, InitializingBean { // Add existing authorities newAuthorities.addAll(authentication.getAuthorities()); - return new RunAsUserToken(this.key, authentication.getPrincipal(), - authentication.getCredentials(), newAuthorities, - authentication.getClass()); + return new RunAsUserToken(this.key, authentication.getPrincipal(), authentication.getCredentials(), + newAuthorities, authentication.getClass()); } public String getKey() { @@ -108,7 +108,6 @@ public class RunAsManagerImpl implements RunAsManager, InitializingBean { /** * Allows the default role prefix of ROLE_ to be overridden. May be set * to an empty value, although this is usually not desirable. - * * @param rolePrefix the new prefix */ public void setRolePrefix(String rolePrefix) { @@ -116,19 +115,17 @@ public class RunAsManagerImpl implements RunAsManager, InitializingBean { } public boolean supports(ConfigAttribute attribute) { - return attribute.getAttribute() != null - && attribute.getAttribute().startsWith("RUN_AS_"); + return attribute.getAttribute() != null && attribute.getAttribute().startsWith("RUN_AS_"); } /** * This implementation supports any type of class, because it does not query the * presented secure object. - * * @param clazz the secure object - * * @return always true */ public boolean supports(Class clazz) { return true; } + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/RunAsUserToken.java b/core/src/main/java/org/springframework/security/access/intercept/RunAsUserToken.java index e050f4433f..fe608b511c 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/RunAsUserToken.java +++ b/core/src/main/java/org/springframework/security/access/intercept/RunAsUserToken.java @@ -37,8 +37,11 @@ public class RunAsUserToken extends AbstractAuthenticationToken { // ================================================================================================ private final Class originalAuthentication; + private final Object credentials; + private final Object principal; + private final int keyHash; // ~ Constructors @@ -79,10 +82,10 @@ public class RunAsUserToken extends AbstractAuthenticationToken { @Override public String toString() { StringBuilder sb = new StringBuilder(super.toString()); - String className = this.originalAuthentication == null ? null - : this.originalAuthentication.getName(); + String className = this.originalAuthentication == null ? null : this.originalAuthentication.getName(); sb.append("; Original Class: ").append(className); return sb.toString(); } + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java b/core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java index bb7f8d236a..f69054698c 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java +++ b/core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptor.java @@ -37,8 +37,8 @@ import org.aopalliance.intercept.MethodInvocation; * @author Ben Alex * @author Rob Winch */ -public class MethodSecurityInterceptor extends AbstractSecurityInterceptor implements - MethodInterceptor { +public class MethodSecurityInterceptor extends AbstractSecurityInterceptor implements MethodInterceptor { + // ~ Instance fields // ================================================================================================ @@ -53,12 +53,9 @@ public class MethodSecurityInterceptor extends AbstractSecurityInterceptor imple /** * This method should be used to enforce security on a MethodInvocation. - * * @param mi The method being invoked which requires a security decision - * * @return The returned value from the method invocation (possibly modified by the * {@code AfterInvocationManager}). - * * @throws Throwable if any error occurs */ public Object invoke(MethodInvocation mi) throws Throwable { @@ -85,4 +82,5 @@ public class MethodSecurityInterceptor extends AbstractSecurityInterceptor imple public void setSecurityMetadataSource(MethodSecurityMetadataSource newSource) { this.securityMetadataSource = newSource; } + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java b/core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java index d6ba04d102..bec9cb0bf8 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java +++ b/core/src/main/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisor.java @@ -38,8 +38,8 @@ import org.springframework.util.Assert; * {@link MethodInterceptor} from public (non-secure) methods. *

      * Because the AOP framework caches advice calculations, this is normally faster than just - * letting the MethodInterceptor run and find out itself that it has - * no work to do. + * letting the MethodInterceptor run and find out itself that it has no work + * to do. *

      * This class also allows the use of Spring's {@code DefaultAdvisorAutoProxyCreator}, * which makes configuration easier than setup a ProxyFactoryBean for each @@ -51,17 +51,23 @@ import org.springframework.util.Assert; * @author Ben Alex * @author Luke Taylor */ -public class MethodSecurityMetadataSourceAdvisor extends AbstractPointcutAdvisor - implements BeanFactoryAware { +public class MethodSecurityMetadataSourceAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware { + // ~ Instance fields // ================================================================================================ private transient MethodSecurityMetadataSource attributeSource; + private transient MethodInterceptor interceptor; + private final Pointcut pointcut = new MethodSecurityMetadataSourcePointcut(); + private BeanFactory beanFactory; + private final String adviceBeanName; + private final String metadataSourceBeanName; + private transient volatile Object adviceMonitor = new Object(); // ~ Constructors @@ -73,19 +79,17 @@ public class MethodSecurityMetadataSourceAdvisor extends AbstractPointcutAdvisor * instantiation of the interceptor (and hence the AuthenticationManager). See * SEC-773, for example. The metadataSourceBeanName is used rather than a direct * reference to support serialization via a bean factory lookup. - * * @param adviceBeanName name of the MethodSecurityInterceptor bean * @param attributeSource the SecurityMetadataSource (should be the same as the one * used on the interceptor) * @param attributeSourceBeanName the bean name of the attributeSource (required for * serialization) */ - public MethodSecurityMetadataSourceAdvisor(String adviceBeanName, - MethodSecurityMetadataSource attributeSource, String attributeSourceBeanName) { + public MethodSecurityMetadataSourceAdvisor(String adviceBeanName, MethodSecurityMetadataSource attributeSource, + String attributeSourceBeanName) { Assert.notNull(adviceBeanName, "The adviceBeanName cannot be null"); Assert.notNull(attributeSource, "The attributeSource cannot be null"); - Assert.notNull(attributeSourceBeanName, - "The attributeSourceBeanName cannot be null"); + Assert.notNull(attributeSourceBeanName, "The attributeSourceBeanName cannot be null"); this.adviceBeanName = adviceBeanName; this.attributeSource = attributeSource; @@ -102,12 +106,9 @@ public class MethodSecurityMetadataSourceAdvisor extends AbstractPointcutAdvisor public Advice getAdvice() { synchronized (this.adviceMonitor) { if (interceptor == null) { - Assert.notNull(adviceBeanName, - "'adviceBeanName' must be set for use with bean factory lookup."); - Assert.state(beanFactory != null, - "BeanFactory must be set to resolve 'adviceBeanName'"); - interceptor = beanFactory.getBean(this.adviceBeanName, - MethodInterceptor.class); + Assert.notNull(adviceBeanName, "'adviceBeanName' must be set for use with bean factory lookup."); + Assert.state(beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'"); + interceptor = beanFactory.getBean(this.adviceBeanName, MethodInterceptor.class); } return interceptor; } @@ -117,23 +118,23 @@ public class MethodSecurityMetadataSourceAdvisor extends AbstractPointcutAdvisor this.beanFactory = beanFactory; } - private void readObject(ObjectInputStream ois) throws IOException, - ClassNotFoundException { + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ois.defaultReadObject(); adviceMonitor = new Object(); - attributeSource = beanFactory.getBean(metadataSourceBeanName, - MethodSecurityMetadataSource.class); + attributeSource = beanFactory.getBean(metadataSourceBeanName, MethodSecurityMetadataSource.class); } // ~ Inner Classes // ================================================================================================== - class MethodSecurityMetadataSourcePointcut extends StaticMethodMatcherPointcut - implements Serializable { + class MethodSecurityMetadataSourcePointcut extends StaticMethodMatcherPointcut implements Serializable { + @SuppressWarnings("unchecked") public boolean matches(Method m, Class targetClass) { Collection attributes = attributeSource.getAttributes(m, targetClass); return attributes != null && !attributes.isEmpty(); } + } + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/aopalliance/package-info.java b/core/src/main/java/org/springframework/security/access/intercept/aopalliance/package-info.java index cdf2da36eb..9d59151f06 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/aopalliance/package-info.java +++ b/core/src/main/java/org/springframework/security/access/intercept/aopalliance/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Enforces security for AOP Alliance MethodInvocations, such as via Spring AOP. + * Enforces security for AOP Alliance MethodInvocations, such as via Spring + * AOP. */ package org.springframework.security.access.intercept.aopalliance; - diff --git a/core/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJCallback.java b/core/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJCallback.java index 7b76686229..d960d62372 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJCallback.java +++ b/core/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJCallback.java @@ -24,8 +24,10 @@ package org.springframework.security.access.intercept.aspectj; * @author Ben Alex */ public interface AspectJCallback { + // ~ Methods // ======================================================================================================== Object proceedWithObject(); + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptor.java b/core/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptor.java index c3c8fc25b1..2b9fcbe2e6 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptor.java +++ b/core/src/main/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptor.java @@ -36,7 +36,6 @@ public final class AspectJMethodSecurityInterceptor extends MethodSecurityInterc /** * Method that is suitable for user with @Aspect notation. - * * @param jp The AspectJ joint point being invoked which requires a security decision * @return The returned value from the method invocation * @throws Throwable if the invocation throws one @@ -47,16 +46,13 @@ public final class AspectJMethodSecurityInterceptor extends MethodSecurityInterc /** * Method that is suitable for user with traditional AspectJ-code aspects. - * * @param jp The AspectJ joint point being invoked which requires a security decision * @param advisorProceed the advice-defined anonymous class that implements * {@code AspectJCallback} containing a simple {@code return proceed();} statement - * * @return The returned value from the method invocation */ public Object invoke(JoinPoint jp, AspectJCallback advisorProceed) { - InterceptorStatusToken token = super - .beforeInvocation(new MethodInvocationAdapter(jp)); + InterceptorStatusToken token = super.beforeInvocation(new MethodInvocationAdapter(jp)); Object result; try { @@ -68,4 +64,5 @@ public final class AspectJMethodSecurityInterceptor extends MethodSecurityInterc return super.afterInvocation(token, result); } + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java b/core/src/main/java/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java index d7dc2ea554..5a19ddffaf 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java +++ b/core/src/main/java/org/springframework/security/access/intercept/aspectj/MethodInvocationAdapter.java @@ -31,8 +31,11 @@ import org.aspectj.lang.reflect.CodeSignature; * @since 3.0.3 */ public final class MethodInvocationAdapter implements MethodInvocation { + private final ProceedingJoinPoint jp; + private final Method method; + private final Object target; MethodInvocationAdapter(JoinPoint jp) { @@ -45,15 +48,13 @@ public final class MethodInvocationAdapter implements MethodInvocation { target = jp.getSignature().getDeclaringType(); } String targetMethodName = jp.getStaticPart().getSignature().getName(); - Class[] types = ((CodeSignature) jp.getStaticPart().getSignature()) - .getParameterTypes(); + Class[] types = ((CodeSignature) jp.getStaticPart().getSignature()).getParameterTypes(); Class declaringType = jp.getStaticPart().getSignature().getDeclaringType(); method = findMethod(targetMethodName, declaringType, types); if (method == null) { - throw new IllegalArgumentException( - "Could not obtain target method from JoinPoint: '" + jp + "'"); + throw new IllegalArgumentException("Could not obtain target method from JoinPoint: '" + jp + "'"); } } @@ -96,4 +97,5 @@ public final class MethodInvocationAdapter implements MethodInvocation { public Object proceed() throws Throwable { return jp.proceed(); } + } diff --git a/core/src/main/java/org/springframework/security/access/intercept/aspectj/package-info.java b/core/src/main/java/org/springframework/security/access/intercept/aspectj/package-info.java index 37139ad9b8..d8e8792d9d 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/aspectj/package-info.java +++ b/core/src/main/java/org/springframework/security/access/intercept/aspectj/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Enforces security for AspectJ JointPoints, delegating secure object callbacks to the calling aspect. + * Enforces security for AspectJ JointPoints, delegating secure object + * callbacks to the calling aspect. */ package org.springframework.security.access.intercept.aspectj; - diff --git a/core/src/main/java/org/springframework/security/access/intercept/package-info.java b/core/src/main/java/org/springframework/security/access/intercept/package-info.java index e2c7501807..02bcbacd7a 100644 --- a/core/src/main/java/org/springframework/security/access/intercept/package-info.java +++ b/core/src/main/java/org/springframework/security/access/intercept/package-info.java @@ -17,21 +17,19 @@ * Abstract level security interception classes which are responsible for enforcing the * configured security constraints for a secure object. *

      - * A secure object is a term frequently used throughout the security - * system. It does not refer to a business object that is being - * secured, but instead refers to some infrastructure object that can have - * security facilities provided for it by Spring Security. - * For example, one secure object would be MethodInvocation, - * whilst another would be HTTP - * {@code org.springframework.security.web.FilterInvocation}. Note these are - * infrastructure objects and their design allows them to represent a large - * variety of actual resources that might need to be secured, such as business - * objects or HTTP request URLs. - *

      Each secure object typically has its own interceptor package. - * Each package usually includes a concrete security interceptor (which subclasses - * {@link org.springframework.security.access.intercept.AbstractSecurityInterceptor}) and an - * appropriate {@link org.springframework.security.access.SecurityMetadataSource} - * for the type of resources the secure object represents. + * A secure object is a term frequently used throughout the security system. It + * does not refer to a business object that is being secured, but instead refers to + * some infrastructure object that can have security facilities provided for it by Spring + * Security. For example, one secure object would be MethodInvocation, whilst + * another would be HTTP {@code org.springframework.security.web.FilterInvocation}. Note + * these are infrastructure objects and their design allows them to represent a large + * variety of actual resources that might need to be secured, such as business objects or + * HTTP request URLs. + *

      + * Each secure object typically has its own interceptor package. Each package usually + * includes a concrete security interceptor (which subclasses + * {@link org.springframework.security.access.intercept.AbstractSecurityInterceptor}) and + * an appropriate {@link org.springframework.security.access.SecurityMetadataSource} for + * the type of resources the secure object represents. */ package org.springframework.security.access.intercept; - diff --git a/core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java b/core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java index ef65794b08..61627c34fe 100644 --- a/core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java +++ b/core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java @@ -42,8 +42,7 @@ import org.springframework.security.access.ConfigAttribute; * @author Luke taylor * @since 2.0 */ -public abstract class AbstractFallbackMethodSecurityMetadataSource extends - AbstractMethodSecurityMetadataSource { +public abstract class AbstractFallbackMethodSecurityMetadataSource extends AbstractMethodSecurityMetadataSource { public Collection getAttributes(Method method, Class targetClass) { // The method may be on an interface, but we need attributes from the target @@ -83,13 +82,11 @@ public abstract class AbstractFallbackMethodSecurityMetadataSource extends * may wish to provide advanced capabilities related to method metadata being * "registered" against a method even if the target class does not declare the method * (i.e. the subclass may only inherit the method). - * * @param method the method for the current invocation (never null) * @param targetClass the target class for the invocation (may be null) * @return the security metadata (or null if no metadata applies) */ - protected abstract Collection findAttributes(Method method, - Class targetClass); + protected abstract Collection findAttributes(Method method, Class targetClass); /** * Obtains the security metadata registered against the specified class. @@ -99,7 +96,6 @@ public abstract class AbstractFallbackMethodSecurityMetadataSource extends * should NOT aggregate metadata for each method registered against a class, as the * abstract superclass will separate invoke {@link #findAttributes(Method, Class)} for * individual methods as appropriate. - * * @param clazz the target class for the invocation (never null) * @return the security metadata (or null if no metadata applies) */ diff --git a/core/src/main/java/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java b/core/src/main/java/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java index dcb4d987e3..88dc80fb05 100644 --- a/core/src/main/java/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java +++ b/core/src/main/java/org/springframework/security/access/method/AbstractMethodSecurityMetadataSource.java @@ -31,8 +31,7 @@ import org.springframework.security.access.ConfigAttribute; * @author Ben Alex * @author Luke Taylor */ -public abstract class AbstractMethodSecurityMetadataSource implements - MethodSecurityMetadataSource { +public abstract class AbstractMethodSecurityMetadataSource implements MethodSecurityMetadataSource { protected final Log logger = LogFactory.getLog(getClass()); @@ -65,4 +64,5 @@ public abstract class AbstractMethodSecurityMetadataSource implements public final boolean supports(Class clazz) { return (MethodInvocation.class.isAssignableFrom(clazz)); } + } diff --git a/core/src/main/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java b/core/src/main/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java index 9d85983e33..e51853c6cb 100644 --- a/core/src/main/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java +++ b/core/src/main/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSource.java @@ -36,21 +36,19 @@ import org.springframework.util.ObjectUtils; * @author Ben Alex * @author Luke Taylor */ -public final class DelegatingMethodSecurityMetadataSource extends - AbstractMethodSecurityMetadataSource { - private final static List NULL_CONFIG_ATTRIBUTE = Collections - .emptyList(); +public final class DelegatingMethodSecurityMetadataSource extends AbstractMethodSecurityMetadataSource { + + private final static List NULL_CONFIG_ATTRIBUTE = Collections.emptyList(); private final List methodSecurityMetadataSources; + private final Map> attributeCache = new HashMap<>(); // ~ Constructor // ==================================================================================================== - public DelegatingMethodSecurityMetadataSource( - List methodSecurityMetadataSources) { - Assert.notNull(methodSecurityMetadataSources, - "MethodSecurityMetadataSources cannot be null"); + public DelegatingMethodSecurityMetadataSource(List methodSecurityMetadataSources) { + Assert.notNull(methodSecurityMetadataSources, "MethodSecurityMetadataSources cannot be null"); this.methodSecurityMetadataSources = methodSecurityMetadataSources; } @@ -83,8 +81,7 @@ public final class DelegatingMethodSecurityMetadataSource extends } if (logger.isDebugEnabled()) { - logger.debug("Caching method [" + cacheKey + "] with attributes " - + attributes); + logger.debug("Caching method [" + cacheKey + "] with attributes " + attributes); } this.attributeCache.put(cacheKey, attributes); @@ -113,7 +110,9 @@ public final class DelegatingMethodSecurityMetadataSource extends // ================================================================================================== private static class DefaultCacheKey { + private final Method method; + private final Class targetClass; DefaultCacheKey(Method method, Class targetClass) { @@ -124,20 +123,20 @@ public final class DelegatingMethodSecurityMetadataSource extends @Override public boolean equals(Object other) { DefaultCacheKey otherKey = (DefaultCacheKey) other; - return (this.method.equals(otherKey.method) && ObjectUtils.nullSafeEquals( - this.targetClass, otherKey.targetClass)); + return (this.method.equals(otherKey.method) + && ObjectUtils.nullSafeEquals(this.targetClass, otherKey.targetClass)); } @Override public int hashCode() { - return this.method.hashCode() * 21 - + (this.targetClass != null ? this.targetClass.hashCode() : 0); + return this.method.hashCode() * 21 + (this.targetClass != null ? this.targetClass.hashCode() : 0); } @Override public String toString() { - return "CacheKey[" + (targetClass == null ? "-" : targetClass.getName()) - + "; " + method + "]"; + return "CacheKey[" + (targetClass == null ? "-" : targetClass.getName()) + "; " + method + "]"; } + } + } diff --git a/core/src/main/java/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java b/core/src/main/java/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java index df79e47b1e..2591c1655c 100644 --- a/core/src/main/java/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java +++ b/core/src/main/java/org/springframework/security/access/method/MapBasedMethodSecurityMetadataSource.java @@ -42,8 +42,8 @@ import org.springframework.util.ClassUtils; * @author Ben Alex * @since 2.0 */ -public class MapBasedMethodSecurityMetadataSource extends - AbstractFallbackMethodSecurityMetadataSource implements BeanClassLoaderAware { +public class MapBasedMethodSecurityMetadataSource extends AbstractFallbackMethodSecurityMetadataSource + implements BeanClassLoaderAware { // ~ Instance fields // ================================================================================================ @@ -65,8 +65,7 @@ public class MapBasedMethodSecurityMetadataSource extends * Creates the MapBasedMethodSecurityMetadataSource from a * @param methodMap map of method names to ConfigAttributes. */ - public MapBasedMethodSecurityMetadataSource( - Map> methodMap) { + public MapBasedMethodSecurityMetadataSource(Map> methodMap) { for (Map.Entry> entry : methodMap.entrySet()) { addSecureMethod(entry.getKey(), entry.getValue()); } @@ -85,8 +84,7 @@ public class MapBasedMethodSecurityMetadataSource extends * applicable. */ @Override - protected Collection findAttributes(Method method, - Class targetClass) { + protected Collection findAttributes(Method method, Class targetClass) { if (targetClass == null) { return null; } @@ -94,8 +92,7 @@ public class MapBasedMethodSecurityMetadataSource extends return findAttributesSpecifiedAgainst(method, targetClass); } - private List findAttributesSpecifiedAgainst(Method method, - Class clazz) { + private List findAttributesSpecifiedAgainst(Method method, Class clazz) { RegisteredMethod registeredMethod = new RegisteredMethod(method, clazz); if (methodMap.containsKey(registeredMethod)) { return methodMap.get(registeredMethod); @@ -110,7 +107,6 @@ public class MapBasedMethodSecurityMetadataSource extends /** * Add configuration attributes for a secure method. Method names can end or start * with * for matching multiple methods. - * * @param name type and method name, separated by a dot * @param attr the security attributes associated with the method */ @@ -118,8 +114,7 @@ public class MapBasedMethodSecurityMetadataSource extends int lastDotIndex = name.lastIndexOf("."); if (lastDotIndex == -1) { - throw new IllegalArgumentException("'" + name - + "' is not a valid method name: format is FQN.methodName"); + throw new IllegalArgumentException("'" + name + "' is not a valid method name: format is FQN.methodName"); } String methodName = name.substring(lastDotIndex + 1); @@ -134,19 +129,16 @@ public class MapBasedMethodSecurityMetadataSource extends /** * Add configuration attributes for a secure method. Mapped method names can end or * start with * for matching multiple methods. - * * @param javaType target interface or class the security configuration attribute * applies to * @param mappedName mapped method name, which the javaType has declared or inherited * @param attr required authorities associated with the method */ - public void addSecureMethod(Class javaType, String mappedName, - List attr) { + public void addSecureMethod(Class javaType, String mappedName, List attr) { String name = javaType.getName() + '.' + mappedName; if (logger.isDebugEnabled()) { - logger.debug("Request to add secure method [" + name + "] with attributes [" - + attr + "]"); + logger.debug("Request to add secure method [" + name + "] with attributes [" + attr + "]"); } Method[] methods = javaType.getMethods(); @@ -159,8 +151,7 @@ public class MapBasedMethodSecurityMetadataSource extends } if (matchingMethods.isEmpty()) { - throw new IllegalArgumentException("Couldn't find method '" + mappedName - + "' on '" + javaType + "'"); + throw new IllegalArgumentException("Couldn't find method '" + mappedName + "' on '" + javaType + "'"); } // register all matching methods @@ -168,24 +159,20 @@ public class MapBasedMethodSecurityMetadataSource extends RegisteredMethod registeredMethod = new RegisteredMethod(method, javaType); String regMethodName = this.nameMap.get(registeredMethod); - if ((regMethodName == null) - || (!regMethodName.equals(name) && (regMethodName.length() <= name - .length()))) { + if ((regMethodName == null) || (!regMethodName.equals(name) && (regMethodName.length() <= name.length()))) { // no already registered method name, or more specific // method name specification now -> (re-)register method if (regMethodName != null) { - logger.debug("Replacing attributes for secure method [" + method - + "]: current name [" + name + "] is more specific than [" - + regMethodName + "]"); + logger.debug("Replacing attributes for secure method [" + method + "]: current name [" + name + + "] is more specific than [" + regMethodName + "]"); } this.nameMap.put(registeredMethod, name); addSecureMethod(registeredMethod, attr); } else { - logger.debug("Keeping attributes for secure method [" + method - + "]: current name [" + name + "] is not more specific than [" - + regMethodName + "]"); + logger.debug("Keeping attributes for secure method [" + method + "]: current name [" + name + + "] is not more specific than [" + regMethodName + "]"); } } } @@ -199,14 +186,11 @@ public class MapBasedMethodSecurityMetadataSource extends *

      * This method should only be called during initialization of the {@code BeanFactory}. */ - public void addSecureMethod(Class javaType, Method method, - List attr) { + public void addSecureMethod(Class javaType, Method method, List attr) { RegisteredMethod key = new RegisteredMethod(method, javaType); if (methodMap.containsKey(key)) { - logger.debug("Method [" + method - + "] is already registered with attributes [" + methodMap.get(key) - + "]"); + logger.debug("Method [" + method + "] is already registered with attributes [" + methodMap.get(key) + "]"); return; } @@ -215,7 +199,6 @@ public class MapBasedMethodSecurityMetadataSource extends /** * Add configuration attributes for a secure method. - * * @param method the method to be secured * @param attr required authorities associated with the method */ @@ -223,15 +206,13 @@ public class MapBasedMethodSecurityMetadataSource extends Assert.notNull(method, "RegisteredMethod required"); Assert.notNull(attr, "Configuration attribute required"); if (logger.isInfoEnabled()) { - logger.info("Adding secure method [" + method + "] with attributes [" + attr - + "]"); + logger.info("Adding secure method [" + method + "] with attributes [" + attr + "]"); } this.methodMap.put(method, attr); } /** * Obtains the configuration attributes explicitly defined against this bean. - * * @return the attributes explicitly defined against this bean */ @Override @@ -248,17 +229,13 @@ public class MapBasedMethodSecurityMetadataSource extends /** * Return if the given method name matches the mapped name. The default implementation * checks for "xxx" and "xxx" matches. - * * @param methodName the method name of the class * @param mappedName the name in the descriptor - * * @return if the names match */ private boolean isMatch(String methodName, String mappedName) { - return (mappedName.endsWith("*") && methodName.startsWith(mappedName.substring(0, - mappedName.length() - 1))) - || (mappedName.startsWith("*") && methodName.endsWith(mappedName - .substring(1, mappedName.length()))); + return (mappedName.endsWith("*") && methodName.startsWith(mappedName.substring(0, mappedName.length() - 1))) + || (mappedName.startsWith("*") && methodName.endsWith(mappedName.substring(1, mappedName.length()))); } @Override @@ -284,7 +261,9 @@ public class MapBasedMethodSecurityMetadataSource extends * we're invoking against and the Method will provide details of the declared class. */ private static class RegisteredMethod { + private final Method method; + private final Class registeredJavaType; RegisteredMethod(Method method, Class registeredJavaType) { @@ -301,8 +280,7 @@ public class MapBasedMethodSecurityMetadataSource extends } if (obj != null && obj instanceof RegisteredMethod) { RegisteredMethod rhs = (RegisteredMethod) obj; - return method.equals(rhs.method) - && registeredJavaType.equals(rhs.registeredJavaType); + return method.equals(rhs.method) && registeredJavaType.equals(rhs.registeredJavaType); } return false; } @@ -314,9 +292,9 @@ public class MapBasedMethodSecurityMetadataSource extends @Override public String toString() { - return "RegisteredMethod[" + registeredJavaType.getName() + "; " + method - + "]"; + return "RegisteredMethod[" + registeredJavaType.getName() + "; " + method + "]"; } + } } diff --git a/core/src/main/java/org/springframework/security/access/method/MethodSecurityMetadataSource.java b/core/src/main/java/org/springframework/security/access/method/MethodSecurityMetadataSource.java index adfc739ed7..5cfb3ff9ca 100644 --- a/core/src/main/java/org/springframework/security/access/method/MethodSecurityMetadataSource.java +++ b/core/src/main/java/org/springframework/security/access/method/MethodSecurityMetadataSource.java @@ -29,5 +29,7 @@ import org.springframework.security.access.SecurityMetadataSource; * @author Ben Alex */ public interface MethodSecurityMetadataSource extends SecurityMetadataSource { + Collection getAttributes(Method method, Class targetClass); + } diff --git a/core/src/main/java/org/springframework/security/access/method/P.java b/core/src/main/java/org/springframework/security/access/method/P.java index 0d8139e455..b164c572ab 100644 --- a/core/src/main/java/org/springframework/security/access/method/P.java +++ b/core/src/main/java/org/springframework/security/access/method/P.java @@ -45,4 +45,5 @@ public @interface P { * @return */ String value(); + } \ No newline at end of file diff --git a/core/src/main/java/org/springframework/security/access/method/package-info.java b/core/src/main/java/org/springframework/security/access/method/package-info.java index b90eb4948e..619c0bde09 100644 --- a/core/src/main/java/org/springframework/security/access/method/package-info.java +++ b/core/src/main/java/org/springframework/security/access/method/package-info.java @@ -14,8 +14,7 @@ * limitations under the License. */ /** - * Provides {@code SecurityMetadataSource} implementations for securing Java method invocations via different - * AOP libraries. + * Provides {@code SecurityMetadataSource} implementations for securing Java method + * invocations via different AOP libraries. */ package org.springframework.security.access.method; - diff --git a/core/src/main/java/org/springframework/security/access/package-info.java b/core/src/main/java/org/springframework/security/access/package-info.java index 99908b931a..ebf53f5585 100644 --- a/core/src/main/java/org/springframework/security/access/package-info.java +++ b/core/src/main/java/org/springframework/security/access/package-info.java @@ -14,9 +14,10 @@ * limitations under the License. */ /** - * Core access-control related code, including security metadata related classes, interception code, access control - * annotations, EL support and voter-based implementations of the central - * {@link org.springframework.security.access.AccessDecisionManager AccessDecisionManager} interface. + * Core access-control related code, including security metadata related classes, + * interception code, access control annotations, EL support and voter-based + * implementations of the central + * {@link org.springframework.security.access.AccessDecisionManager AccessDecisionManager} + * interface. */ package org.springframework.security.access; - diff --git a/core/src/main/java/org/springframework/security/access/prepost/PostAuthorize.java b/core/src/main/java/org/springframework/security/access/prepost/PostAuthorize.java index 18e5abe644..379c3dcbd5 100644 --- a/core/src/main/java/org/springframework/security/access/prepost/PostAuthorize.java +++ b/core/src/main/java/org/springframework/security/access/prepost/PostAuthorize.java @@ -34,9 +34,11 @@ import java.lang.annotation.Target; @Inherited @Documented public @interface PostAuthorize { + /** * @return the Spring-EL expression to be evaluated after invoking the protected * method */ String value(); + } diff --git a/core/src/main/java/org/springframework/security/access/prepost/PostFilter.java b/core/src/main/java/org/springframework/security/access/prepost/PostFilter.java index 73efa4ad3b..5628e972eb 100644 --- a/core/src/main/java/org/springframework/security/access/prepost/PostFilter.java +++ b/core/src/main/java/org/springframework/security/access/prepost/PostFilter.java @@ -34,9 +34,11 @@ import java.lang.annotation.Target; @Inherited @Documented public @interface PostFilter { + /** * @return the Spring-EL expression to be evaluated after invoking the protected * method */ String value(); + } diff --git a/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java b/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java index 6c171fb7e1..28218b7885 100644 --- a/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java +++ b/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAdviceProvider.java @@ -35,6 +35,7 @@ import org.springframework.security.core.Authentication; * @since 3.0 */ public class PostInvocationAdviceProvider implements AfterInvocationProvider { + protected final Log logger = LogFactory.getLog(getClass()); private final PostInvocationAuthorizationAdvice postAdvice; @@ -43,9 +44,8 @@ public class PostInvocationAdviceProvider implements AfterInvocationProvider { this.postAdvice = postAdvice; } - public Object decide(Authentication authentication, Object object, - Collection config, Object returnedObject) - throws AccessDeniedException { + public Object decide(Authentication authentication, Object object, Collection config, + Object returnedObject) throws AccessDeniedException { PostInvocationAttribute pia = findPostInvocationAttribute(config); @@ -53,12 +53,10 @@ public class PostInvocationAdviceProvider implements AfterInvocationProvider { return returnedObject; } - return postAdvice.after(authentication, (MethodInvocation) object, pia, - returnedObject); + return postAdvice.after(authentication, (MethodInvocation) object, pia, returnedObject); } - private PostInvocationAttribute findPostInvocationAttribute( - Collection config) { + private PostInvocationAttribute findPostInvocationAttribute(Collection config) { for (ConfigAttribute attribute : config) { if (attribute instanceof PostInvocationAttribute) { return (PostInvocationAttribute) attribute; @@ -75,4 +73,5 @@ public class PostInvocationAdviceProvider implements AfterInvocationProvider { public boolean supports(Class clazz) { return clazz.isAssignableFrom(MethodInvocation.class); } + } diff --git a/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAttribute.java b/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAttribute.java index 9608345f3e..e45a10a7d3 100644 --- a/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAttribute.java +++ b/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAttribute.java @@ -18,8 +18,8 @@ package org.springframework.security.access.prepost; import org.springframework.security.access.ConfigAttribute; /** - * Marker interface for attributes which are created from combined @PostFilter and @PostAuthorize - * annotations. + * Marker interface for attributes which are created from combined @PostFilter + * and @PostAuthorize annotations. *

      * Consumed by a {@link PostInvocationAuthorizationAdvice}. * diff --git a/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAuthorizationAdvice.java b/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAuthorizationAdvice.java index 76166982ab..78f2e4b4ab 100644 --- a/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAuthorizationAdvice.java +++ b/core/src/main/java/org/springframework/security/access/prepost/PostInvocationAuthorizationAdvice.java @@ -28,7 +28,7 @@ import org.springframework.security.core.Authentication; */ public interface PostInvocationAuthorizationAdvice extends AopInfrastructureBean { - Object after(Authentication authentication, MethodInvocation mi, - PostInvocationAttribute pia, Object returnedObject) + Object after(Authentication authentication, MethodInvocation mi, PostInvocationAttribute pia, Object returnedObject) throws AccessDeniedException; + } diff --git a/core/src/main/java/org/springframework/security/access/prepost/PreAuthorize.java b/core/src/main/java/org/springframework/security/access/prepost/PreAuthorize.java index 65cc07a60f..0292b2be73 100644 --- a/core/src/main/java/org/springframework/security/access/prepost/PreAuthorize.java +++ b/core/src/main/java/org/springframework/security/access/prepost/PreAuthorize.java @@ -34,9 +34,11 @@ import java.lang.annotation.Target; @Inherited @Documented public @interface PreAuthorize { + /** * @return the Spring-EL expression to be evaluated before invoking the protected * method */ String value(); + } diff --git a/core/src/main/java/org/springframework/security/access/prepost/PreFilter.java b/core/src/main/java/org/springframework/security/access/prepost/PreFilter.java index 0432936576..880feedfa3 100644 --- a/core/src/main/java/org/springframework/security/access/prepost/PreFilter.java +++ b/core/src/main/java/org/springframework/security/access/prepost/PreFilter.java @@ -46,6 +46,7 @@ import java.lang.annotation.Target; @Inherited @Documented public @interface PreFilter { + /** * @return the Spring-EL expression to be evaluated before invoking the protected * method @@ -58,4 +59,5 @@ public @interface PreFilter { * attribute can be omitted. */ String filterTarget() default ""; + } diff --git a/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAttribute.java b/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAttribute.java index a0fecd9e49..3c11e7a7fe 100644 --- a/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAttribute.java +++ b/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAttribute.java @@ -18,8 +18,8 @@ package org.springframework.security.access.prepost; import org.springframework.security.access.ConfigAttribute; /** - * Marker interface for attributes which are created from combined @PreFilter and @PreAuthorize - * annotations. + * Marker interface for attributes which are created from combined @PreFilter + * and @PreAuthorize annotations. *

      * Consumed by a {@link PreInvocationAuthorizationAdvice}. * diff --git a/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdvice.java b/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdvice.java index 72bd17009b..1f6f75ffe7 100644 --- a/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdvice.java +++ b/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdvice.java @@ -30,14 +30,13 @@ public interface PreInvocationAuthorizationAdvice extends AopInfrastructureBean /** * The "before" advice which should be executed to perform any filtering necessary and * to decide whether the method call is authorised. - * * @param authentication the information on the principal on whose account the * decision should be made * @param mi the method invocation being attempted - * @param preInvocationAttribute the attribute built from the @PreFilter and @PostFilter - * annotations. + * @param preInvocationAttribute the attribute built from the @PreFilter + * and @PostFilter annotations. * @return true if authorised, false otherwise */ - boolean before(Authentication authentication, MethodInvocation mi, - PreInvocationAttribute preInvocationAttribute); + boolean before(Authentication authentication, MethodInvocation mi, PreInvocationAttribute preInvocationAttribute); + } diff --git a/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java b/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java index 4432fbc6cf..7c89e1c23b 100644 --- a/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java +++ b/core/src/main/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoter.java @@ -37,8 +37,8 @@ import org.springframework.security.core.Authentication; * @author Luke Taylor * @since 3.0 */ -public class PreInvocationAuthorizationAdviceVoter implements - AccessDecisionVoter { +public class PreInvocationAuthorizationAdviceVoter implements AccessDecisionVoter { + protected final Log logger = LogFactory.getLog(getClass()); private final PreInvocationAuthorizationAdvice preAdvice; @@ -55,8 +55,7 @@ public class PreInvocationAuthorizationAdviceVoter implements return MethodInvocation.class.isAssignableFrom(clazz); } - public int vote(Authentication authentication, MethodInvocation method, - Collection attributes) { + public int vote(Authentication authentication, MethodInvocation method, Collection attributes) { // Find prefilter and preauth (or combined) attributes // if both null, abstain @@ -74,8 +73,7 @@ public class PreInvocationAuthorizationAdviceVoter implements return allowed ? ACCESS_GRANTED : ACCESS_DENIED; } - private PreInvocationAttribute findPreInvocationAttribute( - Collection config) { + private PreInvocationAttribute findPreInvocationAttribute(Collection config) { for (ConfigAttribute attribute : config) { if (attribute instanceof PreInvocationAttribute) { return (PreInvocationAttribute) attribute; @@ -84,4 +82,5 @@ public class PreInvocationAuthorizationAdviceVoter implements return null; } + } diff --git a/core/src/main/java/org/springframework/security/access/prepost/PrePostAdviceReactiveMethodInterceptor.java b/core/src/main/java/org/springframework/security/access/prepost/PrePostAdviceReactiveMethodInterceptor.java index 98ef8d43e1..debb0dce37 100644 --- a/core/src/main/java/org/springframework/security/access/prepost/PrePostAdviceReactiveMethodInterceptor.java +++ b/core/src/main/java/org/springframework/security/access/prepost/PrePostAdviceReactiveMethodInterceptor.java @@ -36,15 +36,16 @@ import java.lang.reflect.Method; import java.util.Collection; /** - * A {@link MethodInterceptor} that supports {@link PreAuthorize} and {@link PostAuthorize} for methods that return - * {@link Mono} or {@link Flux} + * A {@link MethodInterceptor} that supports {@link PreAuthorize} and + * {@link PostAuthorize} for methods that return {@link Mono} or {@link Flux} * * @author Rob Winch * @since 5.0 */ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor { + private Authentication anonymous = new AnonymousAuthenticationToken("key", "anonymous", - AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); + AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); private final MethodSecurityMetadataSource attributeSource; @@ -58,7 +59,9 @@ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor * @param preInvocationAdvice the {@link PreInvocationAuthorizationAdvice} to use * @param postInvocationAdvice the {@link PostInvocationAuthorizationAdvice} to use */ - public PrePostAdviceReactiveMethodInterceptor(MethodSecurityMetadataSource attributeSource, PreInvocationAuthorizationAdvice preInvocationAdvice, PostInvocationAuthorizationAdvice postInvocationAdvice) { + public PrePostAdviceReactiveMethodInterceptor(MethodSecurityMetadataSource attributeSource, + PreInvocationAuthorizationAdvice preInvocationAdvice, + PostInvocationAuthorizationAdvice postInvocationAdvice) { Assert.notNull(attributeSource, "attributeSource cannot be null"); Assert.notNull(preInvocationAdvice, "preInvocationAdvice cannot be null"); Assert.notNull(postInvocationAdvice, "postInvocationAdvice cannot be null"); @@ -73,52 +76,44 @@ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor Method method = invocation.getMethod(); Class returnType = method.getReturnType(); if (!Publisher.class.isAssignableFrom(returnType)) { - throw new IllegalStateException("The returnType " + returnType + " on " + method + " must return an instance of org.reactivestreams.Publisher (i.e. Mono / Flux) in order to support Reactor Context"); + throw new IllegalStateException("The returnType " + returnType + " on " + method + + " must return an instance of org.reactivestreams.Publisher (i.e. Mono / Flux) in order to support Reactor Context"); } Class targetClass = invocation.getThis().getClass(); - Collection attributes = this.attributeSource - .getAttributes(method, targetClass); + Collection attributes = this.attributeSource.getAttributes(method, targetClass); PreInvocationAttribute preAttr = findPreInvocationAttribute(attributes); Mono toInvoke = ReactiveSecurityContextHolder.getContext() - .map(SecurityContext::getAuthentication) - .defaultIfEmpty(this.anonymous) - .filter( auth -> this.preInvocationAdvice.before(auth, invocation, preAttr)) - .switchIfEmpty(Mono.defer(() -> Mono.error(new AccessDeniedException("Denied")))); - + .map(SecurityContext::getAuthentication).defaultIfEmpty(this.anonymous) + .filter(auth -> this.preInvocationAdvice.before(auth, invocation, preAttr)) + .switchIfEmpty(Mono.defer(() -> Mono.error(new AccessDeniedException("Denied")))); PostInvocationAttribute attr = findPostInvocationAttribute(attributes); if (Mono.class.isAssignableFrom(returnType)) { - return toInvoke - .flatMap( auth -> this.>proceed(invocation) - .map( r -> attr == null ? r : this.postAdvice.after(auth, invocation, attr, r)) - ); + return toInvoke.flatMap(auth -> this.>proceed(invocation) + .map(r -> attr == null ? r : this.postAdvice.after(auth, invocation, attr, r))); } if (Flux.class.isAssignableFrom(returnType)) { - return toInvoke - .flatMapMany( auth -> this.>proceed(invocation) - .map( r -> attr == null ? r : this.postAdvice.after(auth, invocation, attr, r)) - ); + return toInvoke.flatMapMany(auth -> this.>proceed(invocation) + .map(r -> attr == null ? r : this.postAdvice.after(auth, invocation, attr, r))); } - return toInvoke - .flatMapMany( auth -> Flux.from(this.>proceed(invocation)) - .map( r -> attr == null ? r : this.postAdvice.after(auth, invocation, attr, r)) - ); + return toInvoke.flatMapMany(auth -> Flux.from(this.>proceed(invocation)) + .map(r -> attr == null ? r : this.postAdvice.after(auth, invocation, attr, r))); } private static > T proceed(final MethodInvocation invocation) { try { return (T) invocation.proceed(); - } catch(Throwable throwable) { + } + catch (Throwable throwable) { throw Exceptions.propagate(throwable); } } - private static PostInvocationAttribute findPostInvocationAttribute( - Collection config) { + private static PostInvocationAttribute findPostInvocationAttribute(Collection config) { for (ConfigAttribute attribute : config) { if (attribute instanceof PostInvocationAttribute) { return (PostInvocationAttribute) attribute; @@ -128,8 +123,7 @@ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor return null; } - private static PreInvocationAttribute findPreInvocationAttribute( - Collection config) { + private static PreInvocationAttribute findPreInvocationAttribute(Collection config) { for (ConfigAttribute attribute : config) { if (attribute instanceof PreInvocationAttribute) { return (PreInvocationAttribute) attribute; @@ -138,4 +132,5 @@ public class PrePostAdviceReactiveMethodInterceptor implements MethodInterceptor return null; } + } diff --git a/core/src/main/java/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java b/core/src/main/java/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java index c6797debf1..16f8cc04e0 100644 --- a/core/src/main/java/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java +++ b/core/src/main/java/org/springframework/security/access/prepost/PrePostAnnotationSecurityMetadataSource.java @@ -25,11 +25,12 @@ import org.springframework.security.access.method.AbstractMethodSecurityMetadata import org.springframework.util.ClassUtils; /** - * MethodSecurityMetadataSource which extracts metadata from the @PreFilter and @PreAuthorize - * annotations placed on a method. This class is merely responsible for locating the - * relevant annotations (if any). It delegates the actual ConfigAttribute - * creation to its {@link PrePostInvocationAttributeFactory}, thus decoupling itself from - * the mechanism which will enforce the annotations' behaviour. + * MethodSecurityMetadataSource which extracts metadata from the @PreFilter + * and @PreAuthorize annotations placed on a method. This class is merely responsible for + * locating the relevant annotations (if any). It delegates the actual + * ConfigAttribute creation to its {@link PrePostInvocationAttributeFactory}, + * thus decoupling itself from the mechanism which will enforce the annotations' + * behaviour. *

      * Annotations may be specified on classes or methods, and method-specific annotations * will take precedence. If you use any annotation and do not specify a pre-authorization @@ -41,17 +42,14 @@ import org.springframework.util.ClassUtils; * defined on the method itself, or at interface or class level. * * @see PreInvocationAuthorizationAdviceVoter - * * @author Luke Taylor * @since 3.0 */ -public class PrePostAnnotationSecurityMetadataSource extends - AbstractMethodSecurityMetadataSource { +public class PrePostAnnotationSecurityMetadataSource extends AbstractMethodSecurityMetadataSource { private final PrePostInvocationAttributeFactory attributeFactory; - public PrePostAnnotationSecurityMetadataSource( - PrePostInvocationAttributeFactory attributeFactory) { + public PrePostAnnotationSecurityMetadataSource(PrePostInvocationAttributeFactory attributeFactory) { this.attributeFactory = attributeFactory; } @@ -60,18 +58,15 @@ public class PrePostAnnotationSecurityMetadataSource extends return Collections.emptyList(); } - logger.trace("Looking for Pre/Post annotations for method '" + method.getName() - + "' on target class '" + targetClass + "'"); + logger.trace("Looking for Pre/Post annotations for method '" + method.getName() + "' on target class '" + + targetClass + "'"); PreFilter preFilter = findAnnotation(method, targetClass, PreFilter.class); - PreAuthorize preAuthorize = findAnnotation(method, targetClass, - PreAuthorize.class); + PreAuthorize preAuthorize = findAnnotation(method, targetClass, PreAuthorize.class); PostFilter postFilter = findAnnotation(method, targetClass, PostFilter.class); // TODO: Can we check for void methods and throw an exception here? - PostAuthorize postAuthorize = findAnnotation(method, targetClass, - PostAuthorize.class); + PostAuthorize postAuthorize = findAnnotation(method, targetClass, PostAuthorize.class); - if (preFilter == null && preAuthorize == null && postFilter == null - && postAuthorize == null) { + if (preFilter == null && preAuthorize == null && postFilter == null && postAuthorize == null) { // There is no meta-data so return logger.trace("No expression annotations found"); return Collections.emptyList(); @@ -81,20 +76,19 @@ public class PrePostAnnotationSecurityMetadataSource extends String filterObject = preFilter == null ? null : preFilter.filterTarget(); String preAuthorizeAttribute = preAuthorize == null ? null : preAuthorize.value(); String postFilterAttribute = postFilter == null ? null : postFilter.value(); - String postAuthorizeAttribute = postAuthorize == null ? null : postAuthorize - .value(); + String postAuthorizeAttribute = postAuthorize == null ? null : postAuthorize.value(); ArrayList attrs = new ArrayList<>(2); - PreInvocationAttribute pre = attributeFactory.createPreInvocationAttribute( - preFilterAttribute, filterObject, preAuthorizeAttribute); + PreInvocationAttribute pre = attributeFactory.createPreInvocationAttribute(preFilterAttribute, filterObject, + preAuthorizeAttribute); if (pre != null) { attrs.add(pre); } - PostInvocationAttribute post = attributeFactory.createPostInvocationAttribute( - postFilterAttribute, postAuthorizeAttribute); + PostInvocationAttribute post = attributeFactory.createPostInvocationAttribute(postFilterAttribute, + postAuthorizeAttribute); if (post != null) { attrs.add(post); @@ -115,8 +109,7 @@ public class PrePostAnnotationSecurityMetadataSource extends * for the logic of this method. The ordering here is slightly different in that we * consider method-specific annotations on an interface before class-level ones. */ - private A findAnnotation(Method method, Class targetClass, - Class annotationClass) { + private A findAnnotation(Method method, Class targetClass, Class annotationClass) { // The method may be on an interface, but we need attributes from the target // class. // If the target class is null, the method will be unchanged. @@ -140,12 +133,10 @@ public class PrePostAnnotationSecurityMetadataSource extends // Check the class-level (note declaringClass, not targetClass, which may not // actually implement the method) - annotation = AnnotationUtils.findAnnotation(specificMethod.getDeclaringClass(), - annotationClass); + annotation = AnnotationUtils.findAnnotation(specificMethod.getDeclaringClass(), annotationClass); if (annotation != null) { - logger.debug(annotation + " found on: " - + specificMethod.getDeclaringClass().getName()); + logger.debug(annotation + " found on: " + specificMethod.getDeclaringClass().getName()); return annotation; } diff --git a/core/src/main/java/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java b/core/src/main/java/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java index bd1716555a..6c6f9c3360 100644 --- a/core/src/main/java/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java +++ b/core/src/main/java/org/springframework/security/access/prepost/PrePostInvocationAttributeFactory.java @@ -18,15 +18,14 @@ package org.springframework.security.access.prepost; import org.springframework.aop.framework.AopInfrastructureBean; /** - * * @author Luke Taylor * @since 3.0 */ public interface PrePostInvocationAttributeFactory extends AopInfrastructureBean { - PreInvocationAttribute createPreInvocationAttribute(String preFilterAttribute, - String filterObject, String preAuthorizeAttribute); + PreInvocationAttribute createPreInvocationAttribute(String preFilterAttribute, String filterObject, + String preAuthorizeAttribute); + + PostInvocationAttribute createPostInvocationAttribute(String postFilterAttribute, String postAuthorizeAttribute); - PostInvocationAttribute createPostInvocationAttribute(String postFilterAttribute, - String postAuthorizeAttribute); } diff --git a/core/src/main/java/org/springframework/security/access/prepost/package-info.java b/core/src/main/java/org/springframework/security/access/prepost/package-info.java index 8db4a0005b..f23230de60 100644 --- a/core/src/main/java/org/springframework/security/access/prepost/package-info.java +++ b/core/src/main/java/org/springframework/security/access/prepost/package-info.java @@ -14,11 +14,10 @@ * limitations under the License. */ /** - * Contains the infrastructure classes for handling the {@code @PreAuthorize}, {@code @PreFilter}, {@code @PostAuthorize} - * and {@code @PostFilter} annotations. + * Contains the infrastructure classes for handling the {@code @PreAuthorize}, + * {@code @PreFilter}, {@code @PostAuthorize} and {@code @PostFilter} annotations. *

      - * Other than the annotations themselves, the classes should be regarded as for internal framework use and - * are liable to change without notice. + * Other than the annotations themselves, the classes should be regarded as for internal + * framework use and are liable to change without notice. */ package org.springframework.security.access.prepost; - diff --git a/core/src/main/java/org/springframework/security/access/vote/AbstractAccessDecisionManager.java b/core/src/main/java/org/springframework/security/access/vote/AbstractAccessDecisionManager.java index 3cec181713..cffdef99da 100644 --- a/core/src/main/java/org/springframework/security/access/vote/AbstractAccessDecisionManager.java +++ b/core/src/main/java/org/springframework/security/access/vote/AbstractAccessDecisionManager.java @@ -39,8 +39,9 @@ import org.springframework.util.Assert; * and the access control behaviour if all voters abstain from voting (defaults to deny * access). */ -public abstract class AbstractAccessDecisionManager implements AccessDecisionManager, - InitializingBean, MessageSourceAware { +public abstract class AbstractAccessDecisionManager + implements AccessDecisionManager, InitializingBean, MessageSourceAware { + // ~ Instance fields // ================================================================================================ protected final Log logger = LogFactory.getLog(getClass()); @@ -51,8 +52,7 @@ public abstract class AbstractAccessDecisionManager implements AccessDecisionMan private boolean allowIfAllAbstainDecisions = false; - protected AbstractAccessDecisionManager( - List> decisionVoters) { + protected AbstractAccessDecisionManager(List> decisionVoters) { Assert.notEmpty(decisionVoters, "A list of AccessDecisionVoters is required"); this.decisionVoters = decisionVoters; } @@ -67,8 +67,8 @@ public abstract class AbstractAccessDecisionManager implements AccessDecisionMan protected final void checkAllowIfAllAbstainDecisions() { if (!this.isAllowIfAllAbstainDecisions()) { - throw new AccessDeniedException(messages.getMessage( - "AbstractAccessDecisionManager.accessDenied", "Access is denied")); + throw new AccessDeniedException( + messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); } } @@ -104,7 +104,6 @@ public abstract class AbstractAccessDecisionManager implements AccessDecisionMan *

      * If one or more voters cannot support the presented class, false is * returned. - * * @param clazz the type of secured object being presented * @return true if this type is supported */ @@ -117,4 +116,5 @@ public abstract class AbstractAccessDecisionManager implements AccessDecisionMan return true; } + } diff --git a/core/src/main/java/org/springframework/security/access/vote/AbstractAclVoter.java b/core/src/main/java/org/springframework/security/access/vote/AbstractAclVoter.java index 67fbe73bef..7b2eb5e24a 100644 --- a/core/src/main/java/org/springframework/security/access/vote/AbstractAclVoter.java +++ b/core/src/main/java/org/springframework/security/access/vote/AbstractAclVoter.java @@ -27,6 +27,7 @@ import org.springframework.util.Assert; * @author Ben Alex */ public abstract class AbstractAclVoter implements AccessDecisionVoter { + // ~ Instance fields // ================================================================================================ @@ -57,21 +58,19 @@ public abstract class AbstractAclVoter implements AccessDecisionVoter processDomainObjectClass) { - Assert.notNull(processDomainObjectClass, - "processDomainObjectClass cannot be set to null"); + Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null"); this.processDomainObjectClass = processDomainObjectClass; } /** * This implementation supports only MethodSecurityInterceptor, because * it queries the presented MethodInvocation. - * * @param clazz the secure object - * * @return true if the secure object is MethodInvocation, * false otherwise */ public boolean supports(Class clazz) { return (MethodInvocation.class.isAssignableFrom(clazz)); } + } diff --git a/core/src/main/java/org/springframework/security/access/vote/AffirmativeBased.java b/core/src/main/java/org/springframework/security/access/vote/AffirmativeBased.java index 30f27da022..c43aad9c14 100644 --- a/core/src/main/java/org/springframework/security/access/vote/AffirmativeBased.java +++ b/core/src/main/java/org/springframework/security/access/vote/AffirmativeBased.java @@ -47,16 +47,14 @@ public class AffirmativeBased extends AbstractAccessDecisionManager { * be based on the {@link #isAllowIfAllAbstainDecisions()} property (defaults to * false). *

      - * * @param authentication the caller invoking the method * @param object the secured object * @param configAttributes the configuration attributes associated with the method * being invoked - * * @throws AccessDeniedException if access is denied */ - public void decide(Authentication authentication, Object object, - Collection configAttributes) throws AccessDeniedException { + public void decide(Authentication authentication, Object object, Collection configAttributes) + throws AccessDeniedException { int deny = 0; for (AccessDecisionVoter voter : getDecisionVoters()) { @@ -81,11 +79,12 @@ public class AffirmativeBased extends AbstractAccessDecisionManager { } if (deny > 0) { - throw new AccessDeniedException(messages.getMessage( - "AbstractAccessDecisionManager.accessDenied", "Access is denied")); + throw new AccessDeniedException( + messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); } // To get this far, every AccessDecisionVoter abstained checkAllowIfAllAbstainDecisions(); } + } diff --git a/core/src/main/java/org/springframework/security/access/vote/AuthenticatedVoter.java b/core/src/main/java/org/springframework/security/access/vote/AuthenticatedVoter.java index beb357b1eb..36addaffdc 100644 --- a/core/src/main/java/org/springframework/security/access/vote/AuthenticatedVoter.java +++ b/core/src/main/java/org/springframework/security/access/vote/AuthenticatedVoter.java @@ -47,12 +47,16 @@ import org.springframework.util.Assert; * @author Ben Alex */ public class AuthenticatedVoter implements AccessDecisionVoter { + // ~ Static fields/initializers // ===================================================================================== public static final String IS_AUTHENTICATED_FULLY = "IS_AUTHENTICATED_FULLY"; + public static final String IS_AUTHENTICATED_REMEMBERED = "IS_AUTHENTICATED_REMEMBERED"; + public static final String IS_AUTHENTICATED_ANONYMOUSLY = "IS_AUTHENTICATED_ANONYMOUSLY"; + // ~ Instance fields // ================================================================================================ @@ -62,22 +66,19 @@ public class AuthenticatedVoter implements AccessDecisionVoter { // ======================================================================================================== private boolean isFullyAuthenticated(Authentication authentication) { - return (!authenticationTrustResolver.isAnonymous(authentication) && !authenticationTrustResolver - .isRememberMe(authentication)); + return (!authenticationTrustResolver.isAnonymous(authentication) + && !authenticationTrustResolver.isRememberMe(authentication)); } - public void setAuthenticationTrustResolver( - AuthenticationTrustResolver authenticationTrustResolver) { - Assert.notNull(authenticationTrustResolver, - "AuthenticationTrustResolver cannot be set to null"); + public void setAuthenticationTrustResolver(AuthenticationTrustResolver authenticationTrustResolver) { + Assert.notNull(authenticationTrustResolver, "AuthenticationTrustResolver cannot be set to null"); this.authenticationTrustResolver = authenticationTrustResolver; } public boolean supports(ConfigAttribute attribute) { - if ((attribute.getAttribute() != null) - && (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute()) - || IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute()) || IS_AUTHENTICATED_ANONYMOUSLY - .equals(attribute.getAttribute()))) { + if ((attribute.getAttribute() != null) && (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute()) + || IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute()) + || IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute()))) { return true; } else { @@ -88,17 +89,14 @@ public class AuthenticatedVoter implements AccessDecisionVoter { /** * This implementation supports any type of class, because it does not query the * presented secure object. - * * @param clazz the secure object type - * * @return always {@code true} */ public boolean supports(Class clazz) { return true; } - public int vote(Authentication authentication, Object object, - Collection attributes) { + public int vote(Authentication authentication, Object object, Collection attributes) { int result = ACCESS_ABSTAIN; for (ConfigAttribute attribute : attributes) { @@ -119,8 +117,7 @@ public class AuthenticatedVoter implements AccessDecisionVoter { } if (IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute())) { - if (authenticationTrustResolver.isAnonymous(authentication) - || isFullyAuthenticated(authentication) + if (authenticationTrustResolver.isAnonymous(authentication) || isFullyAuthenticated(authentication) || authenticationTrustResolver.isRememberMe(authentication)) { return ACCESS_GRANTED; } @@ -130,4 +127,5 @@ public class AuthenticatedVoter implements AccessDecisionVoter { return result; } + } diff --git a/core/src/main/java/org/springframework/security/access/vote/ConsensusBased.java b/core/src/main/java/org/springframework/security/access/vote/ConsensusBased.java index 2b4be013a3..d113655c7e 100644 --- a/core/src/main/java/org/springframework/security/access/vote/ConsensusBased.java +++ b/core/src/main/java/org/springframework/security/access/vote/ConsensusBased.java @@ -33,6 +33,7 @@ import org.springframework.security.core.Authentication; * {@link UnanimousBased}. */ public class ConsensusBased extends AbstractAccessDecisionManager { + // ~ Instance fields // ================================================================================================ @@ -56,16 +57,14 @@ public class ConsensusBased extends AbstractAccessDecisionManager { * If every AccessDecisionVoter abstained from voting, the decision will * be based on the {@link #isAllowIfAllAbstainDecisions()} property (defaults to * false). - * * @param authentication the caller invoking the method * @param object the secured object * @param configAttributes the configuration attributes associated with the method * being invoked - * * @throws AccessDeniedException if access is denied */ - public void decide(Authentication authentication, Object object, - Collection configAttributes) throws AccessDeniedException { + public void decide(Authentication authentication, Object object, Collection configAttributes) + throws AccessDeniedException { int grant = 0; int deny = 0; @@ -97,8 +96,8 @@ public class ConsensusBased extends AbstractAccessDecisionManager { } if (deny > grant) { - throw new AccessDeniedException(messages.getMessage( - "AbstractAccessDecisionManager.accessDenied", "Access is denied")); + throw new AccessDeniedException( + messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); } if ((grant == deny) && (grant != 0)) { @@ -106,8 +105,8 @@ public class ConsensusBased extends AbstractAccessDecisionManager { return; } else { - throw new AccessDeniedException(messages.getMessage( - "AbstractAccessDecisionManager.accessDenied", "Access is denied")); + throw new AccessDeniedException( + messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); } } @@ -119,8 +118,8 @@ public class ConsensusBased extends AbstractAccessDecisionManager { return allowIfEqualGrantedDeniedDecisions; } - public void setAllowIfEqualGrantedDeniedDecisions( - boolean allowIfEqualGrantedDeniedDecisions) { + public void setAllowIfEqualGrantedDeniedDecisions(boolean allowIfEqualGrantedDeniedDecisions) { this.allowIfEqualGrantedDeniedDecisions = allowIfEqualGrantedDeniedDecisions; } + } diff --git a/core/src/main/java/org/springframework/security/access/vote/RoleHierarchyVoter.java b/core/src/main/java/org/springframework/security/access/vote/RoleHierarchyVoter.java index 32e1598e4d..88da1dc1bd 100644 --- a/core/src/main/java/org/springframework/security/access/vote/RoleHierarchyVoter.java +++ b/core/src/main/java/org/springframework/security/access/vote/RoleHierarchyVoter.java @@ -30,6 +30,7 @@ import org.springframework.util.Assert; * @since 2.0.4 */ public class RoleHierarchyVoter extends RoleVoter { + private RoleHierarchy roleHierarchy = null; public RoleHierarchyVoter(RoleHierarchy roleHierarchy) { @@ -41,9 +42,8 @@ public class RoleHierarchyVoter extends RoleVoter { * Calls the RoleHierarchy to obtain the complete set of user authorities. */ @Override - Collection extractAuthorities( - Authentication authentication) { - return roleHierarchy.getReachableGrantedAuthorities(authentication - .getAuthorities()); + Collection extractAuthorities(Authentication authentication) { + return roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities()); } + } diff --git a/core/src/main/java/org/springframework/security/access/vote/RoleVoter.java b/core/src/main/java/org/springframework/security/access/vote/RoleVoter.java index e4d1bd6319..e61ba03b3c 100644 --- a/core/src/main/java/org/springframework/security/access/vote/RoleVoter.java +++ b/core/src/main/java/org/springframework/security/access/vote/RoleVoter.java @@ -50,6 +50,7 @@ import org.springframework.security.core.GrantedAuthority; * @author colin sampaleanu */ public class RoleVoter implements AccessDecisionVoter { + // ~ Instance fields // ================================================================================================ @@ -65,7 +66,6 @@ public class RoleVoter implements AccessDecisionVoter { /** * Allows the default role prefix of ROLE_ to be overridden. May be set * to an empty value, although this is usually not desirable. - * * @param rolePrefix the new prefix */ public void setRolePrefix(String rolePrefix) { @@ -73,8 +73,7 @@ public class RoleVoter implements AccessDecisionVoter { } public boolean supports(ConfigAttribute attribute) { - if ((attribute.getAttribute() != null) - && attribute.getAttribute().startsWith(getRolePrefix())) { + if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith(getRolePrefix())) { return true; } else { @@ -85,17 +84,14 @@ public class RoleVoter implements AccessDecisionVoter { /** * This implementation supports any type of class, because it does not query the * presented secure object. - * * @param clazz the secure object - * * @return always true */ public boolean supports(Class clazz) { return true; } - public int vote(Authentication authentication, Object object, - Collection attributes) { + public int vote(Authentication authentication, Object object, Collection attributes) { if (authentication == null) { return ACCESS_DENIED; } @@ -118,8 +114,8 @@ public class RoleVoter implements AccessDecisionVoter { return result; } - Collection extractAuthorities( - Authentication authentication) { + Collection extractAuthorities(Authentication authentication) { return authentication.getAuthorities(); } + } diff --git a/core/src/main/java/org/springframework/security/access/vote/UnanimousBased.java b/core/src/main/java/org/springframework/security/access/vote/UnanimousBased.java index af7f8eae9d..7408cf5eab 100644 --- a/core/src/main/java/org/springframework/security/access/vote/UnanimousBased.java +++ b/core/src/main/java/org/springframework/security/access/vote/UnanimousBased.java @@ -52,16 +52,14 @@ public class UnanimousBased extends AbstractAccessDecisionManager { * If every AccessDecisionVoter abstained from voting, the decision will * be based on the {@link #isAllowIfAllAbstainDecisions()} property (defaults to * false). - * * @param authentication the caller invoking the method * @param object the secured object * @param attributes the configuration attributes associated with the method being * invoked - * * @throws AccessDeniedException if access is denied */ - public void decide(Authentication authentication, Object object, - Collection attributes) throws AccessDeniedException { + public void decide(Authentication authentication, Object object, Collection attributes) + throws AccessDeniedException { int grant = 0; @@ -85,9 +83,8 @@ public class UnanimousBased extends AbstractAccessDecisionManager { break; case AccessDecisionVoter.ACCESS_DENIED: - throw new AccessDeniedException(messages.getMessage( - "AbstractAccessDecisionManager.accessDenied", - "Access is denied")); + throw new AccessDeniedException( + messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied")); default: break; @@ -103,4 +100,5 @@ public class UnanimousBased extends AbstractAccessDecisionManager { // To get this far, every AccessDecisionVoter abstained checkAllowIfAllAbstainDecisions(); } + } diff --git a/core/src/main/java/org/springframework/security/access/vote/package-info.java b/core/src/main/java/org/springframework/security/access/vote/package-info.java index 6c8cf27fea..926d46fdc6 100644 --- a/core/src/main/java/org/springframework/security/access/vote/package-info.java +++ b/core/src/main/java/org/springframework/security/access/vote/package-info.java @@ -17,4 +17,3 @@ * Implements a vote-based approach to authorization decisions. */ package org.springframework.security.access.vote; - diff --git a/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java index c3b017b7c9..9032826953 100644 --- a/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java @@ -36,13 +36,15 @@ import org.springframework.security.core.userdetails.UserDetails; * @author Ben Alex * @author Luke Taylor */ -public abstract class AbstractAuthenticationToken implements Authentication, - CredentialsContainer { +public abstract class AbstractAuthenticationToken implements Authentication, CredentialsContainer { + // ~ Instance fields // ================================================================================================ private final Collection authorities; + private Object details; + private boolean authenticated = false; // ~ Constructors @@ -50,9 +52,8 @@ public abstract class AbstractAuthenticationToken implements Authentication, /** * Creates a token with the supplied array of authorities. - * * @param authorities the collection of GrantedAuthoritys for the principal - * represented by this authentication object. + * represented by this authentication object. */ public AbstractAuthenticationToken(Collection authorities) { if (authorities == null) { @@ -62,12 +63,10 @@ public abstract class AbstractAuthenticationToken implements Authentication, for (GrantedAuthority a : authorities) { if (a == null) { - throw new IllegalArgumentException( - "Authorities collection cannot contain any null elements"); + throw new IllegalArgumentException("Authorities collection cannot contain any null elements"); } } - ArrayList temp = new ArrayList<>( - authorities.size()); + ArrayList temp = new ArrayList<>(authorities.size()); temp.addAll(authorities); this.authorities = Collections.unmodifiableList(temp); } @@ -154,8 +153,7 @@ public abstract class AbstractAuthenticationToken implements Authentication, return false; } - if ((this.getCredentials() != null) - && !this.getCredentials().equals(test.getCredentials())) { + if ((this.getCredentials() != null) && !this.getCredentials().equals(test.getCredentials())) { return false; } @@ -163,8 +161,7 @@ public abstract class AbstractAuthenticationToken implements Authentication, return false; } - if (this.getPrincipal() != null - && !this.getPrincipal().equals(test.getPrincipal())) { + if (this.getPrincipal() != null && !this.getPrincipal().equals(test.getPrincipal())) { return false; } @@ -218,10 +215,12 @@ public abstract class AbstractAuthenticationToken implements Authentication, sb.append(authority); } - } else { + } + else { sb.append("Not granted any authorities"); } return sb.toString(); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/AbstractUserDetailsReactiveAuthenticationManager.java b/core/src/main/java/org/springframework/security/authentication/AbstractUserDetailsReactiveAuthenticationManager.java index cbc6e3b71b..7351278502 100644 --- a/core/src/main/java/org/springframework/security/authentication/AbstractUserDetailsReactiveAuthenticationManager.java +++ b/core/src/main/java/org/springframework/security/authentication/AbstractUserDetailsReactiveAuthenticationManager.java @@ -33,8 +33,8 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.util.Assert; /** - * A base {@link ReactiveAuthenticationManager} that allows subclasses to override and work with - * {@link UserDetails} objects. + * A base {@link ReactiveAuthenticationManager} that allows subclasses to override and + * work with {@link UserDetails} objects. * *

      * Upon successful validation, a UsernamePasswordAuthenticationToken will be @@ -61,25 +61,22 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager implement if (!user.isAccountNonLocked()) { logger.debug("User account is locked"); - throw new LockedException(this.messages.getMessage( - "AbstractUserDetailsAuthenticationProvider.locked", + throw new LockedException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked", "User account is locked")); } if (!user.isEnabled()) { logger.debug("User account is disabled"); - throw new DisabledException(this.messages.getMessage( - "AbstractUserDetailsAuthenticationProvider.disabled", - "User is disabled")); + throw new DisabledException( + this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled", "User is disabled")); } if (!user.isAccountNonExpired()) { logger.debug("User account is expired"); - throw new AccountExpiredException(this.messages.getMessage( - "AbstractUserDetailsAuthenticationProvider.expired", - "User account has expired")); + throw new AccountExpiredException(this.messages + .getMessage("AbstractUserDetailsAuthenticationProvider.expired", "User account has expired")); } }; @@ -88,8 +85,7 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager implement logger.debug("User account credentials have expired"); throw new CredentialsExpiredException(this.messages.getMessage( - "AbstractUserDetailsAuthenticationProvider.credentialsExpired", - "User credentials have expired")); + "AbstractUserDetailsAuthenticationProvider.credentialsExpired", "User credentials have expired")); } }; @@ -97,9 +93,7 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager implement public Mono authenticate(Authentication authentication) { final String username = authentication.getName(); final String presentedPassword = (String) authentication.getCredentials(); - return retrieveUser(username) - .doOnNext(this.preAuthenticationChecks::check) - .publishOn(this.scheduler) + return retrieveUser(username).doOnNext(this.preAuthenticationChecks::check).publishOn(this.scheduler) .filter(u -> this.passwordEncoder.matches(presentedPassword, u.getPassword())) .switchIfEmpty(Mono.defer(() -> Mono.error(new BadCredentialsException("Invalid Credentials")))) .flatMap(u -> { @@ -110,14 +104,13 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager implement return this.userDetailsPasswordService.updatePassword(u, newPassword); } return Mono.just(u); - }) - .doOnNext(this.postAuthenticationChecks::check) - .map(u -> new UsernamePasswordAuthenticationToken(u, u.getPassword(), u.getAuthorities()) ); + }).doOnNext(this.postAuthenticationChecks::check) + .map(u -> new UsernamePasswordAuthenticationToken(u, u.getPassword(), u.getAuthorities())); } /** - * The {@link PasswordEncoder} that is used for validating the password. The default is - * {@link PasswordEncoderFactories#createDelegatingPasswordEncoder()} + * The {@link PasswordEncoder} that is used for validating the password. The default + * is {@link PasswordEncoderFactories#createDelegatingPasswordEncoder()} * @param passwordEncoder the {@link PasswordEncoder} to use. Cannot be null */ public void setPasswordEncoder(PasswordEncoder passwordEncoder) { @@ -126,13 +119,14 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager implement } /** - * Sets the {@link Scheduler} used by the {@link UserDetailsRepositoryReactiveAuthenticationManager}. - * The default is {@code Schedulers.newParallel(String)} because modern password encoding is - * a CPU intensive task that is non blocking. This means validation is bounded by the - * number of CPUs. Some applications may want to customize the {@link Scheduler}. For - * example, if users are stuck using the insecure {@link org.springframework.security.crypto.password.NoOpPasswordEncoder} - * they might want to leverage {@code Schedulers.immediate()}. - * + * Sets the {@link Scheduler} used by the + * {@link UserDetailsRepositoryReactiveAuthenticationManager}. The default is + * {@code Schedulers.newParallel(String)} because modern password encoding is a CPU + * intensive task that is non blocking. This means validation is bounded by the number + * of CPUs. Some applications may want to customize the {@link Scheduler}. For + * example, if users are stuck using the insecure + * {@link org.springframework.security.crypto.password.NoOpPasswordEncoder} they might + * want to leverage {@code Schedulers.immediate()}. * @param scheduler the {@link Scheduler} to use. Cannot be null. * @since 5.0.6 */ @@ -145,15 +139,13 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager implement * Sets the service to use for upgrading passwords on successful authentication. * @param userDetailsPasswordService the service to use */ - public void setUserDetailsPasswordService( - ReactiveUserDetailsPasswordService userDetailsPasswordService) { + public void setUserDetailsPasswordService(ReactiveUserDetailsPasswordService userDetailsPasswordService) { this.userDetailsPasswordService = userDetailsPasswordService; } /** * Sets the strategy which will be used to validate the loaded UserDetails * object after authentication occurs. - * * @param postAuthenticationChecks The {@link UserDetailsChecker} * @since 5.2 */ @@ -163,9 +155,8 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager implement } /** - * Allows subclasses to retrieve the UserDetails - * from an implementation-specific location. - * + * Allows subclasses to retrieve the UserDetails from an + * implementation-specific location. * @param username The username to retrieve * @return the user information. If authentication fails, a Mono error is returned. */ diff --git a/core/src/main/java/org/springframework/security/authentication/AccountExpiredException.java b/core/src/main/java/org/springframework/security/authentication/AccountExpiredException.java index 2636cf0931..a147bed9a4 100644 --- a/core/src/main/java/org/springframework/security/authentication/AccountExpiredException.java +++ b/core/src/main/java/org/springframework/security/authentication/AccountExpiredException.java @@ -23,12 +23,12 @@ package org.springframework.security.authentication; * @author Ben Alex */ public class AccountExpiredException extends AccountStatusException { + // ~ Constructors // =================================================================================================== /** * Constructs a AccountExpiredException with the specified message. - * * @param msg the detail message */ public AccountExpiredException(String msg) { @@ -38,11 +38,11 @@ public class AccountExpiredException extends AccountStatusException { /** * Constructs a AccountExpiredException with the specified message and * root cause. - * * @param msg the detail message * @param t root cause */ public AccountExpiredException(String msg, Throwable t) { super(msg, t); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/AccountStatusException.java b/core/src/main/java/org/springframework/security/authentication/AccountStatusException.java index bed91273a9..56e6daa30b 100644 --- a/core/src/main/java/org/springframework/security/authentication/AccountStatusException.java +++ b/core/src/main/java/org/springframework/security/authentication/AccountStatusException.java @@ -24,6 +24,7 @@ import org.springframework.security.core.AuthenticationException; * @author Luke Taylor */ public abstract class AccountStatusException extends AuthenticationException { + public AccountStatusException(String msg) { super(msg); } @@ -31,4 +32,5 @@ public abstract class AccountStatusException extends AuthenticationException { public AccountStatusException(String msg, Throwable t) { super(msg, t); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/AccountStatusUserDetailsChecker.java b/core/src/main/java/org/springframework/security/authentication/AccountStatusUserDetailsChecker.java index 89512454bb..0157393a87 100644 --- a/core/src/main/java/org/springframework/security/authentication/AccountStatusUserDetailsChecker.java +++ b/core/src/main/java/org/springframework/security/authentication/AccountStatusUserDetailsChecker.java @@ -28,30 +28,27 @@ import org.springframework.util.Assert; */ public class AccountStatusUserDetailsChecker implements UserDetailsChecker, MessageSourceAware { - protected MessageSourceAccessor messages = SpringSecurityMessageSource - .getAccessor(); + protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); public void check(UserDetails user) { if (!user.isAccountNonLocked()) { - throw new LockedException(messages.getMessage( - "AccountStatusUserDetailsChecker.locked", "User account is locked")); + throw new LockedException( + messages.getMessage("AccountStatusUserDetailsChecker.locked", "User account is locked")); } if (!user.isEnabled()) { - throw new DisabledException(messages.getMessage( - "AccountStatusUserDetailsChecker.disabled", "User is disabled")); + throw new DisabledException( + messages.getMessage("AccountStatusUserDetailsChecker.disabled", "User is disabled")); } if (!user.isAccountNonExpired()) { throw new AccountExpiredException( - messages.getMessage("AccountStatusUserDetailsChecker.expired", - "User account has expired")); + messages.getMessage("AccountStatusUserDetailsChecker.expired", "User account has expired")); } if (!user.isCredentialsNonExpired()) { - throw new CredentialsExpiredException(messages.getMessage( - "AccountStatusUserDetailsChecker.credentialsExpired", - "User credentials have expired")); + throw new CredentialsExpiredException(messages + .getMessage("AccountStatusUserDetailsChecker.credentialsExpired", "User credentials have expired")); } } @@ -63,4 +60,5 @@ public class AccountStatusUserDetailsChecker implements UserDetailsChecker, Mess Assert.notNull(messageSource, "messageSource cannot be null"); this.messages = new MessageSourceAccessor(messageSource); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationProvider.java b/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationProvider.java index ba0dfeff2a..a74b615f53 100644 --- a/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationProvider.java +++ b/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationProvider.java @@ -33,13 +33,13 @@ import org.springframework.util.Assert; * * @author Ben Alex */ -public class AnonymousAuthenticationProvider implements AuthenticationProvider, - MessageSourceAware { +public class AnonymousAuthenticationProvider implements AuthenticationProvider, MessageSourceAware { // ~ Instance fields // ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); + private String key; public AnonymousAuthenticationProvider(String key) { @@ -50,17 +50,14 @@ public class AnonymousAuthenticationProvider implements AuthenticationProvider, // ~ Methods // ======================================================================================================== - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } - if (this.key.hashCode() != ((AnonymousAuthenticationToken) authentication) - .getKeyHash()) { - throw new BadCredentialsException( - messages.getMessage("AnonymousAuthenticationProvider.incorrectKey", - "The presented AnonymousAuthenticationToken does not contain the expected key")); + if (this.key.hashCode() != ((AnonymousAuthenticationToken) authentication).getKeyHash()) { + throw new BadCredentialsException(messages.getMessage("AnonymousAuthenticationProvider.incorrectKey", + "The presented AnonymousAuthenticationToken does not contain the expected key")); } return authentication; @@ -78,4 +75,5 @@ public class AnonymousAuthenticationProvider implements AuthenticationProvider, public boolean supports(Class authentication) { return (AnonymousAuthenticationToken.class.isAssignableFrom(authentication)); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java index 5ec688d361..6de6ed2cae 100644 --- a/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationToken.java @@ -27,13 +27,15 @@ import org.springframework.util.Assert; * * @author Ben Alex */ -public class AnonymousAuthenticationToken extends AbstractAuthenticationToken implements - Serializable { +public class AnonymousAuthenticationToken extends AbstractAuthenticationToken implements Serializable { + // ~ Instance fields // ================================================================================================ private static final long serialVersionUID = 1L; + private final Object principal; + private final int keyHash; // ~ Constructors @@ -41,27 +43,25 @@ public class AnonymousAuthenticationToken extends AbstractAuthenticationToken im /** * Constructor. - * - * @param key to identify if this object made by an authorised client - * @param principal the principal (typically a UserDetails) + * @param key to identify if this object made by an authorised client + * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal * @throws IllegalArgumentException if a null was passed */ public AnonymousAuthenticationToken(String key, Object principal, - Collection authorities) { + Collection authorities) { this(extractKeyHash(key), principal, authorities); } /** * Constructor helps in Jackson Deserialization - * - * @param keyHash hashCode of provided Key, constructed by above constructor - * @param principal the principal (typically a UserDetails) + * @param keyHash hashCode of provided Key, constructed by above constructor + * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal * @since 4.2 */ private AnonymousAuthenticationToken(Integer keyHash, Object principal, - Collection authorities) { + Collection authorities) { super(authorities); if (principal == null || "".equals(principal)) { @@ -110,7 +110,6 @@ public class AnonymousAuthenticationToken extends AbstractAuthenticationToken im /** * Always returns an empty String - * * @return an empty String */ @Override @@ -126,4 +125,5 @@ public class AnonymousAuthenticationToken extends AbstractAuthenticationToken im public Object getPrincipal() { return this.principal; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/AuthenticationCredentialsNotFoundException.java b/core/src/main/java/org/springframework/security/authentication/AuthenticationCredentialsNotFoundException.java index 8d096c450a..4341f13393 100644 --- a/core/src/main/java/org/springframework/security/authentication/AuthenticationCredentialsNotFoundException.java +++ b/core/src/main/java/org/springframework/security/authentication/AuthenticationCredentialsNotFoundException.java @@ -27,13 +27,13 @@ import org.springframework.security.core.AuthenticationException; * @author Ben Alex */ public class AuthenticationCredentialsNotFoundException extends AuthenticationException { + // ~ Constructors // =================================================================================================== /** * Constructs an AuthenticationCredentialsNotFoundException with the * specified message. - * * @param msg the detail message */ public AuthenticationCredentialsNotFoundException(String msg) { @@ -43,11 +43,11 @@ public class AuthenticationCredentialsNotFoundException extends AuthenticationEx /** * Constructs an AuthenticationCredentialsNotFoundException with the * specified message and root cause. - * * @param msg the detail message * @param t root cause */ public AuthenticationCredentialsNotFoundException(String msg, Throwable t) { super(msg, t); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/AuthenticationDetailsSource.java b/core/src/main/java/org/springframework/security/authentication/AuthenticationDetailsSource.java index 27f8550a88..8c6af9199b 100644 --- a/core/src/main/java/org/springframework/security/authentication/AuthenticationDetailsSource.java +++ b/core/src/main/java/org/springframework/security/authentication/AuthenticationDetailsSource.java @@ -23,17 +23,17 @@ package org.springframework.security.authentication; * @author Ben Alex */ public interface AuthenticationDetailsSource { + // ~ Methods // ======================================================================================================== /** * Called by a class when it wishes a new authentication details instance to be * created. - * * @param context the request object, which may be used by the authentication details * object - * * @return a fully-configured authentication details instance */ T buildDetails(C context); + } diff --git a/core/src/main/java/org/springframework/security/authentication/AuthenticationEventPublisher.java b/core/src/main/java/org/springframework/security/authentication/AuthenticationEventPublisher.java index b467ebcfe2..686cfb7a62 100644 --- a/core/src/main/java/org/springframework/security/authentication/AuthenticationEventPublisher.java +++ b/core/src/main/java/org/springframework/security/authentication/AuthenticationEventPublisher.java @@ -19,7 +19,6 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; /** - * * @author Luke Taylor * @since 3.0 */ @@ -27,6 +26,6 @@ public interface AuthenticationEventPublisher { void publishAuthenticationSuccess(Authentication authentication); - void publishAuthenticationFailure(AuthenticationException exception, - Authentication authentication); + void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication); + } diff --git a/core/src/main/java/org/springframework/security/authentication/AuthenticationManager.java b/core/src/main/java/org/springframework/security/authentication/AuthenticationManager.java index 6288a6f179..6a8d48ecff 100644 --- a/core/src/main/java/org/springframework/security/authentication/AuthenticationManager.java +++ b/core/src/main/java/org/springframework/security/authentication/AuthenticationManager.java @@ -25,6 +25,7 @@ import org.springframework.security.core.AuthenticationException; * @author Ben Alex */ public interface AuthenticationManager { + // ~ Methods // ======================================================================================================== @@ -48,13 +49,10 @@ public interface AuthenticationManager { * above (i.e. if an account is disabled or locked, the authentication request is * immediately rejected and the credentials testing process is not performed). This * prevents credentials being tested against disabled or locked accounts. - * * @param authentication the authentication request object - * * @return a fully authenticated object including credentials - * * @throws AuthenticationException if authentication fails */ - Authentication authenticate(Authentication authentication) - throws AuthenticationException; + Authentication authenticate(Authentication authentication) throws AuthenticationException; + } diff --git a/core/src/main/java/org/springframework/security/authentication/AuthenticationManagerResolver.java b/core/src/main/java/org/springframework/security/authentication/AuthenticationManagerResolver.java index ad1ea989c8..8a0b8dc979 100644 --- a/core/src/main/java/org/springframework/security/authentication/AuthenticationManagerResolver.java +++ b/core/src/main/java/org/springframework/security/authentication/AuthenticationManagerResolver.java @@ -17,7 +17,8 @@ package org.springframework.security.authentication; /** - * An interface for resolving an {@link AuthenticationManager} based on the provided context + * An interface for resolving an {@link AuthenticationManager} based on the provided + * context * * @author Josh Cummings * @since 5.2 @@ -30,4 +31,5 @@ public interface AuthenticationManagerResolver { * @return the {@link AuthenticationManager} to use */ AuthenticationManager resolve(C context); + } diff --git a/core/src/main/java/org/springframework/security/authentication/AuthenticationProvider.java b/core/src/main/java/org/springframework/security/authentication/AuthenticationProvider.java index 2c4e2763e1..9167027a06 100644 --- a/core/src/main/java/org/springframework/security/authentication/AuthenticationProvider.java +++ b/core/src/main/java/org/springframework/security/authentication/AuthenticationProvider.java @@ -26,6 +26,7 @@ import org.springframework.security.core.AuthenticationException; * @author Ben Alex */ public interface AuthenticationProvider { + // ~ Methods // ======================================================================================================== @@ -33,19 +34,15 @@ public interface AuthenticationProvider { * Performs authentication with the same contract as * {@link org.springframework.security.authentication.AuthenticationManager#authenticate(Authentication)} * . - * * @param authentication the authentication request object. - * * @return a fully authenticated object including credentials. May return * null if the AuthenticationProvider is unable to support * authentication of the passed Authentication object. In such a case, * the next AuthenticationProvider that supports the presented * Authentication class will be tried. - * * @throws AuthenticationException if authentication fails. */ - Authentication authenticate(Authentication authentication) - throws AuthenticationException; + Authentication authenticate(Authentication authentication) throws AuthenticationException; /** * Returns true if this AuthenticationProvider supports the @@ -62,11 +59,10 @@ public interface AuthenticationProvider { * Selection of an AuthenticationProvider capable of performing * authentication is conducted at runtime the ProviderManager. *

      - * * @param authentication - * * @return true if the implementation can more closely evaluate the * Authentication class presented */ boolean supports(Class authentication); + } diff --git a/core/src/main/java/org/springframework/security/authentication/AuthenticationServiceException.java b/core/src/main/java/org/springframework/security/authentication/AuthenticationServiceException.java index f6aef41cc3..bc1736b489 100644 --- a/core/src/main/java/org/springframework/security/authentication/AuthenticationServiceException.java +++ b/core/src/main/java/org/springframework/security/authentication/AuthenticationServiceException.java @@ -28,13 +28,13 @@ import org.springframework.security.core.AuthenticationException; * @see InternalAuthenticationServiceException */ public class AuthenticationServiceException extends AuthenticationException { + // ~ Constructors // =================================================================================================== /** * Constructs an AuthenticationServiceException with the specified * message. - * * @param msg the detail message */ public AuthenticationServiceException(String msg) { @@ -44,11 +44,11 @@ public class AuthenticationServiceException extends AuthenticationException { /** * Constructs an AuthenticationServiceException with the specified * message and root cause. - * * @param msg the detail message * @param t root cause */ public AuthenticationServiceException(String msg, Throwable t) { super(msg, t); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/AuthenticationTrustResolver.java b/core/src/main/java/org/springframework/security/authentication/AuthenticationTrustResolver.java index 4192b13765..c218dcfca6 100644 --- a/core/src/main/java/org/springframework/security/authentication/AuthenticationTrustResolver.java +++ b/core/src/main/java/org/springframework/security/authentication/AuthenticationTrustResolver.java @@ -24,6 +24,7 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ public interface AuthenticationTrustResolver { + // ~ Methods // ======================================================================================================== @@ -34,10 +35,8 @@ public interface AuthenticationTrustResolver { * rejection (i.e. as would be the case if the principal was non-anonymous/fully * authenticated) or direct the principal to attempt actual authentication (i.e. as * would be the case if the Authentication was merely anonymous). - * * @param authentication to test (may be null in which case the method * will always return false) - * * @return true the passed authentication token represented an anonymous * principal, false otherwise */ @@ -50,12 +49,11 @@ public interface AuthenticationTrustResolver { * The method is provided to assist with custom AccessDecisionVoters and * the like that you might develop. Of course, you don't need to use this method * either and can develop your own "trust level" hierarchy instead. - * * @param authentication to test (may be null in which case the method * will always return false) - * * @return true the passed authentication token represented a principal * authenticated using a remember-me token, false otherwise */ boolean isRememberMe(Authentication authentication); + } diff --git a/core/src/main/java/org/springframework/security/authentication/AuthenticationTrustResolverImpl.java b/core/src/main/java/org/springframework/security/authentication/AuthenticationTrustResolverImpl.java index 53a9aef58b..b9292965fc 100644 --- a/core/src/main/java/org/springframework/security/authentication/AuthenticationTrustResolverImpl.java +++ b/core/src/main/java/org/springframework/security/authentication/AuthenticationTrustResolverImpl.java @@ -30,10 +30,12 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ public class AuthenticationTrustResolverImpl implements AuthenticationTrustResolver { + // ~ Instance fields // ================================================================================================ private Class anonymousClass = AnonymousAuthenticationToken.class; + private Class rememberMeClass = RememberMeAuthenticationToken.class; // ~ Methods @@ -70,4 +72,5 @@ public class AuthenticationTrustResolverImpl implements AuthenticationTrustResol public void setRememberMeClass(Class rememberMeClass) { this.rememberMeClass = rememberMeClass; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/BadCredentialsException.java b/core/src/main/java/org/springframework/security/authentication/BadCredentialsException.java index 7b050d9078..15f9bce92e 100644 --- a/core/src/main/java/org/springframework/security/authentication/BadCredentialsException.java +++ b/core/src/main/java/org/springframework/security/authentication/BadCredentialsException.java @@ -25,12 +25,12 @@ import org.springframework.security.core.AuthenticationException; * @author Ben Alex */ public class BadCredentialsException extends AuthenticationException { + // ~ Constructors // =================================================================================================== /** * Constructs a BadCredentialsException with the specified message. - * * @param msg the detail message */ public BadCredentialsException(String msg) { @@ -40,11 +40,11 @@ public class BadCredentialsException extends AuthenticationException { /** * Constructs a BadCredentialsException with the specified message and * root cause. - * * @param msg the detail message * @param t root cause */ public BadCredentialsException(String msg, Throwable t) { super(msg, t); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/CachingUserDetailsService.java b/core/src/main/java/org/springframework/security/authentication/CachingUserDetailsService.java index ed5dc9241c..aaefaa570f 100644 --- a/core/src/main/java/org/springframework/security/authentication/CachingUserDetailsService.java +++ b/core/src/main/java/org/springframework/security/authentication/CachingUserDetailsService.java @@ -22,12 +22,13 @@ import org.springframework.security.core.userdetails.cache.NullUserCache; import org.springframework.util.Assert; /** - * * @author Luke Taylor * @since 2.0 */ public class CachingUserDetailsService implements UserDetailsService { + private UserCache userCache = new NullUserCache(); + private final UserDetailsService delegate; public CachingUserDetailsService(UserDetailsService delegate) { @@ -49,12 +50,12 @@ public class CachingUserDetailsService implements UserDetailsService { user = delegate.loadUserByUsername(username); } - Assert.notNull(user, () -> "UserDetailsService " + delegate - + " returned null for username " + username + ". " + Assert.notNull(user, () -> "UserDetailsService " + delegate + " returned null for username " + username + ". " + "This is an interface contract violation"); userCache.putUserInCache(user); return user; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/CredentialsExpiredException.java b/core/src/main/java/org/springframework/security/authentication/CredentialsExpiredException.java index 494ca04348..eaa1fa1226 100644 --- a/core/src/main/java/org/springframework/security/authentication/CredentialsExpiredException.java +++ b/core/src/main/java/org/springframework/security/authentication/CredentialsExpiredException.java @@ -23,12 +23,12 @@ package org.springframework.security.authentication; * @author Ben Alex */ public class CredentialsExpiredException extends AccountStatusException { + // ~ Constructors // =================================================================================================== /** * Constructs a CredentialsExpiredException with the specified message. - * * @param msg the detail message */ public CredentialsExpiredException(String msg) { @@ -38,11 +38,11 @@ public class CredentialsExpiredException extends AccountStatusException { /** * Constructs a CredentialsExpiredException with the specified message * and root cause. - * * @param msg the detail message * @param t root cause */ public CredentialsExpiredException(String msg, Throwable t) { super(msg, t); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java b/core/src/main/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java index 965a6ee2a9..5749fde2eb 100644 --- a/core/src/main/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java +++ b/core/src/main/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java @@ -58,55 +58,45 @@ import org.springframework.util.Assert; * @author Luke Taylor * @since 3.0 */ -public class DefaultAuthenticationEventPublisher implements AuthenticationEventPublisher, - ApplicationEventPublisherAware { +public class DefaultAuthenticationEventPublisher + implements AuthenticationEventPublisher, ApplicationEventPublisherAware { + private final Log logger = LogFactory.getLog(getClass()); private ApplicationEventPublisher applicationEventPublisher; + private final HashMap> exceptionMappings = new HashMap<>(); + private Constructor defaultAuthenticationFailureEventConstructor; public DefaultAuthenticationEventPublisher() { this(null); } - public DefaultAuthenticationEventPublisher( - ApplicationEventPublisher applicationEventPublisher) { + public DefaultAuthenticationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; - addMapping(BadCredentialsException.class.getName(), - AuthenticationFailureBadCredentialsEvent.class); - addMapping(UsernameNotFoundException.class.getName(), - AuthenticationFailureBadCredentialsEvent.class); - addMapping(AccountExpiredException.class.getName(), - AuthenticationFailureExpiredEvent.class); - addMapping(ProviderNotFoundException.class.getName(), - AuthenticationFailureProviderNotFoundEvent.class); - addMapping(DisabledException.class.getName(), - AuthenticationFailureDisabledEvent.class); - addMapping(LockedException.class.getName(), - AuthenticationFailureLockedEvent.class); - addMapping(AuthenticationServiceException.class.getName(), - AuthenticationFailureServiceExceptionEvent.class); - addMapping(CredentialsExpiredException.class.getName(), - AuthenticationFailureCredentialsExpiredEvent.class); - addMapping( - "org.springframework.security.authentication.cas.ProxyUntrustedException", + addMapping(BadCredentialsException.class.getName(), AuthenticationFailureBadCredentialsEvent.class); + addMapping(UsernameNotFoundException.class.getName(), AuthenticationFailureBadCredentialsEvent.class); + addMapping(AccountExpiredException.class.getName(), AuthenticationFailureExpiredEvent.class); + addMapping(ProviderNotFoundException.class.getName(), AuthenticationFailureProviderNotFoundEvent.class); + addMapping(DisabledException.class.getName(), AuthenticationFailureDisabledEvent.class); + addMapping(LockedException.class.getName(), AuthenticationFailureLockedEvent.class); + addMapping(AuthenticationServiceException.class.getName(), AuthenticationFailureServiceExceptionEvent.class); + addMapping(CredentialsExpiredException.class.getName(), AuthenticationFailureCredentialsExpiredEvent.class); + addMapping("org.springframework.security.authentication.cas.ProxyUntrustedException", AuthenticationFailureProxyUntrustedEvent.class); - addMapping( - "org.springframework.security.oauth2.server.resource.InvalidBearerTokenException", + addMapping("org.springframework.security.oauth2.server.resource.InvalidBearerTokenException", AuthenticationFailureBadCredentialsEvent.class); } public void publishAuthenticationSuccess(Authentication authentication) { if (applicationEventPublisher != null) { - applicationEventPublisher.publishEvent(new AuthenticationSuccessEvent( - authentication)); + applicationEventPublisher.publishEvent(new AuthenticationSuccessEvent(authentication)); } } - public void publishAuthenticationFailure(AuthenticationException exception, - Authentication authentication) { + public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) { Constructor constructor = getEventConstructor(exception); AbstractAuthenticationEvent event = null; @@ -125,49 +115,42 @@ public class DefaultAuthenticationEventPublisher implements AuthenticationEventP } else { if (logger.isDebugEnabled()) { - logger.debug("No event was found for the exception " - + exception.getClass().getName()); + logger.debug("No event was found for the exception " + exception.getClass().getName()); } } } private Constructor getEventConstructor(AuthenticationException exception) { - Constructor eventConstructor = - this.exceptionMappings.get(exception.getClass().getName()); + Constructor eventConstructor = this.exceptionMappings + .get(exception.getClass().getName()); return (eventConstructor == null ? this.defaultAuthenticationFailureEventConstructor : eventConstructor); } - public void setApplicationEventPublisher( - ApplicationEventPublisher applicationEventPublisher) { + public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } /** * Sets additional exception to event mappings. These are automatically merged with * the default exception to event mappings that ProviderManager defines. - * * @param additionalExceptionMappings where keys are the fully-qualified string name * of the exception class and the values are the fully-qualified string name of the * event class to fire. - * * @deprecated use {@link #setAdditionalExceptionMappings(Map)} */ @Deprecated @SuppressWarnings({ "unchecked" }) public void setAdditionalExceptionMappings(Properties additionalExceptionMappings) { - Assert.notNull(additionalExceptionMappings, - "The exceptionMappings object must not be null"); + Assert.notNull(additionalExceptionMappings, "The exceptionMappings object must not be null"); for (Object exceptionClass : additionalExceptionMappings.keySet()) { String eventClass = (String) additionalExceptionMappings.get(exceptionClass); try { Class clazz = getClass().getClassLoader().loadClass(eventClass); Assert.isAssignable(AbstractAuthenticationFailureEvent.class, clazz); - addMapping((String) exceptionClass, - (Class) clazz); + addMapping((String) exceptionClass, (Class) clazz); } catch (ClassNotFoundException e) { - throw new RuntimeException("Failed to load authentication event class " - + eventClass); + throw new RuntimeException("Failed to load authentication event class " + eventClass); } } } @@ -175,29 +158,27 @@ public class DefaultAuthenticationEventPublisher implements AuthenticationEventP /** * Sets additional exception to event mappings. These are automatically merged with * the default exception to event mappings that ProviderManager defines. - * * @param mappings where keys are exception classes and values are event classes. * @since 5.3 */ - public void setAdditionalExceptionMappings(Map, - Class> mappings){ + public void setAdditionalExceptionMappings( + Map, Class> mappings) { Assert.notEmpty(mappings, "The mappings Map must not be empty nor null"); - for (Map.Entry, Class> entry - : mappings.entrySet()) { - Class exceptionClass = entry.getKey(); - Class eventClass = entry.getValue(); - Assert.notNull(exceptionClass, "exceptionClass cannot be null"); - Assert.notNull(eventClass, "eventClass cannot be null"); - addMapping(exceptionClass.getName(), (Class) eventClass); + for (Map.Entry, Class> entry : mappings + .entrySet()) { + Class exceptionClass = entry.getKey(); + Class eventClass = entry.getValue(); + Assert.notNull(exceptionClass, "exceptionClass cannot be null"); + Assert.notNull(eventClass, "eventClass cannot be null"); + addMapping(exceptionClass.getName(), (Class) eventClass); } } /** * Sets a default authentication failure event as a fallback event for any unmapped * exceptions not mapped in the exception mappings. - * - * @param defaultAuthenticationFailureEventClass is the authentication failure event class - * to be fired for unmapped exceptions. + * @param defaultAuthenticationFailureEventClass is the authentication failure event + * class to be fired for unmapped exceptions. */ public void setDefaultAuthenticationFailureEvent( Class defaultAuthenticationFailureEventClass) { @@ -206,22 +187,23 @@ public class DefaultAuthenticationEventPublisher implements AuthenticationEventP try { this.defaultAuthenticationFailureEventConstructor = defaultAuthenticationFailureEventClass .getConstructor(Authentication.class, AuthenticationException.class); - } catch (NoSuchMethodException e) { + } + catch (NoSuchMethodException e) { throw new RuntimeException("Default Authentication Failure event class " + defaultAuthenticationFailureEventClass.getName() + " has no suitable constructor"); } } - private void addMapping(String exceptionClass, - Class eventClass) { + private void addMapping(String exceptionClass, Class eventClass) { try { Constructor constructor = eventClass .getConstructor(Authentication.class, AuthenticationException.class); exceptionMappings.put(exceptionClass, constructor); } catch (NoSuchMethodException e) { - throw new RuntimeException("Authentication event class " - + eventClass.getName() + " has no suitable constructor"); + throw new RuntimeException( + "Authentication event class " + eventClass.getName() + " has no suitable constructor"); } } + } diff --git a/core/src/main/java/org/springframework/security/authentication/DelegatingReactiveAuthenticationManager.java b/core/src/main/java/org/springframework/security/authentication/DelegatingReactiveAuthenticationManager.java index 0a2a43d532..cd6c7d1ef2 100644 --- a/core/src/main/java/org/springframework/security/authentication/DelegatingReactiveAuthenticationManager.java +++ b/core/src/main/java/org/springframework/security/authentication/DelegatingReactiveAuthenticationManager.java @@ -26,30 +26,28 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** - * A {@link ReactiveAuthenticationManager} that delegates to other {@link ReactiveAuthenticationManager} instances using - * the result from the first non empty result. + * A {@link ReactiveAuthenticationManager} that delegates to other + * {@link ReactiveAuthenticationManager} instances using the result from the first non + * empty result. * * @author Rob Winch * @since 5.1 */ -public class DelegatingReactiveAuthenticationManager - implements ReactiveAuthenticationManager { +public class DelegatingReactiveAuthenticationManager implements ReactiveAuthenticationManager { + private final List delegates; - public DelegatingReactiveAuthenticationManager( - ReactiveAuthenticationManager... entryPoints) { + public DelegatingReactiveAuthenticationManager(ReactiveAuthenticationManager... entryPoints) { this(Arrays.asList(entryPoints)); } - public DelegatingReactiveAuthenticationManager( - List entryPoints) { + public DelegatingReactiveAuthenticationManager(List entryPoints) { Assert.notEmpty(entryPoints, "entryPoints cannot be null"); this.delegates = entryPoints; } public Mono authenticate(Authentication authentication) { - return Flux.fromIterable(this.delegates) - .concatMap(m -> m.authenticate(authentication)) - .next(); + return Flux.fromIterable(this.delegates).concatMap(m -> m.authenticate(authentication)).next(); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/DisabledException.java b/core/src/main/java/org/springframework/security/authentication/DisabledException.java index bc48774b89..92d63cb4c9 100644 --- a/core/src/main/java/org/springframework/security/authentication/DisabledException.java +++ b/core/src/main/java/org/springframework/security/authentication/DisabledException.java @@ -23,12 +23,12 @@ package org.springframework.security.authentication; * @author Ben Alex */ public class DisabledException extends AccountStatusException { + // ~ Constructors // =================================================================================================== /** * Constructs a DisabledException with the specified message. - * * @param msg the detail message */ public DisabledException(String msg) { @@ -38,11 +38,11 @@ public class DisabledException extends AccountStatusException { /** * Constructs a DisabledException with the specified message and root * cause. - * * @param msg the detail message * @param t root cause */ public DisabledException(String msg, Throwable t) { super(msg, t); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/InsufficientAuthenticationException.java b/core/src/main/java/org/springframework/security/authentication/InsufficientAuthenticationException.java index e60723f546..6cc4c09f05 100644 --- a/core/src/main/java/org/springframework/security/authentication/InsufficientAuthenticationException.java +++ b/core/src/main/java/org/springframework/security/authentication/InsufficientAuthenticationException.java @@ -32,13 +32,13 @@ import org.springframework.security.core.AuthenticationException; * @author Ben Alex */ public class InsufficientAuthenticationException extends AuthenticationException { + // ~ Constructors // =================================================================================================== /** * Constructs an InsufficientAuthenticationException with the specified * message. - * * @param msg the detail message */ public InsufficientAuthenticationException(String msg) { @@ -48,11 +48,11 @@ public class InsufficientAuthenticationException extends AuthenticationException /** * Constructs an InsufficientAuthenticationException with the specified * message and root cause. - * * @param msg the detail message * @param t root cause */ public InsufficientAuthenticationException(String msg, Throwable t) { super(msg, t); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/InternalAuthenticationServiceException.java b/core/src/main/java/org/springframework/security/authentication/InternalAuthenticationServiceException.java index 5c08ed4e71..4e26ddd1a1 100644 --- a/core/src/main/java/org/springframework/security/authentication/InternalAuthenticationServiceException.java +++ b/core/src/main/java/org/springframework/security/authentication/InternalAuthenticationServiceException.java @@ -34,8 +34,7 @@ package org.springframework.security.authentication; * @author Rob Winch * */ -public class InternalAuthenticationServiceException extends - AuthenticationServiceException { +public class InternalAuthenticationServiceException extends AuthenticationServiceException { public InternalAuthenticationServiceException(String message, Throwable cause) { super(message, cause); @@ -44,4 +43,5 @@ public class InternalAuthenticationServiceException extends public InternalAuthenticationServiceException(String message) { super(message); } + } \ No newline at end of file diff --git a/core/src/main/java/org/springframework/security/authentication/LockedException.java b/core/src/main/java/org/springframework/security/authentication/LockedException.java index ff27ec8cc7..7dd2464959 100644 --- a/core/src/main/java/org/springframework/security/authentication/LockedException.java +++ b/core/src/main/java/org/springframework/security/authentication/LockedException.java @@ -23,12 +23,12 @@ package org.springframework.security.authentication; * @author Ben Alex */ public class LockedException extends AccountStatusException { + // ~ Constructors // =================================================================================================== /** * Constructs a LockedException with the specified message. - * * @param msg the detail message. */ public LockedException(String msg) { @@ -38,11 +38,11 @@ public class LockedException extends AccountStatusException { /** * Constructs a LockedException with the specified message and root * cause. - * * @param msg the detail message. * @param t root cause */ public LockedException(String msg, Throwable t) { super(msg, t); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/ProviderManager.java b/core/src/main/java/org/springframework/security/authentication/ProviderManager.java index 959309c95e..93af53655f 100644 --- a/core/src/main/java/org/springframework/security/authentication/ProviderManager.java +++ b/core/src/main/java/org/springframework/security/authentication/ProviderManager.java @@ -80,14 +80,12 @@ import org.springframework.util.CollectionUtils; * {@code AuthenticationManager} if one has been set. So in this situation, the parent * should not generally be configured to publish events or there will be duplicates. * - * * @author Ben Alex * @author Luke Taylor - * * @see DefaultAuthenticationEventPublisher */ -public class ProviderManager implements AuthenticationManager, MessageSourceAware, - InitializingBean { +public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean { + // ~ Static fields/initializers // ===================================================================================== @@ -97,14 +95,17 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar // ================================================================================================ private AuthenticationEventPublisher eventPublisher = new NullEventPublisher(); + private List providers = Collections.emptyList(); + protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); + private AuthenticationManager parent; + private boolean eraseCredentialsAfterAuthentication = true; /** * Construct a {@link ProviderManager} using the given {@link AuthenticationProvider}s - * * @param providers the {@link AuthenticationProvider}s to use */ public ProviderManager(AuthenticationProvider... providers) { @@ -113,7 +114,6 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar /** * Construct a {@link ProviderManager} using the given {@link AuthenticationProvider}s - * * @param providers the {@link AuthenticationProvider}s to use */ public ProviderManager(List providers) { @@ -122,12 +122,10 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar /** * Construct a {@link ProviderManager} using the provided parameters - * * @param providers the {@link AuthenticationProvider}s to use * @param parent a parent {@link AuthenticationManager} to fall back to */ - public ProviderManager(List providers, - AuthenticationManager parent) { + public ProviderManager(List providers, AuthenticationManager parent) { Assert.notNull(providers, "providers list cannot be null"); this.providers = providers; this.parent = parent; @@ -144,11 +142,10 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar private void checkState() { if (parent == null && providers.isEmpty()) { throw new IllegalArgumentException( - "A parent AuthenticationManager or a list " - + "of AuthenticationProviders is required"); - } else if (CollectionUtils.contains(providers.iterator(), null)) { - throw new IllegalArgumentException( - "providers list cannot contain null values"); + "A parent AuthenticationManager or a list " + "of AuthenticationProviders is required"); + } + else if (CollectionUtils.contains(providers.iterator(), null)) { + throw new IllegalArgumentException("providers list cannot contain null values"); } } @@ -161,24 +158,18 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar * attempted with that AuthenticationProvider. *

      * If more than one AuthenticationProvider supports the passed - * Authentication object, the first one able to successfully - * authenticate the Authentication object determines the - * result, overriding any possible AuthenticationException - * thrown by earlier supporting AuthenticationProviders. - * On successful authentication, no subsequent AuthenticationProviders - * will be tried. - * If authentication was not successful by any supporting - * AuthenticationProvider the last thrown - * AuthenticationException will be rethrown. - * + * Authentication object, the first one able to successfully authenticate + * the Authentication object determines the result, + * overriding any possible AuthenticationException thrown by earlier + * supporting AuthenticationProviders. On successful authentication, no + * subsequent AuthenticationProviders will be tried. If authentication + * was not successful by any supporting AuthenticationProvider the last + * thrown AuthenticationException will be rethrown. * @param authentication the authentication request object. - * * @return a fully authenticated object including credentials. - * * @throws AuthenticationException if authentication fails. */ - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { Class toTest = authentication.getClass(); AuthenticationException lastException = null; AuthenticationException parentException = null; @@ -192,8 +183,7 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar } if (debug) { - logger.debug("Authentication attempt using " - + provider.getClass().getName()); + logger.debug("Authentication attempt using " + provider.getClass().getName()); } try { @@ -209,7 +199,8 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar // SEC-546: Avoid polling additional providers if auth failure is due to // invalid account status throw e; - } catch (AuthenticationException e) { + } + catch (AuthenticationException e) { lastException = e; } } @@ -231,15 +222,16 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar } if (result != null) { - if (eraseCredentialsAfterAuthentication - && (result instanceof CredentialsContainer)) { + if (eraseCredentialsAfterAuthentication && (result instanceof CredentialsContainer)) { // Authentication is complete. Remove credentials and other secret data // from authentication ((CredentialsContainer) result).eraseCredentials(); } - // If the parent AuthenticationManager was attempted and successful then it will publish an AuthenticationSuccessEvent - // This check prevents a duplicate AuthenticationSuccessEvent if the parent AuthenticationManager already published it + // If the parent AuthenticationManager was attempted and successful then it + // will publish an AuthenticationSuccessEvent + // This check prevents a duplicate AuthenticationSuccessEvent if the parent + // AuthenticationManager already published it if (parentResult == null) { eventPublisher.publishAuthenticationSuccess(result); } @@ -249,14 +241,14 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar // Parent was null, or didn't authenticate (or throw an exception). if (lastException == null) { - lastException = new ProviderNotFoundException(messages.getMessage( - "ProviderManager.providerNotFound", - new Object[] { toTest.getName() }, - "No AuthenticationProvider found for {0}")); + lastException = new ProviderNotFoundException(messages.getMessage("ProviderManager.providerNotFound", + new Object[] { toTest.getName() }, "No AuthenticationProvider found for {0}")); } - // If the parent AuthenticationManager was attempted and failed then it will publish an AbstractAuthenticationFailureEvent - // This check prevents a duplicate AbstractAuthenticationFailureEvent if the parent AuthenticationManager already published it + // If the parent AuthenticationManager was attempted and failed then it will + // publish an AbstractAuthenticationFailureEvent + // This check prevents a duplicate AbstractAuthenticationFailureEvent if the + // parent AuthenticationManager already published it if (parentException == null) { prepareException(lastException, authentication); } @@ -272,7 +264,6 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar /** * Copies the authentication details from a source Authentication object to a * destination one, provided the latter does not already have one set. - * * @param source source authentication * @param dest the destination authentication object */ @@ -292,8 +283,7 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar this.messages = new MessageSourceAccessor(messageSource); } - public void setAuthenticationEventPublisher( - AuthenticationEventPublisher eventPublisher) { + public void setAuthenticationEventPublisher(AuthenticationEventPublisher eventPublisher) { Assert.notNull(eventPublisher, "AuthenticationEventPublisher cannot be null"); this.eventPublisher = eventPublisher; } @@ -303,7 +293,6 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar * {@code CredentialsContainer} interface will have its * {@link CredentialsContainer#eraseCredentials() eraseCredentials} method called * before it is returned from the {@code authenticate()} method. - * * @param eraseSecretData set to {@literal false} to retain the credentials data in * memory. Defaults to {@literal true}. */ @@ -316,11 +305,13 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar } private static final class NullEventPublisher implements AuthenticationEventPublisher { - public void publishAuthenticationFailure(AuthenticationException exception, - Authentication authentication) { + + public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) { } public void publishAuthenticationSuccess(Authentication authentication) { } + } + } diff --git a/core/src/main/java/org/springframework/security/authentication/ProviderNotFoundException.java b/core/src/main/java/org/springframework/security/authentication/ProviderNotFoundException.java index 62169c32f7..4cde08daa9 100644 --- a/core/src/main/java/org/springframework/security/authentication/ProviderNotFoundException.java +++ b/core/src/main/java/org/springframework/security/authentication/ProviderNotFoundException.java @@ -26,15 +26,16 @@ import org.springframework.security.core.AuthenticationException; * @author Ben Alex */ public class ProviderNotFoundException extends AuthenticationException { + // ~ Constructors // =================================================================================================== /** * Constructs a ProviderNotFoundException with the specified message. - * * @param msg the detail message */ public ProviderNotFoundException(String msg) { super(msg); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/ReactiveAuthenticationManager.java b/core/src/main/java/org/springframework/security/authentication/ReactiveAuthenticationManager.java index 72d554d48e..806e0cd2f5 100644 --- a/core/src/main/java/org/springframework/security/authentication/ReactiveAuthenticationManager.java +++ b/core/src/main/java/org/springframework/security/authentication/ReactiveAuthenticationManager.java @@ -30,11 +30,11 @@ public interface ReactiveAuthenticationManager { /** * Attempts to authenticate the provided {@link Authentication} - * * @param authentication the {@link Authentication} to test * @return if authentication is successful an {@link Authentication} is returned. If * authentication cannot be determined, an empty Mono is returned. If authentication * fails, a Mono error is returned. */ Mono authenticate(Authentication authentication); + } diff --git a/core/src/main/java/org/springframework/security/authentication/ReactiveAuthenticationManagerAdapter.java b/core/src/main/java/org/springframework/security/authentication/ReactiveAuthenticationManagerAdapter.java index 087a169b94..a26649dbc2 100644 --- a/core/src/main/java/org/springframework/security/authentication/ReactiveAuthenticationManagerAdapter.java +++ b/core/src/main/java/org/springframework/security/authentication/ReactiveAuthenticationManagerAdapter.java @@ -22,9 +22,10 @@ import reactor.core.scheduler.Scheduler; import reactor.core.scheduler.Schedulers; /** - * Adapts an AuthenticationManager to the reactive APIs. This is somewhat necessary because many of the ways that - * credentials are stored (i.e. JDBC, LDAP, etc) do not have reactive implementations. What's more is it is generally - * considered best practice to store passwords in a hash that is intentionally slow which would block ever request + * Adapts an AuthenticationManager to the reactive APIs. This is somewhat necessary + * because many of the ways that credentials are stored (i.e. JDBC, LDAP, etc) do not have + * reactive implementations. What's more is it is generally considered best practice to + * store passwords in a hash that is intentionally slow which would block ever request * from coming in unless it was put on another thread. * * @author Rob Winch @@ -32,6 +33,7 @@ import reactor.core.scheduler.Schedulers; * @since 5.0 */ public class ReactiveAuthenticationManagerAdapter implements ReactiveAuthenticationManager { + private final AuthenticationManager authenticationManager; private Scheduler scheduler = Schedulers.boundedElastic(); @@ -43,16 +45,14 @@ public class ReactiveAuthenticationManagerAdapter implements ReactiveAuthenticat @Override public Mono authenticate(Authentication token) { - return Mono.just(token) - .publishOn(this.scheduler) - .flatMap( t -> { - try { - return Mono.just(authenticationManager.authenticate(t)); - } catch(Throwable error) { - return Mono.error(error); - } - }) - .filter( a -> a.isAuthenticated()); + return Mono.just(token).publishOn(this.scheduler).flatMap(t -> { + try { + return Mono.just(authenticationManager.authenticate(t)); + } + catch (Throwable error) { + return Mono.error(error); + } + }).filter(a -> a.isAuthenticated()); } /** diff --git a/core/src/main/java/org/springframework/security/authentication/ReactiveAuthenticationManagerResolver.java b/core/src/main/java/org/springframework/security/authentication/ReactiveAuthenticationManagerResolver.java index 25c4fc8241..705eb3969e 100644 --- a/core/src/main/java/org/springframework/security/authentication/ReactiveAuthenticationManagerResolver.java +++ b/core/src/main/java/org/springframework/security/authentication/ReactiveAuthenticationManagerResolver.java @@ -21,12 +21,15 @@ import org.springframework.security.authentication.ReactiveAuthenticationManager import reactor.core.publisher.Mono; /** - * An interface for resolving a {@link ReactiveAuthenticationManager} based on the provided context + * An interface for resolving a {@link ReactiveAuthenticationManager} based on the + * provided context * * @author Rafiullah Hamedy * @since 5.2 */ @FunctionalInterface public interface ReactiveAuthenticationManagerResolver { + Mono resolve(C context); + } \ No newline at end of file diff --git a/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationProvider.java b/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationProvider.java index 0b44ba0fb1..0eb69c59fa 100644 --- a/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationProvider.java +++ b/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationProvider.java @@ -32,12 +32,13 @@ import org.springframework.util.Assert; * To be successfully validated, the {@link RememberMeAuthenticationToken#getKeyHash()} * must match this class' {@link #getKey()}. */ -public class RememberMeAuthenticationProvider implements AuthenticationProvider, - InitializingBean, MessageSourceAware { +public class RememberMeAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { + // ~ Instance fields // ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); + private String key; public RememberMeAuthenticationProvider(String key) { @@ -52,17 +53,14 @@ public class RememberMeAuthenticationProvider implements AuthenticationProvider, Assert.notNull(this.messages, "A message source must be set"); } - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; } - if (this.key.hashCode() != ((RememberMeAuthenticationToken) authentication) - .getKeyHash()) { - throw new BadCredentialsException( - messages.getMessage("RememberMeAuthenticationProvider.incorrectKey", - "The presented RememberMeAuthenticationToken does not contain the expected key")); + if (this.key.hashCode() != ((RememberMeAuthenticationToken) authentication).getKeyHash()) { + throw new BadCredentialsException(messages.getMessage("RememberMeAuthenticationProvider.incorrectKey", + "The presented RememberMeAuthenticationToken does not contain the expected key")); } return authentication; @@ -79,4 +77,5 @@ public class RememberMeAuthenticationProvider implements AuthenticationProvider, public boolean supports(Class authentication) { return (RememberMeAuthenticationToken.class.isAssignableFrom(authentication)); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java index 1e75db9a50..25a53c6783 100644 --- a/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationToken.java @@ -38,6 +38,7 @@ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken { // ================================================================================================ private final Object principal; + private final int keyHash; // ~ Constructors @@ -45,20 +46,17 @@ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken { /** * Constructor. - * - * @param key to identify if this object made by an authorised client - * @param principal the principal (typically a UserDetails) + * @param key to identify if this object made by an authorised client + * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal * @throws IllegalArgumentException if a null was passed */ public RememberMeAuthenticationToken(String key, Object principal, - Collection authorities) { + Collection authorities) { super(authorities); - if ((key == null) || ("".equals(key)) || (principal == null) - || "".equals(principal)) { - throw new IllegalArgumentException( - "Cannot pass null or empty values to constructor"); + if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal)) { + throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); } this.keyHash = key.hashCode(); @@ -68,13 +66,13 @@ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken { /** * Private Constructor to help in Jackson deserialization. - * - * @param keyHash hashCode of above given key. - * @param principal the principal (typically a UserDetails) + * @param keyHash hashCode of above given key. + * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal * @since 4.2 */ - private RememberMeAuthenticationToken(Integer keyHash, Object principal, Collection authorities) { + private RememberMeAuthenticationToken(Integer keyHash, Object principal, + Collection authorities) { super(authorities); this.keyHash = keyHash; @@ -87,7 +85,6 @@ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken { /** * Always returns an empty String - * * @return an empty String */ @Override @@ -129,4 +126,5 @@ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken { result = 31 * result + this.keyHash; return result; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/TestingAuthenticationProvider.java b/core/src/main/java/org/springframework/security/authentication/TestingAuthenticationProvider.java index ff42fe79c6..d71cb0be5e 100644 --- a/core/src/main/java/org/springframework/security/authentication/TestingAuthenticationProvider.java +++ b/core/src/main/java/org/springframework/security/authentication/TestingAuthenticationProvider.java @@ -33,15 +33,16 @@ import org.springframework.security.core.AuthenticationException; * @author Ben Alex */ public class TestingAuthenticationProvider implements AuthenticationProvider { + // ~ Methods // ======================================================================================================== - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { return authentication; } public boolean supports(Class authentication) { return TestingAuthenticationToken.class.isAssignableFrom(authentication); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/TestingAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/TestingAuthenticationToken.java index 9aeb4446b7..18ee4ec882 100644 --- a/core/src/main/java/org/springframework/security/authentication/TestingAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/TestingAuthenticationToken.java @@ -30,11 +30,14 @@ import java.util.List; * @author Ben Alex */ public class TestingAuthenticationToken extends AbstractAuthenticationToken { + // ~ Instance fields // ================================================================================================ private static final long serialVersionUID = 1L; + private final Object credentials; + private final Object principal; // ~ Constructors @@ -46,13 +49,11 @@ public class TestingAuthenticationToken extends AbstractAuthenticationToken { this.credentials = credentials; } - public TestingAuthenticationToken(Object principal, Object credentials, - String... authorities) { + public TestingAuthenticationToken(Object principal, Object credentials, String... authorities) { this(principal, credentials, AuthorityUtils.createAuthorityList(authorities)); } - public TestingAuthenticationToken(Object principal, Object credentials, - List authorities) { + public TestingAuthenticationToken(Object principal, Object credentials, List authorities) { super(authorities); this.principal = principal; this.credentials = credentials; @@ -69,4 +70,5 @@ public class TestingAuthenticationToken extends AbstractAuthenticationToken { public Object getPrincipal() { return this.principal; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManager.java b/core/src/main/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManager.java index 5d273beb4b..a27ed5f68d 100644 --- a/core/src/main/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManager.java +++ b/core/src/main/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManager.java @@ -23,14 +23,15 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.util.Assert; /** - * A {@link ReactiveAuthenticationManager} that uses a {@link ReactiveUserDetailsService} to validate the provided - * username and password. + * A {@link ReactiveAuthenticationManager} that uses a {@link ReactiveUserDetailsService} + * to validate the provided username and password. * * @author Rob Winch * @author Eddú Meléndez * @since 5.0 */ -public class UserDetailsRepositoryReactiveAuthenticationManager extends AbstractUserDetailsReactiveAuthenticationManager { +public class UserDetailsRepositoryReactiveAuthenticationManager + extends AbstractUserDetailsReactiveAuthenticationManager { private ReactiveUserDetailsService userDetailsService; diff --git a/core/src/main/java/org/springframework/security/authentication/UsernamePasswordAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/UsernamePasswordAuthenticationToken.java index 152d9961e6..634cc35f50 100644 --- a/core/src/main/java/org/springframework/security/authentication/UsernamePasswordAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/UsernamePasswordAuthenticationToken.java @@ -40,6 +40,7 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT // ================================================================================================ private final Object principal; + private Object credentials; // ~ Constructors @@ -63,7 +64,6 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT * AuthenticationProvider implementations that are satisfied with * producing a trusted (i.e. {@link #isAuthenticated()} = true) * authentication token. - * * @param principal * @param credentials * @param authorities @@ -101,4 +101,5 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT super.eraseCredentials(); credentials = null; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.java b/core/src/main/java/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.java index c752c81197..cc054bc87e 100644 --- a/core/src/main/java/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.java +++ b/core/src/main/java/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.java @@ -76,8 +76,8 @@ import org.springframework.util.Assert; * * @author Ben Alex */ -public abstract class AbstractUserDetailsAuthenticationProvider implements - AuthenticationProvider, InitializingBean, MessageSourceAware { +public abstract class AbstractUserDetailsAuthenticationProvider + implements AuthenticationProvider, InitializingBean, MessageSourceAware { protected final Log logger = LogFactory.getLog(getClass()); @@ -85,11 +85,17 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements // ================================================================================================ protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); + private UserCache userCache = new NullUserCache(); + private boolean forcePrincipalAsString = false; + protected boolean hideUserNotFoundExceptions = true; + private UserDetailsChecker preAuthenticationChecks = new DefaultPreAuthenticationChecks(); + private UserDetailsChecker postAuthenticationChecks = new DefaultPostAuthenticationChecks(); + private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper(); // ~ Methods @@ -103,19 +109,16 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements * properties of UserDetails and/or * UsernamePasswordAuthenticationToken, these should also appear in this * method. - * * @param userDetails as retrieved from the * {@link #retrieveUser(String, UsernamePasswordAuthenticationToken)} or * UserCache * @param authentication the current request that needs to be authenticated - * * @throws AuthenticationException AuthenticationException if the credentials could * not be validated (generally a BadCredentialsException, an * AuthenticationServiceException) */ protected abstract void additionalAuthenticationChecks(UserDetails userDetails, - UsernamePasswordAuthenticationToken authentication) - throws AuthenticationException; + UsernamePasswordAuthenticationToken authentication) throws AuthenticationException; public final void afterPropertiesSet() throws Exception { Assert.notNull(this.userCache, "A user cache must be set"); @@ -123,16 +126,13 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements doAfterPropertiesSet(); } - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, - () -> messages.getMessage( - "AbstractUserDetailsAuthenticationProvider.onlySupports", + () -> messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports", "Only UsernamePasswordAuthenticationToken is supported")); // Determine username - String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" - : authentication.getName(); + String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName(); boolean cacheWasUsed = true; UserDetails user = this.userCache.getUserFromCache(username); @@ -141,41 +141,35 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements cacheWasUsed = false; try { - user = retrieveUser(username, - (UsernamePasswordAuthenticationToken) authentication); + user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); } catch (UsernameNotFoundException notFound) { logger.debug("User '" + username + "' not found"); if (hideUserNotFoundExceptions) { - throw new BadCredentialsException(messages.getMessage( - "AbstractUserDetailsAuthenticationProvider.badCredentials", - "Bad credentials")); + throw new BadCredentialsException(messages + .getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } else { throw notFound; } } - Assert.notNull(user, - "retrieveUser returned null - a violation of the interface contract"); + Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract"); } try { preAuthenticationChecks.check(user); - additionalAuthenticationChecks(user, - (UsernamePasswordAuthenticationToken) authentication); + additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); } catch (AuthenticationException exception) { if (cacheWasUsed) { // There was a problem, so try again after checking // we're using latest data (i.e. not from the cache) cacheWasUsed = false; - user = retrieveUser(username, - (UsernamePasswordAuthenticationToken) authentication); + user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); preAuthenticationChecks.check(user); - additionalAuthenticationChecks(user, - (UsernamePasswordAuthenticationToken) authentication); + additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication); } else { throw exception; @@ -206,23 +200,20 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements * Subclasses will usually store the original credentials the user supplied (not * salted or encoded passwords) in the returned Authentication object. *

      - * * @param principal that should be the principal in the returned object (defined by * the {@link #isForcePrincipalAsString()} method) * @param authentication that was presented to the provider for validation * @param user that was loaded by the implementation - * * @return the successful authentication token */ - protected Authentication createSuccessAuthentication(Object principal, - Authentication authentication, UserDetails user) { + protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, + UserDetails user) { // Ensure we return the original credentials the user supplied, // so subsequent attempts are successful even with encoded passwords. // Also ensure we return the original getDetails(), so that future // authentication events after cache expiry contain the details - UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken( - principal, authentication.getCredentials(), - authoritiesMapper.mapAuthorities(user.getAuthorities())); + UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(principal, + authentication.getCredentials(), authoritiesMapper.mapAuthorities(user.getAuthorities())); result.setDetails(authentication.getDetails()); return result; @@ -271,21 +262,17 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements * so that code related to credentials validation need not be duplicated across two * methods. *

      - * * @param username The username to retrieve * @param authentication The authentication request, which subclasses may * need to perform a binding-based retrieval of the UserDetails - * * @return the user information (never null - instead an exception should * the thrown) - * * @throws AuthenticationException if the credentials could not be validated * (generally a BadCredentialsException, an * AuthenticationServiceException or * UsernameNotFoundException) */ - protected abstract UserDetails retrieveUser(String username, - UsernamePasswordAuthenticationToken authentication) + protected abstract UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException; public void setForcePrincipalAsString(boolean forcePrincipalAsString) { @@ -299,7 +286,6 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements * UsernameNotFoundExceptions to be thrown instead for the former. Note * this is considered less secure than throwing BadCredentialsException * for both exceptions. - * * @param hideUserNotFoundExceptions set to false if you wish * UsernameNotFoundExceptions to be thrown instead of the non-specific * BadCredentialsException (defaults to true) @@ -317,8 +303,7 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements } public boolean supports(Class authentication) { - return (UsernamePasswordAuthenticationToken.class - .isAssignableFrom(authentication)); + return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); } protected UserDetailsChecker getPreAuthenticationChecks() { @@ -328,7 +313,6 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements /** * Sets the policy will be used to verify the status of the loaded * UserDetails before validation of the credentials takes place. - * * @param preAuthenticationChecks strategy to be invoked prior to authentication. */ public void setPreAuthenticationChecks(UserDetailsChecker preAuthenticationChecks) { @@ -348,42 +332,44 @@ public abstract class AbstractUserDetailsAuthenticationProvider implements } private class DefaultPreAuthenticationChecks implements UserDetailsChecker { + public void check(UserDetails user) { if (!user.isAccountNonLocked()) { logger.debug("User account is locked"); - throw new LockedException(messages.getMessage( - "AbstractUserDetailsAuthenticationProvider.locked", + throw new LockedException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked", "User account is locked")); } if (!user.isEnabled()) { logger.debug("User account is disabled"); - throw new DisabledException(messages.getMessage( - "AbstractUserDetailsAuthenticationProvider.disabled", - "User is disabled")); + throw new DisabledException( + messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled", "User is disabled")); } if (!user.isAccountNonExpired()) { logger.debug("User account is expired"); - throw new AccountExpiredException(messages.getMessage( - "AbstractUserDetailsAuthenticationProvider.expired", - "User account has expired")); + throw new AccountExpiredException(messages + .getMessage("AbstractUserDetailsAuthenticationProvider.expired", "User account has expired")); } } + } private class DefaultPostAuthenticationChecks implements UserDetailsChecker { + public void check(UserDetails user) { if (!user.isCredentialsNonExpired()) { logger.debug("User account credentials have expired"); - throw new CredentialsExpiredException(messages.getMessage( - "AbstractUserDetailsAuthenticationProvider.credentialsExpired", - "User credentials have expired")); + throw new CredentialsExpiredException( + messages.getMessage("AbstractUserDetailsAuthenticationProvider.credentialsExpired", + "User credentials have expired")); } } + } + } diff --git a/core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java b/core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java index 2771f9790a..f2a2b57769 100644 --- a/core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java +++ b/core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java @@ -38,13 +38,13 @@ import org.springframework.util.Assert; * @author Rob Winch */ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { + // ~ Static fields/initializers // ===================================================================================== /** - * The plaintext password used to perform - * PasswordEncoder#matches(CharSequence, String)} on when the user is - * not found to avoid SEC-2056. + * The plaintext password used to perform PasswordEncoder#matches(CharSequence, + * String)} on when the user is not found to avoid SEC-2056. */ private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword"; @@ -54,9 +54,8 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication private PasswordEncoder passwordEncoder; /** - * The password used to perform - * {@link PasswordEncoder#matches(CharSequence, String)} on when the user is - * not found to avoid SEC-2056. This is necessary, because some + * The password used to perform {@link PasswordEncoder#matches(CharSequence, String)} + * on when the user is not found to avoid SEC-2056. This is necessary, because some * {@link PasswordEncoder} implementations will short circuit if the password is not * in a valid format. */ @@ -75,14 +74,12 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication @SuppressWarnings("deprecation") protected void additionalAuthenticationChecks(UserDetails userDetails, - UsernamePasswordAuthenticationToken authentication) - throws AuthenticationException { + UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { if (authentication.getCredentials() == null) { logger.debug("Authentication failed: no credentials provided"); - throw new BadCredentialsException(messages.getMessage( - "AbstractUserDetailsAuthenticationProvider.badCredentials", - "Bad credentials")); + throw new BadCredentialsException( + messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } String presentedPassword = authentication.getCredentials().toString(); @@ -90,9 +87,8 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) { logger.debug("Authentication failed: password does not match stored value"); - throw new BadCredentialsException(messages.getMessage( - "AbstractUserDetailsAuthenticationProvider.badCredentials", - "Bad credentials")); + throw new BadCredentialsException( + messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } } @@ -100,8 +96,7 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication Assert.notNull(this.userDetailsService, "A UserDetailsService must be set"); } - protected final UserDetails retrieveUser(String username, - UsernamePasswordAuthenticationToken authentication) + protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { prepareTimingAttackProtection(); try { @@ -125,8 +120,8 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication } @Override - protected Authentication createSuccessAuthentication(Object principal, - Authentication authentication, UserDetails user) { + protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, + UserDetails user) { boolean upgradeEncoding = this.userDetailsPasswordService != null && this.passwordEncoder.upgradeEncoding(user.getPassword()); if (upgradeEncoding) { @@ -152,8 +147,8 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication /** * Sets the PasswordEncoder instance to be used to encode and validate passwords. If - * not set, the password will be compared using {@link PasswordEncoderFactories#createDelegatingPasswordEncoder()} - * + * not set, the password will be compared using + * {@link PasswordEncoderFactories#createDelegatingPasswordEncoder()} * @param passwordEncoder must be an instance of one of the {@code PasswordEncoder} * types. */ @@ -175,8 +170,8 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication return userDetailsService; } - public void setUserDetailsPasswordService( - UserDetailsPasswordService userDetailsPasswordService) { + public void setUserDetailsPasswordService(UserDetailsPasswordService userDetailsPasswordService) { this.userDetailsPasswordService = userDetailsPasswordService; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/dao/package-info.java b/core/src/main/java/org/springframework/security/authentication/dao/package-info.java index a171b83750..1eaaf2baec 100644 --- a/core/src/main/java/org/springframework/security/authentication/dao/package-info.java +++ b/core/src/main/java/org/springframework/security/authentication/dao/package-info.java @@ -17,4 +17,3 @@ * An {@code AuthenticationProvider} which relies upon a data access object. */ package org.springframework.security.authentication.dao; - diff --git a/core/src/main/java/org/springframework/security/authentication/event/AbstractAuthenticationEvent.java b/core/src/main/java/org/springframework/security/authentication/event/AbstractAuthenticationEvent.java index 3102a7f688..4c6975d322 100644 --- a/core/src/main/java/org/springframework/security/authentication/event/AbstractAuthenticationEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/event/AbstractAuthenticationEvent.java @@ -30,6 +30,7 @@ import org.springframework.context.ApplicationEvent; * @author Ben Alex */ public abstract class AbstractAuthenticationEvent extends ApplicationEvent { + // ~ Constructors // =================================================================================================== @@ -43,10 +44,10 @@ public abstract class AbstractAuthenticationEvent extends ApplicationEvent { /** * Getters for the Authentication request that caused the event. Also * available from super.getSource(). - * * @return the authentication request */ public Authentication getAuthentication() { return (Authentication) super.getSource(); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/event/AbstractAuthenticationFailureEvent.java b/core/src/main/java/org/springframework/security/authentication/event/AbstractAuthenticationFailureEvent.java index 74dec87a9e..906ee2a3d9 100644 --- a/core/src/main/java/org/springframework/security/authentication/event/AbstractAuthenticationFailureEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/event/AbstractAuthenticationFailureEvent.java @@ -26,8 +26,8 @@ import org.springframework.util.Assert; * * @author Ben Alex */ -public abstract class AbstractAuthenticationFailureEvent extends - AbstractAuthenticationEvent { +public abstract class AbstractAuthenticationFailureEvent extends AbstractAuthenticationEvent { + // ~ Instance fields // ================================================================================================ @@ -36,8 +36,7 @@ public abstract class AbstractAuthenticationFailureEvent extends // ~ Constructors // =================================================================================================== - public AbstractAuthenticationFailureEvent(Authentication authentication, - AuthenticationException exception) { + public AbstractAuthenticationFailureEvent(Authentication authentication, AuthenticationException exception) { super(authentication); Assert.notNull(exception, "AuthenticationException is required"); this.exception = exception; @@ -49,4 +48,5 @@ public abstract class AbstractAuthenticationFailureEvent extends public AuthenticationException getException() { return exception; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureBadCredentialsEvent.java b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureBadCredentialsEvent.java index c1edd6f79a..2d895f88c9 100644 --- a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureBadCredentialsEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureBadCredentialsEvent.java @@ -25,13 +25,13 @@ import org.springframework.security.core.AuthenticationException; * * @author Ben Alex */ -public class AuthenticationFailureBadCredentialsEvent extends - AbstractAuthenticationFailureEvent { +public class AuthenticationFailureBadCredentialsEvent extends AbstractAuthenticationFailureEvent { + // ~ Constructors // =================================================================================================== - public AuthenticationFailureBadCredentialsEvent(Authentication authentication, - AuthenticationException exception) { + public AuthenticationFailureBadCredentialsEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureCredentialsExpiredEvent.java b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureCredentialsExpiredEvent.java index 2414f05ae9..f9e3c20c52 100644 --- a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureCredentialsExpiredEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureCredentialsExpiredEvent.java @@ -25,8 +25,8 @@ import org.springframework.security.core.AuthenticationException; * * @author Ben Alex */ -public class AuthenticationFailureCredentialsExpiredEvent extends - AbstractAuthenticationFailureEvent { +public class AuthenticationFailureCredentialsExpiredEvent extends AbstractAuthenticationFailureEvent { + // ~ Constructors // =================================================================================================== @@ -34,4 +34,5 @@ public class AuthenticationFailureCredentialsExpiredEvent extends AuthenticationException exception) { super(authentication, exception); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureDisabledEvent.java b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureDisabledEvent.java index d9a8dd22c1..12bd98bf2a 100644 --- a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureDisabledEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureDisabledEvent.java @@ -25,13 +25,13 @@ import org.springframework.security.core.AuthenticationException; * * @author Ben Alex */ -public class AuthenticationFailureDisabledEvent extends - AbstractAuthenticationFailureEvent { +public class AuthenticationFailureDisabledEvent extends AbstractAuthenticationFailureEvent { + // ~ Constructors // =================================================================================================== - public AuthenticationFailureDisabledEvent(Authentication authentication, - AuthenticationException exception) { + public AuthenticationFailureDisabledEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureExpiredEvent.java b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureExpiredEvent.java index e95bcf3eae..c0c00a8321 100644 --- a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureExpiredEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureExpiredEvent.java @@ -26,11 +26,12 @@ import org.springframework.security.core.AuthenticationException; * @author Ben Alex */ public class AuthenticationFailureExpiredEvent extends AbstractAuthenticationFailureEvent { + // ~ Constructors // =================================================================================================== - public AuthenticationFailureExpiredEvent(Authentication authentication, - AuthenticationException exception) { + public AuthenticationFailureExpiredEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureLockedEvent.java b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureLockedEvent.java index 0e0e88b6a7..b4a63f5257 100644 --- a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureLockedEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureLockedEvent.java @@ -26,11 +26,12 @@ import org.springframework.security.core.AuthenticationException; * @author Ben Alex */ public class AuthenticationFailureLockedEvent extends AbstractAuthenticationFailureEvent { + // ~ Constructors // =================================================================================================== - public AuthenticationFailureLockedEvent(Authentication authentication, - AuthenticationException exception) { + public AuthenticationFailureLockedEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureProviderNotFoundEvent.java b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureProviderNotFoundEvent.java index e3e9f2d818..86e84c819c 100644 --- a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureProviderNotFoundEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureProviderNotFoundEvent.java @@ -25,8 +25,8 @@ import org.springframework.security.core.AuthenticationException; * * @author Ben Alex */ -public class AuthenticationFailureProviderNotFoundEvent extends - AbstractAuthenticationFailureEvent { +public class AuthenticationFailureProviderNotFoundEvent extends AbstractAuthenticationFailureEvent { + // ~ Constructors // =================================================================================================== @@ -34,4 +34,5 @@ public class AuthenticationFailureProviderNotFoundEvent extends AuthenticationException exception) { super(authentication, exception); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureProxyUntrustedEvent.java b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureProxyUntrustedEvent.java index 667076bc06..c64fdc3d85 100644 --- a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureProxyUntrustedEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureProxyUntrustedEvent.java @@ -25,13 +25,13 @@ import org.springframework.security.core.AuthenticationException; * * @author Ben Alex */ -public class AuthenticationFailureProxyUntrustedEvent extends - AbstractAuthenticationFailureEvent { +public class AuthenticationFailureProxyUntrustedEvent extends AbstractAuthenticationFailureEvent { + // ~ Constructors // =================================================================================================== - public AuthenticationFailureProxyUntrustedEvent(Authentication authentication, - AuthenticationException exception) { + public AuthenticationFailureProxyUntrustedEvent(Authentication authentication, AuthenticationException exception) { super(authentication, exception); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureServiceExceptionEvent.java b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureServiceExceptionEvent.java index 52869e5357..565d022d87 100644 --- a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureServiceExceptionEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureServiceExceptionEvent.java @@ -25,8 +25,8 @@ import org.springframework.security.core.AuthenticationException; * * @author Ben Alex */ -public class AuthenticationFailureServiceExceptionEvent extends - AbstractAuthenticationFailureEvent { +public class AuthenticationFailureServiceExceptionEvent extends AbstractAuthenticationFailureEvent { + // ~ Constructors // =================================================================================================== @@ -34,4 +34,5 @@ public class AuthenticationFailureServiceExceptionEvent extends AuthenticationException exception) { super(authentication, exception); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationSuccessEvent.java b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationSuccessEvent.java index 67a7b18f11..6eafa52c9e 100644 --- a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationSuccessEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationSuccessEvent.java @@ -24,10 +24,12 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ public class AuthenticationSuccessEvent extends AbstractAuthenticationEvent { + // ~ Constructors // =================================================================================================== public AuthenticationSuccessEvent(Authentication authentication) { super(authentication); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/event/InteractiveAuthenticationSuccessEvent.java b/core/src/main/java/org/springframework/security/authentication/event/InteractiveAuthenticationSuccessEvent.java index db60e208f7..d73b49a4b7 100644 --- a/core/src/main/java/org/springframework/security/authentication/event/InteractiveAuthenticationSuccessEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/event/InteractiveAuthenticationSuccessEvent.java @@ -34,6 +34,7 @@ import org.springframework.util.Assert; * @author Ben Alex */ public class InteractiveAuthenticationSuccessEvent extends AbstractAuthenticationEvent { + // ~ Instance fields // ================================================================================================ @@ -42,8 +43,7 @@ public class InteractiveAuthenticationSuccessEvent extends AbstractAuthenticatio // ~ Constructors // =================================================================================================== - public InteractiveAuthenticationSuccessEvent(Authentication authentication, - Class generatedBy) { + public InteractiveAuthenticationSuccessEvent(Authentication authentication, Class generatedBy) { super(authentication); Assert.notNull(generatedBy, "generatedBy cannot be null"); this.generatedBy = generatedBy; @@ -55,10 +55,10 @@ public class InteractiveAuthenticationSuccessEvent extends AbstractAuthenticatio /** * Getter for the Class that generated this event. This can be useful for * generating additional logging information. - * * @return the class */ public Class getGeneratedBy() { return generatedBy; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/event/LoggerListener.java b/core/src/main/java/org/springframework/security/authentication/event/LoggerListener.java index 0d23755dea..8332e48999 100644 --- a/core/src/main/java/org/springframework/security/authentication/event/LoggerListener.java +++ b/core/src/main/java/org/springframework/security/authentication/event/LoggerListener.java @@ -29,6 +29,7 @@ import org.springframework.util.ClassUtils; * @author Ben Alex */ public class LoggerListener implements ApplicationListener { + // ~ Static fields/initializers // ===================================================================================== @@ -44,8 +45,7 @@ public class LoggerListener implements ApplicationListenerProviderManager automatically publishes events to the application context. These events are - * received by all registered Spring ApplicationListeners. + * The ProviderManager automatically publishes events to the application + * context. These events are received by all registered Spring + * ApplicationListeners. */ package org.springframework.security.authentication.event; - diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/AbstractJaasAuthenticationProvider.java b/core/src/main/java/org/springframework/security/authentication/jaas/AbstractJaasAuthenticationProvider.java index 54552a1e0f..532ceb2030 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/AbstractJaasAuthenticationProvider.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/AbstractJaasAuthenticationProvider.java @@ -64,8 +64,8 @@ import org.springframework.util.ObjectUtils; * *

      * When using JAAS login modules as the authentication source, sometimes the - * LoginContext will require CallbackHandlers. The + * "https://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/login/LoginContext.html" + * > LoginContext will require CallbackHandlers. The * AbstractJaasAuthenticationProvider uses an internal CallbackHandler to wrap the {@link JaasAuthenticationCallbackHandler}s configured @@ -113,17 +113,22 @@ import org.springframework.util.ObjectUtils; * @author Ray Krueger * @author Rob Winch */ -public abstract class AbstractJaasAuthenticationProvider - implements AuthenticationProvider, ApplicationEventPublisherAware, - InitializingBean, ApplicationListener { +public abstract class AbstractJaasAuthenticationProvider implements AuthenticationProvider, + ApplicationEventPublisherAware, InitializingBean, ApplicationListener { + // ~ Instance fields // ================================================================================================ private ApplicationEventPublisher applicationEventPublisher; + private AuthorityGranter[] authorityGranters; + private JaasAuthenticationCallbackHandler[] callbackHandlers; + protected final Log log = LogFactory.getLog(getClass()); + private LoginExceptionResolver loginExceptionResolver = new DefaultLoginExceptionResolver(); + private String loginContextName = "SPRINGSECURITY"; // ~ Methods @@ -136,33 +141,26 @@ public abstract class AbstractJaasAuthenticationProvider * {@link JaasPasswordCallbackHandler}. */ public void afterPropertiesSet() throws Exception { - Assert.hasLength(this.loginContextName, - "loginContextName cannot be null or empty"); - Assert.notEmpty(this.authorityGranters, - "authorityGranters cannot be null or empty"); + Assert.hasLength(this.loginContextName, "loginContextName cannot be null or empty"); + Assert.notEmpty(this.authorityGranters, "authorityGranters cannot be null or empty"); if (ObjectUtils.isEmpty(this.callbackHandlers)) { - setCallbackHandlers(new JaasAuthenticationCallbackHandler[] { - new JaasNameCallbackHandler(), new JaasPasswordCallbackHandler() }); + setCallbackHandlers(new JaasAuthenticationCallbackHandler[] { new JaasNameCallbackHandler(), + new JaasPasswordCallbackHandler() }); } - Assert.notNull(this.loginExceptionResolver, - "loginExceptionResolver cannot be null"); + Assert.notNull(this.loginExceptionResolver, "loginExceptionResolver cannot be null"); } /** * Attempts to login the user given the Authentication objects principal and * credential - * * @param auth The Authentication object to be authenticated. - * * @return The authenticated Authentication object, with it's grantedAuthorities set. - * * @throws AuthenticationException This implementation does not handle 'locked' or * 'disabled' accounts. This method only throws a AuthenticationServiceException, with * the message of the LoginException that will be thrown, should the * loginContext.login() method fail. */ - public Authentication authenticate(Authentication auth) - throws AuthenticationException { + public Authentication authenticate(Authentication auth) throws AuthenticationException { if (!(auth instanceof UsernamePasswordAuthenticationToken)) { return null; } @@ -172,8 +170,7 @@ public abstract class AbstractJaasAuthenticationProvider try { // Create the LoginContext object, and pass our InternallCallbackHandler - LoginContext loginContext = createLoginContext( - new InternalCallbackHandler(auth)); + LoginContext loginContext = createLoginContext(new InternalCallbackHandler(auth)); // Attempt to login the user, the LoginContext will call our // InternalCallbackHandler at this point. @@ -201,9 +198,8 @@ public abstract class AbstractJaasAuthenticationProvider } // Convert the authorities set back to an array and apply it to the token. - JaasAuthenticationToken result = new JaasAuthenticationToken( - request.getPrincipal(), request.getCredentials(), - new ArrayList<>(authorities), loginContext); + JaasAuthenticationToken result = new JaasAuthenticationToken(request.getPrincipal(), + request.getCredentials(), new ArrayList<>(authorities), loginContext); // Publish the success event publishSuccessEvent(result); @@ -213,8 +209,7 @@ public abstract class AbstractJaasAuthenticationProvider } catch (LoginException loginException) { - AuthenticationException ase = this.loginExceptionResolver - .resolveException(loginException); + AuthenticationException ase = this.loginExceptionResolver.resolveException(loginException); publishFailureEvent(request, ase); throw ase; @@ -223,21 +218,17 @@ public abstract class AbstractJaasAuthenticationProvider /** * Creates the LoginContext to be used for authentication. - * * @param handler The CallbackHandler that should be used for the LoginContext (never * null). * @return the LoginContext to use for authentication. * @throws LoginException */ - protected abstract LoginContext createLoginContext(CallbackHandler handler) - throws LoginException; + protected abstract LoginContext createLoginContext(CallbackHandler handler) throws LoginException; /** * Handles the logout by getting the security contexts for the destroyed session and * invoking {@code LoginContext.logout()} for any which contain a * {@code JaasAuthenticationToken}. - * - * * @param event the session event which contains the current session */ protected void handleLogout(SessionDestroyedEvent event) { @@ -260,14 +251,12 @@ public abstract class AbstractJaasAuthenticationProvider boolean debug = this.log.isDebugEnabled(); if (loginContext != null) { if (debug) { - this.log.debug("Logging principal: [" + token.getPrincipal() - + "] out of LoginContext"); + this.log.debug("Logging principal: [" + token.getPrincipal() + "] out of LoginContext"); } loginContext.logout(); } else if (debug) { - this.log.debug("Cannot logout principal: [" + token.getPrincipal() - + "] from LoginContext. " + this.log.debug("Cannot logout principal: [" + token.getPrincipal() + "] from LoginContext. " + "The LoginContext is unavailable"); } } @@ -285,28 +274,23 @@ public abstract class AbstractJaasAuthenticationProvider /** * Publishes the {@link JaasAuthenticationFailedEvent}. Can be overridden by * subclasses for different functionality - * * @param token The authentication token being processed * @param ase The excetion that caused the authentication failure */ - protected void publishFailureEvent(UsernamePasswordAuthenticationToken token, - AuthenticationException ase) { + protected void publishFailureEvent(UsernamePasswordAuthenticationToken token, AuthenticationException ase) { if (this.applicationEventPublisher != null) { - this.applicationEventPublisher - .publishEvent(new JaasAuthenticationFailedEvent(token, ase)); + this.applicationEventPublisher.publishEvent(new JaasAuthenticationFailedEvent(token, ase)); } } /** * Publishes the {@link JaasAuthenticationSuccessEvent}. Can be overridden by * subclasses for different functionality. - * * @param token The token being processed */ protected void publishSuccessEvent(UsernamePasswordAuthenticationToken token) { if (this.applicationEventPublisher != null) { - this.applicationEventPublisher - .publishEvent(new JaasAuthenticationSuccessEvent(token)); + this.applicationEventPublisher.publishEvent(new JaasAuthenticationSuccessEvent(token)); } } @@ -314,7 +298,6 @@ public abstract class AbstractJaasAuthenticationProvider * Returns the AuthorityGrannter array that was passed to the * {@link #setAuthorityGranters(AuthorityGranter[])} method, or null if it none were * ever set. - * * @return The AuthorityGranter array, or null * * @see #setAuthorityGranters(AuthorityGranter[]) @@ -326,7 +309,6 @@ public abstract class AbstractJaasAuthenticationProvider /** * Set the AuthorityGranters that should be consulted for role names to be granted to * the Authentication. - * * @param authorityGranters AuthorityGranter array * * @see JaasAuthenticationProvider @@ -338,7 +320,6 @@ public abstract class AbstractJaasAuthenticationProvider /** * Returns the current JaasAuthenticationCallbackHandler array, or null if none are * set. - * * @return the JAASAuthenticationCallbackHandlers. * * @see #setCallbackHandlers(JaasAuthenticationCallbackHandler[]) @@ -350,11 +331,9 @@ public abstract class AbstractJaasAuthenticationProvider /** * Set the JAASAuthentcationCallbackHandler array to handle callback objects generated * by the LoginContext.login method. - * * @param callbackHandlers Array of JAASAuthenticationCallbackHandlers */ - public void setCallbackHandlers( - JaasAuthenticationCallbackHandler[] callbackHandlers) { + public void setCallbackHandlers(JaasAuthenticationCallbackHandler[] callbackHandlers) { this.callbackHandlers = callbackHandlers; } @@ -365,7 +344,6 @@ public abstract class AbstractJaasAuthenticationProvider /** * Set the loginContextName, this name is used as the index to the configuration * specified in the loginConfig property. - * * @param loginContextName */ public void setLoginContextName(String loginContextName) { @@ -384,8 +362,7 @@ public abstract class AbstractJaasAuthenticationProvider return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass); } - public void setApplicationEventPublisher( - ApplicationEventPublisher applicationEventPublisher) { + public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } @@ -400,19 +377,21 @@ public abstract class AbstractJaasAuthenticationProvider * Wrapper class for JAASAuthenticationCallbackHandlers */ private class InternalCallbackHandler implements CallbackHandler { + private final Authentication authentication; InternalCallbackHandler(Authentication authentication) { this.authentication = authentication; } - public void handle(Callback[] callbacks) - throws IOException, UnsupportedCallbackException { + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (JaasAuthenticationCallbackHandler handler : AbstractJaasAuthenticationProvider.this.callbackHandlers) { for (Callback callback : callbacks) { handler.handle(callback, this.authentication); } } } + } + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/AuthorityGranter.java b/core/src/main/java/org/springframework/security/authentication/jaas/AuthorityGranter.java index f0eb9f1440..14f0961d8e 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/AuthorityGranter.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/AuthorityGranter.java @@ -30,6 +30,7 @@ import java.util.Set; * @author Ray Krueger */ public interface AuthorityGranter { + // ~ Methods // ======================================================================================================== @@ -41,12 +42,11 @@ public interface AuthorityGranter { *

      * The set may contain any object as all objects in the returned set will be passed to * the JaasGrantedAuthority constructor using toString(). - * * @param principal One of the principals from the * LoginContext.getSubect().getPrincipals() method. - * * @return the role names to grant, or null, meaning no roles should be granted to the * principal. */ Set grant(Principal principal); + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/DefaultJaasAuthenticationProvider.java b/core/src/main/java/org/springframework/security/authentication/jaas/DefaultJaasAuthenticationProvider.java index 379a70c08b..8e865213ad 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/DefaultJaasAuthenticationProvider.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/DefaultJaasAuthenticationProvider.java @@ -84,8 +84,8 @@ import org.springframework.util.Assert; * @see AbstractJaasAuthenticationProvider * @see InMemoryConfiguration */ -public class DefaultJaasAuthenticationProvider - extends AbstractJaasAuthenticationProvider { +public class DefaultJaasAuthenticationProvider extends AbstractJaasAuthenticationProvider { + // ~ Instance fields // ================================================================================================ @@ -105,8 +105,7 @@ public class DefaultJaasAuthenticationProvider * {@link #setConfiguration(Configuration)}. */ @Override - protected LoginContext createLoginContext(CallbackHandler handler) - throws LoginException { + protected LoginContext createLoginContext(CallbackHandler handler) throws LoginException { return new LoginContext(getLoginContextName(), null, handler, getConfiguration()); } @@ -116,11 +115,11 @@ public class DefaultJaasAuthenticationProvider /** * Sets the Configuration to use for Authentication. - * * @param configuration the Configuration that is used when * {@link #createLoginContext(CallbackHandler)} is called. */ public void setConfiguration(Configuration configuration) { this.configuration = configuration; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/DefaultLoginExceptionResolver.java b/core/src/main/java/org/springframework/security/authentication/jaas/DefaultLoginExceptionResolver.java index 3f43cb325a..82d978dc3a 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/DefaultLoginExceptionResolver.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/DefaultLoginExceptionResolver.java @@ -28,10 +28,12 @@ import javax.security.auth.login.LoginException; * @author Ray Krueger */ public class DefaultLoginExceptionResolver implements LoginExceptionResolver { + // ~ Methods // ======================================================================================================== public AuthenticationException resolveException(LoginException e) { return new AuthenticationServiceException(e.getMessage(), e); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationCallbackHandler.java b/core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationCallbackHandler.java index 070ba6599f..703ecb732c 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationCallbackHandler.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationCallbackHandler.java @@ -26,8 +26,8 @@ import org.springframework.security.core.Authentication; * The JaasAuthenticationCallbackHandler is similar to the * javax.security.auth.callback.CallbackHandler interface in that it defines a handle * method. The JaasAuthenticationCallbackHandler is only asked to handle one Callback - * instance at time rather than an array of all Callbacks, as the javax... - * CallbackHandler defines. + * instance at time rather than an array of all Callbacks, as the javax... CallbackHandler + * defines. * *

      * Before a JaasAuthenticationCallbackHandler is asked to 'handle' any callbacks, it is @@ -36,16 +36,16 @@ import org.springframework.security.core.Authentication; *

      * * @author Ray Krueger - * * @see JaasNameCallbackHandler * @see JaasPasswordCallbackHandler - * @see Callback - * @see + * @see Callback + * @see * CallbackHandler */ public interface JaasAuthenticationCallbackHandler { + // ~ Methods // ======================================================================================================== @@ -55,11 +55,10 @@ public interface JaasAuthenticationCallbackHandler { * >Callback. The handle method will be called for every callback instance sent * from the LoginContext. Meaning that The handle method may be called multiple times * for a given JaasAuthenticationCallbackHandler. - * * @param callback * @param auth The Authentication object currently being authenticated. * */ - void handle(Callback callback, Authentication auth) throws IOException, - UnsupportedCallbackException; + void handle(Callback callback, Authentication auth) throws IOException, UnsupportedCallbackException; + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationProvider.java b/core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationProvider.java index 34a3f231ee..4061a9216b 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationProvider.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationProvider.java @@ -84,8 +84,8 @@ import org.springframework.util.Assert; * *

      * When using JAAS login modules as the authentication source, sometimes the - * LoginContext will require CallbackHandlers. The JaasAuthenticationProvider + * "https://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/login/LoginContext.html" + * > LoginContext will require CallbackHandlers. The JaasAuthenticationProvider * uses an internal CallbackHandler to wrap the {@link JaasAuthenticationCallbackHandler}s configured @@ -138,6 +138,7 @@ import org.springframework.util.Assert; * @author Rob Winch */ public class JaasAuthenticationProvider extends AbstractJaasAuthenticationProvider { + // ~ Static fields/initializers // ===================================================================================== @@ -148,6 +149,7 @@ public class JaasAuthenticationProvider extends AbstractJaasAuthenticationProvid // ================================================================================================ private Resource loginConfig; + private boolean refreshConfigurationOnStartup = true; // ~ Methods @@ -157,10 +159,8 @@ public class JaasAuthenticationProvider extends AbstractJaasAuthenticationProvid public void afterPropertiesSet() throws Exception { // the superclass is not called because it does additional checks that are // non-passive - Assert.hasLength(getLoginContextName(), - () -> "loginContextName must be set on " + getClass()); - Assert.notNull(this.loginConfig, - () -> "loginConfig must be set on " + getClass()); + Assert.hasLength(getLoginContextName(), () -> "loginContextName must be set on " + getClass()); + Assert.notNull(this.loginConfig, () -> "loginConfig must be set on " + getClass()); configureJaas(this.loginConfig); Assert.notNull(Configuration.getConfiguration(), @@ -171,16 +171,13 @@ public class JaasAuthenticationProvider extends AbstractJaasAuthenticationProvid } @Override - protected LoginContext createLoginContext(CallbackHandler handler) - throws LoginException { + protected LoginContext createLoginContext(CallbackHandler handler) throws LoginException { return new LoginContext(getLoginContextName(), handler); } /** * Hook method for configuring Jaas. - * * @param loginConfig URL to Jaas login configuration - * * @throws IOException if there is a problem reading the config resource. */ protected void configureJaas(Resource loginConfig) throws IOException { @@ -227,8 +224,7 @@ public class JaasAuthenticationProvider extends AbstractJaasAuthenticationProvid String loginConfigPath; try { - loginConfigPath = this.loginConfig.getFile().getAbsolutePath() - .replace(File.separatorChar, '/'); + loginConfigPath = this.loginConfig.getFile().getAbsolutePath().replace(File.separatorChar, '/'); if (!loginConfigPath.startsWith("/")) { loginConfigPath = "/" + loginConfigPath; @@ -245,16 +241,13 @@ public class JaasAuthenticationProvider extends AbstractJaasAuthenticationProvid /** * Publishes the {@link JaasAuthenticationFailedEvent}. Can be overridden by * subclasses for different functionality - * * @param token The authentication token being processed * @param ase The excetion that caused the authentication failure */ @Override - protected void publishFailureEvent(UsernamePasswordAuthenticationToken token, - AuthenticationException ase) { + protected void publishFailureEvent(UsernamePasswordAuthenticationToken token, AuthenticationException ase) { // exists for passivity (the superclass does a null check before publishing) - getApplicationEventPublisher() - .publishEvent(new JaasAuthenticationFailedEvent(token, ase)); + getApplicationEventPublisher().publishEvent(new JaasAuthenticationFailedEvent(token, ase)); } public Resource getLoginConfig() { @@ -263,7 +256,6 @@ public class JaasAuthenticationProvider extends AbstractJaasAuthenticationProvid /** * Set the JAAS login configuration file. - * * @param loginConfig * * @see SEC-1320 - * * @param refresh set to {@code false} to disable reloading of the configuration. May * be useful in some environments. */ public void setRefreshConfigurationOnStartup(boolean refresh) { this.refreshConfigurationOnStartup = refresh; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationToken.java b/core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationToken.java index ced47d245f..9bb3bcc5a9 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationToken.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/JaasAuthenticationToken.java @@ -42,14 +42,13 @@ public class JaasAuthenticationToken extends UsernamePasswordAuthenticationToken // ~ Constructors // =================================================================================================== - public JaasAuthenticationToken(Object principal, Object credentials, - LoginContext loginContext) { + public JaasAuthenticationToken(Object principal, Object credentials, LoginContext loginContext) { super(principal, credentials); this.loginContext = loginContext; } - public JaasAuthenticationToken(Object principal, Object credentials, - List authorities, LoginContext loginContext) { + public JaasAuthenticationToken(Object principal, Object credentials, List authorities, + LoginContext loginContext) { super(principal, credentials, authorities); this.loginContext = loginContext; } @@ -60,4 +59,5 @@ public class JaasAuthenticationToken extends UsernamePasswordAuthenticationToken public LoginContext getLoginContext() { return loginContext; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/JaasGrantedAuthority.java b/core/src/main/java/org/springframework/security/authentication/jaas/JaasGrantedAuthority.java index d6fc0b9a4f..11998cf379 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/JaasGrantedAuthority.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/JaasGrantedAuthority.java @@ -27,7 +27,6 @@ import java.security.Principal; * that an {@link AuthorityGranter} used as a reason to grant this authority. * * @author Ray Krueger - * * @see AuthorityGranter */ public final class JaasGrantedAuthority implements GrantedAuthority { @@ -35,6 +34,7 @@ public final class JaasGrantedAuthority implements GrantedAuthority { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private final String role; + private final Principal principal; public JaasGrantedAuthority(String role, Principal principal) { @@ -81,4 +81,5 @@ public final class JaasGrantedAuthority implements GrantedAuthority { public String toString() { return "Jaas Authority [" + role + "," + principal + "]"; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/JaasNameCallbackHandler.java b/core/src/main/java/org/springframework/security/authentication/jaas/JaasNameCallbackHandler.java index 2a53197e64..40413bdfb1 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/JaasNameCallbackHandler.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/JaasNameCallbackHandler.java @@ -28,13 +28,13 @@ import javax.security.auth.callback.NameCallback; * specifically tailored to handling the NameCallback.
      * * @author Ray Krueger - * - * @see Callback - * @see NameCallback + * @see Callback + * @see NameCallback */ public class JaasNameCallbackHandler implements JaasAuthenticationCallbackHandler { + // ~ Methods // ======================================================================================================== @@ -42,7 +42,6 @@ public class JaasNameCallbackHandler implements JaasAuthenticationCallbackHandle * If the callback passed to the 'handle' method is an instance of NameCallback, the * JaasNameCallbackHandler will call, * callback.setName(authentication.getPrincipal().toString()). - * * @param callback * @param authentication * @@ -64,4 +63,5 @@ public class JaasNameCallbackHandler implements JaasAuthenticationCallbackHandle ncb.setName(username); } } + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/JaasPasswordCallbackHandler.java b/core/src/main/java/org/springframework/security/authentication/jaas/JaasPasswordCallbackHandler.java index c42f392a57..4db830daaa 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/JaasPasswordCallbackHandler.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/JaasPasswordCallbackHandler.java @@ -24,17 +24,18 @@ import javax.security.auth.callback.PasswordCallback; /** * The most basic Callbacks to be handled when using a LoginContext from JAAS, are the * NameCallback and PasswordCallback. Spring Security provides the - * JaasPasswordCallbackHandler specifically tailored to handling the PasswordCallback.
      + * JaasPasswordCallbackHandler specifically tailored to handling the PasswordCallback. + *
      * * @author Ray Krueger - * - * @see Callback - * @see + * @see Callback + * @see * PasswordCallback */ public class JaasPasswordCallbackHandler implements JaasAuthenticationCallbackHandler { + // ~ Methods // ======================================================================================================== @@ -42,7 +43,6 @@ public class JaasPasswordCallbackHandler implements JaasAuthenticationCallbackHa * If the callback passed to the 'handle' method is an instance of PasswordCallback, * the JaasPasswordCallbackHandler will call, * callback.setPassword(authentication.getCredentials().toString()). - * * @param callback * @param auth * @@ -53,4 +53,5 @@ public class JaasPasswordCallbackHandler implements JaasAuthenticationCallbackHa pc.setPassword(auth.getCredentials().toString().toCharArray()); } } + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/LoginExceptionResolver.java b/core/src/main/java/org/springframework/security/authentication/jaas/LoginExceptionResolver.java index 5fc36f4b3c..63d36985a9 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/LoginExceptionResolver.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/LoginExceptionResolver.java @@ -31,16 +31,16 @@ import javax.security.auth.login.LoginException; * @author Ray Krueger */ public interface LoginExceptionResolver { + // ~ Methods // ======================================================================================================== /** * Translates a Jaas LoginException to an SpringSecurityException. - * * @param e The LoginException thrown by the configured LoginModule. - * * @return The AuthenticationException that the JaasAuthenticationProvider should * throw. */ AuthenticationException resolveException(LoginException e); + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/SecurityContextLoginModule.java b/core/src/main/java/org/springframework/security/authentication/jaas/SecurityContextLoginModule.java index 38756da657..14bc89cb7c 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/SecurityContextLoginModule.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/SecurityContextLoginModule.java @@ -52,6 +52,7 @@ import javax.security.auth.spi.LoginModule; * @author Ray Krueger */ public class SecurityContextLoginModule implements LoginModule { + // ~ Static fields/initializers // ===================================================================================== @@ -61,7 +62,9 @@ public class SecurityContextLoginModule implements LoginModule { // ================================================================================================ private Authentication authen; + private Subject subject; + private boolean ignoreMissingAuthentication = false; // ~ Methods @@ -70,10 +73,8 @@ public class SecurityContextLoginModule implements LoginModule { /** * Abort the authentication process by forgetting the Spring Security * Authentication. - * * @return true if this method succeeded, or false if this LoginModule * should be ignored. - * * @exception LoginException if the abort fails */ public boolean abort() { @@ -89,10 +90,8 @@ public class SecurityContextLoginModule implements LoginModule { /** * Authenticate the Subject (phase two) by adding the Spring Security * Authentication to the Subject's principals. - * * @return true if this method succeeded, or false if this LoginModule * should be ignored. - * * @exception LoginException if the commit fails */ public boolean commit() { @@ -118,30 +117,25 @@ public class SecurityContextLoginModule implements LoginModule { * code establishing the LoginContext likely won't provide one that * understands Spring Security. Also ignores the sharedState and * options parameters, since none are recognized. - * * @param subject the Subject to be authenticated. * @param callbackHandler is ignored * @param sharedState is ignored * @param options are ignored */ @SuppressWarnings("unchecked") - public void initialize(Subject subject, CallbackHandler callbackHandler, - Map sharedState, Map options) { + public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { this.subject = subject; if (options != null) { - ignoreMissingAuthentication = "true".equals(options - .get("ignoreMissingAuthentication")); + ignoreMissingAuthentication = "true".equals(options.get("ignoreMissingAuthentication")); } } /** * Authenticate the Subject (phase one) by extracting the Spring Security * Authentication from the current SecurityContext. - * * @return true if the authentication succeeded, or false if this * LoginModule should be ignored. - * * @throws LoginException if the authentication fails */ public boolean login() throws LoginException { @@ -165,10 +159,8 @@ public class SecurityContextLoginModule implements LoginModule { /** * Log out the Subject. - * * @return true if this method succeeded, or false if this LoginModule * should be ignored. - * * @exception LoginException if the logout fails */ public boolean logout() { @@ -181,4 +173,5 @@ public class SecurityContextLoginModule implements LoginModule { return true; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/event/JaasAuthenticationEvent.java b/core/src/main/java/org/springframework/security/authentication/jaas/event/JaasAuthenticationEvent.java index 2c3332d59b..8cedd283bd 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/event/JaasAuthenticationEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/event/JaasAuthenticationEvent.java @@ -28,12 +28,12 @@ import org.springframework.context.ApplicationEvent; * @author Ray Krueger */ public abstract class JaasAuthenticationEvent extends ApplicationEvent { + // ~ Constructors // =================================================================================================== /** * The Authentication object is stored as the ApplicationEvent 'source'. - * * @param auth */ public JaasAuthenticationEvent(Authentication auth) { @@ -45,10 +45,10 @@ public abstract class JaasAuthenticationEvent extends ApplicationEvent { /** * Pre-casted method that returns the 'source' of the event. - * * @return the Authentication */ public Authentication getAuthentication() { return (Authentication) source; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/event/JaasAuthenticationFailedEvent.java b/core/src/main/java/org/springframework/security/authentication/jaas/event/JaasAuthenticationFailedEvent.java index e3955c909f..ca92f0e548 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/event/JaasAuthenticationFailedEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/event/JaasAuthenticationFailedEvent.java @@ -25,6 +25,7 @@ import org.springframework.security.core.Authentication; * @author Ray Krueger */ public class JaasAuthenticationFailedEvent extends JaasAuthenticationEvent { + // ~ Instance fields // ================================================================================================ @@ -44,4 +45,5 @@ public class JaasAuthenticationFailedEvent extends JaasAuthenticationEvent { public Exception getException() { return exception; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/event/JaasAuthenticationSuccessEvent.java b/core/src/main/java/org/springframework/security/authentication/jaas/event/JaasAuthenticationSuccessEvent.java index f57d4ab35d..9d1690db92 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/event/JaasAuthenticationSuccessEvent.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/event/JaasAuthenticationSuccessEvent.java @@ -27,10 +27,12 @@ import org.springframework.security.core.Authentication; * @author Ray Krueger */ public class JaasAuthenticationSuccessEvent extends JaasAuthenticationEvent { + // ~ Constructors // =================================================================================================== public JaasAuthenticationSuccessEvent(Authentication auth) { super(auth); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/event/package-info.java b/core/src/main/java/org/springframework/security/authentication/jaas/event/package-info.java index 266efce2c0..a6d7946886 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/event/package-info.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/event/package-info.java @@ -14,8 +14,7 @@ * limitations under the License. */ /** - * JAAS authentication events which can be published to the Spring application context by the JAAS authentication - * provider. + * JAAS authentication events which can be published to the Spring application context by + * the JAAS authentication provider. */ package org.springframework.security.authentication.jaas.event; - diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/memory/InMemoryConfiguration.java b/core/src/main/java/org/springframework/security/authentication/jaas/memory/InMemoryConfiguration.java index 181b118b98..3bd86695a5 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/memory/InMemoryConfiguration.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/memory/InMemoryConfiguration.java @@ -35,10 +35,12 @@ import org.springframework.util.Assert; * @author Rob Winch */ public class InMemoryConfiguration extends Configuration { + // ~ Instance fields // ================================================================================================ private final AppConfigurationEntry[] defaultConfiguration; + private final Map mappedConfigurations; // ~ Constructors @@ -47,24 +49,20 @@ public class InMemoryConfiguration extends Configuration { /** * Creates a new instance with only a defaultConfiguration. Any configuration name * will result in defaultConfiguration being returned. - * * @param defaultConfiguration The result for any calls to * {@link #getAppConfigurationEntry(String)}. Can be null. */ public InMemoryConfiguration(AppConfigurationEntry[] defaultConfiguration) { - this(Collections.emptyMap(), - defaultConfiguration); + this(Collections.emptyMap(), defaultConfiguration); } /** * Creates a new instance with a mapping of login context name to an array of * {@link AppConfigurationEntry}s. - * * @param mappedConfigurations each key represents a login context name and each value * is an Array of {@link AppConfigurationEntry}s that should be used. */ - public InMemoryConfiguration( - Map mappedConfigurations) { + public InMemoryConfiguration(Map mappedConfigurations) { this(mappedConfigurations, null); } @@ -72,14 +70,12 @@ public class InMemoryConfiguration extends Configuration { * Creates a new instance with a mapping of login context name to an array of * {@link AppConfigurationEntry}s along with a default configuration that will be used * if no mapping is found for the given login context name. - * * @param mappedConfigurations each key represents a login context name and each value * is an Array of {@link AppConfigurationEntry}s that should be used. * @param defaultConfiguration The result for any calls to * {@link #getAppConfigurationEntry(String)}. Can be null. */ - public InMemoryConfiguration( - Map mappedConfigurations, + public InMemoryConfiguration(Map mappedConfigurations, AppConfigurationEntry[] defaultConfiguration) { Assert.notNull(mappedConfigurations, "mappedConfigurations cannot be null."); this.mappedConfigurations = mappedConfigurations; @@ -101,4 +97,5 @@ public class InMemoryConfiguration extends Configuration { @Override public void refresh() { } + } \ No newline at end of file diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/memory/package-info.java b/core/src/main/java/org/springframework/security/authentication/jaas/memory/package-info.java index 0657c03910..79662dcf5c 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/memory/package-info.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/memory/package-info.java @@ -17,4 +17,3 @@ * An in memory JAAS implementation. */ package org.springframework.security.authentication.jaas.memory; - diff --git a/core/src/main/java/org/springframework/security/authentication/jaas/package-info.java b/core/src/main/java/org/springframework/security/authentication/jaas/package-info.java index 3204025524..0362b02652 100644 --- a/core/src/main/java/org/springframework/security/authentication/jaas/package-info.java +++ b/core/src/main/java/org/springframework/security/authentication/jaas/package-info.java @@ -17,4 +17,3 @@ * An authentication provider for JAAS. */ package org.springframework.security.authentication.jaas; - diff --git a/core/src/main/java/org/springframework/security/authentication/package-info.java b/core/src/main/java/org/springframework/security/authentication/package-info.java index e56ab09664..a318d942e8 100644 --- a/core/src/main/java/org/springframework/security/authentication/package-info.java +++ b/core/src/main/java/org/springframework/security/authentication/package-info.java @@ -14,12 +14,15 @@ * limitations under the License. */ /** - * Core classes and interfaces related to user authentication, which are used throughout Spring Security. + * Core classes and interfaces related to user authentication, which are used throughout + * Spring Security. *

      - * Of key importance is the {@link org.springframework.security.authentication.AuthenticationManager AuthenticationManager} - * and its default implementation {@link org.springframework.security.authentication.ProviderManager - * ProviderManager}, which maintains a list {@link org.springframework.security.authentication.AuthenticationProvider + * Of key importance is the + * {@link org.springframework.security.authentication.AuthenticationManager + * AuthenticationManager} and its default implementation + * {@link org.springframework.security.authentication.ProviderManager ProviderManager}, + * which maintains a list + * {@link org.springframework.security.authentication.AuthenticationProvider * AuthenticationProvider}s to which it delegates authentication requests. */ package org.springframework.security.authentication; - diff --git a/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationException.java b/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationException.java index 8cb14cbdd3..7f44aaf305 100644 --- a/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationException.java +++ b/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationException.java @@ -39,10 +39,10 @@ public class RemoteAuthenticationException extends NestedRuntimeException { /** * Constructs a RemoteAuthenticationException with the specified message * and no root cause. - * * @param msg the detail message */ public RemoteAuthenticationException(String msg) { super(msg); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManager.java b/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManager.java index 4108468dfa..c0e1ac7a05 100644 --- a/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManager.java +++ b/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManager.java @@ -26,6 +26,7 @@ import org.springframework.security.core.GrantedAuthority; * @author Ben Alex */ public interface RemoteAuthenticationManager { + // ~ Methods // ======================================================================================================== @@ -39,15 +40,13 @@ public interface RemoteAuthenticationManager { * required for remote clients to enable/disable relevant user interface commands etc. * There is nothing preventing users from implementing their own equivalent package * that works with more complex object types. - * * @param username the username the remote client wishes to authenticate with. * @param password the password the remote client wishes to authenticate with. - * * @return all of the granted authorities the specified username and password have * access to. - * * @throws RemoteAuthenticationException if the authentication failed. */ - Collection attemptAuthentication(String username, - String password) throws RemoteAuthenticationException; + Collection attemptAuthentication(String username, String password) + throws RemoteAuthenticationException; + } diff --git a/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImpl.java b/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImpl.java index 35e1a6d556..2209d42436 100644 --- a/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImpl.java +++ b/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImpl.java @@ -33,8 +33,8 @@ import org.springframework.util.Assert; * * @author Ben Alex */ -public class RemoteAuthenticationManagerImpl implements RemoteAuthenticationManager, - InitializingBean { +public class RemoteAuthenticationManagerImpl implements RemoteAuthenticationManager, InitializingBean { + // ~ Instance fields // ================================================================================================ @@ -47,10 +47,9 @@ public class RemoteAuthenticationManagerImpl implements RemoteAuthenticationMana Assert.notNull(this.authenticationManager, "authenticationManager is required"); } - public Collection attemptAuthentication(String username, - String password) throws RemoteAuthenticationException { - UsernamePasswordAuthenticationToken request = new UsernamePasswordAuthenticationToken( - username, password); + public Collection attemptAuthentication(String username, String password) + throws RemoteAuthenticationException { + UsernamePasswordAuthenticationToken request = new UsernamePasswordAuthenticationToken(username, password); try { return authenticationManager.authenticate(request).getAuthorities(); @@ -67,4 +66,5 @@ public class RemoteAuthenticationManagerImpl implements RemoteAuthenticationMana public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } + } diff --git a/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationProvider.java b/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationProvider.java index 7e6b8c6b15..b105b1d21c 100644 --- a/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationProvider.java +++ b/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationProvider.java @@ -50,8 +50,8 @@ import org.springframework.util.Assert; * * @author Ben Alex */ -public class RemoteAuthenticationProvider implements AuthenticationProvider, - InitializingBean { +public class RemoteAuthenticationProvider implements AuthenticationProvider, InitializingBean { + // ~ Instance fields // ================================================================================================ @@ -61,17 +61,15 @@ public class RemoteAuthenticationProvider implements AuthenticationProvider, // ======================================================================================================== public void afterPropertiesSet() { - Assert.notNull(this.remoteAuthenticationManager, - "remoteAuthenticationManager is mandatory"); + Assert.notNull(this.remoteAuthenticationManager, "remoteAuthenticationManager is mandatory"); } - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getPrincipal().toString(); Object credentials = authentication.getCredentials(); String password = credentials == null ? null : credentials.toString(); - Collection authorities = remoteAuthenticationManager - .attemptAuthentication(username, password); + Collection authorities = remoteAuthenticationManager.attemptAuthentication(username, + password); return new UsernamePasswordAuthenticationToken(username, password, authorities); } @@ -80,13 +78,12 @@ public class RemoteAuthenticationProvider implements AuthenticationProvider, return remoteAuthenticationManager; } - public void setRemoteAuthenticationManager( - RemoteAuthenticationManager remoteAuthenticationManager) { + public void setRemoteAuthenticationManager(RemoteAuthenticationManager remoteAuthenticationManager) { this.remoteAuthenticationManager = remoteAuthenticationManager; } public boolean supports(Class authentication) { - return (UsernamePasswordAuthenticationToken.class - .isAssignableFrom(authentication)); + return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); } + } diff --git a/core/src/main/java/org/springframework/security/authentication/rcp/package-info.java b/core/src/main/java/org/springframework/security/authentication/rcp/package-info.java index 443fb72df3..f76b553f6f 100644 --- a/core/src/main/java/org/springframework/security/authentication/rcp/package-info.java +++ b/core/src/main/java/org/springframework/security/authentication/rcp/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Allows remote clients to authenticate and obtain a populated Authentication object. + * Allows remote clients to authenticate and obtain a populated + * Authentication object. */ package org.springframework.security.authentication.rcp; - diff --git a/core/src/main/java/org/springframework/security/authorization/AuthenticatedReactiveAuthorizationManager.java b/core/src/main/java/org/springframework/security/authorization/AuthenticatedReactiveAuthorizationManager.java index 8647f685fd..8a78190efa 100644 --- a/core/src/main/java/org/springframework/security/authorization/AuthenticatedReactiveAuthorizationManager.java +++ b/core/src/main/java/org/springframework/security/authorization/AuthenticatedReactiveAuthorizationManager.java @@ -36,14 +36,13 @@ public class AuthenticatedReactiveAuthorizationManager implements ReactiveAut @Override public Mono check(Mono authentication, T object) { - return authentication - .filter(this::isNotAnonymous) - .map(a -> new AuthorizationDecision(a.isAuthenticated())) - .defaultIfEmpty(new AuthorizationDecision(false)); + return authentication.filter(this::isNotAnonymous).map(a -> new AuthorizationDecision(a.isAuthenticated())) + .defaultIfEmpty(new AuthorizationDecision(false)); } /** - * Verify (via {@link AuthenticationTrustResolver}) that the given authentication is not anonymous. + * Verify (via {@link AuthenticationTrustResolver}) that the given authentication is + * not anonymous. * @param authentication to be checked * @return true if not anonymous, otherwise false. */ @@ -60,5 +59,7 @@ public class AuthenticatedReactiveAuthorizationManager implements ReactiveAut return new AuthenticatedReactiveAuthorizationManager<>(); } - private AuthenticatedReactiveAuthorizationManager() {} + private AuthenticatedReactiveAuthorizationManager() { + } + } diff --git a/core/src/main/java/org/springframework/security/authorization/AuthorityReactiveAuthorizationManager.java b/core/src/main/java/org/springframework/security/authorization/AuthorityReactiveAuthorizationManager.java index 5ab05c960c..31d85ebfb1 100644 --- a/core/src/main/java/org/springframework/security/authorization/AuthorityReactiveAuthorizationManager.java +++ b/core/src/main/java/org/springframework/security/authorization/AuthorityReactiveAuthorizationManager.java @@ -32,6 +32,7 @@ import java.util.List; * @param the type of object being authorized */ public class AuthorityReactiveAuthorizationManager implements ReactiveAuthorizationManager { + private final List authorities; private AuthorityReactiveAuthorizationManager(String... authorities) { @@ -40,19 +41,15 @@ public class AuthorityReactiveAuthorizationManager implements ReactiveAuthori @Override public Mono check(Mono authentication, T object) { - return authentication - .filter(a -> a.isAuthenticated()) - .flatMapIterable( a -> a.getAuthorities()) - .map(g -> g.getAuthority()) - .any(a -> this.authorities.contains(a)) - .map( hasAuthority -> new AuthorizationDecision(hasAuthority)) - .defaultIfEmpty(new AuthorizationDecision(false)); + return authentication.filter(a -> a.isAuthenticated()).flatMapIterable(a -> a.getAuthorities()) + .map(g -> g.getAuthority()).any(a -> this.authorities.contains(a)) + .map(hasAuthority -> new AuthorizationDecision(hasAuthority)) + .defaultIfEmpty(new AuthorizationDecision(false)); } /** * Creates an instance of {@link AuthorityReactiveAuthorizationManager} with the * provided authority. - * * @param authority the authority to check for * @param the type of object being authorized * @return the new instance @@ -83,7 +80,6 @@ public class AuthorityReactiveAuthorizationManager implements ReactiveAuthori /** * Creates an instance of {@link AuthorityReactiveAuthorizationManager} with the * provided authority. - * * @param role the authority to check for prefixed with "ROLE_" * @param the type of object being authorized * @return the new instance @@ -113,9 +109,10 @@ public class AuthorityReactiveAuthorizationManager implements ReactiveAuthori private static String[] toNamedRolesArray(String... roles) { String[] result = new String[roles.length]; - for (int i=0; i < roles.length; i++) { + for (int i = 0; i < roles.length; i++) { result[i] = "ROLE_" + roles[i]; } return result; } + } diff --git a/core/src/main/java/org/springframework/security/authorization/AuthorizationDecision.java b/core/src/main/java/org/springframework/security/authorization/AuthorizationDecision.java index 08fdf7a92d..2ad6b7cf33 100644 --- a/core/src/main/java/org/springframework/security/authorization/AuthorizationDecision.java +++ b/core/src/main/java/org/springframework/security/authorization/AuthorizationDecision.java @@ -21,6 +21,7 @@ package org.springframework.security.authorization; * @since 5.0 */ public class AuthorizationDecision { + private final boolean granted; public AuthorizationDecision(boolean granted) { @@ -30,4 +31,5 @@ public class AuthorizationDecision { public boolean isGranted() { return granted; } + } diff --git a/core/src/main/java/org/springframework/security/authorization/ReactiveAuthorizationManager.java b/core/src/main/java/org/springframework/security/authorization/ReactiveAuthorizationManager.java index 6686658cbc..92522b9e7a 100644 --- a/core/src/main/java/org/springframework/security/authorization/ReactiveAuthorizationManager.java +++ b/core/src/main/java/org/springframework/security/authorization/ReactiveAuthorizationManager.java @@ -21,17 +21,17 @@ import org.springframework.security.core.Authentication; import reactor.core.publisher.Mono; /** - * A reactive authorization manager which can determine if an {@link Authentication} - * has access to a specific object. + * A reactive authorization manager which can determine if an {@link Authentication} has + * access to a specific object. * * @author Rob Winch * @since 5.0 * @param the type of object that the authorization check is being done one. */ public interface ReactiveAuthorizationManager { + /** * Determines if access is granted for a specific authentication and object. - * * @param authentication the Authentication to check * @param object the object to check * @return an decision or empty Mono if no decision could be made. @@ -40,17 +40,15 @@ public interface ReactiveAuthorizationManager { /** * Determines if access should be granted for a specific authentication and object - * - * @param authentication the Authentication to check * @param object the object to check * @return an empty Mono if authorization is granted or a Mono error if access is * denied */ default Mono verify(Mono authentication, T object) { - return check(authentication, object) - .filter( d -> d.isGranted()) - .switchIfEmpty(Mono.defer(() -> Mono.error(new AccessDeniedException("Access Denied")))) - .flatMap( d -> Mono.empty() ); + return check(authentication, object).filter(d -> d.isGranted()) + .switchIfEmpty(Mono.defer(() -> Mono.error(new AccessDeniedException("Access Denied")))) + .flatMap(d -> Mono.empty()); } + } diff --git a/core/src/main/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextSupport.java b/core/src/main/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextSupport.java index 7cc9a342d8..ea3d40857c 100644 --- a/core/src/main/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextSupport.java +++ b/core/src/main/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextSupport.java @@ -34,7 +34,6 @@ abstract class AbstractDelegatingSecurityContextSupport { /** * Creates a new {@link AbstractDelegatingSecurityContextSupport} that uses the * specified {@link SecurityContext}. - * * @param securityContext the {@link SecurityContext} to use for each * {@link DelegatingSecurityContextRunnable} and each * {@link DelegatingSecurityContextCallable} or null to default to the current @@ -51,4 +50,5 @@ abstract class AbstractDelegatingSecurityContextSupport { protected final Callable wrap(Callable delegate) { return DelegatingSecurityContextCallable.create(delegate, securityContext); } + } diff --git a/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextCallable.java b/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextCallable.java index d65272ec5d..9b4934feb6 100644 --- a/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextCallable.java +++ b/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextCallable.java @@ -23,13 +23,13 @@ import org.springframework.util.Assert; /** *

      - * Wraps a delegate {@link Callable} with logic for setting up a - * {@link SecurityContext} before invoking the delegate {@link Callable} and - * then removing the {@link SecurityContext} after the delegate has completed. + * Wraps a delegate {@link Callable} with logic for setting up a {@link SecurityContext} + * before invoking the delegate {@link Callable} and then removing the + * {@link SecurityContext} after the delegate has completed. *

      *

      - * If there is a {@link SecurityContext} that already exists, it will be - * restored after the {@link #call()} method is invoked. + * If there is a {@link SecurityContext} that already exists, it will be restored after + * the {@link #call()} method is invoked. *

      * * @author Rob Winch @@ -39,16 +39,14 @@ public final class DelegatingSecurityContextCallable implements Callable { private final Callable delegate; - /** - * The {@link SecurityContext} that the delegate {@link Callable} will be - * ran as. + * The {@link SecurityContext} that the delegate {@link Callable} will be ran as. */ private final SecurityContext delegateSecurityContext; /** - * The {@link SecurityContext} that was on the {@link SecurityContextHolder} - * prior to being set to the delegateSecurityContext. + * The {@link SecurityContext} that was on the {@link SecurityContextHolder} prior to + * being set to the delegateSecurityContext. */ private SecurityContext originalSecurityContext; @@ -60,8 +58,7 @@ public final class DelegatingSecurityContextCallable implements Callable { * @param securityContext the {@link SecurityContext} to establish for the delegate * {@link Callable}. Cannot be null. */ - public DelegatingSecurityContextCallable(Callable delegate, - SecurityContext securityContext) { + public DelegatingSecurityContextCallable(Callable delegate, SecurityContext securityContext) { Assert.notNull(delegate, "delegate cannot be null"); Assert.notNull(securityContext, "securityContext cannot be null"); this.delegate = delegate; @@ -90,7 +87,8 @@ public final class DelegatingSecurityContextCallable implements Callable { SecurityContext emptyContext = SecurityContextHolder.createEmptyContext(); if (emptyContext.equals(originalSecurityContext)) { SecurityContextHolder.clearContext(); - } else { + } + else { SecurityContextHolder.setContext(originalSecurityContext); } this.originalSecurityContext = null; @@ -107,17 +105,15 @@ public final class DelegatingSecurityContextCallable implements Callable { * {@link Callable} and {@link SecurityContext}, but if the securityContext is null * will defaults to the current {@link SecurityContext} on the * {@link SecurityContextHolder} - * * @param delegate the delegate {@link DelegatingSecurityContextCallable} to run with * the specified {@link SecurityContext}. Cannot be null. * @param securityContext the {@link SecurityContext} to establish for the delegate * {@link Callable}. If null, defaults to {@link SecurityContextHolder#getContext()} * @return */ - public static Callable create(Callable delegate, - SecurityContext securityContext) { - return securityContext == null ? new DelegatingSecurityContextCallable<>( - delegate) : new DelegatingSecurityContextCallable<>(delegate, - securityContext); + public static Callable create(Callable delegate, SecurityContext securityContext) { + return securityContext == null ? new DelegatingSecurityContextCallable<>(delegate) + : new DelegatingSecurityContextCallable<>(delegate, securityContext); } + } diff --git a/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextExecutor.java b/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextExecutor.java index ba9c0a6217..9e55733767 100644 --- a/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextExecutor.java +++ b/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextExecutor.java @@ -28,21 +28,19 @@ import org.springframework.util.Assert; * @author Rob Winch * @since 3.2 */ -public class DelegatingSecurityContextExecutor extends - AbstractDelegatingSecurityContextSupport implements Executor { +public class DelegatingSecurityContextExecutor extends AbstractDelegatingSecurityContextSupport implements Executor { + private final Executor delegate; /** * Creates a new {@link DelegatingSecurityContextExecutor} that uses the specified * {@link SecurityContext}. - * * @param delegateExecutor the {@link Executor} to delegate to. Cannot be null. * @param securityContext the {@link SecurityContext} to use for each * {@link DelegatingSecurityContextRunnable} or null to default to the current * {@link SecurityContext} */ - public DelegatingSecurityContextExecutor(Executor delegateExecutor, - SecurityContext securityContext) { + public DelegatingSecurityContextExecutor(Executor delegateExecutor, SecurityContext securityContext) { super(securityContext); Assert.notNull(delegateExecutor, "delegateExecutor cannot be null"); this.delegate = delegateExecutor; @@ -52,7 +50,6 @@ public class DelegatingSecurityContextExecutor extends * Creates a new {@link DelegatingSecurityContextExecutor} that uses the current * {@link SecurityContext} from the {@link SecurityContextHolder} at the time the task * is submitted. - * * @param delegate the {@link Executor} to delegate to. Cannot be null. */ public DelegatingSecurityContextExecutor(Executor delegate) { @@ -67,4 +64,5 @@ public class DelegatingSecurityContextExecutor extends protected final Executor getDelegateExecutor() { return delegate; } + } \ No newline at end of file diff --git a/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextExecutorService.java b/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextExecutorService.java index 9f00bb4fab..db4a0b3cee 100644 --- a/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextExecutorService.java +++ b/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextExecutorService.java @@ -36,29 +36,27 @@ import org.springframework.security.core.context.SecurityContextHolder; * @author Rob Winch * @since 3.2 */ -public class DelegatingSecurityContextExecutorService extends - DelegatingSecurityContextExecutor implements ExecutorService { +public class DelegatingSecurityContextExecutorService extends DelegatingSecurityContextExecutor + implements ExecutorService { + /** * Creates a new {@link DelegatingSecurityContextExecutorService} that uses the * specified {@link SecurityContext}. - * * @param delegateExecutorService the {@link ExecutorService} to delegate to. Cannot * be null. * @param securityContext the {@link SecurityContext} to use for each * {@link DelegatingSecurityContextRunnable} and each * {@link DelegatingSecurityContextCallable}. */ - public DelegatingSecurityContextExecutorService( - ExecutorService delegateExecutorService, SecurityContext securityContext) { + public DelegatingSecurityContextExecutorService(ExecutorService delegateExecutorService, + SecurityContext securityContext) { super(delegateExecutorService, securityContext); } /** * Creates a new {@link DelegatingSecurityContextExecutorService} that uses the * current {@link SecurityContext} from the {@link SecurityContextHolder}. - * - * @param delegate the {@link ExecutorService} to delegate to. Cannot be - * null. + * @param delegate the {@link ExecutorService} to delegate to. Cannot be null. */ public DelegatingSecurityContextExecutorService(ExecutorService delegate) { this(delegate, null); @@ -80,8 +78,7 @@ public class DelegatingSecurityContextExecutorService extends return getDelegate().isTerminated(); } - public final boolean awaitTermination(long timeout, TimeUnit unit) - throws InterruptedException { + public final boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { return getDelegate().awaitTermination(timeout, unit); } @@ -107,15 +104,13 @@ public class DelegatingSecurityContextExecutorService extends } @SuppressWarnings({ "rawtypes", "unchecked" }) - public final List invokeAll(Collection tasks, long timeout, TimeUnit unit) - throws InterruptedException { + public final List invokeAll(Collection tasks, long timeout, TimeUnit unit) throws InterruptedException { tasks = createTasks(tasks); return getDelegate().invokeAll(tasks, timeout, unit); } @SuppressWarnings({ "rawtypes", "unchecked" }) - public final Object invokeAny(Collection tasks) throws InterruptedException, - ExecutionException { + public final Object invokeAny(Collection tasks) throws InterruptedException, ExecutionException { tasks = createTasks(tasks); return getDelegate().invokeAny(tasks); } @@ -141,4 +136,5 @@ public class DelegatingSecurityContextExecutorService extends private ExecutorService getDelegate() { return (ExecutorService) getDelegateExecutor(); } + } diff --git a/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextRunnable.java b/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextRunnable.java index addba8cfd9..e4cbd752f6 100644 --- a/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextRunnable.java +++ b/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextRunnable.java @@ -26,8 +26,8 @@ import org.springframework.util.Assert; * {@link SecurityContext} after the delegate has completed. *

      *

      - * If there is a {@link SecurityContext} that already exists, it will be - * restored after the {@link #run()} method is invoked. + * If there is a {@link SecurityContext} that already exists, it will be restored after + * the {@link #run()} method is invoked. *

      * * @author Rob Winch @@ -38,14 +38,13 @@ public final class DelegatingSecurityContextRunnable implements Runnable { private final Runnable delegate; /** - * The {@link SecurityContext} that the delegate {@link Runnable} will be - * ran as. + * The {@link SecurityContext} that the delegate {@link Runnable} will be ran as. */ private final SecurityContext delegateSecurityContext; /** - * The {@link SecurityContext} that was on the {@link SecurityContextHolder} - * prior to being set to the delegateSecurityContext. + * The {@link SecurityContext} that was on the {@link SecurityContextHolder} prior to + * being set to the delegateSecurityContext. */ private SecurityContext originalSecurityContext; @@ -57,8 +56,7 @@ public final class DelegatingSecurityContextRunnable implements Runnable { * @param securityContext the {@link SecurityContext} to establish for the delegate * {@link Runnable}. Cannot be null. */ - public DelegatingSecurityContextRunnable(Runnable delegate, - SecurityContext securityContext) { + public DelegatingSecurityContextRunnable(Runnable delegate, SecurityContext securityContext) { Assert.notNull(delegate, "delegate cannot be null"); Assert.notNull(securityContext, "securityContext cannot be null"); this.delegate = delegate; @@ -87,7 +85,8 @@ public final class DelegatingSecurityContextRunnable implements Runnable { SecurityContext emptyContext = SecurityContextHolder.createEmptyContext(); if (emptyContext.equals(originalSecurityContext)) { SecurityContextHolder.clearContext(); - } else { + } + else { SecurityContextHolder.setContext(originalSecurityContext); } this.originalSecurityContext = null; @@ -101,7 +100,6 @@ public final class DelegatingSecurityContextRunnable implements Runnable { /** * Factory method for creating a {@link DelegatingSecurityContextRunnable}. - * * @param delegate the original {@link Runnable} that will be delegated to after * establishing a {@link SecurityContext} on the {@link SecurityContextHolder}. Cannot * have null. @@ -115,4 +113,5 @@ public final class DelegatingSecurityContextRunnable implements Runnable { return securityContext == null ? new DelegatingSecurityContextRunnable(delegate) : new DelegatingSecurityContextRunnable(delegate, securityContext); } + } diff --git a/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextScheduledExecutorService.java b/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextScheduledExecutorService.java index f58fc68989..b88c4a3b1b 100644 --- a/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextScheduledExecutorService.java +++ b/core/src/main/java/org/springframework/security/concurrent/DelegatingSecurityContextScheduledExecutorService.java @@ -31,20 +31,19 @@ import org.springframework.security.core.context.SecurityContextHolder; * @author Rob Winch * @since 3.2 */ -public final class DelegatingSecurityContextScheduledExecutorService extends - DelegatingSecurityContextExecutorService implements ScheduledExecutorService { +public final class DelegatingSecurityContextScheduledExecutorService extends DelegatingSecurityContextExecutorService + implements ScheduledExecutorService { + /** * Creates a new {@link DelegatingSecurityContextScheduledExecutorService} that uses * the specified {@link SecurityContext}. - * * @param delegateScheduledExecutorService the {@link ScheduledExecutorService} to * delegate to. Cannot be null. * @param securityContext the {@link SecurityContext} to use for each * {@link DelegatingSecurityContextRunnable} and each * {@link DelegatingSecurityContextCallable}. */ - public DelegatingSecurityContextScheduledExecutorService( - ScheduledExecutorService delegateScheduledExecutorService, + public DelegatingSecurityContextScheduledExecutorService(ScheduledExecutorService delegateScheduledExecutorService, SecurityContext securityContext) { super(delegateScheduledExecutorService, securityContext); } @@ -52,12 +51,10 @@ public final class DelegatingSecurityContextScheduledExecutorService extends /** * Creates a new {@link DelegatingSecurityContextScheduledExecutorService} that uses * the current {@link SecurityContext} from the {@link SecurityContextHolder}. - * * @param delegate the {@link ScheduledExecutorService} to delegate to. Cannot be * null. */ - public DelegatingSecurityContextScheduledExecutorService( - ScheduledExecutorService delegate) { + public DelegatingSecurityContextScheduledExecutorService(ScheduledExecutorService delegate) { this(delegate, null); } @@ -66,20 +63,17 @@ public final class DelegatingSecurityContextScheduledExecutorService extends return getDelegate().schedule(command, delay, unit); } - public ScheduledFuture schedule(Callable callable, long delay, - TimeUnit unit) { + public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { callable = wrap(callable); return getDelegate().schedule(callable, delay, unit); } - public ScheduledFuture scheduleAtFixedRate(Runnable command, - long initialDelay, long period, TimeUnit unit) { + public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { command = wrap(command); return getDelegate().scheduleAtFixedRate(command, initialDelay, period, unit); } - public ScheduledFuture scheduleWithFixedDelay(Runnable command, - long initialDelay, long delay, TimeUnit unit) { + public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { command = wrap(command); return getDelegate().scheduleWithFixedDelay(command, initialDelay, delay, unit); } @@ -87,4 +81,5 @@ public final class DelegatingSecurityContextScheduledExecutorService extends private ScheduledExecutorService getDelegate() { return (ScheduledExecutorService) getDelegateExecutor(); } + } diff --git a/core/src/main/java/org/springframework/security/context/DelegatingApplicationListener.java b/core/src/main/java/org/springframework/security/context/DelegatingApplicationListener.java index b1341a91df..331741fc8f 100644 --- a/core/src/main/java/org/springframework/security/context/DelegatingApplicationListener.java +++ b/core/src/main/java/org/springframework/security/context/DelegatingApplicationListener.java @@ -30,8 +30,8 @@ import java.util.concurrent.CopyOnWriteArrayList; * * @author Rob Winch */ -public final class DelegatingApplicationListener implements - ApplicationListener { +public final class DelegatingApplicationListener implements ApplicationListener { + private List listeners = new CopyOnWriteArrayList<>(); public void onApplicationEvent(ApplicationEvent event) { @@ -49,13 +49,12 @@ public final class DelegatingApplicationListener implements /** * Adds a new SmartApplicationListener to use. - * * @param smartApplicationListener the SmartApplicationListener to use. Cannot be * null. */ public void addListener(SmartApplicationListener smartApplicationListener) { - Assert.notNull(smartApplicationListener, - "smartApplicationListener cannot be null"); + Assert.notNull(smartApplicationListener, "smartApplicationListener cannot be null"); listeners.add(smartApplicationListener); } + } diff --git a/core/src/main/java/org/springframework/security/converter/RsaKeyConverters.java b/core/src/main/java/org/springframework/security/converter/RsaKeyConverters.java index c0aeb2a53d..79df65af8a 100644 --- a/core/src/main/java/org/springframework/security/converter/RsaKeyConverters.java +++ b/core/src/main/java/org/springframework/security/converter/RsaKeyConverters.java @@ -39,33 +39,38 @@ import org.springframework.util.Assert; * @since 5.2 */ public class RsaKeyConverters { + private static final String DASHES = "-----"; + private static final String PKCS8_PEM_HEADER = DASHES + "BEGIN PRIVATE KEY" + DASHES; + private static final String PKCS8_PEM_FOOTER = DASHES + "END PRIVATE KEY" + DASHES; + private static final String X509_PEM_HEADER = DASHES + "BEGIN PUBLIC KEY" + DASHES; + private static final String X509_PEM_FOOTER = DASHES + "END PUBLIC KEY" + DASHES; /** * Construct a {@link Converter} for converting a PEM-encoded PKCS#8 RSA Private Key * into a {@link RSAPrivateKey}. * - * Note that keys are often formatted in PKCS#1 and this can easily be identified by the header. - * If the key file begins with "-----BEGIN RSA PRIVATE KEY-----", then it is PKCS#1. If it is - * PKCS#8 formatted, then it begins with "-----BEGIN PRIVATE KEY-----". + * Note that keys are often formatted in PKCS#1 and this can easily be identified by + * the header. If the key file begins with "-----BEGIN RSA PRIVATE KEY-----", then it + * is PKCS#1. If it is PKCS#8 formatted, then it begins with "-----BEGIN PRIVATE + * KEY-----". * - * This converter does not close the {@link InputStream} in order to avoid making non-portable - * assumptions about the streams' origin and further use. - * - * @return A {@link Converter} that can read a PEM-encoded PKCS#8 RSA Private Key and return a - * {@link RSAPrivateKey}. + * This converter does not close the {@link InputStream} in order to avoid making + * non-portable assumptions about the streams' origin and further use. + * @return A {@link Converter} that can read a PEM-encoded PKCS#8 RSA Private Key and + * return a {@link RSAPrivateKey}. */ public static Converter pkcs8() { KeyFactory keyFactory = rsaFactory(); return source -> { List lines = readAllLines(source); Assert.isTrue(!lines.isEmpty() && lines.get(0).startsWith(PKCS8_PEM_HEADER), - "Key is not in PEM-encoded PKCS#8 format, " + - "please check that the header begins with -----" + PKCS8_PEM_HEADER + "-----"); + "Key is not in PEM-encoded PKCS#8 format, " + "please check that the header begins with -----" + + PKCS8_PEM_HEADER + "-----"); StringBuilder base64Encoded = new StringBuilder(); for (String line : lines) { if (RsaKeyConverters.isNotPkcs8Wrapper(line)) { @@ -75,9 +80,9 @@ public class RsaKeyConverters { byte[] pkcs8 = Base64.getDecoder().decode(base64Encoded.toString()); try { - return (RSAPrivateKey) keyFactory.generatePrivate( - new PKCS8EncodedKeySpec(pkcs8)); - } catch (Exception e) { + return (RSAPrivateKey) keyFactory.generatePrivate(new PKCS8EncodedKeySpec(pkcs8)); + } + catch (Exception e) { throw new IllegalArgumentException(e); } }; @@ -87,19 +92,18 @@ public class RsaKeyConverters { * Construct a {@link Converter} for converting a PEM-encoded X.509 RSA Public Key * into a {@link RSAPublicKey}. * - * This converter does not close the {@link InputStream} in order to avoid making non-portable - * assumptions about the streams' origin and further use. - * - * @return A {@link Converter} that can read a PEM-encoded X.509 RSA Public Key and return a - * {@link RSAPublicKey}. + * This converter does not close the {@link InputStream} in order to avoid making + * non-portable assumptions about the streams' origin and further use. + * @return A {@link Converter} that can read a PEM-encoded X.509 RSA Public Key and + * return a {@link RSAPublicKey}. */ public static Converter x509() { KeyFactory keyFactory = rsaFactory(); return source -> { List lines = readAllLines(source); Assert.isTrue(!lines.isEmpty() && lines.get(0).startsWith(X509_PEM_HEADER), - "Key is not in PEM-encoded X.509 format, " + - "please check that the header begins with -----" + X509_PEM_HEADER + "-----"); + "Key is not in PEM-encoded X.509 format, " + "please check that the header begins with -----" + + X509_PEM_HEADER + "-----"); StringBuilder base64Encoded = new StringBuilder(); for (String line : lines) { if (RsaKeyConverters.isNotX509Wrapper(line)) { @@ -109,9 +113,9 @@ public class RsaKeyConverters { byte[] x509 = Base64.getDecoder().decode(base64Encoded.toString()); try { - return (RSAPublicKey) keyFactory.generatePublic( - new X509EncodedKeySpec(x509)); - } catch (Exception e) { + return (RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(x509)); + } + catch (Exception e) { throw new IllegalArgumentException(e); } }; @@ -125,7 +129,8 @@ public class RsaKeyConverters { private static KeyFactory rsaFactory() { try { return KeyFactory.getInstance("RSA"); - } catch (NoSuchAlgorithmException e) { + } + catch (NoSuchAlgorithmException e) { throw new IllegalStateException(e); } } @@ -137,4 +142,5 @@ public class RsaKeyConverters { private static boolean isNotX509Wrapper(String line) { return !X509_PEM_HEADER.equals(line) && !X509_PEM_FOOTER.equals(line); } + } diff --git a/core/src/main/java/org/springframework/security/core/AuthenticatedPrincipal.java b/core/src/main/java/org/springframework/security/core/AuthenticatedPrincipal.java index 51739334bf..177ff2dfa7 100644 --- a/core/src/main/java/org/springframework/security/core/AuthenticatedPrincipal.java +++ b/core/src/main/java/org/springframework/security/core/AuthenticatedPrincipal.java @@ -19,15 +19,15 @@ import org.springframework.security.authentication.AuthenticationManager; /** * Representation of an authenticated Principal once an - * {@link Authentication} request has been successfully authenticated - * by the {@link AuthenticationManager#authenticate(Authentication)} method. + * {@link Authentication} request has been successfully authenticated by the + * {@link AuthenticationManager#authenticate(Authentication)} method. * * Implementors typically provide their own representation of a Principal, - * which usually contains information describing the Principal entity, - * such as, first/middle/last name, address, email, phone, id, etc. + * which usually contains information describing the Principal entity, such + * as, first/middle/last name, address, email, phone, id, etc. * - * This interface allows implementors to expose specific attributes - * of their custom representation of Principal in a generic way. + * This interface allows implementors to expose specific attributes of their custom + * representation of Principal in a generic way. * * @author Joe Grandja * @since 5.0 @@ -37,8 +37,8 @@ import org.springframework.security.authentication.AuthenticationManager; public interface AuthenticatedPrincipal { /** - * Returns the name of the authenticated Principal. Never null. - * + * Returns the name of the authenticated Principal. Never + * null. * @return the name of the authenticated Principal */ String getName(); diff --git a/core/src/main/java/org/springframework/security/core/Authentication.java b/core/src/main/java/org/springframework/security/core/Authentication.java index 0a09c26a20..5b762ef72e 100644 --- a/core/src/main/java/org/springframework/security/core/Authentication.java +++ b/core/src/main/java/org/springframework/security/core/Authentication.java @@ -49,6 +49,7 @@ import org.springframework.security.core.context.SecurityContextHolder; * @author Ben Alex */ public interface Authentication extends Principal, Serializable { + // ~ Methods // ======================================================================================================== @@ -61,7 +62,6 @@ public interface Authentication extends Principal, Serializable { * do not affect the state of the Authentication object, or use an unmodifiable * instance. *

      - * * @return the authorities granted to the principal, or an empty collection if the * token has not been authenticated. Never null. */ @@ -71,7 +71,6 @@ public interface Authentication extends Principal, Serializable { * The credentials that prove the principal is correct. This is usually a password, * but could be anything relevant to the AuthenticationManager. Callers * are expected to populate the credentials. - * * @return the credentials that prove the identity of the Principal */ Object getCredentials(); @@ -79,7 +78,6 @@ public interface Authentication extends Principal, Serializable { /** * Stores additional details about the authentication request. These might be an IP * address, certificate serial number etc. - * * @return additional details about the authentication request, or null * if not used */ @@ -94,7 +92,6 @@ public interface Authentication extends Principal, Serializable { * Authentication containing richer information as the principal for use by * the application. Many of the authentication providers will create a * {@code UserDetails} object as the principal. - * * @return the Principal being authenticated or the authenticated * principal after authentication. */ @@ -114,7 +111,6 @@ public interface Authentication extends Principal, Serializable { * about returning true from this method unless they are either * immutable, or have some way of ensuring the properties have not been changed since * original creation. - * * @return true if the token has been authenticated and the * AbstractSecurityInterceptor does not need to present the token to the * AuthenticationManager again for re-authentication. @@ -130,14 +126,13 @@ public interface Authentication extends Principal, Serializable { * an invocation with a true parameter (which would indicate the * authentication token is trusted - a potential security risk) the implementation * should throw an {@link IllegalArgumentException}. - * * @param isAuthenticated true if the token should be trusted (which may * result in an exception) or false if the token should not be trusted - * * @throws IllegalArgumentException if an attempt to make the authentication token * trusted (by passing true as the argument) is rejected due to the * implementation being immutable or implementing its own alternative approach to * {@link #isAuthenticated()} */ void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException; + } diff --git a/core/src/main/java/org/springframework/security/core/AuthenticationException.java b/core/src/main/java/org/springframework/security/core/AuthenticationException.java index 0d85b76ef2..1680049188 100644 --- a/core/src/main/java/org/springframework/security/core/AuthenticationException.java +++ b/core/src/main/java/org/springframework/security/core/AuthenticationException.java @@ -30,7 +30,6 @@ public abstract class AuthenticationException extends RuntimeException { /** * Constructs an {@code AuthenticationException} with the specified message and root * cause. - * * @param msg the detail message * @param t the root cause */ @@ -41,7 +40,6 @@ public abstract class AuthenticationException extends RuntimeException { /** * Constructs an {@code AuthenticationException} with the specified message and no * root cause. - * * @param msg the detail message */ public AuthenticationException(String msg) { diff --git a/core/src/main/java/org/springframework/security/core/ComparableVersion.java b/core/src/main/java/org/springframework/security/core/ComparableVersion.java index e5b6f247c2..e34f04b3e4 100644 --- a/core/src/main/java/org/springframework/security/core/ComparableVersion.java +++ b/core/src/main/java/org/springframework/security/core/ComparableVersion.java @@ -78,13 +78,14 @@ import java.util.Stack; * *

      * - * @see "Versioning" on - * Maven Wiki + * @see "Versioning" on Maven + * Wiki * @author Kenney Westerhof * @author Hervé Boutemy */ class ComparableVersion implements Comparable { + private String value; private String canonical; @@ -92,8 +93,11 @@ class ComparableVersion implements Comparable { private ListItem items; private interface Item { + int INTEGER_ITEM = 0; + int STRING_ITEM = 1; + int LIST_ITEM = 2; int compareTo(Item item); @@ -101,12 +105,14 @@ class ComparableVersion implements Comparable { int getType(); boolean isNull(); + } /** * Represents a numeric item in the version item list. */ private static class IntegerItem implements Item { + private static final BigInteger BigInteger_ZERO = new BigInteger("0"); private final BigInteger value; @@ -156,14 +162,15 @@ class ComparableVersion implements Comparable { public String toString() { return value.toString(); } + } /** * Represents a string in the version item list, usually a qualifier. */ private static class StringItem implements Item { - private static final String[] QUALIFIERS = { "alpha", "beta", "milestone", "rc", - "snapshot", "", "sp" }; + + private static final String[] QUALIFIERS = { "alpha", "beta", "milestone", "rc", "snapshot", "", "sp" }; private static final List _QUALIFIERS = Arrays.asList(QUALIFIERS); @@ -179,8 +186,7 @@ class ComparableVersion implements Comparable { * determine if a given qualifier makes the version older than one without a * qualifier, or more recent. */ - private static final String RELEASE_VERSION_INDEX = String.valueOf(_QUALIFIERS - .indexOf("")); + private static final String RELEASE_VERSION_INDEX = String.valueOf(_QUALIFIERS.indexOf("")); private String value; @@ -222,7 +228,6 @@ class ComparableVersion implements Comparable { * if/then/else to check for -1 or QUALIFIERS.size and then resort to lexical * ordering. Most comparisons are decided by the first character, so this is still * fast. If more characters are needed then it requires a lexical sort anyway. - * * @param qualifier * @return an equivalent value that can be used with lexical comparison */ @@ -243,8 +248,7 @@ class ComparableVersion implements Comparable { return -1; // 1.any < 1.1 ? case STRING_ITEM: - return comparableQualifier(value).compareTo( - comparableQualifier(((StringItem) item).value)); + return comparableQualifier(value).compareTo(comparableQualifier(((StringItem) item).value)); case LIST_ITEM: return -1; // 1.any < 1-1 @@ -258,6 +262,7 @@ class ComparableVersion implements Comparable { public String toString() { return value; } + } /** @@ -265,6 +270,7 @@ class ComparableVersion implements Comparable { * and for sub-lists (which start with '-(number)' in the version specification). */ private static class ListItem extends ArrayList implements Item { + @Override public int getType() { return LIST_ITEM; @@ -276,8 +282,7 @@ class ComparableVersion implements Comparable { } void normalize() { - for (ListIterator iterator = listIterator(size()); iterator - .hasPrevious();) { + for (ListIterator iterator = listIterator(size()); iterator.hasPrevious();) { Item item = iterator.previous(); if (item.isNull()) { iterator.remove(); // remove null trailing items: 0, "", empty list @@ -339,6 +344,7 @@ class ComparableVersion implements Comparable { buffer.append(')'); return buffer.toString(); } + } ComparableVersion(String version) { @@ -385,8 +391,7 @@ class ComparableVersion implements Comparable { if (isDigit) { list.normalize(); // 1.0-* = 1-* - if ((i + 1 < version.length()) - && Character.isDigit(version.charAt(i + 1))) { + if ((i + 1 < version.length()) && Character.isDigit(version.charAt(i + 1))) { // new ListItem only if previous were digits and new char is a // digit, // ie need to differentiate only 1.1 from 1-1 @@ -442,12 +447,12 @@ class ComparableVersion implements Comparable { @Override public boolean equals(Object o) { - return (o instanceof ComparableVersion) - && canonical.equals(((ComparableVersion) o).canonical); + return (o instanceof ComparableVersion) && canonical.equals(((ComparableVersion) o).canonical); } @Override public int hashCode() { return canonical.hashCode(); } + } diff --git a/core/src/main/java/org/springframework/security/core/CredentialsContainer.java b/core/src/main/java/org/springframework/security/core/CredentialsContainer.java index 5dc1b520cf..d36bae8aeb 100644 --- a/core/src/main/java/org/springframework/security/core/CredentialsContainer.java +++ b/core/src/main/java/org/springframework/security/core/CredentialsContainer.java @@ -29,5 +29,7 @@ package org.springframework.security.core; * @since 3.0.3 */ public interface CredentialsContainer { + void eraseCredentials(); + } diff --git a/core/src/main/java/org/springframework/security/core/GrantedAuthority.java b/core/src/main/java/org/springframework/security/core/GrantedAuthority.java index 7e29789fbe..52e0d23326 100644 --- a/core/src/main/java/org/springframework/security/core/GrantedAuthority.java +++ b/core/src/main/java/org/springframework/security/core/GrantedAuthority.java @@ -30,6 +30,7 @@ import org.springframework.security.access.AccessDecisionManager; * @author Ben Alex */ public interface GrantedAuthority extends Serializable { + // ~ Methods // ======================================================================================================== @@ -44,10 +45,10 @@ public interface GrantedAuthority extends Serializable { * null will require an AccessDecisionManager (or delegate) * to specifically support the GrantedAuthority implementation, so * returning null should be avoided unless actually required. - * * @return a representation of the granted authority (or null if the * granted authority cannot be expressed as a String with sufficient * precision). */ String getAuthority(); + } diff --git a/core/src/main/java/org/springframework/security/core/SpringSecurityCoreVersion.java b/core/src/main/java/org/springframework/security/core/SpringSecurityCoreVersion.java index 89b47d111f..b2252bb08d 100644 --- a/core/src/main/java/org/springframework/security/core/SpringSecurityCoreVersion.java +++ b/core/src/main/java/org/springframework/security/core/SpringSecurityCoreVersion.java @@ -30,8 +30,8 @@ import java.util.Properties; * @author Rob Winch */ public class SpringSecurityCoreVersion { - private static final String DISABLE_CHECKS = SpringSecurityCoreVersion.class.getName() - .concat(".DISABLE_CHECKS"); + + private static final String DISABLE_CHECKS = SpringSecurityCoreVersion.class.getName().concat(".DISABLE_CHECKS"); private static final Log logger = LogFactory.getLog(SpringSecurityCoreVersion.class); @@ -63,7 +63,6 @@ public class SpringSecurityCoreVersion { /** * Perform version checks with specific min Spring Version - * * @param minSpringVersion */ private static void performVersionChecks(String minSpringVersion) { @@ -79,8 +78,7 @@ public class SpringSecurityCoreVersion { } logger.info("You are running with Spring Security Core " + version); - if (new ComparableVersion(springVersion) - .compareTo(new ComparableVersion(minSpringVersion)) < 0) { + if (new ComparableVersion(springVersion).compareTo(new ComparableVersion(minSpringVersion)) < 0) { logger.warn("**** You are advised to use Spring " + minSpringVersion + " or later with this version. You are running: " + springVersion); } @@ -89,13 +87,11 @@ public class SpringSecurityCoreVersion { /** * Disable if springVersion and springSecurityVersion are the same to allow working * with Uber Jars. - * * @param springVersion * @param springSecurityVersion * @return */ - private static boolean disableChecks(String springVersion, - String springSecurityVersion) { + private static boolean disableChecks(String springVersion, String springSecurityVersion) { if (springVersion == null || springVersion.equals(springSecurityVersion)) { return true; } @@ -109,10 +105,13 @@ public class SpringSecurityCoreVersion { private static String getSpringVersion() { Properties properties = new Properties(); try { - properties.load(SpringSecurityCoreVersion.class.getClassLoader().getResourceAsStream("META-INF/spring-security.versions")); - } catch (IOException | NullPointerException e) { + properties.load(SpringSecurityCoreVersion.class.getClassLoader() + .getResourceAsStream("META-INF/spring-security.versions")); + } + catch (IOException | NullPointerException e) { return null; } return properties.getProperty("org.springframework:spring-core"); } + } diff --git a/core/src/main/java/org/springframework/security/core/SpringSecurityMessageSource.java b/core/src/main/java/org/springframework/security/core/SpringSecurityMessageSource.java index 74959b6eee..73d65df288 100644 --- a/core/src/main/java/org/springframework/security/core/SpringSecurityMessageSource.java +++ b/core/src/main/java/org/springframework/security/core/SpringSecurityMessageSource.java @@ -32,6 +32,7 @@ import org.springframework.context.support.ResourceBundleMessageSource; * @author Ben Alex */ public class SpringSecurityMessageSource extends ResourceBundleMessageSource { + // ~ Constructors // =================================================================================================== @@ -45,4 +46,5 @@ public class SpringSecurityMessageSource extends ResourceBundleMessageSource { public static MessageSourceAccessor getAccessor() { return new MessageSourceAccessor(new SpringSecurityMessageSource()); } + } diff --git a/core/src/main/java/org/springframework/security/core/Transient.java b/core/src/main/java/org/springframework/security/core/Transient.java index b5bb566e7f..a3d8d749a3 100644 --- a/core/src/main/java/org/springframework/security/core/Transient.java +++ b/core/src/main/java/org/springframework/security/core/Transient.java @@ -24,15 +24,16 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * A marker for {@link Authentication}s that should never be stored across requests, for example - * a bearer token authentication + * A marker for {@link Authentication}s that should never be stored across requests, for + * example a bearer token authentication * * @author Josh Cummings * @since 5.1 */ -@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) +@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE }) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Transient { + } diff --git a/core/src/main/java/org/springframework/security/core/annotation/AuthenticationPrincipal.java b/core/src/main/java/org/springframework/security/core/annotation/AuthenticationPrincipal.java index f75f2bfd28..aa0cbfcef3 100644 --- a/core/src/main/java/org/springframework/security/core/annotation/AuthenticationPrincipal.java +++ b/core/src/main/java/org/springframework/security/core/annotation/AuthenticationPrincipal.java @@ -42,7 +42,6 @@ public @interface AuthenticationPrincipal { /** * True if a {@link ClassCastException} should be thrown when the current * {@link Authentication#getPrincipal()} is the incorrect type. Default is false. - * * @return */ boolean errorOnInvalidType() default false; @@ -71,8 +70,8 @@ public @interface AuthenticationPrincipal { *
       	 * @AuthenticationPrincipal(expression = "customUser")
       	 * 
      - * * @return the expression to use. */ String expression() default ""; + } diff --git a/core/src/main/java/org/springframework/security/core/annotation/CurrentSecurityContext.java b/core/src/main/java/org/springframework/security/core/annotation/CurrentSecurityContext.java index c32adb405c..77a5ccb223 100644 --- a/core/src/main/java/org/springframework/security/core/annotation/CurrentSecurityContext.java +++ b/core/src/main/java/org/springframework/security/core/annotation/CurrentSecurityContext.java @@ -22,8 +22,8 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Annotation that is used to resolve the {@link org.springframework.security.core.context.SecurityContext} as a method - * argument. + * Annotation that is used to resolve the + * {@link org.springframework.security.core.context.SecurityContext} as a method argument. * * @author Dan Zheng * @since 5.2 @@ -44,26 +44,27 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CurrentSecurityContext { + /** * True if a {@link ClassCastException} should be thrown when the current - * {@link org.springframework.security.core.context.SecurityContext} is the incorrect type. Default is false. - * + * {@link org.springframework.security.core.context.SecurityContext} is the incorrect + * type. Default is false. * @return whether or not to error on an invalid type */ boolean errorOnInvalidType() default false; /** - * If specified, will use the provided SpEL expression to resolve the security context. This - * is convenient if applications need to transform the result. + * If specified, will use the provided SpEL expression to resolve the security + * context. This is convenient if applications need to transform the result. * - * For example, if an application needs to extract its custom {@code Authentication} implementation, - * then it could specify the appropriate SpEL like so: + * For example, if an application needs to extract its custom {@code Authentication} + * implementation, then it could specify the appropriate SpEL like so: * *
       	 * @CurrentSecurityContext(expression = "authentication") CustomAuthentication authentication
       	 * 
      - * * @return the expression to use */ String expression() default ""; + } diff --git a/core/src/main/java/org/springframework/security/core/authority/AuthorityUtils.java b/core/src/main/java/org/springframework/security/core/authority/AuthorityUtils.java index df67a2aba1..9dac63b949 100644 --- a/core/src/main/java/org/springframework/security/core/authority/AuthorityUtils.java +++ b/core/src/main/java/org/springframework/security/core/authority/AuthorityUtils.java @@ -34,19 +34,17 @@ import org.springframework.util.Assert; * @author Luke Taylor */ public abstract class AuthorityUtils { + public static final List NO_AUTHORITIES = Collections.emptyList(); /** * Creates a array of GrantedAuthority objects from a comma-separated string * representation (e.g. "ROLE_A, ROLE_B, ROLE_C"). - * * @param authorityString the comma-separated string * @return the authorities created by tokenizing the string */ - public static List commaSeparatedStringToAuthorityList( - String authorityString) { - return createAuthorityList(StringUtils - .tokenizeToStringArray(authorityString, ",")); + public static List commaSeparatedStringToAuthorityList(String authorityString) { + return createAuthorityList(StringUtils.tokenizeToStringArray(authorityString, ",")); } /** @@ -54,8 +52,7 @@ public abstract class AuthorityUtils { * @return a Set of the Strings obtained from each call to * GrantedAuthority.getAuthority() */ - public static Set authorityListToSet( - Collection userAuthorities) { + public static Set authorityListToSet(Collection userAuthorities) { Assert.notNull(userAuthorities, "userAuthorities cannot be null"); Set set = new HashSet<>(userAuthorities.size()); @@ -68,7 +65,6 @@ public abstract class AuthorityUtils { /** * Converts authorities into a List of GrantedAuthority objects. - * * @param authorities the authorities to convert * @return a List of GrantedAuthority objects */ @@ -81,4 +77,5 @@ public abstract class AuthorityUtils { return grantedAuthorities; } + } diff --git a/core/src/main/java/org/springframework/security/core/authority/GrantedAuthoritiesContainer.java b/core/src/main/java/org/springframework/security/core/authority/GrantedAuthoritiesContainer.java index 5564316755..1c7c00eb70 100644 --- a/core/src/main/java/org/springframework/security/core/authority/GrantedAuthoritiesContainer.java +++ b/core/src/main/java/org/springframework/security/core/authority/GrantedAuthoritiesContainer.java @@ -31,5 +31,7 @@ import org.springframework.security.core.GrantedAuthority; * @since 2.0 */ public interface GrantedAuthoritiesContainer extends Serializable { + Collection getGrantedAuthorities(); + } diff --git a/core/src/main/java/org/springframework/security/core/authority/SimpleGrantedAuthority.java b/core/src/main/java/org/springframework/security/core/authority/SimpleGrantedAuthority.java index 21e2803e2e..e2081c0af4 100644 --- a/core/src/main/java/org/springframework/security/core/authority/SimpleGrantedAuthority.java +++ b/core/src/main/java/org/springframework/security/core/authority/SimpleGrantedAuthority.java @@ -66,4 +66,5 @@ public final class SimpleGrantedAuthority implements GrantedAuthority { public String toString() { return this.role; } + } diff --git a/core/src/main/java/org/springframework/security/core/authority/mapping/Attributes2GrantedAuthoritiesMapper.java b/core/src/main/java/org/springframework/security/core/authority/mapping/Attributes2GrantedAuthoritiesMapper.java index a375df225d..85b471cf00 100755 --- a/core/src/main/java/org/springframework/security/core/authority/mapping/Attributes2GrantedAuthoritiesMapper.java +++ b/core/src/main/java/org/springframework/security/core/authority/mapping/Attributes2GrantedAuthoritiesMapper.java @@ -27,16 +27,16 @@ import org.springframework.security.core.GrantedAuthority; * @since 2.0 */ public interface Attributes2GrantedAuthoritiesMapper { + /** * Implementations of this method should map the given collection of attributes to a * collection of Spring Security GrantedAuthorities. There are no restrictions for the * mapping process; a single attribute can be mapped to multiple Spring Security * GrantedAuthorities, all attributes can be mapped to a single Spring Security * {@code GrantedAuthority}, some attributes may not be mapped, etc. - * * @param attributes the attributes to be mapped * @return the collection of authorities created from the attributes */ - Collection getGrantedAuthorities( - Collection attributes); + Collection getGrantedAuthorities(Collection attributes); + } diff --git a/core/src/main/java/org/springframework/security/core/authority/mapping/GrantedAuthoritiesMapper.java b/core/src/main/java/org/springframework/security/core/authority/mapping/GrantedAuthoritiesMapper.java index 99aa7e340e..61ba162fbd 100644 --- a/core/src/main/java/org/springframework/security/core/authority/mapping/GrantedAuthoritiesMapper.java +++ b/core/src/main/java/org/springframework/security/core/authority/mapping/GrantedAuthoritiesMapper.java @@ -27,6 +27,7 @@ import java.util.*; * @author Luke Taylor */ public interface GrantedAuthoritiesMapper { - Collection mapAuthorities( - Collection authorities); + + Collection mapAuthorities(Collection authorities); + } diff --git a/core/src/main/java/org/springframework/security/core/authority/mapping/MapBasedAttributes2GrantedAuthoritiesMapper.java b/core/src/main/java/org/springframework/security/core/authority/mapping/MapBasedAttributes2GrantedAuthoritiesMapper.java index dd3eb7e0cf..c24231f347 100755 --- a/core/src/main/java/org/springframework/security/core/authority/mapping/MapBasedAttributes2GrantedAuthoritiesMapper.java +++ b/core/src/main/java/org/springframework/security/core/authority/mapping/MapBasedAttributes2GrantedAuthoritiesMapper.java @@ -31,16 +31,17 @@ import org.springframework.util.StringUtils; * * @author Ruud Senden */ -public class MapBasedAttributes2GrantedAuthoritiesMapper implements - Attributes2GrantedAuthoritiesMapper, MappableAttributesRetriever, - InitializingBean { +public class MapBasedAttributes2GrantedAuthoritiesMapper + implements Attributes2GrantedAuthoritiesMapper, MappableAttributesRetriever, InitializingBean { + private Map> attributes2grantedAuthoritiesMap = null; + private String stringSeparator = ","; + private Set mappableAttributes = null; public void afterPropertiesSet() { - Assert.notNull(attributes2grantedAuthoritiesMap, - "attributes2grantedAuthoritiesMap must be set"); + Assert.notNull(attributes2grantedAuthoritiesMap, "attributes2grantedAuthoritiesMap must be set"); } /** @@ -49,8 +50,7 @@ public class MapBasedAttributes2GrantedAuthoritiesMapper implements public List getGrantedAuthorities(Collection attributes) { ArrayList gaList = new ArrayList<>(); for (String attribute : attributes) { - Collection c = attributes2grantedAuthoritiesMap - .get(attribute); + Collection c = attributes2grantedAuthoritiesMap.get(attribute); if (c != null) { gaList.addAll(c); } @@ -71,38 +71,32 @@ public class MapBasedAttributes2GrantedAuthoritiesMapper implements * @param attributes2grantedAuthoritiesMap The attributes2grantedAuthoritiesMap to * set. */ - public void setAttributes2grantedAuthoritiesMap( - final Map attributes2grantedAuthoritiesMap) { + public void setAttributes2grantedAuthoritiesMap(final Map attributes2grantedAuthoritiesMap) { Assert.notEmpty(attributes2grantedAuthoritiesMap, "A non-empty attributes2grantedAuthoritiesMap must be supplied"); this.attributes2grantedAuthoritiesMap = preProcessMap(attributes2grantedAuthoritiesMap); - mappableAttributes = Collections - .unmodifiableSet(this.attributes2grantedAuthoritiesMap.keySet()); + mappableAttributes = Collections.unmodifiableSet(this.attributes2grantedAuthoritiesMap.keySet()); } /** * Preprocess the given map to convert all the values to GrantedAuthority collections - * * @param orgMap The map to process * @return the processed Map */ private Map> preProcessMap(Map orgMap) { - Map> result = new HashMap<>( - orgMap.size()); + Map> result = new HashMap<>(orgMap.size()); for (Map.Entry entry : orgMap.entrySet()) { Assert.isInstanceOf(String.class, entry.getKey(), "attributes2grantedAuthoritiesMap contains non-String objects as keys"); - result.put((String) entry.getKey(), - getGrantedAuthorityCollection(entry.getValue())); + result.put((String) entry.getKey(), getGrantedAuthorityCollection(entry.getValue())); } return result; } /** * Convert the given value to a collection of Granted Authorities - * * @param value The value to convert to a GrantedAuthority Collection * @return Collection containing the GrantedAuthority Collection */ @@ -115,12 +109,10 @@ public class MapBasedAttributes2GrantedAuthoritiesMapper implements /** * Convert the given value to a collection of Granted Authorities, adding the result * to the given result collection. - * * @param value The value to convert to a GrantedAuthority Collection * @return Collection containing the GrantedAuthority Collection */ - private void addGrantedAuthorityCollection(Collection result, - Object value) { + private void addGrantedAuthorityCollection(Collection result, Object value) { if (value == null) { return; } @@ -137,27 +129,23 @@ public class MapBasedAttributes2GrantedAuthoritiesMapper implements result.add((GrantedAuthority) value); } else { - throw new IllegalArgumentException("Invalid object type: " - + value.getClass().getName()); + throw new IllegalArgumentException("Invalid object type: " + value.getClass().getName()); } } - private void addGrantedAuthorityCollection(Collection result, - Collection value) { + private void addGrantedAuthorityCollection(Collection result, Collection value) { for (Object elt : value) { addGrantedAuthorityCollection(result, elt); } } - private void addGrantedAuthorityCollection(Collection result, - Object[] value) { + private void addGrantedAuthorityCollection(Collection result, Object[] value) { for (Object aValue : value) { addGrantedAuthorityCollection(result, aValue); } } - private void addGrantedAuthorityCollection(Collection result, - String value) { + private void addGrantedAuthorityCollection(Collection result, String value) { StringTokenizer st = new StringTokenizer(value, stringSeparator, false); while (st.hasMoreTokens()) { String nextToken = st.nextToken(); diff --git a/core/src/main/java/org/springframework/security/core/authority/mapping/MappableAttributesRetriever.java b/core/src/main/java/org/springframework/security/core/authority/mapping/MappableAttributesRetriever.java index 67fd1d0374..f9f646182c 100755 --- a/core/src/main/java/org/springframework/security/core/authority/mapping/MappableAttributesRetriever.java +++ b/core/src/main/java/org/springframework/security/core/authority/mapping/MappableAttributesRetriever.java @@ -26,11 +26,12 @@ import java.util.Set; * @since 2.0 */ public interface MappableAttributesRetriever { + /** * Implementations of this method should return a set of all string attributes which * can be mapped to GrantedAuthoritys. - * * @return set of all mappable roles */ Set getMappableAttributes(); + } diff --git a/core/src/main/java/org/springframework/security/core/authority/mapping/NullAuthoritiesMapper.java b/core/src/main/java/org/springframework/security/core/authority/mapping/NullAuthoritiesMapper.java index dd22a1e649..05c971b775 100644 --- a/core/src/main/java/org/springframework/security/core/authority/mapping/NullAuthoritiesMapper.java +++ b/core/src/main/java/org/springframework/security/core/authority/mapping/NullAuthoritiesMapper.java @@ -23,8 +23,9 @@ import java.util.*; * @author Luke Taylor */ public class NullAuthoritiesMapper implements GrantedAuthoritiesMapper { - public Collection mapAuthorities( - Collection authorities) { + + public Collection mapAuthorities(Collection authorities) { return authorities; } + } diff --git a/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAttributes2GrantedAuthoritiesMapper.java b/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAttributes2GrantedAuthoritiesMapper.java index b3c0a92109..9d1eec38af 100755 --- a/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAttributes2GrantedAuthoritiesMapper.java +++ b/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAttributes2GrantedAuthoritiesMapper.java @@ -38,8 +38,9 @@ import org.springframework.util.Assert; * @author Ruud Senden * @since 2.0 */ -public class SimpleAttributes2GrantedAuthoritiesMapper implements - Attributes2GrantedAuthoritiesMapper, InitializingBean { +public class SimpleAttributes2GrantedAuthoritiesMapper + implements Attributes2GrantedAuthoritiesMapper, InitializingBean { + private String attributePrefix = "ROLE_"; private boolean convertAttributeToUpperCase = false; @@ -52,8 +53,7 @@ public class SimpleAttributes2GrantedAuthoritiesMapper implements * Check whether all properties have been set to correct values. */ public void afterPropertiesSet() { - Assert.isTrue( - !(isConvertAttributeToUpperCase() && isConvertAttributeToLowerCase()), + Assert.isTrue(!(isConvertAttributeToUpperCase() && isConvertAttributeToLowerCase()), "Either convertAttributeToUpperCase or convertAttributeToLowerCase can be set to true, but not both"); } @@ -72,7 +72,6 @@ public class SimpleAttributes2GrantedAuthoritiesMapper implements /** * Map the given role one-on-one to a Spring Security GrantedAuthority, optionally * doing case conversion and/or adding a prefix. - * * @param attribute The attribute for which to get a GrantedAuthority * @return GrantedAuthority representing the given role. */ diff --git a/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAuthorityMapper.java b/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAuthorityMapper.java index b381d8fcb9..3615b7e606 100644 --- a/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAuthorityMapper.java +++ b/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAuthorityMapper.java @@ -30,11 +30,14 @@ import java.util.*; * @author Luke Taylor * @since 3.1 */ -public final class SimpleAuthorityMapper implements GrantedAuthoritiesMapper, - InitializingBean { +public final class SimpleAuthorityMapper implements GrantedAuthoritiesMapper, InitializingBean { + private GrantedAuthority defaultAuthority; + private String prefix = "ROLE_"; + private boolean convertToUpperCase = false; + private boolean convertToLowerCase = false; public void afterPropertiesSet() { @@ -47,15 +50,11 @@ public final class SimpleAuthorityMapper implements GrantedAuthoritiesMapper, * prefix settings. The mapping will be one-to-one unless duplicates are produced * during the conversion. If a default authority has been set, this will also be * assigned to each mapping. - * * @param authorities the original authorities - * * @return the converted set of authorities */ - public Set mapAuthorities( - Collection authorities) { - HashSet mapped = new HashSet<>( - authorities.size()); + public Set mapAuthorities(Collection authorities) { + HashSet mapped = new HashSet<>(authorities.size()); for (GrantedAuthority authority : authorities) { mapped.add(mapAuthority(authority.getAuthority())); } @@ -85,7 +84,6 @@ public final class SimpleAuthorityMapper implements GrantedAuthoritiesMapper, /** * Sets the prefix which should be added to the authority name (if it doesn't already * exist) - * * @param prefix the prefix, typically to satisfy the behaviour of an * {@code AccessDecisionVoter}. */ @@ -96,7 +94,6 @@ public final class SimpleAuthorityMapper implements GrantedAuthoritiesMapper, /** * Whether to convert the authority value to upper case in the mapping. - * * @param convertToUpperCase defaults to {@code false} */ public void setConvertToUpperCase(boolean convertToUpperCase) { @@ -105,7 +102,6 @@ public final class SimpleAuthorityMapper implements GrantedAuthoritiesMapper, /** * Whether to convert the authority value to lower case in the mapping. - * * @param convertToLowerCase defaults to {@code false} */ public void setConvertToLowerCase(boolean convertToLowerCase) { @@ -114,11 +110,11 @@ public final class SimpleAuthorityMapper implements GrantedAuthoritiesMapper, /** * Sets a default authority to be assigned to all users - * * @param authority the name of the authority to be assigned to all users. */ public void setDefaultAuthority(String authority) { Assert.hasText(authority, "The authority name cannot be set to an empty value"); this.defaultAuthority = new SimpleGrantedAuthority(authority); } + } diff --git a/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleMappableAttributesRetriever.java b/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleMappableAttributesRetriever.java index 0ce561150e..d66e484837 100755 --- a/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleMappableAttributesRetriever.java +++ b/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleMappableAttributesRetriever.java @@ -27,6 +27,7 @@ import java.util.Set; * @since 2.0 */ public class SimpleMappableAttributesRetriever implements MappableAttributesRetriever { + private Set mappableAttributes = null; /* diff --git a/core/src/main/java/org/springframework/security/core/authority/mapping/package-info.java b/core/src/main/java/org/springframework/security/core/authority/mapping/package-info.java index f52d4bf459..c2bacb6ba3 100644 --- a/core/src/main/java/org/springframework/security/core/authority/mapping/package-info.java +++ b/core/src/main/java/org/springframework/security/core/authority/mapping/package-info.java @@ -17,8 +17,7 @@ * Strategies for mapping a list of attributes (such as roles or LDAP groups) to a list of * {@code GrantedAuthority}s. *

      - * Provides a layer of indirection between a security data repository and the logical authorities - * required within an application. + * Provides a layer of indirection between a security data repository and the logical + * authorities required within an application. */ package org.springframework.security.core.authority.mapping; - diff --git a/core/src/main/java/org/springframework/security/core/authority/package-info.java b/core/src/main/java/org/springframework/security/core/authority/package-info.java index 3d3822993d..c4356efc30 100644 --- a/core/src/main/java/org/springframework/security/core/authority/package-info.java +++ b/core/src/main/java/org/springframework/security/core/authority/package-info.java @@ -17,4 +17,3 @@ * The default implementation of the {@code GrantedAuthority} interface. */ package org.springframework.security.core.authority; - diff --git a/core/src/main/java/org/springframework/security/core/context/GlobalSecurityContextHolderStrategy.java b/core/src/main/java/org/springframework/security/core/context/GlobalSecurityContextHolderStrategy.java index 18ae5a2828..218fa5cd5e 100644 --- a/core/src/main/java/org/springframework/security/core/context/GlobalSecurityContextHolderStrategy.java +++ b/core/src/main/java/org/springframework/security/core/context/GlobalSecurityContextHolderStrategy.java @@ -28,6 +28,7 @@ import org.springframework.util.Assert; * @author Ben Alex */ final class GlobalSecurityContextHolderStrategy implements SecurityContextHolderStrategy { + // ~ Static fields/initializers // ===================================================================================== @@ -56,4 +57,5 @@ final class GlobalSecurityContextHolderStrategy implements SecurityContextHolder public SecurityContext createEmptyContext() { return new SecurityContextImpl(); } + } diff --git a/core/src/main/java/org/springframework/security/core/context/InheritableThreadLocalSecurityContextHolderStrategy.java b/core/src/main/java/org/springframework/security/core/context/InheritableThreadLocalSecurityContextHolderStrategy.java index 5e9d5e395d..73e8237593 100644 --- a/core/src/main/java/org/springframework/security/core/context/InheritableThreadLocalSecurityContextHolderStrategy.java +++ b/core/src/main/java/org/springframework/security/core/context/InheritableThreadLocalSecurityContextHolderStrategy.java @@ -23,11 +23,10 @@ import org.springframework.util.Assert; * {@link org.springframework.security.core.context.SecurityContextHolderStrategy}. * * @author Ben Alex - * * @see java.lang.ThreadLocal */ -final class InheritableThreadLocalSecurityContextHolderStrategy implements - SecurityContextHolderStrategy { +final class InheritableThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy { + // ~ Static fields/initializers // ===================================================================================== @@ -59,4 +58,5 @@ final class InheritableThreadLocalSecurityContextHolderStrategy implements public SecurityContext createEmptyContext() { return new SecurityContextImpl(); } + } diff --git a/core/src/main/java/org/springframework/security/core/context/ReactiveSecurityContextHolder.java b/core/src/main/java/org/springframework/security/core/context/ReactiveSecurityContextHolder.java index e6ed84ae2c..fc5e0dca2e 100644 --- a/core/src/main/java/org/springframework/security/core/context/ReactiveSecurityContextHolder.java +++ b/core/src/main/java/org/springframework/security/core/context/ReactiveSecurityContextHolder.java @@ -16,7 +16,6 @@ package org.springframework.security.core.context; - import org.springframework.security.core.Authentication; import reactor.core.publisher.Mono; import reactor.util.context.Context; @@ -30,6 +29,7 @@ import java.util.function.Function; * @since 5.0 */ public class ReactiveSecurityContextHolder { + private static final Class SECURITY_CONTEXT_KEY = SecurityContext.class; /** @@ -37,9 +37,8 @@ public class ReactiveSecurityContextHolder { * @return the {@code Mono} */ public static Mono getContext() { - return Mono.subscriberContext() - .filter( c -> c.hasKey(SECURITY_CONTEXT_KEY)) - .flatMap( c-> c.>get(SECURITY_CONTEXT_KEY)); + return Mono.subscriberContext().filter(c -> c.hasKey(SECURITY_CONTEXT_KEY)) + .flatMap(c -> c.>get(SECURITY_CONTEXT_KEY)); } /** @@ -70,4 +69,5 @@ public class ReactiveSecurityContextHolder { public static Context withAuthentication(Authentication authentication) { return withSecurityContext(Mono.just(new SecurityContextImpl(authentication))); } + } diff --git a/core/src/main/java/org/springframework/security/core/context/SecurityContext.java b/core/src/main/java/org/springframework/security/core/context/SecurityContext.java index 1fd92790cc..6c00eb373a 100644 --- a/core/src/main/java/org/springframework/security/core/context/SecurityContext.java +++ b/core/src/main/java/org/springframework/security/core/context/SecurityContext.java @@ -31,12 +31,12 @@ import java.io.Serializable; * @author Ben Alex */ public interface SecurityContext extends Serializable { + // ~ Methods // ======================================================================================================== /** * Obtains the currently authenticated principal, or an authentication request token. - * * @return the Authentication or null if no authentication * information is available */ @@ -45,9 +45,9 @@ public interface SecurityContext extends Serializable { /** * Changes the currently authenticated principal, or removes the authentication * information. - * * @param authentication the new Authentication token, or * null if no further authentication information should be stored */ void setAuthentication(Authentication authentication); + } diff --git a/core/src/main/java/org/springframework/security/core/context/SecurityContextHolder.java b/core/src/main/java/org/springframework/security/core/context/SecurityContextHolder.java index 61c4231c35..edf187589f 100644 --- a/core/src/main/java/org/springframework/security/core/context/SecurityContextHolder.java +++ b/core/src/main/java/org/springframework/security/core/context/SecurityContextHolder.java @@ -48,15 +48,22 @@ import java.lang.reflect.Constructor; * */ public class SecurityContextHolder { + // ~ Static fields/initializers // ===================================================================================== public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL"; + public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL"; + public static final String MODE_GLOBAL = "MODE_GLOBAL"; + public static final String SYSTEM_PROPERTY = "spring.security.strategy"; + private static String strategyName = System.getProperty(SYSTEM_PROPERTY); + private static SecurityContextHolderStrategy strategy; + private static int initializeCount = 0; static { @@ -75,7 +82,6 @@ public class SecurityContextHolder { /** * Obtain the current SecurityContext. - * * @return the security context (never null) */ public static SecurityContext getContext() { @@ -85,7 +91,6 @@ public class SecurityContextHolder { /** * Primarily for troubleshooting purposes, this method shows how many times the class * has re-initialized its SecurityContextHolderStrategy. - * * @return the count (should be one unless you've called * {@link #setStrategyName(String)} to switch to an alternate strategy. */ @@ -125,7 +130,6 @@ public class SecurityContextHolder { /** * Associates a new SecurityContext with the current thread of execution. - * * @param context the new SecurityContext (may not be null) */ public static void setContext(SecurityContext context) { @@ -136,7 +140,6 @@ public class SecurityContextHolder { * Changes the preferred strategy. Do NOT call this method more than once for * a given JVM, as it will re-initialize the strategy and adversely affect any * existing threads using the old strategy. - * * @param strategyName the fully qualified class name of the strategy that should be * used. */ @@ -147,7 +150,6 @@ public class SecurityContextHolder { /** * Allows retrieval of the context strategy. See SEC-1188. - * * @return the configured strategy for storing the security context. */ public static SecurityContextHolderStrategy getContextHolderStrategy() { @@ -163,7 +165,7 @@ public class SecurityContextHolder { @Override public String toString() { - return "SecurityContextHolder[strategy='" + strategyName + "'; initializeCount=" - + initializeCount + "]"; + return "SecurityContextHolder[strategy='" + strategyName + "'; initializeCount=" + initializeCount + "]"; } + } diff --git a/core/src/main/java/org/springframework/security/core/context/SecurityContextHolderStrategy.java b/core/src/main/java/org/springframework/security/core/context/SecurityContextHolderStrategy.java index aa35315f4c..b988fd0294 100644 --- a/core/src/main/java/org/springframework/security/core/context/SecurityContextHolderStrategy.java +++ b/core/src/main/java/org/springframework/security/core/context/SecurityContextHolderStrategy.java @@ -25,6 +25,7 @@ package org.springframework.security.core.context; * @author Ben Alex */ public interface SecurityContextHolderStrategy { + // ~ Methods // ======================================================================================================== @@ -35,7 +36,6 @@ public interface SecurityContextHolderStrategy { /** * Obtains the current context. - * * @return a context (never null - create a default implementation if * necessary) */ @@ -43,7 +43,6 @@ public interface SecurityContextHolderStrategy { /** * Sets the current context. - * * @param context to the new argument (should never be null, although * implementations must check if null has been passed and throw an * IllegalArgumentException in such cases) @@ -54,8 +53,8 @@ public interface SecurityContextHolderStrategy { * Creates a new, empty context implementation, for use by * SecurityContextRepository implementations, when creating a new context for * the first time. - * * @return the empty context. */ SecurityContext createEmptyContext(); + } diff --git a/core/src/main/java/org/springframework/security/core/context/SecurityContextImpl.java b/core/src/main/java/org/springframework/security/core/context/SecurityContextImpl.java index bfd409c1c4..7eaa747bc8 100644 --- a/core/src/main/java/org/springframework/security/core/context/SecurityContextImpl.java +++ b/core/src/main/java/org/springframework/security/core/context/SecurityContextImpl.java @@ -35,7 +35,8 @@ public class SecurityContextImpl implements SecurityContext { private Authentication authentication; - public SecurityContextImpl() {} + public SecurityContextImpl() { + } public SecurityContextImpl(Authentication authentication) { this.authentication = authentication; @@ -96,4 +97,5 @@ public class SecurityContextImpl implements SecurityContext { return sb.toString(); } + } diff --git a/core/src/main/java/org/springframework/security/core/context/ThreadLocalSecurityContextHolderStrategy.java b/core/src/main/java/org/springframework/security/core/context/ThreadLocalSecurityContextHolderStrategy.java index c13a909c59..a6c405bbda 100644 --- a/core/src/main/java/org/springframework/security/core/context/ThreadLocalSecurityContextHolderStrategy.java +++ b/core/src/main/java/org/springframework/security/core/context/ThreadLocalSecurityContextHolderStrategy.java @@ -23,12 +23,11 @@ import org.springframework.util.Assert; * {@link SecurityContextHolderStrategy}. * * @author Ben Alex - * * @see java.lang.ThreadLocal * @see org.springframework.security.core.context.web.SecurityContextPersistenceFilter */ -final class ThreadLocalSecurityContextHolderStrategy implements - SecurityContextHolderStrategy { +final class ThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy { + // ~ Static fields/initializers // ===================================================================================== @@ -60,4 +59,5 @@ final class ThreadLocalSecurityContextHolderStrategy implements public SecurityContext createEmptyContext() { return new SecurityContextImpl(); } + } diff --git a/core/src/main/java/org/springframework/security/core/context/package-info.java b/core/src/main/java/org/springframework/security/core/context/package-info.java index 6660feef43..2b963914fb 100644 --- a/core/src/main/java/org/springframework/security/core/context/package-info.java +++ b/core/src/main/java/org/springframework/security/core/context/package-info.java @@ -14,14 +14,16 @@ * limitations under the License. */ /** - * Classes related to the establishment of a security context for the duration of a request (such as - * an HTTP or RMI invocation). + * Classes related to the establishment of a security context for the duration of a + * request (such as an HTTP or RMI invocation). *

      - * A security context is usually associated with the current execution thread for the duration of the request, - * making the authentication information it contains available throughout all the layers of an application. + * A security context is usually associated with the current execution thread for the + * duration of the request, making the authentication information it contains available + * throughout all the layers of an application. *

      - * The {@link org.springframework.security.core.context.SecurityContext SecurityContext} can be accessed at any point - * by calling the {@link org.springframework.security.core.context.SecurityContextHolder SecurityContextHolder}. + * The {@link org.springframework.security.core.context.SecurityContext SecurityContext} + * can be accessed at any point by calling the + * {@link org.springframework.security.core.context.SecurityContextHolder + * SecurityContextHolder}. */ package org.springframework.security.core.context; - diff --git a/core/src/main/java/org/springframework/security/core/package-info.java b/core/src/main/java/org/springframework/security/core/package-info.java index f27dcaf004..e3f6d2e3b0 100644 --- a/core/src/main/java/org/springframework/security/core/package-info.java +++ b/core/src/main/java/org/springframework/security/core/package-info.java @@ -14,8 +14,7 @@ * limitations under the License. */ /** - * Core classes and interfaces related to user authentication and authorization, as well as the maintenance of - * a security context. + * Core classes and interfaces related to user authentication and authorization, as well + * as the maintenance of a security context. */ package org.springframework.security.core; - diff --git a/core/src/main/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscoverer.java b/core/src/main/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscoverer.java index daac6e6d95..93777caf6d 100644 --- a/core/src/main/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscoverer.java +++ b/core/src/main/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscoverer.java @@ -82,7 +82,6 @@ import org.springframework.util.ReflectionUtils; *

      * * @see DefaultSecurityParameterNameDiscoverer - * * @author Rob Winch * @since 3.2 */ @@ -95,8 +94,7 @@ public class AnnotationParameterNameDiscoverer implements ParameterNameDiscovere } public AnnotationParameterNameDiscoverer(Set annotationClassesToUse) { - Assert.notEmpty(annotationClassesToUse, - "annotationClassesToUse cannot be null or empty"); + Assert.notEmpty(annotationClassesToUse, "annotationClassesToUse cannot be null or empty"); this.annotationClassesToUse = annotationClassesToUse; } @@ -108,16 +106,14 @@ public class AnnotationParameterNameDiscoverer implements ParameterNameDiscovere */ public String[] getParameterNames(Method method) { Method originalMethod = BridgeMethodResolver.findBridgedMethod(method); - String[] paramNames = lookupParameterNames(METHOD_METHODPARAM_FACTORY, - originalMethod); + String[] paramNames = lookupParameterNames(METHOD_METHODPARAM_FACTORY, originalMethod); if (paramNames != null) { return paramNames; } Class declaringClass = method.getDeclaringClass(); Class[] interfaces = declaringClass.getInterfaces(); for (Class intrfc : interfaces) { - Method intrfcMethod = ReflectionUtils.findMethod(intrfc, method.getName(), - method.getParameterTypes()); + Method intrfcMethod = ReflectionUtils.findMethod(intrfc, method.getName(), method.getParameterTypes()); if (intrfcMethod != null) { return lookupParameterNames(METHOD_METHODPARAM_FACTORY, intrfcMethod); } @@ -137,14 +133,13 @@ public class AnnotationParameterNameDiscoverer implements ParameterNameDiscovere /** * Gets the parameter names or null if not found. - * * @param parameterNameFactory the {@link ParameterNameFactory} to use * @param t the {@link AccessibleObject} to find the parameter names on (i.e. Method * or Constructor) * @return the parameter names or null */ - private String[] lookupParameterNames( - ParameterNameFactory parameterNameFactory, T t) { + private String[] lookupParameterNames(ParameterNameFactory parameterNameFactory, + T t) { Annotation[][] parameterAnnotations = parameterNameFactory.findParameterAnnotations(t); int parameterCount = parameterAnnotations.length; String[] paramNames = new String[parameterCount]; @@ -164,30 +159,29 @@ public class AnnotationParameterNameDiscoverer implements ParameterNameDiscovere * Finds the parameter name from the provided {@link Annotation}s or null if it could * not find it. The search is done by looking at the value property of the * {@link #annotationClassesToUse}. - * * @param parameterAnnotations the {@link Annotation}'s to search. * @return */ private String findParameterName(Annotation[] parameterAnnotations) { for (Annotation paramAnnotation : parameterAnnotations) { - if (annotationClassesToUse.contains(paramAnnotation.annotationType() - .getName())) { + if (annotationClassesToUse.contains(paramAnnotation.annotationType().getName())) { return (String) AnnotationUtils.getValue(paramAnnotation, "value"); } } return null; } - private static final ParameterNameFactory> CONSTRUCTOR_METHODPARAM_FACTORY = constructor -> constructor.getParameterAnnotations(); + private static final ParameterNameFactory> CONSTRUCTOR_METHODPARAM_FACTORY = constructor -> constructor + .getParameterAnnotations(); - private static final ParameterNameFactory METHOD_METHODPARAM_FACTORY = method -> method.getParameterAnnotations(); + private static final ParameterNameFactory METHOD_METHODPARAM_FACTORY = method -> method + .getParameterAnnotations(); /** * Strategy interface for looking up the parameter names. * * @author Rob Winch * @since 3.2 - * * @param the type to inspect (i.e. {@link Method} or {@link Constructor}) */ private interface ParameterNameFactory { @@ -199,5 +193,7 @@ public class AnnotationParameterNameDiscoverer implements ParameterNameDiscovere * @return */ Annotation[][] findParameterAnnotations(T t); + } + } diff --git a/core/src/main/java/org/springframework/security/core/parameters/DefaultSecurityParameterNameDiscoverer.java b/core/src/main/java/org/springframework/security/core/parameters/DefaultSecurityParameterNameDiscoverer.java index c7c10fe90c..45161c67f6 100644 --- a/core/src/main/java/org/springframework/security/core/parameters/DefaultSecurityParameterNameDiscoverer.java +++ b/core/src/main/java/org/springframework/security/core/parameters/DefaultSecurityParameterNameDiscoverer.java @@ -45,18 +45,16 @@ import org.springframework.util.ClassUtils; * * * @see AnnotationParameterNameDiscoverer - * * @author Rob Winch * @since 3.2 */ -public class DefaultSecurityParameterNameDiscoverer extends - PrioritizedParameterNameDiscoverer { +public class DefaultSecurityParameterNameDiscoverer extends PrioritizedParameterNameDiscoverer { private final Log logger = LogFactory.getLog(getClass()); private static final String DATA_PARAM_CLASSNAME = "org.springframework.data.repository.query.Param"; - private static final boolean DATA_PARAM_PRESENT = ClassUtils.isPresent( - DATA_PARAM_CLASSNAME, + + private static final boolean DATA_PARAM_PRESENT = ClassUtils.isPresent(DATA_PARAM_CLASSNAME, DefaultSecurityParameterNameDiscoverer.class.getClassLoader()); /** @@ -64,7 +62,7 @@ public class DefaultSecurityParameterNameDiscoverer extends * instances. */ public DefaultSecurityParameterNameDiscoverer() { - this(Collections. emptyList()); + this(Collections.emptyList()); } /** @@ -74,8 +72,7 @@ public class DefaultSecurityParameterNameDiscoverer extends * defaults. Cannot be null. */ @SuppressWarnings("unchecked") - public DefaultSecurityParameterNameDiscoverer( - List parameterNameDiscovers) { + public DefaultSecurityParameterNameDiscoverer(List parameterNameDiscovers) { Assert.notNull(parameterNameDiscovers, "parameterNameDiscovers cannot be null"); for (ParameterNameDiscoverer discover : parameterNameDiscovers) { addDiscoverer(discover); @@ -91,4 +88,5 @@ public class DefaultSecurityParameterNameDiscoverer extends addDiscoverer(new AnnotationParameterNameDiscoverer(annotationClassesToUse)); addDiscoverer(new DefaultParameterNameDiscoverer()); } + } diff --git a/core/src/main/java/org/springframework/security/core/parameters/P.java b/core/src/main/java/org/springframework/security/core/parameters/P.java index f828e3795c..416aa43712 100644 --- a/core/src/main/java/org/springframework/security/core/parameters/P.java +++ b/core/src/main/java/org/springframework/security/core/parameters/P.java @@ -41,4 +41,5 @@ public @interface P { * @return */ String value(); + } diff --git a/core/src/main/java/org/springframework/security/core/session/AbstractSessionEvent.java b/core/src/main/java/org/springframework/security/core/session/AbstractSessionEvent.java index 5a43b2d6de..4c8c20da5c 100644 --- a/core/src/main/java/org/springframework/security/core/session/AbstractSessionEvent.java +++ b/core/src/main/java/org/springframework/security/core/session/AbstractSessionEvent.java @@ -29,4 +29,5 @@ public class AbstractSessionEvent extends ApplicationEvent { public AbstractSessionEvent(Object source) { super(source); } + } diff --git a/core/src/main/java/org/springframework/security/core/session/SessionCreationEvent.java b/core/src/main/java/org/springframework/security/core/session/SessionCreationEvent.java index 97471c85e1..2f62732e97 100644 --- a/core/src/main/java/org/springframework/security/core/session/SessionCreationEvent.java +++ b/core/src/main/java/org/springframework/security/core/session/SessionCreationEvent.java @@ -27,4 +27,5 @@ public abstract class SessionCreationEvent extends AbstractSessionEvent { public SessionCreationEvent(Object source) { super(source); } + } diff --git a/core/src/main/java/org/springframework/security/core/session/SessionDestroyedEvent.java b/core/src/main/java/org/springframework/security/core/session/SessionDestroyedEvent.java index 785c40c0e6..52e5233d2a 100644 --- a/core/src/main/java/org/springframework/security/core/session/SessionDestroyedEvent.java +++ b/core/src/main/java/org/springframework/security/core/session/SessionDestroyedEvent.java @@ -35,7 +35,6 @@ public abstract class SessionDestroyedEvent extends AbstractSessionEvent { /** * Provides the {@code SecurityContext} instances which were associated with the * destroyed session. Usually there will be only one security context per session. - * * @return the {@code SecurityContext} instances which were stored in the current * session (an empty list if there are none). */ @@ -45,4 +44,5 @@ public abstract class SessionDestroyedEvent extends AbstractSessionEvent { * @return the identifier associated with the destroyed session. */ public abstract String getId(); + } diff --git a/core/src/main/java/org/springframework/security/core/session/SessionIdChangedEvent.java b/core/src/main/java/org/springframework/security/core/session/SessionIdChangedEvent.java index 640cdf7618..d46bb20c45 100644 --- a/core/src/main/java/org/springframework/security/core/session/SessionIdChangedEvent.java +++ b/core/src/main/java/org/springframework/security/core/session/SessionIdChangedEvent.java @@ -16,8 +16,8 @@ package org.springframework.security.core.session; /** - * Generic "session ID changed" event which indicates that a session - * identifier (potentially represented by a security context) has changed. + * Generic "session ID changed" event which indicates that a session identifier + * (potentially represented by a security context) has changed. * * @since 5.4 */ @@ -29,16 +29,14 @@ public abstract class SessionIdChangedEvent extends AbstractSessionEvent { /** * Returns the old session ID. - * - * @return the identifier that was previously associated with - * the session. + * @return the identifier that was previously associated with the session. */ public abstract String getOldSessionId(); /** * Returns the new session ID. - * * @return the new identifier that is associated with the session. */ public abstract String getNewSessionId(); + } diff --git a/core/src/main/java/org/springframework/security/core/session/SessionInformation.java b/core/src/main/java/org/springframework/security/core/session/SessionInformation.java index fd7ae3ff73..09e4be8feb 100644 --- a/core/src/main/java/org/springframework/security/core/session/SessionInformation.java +++ b/core/src/main/java/org/springframework/security/core/session/SessionInformation.java @@ -45,8 +45,11 @@ public class SessionInformation implements Serializable { // ================================================================================================ private Date lastRequest; + private final Object principal; + private final String sessionId; + private boolean expired = false; // ~ Constructors @@ -90,4 +93,5 @@ public class SessionInformation implements Serializable { public void refreshLastRequest() { this.lastRequest = new Date(); } + } diff --git a/core/src/main/java/org/springframework/security/core/session/SessionRegistry.java b/core/src/main/java/org/springframework/security/core/session/SessionRegistry.java index 68f4ab054a..017ee8750e 100644 --- a/core/src/main/java/org/springframework/security/core/session/SessionRegistry.java +++ b/core/src/main/java/org/springframework/security/core/session/SessionRegistry.java @@ -24,12 +24,12 @@ import java.util.List; * @author Ben Alex */ public interface SessionRegistry { + // ~ Methods // ======================================================================================================== /** * Obtains all the known principals in the SessionRegistry. - * * @return each of the unique principals, which can then be presented to * {@link #getAllSessions(Object, boolean)}. */ @@ -39,22 +39,17 @@ public interface SessionRegistry { * Obtains all the known sessions for the specified principal. Sessions that have been * destroyed are not returned. Sessions that have expired may be returned, depending * on the passed argument. - * * @param principal to locate sessions for (should never be null) * @param includeExpiredSessions if true, the returned sessions will also * include those that have expired for the principal - * * @return the matching sessions for this principal (should not return null). */ - List getAllSessions(Object principal, - boolean includeExpiredSessions); + List getAllSessions(Object principal, boolean includeExpiredSessions); /** * Obtains the session information for the specified sessionId. Even * expired sessions are returned (although destroyed sessions are never returned). - * * @param sessionId to lookup (should never be null) - * * @return the session information, or null if not found */ SessionInformation getSessionInformation(String sessionId); @@ -63,7 +58,6 @@ public interface SessionRegistry { * Updates the given sessionId so its last request time is equal to the * present date and time. Silently returns if the given sessionId cannot * be found or the session is marked to expire. - * * @param sessionId for which to update the date and time of the last request (should * never be null) */ @@ -72,7 +66,6 @@ public interface SessionRegistry { /** * Registers a new session for the specified principal. The newly registered session * will not be marked for expiration. - * * @param sessionId to associate with the principal (should never be null * ) * @param principal to associate with the session (should never be null) @@ -83,8 +76,8 @@ public interface SessionRegistry { * Deletes all the session information being maintained for the specified * sessionId. If the sessionId is not found, the method * gracefully returns. - * * @param sessionId to delete information for (should never be null) */ void removeSessionInformation(String sessionId); + } diff --git a/core/src/main/java/org/springframework/security/core/session/SessionRegistryImpl.java b/core/src/main/java/org/springframework/security/core/session/SessionRegistryImpl.java index fa00255902..e6f5910557 100644 --- a/core/src/main/java/org/springframework/security/core/session/SessionRegistryImpl.java +++ b/core/src/main/java/org/springframework/security/core/session/SessionRegistryImpl.java @@ -33,14 +33,14 @@ import java.util.concurrent.CopyOnWriteArraySet; * SessionDestroyedEvent}s published in the Spring application context. *

      * For this class to function correctly in a web application, it is important that you - * register an HttpSessionEventPublisher + * register an HttpSessionEventPublisher * in the web.xml file so that this class is notified of sessions that expire. * * @author Ben Alex * @author Luke Taylor */ -public class SessionRegistryImpl implements SessionRegistry, - ApplicationListener { +public class SessionRegistryImpl implements SessionRegistry, ApplicationListener { // ~ Instance fields // ================================================================================================ @@ -49,6 +49,7 @@ public class SessionRegistryImpl implements SessionRegistry, /** */ private final ConcurrentMap> principals; + /** */ private final Map sessionIds; @@ -60,25 +61,24 @@ public class SessionRegistryImpl implements SessionRegistry, this.sessionIds = new ConcurrentHashMap<>(); } - public SessionRegistryImpl(ConcurrentMap> principals, Map sessionIds) { - this.principals=principals; - this.sessionIds=sessionIds; + public SessionRegistryImpl(ConcurrentMap> principals, + Map sessionIds) { + this.principals = principals; + this.sessionIds = sessionIds; } public List getAllPrincipals() { return new ArrayList<>(principals.keySet()); } - public List getAllSessions(Object principal, - boolean includeExpiredSessions) { + public List getAllSessions(Object principal, boolean includeExpiredSessions) { final Set sessionsUsedByPrincipal = principals.get(principal); if (sessionsUsedByPrincipal == null) { return Collections.emptyList(); } - List list = new ArrayList<>( - sessionsUsedByPrincipal.size()); + List list = new ArrayList<>(sessionsUsedByPrincipal.size()); for (String sessionId : sessionsUsedByPrincipal) { SessionInformation sessionInformation = getSessionInformation(sessionId); @@ -106,7 +106,8 @@ public class SessionRegistryImpl implements SessionRegistry, SessionDestroyedEvent sessionDestroyedEvent = (SessionDestroyedEvent) event; String sessionId = sessionDestroyedEvent.getId(); removeSessionInformation(sessionId); - } else if (event instanceof SessionIdChangedEvent) { + } + else if (event instanceof SessionIdChangedEvent) { SessionIdChangedEvent sessionIdChangedEvent = (SessionIdChangedEvent) event; String oldSessionId = sessionIdChangedEvent.getOldSessionId(); Object principal = sessionIds.get(oldSessionId).getPrincipal(); @@ -134,12 +135,10 @@ public class SessionRegistryImpl implements SessionRegistry, } if (logger.isDebugEnabled()) { - logger.debug("Registering session " + sessionId + ", for principal " - + principal); + logger.debug("Registering session " + sessionId + ", for principal " + principal); } - sessionIds.put(sessionId, - new SessionInformation(principal, sessionId, new Date())); + sessionIds.put(sessionId, new SessionInformation(principal, sessionId, new Date())); principals.compute(principal, (key, sessionsUsedByPrincipal) -> { if (sessionsUsedByPrincipal == null) { @@ -148,8 +147,7 @@ public class SessionRegistryImpl implements SessionRegistry, sessionsUsedByPrincipal.add(sessionId); if (logger.isTraceEnabled()) { - logger.trace("Sessions used by '" + principal + "' : " - + sessionsUsedByPrincipal); + logger.trace("Sessions used by '" + principal + "' : " + sessionsUsedByPrincipal); } return sessionsUsedByPrincipal; }); @@ -165,16 +163,14 @@ public class SessionRegistryImpl implements SessionRegistry, } if (logger.isTraceEnabled()) { - logger.debug("Removing session " + sessionId - + " from set of registered sessions"); + logger.debug("Removing session " + sessionId + " from set of registered sessions"); } sessionIds.remove(sessionId); principals.computeIfPresent(info.getPrincipal(), (key, sessionsUsedByPrincipal) -> { if (logger.isDebugEnabled()) { - logger.debug("Removing session " + sessionId - + " from principal's set of registered sessions"); + logger.debug("Removing session " + sessionId + " from principal's set of registered sessions"); } sessionsUsedByPrincipal.remove(sessionId); @@ -182,15 +178,13 @@ public class SessionRegistryImpl implements SessionRegistry, if (sessionsUsedByPrincipal.isEmpty()) { // No need to keep object in principals Map anymore if (logger.isDebugEnabled()) { - logger.debug("Removing principal " + info.getPrincipal() - + " from registry"); + logger.debug("Removing principal " + info.getPrincipal() + " from registry"); } sessionsUsedByPrincipal = null; } if (logger.isTraceEnabled()) { - logger.trace("Sessions used by '" + info.getPrincipal() + "' : " - + sessionsUsedByPrincipal); + logger.trace("Sessions used by '" + info.getPrincipal() + "' : " + sessionsUsedByPrincipal); } return sessionsUsedByPrincipal; }); diff --git a/core/src/main/java/org/springframework/security/core/session/package-info.java b/core/src/main/java/org/springframework/security/core/session/package-info.java index 7b40d87320..3dc76e0a5d 100644 --- a/core/src/main/java/org/springframework/security/core/session/package-info.java +++ b/core/src/main/java/org/springframework/security/core/session/package-info.java @@ -14,9 +14,11 @@ * limitations under the License. */ /** - * Session abstraction which is provided by the {@code org.springframework.security.core.session.SessionInformation - * SessionInformation} class. The {@link org.springframework.security.core.session.SessionRegistry SessionRegistry} - * is a core part of the web-based concurrent session control, but the code is not dependent on any of the servlet APIs. + * Session abstraction which is provided by the + * {@code org.springframework.security.core.session.SessionInformation + * SessionInformation} class. The + * {@link org.springframework.security.core.session.SessionRegistry SessionRegistry} is a + * core part of the web-based concurrent session control, but the code is not dependent on + * any of the servlet APIs. */ package org.springframework.security.core.session; - diff --git a/core/src/main/java/org/springframework/security/core/token/DefaultToken.java b/core/src/main/java/org/springframework/security/core/token/DefaultToken.java index f5db72c9d0..77fc1a3622 100644 --- a/core/src/main/java/org/springframework/security/core/token/DefaultToken.java +++ b/core/src/main/java/org/springframework/security/core/token/DefaultToken.java @@ -26,8 +26,11 @@ import org.springframework.util.Assert; * @since 2.0.1 */ public class DefaultToken implements Token { + private final String key; + private final long keyCreationTime; + private final String extendedInformation; public DefaultToken(String key, long keyCreationTime, String extendedInformation) { @@ -57,8 +60,7 @@ public class DefaultToken implements Token { public boolean equals(Object obj) { if (obj != null && obj instanceof DefaultToken) { DefaultToken rhs = (DefaultToken) obj; - return this.key.equals(rhs.key) - && this.keyCreationTime == rhs.keyCreationTime + return this.key.equals(rhs.key) && this.keyCreationTime == rhs.keyCreationTime && this.extendedInformation.equals(rhs.extendedInformation); } return false; @@ -75,8 +77,8 @@ public class DefaultToken implements Token { @Override public String toString() { - return "DefaultToken[key=" + key + "; creation=" + new Date(keyCreationTime) - + "; extended=" + extendedInformation + "]"; + return "DefaultToken[key=" + key + "; creation=" + new Date(keyCreationTime) + "; extended=" + + extendedInformation + "]"; } } diff --git a/core/src/main/java/org/springframework/security/core/token/KeyBasedPersistenceTokenService.java b/core/src/main/java/org/springframework/security/core/token/KeyBasedPersistenceTokenService.java index b38b078665..d4114cb19f 100644 --- a/core/src/main/java/org/springframework/security/core/token/KeyBasedPersistenceTokenService.java +++ b/core/src/main/java/org/springframework/security/core/token/KeyBasedPersistenceTokenService.java @@ -72,19 +72,21 @@ import org.springframework.util.StringUtils; * */ public class KeyBasedPersistenceTokenService implements TokenService, InitializingBean { + private int pseudoRandomNumberBytes = 32; + private String serverSecret; + private Integer serverInteger; + private SecureRandom secureRandom; public Token allocateToken(String extendedInformation) { - Assert.notNull(extendedInformation, - "Must provided non-null extendedInformation (but it can be empty)"); + Assert.notNull(extendedInformation, "Must provided non-null extendedInformation (but it can be empty)"); long creationTime = new Date().getTime(); String serverSecret = computeServerSecretApplicableAt(creationTime); String pseudoRandomNumber = generatePseudoRandomNumber(); - String content = creationTime + ":" + pseudoRandomNumber + ":" - + extendedInformation; + String content = creationTime + ":" + pseudoRandomNumber + ":" + extendedInformation; // Compute key String sha512Hex = Sha512DigestUtils.shaHex(content + ":" + serverSecret); @@ -98,10 +100,9 @@ public class KeyBasedPersistenceTokenService implements TokenService, Initializi if (key == null || "".equals(key)) { return null; } - String[] tokens = StringUtils.delimitedListToStringArray( - Utf8.decode(Base64.getDecoder().decode(Utf8.encode(key))), ":"); - Assert.isTrue(tokens.length >= 4, () -> "Expected 4 or more tokens but found " - + tokens.length); + String[] tokens = StringUtils + .delimitedListToStringArray(Utf8.decode(Base64.getDecoder().decode(Utf8.encode(key))), ":"); + Assert.isTrue(tokens.length >= 4, () -> "Expected 4 or more tokens but found " + tokens.length); long creationTime; try { @@ -126,8 +127,7 @@ public class KeyBasedPersistenceTokenService implements TokenService, Initializi String sha1Hex = tokens[tokens.length - 1]; // Verification - String content = creationTime + ":" + pseudoRandomNumber + ":" - + extendedInfo.toString(); + String content = creationTime + ":" + pseudoRandomNumber + ":" + extendedInfo.toString(); String expectedSha512Hex = Sha512DigestUtils.shaHex(content + ":" + serverSecret); Assert.isTrue(expectedSha512Hex.equals(sha1Hex), "Key verification failure"); @@ -164,8 +164,7 @@ public class KeyBasedPersistenceTokenService implements TokenService, Initializi * defaults to 256) */ public void setPseudoRandomNumberBytes(int pseudoRandomNumberBytes) { - Assert.isTrue(pseudoRandomNumberBytes >= 0, - "Must have a positive pseudo random number bit size"); + Assert.isTrue(pseudoRandomNumberBytes >= 0, "Must have a positive pseudo random number bit size"); this.pseudoRandomNumberBytes = pseudoRandomNumberBytes; } @@ -178,4 +177,5 @@ public class KeyBasedPersistenceTokenService implements TokenService, Initializi Assert.notNull(serverInteger, "Server integer required"); Assert.notNull(secureRandom, "SecureRandom instance required"); } + } diff --git a/core/src/main/java/org/springframework/security/core/token/SecureRandomFactoryBean.java b/core/src/main/java/org/springframework/security/core/token/SecureRandomFactoryBean.java index 2d640de72a..fed76cf109 100644 --- a/core/src/main/java/org/springframework/security/core/token/SecureRandomFactoryBean.java +++ b/core/src/main/java/org/springframework/security/core/token/SecureRandomFactoryBean.java @@ -32,6 +32,7 @@ import org.springframework.util.FileCopyUtils; public class SecureRandomFactoryBean implements FactoryBean { private String algorithm = "SHA1PRNG"; + private Resource seed; public SecureRandom getObject() throws Exception { @@ -61,7 +62,6 @@ public class SecureRandomFactoryBean implements FactoryBean { /** * Allows the Pseudo Random Number Generator (PRNG) algorithm to be nominated. * Defaults to "SHA1PRNG". - * * @param algorithm to use (mandatory) */ public void setAlgorithm(String algorithm) { @@ -76,10 +76,10 @@ public class SecureRandomFactoryBean implements FactoryBean { * {@link SecureRandom#setSeed(byte[])} method. Note that this will simply supplement, * rather than replace, the existing seed. As such, it is always safe to set a seed * using this method (it never reduces randomness). - * * @param seed to use, or null if no additional seeding is needed */ public void setSeed(Resource seed) { this.seed = seed; } + } diff --git a/core/src/main/java/org/springframework/security/core/token/Sha512DigestUtils.java b/core/src/main/java/org/springframework/security/core/token/Sha512DigestUtils.java index d1c354955b..a2c16a14fa 100644 --- a/core/src/main/java/org/springframework/security/core/token/Sha512DigestUtils.java +++ b/core/src/main/java/org/springframework/security/core/token/Sha512DigestUtils.java @@ -35,7 +35,6 @@ public abstract class Sha512DigestUtils { /** * Returns an SHA digest. - * * @return An SHA digest instance. * @throws RuntimeException when a {@link java.security.NoSuchAlgorithmException} is * caught. @@ -51,7 +50,6 @@ public abstract class Sha512DigestUtils { /** * Calculates the SHA digest and returns the value as a byte[]. - * * @param data Data to digest * @return SHA digest */ @@ -61,7 +59,6 @@ public abstract class Sha512DigestUtils { /** * Calculates the SHA digest and returns the value as a byte[]. - * * @param data Data to digest * @return SHA digest */ @@ -71,7 +68,6 @@ public abstract class Sha512DigestUtils { /** * Calculates the SHA digest and returns the value as a hex string. - * * @param data Data to digest * @return SHA digest as a hex string */ @@ -81,7 +77,6 @@ public abstract class Sha512DigestUtils { /** * Calculates the SHA digest and returns the value as a hex string. - * * @param data Data to digest * @return SHA digest as a hex string */ diff --git a/core/src/main/java/org/springframework/security/core/token/Token.java b/core/src/main/java/org/springframework/security/core/token/Token.java index 54f8a0ffb9..0ab19a8924 100644 --- a/core/src/main/java/org/springframework/security/core/token/Token.java +++ b/core/src/main/java/org/springframework/security/core/token/Token.java @@ -36,7 +36,6 @@ public interface Token { * Obtains the randomised, secure key assigned to this token. Presentation of this * token to {@link TokenService} will always return a Token that is equal * to the original Token issued for that key. - * * @return a key with appropriate randomness and security. */ String getKey(); @@ -45,7 +44,6 @@ public interface Token { * The time the token key was initially created is available from this method. Note * that a given token must never have this creation time changed. If necessary, a new * token can be requested from the {@link TokenService} to replace the original token. - * * @return the time this token key was created, in the same format as specified by * {@link java.util.Date#getTime()}. */ @@ -54,8 +52,8 @@ public interface Token { /** * Obtains the extended information associated within the token, which was presented * when the token was first created. - * * @return the user-specified extended information, if any */ String getExtendedInformation(); + } diff --git a/core/src/main/java/org/springframework/security/core/token/TokenService.java b/core/src/main/java/org/springframework/security/core/token/TokenService.java index b54af4d317..167163ca55 100644 --- a/core/src/main/java/org/springframework/security/core/token/TokenService.java +++ b/core/src/main/java/org/springframework/security/core/token/TokenService.java @@ -41,9 +41,9 @@ package org.springframework.security.core.token; * */ public interface TokenService { + /** * Forces the allocation of a new {@link Token}. - * * @param extendedInformation the extended information desired in the token (cannot be * null, but can be empty) * @return a new token that has not been issued previously, and is guaranteed to be @@ -55,11 +55,11 @@ public interface TokenService { /** * Permits verification the {@link Token#getKey()} was issued by this * TokenService and reconstructs the corresponding Token. - * * @param key as obtained from {@link Token#getKey()} and created by this * implementation * @return the token, or null if the token was not issued by this * TokenService */ Token verifyToken(String key); + } diff --git a/core/src/main/java/org/springframework/security/core/token/package-info.java b/core/src/main/java/org/springframework/security/core/token/package-info.java index b0cefaf120..ed6b3e931e 100644 --- a/core/src/main/java/org/springframework/security/core/token/package-info.java +++ b/core/src/main/java/org/springframework/security/core/token/package-info.java @@ -17,4 +17,3 @@ * A service for building secure random tokens. */ package org.springframework.security.core.token; - diff --git a/core/src/main/java/org/springframework/security/core/userdetails/AuthenticationUserDetailsService.java b/core/src/main/java/org/springframework/security/core/userdetails/AuthenticationUserDetailsService.java index 7284ec5d93..c87c32f8e9 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/AuthenticationUserDetailsService.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/AuthenticationUserDetailsService.java @@ -27,11 +27,11 @@ import org.springframework.security.core.Authentication; public interface AuthenticationUserDetailsService { /** - * * @param token The pre-authenticated authentication token * @return UserDetails for the given authentication token, never null. * @throws UsernameNotFoundException if no user details can be found for the given * authentication token */ UserDetails loadUserDetails(T token) throws UsernameNotFoundException; + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsService.java b/core/src/main/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsService.java index f0d8c12e56..6c5e7c0b0b 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsService.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsService.java @@ -31,6 +31,7 @@ import reactor.core.publisher.Mono; * @since 5.0 */ public class MapReactiveUserDetailsService implements ReactiveUserDetailsService, ReactiveUserDetailsPasswordService { + private final Map users; /** @@ -70,19 +71,14 @@ public class MapReactiveUserDetailsService implements ReactiveUserDetailsService @Override public Mono updatePassword(UserDetails user, String newPassword) { - return Mono.just(user) - .map(u -> - User.withUserDetails(u) - .password(newPassword) - .build() - ) - .doOnNext(u -> { - String key = getKey(user.getUsername()); - this.users.put(key, u); - }); + return Mono.just(user).map(u -> User.withUserDetails(u).password(newPassword).build()).doOnNext(u -> { + String key = getKey(user.getUsername()); + this.users.put(key, u); + }); } private String getKey(String username) { return username.toLowerCase(); } + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/ReactiveUserDetailsPasswordService.java b/core/src/main/java/org/springframework/security/core/userdetails/ReactiveUserDetailsPasswordService.java index 867c59758a..57e55bb2ce 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/ReactiveUserDetailsPasswordService.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/ReactiveUserDetailsPasswordService.java @@ -20,6 +20,7 @@ import reactor.core.publisher.Mono; /** * An API for changing a {@link UserDetails} password. + * * @author Rob Winch * @since 5.1 */ @@ -28,10 +29,10 @@ public interface ReactiveUserDetailsPasswordService { /** * Modify the specified user's password. This should change the user's password in the * persistent user repository (datbase, LDAP etc). - * * @param user the user to modify the password for * @param newPassword the password to change to * @return the updated UserDetails with the new password */ Mono updatePassword(UserDetails user, String newPassword); + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/ReactiveUserDetailsService.java b/core/src/main/java/org/springframework/security/core/userdetails/ReactiveUserDetailsService.java index c66fbec0a6..63c9b6546d 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/ReactiveUserDetailsService.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/ReactiveUserDetailsService.java @@ -32,4 +32,5 @@ public interface ReactiveUserDetailsService { * @return the {@link UserDetails}. Cannot be null */ Mono findByUsername(String username); + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/User.java b/core/src/main/java/org/springframework/security/core/userdetails/User.java index 05419a012e..3f256021b1 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/User.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/User.java @@ -68,11 +68,17 @@ public class User implements UserDetails, CredentialsContainer { // ~ Instance fields // ================================================================================================ private String password; + private final String username; + private final Set authorities; + private final boolean accountNonExpired; + private final boolean accountNonLocked; + private final boolean credentialsNonExpired; + private final boolean enabled; // ~ Constructors @@ -81,15 +87,13 @@ public class User implements UserDetails, CredentialsContainer { /** * Calls the more complex constructor with all boolean arguments set to {@code true}. */ - public User(String username, String password, - Collection authorities) { + public User(String username, String password, Collection authorities) { this(username, password, true, true, true, true, authorities); } /** * Construct the User with the details required by * {@link org.springframework.security.authentication.dao.DaoAuthenticationProvider}. - * * @param username the username presented to the * DaoAuthenticationProvider * @param password the password that should be presented to the @@ -101,17 +105,15 @@ public class User implements UserDetails, CredentialsContainer { * @param accountNonLocked set to true if the account is not locked * @param authorities the authorities that should be granted to the caller if they * presented the correct username and password and the user is enabled. Not null. - * * @throws IllegalArgumentException if a null value was passed either as * a parameter or as an element in the GrantedAuthority collection */ - public User(String username, String password, boolean enabled, - boolean accountNonExpired, boolean credentialsNonExpired, - boolean accountNonLocked, Collection authorities) { + public User(String username, String password, boolean enabled, boolean accountNonExpired, + boolean credentialsNonExpired, boolean accountNonLocked, + Collection authorities) { if (((username == null) || "".equals(username)) || (password == null)) { - throw new IllegalArgumentException( - "Cannot pass null or empty values to constructor"); + throw new IllegalArgumentException("Cannot pass null or empty values to constructor"); } this.username = username; @@ -158,25 +160,22 @@ public class User implements UserDetails, CredentialsContainer { password = null; } - private static SortedSet sortAuthorities( - Collection authorities) { + private static SortedSet sortAuthorities(Collection authorities) { Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection"); // Ensure array iteration order is predictable (as per // UserDetails.getAuthorities() contract and SEC-717) - SortedSet sortedAuthorities = new TreeSet<>( - new AuthorityComparator()); + SortedSet sortedAuthorities = new TreeSet<>(new AuthorityComparator()); for (GrantedAuthority grantedAuthority : authorities) { - Assert.notNull(grantedAuthority, - "GrantedAuthority list cannot contain any null elements"); + Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements"); sortedAuthorities.add(grantedAuthority); } return sortedAuthorities; } - private static class AuthorityComparator implements Comparator, - Serializable { + private static class AuthorityComparator implements Comparator, Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; public int compare(GrantedAuthority g1, GrantedAuthority g2) { @@ -194,6 +193,7 @@ public class User implements UserDetails, CredentialsContainer { return g1.getAuthority().compareTo(g2.getAuthority()); } + } /** @@ -227,8 +227,7 @@ public class User implements UserDetails, CredentialsContainer { sb.append("Password: [PROTECTED]; "); sb.append("Enabled: ").append(this.enabled).append("; "); sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; "); - sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired) - .append("; "); + sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; "); sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; "); if (!authorities.isEmpty()) { @@ -253,7 +252,6 @@ public class User implements UserDetails, CredentialsContainer { /** * Creates a UserBuilder with a specified user name - * * @param username the username to use * @return the UserBuilder */ @@ -263,7 +261,6 @@ public class User implements UserDetails, CredentialsContainer { /** * Creates a UserBuilder - * * @return the UserBuilder */ public static UserBuilder builder() { @@ -272,8 +269,8 @@ public class User implements UserDetails, CredentialsContainer { /** *

      - * WARNING: This method is considered unsafe for production and is only intended - * for sample applications. + * WARNING: This method is considered unsafe for production and is only + * intended for sample applications. *

      *

      * Creates a user and automatically encodes the provided password using @@ -289,8 +286,7 @@ public class User implements UserDetails, CredentialsContainer { * .build(); * // outputs {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG * System.out.println(user.getPassword()); - * - * + * * * This is not safe for production (it is intended for getting started experience) * because the password "password" is compiled into the source code and then is @@ -300,8 +296,8 @@ public class User implements UserDetails, CredentialsContainer { * securely hashed. This means if the UserDetails password is accidentally exposed, * the password is securely stored. * - * In a production setting, it is recommended to hash the password ahead of time. - * For example: + * In a production setting, it is recommended to hash the password ahead of time. For + * example: * *

       	 * 
      @@ -309,8 +305,7 @@ public class User implements UserDetails, CredentialsContainer {
       	 * // outputs {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
       	 * // remember the password that is printed out and use in the next step
       	 * System.out.println(encoder.encode("password"));
      -	 * 
      -	 * 
      + * * *
       	 * 
      @@ -318,32 +313,28 @@ public class User implements UserDetails, CredentialsContainer {
       	 *     .password("{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG")
       	 *     .roles("USER")
       	 *     .build();
      -	 * 
      -	 * 
      - * + * * @return a UserBuilder that automatically encodes the password with the default * PasswordEncoder * @deprecated Using this method is not considered safe for production, but is * acceptable for demos and getting started. For production purposes, ensure the * password is encoded externally. See the method Javadoc for additional details. - * There are no plans to remove this support. It is deprecated to indicate - * that this is considered insecure for production purposes. + * There are no plans to remove this support. It is deprecated to indicate that this + * is considered insecure for production purposes. */ @Deprecated public static UserBuilder withDefaultPasswordEncoder() { - logger.warn("User.withDefaultPasswordEncoder() is considered unsafe for production and is only intended for sample applications."); + logger.warn( + "User.withDefaultPasswordEncoder() is considered unsafe for production and is only intended for sample applications."); PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); return builder().passwordEncoder(encoder::encode); } public static UserBuilder withUserDetails(UserDetails userDetails) { - return withUsername(userDetails.getUsername()) - .password(userDetails.getPassword()) - .accountExpired(!userDetails.isAccountNonExpired()) - .accountLocked(!userDetails.isAccountNonLocked()) - .authorities(userDetails.getAuthorities()) - .credentialsExpired(!userDetails.isCredentialsNonExpired()) - .disabled(!userDetails.isEnabled()); + return withUsername(userDetails.getUsername()).password(userDetails.getPassword()) + .accountExpired(!userDetails.isAccountNonExpired()).accountLocked(!userDetails.isAccountNonLocked()) + .authorities(userDetails.getAuthorities()).credentialsExpired(!userDetails.isCredentialsNonExpired()) + .disabled(!userDetails.isEnabled()); } /** @@ -351,13 +342,21 @@ public class User implements UserDetails, CredentialsContainer { * should provided. The remaining attributes have reasonable defaults. */ public static class UserBuilder { + private String username; + private String password; + private List authorities; + private boolean accountExpired; + private boolean accountLocked; + private boolean credentialsExpired; + private boolean disabled; + private Function passwordEncoder = password -> password; /** @@ -368,7 +367,6 @@ public class User implements UserDetails, CredentialsContainer { /** * Populates the username. This attribute is required. - * * @param username the username. Cannot be null. * @return the {@link UserBuilder} for method chaining (i.e. to populate * additional attributes for this user) @@ -381,7 +379,6 @@ public class User implements UserDetails, CredentialsContainer { /** * Populates the password. This attribute is required. - * * @param password the password. Cannot be null. * @return the {@link UserBuilder} for method chaining (i.e. to populate * additional attributes for this user) @@ -393,9 +390,8 @@ public class User implements UserDetails, CredentialsContainer { } /** - * Encodes the current password (if non-null) and any future passwords supplied - * to {@link #password(String)}. - * + * Encodes the current password (if non-null) and any future passwords supplied to + * {@link #password(String)}. * @param encoder the encoder to use * @return the {@link UserBuilder} for method chaining (i.e. to populate * additional attributes for this user) @@ -425,18 +421,16 @@ public class User implements UserDetails, CredentialsContainer { * This attribute is required, but can also be populated with * {@link #authorities(String...)}. *

      - * * @param roles the roles for this user (i.e. USER, ADMIN, etc). Cannot be null, * contain null values or start with "ROLE_" * @return the {@link UserBuilder} for method chaining (i.e. to populate * additional attributes for this user) */ public UserBuilder roles(String... roles) { - List authorities = new ArrayList<>( - roles.length); + List authorities = new ArrayList<>(roles.length); for (String role : roles) { - Assert.isTrue(!role.startsWith("ROLE_"), () -> role - + " cannot start with ROLE_ (it is automatically added)"); + Assert.isTrue(!role.startsWith("ROLE_"), + () -> role + " cannot start with ROLE_ (it is automatically added)"); authorities.add(new SimpleGrantedAuthority("ROLE_" + role)); } return authorities(authorities); @@ -444,7 +438,6 @@ public class User implements UserDetails, CredentialsContainer { /** * Populates the authorities. This attribute is required. - * * @param authorities the authorities for this user. Cannot be null, or contain * null values * @return the {@link UserBuilder} for method chaining (i.e. to populate @@ -457,7 +450,6 @@ public class User implements UserDetails, CredentialsContainer { /** * Populates the authorities. This attribute is required. - * * @param authorities the authorities for this user. Cannot be null, or contain * null values * @return the {@link UserBuilder} for method chaining (i.e. to populate @@ -471,7 +463,6 @@ public class User implements UserDetails, CredentialsContainer { /** * Populates the authorities. This attribute is required. - * * @param authorities the authorities for this user (i.e. ROLE_USER, ROLE_ADMIN, * etc). Cannot be null, or contain null values * @return the {@link UserBuilder} for method chaining (i.e. to populate @@ -484,7 +475,6 @@ public class User implements UserDetails, CredentialsContainer { /** * Defines if the account is expired or not. Default is false. - * * @param accountExpired true if the account is expired, false otherwise * @return the {@link UserBuilder} for method chaining (i.e. to populate * additional attributes for this user) @@ -496,7 +486,6 @@ public class User implements UserDetails, CredentialsContainer { /** * Defines if the account is locked or not. Default is false. - * * @param accountLocked true if the account is locked, false otherwise * @return the {@link UserBuilder} for method chaining (i.e. to populate * additional attributes for this user) @@ -508,7 +497,6 @@ public class User implements UserDetails, CredentialsContainer { /** * Defines if the credentials are expired or not. Default is false. - * * @param credentialsExpired true if the credentials are expired, false otherwise * @return the {@link UserBuilder} for method chaining (i.e. to populate * additional attributes for this user) @@ -520,7 +508,6 @@ public class User implements UserDetails, CredentialsContainer { /** * Defines if the account is disabled or not. Default is false. - * * @param disabled true if the account is disabled, false otherwise * @return the {@link UserBuilder} for method chaining (i.e. to populate * additional attributes for this user) @@ -532,8 +519,10 @@ public class User implements UserDetails, CredentialsContainer { public UserDetails build() { String encodedPassword = this.passwordEncoder.apply(password); - return new User(username, encodedPassword, !disabled, !accountExpired, - !credentialsExpired, !accountLocked, authorities); + return new User(username, encodedPassword, !disabled, !accountExpired, !credentialsExpired, !accountLocked, + authorities); } + } + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/UserCache.java b/core/src/main/java/org/springframework/security/core/userdetails/UserCache.java index 2f250e6ff6..da71d3f6ef 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/UserCache.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/UserCache.java @@ -33,18 +33,16 @@ package org.springframework.security.core.userdetails; * each time. * * @see org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider - * * @author Ben Alex */ public interface UserCache { + // ~ Methods // ======================================================================================================== /** * Obtains a {@link UserDetails} from the cache. - * * @param username the {@link User#getUsername()} used to place the user in the cache - * * @return the populated UserDetails or null if the user * could not be found or if the cache entry has expired */ @@ -53,7 +51,6 @@ public interface UserCache { /** * Places a {@link UserDetails} in the cache. The username is the key * used to subsequently retrieve the UserDetails. - * * @param user the fully populated UserDetails to place in the cache */ void putUserInCache(UserDetails user); @@ -66,8 +63,8 @@ public interface UserCache { * Some cache implementations may not support eviction from the cache, in which case * they should provide appropriate behaviour to alter the user in either its * documentation, via an exception, or through a log message. - * * @param username to be evicted from the cache */ void removeUserFromCache(String username); + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/UserDetails.java b/core/src/main/java/org/springframework/security/core/userdetails/UserDetails.java index d1f83da9ef..e4a652489b 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/UserDetails.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/UserDetails.java @@ -38,30 +38,28 @@ import java.util.Collection; * * @see UserDetailsService * @see UserCache - * * @author Ben Alex */ public interface UserDetails extends Serializable { + // ~ Methods // ======================================================================================================== /** * Returns the authorities granted to the user. Cannot return null. - * * @return the authorities, sorted by natural key (never null) */ Collection getAuthorities(); /** * Returns the password used to authenticate the user. - * * @return the password */ String getPassword(); /** - * Returns the username used to authenticate the user. Cannot return null. - * + * Returns the username used to authenticate the user. Cannot return + * null. * @return the username (never null) */ String getUsername(); @@ -69,7 +67,6 @@ public interface UserDetails extends Serializable { /** * Indicates whether the user's account has expired. An expired account cannot be * authenticated. - * * @return true if the user's account is valid (ie non-expired), * false if no longer valid (ie expired) */ @@ -78,7 +75,6 @@ public interface UserDetails extends Serializable { /** * Indicates whether the user is locked or unlocked. A locked user cannot be * authenticated. - * * @return true if the user is not locked, false otherwise */ boolean isAccountNonLocked(); @@ -86,7 +82,6 @@ public interface UserDetails extends Serializable { /** * Indicates whether the user's credentials (password) has expired. Expired * credentials prevent authentication. - * * @return true if the user's credentials are valid (ie non-expired), * false if no longer valid (ie expired) */ @@ -95,8 +90,8 @@ public interface UserDetails extends Serializable { /** * Indicates whether the user is enabled or disabled. A disabled user cannot be * authenticated. - * * @return true if the user is enabled, false otherwise */ boolean isEnabled(); + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsByNameServiceWrapper.java b/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsByNameServiceWrapper.java index daea7fa063..56ca5f49be 100755 --- a/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsByNameServiceWrapper.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsByNameServiceWrapper.java @@ -28,8 +28,9 @@ import org.springframework.util.Assert; * @author Scott Battaglia * @since 2.0 */ -public class UserDetailsByNameServiceWrapper implements - AuthenticationUserDetailsService, InitializingBean { +public class UserDetailsByNameServiceWrapper + implements AuthenticationUserDetailsService, InitializingBean { + private UserDetailsService userDetailsService = null; /** @@ -44,7 +45,6 @@ public class UserDetailsByNameServiceWrapper implement * Constructs a new wrapper using the supplied * {@link org.springframework.security.core.userdetails.UserDetailsService} as the * service to delegate to. - * * @param userDetailsService the UserDetailsService to delegate to. */ public UserDetailsByNameServiceWrapper(final UserDetailsService userDetailsService) { @@ -70,10 +70,10 @@ public class UserDetailsByNameServiceWrapper implement /** * Set the wrapped UserDetailsService implementation - * * @param aUserDetailsService The wrapped UserDetailsService to set */ public void setUserDetailsService(UserDetailsService aUserDetailsService) { this.userDetailsService = aUserDetailsService; } + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsChecker.java b/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsChecker.java index 706022b283..189cd5e28a 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsChecker.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsChecker.java @@ -28,14 +28,15 @@ package org.springframework.security.core.userdetails; * * @author Luke Taylor * @since 2.0 - * * @see org.springframework.security.authentication.AccountStatusUserDetailsChecker * @see org.springframework.security.authentication.AccountStatusException */ public interface UserDetailsChecker { + /** * Examines the User * @param toCheck the UserDetails instance whose status should be checked. */ void check(UserDetails toCheck); + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsPasswordService.java b/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsPasswordService.java index fd56992793..ed85e088aa 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsPasswordService.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsPasswordService.java @@ -18,6 +18,7 @@ package org.springframework.security.core.userdetails; /** * An API for changing a {@link UserDetails} password. + * * @author Rob Winch * @since 5.1 */ @@ -26,11 +27,11 @@ public interface UserDetailsPasswordService { /** * Modify the specified user's password. This should change the user's password in the * persistent user repository (database, LDAP etc). - * * @param user the user to modify the password for - * @param newPassword the password to change to, - * encoded by the configured {@code PasswordEncoder} + * @param newPassword the password to change to, encoded by the configured + * {@code PasswordEncoder} * @return the updated UserDetails with the new password */ UserDetails updatePassword(UserDetails user, String newPassword); + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsService.java b/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsService.java index 82f5631e35..4350d06fff 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsService.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/UserDetailsService.java @@ -29,10 +29,10 @@ package org.springframework.security.core.userdetails; * * @see org.springframework.security.authentication.dao.DaoAuthenticationProvider * @see UserDetails - * * @author Ben Alex */ public interface UserDetailsService { + // ~ Methods // ======================================================================================================== @@ -42,13 +42,11 @@ public interface UserDetailsService { * implementation instance is configured. In this case, the UserDetails * object that comes back may have a username that is of a different case than what * was actually requested.. - * * @param username the username identifying the user whose data is required. - * * @return a fully populated user record (never null) - * * @throws UsernameNotFoundException if the user could not be found or the user has no * GrantedAuthority */ UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/UsernameNotFoundException.java b/core/src/main/java/org/springframework/security/core/userdetails/UsernameNotFoundException.java index af4e5f539a..6851e3a1b5 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/UsernameNotFoundException.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/UsernameNotFoundException.java @@ -25,12 +25,12 @@ import org.springframework.security.core.AuthenticationException; * @author Ben Alex */ public class UsernameNotFoundException extends AuthenticationException { + // ~ Constructors // =================================================================================================== /** * Constructs a UsernameNotFoundException with the specified message. - * * @param msg the detail message. */ public UsernameNotFoundException(String msg) { @@ -40,11 +40,11 @@ public class UsernameNotFoundException extends AuthenticationException { /** * Constructs a {@code UsernameNotFoundException} with the specified message and root * cause. - * * @param msg the detail message. * @param t root cause */ public UsernameNotFoundException(String msg, Throwable t) { super(msg, t); } + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/cache/EhCacheBasedUserCache.java b/core/src/main/java/org/springframework/security/core/userdetails/cache/EhCacheBasedUserCache.java index dacd1c69cf..3fdf210395 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/cache/EhCacheBasedUserCache.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/cache/EhCacheBasedUserCache.java @@ -27,12 +27,13 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.util.Assert; /** - * Caches User objects using a Spring IoC defined EHCACHE. + * Caches User objects using a Spring IoC defined + * EHCACHE. * * @author Ben Alex */ public class EhCacheBasedUserCache implements UserCache, InitializingBean { + // ~ Static fields/initializers // ===================================================================================== @@ -94,4 +95,5 @@ public class EhCacheBasedUserCache implements UserCache, InitializingBean { public void setCache(Ehcache cache) { this.cache = cache; } + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/cache/NullUserCache.java b/core/src/main/java/org/springframework/security/core/userdetails/cache/NullUserCache.java index 79f40369e5..a56f5d1672 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/cache/NullUserCache.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/cache/NullUserCache.java @@ -25,6 +25,7 @@ import org.springframework.security.core.userdetails.UserDetails; * @author Ben Alex */ public class NullUserCache implements UserCache { + // ~ Methods // ======================================================================================================== @@ -37,4 +38,5 @@ public class NullUserCache implements UserCache { public void removeUserFromCache(String username) { } + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/cache/SpringCacheBasedUserCache.java b/core/src/main/java/org/springframework/security/core/userdetails/cache/SpringCacheBasedUserCache.java index 8150bd9023..b54a5dbf3b 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/cache/SpringCacheBasedUserCache.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/cache/SpringCacheBasedUserCache.java @@ -84,4 +84,5 @@ public class SpringCacheBasedUserCache implements UserCache { public void removeUserFromCache(String username) { cache.evict(username); } + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/cache/package-info.java b/core/src/main/java/org/springframework/security/core/userdetails/cache/package-info.java index 44ba285f8e..c4a76e87fc 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/cache/package-info.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/cache/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Implementations of {@link org.springframework.security.core.userdetails.UserCache UserCache}. + * Implementations of {@link org.springframework.security.core.userdetails.UserCache + * UserCache}. */ package org.springframework.security.core.userdetails.cache; - diff --git a/core/src/main/java/org/springframework/security/core/userdetails/jdbc/JdbcDaoImpl.java b/core/src/main/java/org/springframework/security/core/userdetails/jdbc/JdbcDaoImpl.java index ab271a6799..104c89814b 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/jdbc/JdbcDaoImpl.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/jdbc/JdbcDaoImpl.java @@ -107,19 +107,20 @@ import org.springframework.util.Assert; * @author colin sampaleanu * @author Luke Taylor */ -public class JdbcDaoImpl extends JdbcDaoSupport - implements UserDetailsService, MessageSourceAware { +public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService, MessageSourceAware { + // ~ Static fields/initializers // ===================================================================================== - public static final String DEF_USERS_BY_USERNAME_QUERY = "select username,password,enabled " - + "from users " + "where username = ?"; - public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY = "select username,authority " - + "from authorities " + "where username = ?"; + public static final String DEF_USERS_BY_USERNAME_QUERY = "select username,password,enabled " + "from users " + + "where username = ?"; + + public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY = "select username,authority " + "from authorities " + + "where username = ?"; + public static final String DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY = "select g.id, g.group_name, ga.authority " - + "from groups g, group_members gm, group_authorities ga " - + "where gm.username = ? " + "and g.id = ga.group_id " - + "and g.id = gm.group_id"; + + "from groups g, group_members gm, group_authorities ga " + "where gm.username = ? " + + "and g.id = ga.group_id " + "and g.id = gm.group_id"; // ~ Instance fields // ================================================================================================ @@ -127,11 +128,17 @@ public class JdbcDaoImpl extends JdbcDaoSupport protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private String authoritiesByUsernameQuery; + private String groupAuthoritiesByUsernameQuery; + private String usersByUsernameQuery; + private String rolePrefix = ""; + private boolean usernameBasedPrimaryKey = true; + private boolean enableAuthorities = true; + private boolean enableGroups; // ~ Constructors @@ -156,13 +163,11 @@ public class JdbcDaoImpl extends JdbcDaoSupport /** * Allows subclasses to add their own granted authorities to the list to be returned * in the UserDetails. - * * @param username the username, for use by finder methods * @param authorities the current granted authorities, as populated from the * authoritiesByUsername mapping */ - protected void addCustomAuthorities(String username, - List authorities) { + protected void addCustomAuthorities(String username, List authorities) { } public String getUsersByUsernameQuery() { @@ -176,16 +181,14 @@ public class JdbcDaoImpl extends JdbcDaoSupport } @Override - public UserDetails loadUserByUsername(String username) - throws UsernameNotFoundException { + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { List users = loadUsersByUsername(username); if (users.size() == 0) { this.logger.debug("Query returned no results for user '" + username + "'"); - throw new UsernameNotFoundException( - this.messages.getMessage("JdbcDaoImpl.notFound", - new Object[] { username }, "Username {0} not found")); + throw new UsernameNotFoundException(this.messages.getMessage("JdbcDaoImpl.notFound", + new Object[] { username }, "Username {0} not found")); } UserDetails user = users.get(0); // contains no GrantedAuthority[] @@ -205,12 +208,10 @@ public class JdbcDaoImpl extends JdbcDaoSupport addCustomAuthorities(user.getUsername(), dbAuths); if (dbAuths.size() == 0) { - this.logger.debug("User '" + username - + "' has no authorities and will be treated as 'not found'"); + this.logger.debug("User '" + username + "' has no authorities and will be treated as 'not found'"); - throw new UsernameNotFoundException(this.messages.getMessage( - "JdbcDaoImpl.noAuthority", new Object[] { username }, - "User {0} has no GrantedAuthority")); + throw new UsernameNotFoundException(this.messages.getMessage("JdbcDaoImpl.noAuthority", + new Object[] { username }, "User {0} has no GrantedAuthority")); } return createUserDetails(username, user, dbAuths); @@ -221,39 +222,34 @@ public class JdbcDaoImpl extends JdbcDaoSupport * objects. There should normally only be one matching user. */ protected List loadUsersByUsername(String username) { - return getJdbcTemplate().query(this.usersByUsernameQuery, - new String[] { username }, (rs, rowNum) -> { - String username1 = rs.getString(1); - String password = rs.getString(2); - boolean enabled = rs.getBoolean(3); - return new User(username1, password, enabled, true, true, true, - AuthorityUtils.NO_AUTHORITIES); - }); + return getJdbcTemplate().query(this.usersByUsernameQuery, new String[] { username }, (rs, rowNum) -> { + String username1 = rs.getString(1); + String password = rs.getString(2); + boolean enabled = rs.getBoolean(3); + return new User(username1, password, enabled, true, true, true, AuthorityUtils.NO_AUTHORITIES); + }); } /** * Loads authorities by executing the SQL from authoritiesByUsernameQuery. - * * @return a list of GrantedAuthority objects for the user */ protected List loadUserAuthorities(String username) { - return getJdbcTemplate().query(this.authoritiesByUsernameQuery, - new String[] { username }, (rs, rowNum) -> { - String roleName = JdbcDaoImpl.this.rolePrefix + rs.getString(2); + return getJdbcTemplate().query(this.authoritiesByUsernameQuery, new String[] { username }, (rs, rowNum) -> { + String roleName = JdbcDaoImpl.this.rolePrefix + rs.getString(2); - return new SimpleGrantedAuthority(roleName); - }); + return new SimpleGrantedAuthority(roleName); + }); } /** * Loads authorities by executing the SQL from * groupAuthoritiesByUsernameQuery. - * * @return a list of GrantedAuthority objects for the user */ protected List loadGroupAuthorities(String username) { - return getJdbcTemplate().query(this.groupAuthoritiesByUsernameQuery, - new String[] { username }, (rs, rowNum) -> { + return getJdbcTemplate().query(this.groupAuthoritiesByUsernameQuery, new String[] { username }, + (rs, rowNum) -> { String roleName = getRolePrefix() + rs.getString(3); return new SimpleGrantedAuthority(roleName); @@ -263,33 +259,31 @@ public class JdbcDaoImpl extends JdbcDaoSupport /** * Can be overridden to customize the creation of the final UserDetailsObject which is * returned by the loadUserByUsername method. - * * @param username the name originally passed to loadUserByUsername * @param userFromUserQuery the object returned from the execution of the * @param combinedAuthorities the combined array of authorities from all the authority * loading queries. * @return the final UserDetails which should be used in the system. */ - protected UserDetails createUserDetails(String username, - UserDetails userFromUserQuery, List combinedAuthorities) { + protected UserDetails createUserDetails(String username, UserDetails userFromUserQuery, + List combinedAuthorities) { String returnUsername = userFromUserQuery.getUsername(); if (!this.usernameBasedPrimaryKey) { returnUsername = username; } - return new User(returnUsername, userFromUserQuery.getPassword(), - userFromUserQuery.isEnabled(), userFromUserQuery.isAccountNonExpired(), - userFromUserQuery.isCredentialsNonExpired(), userFromUserQuery.isAccountNonLocked(), combinedAuthorities); + return new User(returnUsername, userFromUserQuery.getPassword(), userFromUserQuery.isEnabled(), + userFromUserQuery.isAccountNonExpired(), userFromUserQuery.isCredentialsNonExpired(), + userFromUserQuery.isAccountNonLocked(), combinedAuthorities); } /** * Allows the default query string used to retrieve authorities based on username to * be overridden, if default table or column names need to be changed. The default * query is {@link #DEF_AUTHORITIES_BY_USERNAME_QUERY}; when modifying this query, - * ensure that all returned columns are mapped back to the same column positions as in the - * default query. - * + * ensure that all returned columns are mapped back to the same column positions as in + * the default query. * @param queryString The SQL query string to set */ public void setAuthoritiesByUsernameQuery(String queryString) { @@ -306,7 +300,6 @@ public class JdbcDaoImpl extends JdbcDaoSupport * default query is {@link #DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY}; when modifying * this query, ensure that all returned columns are mapped back to the same column * positions as in the default query. - * * @param queryString The SQL query string to set */ public void setGroupAuthoritiesByUsernameQuery(String queryString) { @@ -319,7 +312,6 @@ public class JdbcDaoImpl extends JdbcDaoSupport * example be used to add the ROLE_ prefix expected to exist in role names * (by default) by some other Spring Security classes, in the case that the prefix is * not already present in the db. - * * @param rolePrefix the new prefix */ public void setRolePrefix(String rolePrefix) { @@ -338,7 +330,6 @@ public class JdbcDaoImpl extends JdbcDaoSupport * UserDetails. If false, the class will use the * {@link #loadUserByUsername(String)} derived username in the returned * UserDetails. - * * @param usernameBasedPrimaryKey true if the mapping queries return the * username String, or false if the mapping returns a * database primary key. @@ -355,14 +346,13 @@ public class JdbcDaoImpl extends JdbcDaoSupport * Allows the default query string used to retrieve users based on username to be * overridden, if default table or column names need to be changed. The default query * is {@link #DEF_USERS_BY_USERNAME_QUERY}; when modifying this query, ensure that all - * returned columns are mapped back to the same column positions as in the default query. - * If the 'enabled' column does not exist in the source database, a permanent true - * value for this column may be returned by using a query similar to + * returned columns are mapped back to the same column positions as in the default + * query. If the 'enabled' column does not exist in the source database, a permanent + * true value for this column may be returned by using a query similar to * *
       	 * "select username,password,'true' as enabled from users where username = ?"
       	 * 
      - * * @param usersByUsernameQueryString The query string to set */ public void setUsersByUsernameQuery(String usersByUsernameQueryString) { @@ -397,4 +387,5 @@ public class JdbcDaoImpl extends JdbcDaoSupport Assert.notNull(messageSource, "messageSource cannot be null"); this.messages = new MessageSourceAccessor(messageSource); } + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/jdbc/package-info.java b/core/src/main/java/org/springframework/security/core/userdetails/jdbc/package-info.java index 75238a665c..b9b4155d19 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/jdbc/package-info.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/jdbc/package-info.java @@ -18,4 +18,3 @@ * {@code org.springframework.security.core.userdetails.UserDetailsService UserDetailsService}. */ package org.springframework.security.core.userdetails.jdbc; - diff --git a/core/src/main/java/org/springframework/security/core/userdetails/memory/UserAttribute.java b/core/src/main/java/org/springframework/security/core/userdetails/memory/UserAttribute.java index 0499931865..5e380c780b 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/memory/UserAttribute.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/memory/UserAttribute.java @@ -24,17 +24,20 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; /** - * Used by {@link org.springframework.security.provisioning.InMemoryUserDetailsManager} to temporarily store the attributes associated with a - * user. + * Used by {@link org.springframework.security.provisioning.InMemoryUserDetailsManager} to + * temporarily store the attributes associated with a user. * * @author Ben Alex */ public class UserAttribute { + // ~ Instance fields // ================================================================================================ private List authorities = new Vector<>(); + private String password; + private boolean enabled = true; // ~ Methods @@ -50,7 +53,6 @@ public class UserAttribute { /** * Set all authorities for this user. - * * @param authorities {@link List} <{@link GrantedAuthority}> * @since 1.1 */ @@ -61,7 +63,6 @@ public class UserAttribute { /** * Set all authorities for this user from String values. It will create the necessary * {@link GrantedAuthority} objects. - * * @param authoritiesAsStrings {@link List} <{@link String}> * @since 1.1 */ @@ -96,4 +97,5 @@ public class UserAttribute { public void setPassword(String password) { this.password = password; } + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/memory/UserAttributeEditor.java b/core/src/main/java/org/springframework/security/core/userdetails/memory/UserAttributeEditor.java index ab4248a767..ffe713b5ae 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/memory/UserAttributeEditor.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/memory/UserAttributeEditor.java @@ -29,6 +29,7 @@ import org.springframework.util.StringUtils; * @author Ben Alex */ public class UserAttributeEditor extends PropertyEditorSupport { + // ~ Methods // ======================================================================================================== @@ -70,4 +71,5 @@ public class UserAttributeEditor extends PropertyEditorSupport { setValue(null); } } + } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/memory/package-info.java b/core/src/main/java/org/springframework/security/core/userdetails/memory/package-info.java index cc7550c568..6e9c74c013 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/memory/package-info.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/memory/package-info.java @@ -17,4 +17,3 @@ * Exposes an in-memory authentication repository. */ package org.springframework.security.core.userdetails.memory; - diff --git a/core/src/main/java/org/springframework/security/core/userdetails/package-info.java b/core/src/main/java/org/springframework/security/core/userdetails/package-info.java index 1f68a69eec..522724b0e5 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/package-info.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/package-info.java @@ -16,9 +16,11 @@ /** * The standard interfaces for implementing user data DAOs. *

      - * Can be the traditional {@link org.springframework.security.core.userdetails.UserDetailsService UserDetailsService} - * which uses a unique username to identify the user or, for more complex requirements, the - * {@link org.springframework.security.core.userdetails.AuthenticationUserDetailsService AuthenticationUserDetailsService}. + * Can be the traditional + * {@link org.springframework.security.core.userdetails.UserDetailsService + * UserDetailsService} which uses a unique username to identify the user or, for more + * complex requirements, the + * {@link org.springframework.security.core.userdetails.AuthenticationUserDetailsService + * AuthenticationUserDetailsService}. */ package org.springframework.security.core.userdetails; - diff --git a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java index 02ad8851f4..062f760f64 100644 --- a/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixin.java @@ -23,10 +23,11 @@ import java.util.Collection; /** * This is a Jackson mixin class helps in serialize/deserialize - * {@link org.springframework.security.authentication.AnonymousAuthenticationToken} class. To use this class you need to register it - * with {@link com.fasterxml.jackson.databind.ObjectMapper} and {@link SimpleGrantedAuthorityMixin} because - * AnonymousAuthenticationToken contains SimpleGrantedAuthority. - *

      + * {@link org.springframework.security.authentication.AnonymousAuthenticationToken} class.
      + * To use this class you need to register it with
      + * {@link com.fasterxml.jackson.databind.ObjectMapper} and
      + * {@link SimpleGrantedAuthorityMixin} because AnonymousAuthenticationToken contains
      + * SimpleGrantedAuthority. 
        *     ObjectMapper mapper = new ObjectMapper();
        *     mapper.registerModule(new CoreJackson2Module());
        * 
      @@ -45,15 +46,17 @@ import java.util.Collection; class AnonymousAuthenticationTokenMixin { /** - * Constructor used by Jackson to create object of {@link org.springframework.security.authentication.AnonymousAuthenticationToken}. - * + * Constructor used by Jackson to create object of + * {@link org.springframework.security.authentication.AnonymousAuthenticationToken}. * @param keyHash hashCode of key provided at the time of token creation by using - * {@link org.springframework.security.authentication.AnonymousAuthenticationToken#AnonymousAuthenticationToken(String, Object, Collection)} + * {@link org.springframework.security.authentication.AnonymousAuthenticationToken#AnonymousAuthenticationToken(String, Object, Collection)} * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal */ @JsonCreator - AnonymousAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, @JsonProperty("principal") Object principal, - @JsonProperty("authorities") Collection authorities) { + AnonymousAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, + @JsonProperty("principal") Object principal, + @JsonProperty("authorities") Collection authorities) { } + } diff --git a/core/src/main/java/org/springframework/security/jackson2/BadCredentialsExceptionMixin.java b/core/src/main/java/org/springframework/security/jackson2/BadCredentialsExceptionMixin.java index 1c47950d7c..9eaaabd5ca 100644 --- a/core/src/main/java/org/springframework/security/jackson2/BadCredentialsExceptionMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/BadCredentialsExceptionMixin.java @@ -22,31 +22,33 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; /** * This mixin class helps in serialize/deserialize - * {@link org.springframework.security.authentication.BadCredentialsException} class. To use this class you need to - * register it with {@link com.fasterxml.jackson.databind.ObjectMapper}. + * {@link org.springframework.security.authentication.BadCredentialsException} class. To + * use this class you need to register it with + * {@link com.fasterxml.jackson.databind.ObjectMapper}. * *
        *     ObjectMapper mapper = new ObjectMapper();
        *     mapper.registerModule(new CoreJackson2Module());
        * 
      * - * Note: This class will save TypeInfo (full class name) into a property called @class - * The cause and stackTrace are ignored in the serialization. + * Note: This class will save TypeInfo (full class name) into a property + * called @class The cause and stackTrace are ignored in the serialization. * * @author Yannick Lombardi * @see CoreJackson2Module * @since 5.0 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) -@JsonIgnoreProperties(ignoreUnknown = true, value = {"cause", "stackTrace"}) +@JsonIgnoreProperties(ignoreUnknown = true, value = { "cause", "stackTrace" }) class BadCredentialsExceptionMixin { /** * Constructor used by Jackson to create * {@link org.springframework.security.authentication.BadCredentialsException} object. - * * @param message the detail message */ @JsonCreator - BadCredentialsExceptionMixin(@JsonProperty("message") String message) {} + BadCredentialsExceptionMixin(@JsonProperty("message") String message) { + } + } diff --git a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java index 8e50b2fff3..ab54087070 100644 --- a/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java +++ b/core/src/main/java/org/springframework/security/jackson2/CoreJackson2Module.java @@ -28,17 +28,19 @@ import org.springframework.security.core.userdetails.User; import java.util.Collections; /** - * Jackson module for spring-security-core. This module register {@link AnonymousAuthenticationTokenMixin}, - * {@link RememberMeAuthenticationTokenMixin}, {@link SimpleGrantedAuthorityMixin}, {@link UnmodifiableSetMixin}, - * {@link UserMixin} and {@link UsernamePasswordAuthenticationTokenMixin}. If no default typing enabled by default then - * it'll enable it because typing info is needed to properly serialize/deserialize objects. In order to use this module just - * add this module into your ObjectMapper configuration. + * Jackson module for spring-security-core. This module register + * {@link AnonymousAuthenticationTokenMixin}, {@link RememberMeAuthenticationTokenMixin}, + * {@link SimpleGrantedAuthorityMixin}, {@link UnmodifiableSetMixin}, {@link UserMixin} + * and {@link UsernamePasswordAuthenticationTokenMixin}. If no default typing enabled by + * default then it'll enable it because typing info is needed to properly + * serialize/deserialize objects. In order to use this module just add this module into + * your ObjectMapper configuration. * *
        *     ObjectMapper mapper = new ObjectMapper();
        *     mapper.registerModule(new CoreJackson2Module());
      - * 
      - * Note: use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get list of all security modules. + *
      Note: use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get list + * of all security modules. * * @author Jitendra Singh. * @see SecurityJackson2Modules @@ -57,10 +59,14 @@ public class CoreJackson2Module extends SimpleModule { context.setMixInAnnotations(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class); context.setMixInAnnotations(RememberMeAuthenticationToken.class, RememberMeAuthenticationTokenMixin.class); context.setMixInAnnotations(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class); - context.setMixInAnnotations(Collections.unmodifiableSet(Collections.emptySet()).getClass(), UnmodifiableSetMixin.class); - context.setMixInAnnotations(Collections.unmodifiableList(Collections.emptyList()).getClass(), UnmodifiableListMixin.class); + context.setMixInAnnotations(Collections.unmodifiableSet(Collections.emptySet()).getClass(), + UnmodifiableSetMixin.class); + context.setMixInAnnotations(Collections.unmodifiableList(Collections.emptyList()).getClass(), + UnmodifiableListMixin.class); context.setMixInAnnotations(User.class, UserMixin.class); - context.setMixInAnnotations(UsernamePasswordAuthenticationToken.class, UsernamePasswordAuthenticationTokenMixin.class); + context.setMixInAnnotations(UsernamePasswordAuthenticationToken.class, + UsernamePasswordAuthenticationTokenMixin.class); context.setMixInAnnotations(BadCredentialsException.class, BadCredentialsExceptionMixin.class); } + } diff --git a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java index 3274a2c779..cf92e4e1b4 100644 --- a/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixin.java @@ -23,13 +23,14 @@ import java.util.Collection; /** * This mixin class helps in serialize/deserialize - * {@link org.springframework.security.authentication.RememberMeAuthenticationToken} class. To use this class you need to register it - * with {@link com.fasterxml.jackson.databind.ObjectMapper} and 2 more mixin classes. + * {@link org.springframework.security.authentication.RememberMeAuthenticationToken} + * class. To use this class you need to register it with + * {@link com.fasterxml.jackson.databind.ObjectMapper} and 2 more mixin classes. * *
        - *
      1. {@link SimpleGrantedAuthorityMixin}
      2. - *
      3. {@link UserMixin}
      4. - *
      5. {@link UnmodifiableSetMixin}
      6. + *
      7. {@link SimpleGrantedAuthorityMixin}
      8. + *
      9. {@link UserMixin}
      10. + *
      11. {@link UnmodifiableSetMixin}
      12. *
      * *
      @@ -37,7 +38,8 @@ import java.util.Collection;
        *     mapper.registerModule(new CoreJackson2Module());
        * 
      * - * Note: This class will save TypeInfo (full class name) into a property called @class + * Note: This class will save TypeInfo (full class name) into a property + * called @class * * @author Jitendra Singh * @see CoreJackson2Module @@ -52,15 +54,16 @@ class RememberMeAuthenticationTokenMixin { /** * Constructor used by Jackson to create - * {@link org.springframework.security.authentication.RememberMeAuthenticationToken} object. - * + * {@link org.springframework.security.authentication.RememberMeAuthenticationToken} + * object. * @param keyHash hashCode of above given key. * @param principal the principal (typically a UserDetails) * @param authorities the authorities granted to the principal */ @JsonCreator RememberMeAuthenticationTokenMixin(@JsonProperty("keyHash") Integer keyHash, - @JsonProperty("principal") Object principal, - @JsonProperty("authorities") Collection authorities) { + @JsonProperty("principal") Object principal, + @JsonProperty("authorities") Collection authorities) { } + } diff --git a/core/src/main/java/org/springframework/security/jackson2/SecurityJackson2Modules.java b/core/src/main/java/org/springframework/security/jackson2/SecurityJackson2Modules.java index 011ee95b1a..be52de8c65 100644 --- a/core/src/main/java/org/springframework/security/jackson2/SecurityJackson2Modules.java +++ b/core/src/main/java/org/springframework/security/jackson2/SecurityJackson2Modules.java @@ -50,8 +50,7 @@ import java.util.Set; *
        *     ObjectMapper mapper = new ObjectMapper();
        *     mapper.registerModules(SecurityJackson2Modules.getModules());
      - * 
      - * Above code is equivalent to + * Above code is equivalent to *

      *

        *     ObjectMapper mapper = new ObjectMapper();
      @@ -70,18 +69,18 @@ import java.util.Set;
       public final class SecurityJackson2Modules {
       
       	private static final Log logger = LogFactory.getLog(SecurityJackson2Modules.class);
      +
       	private static final List securityJackson2ModuleClasses = Arrays.asList(
       			"org.springframework.security.jackson2.CoreJackson2Module",
       			"org.springframework.security.cas.jackson2.CasJackson2Module",
       			"org.springframework.security.web.jackson2.WebJackson2Module",
      -			"org.springframework.security.web.server.jackson2.WebServerJackson2Module"
      -	);
      -	private static final String webServletJackson2ModuleClass =
      -			"org.springframework.security.web.jackson2.WebServletJackson2Module";
      -	private static final String oauth2ClientJackson2ModuleClass =
      -			"org.springframework.security.oauth2.client.jackson2.OAuth2ClientJackson2Module";
      -	private static final String javaTimeJackson2ModuleClass =
      -			"com.fasterxml.jackson.datatype.jsr310.JavaTimeModule";
      +			"org.springframework.security.web.server.jackson2.WebServerJackson2Module");
      +
      +	private static final String webServletJackson2ModuleClass = "org.springframework.security.web.jackson2.WebServletJackson2Module";
      +
      +	private static final String oauth2ClientJackson2ModuleClass = "org.springframework.security.oauth2.client.jackson2.OAuth2ClientJackson2Module";
      +
      +	private static final String javaTimeJackson2ModuleClass = "com.fasterxml.jackson.datatype.jsr310.JavaTimeModule";
       
       	private SecurityJackson2Modules() {
       	}
      @@ -106,7 +105,8 @@ public final class SecurityJackson2Modules {
       				}
       				instance = securityModule.newInstance();
       			}
      -		} catch (Exception e) {
      +		}
      +		catch (Exception e) {
       			if (logger.isDebugEnabled()) {
       				logger.debug("Cannot load module " + className, e);
       			}
      @@ -136,8 +136,8 @@ public final class SecurityJackson2Modules {
       	}
       
       	/**
      -	 * @param loader    the ClassLoader to use
      -	 * @param modules   list of the modules to add
      +	 * @param loader the ClassLoader to use
      +	 * @param modules list of the modules to add
       	 * @param className name of the class to instantiate
       	 */
       	private static void addToModulesList(ClassLoader loader, List modules, String className) {
      @@ -152,60 +152,52 @@ public final class SecurityJackson2Modules {
       	 * @return a TypeResolverBuilder that restricts allowed types.
       	 */
       	private static TypeResolverBuilder createAllowlistedDefaultTyping() {
      -		TypeResolverBuilder  result = new AllowlistTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL);
      +		TypeResolverBuilder result = new AllowlistTypeResolverBuilder(
      +				ObjectMapper.DefaultTyping.NON_FINAL);
       		result = result.init(JsonTypeInfo.Id.CLASS, null);
       		result = result.inclusion(JsonTypeInfo.As.PROPERTY);
       		return result;
       	}
       
       	/**
      -	 * An implementation of {@link ObjectMapper.DefaultTypeResolverBuilder}
      -	 * that inserts an {@code allow all} {@link PolymorphicTypeValidator}
      -	 * and overrides the {@code TypeIdResolver}
      +	 * An implementation of {@link ObjectMapper.DefaultTypeResolverBuilder} that inserts
      +	 * an {@code allow all} {@link PolymorphicTypeValidator} and overrides the
      +	 * {@code TypeIdResolver}
      +	 *
       	 * @author Rob Winch
       	 */
       	static class AllowlistTypeResolverBuilder extends ObjectMapper.DefaultTypeResolverBuilder {
       
       		AllowlistTypeResolverBuilder(ObjectMapper.DefaultTyping defaultTyping) {
      -			super(
      -					defaultTyping,
      -					//we do explicit validation in the TypeIdResolver
      -					BasicPolymorphicTypeValidator.builder()
      -							.allowIfSubType(Object.class)
      -							.build()
      -			);
      +			super(defaultTyping,
      +					// we do explicit validation in the TypeIdResolver
      +					BasicPolymorphicTypeValidator.builder().allowIfSubType(Object.class).build());
       		}
       
       		@Override
      -		protected TypeIdResolver idResolver(MapperConfig config,
      -				JavaType baseType,
      -				PolymorphicTypeValidator subtypeValidator,
      -				Collection subtypes, boolean forSer, boolean forDeser) {
      +		protected TypeIdResolver idResolver(MapperConfig config, JavaType baseType,
      +				PolymorphicTypeValidator subtypeValidator, Collection subtypes, boolean forSer,
      +				boolean forDeser) {
       			TypeIdResolver result = super.idResolver(config, baseType, subtypeValidator, subtypes, forSer, forDeser);
       			return new AllowlistTypeIdResolver(result);
       		}
      +
       	}
       
       	/**
      -	 * A {@link TypeIdResolver} that delegates to an existing implementation and throws an IllegalStateException if the
      -	 * class being looked up is not in the allowlist, does not provide an explicit mixin, and is not annotated with Jackson
      -	 * mappings. See https://github.com/spring-projects/spring-security/issues/4370
      +	 * A {@link TypeIdResolver} that delegates to an existing implementation and throws an
      +	 * IllegalStateException if the class being looked up is not in the allowlist, does
      +	 * not provide an explicit mixin, and is not annotated with Jackson mappings. See
      +	 * https://github.com/spring-projects/spring-security/issues/4370
       	 */
       	static class AllowlistTypeIdResolver implements TypeIdResolver {
      -		private static final Set ALLOWLIST_CLASS_NAMES = Collections.unmodifiableSet(new HashSet(Arrays.asList(
      -			"java.util.ArrayList",
      -			"java.util.Collections$EmptyList",
      -			"java.util.Collections$EmptyMap",
      -			"java.util.Collections$UnmodifiableRandomAccessList",
      -			"java.util.Collections$SingletonList",
      -			"java.util.Date",
      -			"java.time.Instant",
      -			"java.net.URL",
      -			"java.util.TreeMap",
      -			"java.util.HashMap",
      -			"java.util.LinkedHashMap",
      -			"org.springframework.security.core.context.SecurityContextImpl"
      -		)));
      +
      +		private static final Set ALLOWLIST_CLASS_NAMES = Collections
      +				.unmodifiableSet(new HashSet(Arrays.asList("java.util.ArrayList", "java.util.Collections$EmptyList",
      +						"java.util.Collections$EmptyMap", "java.util.Collections$UnmodifiableRandomAccessList",
      +						"java.util.Collections$SingletonList", "java.util.Date", "java.time.Instant", "java.net.URL",
      +						"java.util.TreeMap", "java.util.HashMap", "java.util.LinkedHashMap",
      +						"org.springframework.security.core.context.SecurityContextImpl")));
       
       		private final TypeIdResolver delegate;
       
      @@ -245,14 +237,16 @@ public final class SecurityJackson2Modules {
       			if (isExplicitMixin) {
       				return result;
       			}
      -			JacksonAnnotation jacksonAnnotation = AnnotationUtils.findAnnotation(result.getRawClass(), JacksonAnnotation.class);
      +			JacksonAnnotation jacksonAnnotation = AnnotationUtils.findAnnotation(result.getRawClass(),
      +					JacksonAnnotation.class);
       			if (jacksonAnnotation != null) {
       				return result;
       			}
      -			throw new IllegalArgumentException("The class with " + id + " and name of " + className + " is not in the allowlist. " +
      -				"If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annotations or by providing a Mixin. " +
      -				"If the serialization is only done by a trusted source, you can also enable default typing. " +
      -				"See https://github.com/spring-projects/spring-security/issues/4370 for details");
      +			throw new IllegalArgumentException("The class with " + id + " and name of " + className
      +					+ " is not in the allowlist. "
      +					+ "If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annotations or by providing a Mixin. "
      +					+ "If the serialization is only done by a trusted source, you can also enable default typing. "
      +					+ "See https://github.com/spring-projects/spring-security/issues/4370 for details");
       		}
       
       		private boolean isInAllowlist(String id) {
      @@ -270,4 +264,5 @@ public final class SecurityJackson2Modules {
       		}
       
       	}
      +
       }
      diff --git a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java
      index 4fa8558dc3..55fee7fe68 100644
      --- a/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java
      +++ b/core/src/main/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixin.java
      @@ -26,14 +26,15 @@ import com.fasterxml.jackson.annotation.*;
        *     ObjectMapper mapper = new ObjectMapper();
        *     mapper.registerModule(new CoreJackson2Module());
        * 
      + * * @author Jitendra Singh * @see CoreJackson2Module * @see SecurityJackson2Modules * @since 4.2 */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) -@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY, - isGetterVisibility = JsonAutoDetect.Visibility.NONE) +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, + getterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY, isGetterVisibility = JsonAutoDetect.Visibility.NONE) @JsonIgnoreProperties(ignoreUnknown = true) public abstract class SimpleGrantedAuthorityMixin { @@ -44,4 +45,5 @@ public abstract class SimpleGrantedAuthorityMixin { @JsonCreator public SimpleGrantedAuthorityMixin(@JsonProperty("authority") String role) { } + } diff --git a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableListDeserializer.java b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableListDeserializer.java index af4075f014..a8b3273ceb 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableListDeserializer.java +++ b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableListDeserializer.java @@ -49,10 +49,12 @@ class UnmodifiableListDeserializer extends JsonDeserializer { for (JsonNode elementNode : arrayNode) { result.add(mapper.readValue(elementNode.traverse(mapper), Object.class)); } - } else { + } + else { result.add(mapper.readValue(node.traverse(mapper), Object.class)); } } return Collections.unmodifiableList(result); } + } diff --git a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableListMixin.java b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableListMixin.java index b5fb86e76c..b42d63a6cb 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableListMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableListMixin.java @@ -46,5 +46,7 @@ class UnmodifiableListMixin { * @param s the Set */ @JsonCreator - UnmodifiableListMixin(Set s) {} + UnmodifiableListMixin(Set s) { + } + } diff --git a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetDeserializer.java b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetDeserializer.java index c25ca727f6..4c5f5fd6b5 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetDeserializer.java +++ b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetDeserializer.java @@ -49,10 +49,12 @@ class UnmodifiableSetDeserializer extends JsonDeserializer { for (JsonNode elementNode : arrayNode) { resultSet.add(mapper.readValue(elementNode.traverse(mapper), Object.class)); } - } else { + } + else { resultSet.add(mapper.readValue(node.traverse(mapper), Object.class)); } } return Collections.unmodifiableSet(resultSet); } + } diff --git a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java index 09181a88e6..b212331a2b 100644 --- a/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java +++ b/core/src/main/java/org/springframework/security/jackson2/UnmodifiableSetMixin.java @@ -23,8 +23,8 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.util.Set; /** - * This mixin class used to deserialize java.util.Collections$UnmodifiableSet and used with various AuthenticationToken - * implementation's mixin classes. + * This mixin class used to deserialize java.util.Collections$UnmodifiableSet and used + * with various AuthenticationToken implementation's mixin classes. * *
        *     ObjectMapper mapper = new ObjectMapper();
      @@ -46,5 +46,7 @@ class UnmodifiableSetMixin {
       	 * @param s the Set
       	 */
       	@JsonCreator
      -	UnmodifiableSetMixin(Set s) {}
      +	UnmodifiableSetMixin(Set s) {
      +	}
      +
       }
      diff --git a/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java b/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java
      index 96d3ffe748..23b11f2a3a 100644
      --- a/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java
      +++ b/core/src/main/java/org/springframework/security/jackson2/UserDeserializer.java
      @@ -32,8 +32,8 @@ import java.io.IOException;
       import java.util.Set;
       
       /**
      - * Custom Deserializer for {@link User} class. This is already registered with {@link UserMixin}.
      - * You can also use it directly with your mixin class.
      + * Custom Deserializer for {@link User} class. This is already registered with
      + * {@link UserMixin}. You can also use it directly with your mixin class.
        *
        * @author Jitendra Singh
        * @see UserMixin
      @@ -42,10 +42,10 @@ import java.util.Set;
       class UserDeserializer extends JsonDeserializer {
       
       	/**
      -	 * This method will create {@link User} object. It will ensure successful object creation even if password key is null in
      -	 * serialized json, because credentials may be removed from the {@link User} by invoking {@link User#eraseCredentials()}.
      -	 * In that case there won't be any password key in serialized json.
      -	 *
      +	 * This method will create {@link User} object. It will ensure successful object
      +	 * creation even if password key is null in serialized json, because credentials may
      +	 * be removed from the {@link User} by invoking {@link User#eraseCredentials()}. In
      +	 * that case there won't be any password key in serialized json.
       	 * @param jp the JsonParser
       	 * @param ctxt the DeserializationContext
       	 * @return the user
      @@ -56,18 +56,14 @@ class UserDeserializer extends JsonDeserializer {
       	public User deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
       		ObjectMapper mapper = (ObjectMapper) jp.getCodec();
       		JsonNode jsonNode = mapper.readTree(jp);
      -		Set authorities =
      -				mapper.convertValue(
      -						jsonNode.get("authorities"),
      -						new TypeReference>() {}
      -				);
      +		Set authorities = mapper.convertValue(jsonNode.get("authorities"),
      +				new TypeReference>() {
      +				});
       		JsonNode password = readJsonNode(jsonNode, "password");
      -		User result =  new User(
      -				readJsonNode(jsonNode, "username").asText(), password.asText(""),
      +		User result = new User(readJsonNode(jsonNode, "username").asText(), password.asText(""),
       				readJsonNode(jsonNode, "enabled").asBoolean(), readJsonNode(jsonNode, "accountNonExpired").asBoolean(),
       				readJsonNode(jsonNode, "credentialsNonExpired").asBoolean(),
      -				readJsonNode(jsonNode, "accountNonLocked").asBoolean(), authorities
      -		);
      +				readJsonNode(jsonNode, "accountNonLocked").asBoolean(), authorities);
       
       		if (password.asText(null) == null) {
       			result.eraseCredentials();
      @@ -78,4 +74,5 @@ class UserDeserializer extends JsonDeserializer {
       	private JsonNode readJsonNode(JsonNode jsonNode, String field) {
       		return jsonNode.has(field) ? jsonNode.get(field) : MissingNode.getInstance();
       	}
      +
       }
      diff --git a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java
      index 36fca4e808..0cb7b3c332 100644
      --- a/core/src/main/java/org/springframework/security/jackson2/UserMixin.java
      +++ b/core/src/main/java/org/springframework/security/jackson2/UserMixin.java
      @@ -22,12 +22,14 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
       import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
       
       /**
      - * This mixin class helps in serialize/deserialize {@link org.springframework.security.core.userdetails.User}.
      - * This class also register a custom deserializer {@link UserDeserializer} to deserialize User object successfully.
      - * In order to use this mixin you need to register two more mixin classes in your ObjectMapper configuration.
      + * This mixin class helps in serialize/deserialize
      + * {@link org.springframework.security.core.userdetails.User}. This class also register a
      + * custom deserializer {@link UserDeserializer} to deserialize User object successfully.
      + * In order to use this mixin you need to register two more mixin classes in your
      + * ObjectMapper configuration.
        * 
        - *
      1. {@link SimpleGrantedAuthorityMixin}
      2. - *
      3. {@link UnmodifiableSetMixin}
      4. + *
      5. {@link SimpleGrantedAuthorityMixin}
      6. + *
      7. {@link UnmodifiableSetMixin}
      8. *
      *
        *     ObjectMapper mapper = new ObjectMapper();
      @@ -46,4 +48,5 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
       		isGetterVisibility = JsonAutoDetect.Visibility.NONE)
       @JsonIgnoreProperties(ignoreUnknown = true)
       abstract class UserMixin {
      +
       }
      diff --git a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java
      index 64a5b4a7b0..87fb7fa8a3 100644
      --- a/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java
      +++ b/core/src/main/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenDeserializer.java
      @@ -32,12 +32,13 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
       import org.springframework.security.core.GrantedAuthority;
       
       /**
      - * Custom deserializer for {@link UsernamePasswordAuthenticationToken}. At the time of deserialization
      - * it will invoke suitable constructor depending on the value of authenticated property.
      - * It will ensure that the token's state must not change.
      + * Custom deserializer for {@link UsernamePasswordAuthenticationToken}. At the time of
      + * deserialization it will invoke suitable constructor depending on the value of
      + * authenticated property. It will ensure that the token's state must not change.
        * 

      - * This deserializer is already registered with {@link UsernamePasswordAuthenticationTokenMixin} but - * you can also registered it with your own mixin class. + * This deserializer is already registered with + * {@link UsernamePasswordAuthenticationTokenMixin} but you can also registered it with + * your own mixin class. * * @author Jitendra Singh * @author Greg Turnquist @@ -48,7 +49,8 @@ import org.springframework.security.core.GrantedAuthority; class UsernamePasswordAuthenticationTokenDeserializer extends JsonDeserializer { /** - * This method construct {@link UsernamePasswordAuthenticationToken} object from serialized json. + * This method construct {@link UsernamePasswordAuthenticationToken} object from + * serialized json. * @param jp the JsonParser * @param ctxt the DeserializationContext * @return the user @@ -56,7 +58,8 @@ class UsernamePasswordAuthenticationTokenDeserializer extends JsonDeserializer authorities = mapper.readValue( - readJsonNode(jsonNode, "authorities").traverse(mapper), new TypeReference>() { - }); + List authorities = mapper.readValue(readJsonNode(jsonNode, "authorities").traverse(mapper), + new TypeReference>() { + }); if (authenticated) { token = new UsernamePasswordAuthenticationToken(principal, credentials, authorities); - } else { + } + else { token = new UsernamePasswordAuthenticationToken(principal, credentials); } JsonNode detailsNode = readJsonNode(jsonNode, "details"); if (detailsNode.isNull() || detailsNode.isMissingNode()) { token.setDetails(null); - } else { - Object details = mapper.readValue(detailsNode.toString(), new TypeReference() {}); + } + else { + Object details = mapper.readValue(detailsNode.toString(), new TypeReference() { + }); token.setDetails(details); } return token; @@ -96,4 +104,5 @@ class UsernamePasswordAuthenticationTokenDeserializer extends JsonDeserializer - *
    8. {@link UnmodifiableSetMixin}
    9. - *
    10. {@link SimpleGrantedAuthorityMixin}
    11. - *
    12. {@link UserMixin}
    13. + *
    14. {@link UnmodifiableSetMixin}
    15. + *
    16. {@link SimpleGrantedAuthorityMixin}
    17. + *
    18. {@link UserMixin}
    19. * * *
        *     ObjectMapper mapper = new ObjectMapper();
        *     mapper.registerModule(new CoreJackson2Module());
        * 
      + * * @author Jitendra Singh * @see CoreJackson2Module * @see SecurityJackson2Modules @@ -45,4 +47,5 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; isGetterVisibility = JsonAutoDetect.Visibility.NONE) @JsonDeserialize(using = UsernamePasswordAuthenticationTokenDeserializer.class) abstract class UsernamePasswordAuthenticationTokenMixin { + } diff --git a/core/src/main/java/org/springframework/security/provisioning/GroupManager.java b/core/src/main/java/org/springframework/security/provisioning/GroupManager.java index 4dfcb6031b..76b02290f8 100644 --- a/core/src/main/java/org/springframework/security/provisioning/GroupManager.java +++ b/core/src/main/java/org/springframework/security/provisioning/GroupManager.java @@ -40,7 +40,6 @@ public interface GroupManager { /** * Locates the users who are members of a group - * * @param groupName the group whose members are required * @return the usernames of the group members */ @@ -48,7 +47,6 @@ public interface GroupManager { /** * Creates a new group with the specified list of authorities. - * * @param groupName the name for the new group * @param authorities the authorities which are to be allocated to this group. */ @@ -56,7 +54,6 @@ public interface GroupManager { /** * Removes a group, including all members and authorities. - * * @param groupName the group to remove. */ void deleteGroup(String groupName); @@ -68,7 +65,6 @@ public interface GroupManager { /** * Makes a user a member of a particular group. - * * @param username the user to be given membership. * @param group the name of the group to which the user will be added. */ @@ -76,7 +72,6 @@ public interface GroupManager { /** * Deletes a user's membership of a group. - * * @param username the user * @param groupName the group to remove them from */ @@ -96,4 +91,5 @@ public interface GroupManager { * Deletes an authority from those assigned to a group */ void removeGroupAuthority(String groupName, GrantedAuthority authority); + } diff --git a/core/src/main/java/org/springframework/security/provisioning/InMemoryUserDetailsManager.java b/core/src/main/java/org/springframework/security/provisioning/InMemoryUserDetailsManager.java index f70e1b0af6..984be6d25e 100644 --- a/core/src/main/java/org/springframework/security/provisioning/InMemoryUserDetailsManager.java +++ b/core/src/main/java/org/springframework/security/provisioning/InMemoryUserDetailsManager.java @@ -46,8 +46,8 @@ import org.springframework.util.Assert; * @author Luke Taylor * @since 3.1 */ -public class InMemoryUserDetailsManager implements UserDetailsManager, - UserDetailsPasswordService { +public class InMemoryUserDetailsManager implements UserDetailsManager, UserDetailsPasswordService { + protected final Log logger = LogFactory.getLog(getClass()); private final Map users = new HashMap<>(); @@ -77,8 +77,8 @@ public class InMemoryUserDetailsManager implements UserDetailsManager, String name = (String) names.nextElement(); editor.setAsText(users.getProperty(name)); UserAttribute attr = (UserAttribute) editor.getValue(); - UserDetails user = new User(name, attr.getPassword(), attr.isEnabled(), true, - true, true, attr.getAuthorities()); + UserDetails user = new User(name, attr.getPassword(), attr.isEnabled(), true, true, true, + attr.getAuthorities()); createUser(user); } } @@ -104,14 +104,12 @@ public class InMemoryUserDetailsManager implements UserDetailsManager, } public void changePassword(String oldPassword, String newPassword) { - Authentication currentUser = SecurityContextHolder.getContext() - .getAuthentication(); + Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); if (currentUser == null) { // This would indicate bad coding somewhere throw new AccessDeniedException( - "Can't change password as no Authentication object found in context " - + "for current user."); + "Can't change password as no Authentication object found in context " + "for current user."); } String username = currentUser.getName(); @@ -121,11 +119,9 @@ public class InMemoryUserDetailsManager implements UserDetailsManager, // If an authentication manager has been set, re-authenticate the user with the // supplied password. if (authenticationManager != null) { - logger.debug("Reauthenticating user '" + username - + "' for password change request."); + logger.debug("Reauthenticating user '" + username + "' for password change request."); - authenticationManager.authenticate(new UsernamePasswordAuthenticationToken( - username, oldPassword)); + authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, oldPassword)); } else { logger.debug("No authentication manager set. Password won't be re-checked."); @@ -148,20 +144,19 @@ public class InMemoryUserDetailsManager implements UserDetailsManager, return mutableUser; } - public UserDetails loadUserByUsername(String username) - throws UsernameNotFoundException { + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { UserDetails user = users.get(username.toLowerCase()); if (user == null) { throw new UsernameNotFoundException(username); } - return new User(user.getUsername(), user.getPassword(), user.isEnabled(), - user.isAccountNonExpired(), user.isCredentialsNonExpired(), - user.isAccountNonLocked(), user.getAuthorities()); + return new User(user.getUsername(), user.getPassword(), user.isEnabled(), user.isAccountNonExpired(), + user.isCredentialsNonExpired(), user.isAccountNonLocked(), user.getAuthorities()); } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } + } diff --git a/core/src/main/java/org/springframework/security/provisioning/JdbcUserDetailsManager.java b/core/src/main/java/org/springframework/security/provisioning/JdbcUserDetailsManager.java index 5d298568c0..2808a9da21 100644 --- a/core/src/main/java/org/springframework/security/provisioning/JdbcUserDetailsManager.java +++ b/core/src/main/java/org/springframework/security/provisioning/JdbcUserDetailsManager.java @@ -56,37 +56,53 @@ import java.util.List; * @author Luke Taylor * @since 2.0 */ -public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsManager, - GroupManager { +public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsManager, GroupManager { + // ~ Static fields/initializers // ===================================================================================== // UserDetailsManager SQL public static final String DEF_CREATE_USER_SQL = "insert into users (username, password, enabled) values (?,?,?)"; + public static final String DEF_DELETE_USER_SQL = "delete from users where username = ?"; + public static final String DEF_UPDATE_USER_SQL = "update users set password = ?, enabled = ? where username = ?"; + public static final String DEF_INSERT_AUTHORITY_SQL = "insert into authorities (username, authority) values (?,?)"; + public static final String DEF_DELETE_USER_AUTHORITIES_SQL = "delete from authorities where username = ?"; + public static final String DEF_USER_EXISTS_SQL = "select username from users where username = ?"; + public static final String DEF_CHANGE_PASSWORD_SQL = "update users set password = ? where username = ?"; // GroupManager SQL public static final String DEF_FIND_GROUPS_SQL = "select group_name from groups"; + public static final String DEF_FIND_USERS_IN_GROUP_SQL = "select username from group_members gm, groups g " + "where gm.group_id = g.id and g.group_name = ?"; + public static final String DEF_INSERT_GROUP_SQL = "insert into groups (group_name) values (?)"; + public static final String DEF_FIND_GROUP_ID_SQL = "select id from groups where group_name = ?"; + public static final String DEF_INSERT_GROUP_AUTHORITY_SQL = "insert into group_authorities (group_id, authority) values (?,?)"; + public static final String DEF_DELETE_GROUP_SQL = "delete from groups where id = ?"; + public static final String DEF_DELETE_GROUP_AUTHORITIES_SQL = "delete from group_authorities where group_id = ?"; + public static final String DEF_DELETE_GROUP_MEMBERS_SQL = "delete from group_members where group_id = ?"; + public static final String DEF_RENAME_GROUP_SQL = "update groups set group_name = ? where group_name = ?"; + public static final String DEF_INSERT_GROUP_MEMBER_SQL = "insert into group_members (group_id, username) values (?,?)"; + public static final String DEF_DELETE_GROUP_MEMBER_SQL = "delete from group_members where group_id = ? and username = ?"; + public static final String DEF_GROUP_AUTHORITIES_QUERY_SQL = "select g.id, g.group_name, ga.authority " - + "from groups g, group_authorities ga " - + "where g.group_name = ? " - + "and g.id = ga.group_id "; + + "from groups g, group_authorities ga " + "where g.group_name = ? " + "and g.id = ga.group_id "; + public static final String DEF_DELETE_GROUP_AUTHORITY_SQL = "delete from group_authorities where group_id = ? and authority = ?"; // ~ Instance fields @@ -95,25 +111,43 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa protected final Log logger = LogFactory.getLog(getClass()); private String createUserSql = DEF_CREATE_USER_SQL; + private String deleteUserSql = DEF_DELETE_USER_SQL; + private String updateUserSql = DEF_UPDATE_USER_SQL; + private String createAuthoritySql = DEF_INSERT_AUTHORITY_SQL; + private String deleteUserAuthoritiesSql = DEF_DELETE_USER_AUTHORITIES_SQL; + private String userExistsSql = DEF_USER_EXISTS_SQL; + private String changePasswordSql = DEF_CHANGE_PASSWORD_SQL; private String findAllGroupsSql = DEF_FIND_GROUPS_SQL; + private String findUsersInGroupSql = DEF_FIND_USERS_IN_GROUP_SQL; + private String insertGroupSql = DEF_INSERT_GROUP_SQL; + private String findGroupIdSql = DEF_FIND_GROUP_ID_SQL; + private String insertGroupAuthoritySql = DEF_INSERT_GROUP_AUTHORITY_SQL; + private String deleteGroupSql = DEF_DELETE_GROUP_SQL; + private String deleteGroupAuthoritiesSql = DEF_DELETE_GROUP_AUTHORITIES_SQL; + private String deleteGroupMembersSql = DEF_DELETE_GROUP_MEMBERS_SQL; + private String renameGroupSql = DEF_RENAME_GROUP_SQL; + private String insertGroupMemberSql = DEF_INSERT_GROUP_MEMBER_SQL; + private String deleteGroupMemberSql = DEF_DELETE_GROUP_MEMBER_SQL; + private String groupAuthoritiesSql = DEF_GROUP_AUTHORITIES_QUERY_SQL; + private String deleteGroupAuthoritySql = DEF_DELETE_GROUP_AUTHORITY_SQL; private AuthenticationManager authenticationManager; @@ -147,26 +181,25 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa * objects. There should normally only be one matching user. */ protected List loadUsersByUsername(String username) { - return getJdbcTemplate().query(getUsersByUsernameQuery(), new String[]{username}, - (rs, rowNum) -> { + return getJdbcTemplate().query(getUsersByUsernameQuery(), new String[] { username }, (rs, rowNum) -> { - String userName = rs.getString(1); - String password = rs.getString(2); - boolean enabled = rs.getBoolean(3); + String userName = rs.getString(1); + String password = rs.getString(2); + boolean enabled = rs.getBoolean(3); - boolean accLocked = false; - boolean accExpired = false; - boolean credsExpired = false; + boolean accLocked = false; + boolean accExpired = false; + boolean credsExpired = false; - if (rs.getMetaData().getColumnCount() > 3) { - //NOTE: acc_locked, acc_expired and creds_expired are also to be loaded - accLocked = rs.getBoolean(4); - accExpired = rs.getBoolean(5); - credsExpired = rs.getBoolean(6); - } - return new User(userName, password, enabled, !accExpired, !credsExpired, !accLocked, - AuthorityUtils.NO_AUTHORITIES); - }); + if (rs.getMetaData().getColumnCount() > 3) { + // NOTE: acc_locked, acc_expired and creds_expired are also to be loaded + accLocked = rs.getBoolean(4); + accExpired = rs.getBoolean(5); + credsExpired = rs.getBoolean(6); + } + return new User(userName, password, enabled, !accExpired, !credsExpired, !accLocked, + AuthorityUtils.NO_AUTHORITIES); + }); } public void createUser(final UserDetails user) { @@ -179,7 +212,7 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa int paramCount = ps.getParameterMetaData().getParameterCount(); if (paramCount > 3) { - //NOTE: acc_locked, acc_expired and creds_expired are also to be inserted + // NOTE: acc_locked, acc_expired and creds_expired are also to be inserted ps.setBoolean(4, !user.isAccountNonLocked()); ps.setBoolean(5, !user.isAccountNonExpired()); ps.setBoolean(6, !user.isCredentialsNonExpired()); @@ -201,8 +234,9 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa int paramCount = ps.getParameterMetaData().getParameterCount(); if (paramCount == 3) { ps.setString(3, user.getUsername()); - } else { - //NOTE: acc_locked, acc_expired and creds_expired are also updated + } + else { + // NOTE: acc_locked, acc_expired and creds_expired are also updated ps.setBoolean(3, !user.isAccountNonLocked()); ps.setBoolean(4, !user.isAccountNonExpired()); ps.setBoolean(5, !user.isCredentialsNonExpired()); @@ -222,8 +256,7 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa private void insertUserAuthorities(UserDetails user) { for (GrantedAuthority auth : user.getAuthorities()) { - getJdbcTemplate().update(createAuthoritySql, user.getUsername(), - auth.getAuthority()); + getJdbcTemplate().update(createAuthoritySql, user.getUsername(), auth.getAuthority()); } } @@ -239,16 +272,13 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa getJdbcTemplate().update(deleteUserAuthoritiesSql, username); } - public void changePassword(String oldPassword, String newPassword) - throws AuthenticationException { - Authentication currentUser = SecurityContextHolder.getContext() - .getAuthentication(); + public void changePassword(String oldPassword, String newPassword) throws AuthenticationException { + Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); if (currentUser == null) { // This would indicate bad coding somewhere throw new AccessDeniedException( - "Can't change password as no Authentication object found in context " - + "for current user."); + "Can't change password as no Authentication object found in context " + "for current user."); } String username = currentUser.getName(); @@ -256,11 +286,9 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa // If an authentication manager has been set, re-authenticate the user with the // supplied password. if (authenticationManager != null) { - logger.debug("Reauthenticating user '" + username - + "' for password change request."); + logger.debug("Reauthenticating user '" + username + "' for password change request."); - authenticationManager.authenticate(new UsernamePasswordAuthenticationToken( - username, oldPassword)); + authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, oldPassword)); } else { logger.debug("No authentication manager set. Password won't be re-checked."); @@ -270,30 +298,27 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa getJdbcTemplate().update(changePasswordSql, newPassword, username); - SecurityContextHolder.getContext().setAuthentication( - createNewAuthentication(currentUser, newPassword)); + SecurityContextHolder.getContext().setAuthentication(createNewAuthentication(currentUser, newPassword)); userCache.removeUserFromCache(username); } - protected Authentication createNewAuthentication(Authentication currentAuth, - String newPassword) { + protected Authentication createNewAuthentication(Authentication currentAuth, String newPassword) { UserDetails user = loadUserByUsername(currentAuth.getName()); - UsernamePasswordAuthenticationToken newAuthentication = new UsernamePasswordAuthenticationToken( - user, null, user.getAuthorities()); + UsernamePasswordAuthenticationToken newAuthentication = new UsernamePasswordAuthenticationToken(user, null, + user.getAuthorities()); newAuthentication.setDetails(currentAuth.getDetails()); return newAuthentication; } public boolean userExists(String username) { - List users = getJdbcTemplate().queryForList(userExistsSql, - new String[] { username }, String.class); + List users = getJdbcTemplate().queryForList(userExistsSql, new String[] { username }, String.class); if (users.size() > 1) { - throw new IncorrectResultSizeDataAccessException( - "More than one user found with name '" + username + "'", 1); + throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username + "'", + 1); } return users.size() == 1; @@ -308,12 +333,10 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa public List findUsersInGroup(String groupName) { Assert.hasText(groupName, "groupName should have text"); - return getJdbcTemplate().queryForList(findUsersInGroupSql, - new String[] { groupName }, String.class); + return getJdbcTemplate().queryForList(findUsersInGroupSql, new String[] { groupName }, String.class); } - public void createGroup(final String groupName, - final List authorities) { + public void createGroup(final String groupName, final List authorities) { Assert.hasText(groupName, "groupName should have text"); Assert.notNull(authorities, "authorities cannot be null"); @@ -326,11 +349,10 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa for (GrantedAuthority a : authorities) { final String authority = a.getAuthority(); - getJdbcTemplate().update(insertGroupAuthoritySql, - ps -> { - ps.setInt(1, groupId); - ps.setString(2, authority); - }); + getJdbcTemplate().update(insertGroupAuthoritySql, ps -> { + ps.setInt(1, groupId); + ps.setString(2, authority); + }); } } @@ -386,17 +408,15 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa logger.debug("Loading authorities for group '" + groupName + "'"); Assert.hasText(groupName, "groupName should have text"); - return getJdbcTemplate().query(groupAuthoritiesSql, new String[] { groupName }, - (rs, rowNum) -> { - String roleName = getRolePrefix() + rs.getString(3); + return getJdbcTemplate().query(groupAuthoritiesSql, new String[] { groupName }, (rs, rowNum) -> { + String roleName = getRolePrefix() + rs.getString(3); - return new SimpleGrantedAuthority(roleName); - }); + return new SimpleGrantedAuthority(roleName); + }); } public void removeGroupAuthority(String groupName, final GrantedAuthority authority) { - logger.debug("Removing authority '" + authority + "' from group '" + groupName - + "'"); + logger.debug("Removing authority '" + authority + "' from group '" + groupName + "'"); Assert.hasText(groupName, "groupName should have text"); Assert.notNull(authority, "authority cannot be null"); @@ -532,7 +552,6 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa * Optionally sets the UserCache if one is in use in the application. This allows the * user to be removed from the cache after updates have taken place to avoid stale * data. - * * @param userCache the cache used by the AuthenticationManager. */ public void setUserCache(UserCache userCache) { @@ -550,8 +569,8 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa for (GrantedAuthority authority : authorities) { Assert.notNull(authority, "Authorities list contains a null entry"); - Assert.hasText(authority.getAuthority(), - "getAuthority() method must return a non-empty string"); + Assert.hasText(authority.getAuthority(), "getAuthority() method must return a non-empty string"); } } + } diff --git a/core/src/main/java/org/springframework/security/provisioning/MutableUser.java b/core/src/main/java/org/springframework/security/provisioning/MutableUser.java index 04d62b42fc..b5df07122e 100644 --- a/core/src/main/java/org/springframework/security/provisioning/MutableUser.java +++ b/core/src/main/java/org/springframework/security/provisioning/MutableUser.java @@ -22,7 +22,6 @@ import org.springframework.security.core.SpringSecurityCoreVersion; import org.springframework.security.core.userdetails.UserDetails; /** - * * @author Luke Taylor * @since 3.1 */ @@ -31,6 +30,7 @@ class MutableUser implements MutableUserDetails { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private String password; + private final UserDetails delegate; MutableUser(UserDetails user) { @@ -69,4 +69,5 @@ class MutableUser implements MutableUserDetails { public boolean isEnabled() { return delegate.isEnabled(); } + } diff --git a/core/src/main/java/org/springframework/security/provisioning/MutableUserDetails.java b/core/src/main/java/org/springframework/security/provisioning/MutableUserDetails.java index 10bc1f2d3a..7fdcc40565 100644 --- a/core/src/main/java/org/springframework/security/provisioning/MutableUserDetails.java +++ b/core/src/main/java/org/springframework/security/provisioning/MutableUserDetails.java @@ -18,7 +18,6 @@ package org.springframework.security.provisioning; import org.springframework.security.core.userdetails.UserDetails; /** - * * @author Luke Taylor * @since 3.1 */ diff --git a/core/src/main/java/org/springframework/security/provisioning/UserDetailsManager.java b/core/src/main/java/org/springframework/security/provisioning/UserDetailsManager.java index 730bb6641e..2bbf3db53c 100644 --- a/core/src/main/java/org/springframework/security/provisioning/UserDetailsManager.java +++ b/core/src/main/java/org/springframework/security/provisioning/UserDetailsManager.java @@ -45,7 +45,6 @@ public interface UserDetailsManager extends UserDetailsService { /** * Modify the current user's password. This should change the user's password in the * persistent user repository (datbase, LDAP etc). - * * @param oldPassword current password (for re-authentication if required) * @param newPassword the password to change to */ diff --git a/core/src/main/java/org/springframework/security/provisioning/package-info.java b/core/src/main/java/org/springframework/security/provisioning/package-info.java index 40f1195f63..b64773f3da 100644 --- a/core/src/main/java/org/springframework/security/provisioning/package-info.java +++ b/core/src/main/java/org/springframework/security/provisioning/package-info.java @@ -14,8 +14,7 @@ * limitations under the License. */ /** - * Contains simple user and authority group account provisioning interfaces together with a a - * JDBC-based implementation. + * Contains simple user and authority group account provisioning interfaces together with + * a a JDBC-based implementation. */ package org.springframework.security.provisioning; - diff --git a/core/src/main/java/org/springframework/security/scheduling/DelegatingSecurityContextSchedulingTaskExecutor.java b/core/src/main/java/org/springframework/security/scheduling/DelegatingSecurityContextSchedulingTaskExecutor.java index 6fa2a09a18..ef26041454 100644 --- a/core/src/main/java/org/springframework/security/scheduling/DelegatingSecurityContextSchedulingTaskExecutor.java +++ b/core/src/main/java/org/springframework/security/scheduling/DelegatingSecurityContextSchedulingTaskExecutor.java @@ -32,21 +32,19 @@ import org.springframework.security.task.DelegatingSecurityContextAsyncTaskExecu * @author Rob Winch * @since 3.2 */ -public class DelegatingSecurityContextSchedulingTaskExecutor extends - DelegatingSecurityContextAsyncTaskExecutor implements SchedulingTaskExecutor { +public class DelegatingSecurityContextSchedulingTaskExecutor extends DelegatingSecurityContextAsyncTaskExecutor + implements SchedulingTaskExecutor { /** * Creates a new {@link DelegatingSecurityContextSchedulingTaskExecutor} that uses the * specified {@link SecurityContext}. - * * @param delegateSchedulingTaskExecutor the {@link SchedulingTaskExecutor} to * delegate to. Cannot be null. * @param securityContext the {@link SecurityContext} to use for each * {@link DelegatingSecurityContextRunnable} and * {@link DelegatingSecurityContextCallable} */ - public DelegatingSecurityContextSchedulingTaskExecutor( - SchedulingTaskExecutor delegateSchedulingTaskExecutor, + public DelegatingSecurityContextSchedulingTaskExecutor(SchedulingTaskExecutor delegateSchedulingTaskExecutor, SecurityContext securityContext) { super(delegateSchedulingTaskExecutor, securityContext); } @@ -54,12 +52,10 @@ public class DelegatingSecurityContextSchedulingTaskExecutor extends /** * Creates a new {@link DelegatingSecurityContextSchedulingTaskExecutor} that uses the * current {@link SecurityContext}. - * * @param delegateAsyncTaskExecutor the {@link AsyncTaskExecutor} to delegate to. * Cannot be null. */ - public DelegatingSecurityContextSchedulingTaskExecutor( - SchedulingTaskExecutor delegateAsyncTaskExecutor) { + public DelegatingSecurityContextSchedulingTaskExecutor(SchedulingTaskExecutor delegateAsyncTaskExecutor) { this(delegateAsyncTaskExecutor, null); } @@ -70,4 +66,5 @@ public class DelegatingSecurityContextSchedulingTaskExecutor extends private SchedulingTaskExecutor getDelegate() { return (SchedulingTaskExecutor) getDelegateExecutor(); } + } diff --git a/core/src/main/java/org/springframework/security/scheduling/DelegatingSecurityContextTaskScheduler.java b/core/src/main/java/org/springframework/security/scheduling/DelegatingSecurityContextTaskScheduler.java index 9087732952..df197385f0 100644 --- a/core/src/main/java/org/springframework/security/scheduling/DelegatingSecurityContextTaskScheduler.java +++ b/core/src/main/java/org/springframework/security/scheduling/DelegatingSecurityContextTaskScheduler.java @@ -23,8 +23,8 @@ import java.util.Date; import java.util.concurrent.ScheduledFuture; /** - * An implementation of {@link TaskScheduler} invoking it whenever the trigger - * indicates a next execution time. + * An implementation of {@link TaskScheduler} invoking it whenever the trigger indicates a + * next execution time. * * @author Richard Valdivieso * @since 5.1 @@ -35,7 +35,6 @@ public class DelegatingSecurityContextTaskScheduler implements TaskScheduler { /** * Creates a new {@link DelegatingSecurityContextTaskScheduler} - * * @param taskScheduler the {@link TaskScheduler} */ public DelegatingSecurityContextTaskScheduler(TaskScheduler taskScheduler) { @@ -72,4 +71,5 @@ public class DelegatingSecurityContextTaskScheduler implements TaskScheduler { public ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay) { return taskScheduler.scheduleWithFixedDelay(task, delay); } + } diff --git a/core/src/main/java/org/springframework/security/task/DelegatingSecurityContextAsyncTaskExecutor.java b/core/src/main/java/org/springframework/security/task/DelegatingSecurityContextAsyncTaskExecutor.java index f622747b44..6bdcc89ee1 100644 --- a/core/src/main/java/org/springframework/security/task/DelegatingSecurityContextAsyncTaskExecutor.java +++ b/core/src/main/java/org/springframework/security/task/DelegatingSecurityContextAsyncTaskExecutor.java @@ -31,33 +31,30 @@ import org.springframework.security.core.context.SecurityContext; * @author Rob Winch * @since 3.2 */ -public class DelegatingSecurityContextAsyncTaskExecutor extends - DelegatingSecurityContextTaskExecutor implements AsyncTaskExecutor { +public class DelegatingSecurityContextAsyncTaskExecutor extends DelegatingSecurityContextTaskExecutor + implements AsyncTaskExecutor { /** * Creates a new {@link DelegatingSecurityContextAsyncTaskExecutor} that uses the * specified {@link SecurityContext}. - * * @param delegateAsyncTaskExecutor the {@link AsyncTaskExecutor} to delegate to. * Cannot be null. * @param securityContext the {@link SecurityContext} to use for each * {@link DelegatingSecurityContextRunnable} and * {@link DelegatingSecurityContextCallable} */ - public DelegatingSecurityContextAsyncTaskExecutor( - AsyncTaskExecutor delegateAsyncTaskExecutor, SecurityContext securityContext) { + public DelegatingSecurityContextAsyncTaskExecutor(AsyncTaskExecutor delegateAsyncTaskExecutor, + SecurityContext securityContext) { super(delegateAsyncTaskExecutor, securityContext); } /** * Creates a new {@link DelegatingSecurityContextAsyncTaskExecutor} that uses the * current {@link SecurityContext}. - * * @param delegateAsyncTaskExecutor the {@link AsyncTaskExecutor} to delegate to. * Cannot be null. */ - public DelegatingSecurityContextAsyncTaskExecutor( - AsyncTaskExecutor delegateAsyncTaskExecutor) { + public DelegatingSecurityContextAsyncTaskExecutor(AsyncTaskExecutor delegateAsyncTaskExecutor) { this(delegateAsyncTaskExecutor, null); } @@ -79,4 +76,5 @@ public class DelegatingSecurityContextAsyncTaskExecutor extends private AsyncTaskExecutor getDelegate() { return (AsyncTaskExecutor) getDelegateExecutor(); } + } diff --git a/core/src/main/java/org/springframework/security/task/DelegatingSecurityContextTaskExecutor.java b/core/src/main/java/org/springframework/security/task/DelegatingSecurityContextTaskExecutor.java index 776b89df3c..8aa7c58d56 100644 --- a/core/src/main/java/org/springframework/security/task/DelegatingSecurityContextTaskExecutor.java +++ b/core/src/main/java/org/springframework/security/task/DelegatingSecurityContextTaskExecutor.java @@ -28,30 +28,27 @@ import org.springframework.security.core.context.SecurityContextHolder; * @author Rob Winch * @since 3.2 */ -public class DelegatingSecurityContextTaskExecutor extends - DelegatingSecurityContextExecutor implements TaskExecutor { +public class DelegatingSecurityContextTaskExecutor extends DelegatingSecurityContextExecutor implements TaskExecutor { + /** * Creates a new {@link DelegatingSecurityContextTaskExecutor} that uses the specified * {@link SecurityContext}. - * * @param delegateTaskExecutor the {@link TaskExecutor} to delegate to. Cannot be * null. * @param securityContext the {@link SecurityContext} to use for each * {@link DelegatingSecurityContextRunnable} */ - public DelegatingSecurityContextTaskExecutor(TaskExecutor delegateTaskExecutor, - SecurityContext securityContext) { + public DelegatingSecurityContextTaskExecutor(TaskExecutor delegateTaskExecutor, SecurityContext securityContext) { super(delegateTaskExecutor, securityContext); } /** * Creates a new {@link DelegatingSecurityContextTaskExecutor} that uses the current * {@link SecurityContext} from the {@link SecurityContextHolder}. - * - * @param delegate the {@link TaskExecutor} to delegate to. Cannot be - * null. + * @param delegate the {@link TaskExecutor} to delegate to. Cannot be null. */ public DelegatingSecurityContextTaskExecutor(TaskExecutor delegate) { this(delegate, null); } + } \ No newline at end of file diff --git a/core/src/main/java/org/springframework/security/util/FieldUtils.java b/core/src/main/java/org/springframework/security/util/FieldUtils.java index 50cd8484d7..663ff43b4e 100644 --- a/core/src/main/java/org/springframework/security/util/FieldUtils.java +++ b/core/src/main/java/org/springframework/security/util/FieldUtils.java @@ -33,16 +33,12 @@ public final class FieldUtils { // ======================================================================================================== /** * Attempts to locate the specified field on the class. - * * @param clazz the class definition containing the field * @param fieldName the name of the field to locate - * * @return the Field (never null) - * * @throws IllegalStateException if field could not be found */ - public static Field getField(Class clazz, String fieldName) - throws IllegalStateException { + public static Field getField(Class clazz, String fieldName) throws IllegalStateException { Assert.notNull(clazz, "Class required"); Assert.hasText(fieldName, "Field name required"); @@ -55,8 +51,7 @@ public final class FieldUtils { return getField(clazz.getSuperclass(), fieldName); } - throw new IllegalStateException("Could not locate field '" + fieldName - + "' on class " + clazz); + throw new IllegalStateException("Could not locate field '" + fieldName + "' on class " + clazz); } } @@ -66,8 +61,7 @@ public final class FieldUtils { * @param fieldName the field name, with "." separating nested properties * @return the value of the nested field */ - public static Object getFieldValue(Object bean, String fieldName) - throws IllegalAccessException { + public static Object getFieldValue(Object bean, String fieldName) throws IllegalAccessException { Assert.notNull(bean, "Bean cannot be null"); Assert.hasText(fieldName, "Field name required"); String[] nestedFields = StringUtils.tokenizeToStringArray(fieldName, "."); @@ -102,8 +96,7 @@ public final class FieldUtils { } } - public static void setProtectedFieldValue(String protectedField, Object object, - Object newValue) { + public static void setProtectedFieldValue(String protectedField, Object object, Object newValue) { Field field = FieldUtils.getField(object.getClass(), protectedField); try { @@ -114,4 +107,5 @@ public final class FieldUtils { ReflectionUtils.handleReflectionException(ex); } } + } diff --git a/core/src/main/java/org/springframework/security/util/InMemoryResource.java b/core/src/main/java/org/springframework/security/util/InMemoryResource.java index 65fe2f7bc6..61ea2cea71 100644 --- a/core/src/main/java/org/springframework/security/util/InMemoryResource.java +++ b/core/src/main/java/org/springframework/security/util/InMemoryResource.java @@ -33,10 +33,12 @@ import java.util.Arrays; * @author Luke Taylor */ public class InMemoryResource extends AbstractResource { + // ~ Instance fields // ================================================================================================ private final byte[] source; + private final String description; // ~ Constructors @@ -82,4 +84,5 @@ public class InMemoryResource extends AbstractResource { return Arrays.equals(source, ((InMemoryResource) res).source); } + } diff --git a/core/src/main/java/org/springframework/security/util/MethodInvocationUtils.java b/core/src/main/java/org/springframework/security/util/MethodInvocationUtils.java index fa4c7cd8cb..1b49cd2ec0 100644 --- a/core/src/main/java/org/springframework/security/util/MethodInvocationUtils.java +++ b/core/src/main/java/org/springframework/security/util/MethodInvocationUtils.java @@ -40,17 +40,14 @@ public final class MethodInvocationUtils { /** * Generates a MethodInvocation for specified methodName on * the passed object, using the args to locate the method. - * * @param object the object that will be used to find the relevant Method * @param methodName the name of the method to find * @param args arguments that are required as part of the method signature (can be * empty) - * * @return a MethodInvocation, or null if there was a * problem */ - public static MethodInvocation create(Object object, String methodName, - Object... args) { + public static MethodInvocation create(Object object, String methodName, Object... args) { Assert.notNull(object, "Object required"); Class[] classArgs = null; @@ -95,11 +92,9 @@ public final class MethodInvocationUtils { * through the declared methods on the class, until one is found matching the supplied * name. If more than one method name matches, an IllegalArgumentException * will be raised. - * * @param clazz the class of object that will be used to find the relevant * Method * @param methodName the name of the method to find - * * @return a MethodInvocation, or null if there was a * problem */ @@ -110,9 +105,8 @@ public final class MethodInvocationUtils { for (Method m : clazz.getDeclaredMethods()) { if (m.getName().equals(methodName)) { if (mi != null) { - throw new IllegalArgumentException("The class " + clazz - + " has more than one method named" + " '" + methodName - + "'"); + throw new IllegalArgumentException( + "The class " + clazz + " has more than one method named" + " '" + methodName + "'"); } mi = new SimpleMethodInvocation(null, m); } @@ -125,7 +119,6 @@ public final class MethodInvocationUtils { /** * Generates a MethodInvocation for specified methodName on * the passed class, using the args to locate the method. - * * @param targetObject the object being invoked * @param clazz the class of object that will be used to find the relevant * Method @@ -136,8 +129,8 @@ public final class MethodInvocationUtils { * @return a MethodInvocation, or null if there was a * problem */ - public static MethodInvocation createFromClass(Object targetObject, Class clazz, - String methodName, Class[] classArgs, Object[] args) { + public static MethodInvocation createFromClass(Object targetObject, Class clazz, String methodName, + Class[] classArgs, Object[] args) { Assert.notNull(clazz, "Class required"); Assert.hasText(methodName, "MethodName required"); @@ -152,4 +145,5 @@ public final class MethodInvocationUtils { return new SimpleMethodInvocation(targetObject, method, args); } + } diff --git a/core/src/main/java/org/springframework/security/util/SimpleMethodInvocation.java b/core/src/main/java/org/springframework/security/util/SimpleMethodInvocation.java index a930b22f2f..ec16f61f44 100644 --- a/core/src/main/java/org/springframework/security/util/SimpleMethodInvocation.java +++ b/core/src/main/java/org/springframework/security/util/SimpleMethodInvocation.java @@ -27,11 +27,14 @@ import java.lang.reflect.Method; * @author Ben Alex */ public class SimpleMethodInvocation implements MethodInvocation { + // ~ Instance fields // ================================================================================================ private Method method; + private Object[] arguments; + private Object targetObject; // ~ Constructors @@ -68,4 +71,5 @@ public class SimpleMethodInvocation implements MethodInvocation { public Object proceed() { throw new UnsupportedOperationException("mock method not implemented"); } + } diff --git a/core/src/main/java/org/springframework/security/util/package-info.java b/core/src/main/java/org/springframework/security/util/package-info.java index fba13f4bed..3f3a9bdc95 100644 --- a/core/src/main/java/org/springframework/security/util/package-info.java +++ b/core/src/main/java/org/springframework/security/util/package-info.java @@ -14,10 +14,10 @@ * limitations under the License. */ /** - * General utility classes used throughout the Spring Security framework. Intended for internal use. + * General utility classes used throughout the Spring Security framework. Intended for + * internal use. *

      - * This package should be standalone - it should not have dependencies on other parts of the framework, - * just on external libraries and the JDK. + * This package should be standalone - it should not have dependencies on other parts of + * the framework, just on external libraries and the JDK. */ package org.springframework.security.util; - diff --git a/core/src/test/java/org/springframework/security/ITargetObject.java b/core/src/test/java/org/springframework/security/ITargetObject.java index f0460b6233..46efcfd133 100644 --- a/core/src/test/java/org/springframework/security/ITargetObject.java +++ b/core/src/test/java/org/springframework/security/ITargetObject.java @@ -22,6 +22,7 @@ package org.springframework.security; * @author Ben Alex */ public interface ITargetObject { + // ~ Methods // ======================================================================================================== @@ -34,4 +35,5 @@ public interface ITargetObject { String makeUpperCase(String input); String publicMakeLowerCase(String input); + } diff --git a/core/src/test/java/org/springframework/security/OtherTargetObject.java b/core/src/test/java/org/springframework/security/OtherTargetObject.java index ae0d240d87..32722f405a 100644 --- a/core/src/test/java/org/springframework/security/OtherTargetObject.java +++ b/core/src/test/java/org/springframework/security/OtherTargetObject.java @@ -34,6 +34,7 @@ package org.springframework.security; * @author Ben Alex */ public class OtherTargetObject extends TargetObject implements ITargetObject { + // ~ Methods // ======================================================================================================== @@ -48,4 +49,5 @@ public class OtherTargetObject extends TargetObject implements ITargetObject { public String publicMakeLowerCase(String input) { return super.publicMakeLowerCase(input); } + } diff --git a/core/src/test/java/org/springframework/security/PopulatedDatabase.java b/core/src/test/java/org/springframework/security/PopulatedDatabase.java index af67a37170..8c3774bacb 100644 --- a/core/src/test/java/org/springframework/security/PopulatedDatabase.java +++ b/core/src/test/java/org/springframework/security/PopulatedDatabase.java @@ -27,6 +27,7 @@ import javax.sql.DataSource; * @author Ben Alex */ public class PopulatedDatabase { + // ~ Static fields/initializers // ===================================================================================== @@ -53,11 +54,15 @@ public class PopulatedDatabase { dataSource = new TestDataSource("springsecuritytest"); JdbcTemplate template = new JdbcTemplate(dataSource); - template.execute("CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(500) NOT NULL,ENABLED BOOLEAN NOT NULL)"); - template.execute("CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME))"); + template.execute( + "CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(500) NOT NULL,ENABLED BOOLEAN NOT NULL)"); + template.execute( + "CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME))"); template.execute("CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY)"); - template.execute("CREATE TABLE ACL_OBJECT_IDENTITY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,OBJECT_IDENTITY VARCHAR_IGNORECASE(250) NOT NULL,PARENT_OBJECT BIGINT,ACL_CLASS VARCHAR_IGNORECASE(250) NOT NULL,CONSTRAINT UNIQUE_OBJECT_IDENTITY UNIQUE(OBJECT_IDENTITY),CONSTRAINT SYS_FK_3 FOREIGN KEY(PARENT_OBJECT) REFERENCES ACL_OBJECT_IDENTITY(ID))"); - template.execute("CREATE TABLE ACL_PERMISSION(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,ACL_OBJECT_IDENTITY BIGINT NOT NULL,RECIPIENT VARCHAR_IGNORECASE(100) NOT NULL,MASK INTEGER NOT NULL,CONSTRAINT UNIQUE_RECIPIENT UNIQUE(ACL_OBJECT_IDENTITY,RECIPIENT),CONSTRAINT SYS_FK_7 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID))"); + template.execute( + "CREATE TABLE ACL_OBJECT_IDENTITY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,OBJECT_IDENTITY VARCHAR_IGNORECASE(250) NOT NULL,PARENT_OBJECT BIGINT,ACL_CLASS VARCHAR_IGNORECASE(250) NOT NULL,CONSTRAINT UNIQUE_OBJECT_IDENTITY UNIQUE(OBJECT_IDENTITY),CONSTRAINT SYS_FK_3 FOREIGN KEY(PARENT_OBJECT) REFERENCES ACL_OBJECT_IDENTITY(ID))"); + template.execute( + "CREATE TABLE ACL_PERMISSION(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,ACL_OBJECT_IDENTITY BIGINT NOT NULL,RECIPIENT VARCHAR_IGNORECASE(100) NOT NULL,MASK INTEGER NOT NULL,CONSTRAINT UNIQUE_RECIPIENT UNIQUE(ACL_OBJECT_IDENTITY,RECIPIENT),CONSTRAINT SYS_FK_7 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID))"); template.execute("SET IGNORECASE TRUE"); template.execute("INSERT INTO USERS VALUES('dianne','emu',TRUE)"); template.execute("INSERT INTO USERS VALUES('rod','koala',TRUE)"); @@ -69,15 +74,22 @@ public class PopulatedDatabase { template.execute("INSERT INTO AUTHORITIES VALUES('dianne','ROLE_TELLER')"); template.execute("INSERT INTO AUTHORITIES VALUES('scott','ROLE_TELLER')"); template.execute("INSERT INTO AUTHORITIES VALUES('peter','ROLE_TELLER')"); - template.execute("INSERT INTO acl_object_identity VALUES (1, 'org.springframework.security.acl.DomainObject:1', null, 'org.springframework.security.acl.basic.SimpleAclEntry');"); - template.execute("INSERT INTO acl_object_identity VALUES (2, 'org.springframework.security.acl.DomainObject:2', 1, 'org.springframework.security.acl.basic.SimpleAclEntry');"); - template.execute("INSERT INTO acl_object_identity VALUES (3, 'org.springframework.security.acl.DomainObject:3', 1, 'org.springframework.security.acl.basic.SimpleAclEntry');"); - template.execute("INSERT INTO acl_object_identity VALUES (4, 'org.springframework.security.acl.DomainObject:4', 1, 'org.springframework.security.acl.basic.SimpleAclEntry');"); - template.execute("INSERT INTO acl_object_identity VALUES (5, 'org.springframework.security.acl.DomainObject:5', 3, 'org.springframework.security.acl.basic.SimpleAclEntry');"); - template.execute("INSERT INTO acl_object_identity VALUES (6, 'org.springframework.security.acl.DomainObject:6', 3, 'org.springframework.security.acl.basic.SimpleAclEntry');"); + template.execute( + "INSERT INTO acl_object_identity VALUES (1, 'org.springframework.security.acl.DomainObject:1', null, 'org.springframework.security.acl.basic.SimpleAclEntry');"); + template.execute( + "INSERT INTO acl_object_identity VALUES (2, 'org.springframework.security.acl.DomainObject:2', 1, 'org.springframework.security.acl.basic.SimpleAclEntry');"); + template.execute( + "INSERT INTO acl_object_identity VALUES (3, 'org.springframework.security.acl.DomainObject:3', 1, 'org.springframework.security.acl.basic.SimpleAclEntry');"); + template.execute( + "INSERT INTO acl_object_identity VALUES (4, 'org.springframework.security.acl.DomainObject:4', 1, 'org.springframework.security.acl.basic.SimpleAclEntry');"); + template.execute( + "INSERT INTO acl_object_identity VALUES (5, 'org.springframework.security.acl.DomainObject:5', 3, 'org.springframework.security.acl.basic.SimpleAclEntry');"); + template.execute( + "INSERT INTO acl_object_identity VALUES (6, 'org.springframework.security.acl.DomainObject:6', 3, 'org.springframework.security.acl.basic.SimpleAclEntry');"); // ----- BEGIN deviation from normal sample data load script ----- - template.execute("INSERT INTO acl_object_identity VALUES (7, 'org.springframework.security.acl.DomainObject:7', 3, 'some.invalid.acl.entry.class');"); + template.execute( + "INSERT INTO acl_object_identity VALUES (7, 'org.springframework.security.acl.DomainObject:7', 3, 'some.invalid.acl.entry.class');"); // ----- FINISH deviation from normal sample data load script ----- template.execute("INSERT INTO acl_permission VALUES (null, 1, 'ROLE_SUPERVISOR', 1);"); @@ -92,9 +104,12 @@ public class PopulatedDatabase { public static void createGroupTables(JdbcTemplate template) { // Group tables and data - template.execute("CREATE TABLE GROUPS(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) PRIMARY KEY, GROUP_NAME VARCHAR_IGNORECASE(50) NOT NULL)"); - template.execute("CREATE TABLE GROUP_AUTHORITIES(GROUP_ID BIGINT NOT NULL, AUTHORITY VARCHAR(50) NOT NULL, CONSTRAINT FK_GROUP_AUTHORITIES_GROUP FOREIGN KEY(GROUP_ID) REFERENCES GROUPS(ID))"); - template.execute("CREATE TABLE GROUP_MEMBERS(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) PRIMARY KEY, USERNAME VARCHAR(50) NOT NULL, GROUP_ID BIGINT NOT NULL, CONSTRAINT FK_GROUP_MEMBERS_GROUP FOREIGN KEY(GROUP_ID) REFERENCES GROUPS(ID))"); + template.execute( + "CREATE TABLE GROUPS(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) PRIMARY KEY, GROUP_NAME VARCHAR_IGNORECASE(50) NOT NULL)"); + template.execute( + "CREATE TABLE GROUP_AUTHORITIES(GROUP_ID BIGINT NOT NULL, AUTHORITY VARCHAR(50) NOT NULL, CONSTRAINT FK_GROUP_AUTHORITIES_GROUP FOREIGN KEY(GROUP_ID) REFERENCES GROUPS(ID))"); + template.execute( + "CREATE TABLE GROUP_MEMBERS(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0) PRIMARY KEY, USERNAME VARCHAR(50) NOT NULL, GROUP_ID BIGINT NOT NULL, CONSTRAINT FK_GROUP_MEMBERS_GROUP FOREIGN KEY(GROUP_ID) REFERENCES GROUPS(ID))"); } public static void insertGroupData(JdbcTemplate template) { @@ -122,4 +137,5 @@ public class PopulatedDatabase { template.execute("INSERT INTO GROUP_MEMBERS VALUES (2, 'tom', 1)"); template.execute("INSERT INTO GROUP_MEMBERS VALUES (3, 'tom', 2)"); } + } diff --git a/core/src/test/java/org/springframework/security/TargetObject.java b/core/src/test/java/org/springframework/security/TargetObject.java index 612d401b59..1ab1de4b5c 100644 --- a/core/src/test/java/org/springframework/security/TargetObject.java +++ b/core/src/test/java/org/springframework/security/TargetObject.java @@ -25,6 +25,7 @@ import org.springframework.security.core.context.SecurityContextHolder; * @author Ben Alex */ public class TargetObject implements ITargetObject { + // ~ Methods // ======================================================================================================== @@ -38,9 +39,7 @@ public class TargetObject implements ITargetObject { /** * Returns the lowercase string, followed by security environment information. - * * @param input the message to make lowercase - * * @return the lowercase message, a space, the Authentication class that * was on the SecurityContext at the time of method invocation, and a * boolean indicating if the Authentication object is authenticated or @@ -53,16 +52,13 @@ public class TargetObject implements ITargetObject { return input.toLowerCase() + " Authentication empty"; } else { - return input.toLowerCase() + " " + auth.getClass().getName() + " " - + auth.isAuthenticated(); + return input.toLowerCase() + " " + auth.getClass().getName() + " " + auth.isAuthenticated(); } } /** * Returns the uppercase string, followed by security environment information. - * * @param input the message to make uppercase - * * @return the uppercase message, a space, the Authentication class that * was on the SecurityContext at the time of method invocation, and a * boolean indicating if the Authentication object is authenticated or @@ -71,16 +67,15 @@ public class TargetObject implements ITargetObject { public String makeUpperCase(String input) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - return input.toUpperCase() + " " + auth.getClass().getName() + " " - + auth.isAuthenticated(); + return input.toUpperCase() + " " + auth.getClass().getName() + " " + auth.isAuthenticated(); } /** * Delegates through to the {@link #makeLowerCase(String)} method. - * * @param input the message to be made lower-case */ public String publicMakeLowerCase(String input) { return this.makeLowerCase(input); } + } diff --git a/core/src/test/java/org/springframework/security/TestDataSource.java b/core/src/test/java/org/springframework/security/TestDataSource.java index 53e79e12f0..8db83922ad 100644 --- a/core/src/test/java/org/springframework/security/TestDataSource.java +++ b/core/src/test/java/org/springframework/security/TestDataSource.java @@ -26,6 +26,7 @@ import org.springframework.beans.factory.DisposableBean; * @author Luke Taylor */ public class TestDataSource extends DriverManagerDataSource implements DisposableBean { + String name; public TestDataSource(String databaseName) { @@ -41,4 +42,5 @@ public class TestDataSource extends DriverManagerDataSource implements Disposabl System.out.println("Shutting down database: " + name); new JdbcTemplate(this).execute("SHUTDOWN"); } + } diff --git a/core/src/test/java/org/springframework/security/access/AuthenticationCredentialsNotFoundEventTests.java b/core/src/test/java/org/springframework/security/access/AuthenticationCredentialsNotFoundEventTests.java index 29e8ba822c..553c0068b9 100644 --- a/core/src/test/java/org/springframework/security/access/AuthenticationCredentialsNotFoundEventTests.java +++ b/core/src/test/java/org/springframework/security/access/AuthenticationCredentialsNotFoundEventTests.java @@ -31,8 +31,7 @@ public class AuthenticationCredentialsNotFoundEventTests { @Test(expected = IllegalArgumentException.class) public void testRejectsNulls() { - new AuthenticationCredentialsNotFoundEvent(null, - SecurityConfig.createList("TEST"), + new AuthenticationCredentialsNotFoundEvent(null, SecurityConfig.createList("TEST"), new AuthenticationCredentialsNotFoundException("test")); } @@ -44,7 +43,8 @@ public class AuthenticationCredentialsNotFoundEventTests { @Test(expected = IllegalArgumentException.class) public void testRejectsNulls3() { - new AuthenticationCredentialsNotFoundEvent(new SimpleMethodInvocation(), - SecurityConfig.createList("TEST"), null); + new AuthenticationCredentialsNotFoundEvent(new SimpleMethodInvocation(), SecurityConfig.createList("TEST"), + null); } + } diff --git a/core/src/test/java/org/springframework/security/access/AuthorizationFailureEventTests.java b/core/src/test/java/org/springframework/security/access/AuthorizationFailureEventTests.java index 31a198fddf..7f9c457056 100644 --- a/core/src/test/java/org/springframework/security/access/AuthorizationFailureEventTests.java +++ b/core/src/test/java/org/springframework/security/access/AuthorizationFailureEventTests.java @@ -31,11 +31,12 @@ import java.util.*; * @author Ben Alex */ public class AuthorizationFailureEventTests { - private final UsernamePasswordAuthenticationToken foo = new UsernamePasswordAuthenticationToken( - "foo", "bar"); + + private final UsernamePasswordAuthenticationToken foo = new UsernamePasswordAuthenticationToken("foo", "bar"); + private List attributes = SecurityConfig.createList("TEST"); - private AccessDeniedException exception = new AuthorizationServiceException("error", - new Throwable()); + + private AccessDeniedException exception = new AuthorizationServiceException("error", new Throwable()); @Test(expected = IllegalArgumentException.class) public void rejectsNullSecureObject() { @@ -49,8 +50,7 @@ public class AuthorizationFailureEventTests { @Test(expected = IllegalArgumentException.class) public void rejectsNullAuthentication() { - new AuthorizationFailureEvent(new SimpleMethodInvocation(), attributes, null, - exception); + new AuthorizationFailureEvent(new SimpleMethodInvocation(), attributes, null, exception); } @Test(expected = IllegalArgumentException.class) @@ -60,10 +60,10 @@ public class AuthorizationFailureEventTests { @Test public void gettersReturnCtorSuppliedData() { - AuthorizationFailureEvent event = new AuthorizationFailureEvent(new Object(), - attributes, foo, exception); + AuthorizationFailureEvent event = new AuthorizationFailureEvent(new Object(), attributes, foo, exception); assertThat(event.getConfigAttributes()).isSameAs(attributes); assertThat(event.getAccessDeniedException()).isSameAs(exception); assertThat(event.getAuthentication()).isSameAs(foo); } + } diff --git a/core/src/test/java/org/springframework/security/access/AuthorizedEventTests.java b/core/src/test/java/org/springframework/security/access/AuthorizedEventTests.java index dff9e761ae..ba501ab1c6 100644 --- a/core/src/test/java/org/springframework/security/access/AuthorizedEventTests.java +++ b/core/src/test/java/org/springframework/security/access/AuthorizedEventTests.java @@ -38,13 +38,12 @@ public class AuthorizedEventTests { @Test(expected = IllegalArgumentException.class) public void testRejectsNulls2() { - new AuthorizedEvent(new SimpleMethodInvocation(), null, - new UsernamePasswordAuthenticationToken("foo", "bar")); + new AuthorizedEvent(new SimpleMethodInvocation(), null, new UsernamePasswordAuthenticationToken("foo", "bar")); } @Test(expected = IllegalArgumentException.class) public void testRejectsNulls3() { - new AuthorizedEvent(new SimpleMethodInvocation(), - SecurityConfig.createList("TEST"), null); + new AuthorizedEvent(new SimpleMethodInvocation(), SecurityConfig.createList("TEST"), null); } + } diff --git a/core/src/test/java/org/springframework/security/access/SecurityConfigTests.java b/core/src/test/java/org/springframework/security/access/SecurityConfigTests.java index 3dc60932fd..6d99bd488b 100644 --- a/core/src/test/java/org/springframework/security/access/SecurityConfigTests.java +++ b/core/src/test/java/org/springframework/security/access/SecurityConfigTests.java @@ -16,7 +16,6 @@ package org.springframework.security.access; - import static org.assertj.core.api.Assertions.assertThat; import org.junit.Test; @@ -90,6 +89,7 @@ public class SecurityConfigTests { // ================================================================================================== private class MockConfigAttribute implements ConfigAttribute { + private String attribute; MockConfigAttribute(String configuration) { @@ -99,5 +99,7 @@ public class SecurityConfigTests { public String getAttribute() { return this.attribute; } + } + } diff --git a/core/src/test/java/org/springframework/security/access/annotation/BusinessService.java b/core/src/test/java/org/springframework/security/access/annotation/BusinessService.java index 2494083b2e..eff3ff65a6 100644 --- a/core/src/test/java/org/springframework/security/access/annotation/BusinessService.java +++ b/core/src/test/java/org/springframework/security/access/annotation/BusinessService.java @@ -29,6 +29,7 @@ import org.springframework.security.access.prepost.PreAuthorize; @Secured({ "ROLE_USER" }) @PermitAll public interface BusinessService extends Serializable { + // ~ Methods // ======================================================================================================== diff --git a/core/src/test/java/org/springframework/security/access/annotation/BusinessServiceImpl.java b/core/src/test/java/org/springframework/security/access/annotation/BusinessServiceImpl.java index 5d20ea9a4a..049e74ab3e 100644 --- a/core/src/test/java/org/springframework/security/access/annotation/BusinessServiceImpl.java +++ b/core/src/test/java/org/springframework/security/access/annotation/BusinessServiceImpl.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.List; /** - * * @author Joe Scalise */ public class BusinessServiceImpl implements BusinessService { @@ -67,4 +66,5 @@ public class BusinessServiceImpl implements BusinessService { public void rolesAllowedUser() { } + } diff --git a/core/src/test/java/org/springframework/security/access/annotation/Entity.java b/core/src/test/java/org/springframework/security/access/annotation/Entity.java index 7d68adb48f..ecb14e67aa 100644 --- a/core/src/test/java/org/springframework/security/access/annotation/Entity.java +++ b/core/src/test/java/org/springframework/security/access/annotation/Entity.java @@ -22,6 +22,8 @@ package org.springframework.security.access.annotation; * */ public class Entity { + public Entity(String someParameter) { } + } diff --git a/core/src/test/java/org/springframework/security/access/annotation/ExpressionProtectedBusinessServiceImpl.java b/core/src/test/java/org/springframework/security/access/annotation/ExpressionProtectedBusinessServiceImpl.java index 9652dab648..aa786b5f63 100644 --- a/core/src/test/java/org/springframework/security/access/annotation/ExpressionProtectedBusinessServiceImpl.java +++ b/core/src/test/java/org/springframework/security/access/annotation/ExpressionProtectedBusinessServiceImpl.java @@ -67,4 +67,5 @@ public class ExpressionProtectedBusinessServiceImpl implements BusinessService { public void rolesAllowedUser() { } + } diff --git a/core/src/test/java/org/springframework/security/access/annotation/Jsr250BusinessServiceImpl.java b/core/src/test/java/org/springframework/security/access/annotation/Jsr250BusinessServiceImpl.java index c09c0bab3c..7f8fe3f017 100644 --- a/core/src/test/java/org/springframework/security/access/annotation/Jsr250BusinessServiceImpl.java +++ b/core/src/test/java/org/springframework/security/access/annotation/Jsr250BusinessServiceImpl.java @@ -22,7 +22,6 @@ import javax.annotation.security.RolesAllowed; import javax.annotation.security.PermitAll; /** - * * @author Luke Taylor */ @PermitAll @@ -68,4 +67,5 @@ public class Jsr250BusinessServiceImpl implements BusinessService { public void rolesAllowedUser() { } + } diff --git a/core/src/test/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSourceTests.java b/core/src/test/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSourceTests.java index 2e2597160b..7e78a22718 100644 --- a/core/src/test/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSourceTests.java +++ b/core/src/test/java/org/springframework/security/access/annotation/Jsr250MethodSecurityMetadataSourceTests.java @@ -49,8 +49,7 @@ public class Jsr250MethodSecurityMetadataSourceTests { } private ConfigAttribute[] findAttributes(String methodName) throws Exception { - return this.mds.findAttributes(this.a.getClass().getMethod(methodName), null) - .toArray(new ConfigAttribute[0]); + return this.mds.findAttributes(this.a.getClass().getMethod(methodName), null).toArray(new ConfigAttribute[0]); } @Test @@ -64,8 +63,7 @@ public class Jsr250MethodSecurityMetadataSourceTests { public void permitAllMethodHasPermitAllAttribute() throws Exception { ConfigAttribute[] accessAttributes = findAttributes("permitAllMethod"); assertThat(accessAttributes).hasSize(1); - assertThat(accessAttributes[0].toString()) - .isEqualTo("javax.annotation.security.PermitAll"); + assertThat(accessAttributes[0].toString()).isEqualTo("javax.annotation.security.PermitAll"); } @Test @@ -77,15 +75,15 @@ public class Jsr250MethodSecurityMetadataSourceTests { @Test public void classRoleIsAppliedToNoRoleMethod() throws Exception { - Collection accessAttributes = this.mds.findAttributes( - this.userAllowed.getClass().getMethod("noRoleMethod"), null); + Collection accessAttributes = this.mds + .findAttributes(this.userAllowed.getClass().getMethod("noRoleMethod"), null); assertThat(accessAttributes).isNull(); } @Test public void methodRoleOverridesClassRole() throws Exception { - Collection accessAttributes = this.mds.findAttributes( - this.userAllowed.getClass().getMethod("adminMethod"), null); + Collection accessAttributes = this.mds + .findAttributes(this.userAllowed.getClass().getMethod("adminMethod"), null); assertThat(accessAttributes).hasSize(1); assertThat(accessAttributes.toArray()[0].toString()).isEqualTo("ROLE_ADMIN"); } @@ -130,26 +128,21 @@ public class Jsr250MethodSecurityMetadataSourceTests { * Class-level annotations only affect the class they annotate and their members, that * is, its methods and fields. They never affect a member declared by a superclass, * even if it is not hidden or overridden by the class in question. - * * @throws Exception */ @Test - public void classLevelAnnotationsOnlyAffectTheClassTheyAnnotateAndTheirMembers() - throws Exception { + public void classLevelAnnotationsOnlyAffectTheClassTheyAnnotateAndTheirMembers() throws Exception { Child target = new Child(); - MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), - "notOverriden"); + MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "notOverriden"); Collection accessAttributes = this.mds.getAttributes(mi); assertThat(accessAttributes).isNull(); } @Test - public void classLevelAnnotationsOnlyAffectTheClassTheyAnnotateAndTheirMembersOverriden() - throws Exception { + public void classLevelAnnotationsOnlyAffectTheClassTheyAnnotateAndTheirMembersOverriden() throws Exception { Child target = new Child(); - MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), - "overriden"); + MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "overriden"); Collection accessAttributes = this.mds.getAttributes(mi); assertThat(accessAttributes).hasSize(1); @@ -159,8 +152,7 @@ public class Jsr250MethodSecurityMetadataSourceTests { @Test public void classLevelAnnotationsImpactMemberLevel() throws Exception { Child target = new Child(); - MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), - "defaults"); + MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "defaults"); Collection accessAttributes = this.mds.getAttributes(mi); assertThat(accessAttributes).hasSize(1); @@ -168,11 +160,9 @@ public class Jsr250MethodSecurityMetadataSourceTests { } @Test - public void classLevelAnnotationsIgnoredByExplicitMemberAnnotation() - throws Exception { + public void classLevelAnnotationsIgnoredByExplicitMemberAnnotation() throws Exception { Child target = new Child(); - MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), - "explicitMethod"); + MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "explicitMethod"); Collection accessAttributes = this.mds.getAttributes(mi); assertThat(accessAttributes).hasSize(1); @@ -182,14 +172,12 @@ public class Jsr250MethodSecurityMetadataSourceTests { /** * The interfaces implemented by a class never contribute annotations to the class * itself or any of its members. - * * @throws Exception */ @Test public void interfacesNeverContributeAnnotationsMethodLevel() throws Exception { Parent target = new Parent(); - MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), - "interfaceMethod"); + MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "interfaceMethod"); Collection accessAttributes = this.mds.getAttributes(mi); assertThat(accessAttributes).isEmpty(); @@ -198,8 +186,7 @@ public class Jsr250MethodSecurityMetadataSourceTests { @Test public void interfacesNeverContributeAnnotationsClassLevel() throws Exception { Parent target = new Parent(); - MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), - "notOverriden"); + MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "notOverriden"); Collection accessAttributes = this.mds.getAttributes(mi); assertThat(accessAttributes).isEmpty(); @@ -208,8 +195,7 @@ public class Jsr250MethodSecurityMetadataSourceTests { @Test public void annotationsOnOverriddenMemberIgnored() throws Exception { Child target = new Child(); - MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), - "overridenIgnored"); + MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "overridenIgnored"); Collection accessAttributes = this.mds.getAttributes(mi); assertThat(accessAttributes).hasSize(1); @@ -235,6 +221,7 @@ public class Jsr250MethodSecurityMetadataSourceTests { @PermitAll public void permitAllMethod() { } + } @RolesAllowed("USER") @@ -246,6 +233,7 @@ public class Jsr250MethodSecurityMetadataSourceTests { @RolesAllowed("ADMIN") public void adminMethod() { } + } // JSR-250 Spec @@ -255,6 +243,7 @@ public class Jsr250MethodSecurityMetadataSourceTests { @RolesAllowed("INTERFACEMETHOD") void interfaceMethod(); + } static class Parent implements IParent { @@ -271,6 +260,7 @@ public class Jsr250MethodSecurityMetadataSourceTests { @RolesAllowed("OVERRIDENIGNORED") public void overridenIgnored() { } + } @RolesAllowed("DERIVED") @@ -290,5 +280,7 @@ public class Jsr250MethodSecurityMetadataSourceTests { @RolesAllowed("EXPLICIT") public void explicitMethod() { } + } + } diff --git a/core/src/test/java/org/springframework/security/access/annotation/Jsr250VoterTests.java b/core/src/test/java/org/springframework/security/access/annotation/Jsr250VoterTests.java index 6157b00309..2966163871 100644 --- a/core/src/test/java/org/springframework/security/access/annotation/Jsr250VoterTests.java +++ b/core/src/test/java/org/springframework/security/access/annotation/Jsr250VoterTests.java @@ -27,7 +27,6 @@ import org.springframework.security.access.SecurityConfig; import org.springframework.security.authentication.TestingAuthenticationToken; /** - * * @author Luke Taylor */ public class Jsr250VoterTests { @@ -42,19 +41,18 @@ public class Jsr250VoterTests { attrs.add(new Jsr250SecurityConfig("B")); attrs.add(new Jsr250SecurityConfig("C")); - assertThat(voter.vote( - new TestingAuthenticationToken("user", "pwd", "A"), new Object(), attrs)).isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); - assertThat(voter.vote( - new TestingAuthenticationToken("user", "pwd", "B"), new Object(), attrs)).isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); - assertThat(voter.vote( - new TestingAuthenticationToken("user", "pwd", "C"), new Object(), attrs)).isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); + assertThat(voter.vote(new TestingAuthenticationToken("user", "pwd", "A"), new Object(), attrs)) + .isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); + assertThat(voter.vote(new TestingAuthenticationToken("user", "pwd", "B"), new Object(), attrs)) + .isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); + assertThat(voter.vote(new TestingAuthenticationToken("user", "pwd", "C"), new Object(), attrs)) + .isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); - assertThat(voter.vote( - new TestingAuthenticationToken("user", "pwd", "NONE"), new Object(), - attrs)).isEqualTo(AccessDecisionVoter.ACCESS_DENIED); + assertThat(voter.vote(new TestingAuthenticationToken("user", "pwd", "NONE"), new Object(), attrs)) + .isEqualTo(AccessDecisionVoter.ACCESS_DENIED); - assertThat(voter.vote( - new TestingAuthenticationToken("user", "pwd", "A"), new Object(), + assertThat(voter.vote(new TestingAuthenticationToken("user", "pwd", "A"), new Object(), SecurityConfig.createList("A", "B", "C"))).isEqualTo(AccessDecisionVoter.ACCESS_ABSTAIN); } + } diff --git a/core/src/test/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSourceTests.java b/core/src/test/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSourceTests.java index ad60044daa..d9364734c8 100644 --- a/core/src/test/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSourceTests.java +++ b/core/src/test/java/org/springframework/security/access/annotation/SecuredAnnotationSecurityMetadataSourceTests.java @@ -47,6 +47,7 @@ import org.springframework.security.core.GrantedAuthority; * @author Luke Taylor */ public class SecuredAnnotationSecurityMetadataSourceTests { + // ~ Instance fields // ================================================================================================ @@ -60,15 +61,13 @@ public class SecuredAnnotationSecurityMetadataSourceTests { Method method = null; try { - method = DepartmentServiceImpl.class.getMethod("someUserMethod3", - new Class[] { Department.class }); + method = DepartmentServiceImpl.class.getMethod("someUserMethod3", new Class[] { Department.class }); } catch (NoSuchMethodException unexpected) { fail("Should be a superMethod called 'someUserMethod3' on class!"); } - Collection attrs = mds.findAttributes(method, - DepartmentServiceImpl.class); + Collection attrs = mds.findAttributes(method, DepartmentServiceImpl.class); assertThat(attrs).isNotNull(); @@ -77,22 +76,19 @@ public class SecuredAnnotationSecurityMetadataSourceTests { // should have 1 SecurityConfig for (ConfigAttribute sc : attrs) { - assertThat(sc.getAttribute()).as("Found an incorrect role").isEqualTo( - "ROLE_ADMIN"); + assertThat(sc.getAttribute()).as("Found an incorrect role").isEqualTo("ROLE_ADMIN"); } Method superMethod = null; try { - superMethod = DepartmentServiceImpl.class.getMethod("someUserMethod3", - new Class[] { Entity.class }); + superMethod = DepartmentServiceImpl.class.getMethod("someUserMethod3", new Class[] { Entity.class }); } catch (NoSuchMethodException unexpected) { fail("Should be a superMethod called 'someUserMethod3' on class!"); } - Collection superAttrs = this.mds.findAttributes(superMethod, - DepartmentServiceImpl.class); + Collection superAttrs = this.mds.findAttributes(superMethod, DepartmentServiceImpl.class); assertThat(superAttrs).isNotNull(); @@ -101,15 +97,13 @@ public class SecuredAnnotationSecurityMetadataSourceTests { assertThat(superAttrs).as("Did not find 1 attribute").hasSize(1); // should have 1 SecurityConfig for (ConfigAttribute sc : superAttrs) { - assertThat(sc.getAttribute()).as("Found an incorrect role").isEqualTo( - "ROLE_ADMIN"); + assertThat(sc.getAttribute()).as("Found an incorrect role").isEqualTo("ROLE_ADMIN"); } } @Test public void classLevelAttributesAreFound() { - Collection attrs = this.mds.findAttributes( - BusinessService.class); + Collection attrs = this.mds.findAttributes(BusinessService.class); assertThat(attrs).isNotNull(); @@ -127,15 +121,13 @@ public class SecuredAnnotationSecurityMetadataSourceTests { Method method = null; try { - method = BusinessService.class.getMethod("someUserAndAdminMethod", - new Class[] {}); + method = BusinessService.class.getMethod("someUserAndAdminMethod", new Class[] {}); } catch (NoSuchMethodException unexpected) { fail("Should be a method called 'someUserAndAdminMethod' on class!"); } - Collection attrs = this.mds.findAttributes(method, - BusinessService.class); + Collection attrs = this.mds.findAttributes(method, BusinessService.class); // expect 2 attributes assertThat(attrs).hasSize(2); @@ -164,19 +156,16 @@ public class SecuredAnnotationSecurityMetadataSourceTests { public void customAnnotationAttributesAreFound() { SecuredAnnotationSecurityMetadataSource mds = new SecuredAnnotationSecurityMetadataSource( new CustomSecurityAnnotationMetadataExtractor()); - Collection attrs = mds.findAttributes( - CustomAnnotatedService.class); + Collection attrs = mds.findAttributes(CustomAnnotatedService.class); assertThat(attrs).containsOnly(SecurityEnum.ADMIN); } @Test public void annotatedAnnotationAtClassLevelIsDetected() throws Exception { - MockMethodInvocation annotatedAtClassLevel = new MockMethodInvocation( - new AnnotatedAnnotationAtClassLevel(), ReturnVoid.class, "doSomething", - List.class); + MockMethodInvocation annotatedAtClassLevel = new MockMethodInvocation(new AnnotatedAnnotationAtClassLevel(), + ReturnVoid.class, "doSomething", List.class); - ConfigAttribute[] attrs = mds.getAttributes(annotatedAtClassLevel).toArray( - new ConfigAttribute[0]); + ConfigAttribute[] attrs = mds.getAttributes(annotatedAtClassLevel).toArray(new ConfigAttribute[0]); assertThat(attrs).hasSize(1); assertThat(attrs).extracting("attribute").containsOnly("CUSTOM"); @@ -185,11 +174,9 @@ public class SecuredAnnotationSecurityMetadataSourceTests { @Test public void annotatedAnnotationAtInterfaceLevelIsDetected() throws Exception { MockMethodInvocation annotatedAtInterfaceLevel = new MockMethodInvocation( - new AnnotatedAnnotationAtInterfaceLevel(), ReturnVoid2.class, - "doSomething", List.class); + new AnnotatedAnnotationAtInterfaceLevel(), ReturnVoid2.class, "doSomething", List.class); - ConfigAttribute[] attrs = mds.getAttributes(annotatedAtInterfaceLevel).toArray( - new ConfigAttribute[0]); + ConfigAttribute[] attrs = mds.getAttributes(annotatedAtInterfaceLevel).toArray(new ConfigAttribute[0]); assertThat(attrs).hasSize(1); assertThat(attrs).extracting("attribute").containsOnly("CUSTOM"); @@ -197,11 +184,9 @@ public class SecuredAnnotationSecurityMetadataSourceTests { @Test public void annotatedAnnotationAtMethodLevelIsDetected() throws Exception { - MockMethodInvocation annotatedAtMethodLevel = new MockMethodInvocation( - new AnnotatedAnnotationAtMethodLevel(), ReturnVoid.class, "doSomething", - List.class); - ConfigAttribute[] attrs = mds.getAttributes(annotatedAtMethodLevel).toArray( - new ConfigAttribute[0]); + MockMethodInvocation annotatedAtMethodLevel = new MockMethodInvocation(new AnnotatedAnnotationAtMethodLevel(), + ReturnVoid.class, "doSomething", List.class); + ConfigAttribute[] attrs = mds.getAttributes(annotatedAtMethodLevel).toArray(new ConfigAttribute[0]); assertThat(attrs).hasSize(1); assertThat(attrs).extracting("attribute").containsOnly("CUSTOM"); @@ -221,34 +206,39 @@ public class SecuredAnnotationSecurityMetadataSourceTests { Department(String name) { super(name); } + } interface DepartmentService extends BusinessService { @Secured({ "ROLE_USER" }) Department someUserMethod3(Department dept); + } @SuppressWarnings("serial") - class DepartmentServiceImpl extends BusinessServiceImpl - implements DepartmentService { + class DepartmentServiceImpl extends BusinessServiceImpl implements DepartmentService { @Secured({ "ROLE_ADMIN" }) public Department someUserMethod3(final Department dept) { return super.someUserMethod3(dept); } + } // SEC-1491 Related classes. PoC for custom annotation with enum value. @CustomSecurityAnnotation(SecurityEnum.ADMIN) interface CustomAnnotatedService { + } class CustomAnnotatedServiceImpl implements CustomAnnotatedService { + } enum SecurityEnum implements ConfigAttribute, GrantedAuthority { + ADMIN, USER; public String getAttribute() { @@ -258,24 +248,25 @@ public class SecuredAnnotationSecurityMetadataSourceTests { public String getAuthority() { return toString(); } + } @Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @interface CustomSecurityAnnotation { - SecurityEnum[]value(); + SecurityEnum[] value(); + } - class CustomSecurityAnnotationMetadataExtractor - implements AnnotationMetadataExtractor { + class CustomSecurityAnnotationMetadataExtractor implements AnnotationMetadataExtractor { - public Collection extractAttributes( - CustomSecurityAnnotation securityAnnotation) { + public Collection extractAttributes(CustomSecurityAnnotation securityAnnotation) { SecurityEnum[] values = securityAnnotation.value(); return EnumSet.copyOf(Arrays.asList(values)); } + } @Target({ ElementType.METHOD, ElementType.TYPE }) @@ -283,17 +274,20 @@ public class SecuredAnnotationSecurityMetadataSourceTests { @Inherited @Secured("CUSTOM") public @interface AnnotatedAnnotation { + } public interface ReturnVoid { void doSomething(List param); + } @AnnotatedAnnotation public interface ReturnVoid2 { void doSomething(List param); + } @AnnotatedAnnotation @@ -301,12 +295,14 @@ public class SecuredAnnotationSecurityMetadataSourceTests { public void doSomething(List param) { } + } public static class AnnotatedAnnotationAtInterfaceLevel implements ReturnVoid2 { public void doSomething(List param) { } + } public static class AnnotatedAnnotationAtMethodLevel implements ReturnVoid { @@ -314,5 +310,7 @@ public class SecuredAnnotationSecurityMetadataSourceTests { @AnnotatedAnnotation public void doSomething(List param) { } + } + } diff --git a/core/src/test/java/org/springframework/security/access/annotation/sec2150/CrudRepository.java b/core/src/test/java/org/springframework/security/access/annotation/sec2150/CrudRepository.java index 67e38337bf..6dbc29e864 100644 --- a/core/src/test/java/org/springframework/security/access/annotation/sec2150/CrudRepository.java +++ b/core/src/test/java/org/springframework/security/access/annotation/sec2150/CrudRepository.java @@ -18,4 +18,5 @@ package org.springframework.security.access.annotation.sec2150; public interface CrudRepository { Iterable findAll(); + } \ No newline at end of file diff --git a/core/src/test/java/org/springframework/security/access/annotation/sec2150/MethodInvocationFactory.java b/core/src/test/java/org/springframework/security/access/annotation/sec2150/MethodInvocationFactory.java index fdc35340af..bfde1eb1f5 100644 --- a/core/src/test/java/org/springframework/security/access/annotation/sec2150/MethodInvocationFactory.java +++ b/core/src/test/java/org/springframework/security/access/annotation/sec2150/MethodInvocationFactory.java @@ -23,15 +23,14 @@ public class MethodInvocationFactory { /** * In order to reproduce the bug for SEC-2150, we must have a proxy object that * implements TargetSourceAware and implements our annotated interface. - * * @return * @throws NoSuchMethodException */ - public static MockMethodInvocation createSec2150MethodInvocation() - throws NoSuchMethodException { + public static MockMethodInvocation createSec2150MethodInvocation() throws NoSuchMethodException { ProxyFactory factory = new ProxyFactory(new Class[] { PersonRepository.class }); factory.setTargetClass(CrudRepository.class); PersonRepository repository = (PersonRepository) factory.getProxy(); return new MockMethodInvocation(repository, PersonRepository.class, "findAll"); } + } diff --git a/core/src/test/java/org/springframework/security/access/annotation/sec2150/PersonRepository.java b/core/src/test/java/org/springframework/security/access/annotation/sec2150/PersonRepository.java index 59dcae3a1b..221badfa3c 100644 --- a/core/src/test/java/org/springframework/security/access/annotation/sec2150/PersonRepository.java +++ b/core/src/test/java/org/springframework/security/access/annotation/sec2150/PersonRepository.java @@ -28,4 +28,5 @@ import org.springframework.security.access.prepost.PreAuthorize; @Secured("ROLE_PERSON") @PreAuthorize("hasRole('ROLE_PERSON')") public interface PersonRepository extends CrudRepository { + } \ No newline at end of file diff --git a/core/src/test/java/org/springframework/security/access/expression/AbstractSecurityExpressionHandlerTests.java b/core/src/test/java/org/springframework/security/access/expression/AbstractSecurityExpressionHandlerTests.java index 7b371e123c..1ed4adbd51 100644 --- a/core/src/test/java/org/springframework/security/access/expression/AbstractSecurityExpressionHandlerTests.java +++ b/core/src/test/java/org/springframework/security/access/expression/AbstractSecurityExpressionHandlerTests.java @@ -32,14 +32,15 @@ import org.springframework.security.core.Authentication; * @author Luke Taylor */ public class AbstractSecurityExpressionHandlerTests { + private AbstractSecurityExpressionHandler handler; @Before public void setUp() { handler = new AbstractSecurityExpressionHandler() { @Override - protected SecurityExpressionOperations createSecurityExpressionRoot( - Authentication authentication, Object o) { + protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, + Object o) { return new SecurityExpressionRoot(authentication) { }; } @@ -48,13 +49,11 @@ public class AbstractSecurityExpressionHandlerTests { @Test public void beanNamesAreCorrectlyResolved() { - handler.setApplicationContext(new AnnotationConfigApplicationContext( - TestConfiguration.class)); + handler.setApplicationContext(new AnnotationConfigApplicationContext(TestConfiguration.class)); - Expression expression = handler.getExpressionParser().parseExpression( - "@number10.compareTo(@number20) < 0"); - assertThat(expression.getValue(handler.createEvaluationContext( - mock(Authentication.class), new Object()))).isEqualTo(true); + Expression expression = handler.getExpressionParser().parseExpression("@number10.compareTo(@number20) < 0"); + assertThat(expression.getValue(handler.createEvaluationContext(mock(Authentication.class), new Object()))) + .isEqualTo(true); } @Test(expected = IllegalArgumentException.class) @@ -68,6 +67,7 @@ public class AbstractSecurityExpressionHandlerTests { handler.setExpressionParser(parser); assertThat(parser == handler.getExpressionParser()).isTrue(); } + } @Configuration @@ -82,4 +82,5 @@ class TestConfiguration { Integer number20() { return 20; } + } diff --git a/core/src/test/java/org/springframework/security/access/expression/SecurityExpressionRootTests.java b/core/src/test/java/org/springframework/security/access/expression/SecurityExpressionRootTests.java index 3efa1cefc1..43ff2d07a2 100644 --- a/core/src/test/java/org/springframework/security/access/expression/SecurityExpressionRootTests.java +++ b/core/src/test/java/org/springframework/security/access/expression/SecurityExpressionRootTests.java @@ -19,7 +19,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.assertj.core.api.Assertions.*; - import org.junit.Before; import org.junit.Test; import org.springframework.security.authentication.AuthenticationTrustResolver; @@ -28,13 +27,12 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.AuthorityUtils; /** - * * @author Luke Taylor * @since 3.0 */ public class SecurityExpressionRootTests { - final static Authentication JOE = new TestingAuthenticationToken("joe", "pass", - "ROLE_A", "ROLE_B"); + + final static Authentication JOE = new TestingAuthenticationToken("joe", "pass", "ROLE_A", "ROLE_B"); SecurityExpressionRoot root; @@ -135,4 +133,5 @@ public class SecurityExpressionRootTests { assertThat(root.hasAnyAuthority("NO", "A")).isFalse(); assertThat(root.hasAnyAuthority("ROLE_A", "NOT")).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandlerTests.java b/core/src/test/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandlerTests.java index 85dd94acd4..b229ed632a 100644 --- a/core/src/test/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandlerTests.java +++ b/core/src/test/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandlerTests.java @@ -41,12 +41,15 @@ import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) public class DefaultMethodSecurityExpressionHandlerTests { + private DefaultMethodSecurityExpressionHandler handler; @Mock private Authentication authentication; + @Mock private MethodInvocation methodInvocation; + @Mock private AuthenticationTrustResolver trustResolver; @@ -71,10 +74,8 @@ public class DefaultMethodSecurityExpressionHandlerTests { public void createEvaluationContextCustomTrustResolver() { handler.setTrustResolver(trustResolver); - Expression expression = handler.getExpressionParser() - .parseExpression("anonymous"); - EvaluationContext context = handler.createEvaluationContext(authentication, - methodInvocation); + Expression expression = handler.getExpressionParser().parseExpression("anonymous"); + EvaluationContext context = handler.createEvaluationContext(authentication, methodInvocation); expression.getValue(context, Boolean.class); verify(trustResolver).isAnonymous(authentication); @@ -90,8 +91,7 @@ public class DefaultMethodSecurityExpressionHandlerTests { Expression expression = handler.getExpressionParser().parseExpression("filterObject.key eq 'key2'"); - EvaluationContext context = handler.createEvaluationContext(authentication, - methodInvocation); + EvaluationContext context = handler.createEvaluationContext(authentication, methodInvocation); Object filtered = handler.filter(map, expression, context); @@ -112,8 +112,7 @@ public class DefaultMethodSecurityExpressionHandlerTests { Expression expression = handler.getExpressionParser().parseExpression("filterObject.value eq 'value3'"); - EvaluationContext context = handler.createEvaluationContext(authentication, - methodInvocation); + EvaluationContext context = handler.createEvaluationContext(authentication, methodInvocation); Object filtered = handler.filter(map, expression, context); @@ -132,10 +131,10 @@ public class DefaultMethodSecurityExpressionHandlerTests { map.put("key2", "value2"); map.put("key3", "value3"); - Expression expression = handler.getExpressionParser().parseExpression("(filterObject.key eq 'key1') or (filterObject.value eq 'value2')"); + Expression expression = handler.getExpressionParser() + .parseExpression("(filterObject.key eq 'key1') or (filterObject.value eq 'value2')"); - EvaluationContext context = handler.createEvaluationContext(authentication, - methodInvocation); + EvaluationContext context = handler.createEvaluationContext(authentication, methodInvocation); Object filtered = handler.filter(map, expression, context); @@ -153,8 +152,7 @@ public class DefaultMethodSecurityExpressionHandlerTests { Expression expression = handler.getExpressionParser().parseExpression("filterObject ne '2'"); - EvaluationContext context = handler.createEvaluationContext(authentication, - methodInvocation); + EvaluationContext context = handler.createEvaluationContext(authentication, methodInvocation); Object filtered = handler.filter(stream, expression, context); @@ -170,15 +168,17 @@ public class DefaultMethodSecurityExpressionHandlerTests { Expression expression = handler.getExpressionParser().parseExpression("true"); - EvaluationContext context = handler.createEvaluationContext(authentication, - methodInvocation); + EvaluationContext context = handler.createEvaluationContext(authentication, methodInvocation); ((Stream) handler.filter(upstream, expression, context)).close(); verify(upstream).close(); } private static class Foo { - public void bar(){ + + public void bar() { } + } + } diff --git a/core/src/test/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdviceTests.java b/core/src/test/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdviceTests.java index 27095641d8..aaa78cad96 100644 --- a/core/src/test/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdviceTests.java +++ b/core/src/test/java/org/springframework/security/access/expression/method/ExpressionBasedPreInvocationAdviceTests.java @@ -50,94 +50,78 @@ public class ExpressionBasedPreInvocationAdviceTests { @Test(expected = IllegalArgumentException.class) public void findFilterTargetNameProvidedButNotMatch() throws Exception { - //given - PreInvocationAttribute attribute = new PreInvocationExpressionAttribute("true", - "filterTargetDoesNotMatch", - null); + // given + PreInvocationAttribute attribute = new PreInvocationExpressionAttribute("true", "filterTargetDoesNotMatch", + null); MockMethodInvocation methodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingCollection", - new Class[]{List.class}, - new Object[]{new ArrayList<>()}); - //when - then + "doSomethingCollection", new Class[] { List.class }, new Object[] { new ArrayList<>() }); + // when - then expressionBasedPreInvocationAdvice.before(authentication, methodInvocation, attribute); } @Test(expected = IllegalArgumentException.class) public void findFilterTargetNameProvidedArrayUnsupported() throws Exception { - //given - PreInvocationAttribute attribute = new PreInvocationExpressionAttribute("true", - "param", null); + // given + PreInvocationAttribute attribute = new PreInvocationExpressionAttribute("true", "param", null); MockMethodInvocation methodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingArray", - new Class[]{String[].class}, - new Object[]{new String[0]}); - //when - then + "doSomethingArray", new Class[] { String[].class }, new Object[] { new String[0] }); + // when - then expressionBasedPreInvocationAdvice.before(authentication, methodInvocation, attribute); } @Test public void findFilterTargetNameProvided() throws Exception { - //given + // given PreInvocationAttribute attribute = new PreInvocationExpressionAttribute("true", "param", null); MockMethodInvocation methodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingCollection", - new Class[]{List.class}, - new Object[]{new ArrayList<>()}); + "doSomethingCollection", new Class[] { List.class }, new Object[] { new ArrayList<>() }); - //when - boolean result = expressionBasedPreInvocationAdvice - .before(authentication, methodInvocation, attribute); - //then + // when + boolean result = expressionBasedPreInvocationAdvice.before(authentication, methodInvocation, attribute); + // then assertThat(result).isTrue(); } @Test(expected = IllegalArgumentException.class) public void findFilterTargetNameNotProvidedArrayUnsupported() throws Exception { - //given + // given PreInvocationAttribute attribute = new PreInvocationExpressionAttribute("true", "", null); MockMethodInvocation methodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingArray", - new Class[]{String[].class}, - new Object[]{new String[0]}); - //when - then + "doSomethingArray", new Class[] { String[].class }, new Object[] { new String[0] }); + // when - then expressionBasedPreInvocationAdvice.before(authentication, methodInvocation, attribute); } @Test public void findFilterTargetNameNotProvided() throws Exception { - //given + // given PreInvocationAttribute attribute = new PreInvocationExpressionAttribute("true", "", null); MockMethodInvocation methodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingCollection", - new Class[]{List.class}, - new Object[]{new ArrayList<>()}); - //when + "doSomethingCollection", new Class[] { List.class }, new Object[] { new ArrayList<>() }); + // when boolean result = expressionBasedPreInvocationAdvice.before(authentication, methodInvocation, attribute); - //then + // then assertThat(result).isTrue(); } @Test(expected = IllegalArgumentException.class) public void findFilterTargetNameNotProvidedTypeNotSupported() throws Exception { - //given + // given PreInvocationAttribute attribute = new PreInvocationExpressionAttribute("true", "", null); MockMethodInvocation methodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingString", - new Class[]{String.class}, - new Object[]{"param"}); - //when - then + "doSomethingString", new Class[] { String.class }, new Object[] { "param" }); + // when - then expressionBasedPreInvocationAdvice.before(authentication, methodInvocation, attribute); } @Test(expected = IllegalArgumentException.class) public void findFilterTargetNameNotProvidedMethodAcceptMoreThenOneArgument() throws Exception { - //given + // given PreInvocationAttribute attribute = new PreInvocationExpressionAttribute("true", "", null); MockMethodInvocation methodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, - "doSomethingTwoArgs", - new Class[]{String.class, List.class}, - new Object[]{"param", new ArrayList<>()}); - //when - then + "doSomethingTwoArgs", new Class[] { String.class, List.class }, + new Object[] { "param", new ArrayList<>() }); + // when - then expressionBasedPreInvocationAdvice.before(authentication, methodInvocation, attribute); } @@ -158,5 +142,7 @@ public class ExpressionBasedPreInvocationAdviceTests { public Boolean doSomethingTwoArgs(String param, List list) { return Boolean.TRUE; } + } + } diff --git a/core/src/test/java/org/springframework/security/access/expression/method/MethodExpressionVoterTests.java b/core/src/test/java/org/springframework/security/access/expression/method/MethodExpressionVoterTests.java index 0a738f2ec2..ec66b1ae3b 100644 --- a/core/src/test/java/org/springframework/security/access/expression/method/MethodExpressionVoterTests.java +++ b/core/src/test/java/org/springframework/security/access/expression/method/MethodExpressionVoterTests.java @@ -34,48 +34,44 @@ import org.springframework.security.util.SimpleMethodInvocation; @SuppressWarnings("unchecked") public class MethodExpressionVoterTests { - private TestingAuthenticationToken joe = new TestingAuthenticationToken("joe", - "joespass", "ROLE_blah"); + + private TestingAuthenticationToken joe = new TestingAuthenticationToken("joe", "joespass", "ROLE_blah"); + private PreInvocationAuthorizationAdviceVoter am = new PreInvocationAuthorizationAdviceVoter( new ExpressionBasedPreInvocationAdvice()); @Test public void hasRoleExpressionAllowsUserWithRole() throws Exception { - MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), - methodTakingAnArray()); - assertThat(am.vote(joe, mi, - createAttributes(new PreInvocationExpressionAttribute(null, null, - "hasRole('blah')")))).isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); + MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), methodTakingAnArray()); + assertThat( + am.vote(joe, mi, createAttributes(new PreInvocationExpressionAttribute(null, null, "hasRole('blah')")))) + .isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); } @Test public void hasRoleExpressionDeniesUserWithoutRole() throws Exception { List cad = new ArrayList<>(1); cad.add(new PreInvocationExpressionAttribute(null, null, "hasRole('joedoesnt')")); - MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), - methodTakingAnArray()); + MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), methodTakingAnArray()); assertThat(am.vote(joe, mi, cad)).isEqualTo(AccessDecisionVoter.ACCESS_DENIED); } @Test public void matchingArgAgainstAuthenticationNameIsSuccessful() throws Exception { - MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), - methodTakingAString(), "joe"); + MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), methodTakingAString(), "joe"); assertThat(am.vote(joe, mi, createAttributes(new PreInvocationExpressionAttribute(null, null, "(#argument == principal) and (principal == 'joe')")))) - .isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); + .isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); } @Test public void accessIsGrantedIfNoPreAuthorizeAttributeIsUsed() throws Exception { Collection arg = createCollectionArg("joe", "bob", "sam"); - MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), - methodTakingACollection(), arg); + MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), methodTakingACollection(), arg); assertThat(am.vote(joe, mi, - createAttributes(new PreInvocationExpressionAttribute( - "(filterObject == 'jim')", "collection", null)))) - .isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); + createAttributes(new PreInvocationExpressionAttribute("(filterObject == 'jim')", "collection", null)))) + .isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); // All objects should have been removed, because the expression is always false assertThat(arg).isEmpty(); } @@ -83,46 +79,42 @@ public class MethodExpressionVoterTests { @Test public void collectionPreFilteringIsSuccessful() throws Exception { List arg = createCollectionArg("joe", "bob", "sam"); - MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), - methodTakingACollection(), arg); + MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), methodTakingACollection(), arg); am.vote(joe, mi, createAttributes(new PreInvocationExpressionAttribute( - "(filterObject == 'joe' or filterObject == 'sam')", "collection", - "permitAll"))); + "(filterObject == 'joe' or filterObject == 'sam')", "collection", "permitAll"))); assertThat(arg).containsExactly("joe", "sam"); } @Test(expected = IllegalArgumentException.class) public void arraysCannotBePrefiltered() throws Exception { - MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), - methodTakingAnArray(), createArrayArg("sam", "joe")); - am.vote(joe, mi, createAttributes(new PreInvocationExpressionAttribute( - "(filterObject == 'jim')", "someArray", null))); + MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), methodTakingAnArray(), + createArrayArg("sam", "joe")); + am.vote(joe, mi, + createAttributes(new PreInvocationExpressionAttribute("(filterObject == 'jim')", "someArray", null))); } @Test(expected = IllegalArgumentException.class) public void incorrectFilterTargetNameIsRejected() throws Exception { - MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), - methodTakingACollection(), createCollectionArg("joe", "bob")); - am.vote(joe, mi, createAttributes(new PreInvocationExpressionAttribute( - "(filterObject == 'joe')", "collcetion", null))); + MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), methodTakingACollection(), + createCollectionArg("joe", "bob")); + am.vote(joe, mi, + createAttributes(new PreInvocationExpressionAttribute("(filterObject == 'joe')", "collcetion", null))); } @Test(expected = IllegalArgumentException.class) public void nullNamedFilterTargetIsRejected() throws Exception { - MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), - methodTakingACollection(), new Object[] { null }); - am.vote(joe, mi, createAttributes(new PreInvocationExpressionAttribute( - "(filterObject == 'joe')", "collection", null))); + MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), methodTakingACollection(), + new Object[] { null }); + am.vote(joe, mi, + createAttributes(new PreInvocationExpressionAttribute("(filterObject == 'joe')", "collection", null))); } @Test public void ruleDefinedInAClassMethodIsApplied() throws Exception { - MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), - methodTakingAString(), "joe"); + MethodInvocation mi = new SimpleMethodInvocation(new TargetImpl(), methodTakingAString(), "joe"); assertThat( - am.vote(joe, mi, - createAttributes(new PreInvocationExpressionAttribute(null, null, + am.vote(joe, mi, createAttributes(new PreInvocationExpressionAttribute(null, null, "T(org.springframework.security.access.expression.method.SecurityRules).isJoe(#argument)")))) .isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); } @@ -159,14 +151,17 @@ public class MethodExpressionVoterTests { // ================================================================================================== private interface Target { + void methodTakingAnArray(Object[] args); void methodTakingAString(String argument); Collection methodTakingACollection(Collection collection); + } private static class TargetImpl implements Target { + public void methodTakingAnArray(Object[] args) { } @@ -176,5 +171,7 @@ public class MethodExpressionVoterTests { public Collection methodTakingACollection(Collection collection) { return collection; } + } + } diff --git a/core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContextTests.java b/core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContextTests.java index 18d7e9f787..5d83a6b8e8 100644 --- a/core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContextTests.java +++ b/core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityEvaluationContextTests.java @@ -36,10 +36,13 @@ import static org.mockito.Mockito.doReturn; */ @RunWith(MockitoJUnitRunner.class) public class MethodSecurityEvaluationContextTests { + @Mock private ParameterNameDiscoverer paramNameDiscoverer; + @Mock private Authentication authentication; + @Mock private MethodInvocation methodInvocation; @@ -47,16 +50,16 @@ public class MethodSecurityEvaluationContextTests { public void lookupVariableWhenParameterNameNullThenNotSet() { Class type = String.class; Method method = ReflectionUtils.findMethod(String.class, "contains", CharSequence.class); - doReturn(new String[] {null}).when(paramNameDiscoverer).getParameterNames(method); - doReturn(new Object[]{null}).when(methodInvocation).getArguments(); + doReturn(new String[] { null }).when(paramNameDiscoverer).getParameterNames(method); + doReturn(new Object[] { null }).when(methodInvocation).getArguments(); doReturn(type).when(methodInvocation).getThis(); doReturn(method).when(methodInvocation).getMethod(); - NotNullVariableMethodSecurityEvaluationContext context= new NotNullVariableMethodSecurityEvaluationContext(authentication, methodInvocation, paramNameDiscoverer); + NotNullVariableMethodSecurityEvaluationContext context = new NotNullVariableMethodSecurityEvaluationContext( + authentication, methodInvocation, paramNameDiscoverer); context.lookupVariable("testVariable"); } - private static class NotNullVariableMethodSecurityEvaluationContext - extends MethodSecurityEvaluationContext { + private static class NotNullVariableMethodSecurityEvaluationContext extends MethodSecurityEvaluationContext { NotNullVariableMethodSecurityEvaluationContext(Authentication auth, MethodInvocation mi, ParameterNameDiscoverer parameterNameDiscoverer) { @@ -65,12 +68,14 @@ public class MethodSecurityEvaluationContextTests { @Override public void setVariable(String name, @Nullable Object value) { - if ( name == null ) { + if (name == null) { throw new IllegalArgumentException("name should not be null"); } else { super.setVariable(name, value); } } + } + } diff --git a/core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java b/core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java index 2899956888..4ce1fdd0d6 100644 --- a/core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java +++ b/core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java @@ -34,10 +34,15 @@ import org.springframework.security.core.Authentication; * @author Luke Taylor */ public class MethodSecurityExpressionRootTests { + SpelExpressionParser parser = new SpelExpressionParser(); + MethodSecurityExpressionRoot root; + StandardEvaluationContext ctx; + private AuthenticationTrustResolver trustResolver; + private Authentication user; @Before @@ -99,8 +104,8 @@ public class MethodSecurityExpressionRootTests { ctx.setVariable("domainObject", dummyDomainObject); final PermissionEvaluator pe = mock(PermissionEvaluator.class); root.setPermissionEvaluator(pe); - when(pe.hasPermission(eq(user), eq(dummyDomainObject), any(Integer.class))) - .thenReturn(true).thenReturn(true).thenReturn(false); + when(pe.hasPermission(eq(user), eq(dummyDomainObject), any(Integer.class))).thenReturn(true).thenReturn(true) + .thenReturn(false); Expression e = parser.parseExpression("hasPermission(#domainObject, 0xA)"); // evaluator returns true @@ -135,4 +140,5 @@ public class MethodSecurityExpressionRootTests { e = parser.parseExpression("hasPermission(this.x, 2)"); assertThat(ExpressionUtils.evaluateAsBoolean(e, ctx)).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/access/expression/method/PrePostAnnotationSecurityMetadataSourceTests.java b/core/src/test/java/org/springframework/security/access/expression/method/PrePostAnnotationSecurityMetadataSourceTests.java index 5c0cc78c49..ef0c9abbc2 100644 --- a/core/src/test/java/org/springframework/security/access/expression/method/PrePostAnnotationSecurityMetadataSourceTests.java +++ b/core/src/test/java/org/springframework/security/access/expression/method/PrePostAnnotationSecurityMetadataSourceTests.java @@ -39,54 +39,53 @@ import org.springframework.security.access.prepost.PrePostAnnotationSecurityMeta import org.springframework.test.util.ReflectionTestUtils; /** - * * @author Luke Taylor * @since 3.0 */ public class PrePostAnnotationSecurityMetadataSourceTests { + private PrePostAnnotationSecurityMetadataSource mds = new PrePostAnnotationSecurityMetadataSource( - new ExpressionBasedAnnotationAttributeFactory( - new DefaultMethodSecurityExpressionHandler())); + new ExpressionBasedAnnotationAttributeFactory(new DefaultMethodSecurityExpressionHandler())); private MockMethodInvocation voidImpl1; + private MockMethodInvocation voidImpl2; + private MockMethodInvocation voidImpl3; + private MockMethodInvocation listImpl1; + private MockMethodInvocation notherListImpl1; + private MockMethodInvocation notherListImpl2; + private MockMethodInvocation annotatedAtClassLevel; + private MockMethodInvocation annotatedAtInterfaceLevel; + private MockMethodInvocation annotatedAtMethodLevel; @Before public void setUpData() throws Exception { - voidImpl1 = new MockMethodInvocation(new ReturnVoidImpl1(), ReturnVoid.class, - "doSomething", List.class); - voidImpl2 = new MockMethodInvocation(new ReturnVoidImpl2(), ReturnVoid.class, - "doSomething", List.class); - voidImpl3 = new MockMethodInvocation(new ReturnVoidImpl3(), ReturnVoid.class, - "doSomething", List.class); - listImpl1 = new MockMethodInvocation(new ReturnAListImpl1(), ReturnAList.class, - "doSomething", List.class); - notherListImpl1 = new MockMethodInvocation(new ReturnAnotherListImpl1(), - ReturnAnotherList.class, "doSomething", List.class); - notherListImpl2 = new MockMethodInvocation(new ReturnAnotherListImpl2(), - ReturnAnotherList.class, "doSomething", List.class); - annotatedAtClassLevel = new MockMethodInvocation( - new CustomAnnotationAtClassLevel(), ReturnVoid.class, "doSomething", + voidImpl1 = new MockMethodInvocation(new ReturnVoidImpl1(), ReturnVoid.class, "doSomething", List.class); + voidImpl2 = new MockMethodInvocation(new ReturnVoidImpl2(), ReturnVoid.class, "doSomething", List.class); + voidImpl3 = new MockMethodInvocation(new ReturnVoidImpl3(), ReturnVoid.class, "doSomething", List.class); + listImpl1 = new MockMethodInvocation(new ReturnAListImpl1(), ReturnAList.class, "doSomething", List.class); + notherListImpl1 = new MockMethodInvocation(new ReturnAnotherListImpl1(), ReturnAnotherList.class, "doSomething", List.class); - annotatedAtInterfaceLevel = new MockMethodInvocation( - new CustomAnnotationAtInterfaceLevel(), ReturnVoid2.class, "doSomething", - List.class); - annotatedAtMethodLevel = new MockMethodInvocation( - new CustomAnnotationAtMethodLevel(), ReturnVoid.class, "doSomething", + notherListImpl2 = new MockMethodInvocation(new ReturnAnotherListImpl2(), ReturnAnotherList.class, "doSomething", List.class); + annotatedAtClassLevel = new MockMethodInvocation(new CustomAnnotationAtClassLevel(), ReturnVoid.class, + "doSomething", List.class); + annotatedAtInterfaceLevel = new MockMethodInvocation(new CustomAnnotationAtInterfaceLevel(), ReturnVoid2.class, + "doSomething", List.class); + annotatedAtMethodLevel = new MockMethodInvocation(new CustomAnnotationAtMethodLevel(), ReturnVoid.class, + "doSomething", List.class); } @Test public void classLevelPreAnnotationIsPickedUpWhenNoMethodLevelExists() { - ConfigAttribute[] attrs = mds.getAttributes(voidImpl1).toArray( - new ConfigAttribute[0]); + ConfigAttribute[] attrs = mds.getAttributes(voidImpl1).toArray(new ConfigAttribute[0]); assertThat(attrs).hasSize(1); assertThat(attrs[0] instanceof PreInvocationExpressionAttribute).isTrue(); @@ -98,8 +97,7 @@ public class PrePostAnnotationSecurityMetadataSourceTests { @Test public void mixedClassAndMethodPreAnnotationsAreBothIncluded() { - ConfigAttribute[] attrs = mds.getAttributes(voidImpl2).toArray( - new ConfigAttribute[0]); + ConfigAttribute[] attrs = mds.getAttributes(voidImpl2).toArray(new ConfigAttribute[0]); assertThat(attrs).hasSize(1); assertThat(attrs[0] instanceof PreInvocationExpressionAttribute).isTrue(); @@ -111,8 +109,7 @@ public class PrePostAnnotationSecurityMetadataSourceTests { @Test public void methodWithPreFilterOnlyIsAllowed() { - ConfigAttribute[] attrs = mds.getAttributes(voidImpl3).toArray( - new ConfigAttribute[0]); + ConfigAttribute[] attrs = mds.getAttributes(voidImpl3).toArray(new ConfigAttribute[0]); assertThat(attrs).hasSize(1); assertThat(attrs[0] instanceof PreInvocationExpressionAttribute).isTrue(); @@ -124,8 +121,7 @@ public class PrePostAnnotationSecurityMetadataSourceTests { @Test public void methodWithPostFilterOnlyIsAllowed() { - ConfigAttribute[] attrs = mds.getAttributes(listImpl1).toArray( - new ConfigAttribute[0]); + ConfigAttribute[] attrs = mds.getAttributes(listImpl1).toArray(new ConfigAttribute[0]); assertThat(attrs).hasSize(2); assertThat(attrs[0] instanceof PreInvocationExpressionAttribute).isTrue(); @@ -139,8 +135,7 @@ public class PrePostAnnotationSecurityMetadataSourceTests { @Test public void interfaceAttributesAreIncluded() { - ConfigAttribute[] attrs = mds.getAttributes(notherListImpl1).toArray( - new ConfigAttribute[0]); + ConfigAttribute[] attrs = mds.getAttributes(notherListImpl1).toArray(new ConfigAttribute[0]); assertThat(attrs).hasSize(1); assertThat(attrs[0] instanceof PreInvocationExpressionAttribute).isTrue(); @@ -153,8 +148,7 @@ public class PrePostAnnotationSecurityMetadataSourceTests { @Test public void classAttributesTakesPrecedeceOverInterfaceAttributes() { - ConfigAttribute[] attrs = mds.getAttributes(notherListImpl2).toArray( - new ConfigAttribute[0]); + ConfigAttribute[] attrs = mds.getAttributes(notherListImpl2).toArray(new ConfigAttribute[0]); assertThat(attrs).hasSize(1); assertThat(attrs[0] instanceof PreInvocationExpressionAttribute).isTrue(); @@ -167,24 +161,21 @@ public class PrePostAnnotationSecurityMetadataSourceTests { @Test public void customAnnotationAtClassLevelIsDetected() { - ConfigAttribute[] attrs = mds.getAttributes(annotatedAtClassLevel).toArray( - new ConfigAttribute[0]); + ConfigAttribute[] attrs = mds.getAttributes(annotatedAtClassLevel).toArray(new ConfigAttribute[0]); assertThat(attrs).hasSize(1); } @Test public void customAnnotationAtInterfaceLevelIsDetected() { - ConfigAttribute[] attrs = mds.getAttributes(annotatedAtInterfaceLevel).toArray( - new ConfigAttribute[0]); + ConfigAttribute[] attrs = mds.getAttributes(annotatedAtInterfaceLevel).toArray(new ConfigAttribute[0]); assertThat(attrs).hasSize(1); } @Test public void customAnnotationAtMethodLevelIsDetected() { - ConfigAttribute[] attrs = mds.getAttributes(annotatedAtMethodLevel).toArray( - new ConfigAttribute[0]); + ConfigAttribute[] attrs = mds.getAttributes(annotatedAtMethodLevel).toArray(new ConfigAttribute[0]); assertThat(attrs).hasSize(1); } @@ -194,8 +185,8 @@ public class PrePostAnnotationSecurityMetadataSourceTests { MockMethodInvocation mi = MethodInvocationFactory.createSec2150MethodInvocation(); Collection attributes = mds.getAttributes(mi); assertThat(attributes).hasSize(1); - Expression expression = (Expression) ReflectionTestUtils.getField(attributes - .iterator().next(), "authorizeExpression"); + Expression expression = (Expression) ReflectionTestUtils.getField(attributes.iterator().next(), + "authorizeExpression"); assertThat(expression.getExpressionString()).isEqualTo("hasRole('ROLE_PERSON')"); } @@ -203,47 +194,62 @@ public class PrePostAnnotationSecurityMetadataSourceTests { // ================================================================================================== public interface ReturnVoid { + void doSomething(List param); + } public interface ReturnAList { + List doSomething(List param); + } @PreAuthorize("interfaceAuthzExpression") public interface ReturnAnotherList { + @PreAuthorize("interfaceMethodAuthzExpression") @PreFilter(filterTarget = "param", value = "interfacePreFilterExpression") List doSomething(List param); + } @PreAuthorize("someExpression") public static class ReturnVoidImpl1 implements ReturnVoid { + public void doSomething(List param) { } + } @PreAuthorize("someExpression") public static class ReturnVoidImpl2 implements ReturnVoid { + @PreFilter(filterTarget = "param", value = "somePreFilterExpression") public void doSomething(List param) { } + } public static class ReturnVoidImpl3 implements ReturnVoid { + @PreFilter(filterTarget = "param", value = "somePreFilterExpression") public void doSomething(List param) { } + } public static class ReturnAListImpl1 implements ReturnAList { + @PostFilter("somePostFilterExpression") public List doSomething(List param) { return param; } + } public static class ReturnAListImpl2 implements ReturnAList { + @PreAuthorize("someExpression") @PreFilter(filterTarget = "param", value = "somePreFilterExpression") @PostFilter("somePostFilterExpression") @@ -251,19 +257,24 @@ public class PrePostAnnotationSecurityMetadataSourceTests { public List doSomething(List param) { return param; } + } public static class ReturnAnotherListImpl1 implements ReturnAnotherList { + public List doSomething(List param) { return param; } + } public static class ReturnAnotherListImpl2 implements ReturnAnotherList { + @PreFilter(filterTarget = "param", value = "classMethodPreFilterExpression") public List doSomething(List param) { return param; } + } @Target({ ElementType.METHOD, ElementType.TYPE }) @@ -271,27 +282,37 @@ public class PrePostAnnotationSecurityMetadataSourceTests { @Inherited @PreAuthorize("customAnnotationExpression") public @interface CustomAnnotation { + } @CustomAnnotation public interface ReturnVoid2 { + void doSomething(List param); + } @CustomAnnotation public static class CustomAnnotationAtClassLevel implements ReturnVoid { + public void doSomething(List param) { } + } public static class CustomAnnotationAtInterfaceLevel implements ReturnVoid2 { + public void doSomething(List param) { } + } public static class CustomAnnotationAtMethodLevel implements ReturnVoid { + @CustomAnnotation public void doSomething(List param) { } + } + } diff --git a/core/src/test/java/org/springframework/security/access/expression/method/SecurityRules.java b/core/src/test/java/org/springframework/security/access/expression/method/SecurityRules.java index 2abe9a1118..6943f5ef51 100644 --- a/core/src/test/java/org/springframework/security/access/expression/method/SecurityRules.java +++ b/core/src/test/java/org/springframework/security/access/expression/method/SecurityRules.java @@ -16,6 +16,7 @@ package org.springframework.security.access.expression.method; public class SecurityRules { + public static boolean disallow() { return false; } @@ -27,4 +28,5 @@ public class SecurityRules { public static boolean isJoe(String s) { return "joe".equals(s); } + } diff --git a/core/src/test/java/org/springframework/security/access/hierarchicalroles/HierarchicalRolesTestHelper.java b/core/src/test/java/org/springframework/security/access/hierarchicalroles/HierarchicalRolesTestHelper.java index 901abbdf9d..4a8ba79b6c 100755 --- a/core/src/test/java/org/springframework/security/access/hierarchicalroles/HierarchicalRolesTestHelper.java +++ b/core/src/test/java/org/springframework/security/access/hierarchicalroles/HierarchicalRolesTestHelper.java @@ -29,8 +29,7 @@ import org.apache.commons.collections.CollectionUtils; */ public abstract class HierarchicalRolesTestHelper { - public static boolean containTheSameGrantedAuthorities( - Collection authorities1, + public static boolean containTheSameGrantedAuthorities(Collection authorities1, Collection authorities2) { if (authorities1 == null && authorities2 == null) { return true; @@ -43,8 +42,7 @@ public abstract class HierarchicalRolesTestHelper { } public static boolean containTheSameGrantedAuthoritiesCompareByAuthorityString( - Collection authorities1, - Collection authorities2) { + Collection authorities1, Collection authorities2) { if (authorities1 == null && authorities2 == null) { return true; } @@ -52,13 +50,11 @@ public abstract class HierarchicalRolesTestHelper { if (authorities1 == null || authorities2 == null) { return false; } - return CollectionUtils.isEqualCollection( - toCollectionOfAuthorityStrings(authorities1), + return CollectionUtils.isEqualCollection(toCollectionOfAuthorityStrings(authorities1), toCollectionOfAuthorityStrings(authorities2)); } - public static List toCollectionOfAuthorityStrings( - Collection authorities) { + public static List toCollectionOfAuthorityStrings(Collection authorities) { if (authorities == null) { return null; } diff --git a/core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyAuthoritiesMapperTests.java b/core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyAuthoritiesMapperTests.java index 94f6ec2106..f4a7e39dbf 100644 --- a/core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyAuthoritiesMapperTests.java +++ b/core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyAuthoritiesMapperTests.java @@ -41,9 +41,9 @@ public class RoleHierarchyAuthoritiesMapperTests { mapper = new RoleHierarchyAuthoritiesMapper(new NullRoleHierarchy()); - authorities = mapper.mapAuthorities(AuthorityUtils.createAuthorityList("ROLE_A", - "ROLE_D")); + authorities = mapper.mapAuthorities(AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_D")); assertThat(authorities).hasSize(2); } + } diff --git a/core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImplTests.java b/core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImplTests.java index d25983b3ad..39a701d636 100644 --- a/core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImplTests.java +++ b/core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImplTests.java @@ -40,99 +40,72 @@ public class RoleHierarchyImplTests { RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl(); roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B"); - assertThat(roleHierarchyImpl.getReachableGrantedAuthorities( - authorities0)).isNotNull(); - assertThat( - roleHierarchyImpl.getReachableGrantedAuthorities(authorities0)).isEmpty(); + assertThat(roleHierarchyImpl.getReachableGrantedAuthorities(authorities0)).isNotNull(); + assertThat(roleHierarchyImpl.getReachableGrantedAuthorities(authorities0)).isEmpty(); - assertThat(roleHierarchyImpl.getReachableGrantedAuthorities( - authorities1)).isNotNull(); - assertThat( - roleHierarchyImpl.getReachableGrantedAuthorities(authorities1)).isEmpty(); + assertThat(roleHierarchyImpl.getReachableGrantedAuthorities(authorities1)).isNotNull(); + assertThat(roleHierarchyImpl.getReachableGrantedAuthorities(authorities1)).isEmpty(); } @Test public void testSimpleRoleHierarchy() { - List authorities0 = AuthorityUtils.createAuthorityList( - "ROLE_0"); - List authorities1 = AuthorityUtils.createAuthorityList( - "ROLE_A"); - List authorities2 = AuthorityUtils.createAuthorityList("ROLE_A", - "ROLE_B"); + List authorities0 = AuthorityUtils.createAuthorityList("ROLE_0"); + List authorities1 = AuthorityUtils.createAuthorityList("ROLE_A"); + List authorities2 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B"); RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl(); roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B"); assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - roleHierarchyImpl.getReachableGrantedAuthorities(authorities0), - authorities0)).isTrue(); + roleHierarchyImpl.getReachableGrantedAuthorities(authorities0), authorities0)).isTrue(); assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), - authorities2)).isTrue(); + roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), authorities2)).isTrue(); assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - roleHierarchyImpl.getReachableGrantedAuthorities(authorities2), - authorities2)).isTrue(); + roleHierarchyImpl.getReachableGrantedAuthorities(authorities2), authorities2)).isTrue(); } @Test public void testTransitiveRoleHierarchies() { - List authorities1 = AuthorityUtils.createAuthorityList( - "ROLE_A"); - List authorities2 = AuthorityUtils.createAuthorityList("ROLE_A", - "ROLE_B", "ROLE_C"); - List authorities3 = AuthorityUtils.createAuthorityList("ROLE_A", - "ROLE_B", "ROLE_C", "ROLE_D"); + List authorities1 = AuthorityUtils.createAuthorityList("ROLE_A"); + List authorities2 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B", "ROLE_C"); + List authorities3 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B", "ROLE_C", + "ROLE_D"); RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl(); roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_B > ROLE_C"); assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), - authorities2)).isTrue(); + roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), authorities2)).isTrue(); - roleHierarchyImpl.setHierarchy( - "ROLE_A > ROLE_B\nROLE_B > ROLE_C\nROLE_C > ROLE_D"); + roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_B > ROLE_C\nROLE_C > ROLE_D"); assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), - authorities3)).isTrue(); + roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), authorities3)).isTrue(); } @Test public void testComplexRoleHierarchy() { - List authoritiesInput1 = AuthorityUtils.createAuthorityList( - "ROLE_A"); - List authoritiesOutput1 = AuthorityUtils.createAuthorityList( - "ROLE_A", "ROLE_B", "ROLE_C", "ROLE_D"); - List authoritiesInput2 = AuthorityUtils.createAuthorityList( - "ROLE_B"); - List authoritiesOutput2 = AuthorityUtils.createAuthorityList( - "ROLE_B", "ROLE_D"); - List authoritiesInput3 = AuthorityUtils.createAuthorityList( - "ROLE_C"); - List authoritiesOutput3 = AuthorityUtils.createAuthorityList( - "ROLE_C", "ROLE_D"); - List authoritiesInput4 = AuthorityUtils.createAuthorityList( - "ROLE_D"); - List authoritiesOutput4 = AuthorityUtils.createAuthorityList( + List authoritiesInput1 = AuthorityUtils.createAuthorityList("ROLE_A"); + List authoritiesOutput1 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B", "ROLE_C", "ROLE_D"); + List authoritiesInput2 = AuthorityUtils.createAuthorityList("ROLE_B"); + List authoritiesOutput2 = AuthorityUtils.createAuthorityList("ROLE_B", "ROLE_D"); + List authoritiesInput3 = AuthorityUtils.createAuthorityList("ROLE_C"); + List authoritiesOutput3 = AuthorityUtils.createAuthorityList("ROLE_C", "ROLE_D"); + List authoritiesInput4 = AuthorityUtils.createAuthorityList("ROLE_D"); + List authoritiesOutput4 = AuthorityUtils.createAuthorityList("ROLE_D"); RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl(); - roleHierarchyImpl.setHierarchy( - "ROLE_A > ROLE_B\nROLE_A > ROLE_C\nROLE_C > ROLE_D\nROLE_B > ROLE_D"); + roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_A > ROLE_C\nROLE_C > ROLE_D\nROLE_B > ROLE_D"); assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput1), - authoritiesOutput1)).isTrue(); + roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput1), authoritiesOutput1)).isTrue(); assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput2), - authoritiesOutput2)).isTrue(); + roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput2), authoritiesOutput2)).isTrue(); assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput3), - authoritiesOutput3)).isTrue(); + roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput3), authoritiesOutput3)).isTrue(); assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput4), - authoritiesOutput4)).isTrue(); + roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput4), authoritiesOutput4)).isTrue(); } @Test @@ -154,8 +127,7 @@ public class RoleHierarchyImplTests { } try { - roleHierarchyImpl.setHierarchy( - "ROLE_A > ROLE_B\nROLE_B > ROLE_C\nROLE_C > ROLE_A"); + roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_B > ROLE_C\nROLE_C > ROLE_A"); fail("Cycle in role hierarchy was not detected!"); } catch (CycleInRoleHierarchyException e) { @@ -172,7 +144,8 @@ public class RoleHierarchyImplTests { try { roleHierarchyImpl.setHierarchy("ROLE_C > ROLE_B\nROLE_B > ROLE_A\nROLE_A > ROLE_B"); fail("Cycle in role hierarchy was not detected!"); - } catch (CycleInRoleHierarchyException e) { + } + catch (CycleInRoleHierarchyException e) { } } @@ -181,8 +154,7 @@ public class RoleHierarchyImplTests { RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl(); try { - roleHierarchyImpl.setHierarchy( - "ROLE_A > ROLE_B\nROLE_A > ROLE_C\nROLE_C > ROLE_D\nROLE_B > ROLE_D"); + roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_A > ROLE_C\nROLE_C > ROLE_D\nROLE_B > ROLE_D"); } catch (CycleInRoleHierarchyException e) { fail("A cycle in role hierarchy was incorrectly detected!"); @@ -193,93 +165,78 @@ public class RoleHierarchyImplTests { @Test public void testSimpleRoleHierarchyWithCustomGrantedAuthorityImplementation() { - List authorities0 = HierarchicalRolesTestHelper.createAuthorityList( - "ROLE_0"); - List authorities1 = HierarchicalRolesTestHelper.createAuthorityList( - "ROLE_A"); - List authorities2 = HierarchicalRolesTestHelper.createAuthorityList( - "ROLE_A", "ROLE_B"); + List authorities0 = HierarchicalRolesTestHelper.createAuthorityList("ROLE_0"); + List authorities1 = HierarchicalRolesTestHelper.createAuthorityList("ROLE_A"); + List authorities2 = HierarchicalRolesTestHelper.createAuthorityList("ROLE_A", "ROLE_B"); RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl(); roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B"); - assertThat( - HierarchicalRolesTestHelper.containTheSameGrantedAuthoritiesCompareByAuthorityString( - roleHierarchyImpl.getReachableGrantedAuthorities(authorities0), - authorities0)).isTrue(); - assertThat( - HierarchicalRolesTestHelper.containTheSameGrantedAuthoritiesCompareByAuthorityString( - roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), - authorities2)).isTrue(); - assertThat( - HierarchicalRolesTestHelper.containTheSameGrantedAuthoritiesCompareByAuthorityString( - roleHierarchyImpl.getReachableGrantedAuthorities(authorities2), - authorities2)).isTrue(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthoritiesCompareByAuthorityString( + roleHierarchyImpl.getReachableGrantedAuthorities(authorities0), authorities0)).isTrue(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthoritiesCompareByAuthorityString( + roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), authorities2)).isTrue(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthoritiesCompareByAuthorityString( + roleHierarchyImpl.getReachableGrantedAuthorities(authorities2), authorities2)).isTrue(); } @Test public void testWhitespaceRoleHierarchies() { - List authorities1 = AuthorityUtils.createAuthorityList( - "ROLE A"); - List authorities2 = AuthorityUtils.createAuthorityList("ROLE A", - "ROLE B", "ROLE>C"); - List authorities3 = AuthorityUtils.createAuthorityList("ROLE A", - "ROLE B", "ROLE>C", "ROLE D"); + List authorities1 = AuthorityUtils.createAuthorityList("ROLE A"); + List authorities2 = AuthorityUtils.createAuthorityList("ROLE A", "ROLE B", "ROLE>C"); + List authorities3 = AuthorityUtils.createAuthorityList("ROLE A", "ROLE B", "ROLE>C", + "ROLE D"); RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl(); roleHierarchyImpl.setHierarchy("ROLE A > ROLE B\nROLE B > ROLE>C"); assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), - authorities2)).isTrue(); + roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), authorities2)).isTrue(); - roleHierarchyImpl.setHierarchy( - "ROLE A > ROLE B\nROLE B > ROLE>C\nROLE>C > ROLE D"); + roleHierarchyImpl.setHierarchy("ROLE A > ROLE B\nROLE B > ROLE>C\nROLE>C > ROLE D"); assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), - authorities3)).isTrue(); + roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), authorities3)).isTrue(); } // gh-6954 @Test public void testJavadoc() { - List flatAuthorities = AuthorityUtils.createAuthorityList( - "ROLE_A"); - List allAuthorities = AuthorityUtils.createAuthorityList( - "ROLE_A", "ROLE_B", "ROLE_AUTHENTICATED", "ROLE_UNAUTHENTICATED"); + List flatAuthorities = AuthorityUtils.createAuthorityList("ROLE_A"); + List allAuthorities = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B", + "ROLE_AUTHENTICATED", "ROLE_UNAUTHENTICATED"); RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl(); - roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\n" - + "ROLE_B > ROLE_AUTHENTICATED\n" - + "ROLE_AUTHENTICATED > ROLE_UNAUTHENTICATED"); + roleHierarchyImpl.setHierarchy( + "ROLE_A > ROLE_B\n" + "ROLE_B > ROLE_AUTHENTICATED\n" + "ROLE_AUTHENTICATED > ROLE_UNAUTHENTICATED"); - assertThat(roleHierarchyImpl.getReachableGrantedAuthorities(flatAuthorities)).containsExactlyInAnyOrderElementsOf(allAuthorities); + assertThat(roleHierarchyImpl.getReachableGrantedAuthorities(flatAuthorities)) + .containsExactlyInAnyOrderElementsOf(allAuthorities); } // gh-6954 @Test public void testInterfaceJavadoc() { - List flatAuthorities = AuthorityUtils.createAuthorityList( - "ROLE_HIGHEST"); - List allAuthorities = AuthorityUtils.createAuthorityList( - "ROLE_HIGHEST", "ROLE_HIGHER", "ROLE_LOW", "ROLE_LOWER"); + List flatAuthorities = AuthorityUtils.createAuthorityList("ROLE_HIGHEST"); + List allAuthorities = AuthorityUtils.createAuthorityList("ROLE_HIGHEST", "ROLE_HIGHER", + "ROLE_LOW", "ROLE_LOWER"); RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl(); - roleHierarchyImpl.setHierarchy("ROLE_HIGHEST > ROLE_HIGHER\n" - + "ROLE_HIGHER > ROLE_LOW\n" - + "ROLE_LOW > ROLE_LOWER"); + roleHierarchyImpl + .setHierarchy("ROLE_HIGHEST > ROLE_HIGHER\n" + "ROLE_HIGHER > ROLE_LOW\n" + "ROLE_LOW > ROLE_LOWER"); - assertThat(roleHierarchyImpl.getReachableGrantedAuthorities(flatAuthorities)).containsExactlyInAnyOrderElementsOf(allAuthorities); + assertThat(roleHierarchyImpl.getReachableGrantedAuthorities(flatAuthorities)) + .containsExactlyInAnyOrderElementsOf(allAuthorities); } // gh-6954 @Test public void singleLineLargeHierarchy() { - List flatAuthorities = AuthorityUtils.createAuthorityList( - "ROLE_HIGHEST"); - List allAuthorities = AuthorityUtils.createAuthorityList( - "ROLE_HIGHEST", "ROLE_HIGHER", "ROLE_LOW", "ROLE_LOWER"); + List flatAuthorities = AuthorityUtils.createAuthorityList("ROLE_HIGHEST"); + List allAuthorities = AuthorityUtils.createAuthorityList("ROLE_HIGHEST", "ROLE_HIGHER", + "ROLE_LOW", "ROLE_LOWER"); RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl(); roleHierarchyImpl.setHierarchy("ROLE_HIGHEST > ROLE_HIGHER > ROLE_LOW > ROLE_LOWER"); - assertThat(roleHierarchyImpl.getReachableGrantedAuthorities(flatAuthorities)).containsExactlyInAnyOrderElementsOf(allAuthorities); + assertThat(roleHierarchyImpl.getReachableGrantedAuthorities(flatAuthorities)) + .containsExactlyInAnyOrderElementsOf(allAuthorities); } + } diff --git a/core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyUtilsTests.java b/core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyUtilsTests.java index 2fb503fa95..0563713921 100644 --- a/core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyUtilsTests.java +++ b/core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyUtilsTests.java @@ -28,6 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Joe Grandja */ public class RoleHierarchyUtilsTests { + private static final String EOL = System.lineSeparator(); @Test @@ -90,4 +91,5 @@ public class RoleHierarchyUtilsTests { RoleHierarchyUtils.roleHierarchyFromMap(roleHierarchyMap); } + } diff --git a/core/src/test/java/org/springframework/security/access/hierarchicalroles/TestHelperTests.java b/core/src/test/java/org/springframework/security/access/hierarchicalroles/TestHelperTests.java index 21bf89df09..93800fd011 100644 --- a/core/src/test/java/org/springframework/security/access/hierarchicalroles/TestHelperTests.java +++ b/core/src/test/java/org/springframework/security/access/hierarchicalroles/TestHelperTests.java @@ -35,55 +35,34 @@ public class TestHelperTests { @Test public void testContainTheSameGrantedAuthorities() { - List authorities1 = AuthorityUtils.createAuthorityList( - "ROLE_A", "ROLE_B"); - List authorities2 = AuthorityUtils.createAuthorityList( - "ROLE_B", "ROLE_A"); - List authorities3 = AuthorityUtils.createAuthorityList( - "ROLE_A", "ROLE_C"); - List authorities4 = AuthorityUtils - .createAuthorityList("ROLE_A"); - List authorities5 = AuthorityUtils.createAuthorityList( - "ROLE_A", "ROLE_A"); + List authorities1 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B"); + List authorities2 = AuthorityUtils.createAuthorityList("ROLE_B", "ROLE_A"); + List authorities3 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_C"); + List authorities4 = AuthorityUtils.createAuthorityList("ROLE_A"); + List authorities5 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_A"); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(null, - null)).isTrue(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities1, authorities1)).isTrue(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities1, authorities2)).isTrue(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities2, authorities1)).isTrue(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(null, null)).isTrue(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities1)).isTrue(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities2)).isTrue(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities2, authorities1)).isTrue(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(null, - authorities1)).isFalse(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities1, null)).isFalse(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities1, authorities3)).isFalse(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities3, authorities1)).isFalse(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities1, authorities4)).isFalse(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities4, authorities1)).isFalse(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities4, authorities5)).isFalse(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(null, authorities1)).isFalse(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, null)).isFalse(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities3)).isFalse(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities3, authorities1)).isFalse(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities4)).isFalse(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities4, authorities1)).isFalse(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities4, authorities5)).isFalse(); } // SEC-863 @Test public void testToListOfAuthorityStrings() { - Collection authorities1 = AuthorityUtils.createAuthorityList( - "ROLE_A", "ROLE_B"); - Collection authorities2 = AuthorityUtils.createAuthorityList( - "ROLE_B", "ROLE_A"); - Collection authorities3 = AuthorityUtils.createAuthorityList( - "ROLE_A", "ROLE_C"); - Collection authorities4 = AuthorityUtils - .createAuthorityList("ROLE_A"); - Collection authorities5 = AuthorityUtils.createAuthorityList( - "ROLE_A", "ROLE_A"); + Collection authorities1 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B"); + Collection authorities2 = AuthorityUtils.createAuthorityList("ROLE_B", "ROLE_A"); + Collection authorities3 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_C"); + Collection authorities4 = AuthorityUtils.createAuthorityList("ROLE_A"); + Collection authorities5 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_A"); List authoritiesStrings1 = new ArrayList<>(); authoritiesStrings1.add("ROLE_A"); @@ -105,89 +84,69 @@ public class TestHelperTests { authoritiesStrings5.add("ROLE_A"); assertThat(CollectionUtils.isEqualCollection( - HierarchicalRolesTestHelper.toCollectionOfAuthorityStrings(authorities1), - authoritiesStrings1)).isTrue(); + HierarchicalRolesTestHelper.toCollectionOfAuthorityStrings(authorities1), authoritiesStrings1)) + .isTrue(); assertThat(CollectionUtils.isEqualCollection( - HierarchicalRolesTestHelper.toCollectionOfAuthorityStrings(authorities2), - authoritiesStrings2)).isTrue(); + HierarchicalRolesTestHelper.toCollectionOfAuthorityStrings(authorities2), authoritiesStrings2)) + .isTrue(); assertThat(CollectionUtils.isEqualCollection( - HierarchicalRolesTestHelper.toCollectionOfAuthorityStrings(authorities3), - authoritiesStrings3)).isTrue(); + HierarchicalRolesTestHelper.toCollectionOfAuthorityStrings(authorities3), authoritiesStrings3)) + .isTrue(); assertThat(CollectionUtils.isEqualCollection( - HierarchicalRolesTestHelper.toCollectionOfAuthorityStrings(authorities4), - authoritiesStrings4)).isTrue(); + HierarchicalRolesTestHelper.toCollectionOfAuthorityStrings(authorities4), authoritiesStrings4)) + .isTrue(); assertThat(CollectionUtils.isEqualCollection( - HierarchicalRolesTestHelper.toCollectionOfAuthorityStrings(authorities5), - authoritiesStrings5)).isTrue(); + HierarchicalRolesTestHelper.toCollectionOfAuthorityStrings(authorities5), authoritiesStrings5)) + .isTrue(); } // SEC-863 @Test public void testContainTheSameGrantedAuthoritiesCompareByAuthorityString() { - List authorities1 = AuthorityUtils.createAuthorityList( - "ROLE_A", "ROLE_B"); - List authorities2 = AuthorityUtils.createAuthorityList( - "ROLE_B", "ROLE_A"); - List authorities3 = AuthorityUtils.createAuthorityList( - "ROLE_A", "ROLE_C"); - List authorities4 = AuthorityUtils - .createAuthorityList("ROLE_A"); - List authorities5 = AuthorityUtils.createAuthorityList( - "ROLE_A", "ROLE_A"); + List authorities1 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B"); + List authorities2 = AuthorityUtils.createAuthorityList("ROLE_B", "ROLE_A"); + List authorities3 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_C"); + List authorities4 = AuthorityUtils.createAuthorityList("ROLE_A"); + List authorities5 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_A"); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(null, - null)).isTrue(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities1, authorities1)).isTrue(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities1, authorities2)).isTrue(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities2, authorities1)).isTrue(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(null, null)).isTrue(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities1)).isTrue(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities2)).isTrue(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities2, authorities1)).isTrue(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(null, - authorities1)).isFalse(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities1, null)).isFalse(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities1, authorities3)).isFalse(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities3, authorities1)).isFalse(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities1, authorities4)).isFalse(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities4, authorities1)).isFalse(); - assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities( - authorities4, authorities5)).isFalse(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(null, authorities1)).isFalse(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, null)).isFalse(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities3)).isFalse(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities3, authorities1)).isFalse(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities4)).isFalse(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities4, authorities1)).isFalse(); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities4, authorities5)).isFalse(); } // SEC-863 @Test public void testContainTheSameGrantedAuthoritiesCompareByAuthorityStringWithAuthorityLists() { - List authorities1 = HierarchicalRolesTestHelper - .createAuthorityList("ROLE_A", "ROLE_B"); - List authorities2 = AuthorityUtils.createAuthorityList( - "ROLE_A", "ROLE_B"); - assertThat(HierarchicalRolesTestHelper - .containTheSameGrantedAuthoritiesCompareByAuthorityString(authorities1, - authorities2)).isTrue(); + List authorities1 = HierarchicalRolesTestHelper.createAuthorityList("ROLE_A", "ROLE_B"); + List authorities2 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B"); + assertThat(HierarchicalRolesTestHelper.containTheSameGrantedAuthoritiesCompareByAuthorityString(authorities1, + authorities2)).isTrue(); } // SEC-863 @Test public void testCreateAuthorityList() { - List authorities1 = HierarchicalRolesTestHelper - .createAuthorityList("ROLE_A"); + List authorities1 = HierarchicalRolesTestHelper.createAuthorityList("ROLE_A"); assertThat(authorities1).hasSize(1); assertThat(authorities1.get(0).getAuthority()).isEqualTo("ROLE_A"); - List authorities2 = HierarchicalRolesTestHelper - .createAuthorityList("ROLE_A", "ROLE_C"); + List authorities2 = HierarchicalRolesTestHelper.createAuthorityList("ROLE_A", "ROLE_C"); assertThat(authorities2).hasSize(2); assertThat(authorities2.get(0).getAuthority()).isEqualTo("ROLE_A"); assertThat(authorities2.get(1).getAuthority()).isEqualTo("ROLE_C"); } + } diff --git a/core/src/test/java/org/springframework/security/access/intercept/AbstractSecurityInterceptorTests.java b/core/src/test/java/org/springframework/security/access/intercept/AbstractSecurityInterceptorTests.java index e9bd20de69..7ea4f8eb2e 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/AbstractSecurityInterceptorTests.java +++ b/core/src/test/java/org/springframework/security/access/intercept/AbstractSecurityInterceptorTests.java @@ -31,6 +31,7 @@ import org.springframework.security.util.SimpleMethodInvocation; * @author Ben Alex */ public class AbstractSecurityInterceptorTests { + // ~ Methods // ======================================================================================================== @@ -61,6 +62,7 @@ public class AbstractSecurityInterceptorTests { // ================================================================================================== private class MockSecurityInterceptorReturnsNull extends AbstractSecurityInterceptor { + private SecurityMetadataSource securityMetadataSource; public Class getSecureObjectClass() { @@ -71,14 +73,14 @@ public class AbstractSecurityInterceptorTests { return securityMetadataSource; } - public void setSecurityMetadataSource( - SecurityMetadataSource securityMetadataSource) { + public void setSecurityMetadataSource(SecurityMetadataSource securityMetadataSource) { this.securityMetadataSource = securityMetadataSource; } + } - private class MockSecurityInterceptorWhichOnlySupportsStrings extends - AbstractSecurityInterceptor { + private class MockSecurityInterceptorWhichOnlySupportsStrings extends AbstractSecurityInterceptor { + private SecurityMetadataSource securityMetadataSource; public Class getSecureObjectClass() { @@ -89,9 +91,10 @@ public class AbstractSecurityInterceptorTests { return securityMetadataSource; } - public void setSecurityMetadataSource( - SecurityMetadataSource securityMetadataSource) { + public void setSecurityMetadataSource(SecurityMetadataSource securityMetadataSource) { this.securityMetadataSource = securityMetadataSource; } + } + } diff --git a/core/src/test/java/org/springframework/security/access/intercept/AfterInvocationProviderManagerTests.java b/core/src/test/java/org/springframework/security/access/intercept/AfterInvocationProviderManagerTests.java index 90ce27038c..d2439954ab 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/AfterInvocationProviderManagerTests.java +++ b/core/src/test/java/org/springframework/security/access/intercept/AfterInvocationProviderManagerTests.java @@ -46,41 +46,33 @@ public class AfterInvocationProviderManagerTests { public void testCorrectOperation() throws Exception { AfterInvocationProviderManager manager = new AfterInvocationProviderManager(); List list = new Vector(); - list.add(new MockAfterInvocationProvider("swap1", MethodInvocation.class, - new SecurityConfig("GIVE_ME_SWAP1"))); - list.add(new MockAfterInvocationProvider("swap2", MethodInvocation.class, - new SecurityConfig("GIVE_ME_SWAP2"))); - list.add(new MockAfterInvocationProvider("swap3", MethodInvocation.class, - new SecurityConfig("GIVE_ME_SWAP3"))); + list.add(new MockAfterInvocationProvider("swap1", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP1"))); + list.add(new MockAfterInvocationProvider("swap2", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP2"))); + list.add(new MockAfterInvocationProvider("swap3", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP3"))); manager.setProviders(list); assertThat(manager.getProviders()).isEqualTo(list); manager.afterPropertiesSet(); - List attr1 = SecurityConfig.createList( - new String[] { "GIVE_ME_SWAP1" }); - List attr2 = SecurityConfig.createList( - new String[] { "GIVE_ME_SWAP2" }); - List attr3 = SecurityConfig.createList( - new String[] { "GIVE_ME_SWAP3" }); - List attr2and3 = SecurityConfig.createList( - new String[] { "GIVE_ME_SWAP2", "GIVE_ME_SWAP3" }); - List attr4 = SecurityConfig.createList( - new String[] { "NEVER_CAUSES_SWAP" }); + List attr1 = SecurityConfig.createList(new String[] { "GIVE_ME_SWAP1" }); + List attr2 = SecurityConfig.createList(new String[] { "GIVE_ME_SWAP2" }); + List attr3 = SecurityConfig.createList(new String[] { "GIVE_ME_SWAP3" }); + List attr2and3 = SecurityConfig.createList(new String[] { "GIVE_ME_SWAP2", "GIVE_ME_SWAP3" }); + List attr4 = SecurityConfig.createList(new String[] { "NEVER_CAUSES_SWAP" }); - assertThat(manager.decide(null, new SimpleMethodInvocation(), attr1, - "content-before-swapping")).isEqualTo("swap1"); + assertThat(manager.decide(null, new SimpleMethodInvocation(), attr1, "content-before-swapping")) + .isEqualTo("swap1"); - assertThat(manager.decide(null, new SimpleMethodInvocation(), attr2, - "content-before-swapping")).isEqualTo("swap2"); + assertThat(manager.decide(null, new SimpleMethodInvocation(), attr2, "content-before-swapping")) + .isEqualTo("swap2"); - assertThat(manager.decide(null, new SimpleMethodInvocation(), attr3, - "content-before-swapping")).isEqualTo("swap3"); + assertThat(manager.decide(null, new SimpleMethodInvocation(), attr3, "content-before-swapping")) + .isEqualTo("swap3"); - assertThat(manager.decide(null, new SimpleMethodInvocation(), attr4, - "content-before-swapping")).isEqualTo("content-before-swapping"); + assertThat(manager.decide(null, new SimpleMethodInvocation(), attr4, "content-before-swapping")) + .isEqualTo("content-before-swapping"); - assertThat(manager.decide(null, new SimpleMethodInvocation(), attr2and3, - "content-before-swapping")).isEqualTo("swap3"); + assertThat(manager.decide(null, new SimpleMethodInvocation(), attr2and3, "content-before-swapping")) + .isEqualTo("swap3"); } @Test @@ -101,11 +93,9 @@ public class AfterInvocationProviderManagerTests { public void testRejectsNonAfterInvocationProviders() { AfterInvocationProviderManager manager = new AfterInvocationProviderManager(); List list = new Vector(); - list.add(new MockAfterInvocationProvider("swap1", MethodInvocation.class, - new SecurityConfig("GIVE_ME_SWAP1"))); + list.add(new MockAfterInvocationProvider("swap1", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP1"))); list.add(45); - list.add(new MockAfterInvocationProvider("swap3", MethodInvocation.class, - new SecurityConfig("GIVE_ME_SWAP3"))); + list.add(new MockAfterInvocationProvider("swap3", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP3"))); try { manager.setProviders(list); @@ -133,12 +123,9 @@ public class AfterInvocationProviderManagerTests { public void testSupportsConfigAttributeIteration() throws Exception { AfterInvocationProviderManager manager = new AfterInvocationProviderManager(); List list = new Vector(); - list.add(new MockAfterInvocationProvider("swap1", MethodInvocation.class, - new SecurityConfig("GIVE_ME_SWAP1"))); - list.add(new MockAfterInvocationProvider("swap2", MethodInvocation.class, - new SecurityConfig("GIVE_ME_SWAP2"))); - list.add(new MockAfterInvocationProvider("swap3", MethodInvocation.class, - new SecurityConfig("GIVE_ME_SWAP3"))); + list.add(new MockAfterInvocationProvider("swap1", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP1"))); + list.add(new MockAfterInvocationProvider("swap2", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP2"))); + list.add(new MockAfterInvocationProvider("swap3", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP3"))); manager.setProviders(list); manager.afterPropertiesSet(); @@ -150,12 +137,9 @@ public class AfterInvocationProviderManagerTests { public void testSupportsSecureObjectIteration() throws Exception { AfterInvocationProviderManager manager = new AfterInvocationProviderManager(); List list = new Vector(); - list.add(new MockAfterInvocationProvider("swap1", MethodInvocation.class, - new SecurityConfig("GIVE_ME_SWAP1"))); - list.add(new MockAfterInvocationProvider("swap2", MethodInvocation.class, - new SecurityConfig("GIVE_ME_SWAP2"))); - list.add(new MockAfterInvocationProvider("swap3", MethodInvocation.class, - new SecurityConfig("GIVE_ME_SWAP3"))); + list.add(new MockAfterInvocationProvider("swap1", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP1"))); + list.add(new MockAfterInvocationProvider("swap2", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP2"))); + list.add(new MockAfterInvocationProvider("swap3", MethodInvocation.class, new SecurityConfig("GIVE_ME_SWAP3"))); manager.setProviders(list); manager.afterPropertiesSet(); @@ -185,9 +169,8 @@ public class AfterInvocationProviderManagerTests { this.configAttribute = configAttribute; } - public Object decide(Authentication authentication, Object object, - Collection config, Object returnedObject) - throws AccessDeniedException { + public Object decide(Authentication authentication, Object object, Collection config, + Object returnedObject) throws AccessDeniedException { if (config.contains(configAttribute)) { return forceReturnObject; } @@ -202,5 +185,7 @@ public class AfterInvocationProviderManagerTests { public boolean supports(ConfigAttribute attribute) { return attribute.equals(configAttribute); } + } + } diff --git a/core/src/test/java/org/springframework/security/access/intercept/InterceptorStatusTokenTests.java b/core/src/test/java/org/springframework/security/access/intercept/InterceptorStatusTokenTests.java index f9f163aeb8..c95c1a800d 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/InterceptorStatusTokenTests.java +++ b/core/src/test/java/org/springframework/security/access/intercept/InterceptorStatusTokenTests.java @@ -47,4 +47,5 @@ public class InterceptorStatusTokenTests { assertThat(token.getSecureObject()).isEqualTo(mi); assertThat(token.getSecurityContext()).isSameAs(ctx); } + } diff --git a/core/src/test/java/org/springframework/security/access/intercept/NullRunAsManagerTests.java b/core/src/test/java/org/springframework/security/access/intercept/NullRunAsManagerTests.java index 3200cb954d..8f8ca85e0a 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/NullRunAsManagerTests.java +++ b/core/src/test/java/org/springframework/security/access/intercept/NullRunAsManagerTests.java @@ -27,6 +27,7 @@ import org.springframework.security.access.SecurityConfig; * @author Ben Alex */ public class NullRunAsManagerTests { + // ~ Methods // ======================================================================================================== @@ -47,4 +48,5 @@ public class NullRunAsManagerTests { NullRunAsManager runAs = new NullRunAsManager(); assertThat(runAs.supports(new SecurityConfig("X"))).isFalse(); } + } diff --git a/core/src/test/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProviderTests.java b/core/src/test/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProviderTests.java index ad2fda9bd9..ec92ca2b1d 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProviderTests.java +++ b/core/src/test/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProviderTests.java @@ -33,8 +33,7 @@ public class RunAsImplAuthenticationProviderTests { @Test(expected = BadCredentialsException.class) public void testAuthenticationFailDueToWrongKey() { RunAsUserToken token = new RunAsUserToken("wrong_key", "Test", "Password", - AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), - UsernamePasswordAuthenticationToken.class); + AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), UsernamePasswordAuthenticationToken.class); RunAsImplAuthenticationProvider provider = new RunAsImplAuthenticationProvider(); provider.setKey("hello_world"); @@ -44,15 +43,13 @@ public class RunAsImplAuthenticationProviderTests { @Test public void testAuthenticationSuccess() { RunAsUserToken token = new RunAsUserToken("my_password", "Test", "Password", - AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), - UsernamePasswordAuthenticationToken.class); + AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), UsernamePasswordAuthenticationToken.class); RunAsImplAuthenticationProvider provider = new RunAsImplAuthenticationProvider(); provider.setKey("my_password"); Authentication result = provider.authenticate(token); - Assert.assertTrue("Should have returned RunAsUserToken", - result instanceof RunAsUserToken); + Assert.assertTrue("Should have returned RunAsUserToken", result instanceof RunAsUserToken); RunAsUserToken resultCast = (RunAsUserToken) result; assertThat(resultCast.getKeyHash()).isEqualTo("my_password".hashCode()); @@ -79,4 +76,5 @@ public class RunAsImplAuthenticationProviderTests { assertThat(provider.supports(RunAsUserToken.class)).isTrue(); assertThat(!provider.supports(TestingAuthenticationToken.class)).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/access/intercept/RunAsManagerImplTests.java b/core/src/test/java/org/springframework/security/access/intercept/RunAsManagerImplTests.java index be93663948..e5cb1a8dc3 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/RunAsManagerImplTests.java +++ b/core/src/test/java/org/springframework/security/access/intercept/RunAsManagerImplTests.java @@ -42,8 +42,7 @@ public class RunAsManagerImplTests { @Test public void testDoesNotReturnAdditionalAuthoritiesIfCalledWithoutARunAsSetting() { - UsernamePasswordAuthenticationToken inputToken = new UsernamePasswordAuthenticationToken( - "Test", "Password", + UsernamePasswordAuthenticationToken inputToken = new UsernamePasswordAuthenticationToken("Test", "Password", AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO")); RunAsManagerImpl runAs = new RunAsManagerImpl(); @@ -56,8 +55,8 @@ public class RunAsManagerImplTests { @Test public void testRespectsRolePrefix() { - UsernamePasswordAuthenticationToken inputToken = new UsernamePasswordAuthenticationToken( - "Test", "Password", AuthorityUtils.createAuthorityList("ONE", "TWO")); + UsernamePasswordAuthenticationToken inputToken = new UsernamePasswordAuthenticationToken("Test", "Password", + AuthorityUtils.createAuthorityList("ONE", "TWO")); RunAsManagerImpl runAs = new RunAsManagerImpl(); runAs.setKey("my_password"); @@ -66,12 +65,10 @@ public class RunAsManagerImplTests { Authentication result = runAs.buildRunAs(inputToken, new Object(), SecurityConfig.createList("RUN_AS_SOMETHING")); - assertThat(result instanceof RunAsUserToken).withFailMessage( - "Should have returned a RunAsUserToken").isTrue(); + assertThat(result instanceof RunAsUserToken).withFailMessage("Should have returned a RunAsUserToken").isTrue(); assertThat(result.getPrincipal()).isEqualTo(inputToken.getPrincipal()); assertThat(result.getCredentials()).isEqualTo(inputToken.getCredentials()); - Set authorities = AuthorityUtils.authorityListToSet( - result.getAuthorities()); + Set authorities = AuthorityUtils.authorityListToSet(result.getAuthorities()); assertThat(authorities.contains("FOOBAR_RUN_AS_SOMETHING")).isTrue(); assertThat(authorities.contains("ONE")).isTrue(); @@ -83,8 +80,7 @@ public class RunAsManagerImplTests { @Test public void testReturnsAdditionalGrantedAuthorities() { - UsernamePasswordAuthenticationToken inputToken = new UsernamePasswordAuthenticationToken( - "Test", "Password", + UsernamePasswordAuthenticationToken inputToken = new UsernamePasswordAuthenticationToken("Test", "Password", AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO")); RunAsManagerImpl runAs = new RunAsManagerImpl(); @@ -100,8 +96,7 @@ public class RunAsManagerImplTests { assertThat(result.getPrincipal()).isEqualTo(inputToken.getPrincipal()); assertThat(result.getCredentials()).isEqualTo(inputToken.getCredentials()); - Set authorities = AuthorityUtils.authorityListToSet( - result.getAuthorities()); + Set authorities = AuthorityUtils.authorityListToSet(result.getAuthorities()); assertThat(authorities.contains("ROLE_RUN_AS_SOMETHING")).isTrue(); assertThat(authorities.contains("ROLE_ONE")).isTrue(); assertThat(authorities.contains("ROLE_TWO")).isTrue(); @@ -138,4 +133,5 @@ public class RunAsManagerImplTests { assertThat(!runAs.supports(new SecurityConfig("ROLE_WHICH_IS_IGNORED"))).isTrue(); assertThat(!runAs.supports(new SecurityConfig("role_LOWER_CASE_FAILS"))).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/access/intercept/RunAsUserTokenTests.java b/core/src/test/java/org/springframework/security/access/intercept/RunAsUserTokenTests.java index a378d586ce..4182eece6e 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/RunAsUserTokenTests.java +++ b/core/src/test/java/org/springframework/security/access/intercept/RunAsUserTokenTests.java @@ -33,8 +33,7 @@ public class RunAsUserTokenTests { @Test public void testAuthenticationSetting() { RunAsUserToken token = new RunAsUserToken("my_password", "Test", "Password", - AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), - UsernamePasswordAuthenticationToken.class); + AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), UsernamePasswordAuthenticationToken.class); assertThat(token.isAuthenticated()).isTrue(); token.setAuthenticated(false); assertThat(!token.isAuthenticated()).isTrue(); @@ -43,13 +42,11 @@ public class RunAsUserTokenTests { @Test public void testGetters() { RunAsUserToken token = new RunAsUserToken("my_password", "Test", "Password", - AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), - UsernamePasswordAuthenticationToken.class); + AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), UsernamePasswordAuthenticationToken.class); assertThat("Test").isEqualTo(token.getPrincipal()); assertThat("Password").isEqualTo(token.getCredentials()); assertThat("my_password".hashCode()).isEqualTo(token.getKeyHash()); - assertThat(UsernamePasswordAuthenticationToken.class).isEqualTo( - token.getOriginalAuthentication()); + assertThat(UsernamePasswordAuthenticationToken.class).isEqualTo(token.getOriginalAuthentication()); } @Test @@ -68,10 +65,10 @@ public class RunAsUserTokenTests { @Test public void testToString() { RunAsUserToken token = new RunAsUserToken("my_password", "Test", "Password", - AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), - UsernamePasswordAuthenticationToken.class); - assertThat(token.toString().lastIndexOf("Original Class: " - + UsernamePasswordAuthenticationToken.class.getName().toString()) != -1).isTrue(); + AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), UsernamePasswordAuthenticationToken.class); + assertThat(token.toString() + .lastIndexOf("Original Class: " + UsernamePasswordAuthenticationToken.class.getName().toString()) != -1) + .isTrue(); } // SEC-1792 @@ -81,4 +78,5 @@ public class RunAsUserTokenTests { AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), null); assertThat(token.toString().lastIndexOf("Original Class: null") != -1).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptorTests.java b/core/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptorTests.java index b4e1f61c64..eff1830caf 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptorTests.java +++ b/core/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityInterceptorTests.java @@ -54,13 +54,21 @@ import java.util.*; */ @SuppressWarnings("unchecked") public class MethodSecurityInterceptorTests { + private TestingAuthenticationToken token; + private MethodSecurityInterceptor interceptor; + private ITargetObject realTarget; + private ITargetObject advisedTarget; + private AccessDecisionManager adm; + private MethodSecurityMetadataSource mds; + private AuthenticationManager authman; + private ApplicationEventPublisher eventPublisher; // ~ Methods @@ -132,23 +140,20 @@ public class MethodSecurityInterceptorTests { } @Test(expected = IllegalArgumentException.class) - public void initializationRejectsSecurityMetadataSourceThatDoesNotSupportMethodInvocation() - throws Throwable { + public void initializationRejectsSecurityMetadataSourceThatDoesNotSupportMethodInvocation() throws Throwable { when(mds.supports(MethodInvocation.class)).thenReturn(false); interceptor.afterPropertiesSet(); } @Test(expected = IllegalArgumentException.class) - public void initializationRejectsAccessDecisionManagerThatDoesNotSupportMethodInvocation() - throws Exception { + public void initializationRejectsAccessDecisionManagerThatDoesNotSupportMethodInvocation() throws Exception { when(mds.supports(MethodInvocation.class)).thenReturn(true); when(adm.supports(MethodInvocation.class)).thenReturn(false); interceptor.afterPropertiesSet(); } @Test(expected = IllegalArgumentException.class) - public void intitalizationRejectsRunAsManagerThatDoesNotSupportMethodInvocation() - throws Exception { + public void intitalizationRejectsRunAsManagerThatDoesNotSupportMethodInvocation() throws Exception { final RunAsManager ram = mock(RunAsManager.class); when(ram.supports(MethodInvocation.class)).thenReturn(false); interceptor.setRunAsManager(ram); @@ -156,8 +161,7 @@ public class MethodSecurityInterceptorTests { } @Test(expected = IllegalArgumentException.class) - public void intitalizationRejectsAfterInvocationManagerThatDoesNotSupportMethodInvocation() - throws Exception { + public void intitalizationRejectsAfterInvocationManagerThatDoesNotSupportMethodInvocation() throws Exception { final AfterInvocationManager aim = mock(AfterInvocationManager.class); when(aim.supports(MethodInvocation.class)).thenReturn(false); interceptor.setAfterInvocationManager(aim); @@ -165,15 +169,13 @@ public class MethodSecurityInterceptorTests { } @Test(expected = IllegalArgumentException.class) - public void initializationFailsIfAccessDecisionManagerRejectsConfigAttributes() - throws Exception { + public void initializationFailsIfAccessDecisionManagerRejectsConfigAttributes() throws Exception { when(adm.supports(any(ConfigAttribute.class))).thenReturn(false); interceptor.afterPropertiesSet(); } @Test - public void validationNotAttemptedIfIsValidateConfigAttributesSetToFalse() - throws Exception { + public void validationNotAttemptedIfIsValidateConfigAttributesSetToFalse() throws Exception { when(adm.supports(MethodInvocation.class)).thenReturn(true); when(mds.supports(MethodInvocation.class)).thenReturn(true); interceptor.setValidateConfigAttributes(false); @@ -183,8 +185,7 @@ public class MethodSecurityInterceptorTests { } @Test - public void validationNotAttemptedIfMethodSecurityMetadataSourceReturnsNullForAttributes() - throws Exception { + public void validationNotAttemptedIfMethodSecurityMetadataSourceReturnsNullForAttributes() throws Exception { when(adm.supports(MethodInvocation.class)).thenReturn(true); when(mds.supports(MethodInvocation.class)).thenReturn(true); when(mds.getAllConfigAttributes()).thenReturn(null); @@ -205,19 +206,18 @@ public class MethodSecurityInterceptorTests { public void callingAPublicMethodWhenPresentingAnAuthenticationObjectDoesntChangeItsAuthenticatedProperty() { mdsReturnsNull(); SecurityContextHolder.getContext().setAuthentication(token); - assertThat(advisedTarget.publicMakeLowerCase("HELLO")).isEqualTo("hello org.springframework.security.authentication.TestingAuthenticationToken false"); + assertThat(advisedTarget.publicMakeLowerCase("HELLO")) + .isEqualTo("hello org.springframework.security.authentication.TestingAuthenticationToken false"); assertThat(!token.isAuthenticated()).isTrue(); } @Test(expected = AuthenticationException.class) public void callIsntMadeWhenAuthenticationManagerRejectsAuthentication() { - final TestingAuthenticationToken token = new TestingAuthenticationToken("Test", - "Password"); + final TestingAuthenticationToken token = new TestingAuthenticationToken("Test", "Password"); SecurityContextHolder.getContext().setAuthentication(token); mdsReturnsUserRole(); - when(authman.authenticate(token)).thenThrow( - new BadCredentialsException("rejected")); + when(authman.authenticate(token)).thenThrow(new BadCredentialsException("rejected")); advisedTarget.makeLowerCase("HELLO"); } @@ -232,7 +232,8 @@ public class MethodSecurityInterceptorTests { String result = advisedTarget.makeLowerCase("HELLO"); // Note we check the isAuthenticated remained true in following line - assertThat(result).isEqualTo("hello org.springframework.security.authentication.TestingAuthenticationToken true"); + assertThat(result) + .isEqualTo("hello org.springframework.security.authentication.TestingAuthenticationToken true"); verify(eventPublisher).publishEvent(any(AuthorizedEvent.class)); } @@ -244,8 +245,8 @@ public class MethodSecurityInterceptorTests { createTarget(true); mdsReturnsUserRole(); when(authman.authenticate(token)).thenReturn(token); - doThrow(new AccessDeniedException("rejected")).when(adm).decide( - any(Authentication.class), any(MethodInvocation.class), any(List.class)); + doThrow(new AccessDeniedException("rejected")).when(adm).decide(any(Authentication.class), + any(MethodInvocation.class), any(List.class)); try { advisedTarget.makeUpperCase("HELLO"); @@ -267,12 +268,11 @@ public class MethodSecurityInterceptorTests { ctx.setAuthentication(token); token.setAuthenticated(true); final RunAsManager runAs = mock(RunAsManager.class); - final RunAsUserToken runAsToken = new RunAsUserToken("key", "someone", "creds", - token.getAuthorities(), TestingAuthenticationToken.class); + final RunAsUserToken runAsToken = new RunAsUserToken("key", "someone", "creds", token.getAuthorities(), + TestingAuthenticationToken.class); interceptor.setRunAsManager(runAs); mdsReturnsUserRole(); - when(runAs.buildRunAs(eq(token), any(MethodInvocation.class), any(List.class))) - .thenReturn(runAsToken); + when(runAs.buildRunAs(eq(token), any(MethodInvocation.class), any(List.class))).thenReturn(runAsToken); String result = advisedTarget.makeUpperCase("hello"); assertThat(result).isEqualTo("HELLO org.springframework.security.access.intercept.RunAsUserToken true"); @@ -290,12 +290,11 @@ public class MethodSecurityInterceptorTests { ctx.setAuthentication(token); token.setAuthenticated(true); final RunAsManager runAs = mock(RunAsManager.class); - final RunAsUserToken runAsToken = new RunAsUserToken("key", "someone", "creds", - token.getAuthorities(), TestingAuthenticationToken.class); + final RunAsUserToken runAsToken = new RunAsUserToken("key", "someone", "creds", token.getAuthorities(), + TestingAuthenticationToken.class); interceptor.setRunAsManager(runAs); mdsReturnsUserRole(); - when(runAs.buildRunAs(eq(token), any(MethodInvocation.class), any(List.class))) - .thenReturn(runAsToken); + when(runAs.buildRunAs(eq(token), any(MethodInvocation.class), any(List.class))).thenReturn(runAsToken); try { advisedTarget.makeUpperCase("hello"); @@ -342,7 +341,7 @@ public class MethodSecurityInterceptorTests { } void mdsReturnsUserRole() { - when(mds.getAttributes(any(MethodInvocation.class))).thenReturn( - SecurityConfig.createList("ROLE_USER")); + when(mds.getAttributes(any(MethodInvocation.class))).thenReturn(SecurityConfig.createList("ROLE_USER")); } + } diff --git a/core/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisorTests.java b/core/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisorTests.java index 6ddf453c9b..88e83036b2 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisorTests.java +++ b/core/src/test/java/org/springframework/security/access/intercept/aopalliance/MethodSecurityMetadataSourceAdvisorTests.java @@ -43,10 +43,8 @@ public class MethodSecurityMetadataSourceAdvisorTests { MethodSecurityMetadataSource mds = mock(MethodSecurityMetadataSource.class); when(mds.getAttributes(method, clazz)).thenReturn(null); - MethodSecurityMetadataSourceAdvisor advisor = new MethodSecurityMetadataSourceAdvisor( - "", mds, ""); - assertThat(advisor.getPointcut().getMethodMatcher().matches(method, - clazz)).isFalse(); + MethodSecurityMetadataSourceAdvisor advisor = new MethodSecurityMetadataSourceAdvisor("", mds, ""); + assertThat(advisor.getPointcut().getMethodMatcher().matches(method, clazz)).isFalse(); } @Test @@ -55,11 +53,9 @@ public class MethodSecurityMetadataSourceAdvisorTests { Method method = clazz.getMethod("countLength", new Class[] { String.class }); MethodSecurityMetadataSource mds = mock(MethodSecurityMetadataSource.class); - when(mds.getAttributes(method, clazz)).thenReturn( - SecurityConfig.createList("ROLE_A")); - MethodSecurityMetadataSourceAdvisor advisor = new MethodSecurityMetadataSourceAdvisor( - "", mds, ""); - assertThat( - advisor.getPointcut().getMethodMatcher().matches(method, clazz)).isTrue(); + when(mds.getAttributes(method, clazz)).thenReturn(SecurityConfig.createList("ROLE_A")); + MethodSecurityMetadataSourceAdvisor advisor = new MethodSecurityMetadataSourceAdvisor("", mds, ""); + assertThat(advisor.getPointcut().getMethodMatcher().matches(method, clazz)).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptorTests.java b/core/src/test/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptorTests.java index e98c5764a6..593db48047 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptorTests.java +++ b/core/src/test/java/org/springframework/security/access/intercept/aspectj/AspectJMethodSecurityInterceptorTests.java @@ -54,12 +54,19 @@ import java.util.List; * @author Rob Winch */ public class AspectJMethodSecurityInterceptorTests { + private TestingAuthenticationToken token; + private AspectJMethodSecurityInterceptor interceptor; + private @Mock AccessDecisionManager adm; + private @Mock MethodSecurityMetadataSource mds; + private @Mock AuthenticationManager authman; + private @Mock AspectJCallback aspectJCallback; + private ProceedingJoinPoint joinPoint; // ~ Methods @@ -87,8 +94,7 @@ public class AspectJMethodSecurityInterceptorTests { when(codeSig.getDeclaringType()).thenReturn(TargetObject.class); when(codeSig.getParameterTypes()).thenReturn(new Class[] { String.class }); when(staticPart.getSignature()).thenReturn(codeSig); - when(mds.getAttributes(any())).thenReturn( - SecurityConfig.createList("ROLE_USER")); + when(mds.getAttributes(any())).thenReturn(SecurityConfig.createList("ROLE_USER")); when(authman.authenticate(token)).thenReturn(token); } @@ -110,8 +116,7 @@ public class AspectJMethodSecurityInterceptorTests { @SuppressWarnings("unchecked") @Test public void callbackIsNotInvokedWhenPermissionDenied() { - doThrow(new AccessDeniedException("denied")).when(adm).decide( - any(), any(), any()); + doThrow(new AccessDeniedException("denied")).when(adm).decide(any(), any(), any()); SecurityContextHolder.getContext().setAuthentication(token); try { @@ -126,8 +131,7 @@ public class AspectJMethodSecurityInterceptorTests { @Test public void adapterHoldsCorrectData() { TargetObject to = new TargetObject(); - Method m = ClassUtils.getMethodIfAvailable(TargetObject.class, "countLength", - new Class[] { String.class }); + Method m = ClassUtils.getMethodIfAvailable(TargetObject.class, "countLength", new Class[] { String.class }); when(joinPoint.getTarget()).thenReturn(to); when(joinPoint.getArgs()).thenReturn(new Object[] { "Hi" }); @@ -166,11 +170,10 @@ public class AspectJMethodSecurityInterceptorTests { ctx.setAuthentication(token); token.setAuthenticated(true); final RunAsManager runAs = mock(RunAsManager.class); - final RunAsUserToken runAsToken = new RunAsUserToken("key", "someone", "creds", - token.getAuthorities(), TestingAuthenticationToken.class); + final RunAsUserToken runAsToken = new RunAsUserToken("key", "someone", "creds", token.getAuthorities(), + TestingAuthenticationToken.class); interceptor.setRunAsManager(runAs); - when(runAs.buildRunAs(eq(token), any(MethodInvocation.class), any(List.class))) - .thenReturn(runAsToken); + when(runAs.buildRunAs(eq(token), any(MethodInvocation.class), any(List.class))).thenReturn(runAsToken); when(aspectJCallback.proceedWithObject()).thenThrow(new RuntimeException()); try { @@ -193,11 +196,10 @@ public class AspectJMethodSecurityInterceptorTests { ctx.setAuthentication(token); token.setAuthenticated(true); final RunAsManager runAs = mock(RunAsManager.class); - final RunAsUserToken runAsToken = new RunAsUserToken("key", "someone", "creds", - token.getAuthorities(), TestingAuthenticationToken.class); + final RunAsUserToken runAsToken = new RunAsUserToken("key", "someone", "creds", token.getAuthorities(), + TestingAuthenticationToken.class); interceptor.setRunAsManager(runAs); - when(runAs.buildRunAs(eq(token), any(MethodInvocation.class), any(List.class))) - .thenReturn(runAsToken); + when(runAs.buildRunAs(eq(token), any(MethodInvocation.class), any(List.class))).thenReturn(runAsToken); when(joinPoint.proceed()).thenThrow(new RuntimeException()); try { @@ -211,4 +213,5 @@ public class AspectJMethodSecurityInterceptorTests { assertThat(SecurityContextHolder.getContext()).isSameAs(ctx); assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(token); } + } diff --git a/core/src/test/java/org/springframework/security/access/intercept/method/MapBasedMethodSecurityMetadataSourceTests.java b/core/src/test/java/org/springframework/security/access/intercept/method/MapBasedMethodSecurityMetadataSourceTests.java index 89ae4f9822..90fd117663 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/method/MapBasedMethodSecurityMetadataSourceTests.java +++ b/core/src/test/java/org/springframework/security/access/intercept/method/MapBasedMethodSecurityMetadataSourceTests.java @@ -33,10 +33,15 @@ import org.springframework.security.access.method.MapBasedMethodSecurityMetadata * @since 2.0.4 */ public class MapBasedMethodSecurityMetadataSourceTests { + private final List ROLE_A = SecurityConfig.createList("ROLE_A"); + private final List ROLE_B = SecurityConfig.createList("ROLE_B"); + private MapBasedMethodSecurityMetadataSource mds; + private Method someMethodString; + private Method someMethodInteger; @Before @@ -64,10 +69,13 @@ public class MapBasedMethodSecurityMetadataSourceTests { @SuppressWarnings("unused") private class MockService { + public void someMethod(String s) { } public void someMethod(Integer i) { } + } + } diff --git a/core/src/test/java/org/springframework/security/access/intercept/method/MethodInvocationPrivilegeEvaluatorTests.java b/core/src/test/java/org/springframework/security/access/intercept/method/MethodInvocationPrivilegeEvaluatorTests.java index 80b6b3ac4d..bc7db2355b 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/method/MethodInvocationPrivilegeEvaluatorTests.java +++ b/core/src/test/java/org/springframework/security/access/intercept/method/MethodInvocationPrivilegeEvaluatorTests.java @@ -47,10 +47,15 @@ import org.springframework.security.util.MethodInvocationUtils; * @author Ben Alex */ public class MethodInvocationPrivilegeEvaluatorTests { + private TestingAuthenticationToken token; + private MethodSecurityInterceptor interceptor; + private AccessDecisionManager adm; + private MethodSecurityMetadataSource mds; + private final List role = SecurityConfig.createList("ROLE_IGNORED"); // ~ Methods @@ -72,8 +77,7 @@ public class MethodInvocationPrivilegeEvaluatorTests { @Test public void allowsAccessUsingCreate() throws Exception { Object object = new TargetObject(); - final MethodInvocation mi = MethodInvocationUtils.create(object, "makeLowerCase", - "foobar"); + final MethodInvocation mi = MethodInvocationUtils.create(object, "makeLowerCase", "foobar"); MethodInvocationPrivilegeEvaluator mipe = new MethodInvocationPrivilegeEvaluator(); when(mds.getAttributes(mi)).thenReturn(role); @@ -86,9 +90,8 @@ public class MethodInvocationPrivilegeEvaluatorTests { @Test public void allowsAccessUsingCreateFromClass() { - final MethodInvocation mi = MethodInvocationUtils.createFromClass( - new OtherTargetObject(), ITargetObject.class, "makeLowerCase", - new Class[] { String.class }, new Object[] { "Hello world" }); + final MethodInvocation mi = MethodInvocationUtils.createFromClass(new OtherTargetObject(), ITargetObject.class, + "makeLowerCase", new Class[] { String.class }, new Object[] { "Hello world" }); MethodInvocationPrivilegeEvaluator mipe = new MethodInvocationPrivilegeEvaluator(); mipe.setSecurityInterceptor(interceptor); when(mds.getAttributes(mi)).thenReturn(role); @@ -99,8 +102,7 @@ public class MethodInvocationPrivilegeEvaluatorTests { @Test public void declinesAccessUsingCreate() { Object object = new TargetObject(); - final MethodInvocation mi = MethodInvocationUtils.create(object, "makeLowerCase", - "foobar"); + final MethodInvocation mi = MethodInvocationUtils.create(object, "makeLowerCase", "foobar"); MethodInvocationPrivilegeEvaluator mipe = new MethodInvocationPrivilegeEvaluator(); mipe.setSecurityInterceptor(interceptor); when(mds.getAttributes(mi)).thenReturn(role); @@ -111,9 +113,8 @@ public class MethodInvocationPrivilegeEvaluatorTests { @Test public void declinesAccessUsingCreateFromClass() { - final MethodInvocation mi = MethodInvocationUtils.createFromClass( - new OtherTargetObject(), ITargetObject.class, "makeLowerCase", - new Class[] { String.class }, new Object[] { "helloWorld" }); + final MethodInvocation mi = MethodInvocationUtils.createFromClass(new OtherTargetObject(), ITargetObject.class, + "makeLowerCase", new Class[] { String.class }, new Object[] { "helloWorld" }); MethodInvocationPrivilegeEvaluator mipe = new MethodInvocationPrivilegeEvaluator(); mipe.setSecurityInterceptor(interceptor); @@ -122,4 +123,5 @@ public class MethodInvocationPrivilegeEvaluatorTests { assertThat(mipe.isAllowed(mi, token)).isFalse(); } + } diff --git a/core/src/test/java/org/springframework/security/access/intercept/method/MockMethodInvocation.java b/core/src/test/java/org/springframework/security/access/intercept/method/MockMethodInvocation.java index 8c295000ff..888ff6a2af 100644 --- a/core/src/test/java/org/springframework/security/access/intercept/method/MockMethodInvocation.java +++ b/core/src/test/java/org/springframework/security/access/intercept/method/MockMethodInvocation.java @@ -22,18 +22,21 @@ import java.lang.reflect.Method; @SuppressWarnings("unchecked") public class MockMethodInvocation implements MethodInvocation { + private Method method; + private Object targetObject; + private Object[] arguments = new Object[0]; public MockMethodInvocation(Object targetObject, Class clazz, String methodName, Class[] parameterTypes, - Object[] arguments) throws NoSuchMethodException { + Object[] arguments) throws NoSuchMethodException { this(targetObject, clazz, methodName, parameterTypes); this.arguments = arguments; } - public MockMethodInvocation(Object targetObject, Class clazz, String methodName, - Class... parameterTypes) throws NoSuchMethodException { + public MockMethodInvocation(Object targetObject, Class clazz, String methodName, Class... parameterTypes) + throws NoSuchMethodException { this.method = clazz.getMethod(methodName, parameterTypes); this.targetObject = targetObject; } @@ -57,4 +60,5 @@ public class MockMethodInvocation implements MethodInvocation { public Object proceed() { return null; } + } diff --git a/core/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java b/core/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java index b16f71b8bd..8922194607 100644 --- a/core/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java +++ b/core/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java @@ -32,20 +32,20 @@ import java.util.*; */ @SuppressWarnings({ "unchecked" }) public class DelegatingMethodSecurityMetadataSourceTests { + DelegatingMethodSecurityMetadataSource mds; @Test public void returnsEmptyListIfDelegateReturnsNull() throws Exception { List sources = new ArrayList(); MethodSecurityMetadataSource delegate = mock(MethodSecurityMetadataSource.class); - when(delegate.getAttributes(ArgumentMatchers. any(), ArgumentMatchers.any(Class.class))) + when(delegate.getAttributes(ArgumentMatchers.any(), ArgumentMatchers.any(Class.class))) .thenReturn(null); sources.add(delegate); mds = new DelegatingMethodSecurityMetadataSource(sources); assertThat(mds.getMethodSecurityMetadataSources()).isSameAs(sources); assertThat(mds.getAllConfigAttributes().isEmpty()).isTrue(); - MethodInvocation mi = new SimpleMethodInvocation(null, - String.class.getMethod("toString")); + MethodInvocation mi = new SimpleMethodInvocation(null, String.class.getMethod("toString")); assertThat(mds.getAttributes(mi)).isEqualTo(Collections.emptyList()); // Exercise the cached case assertThat(mds.getAttributes(mi)).isEqualTo(Collections.emptyList()); @@ -67,8 +67,7 @@ public class DelegatingMethodSecurityMetadataSourceTests { assertThat(mds.getAttributes(mi)).isSameAs(attributes); // Exercise the cached case assertThat(mds.getAttributes(mi)).isSameAs(attributes); - assertThat(mds.getAttributes( - new SimpleMethodInvocation(null, String.class.getMethod("length")))).isEmpty(); + assertThat(mds.getAttributes(new SimpleMethodInvocation(null, String.class.getMethod("length")))).isEmpty(); } } diff --git a/core/src/test/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoterTests.java b/core/src/test/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoterTests.java index bb6f951680..25f7956a27 100644 --- a/core/src/test/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoterTests.java +++ b/core/src/test/java/org/springframework/security/access/prepost/PreInvocationAuthorizationAdviceVoterTests.java @@ -28,8 +28,10 @@ import org.springframework.security.access.intercept.aspectj.MethodInvocationAda @RunWith(MockitoJUnitRunner.class) public class PreInvocationAuthorizationAdviceVoterTests { + @Mock private PreInvocationAuthorizationAdvice authorizationAdvice; + private PreInvocationAuthorizationAdviceVoter voter; @Before @@ -52,4 +54,5 @@ public class PreInvocationAuthorizationAdviceVoterTests { public void supportsMethodInvocationAdapter() { assertThat(voter.supports(MethodInvocationAdapter.class)).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/access/vote/AbstractAccessDecisionManagerTests.java b/core/src/test/java/org/springframework/security/access/vote/AbstractAccessDecisionManagerTests.java index e3fb32d6bb..fbf69e25c3 100644 --- a/core/src/test/java/org/springframework/security/access/vote/AbstractAccessDecisionManagerTests.java +++ b/core/src/test/java/org/springframework/security/access/vote/AbstractAccessDecisionManagerTests.java @@ -136,14 +136,13 @@ public class AbstractAccessDecisionManagerTests { private class MockDecisionManagerImpl extends AbstractAccessDecisionManager { - protected MockDecisionManagerImpl( - List> decisionVoters) { + protected MockDecisionManagerImpl(List> decisionVoters) { super(decisionVoters); } - public void decide(Authentication authentication, Object object, - Collection configAttributes) { + public void decide(Authentication authentication, Object object, Collection configAttributes) { } + } private class MockStringOnlyVoter implements AccessDecisionVoter { @@ -156,9 +155,10 @@ public class AbstractAccessDecisionManagerTests { throw new UnsupportedOperationException("mock method not implemented"); } - public int vote(Authentication authentication, Object object, - Collection attributes) { + public int vote(Authentication authentication, Object object, Collection attributes) { throw new UnsupportedOperationException("mock method not implemented"); } + } + } diff --git a/core/src/test/java/org/springframework/security/access/vote/AbstractAclVoterTests.java b/core/src/test/java/org/springframework/security/access/vote/AbstractAclVoterTests.java index 4f66e67244..c9474d7c6d 100644 --- a/core/src/test/java/org/springframework/security/access/vote/AbstractAclVoterTests.java +++ b/core/src/test/java/org/springframework/security/access/vote/AbstractAclVoterTests.java @@ -26,10 +26,10 @@ import org.springframework.security.core.Authentication; import org.springframework.security.util.MethodInvocationUtils; /** - * * @author Luke Taylor */ public class AbstractAclVoterTests { + private AbstractAclVoter voter = new AbstractAclVoter() { public boolean supports(ConfigAttribute attribute) { return false; @@ -50,21 +50,21 @@ public class AbstractAclVoterTests { @Test public void expectedDomainObjectArgumentIsReturnedFromMethodInvocation() { voter.setProcessDomainObjectClass(String.class); - MethodInvocation mi = MethodInvocationUtils.create(new TestClass(), - "methodTakingAString", "The Argument"); + MethodInvocation mi = MethodInvocationUtils.create(new TestClass(), "methodTakingAString", "The Argument"); assertThat(voter.getDomainObjectInstance(mi)).isEqualTo("The Argument"); } @Test public void correctArgumentIsSelectedFromMultipleArgs() { voter.setProcessDomainObjectClass(String.class); - MethodInvocation mi = MethodInvocationUtils.create(new TestClass(), - "methodTakingAListAndAString", new ArrayList<>(), "The Argument"); + MethodInvocation mi = MethodInvocationUtils.create(new TestClass(), "methodTakingAListAndAString", + new ArrayList<>(), "The Argument"); assertThat(voter.getDomainObjectInstance(mi)).isEqualTo("The Argument"); } @SuppressWarnings("unused") private static class TestClass { + public void methodTakingAString(String arg) { } @@ -73,6 +73,7 @@ public class AbstractAclVoterTests { public void methodTakingAListAndAString(ArrayList arg1, String arg2) { } + } } diff --git a/core/src/test/java/org/springframework/security/access/vote/AffirmativeBasedTests.java b/core/src/test/java/org/springframework/security/access/vote/AffirmativeBasedTests.java index bf237fb51b..4e75b038e0 100644 --- a/core/src/test/java/org/springframework/security/access/vote/AffirmativeBasedTests.java +++ b/core/src/test/java/org/springframework/security/access/vote/AffirmativeBasedTests.java @@ -38,12 +38,17 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ public class AffirmativeBasedTests { + private final List attrs = new ArrayList<>(); - private final Authentication user = new TestingAuthenticationToken("somebody", - "password", "ROLE_1", "ROLE_2"); + + private final Authentication user = new TestingAuthenticationToken("somebody", "password", "ROLE_1", "ROLE_2"); + private AffirmativeBased mgr; + private AccessDecisionVoter grant; + private AccessDecisionVoter abstain; + private AccessDecisionVoter deny; @Before @@ -63,40 +68,34 @@ public class AffirmativeBasedTests { } @Test - public void oneAffirmativeVoteOneDenyVoteOneAbstainVoteGrantsAccess() - throws Exception { + public void oneAffirmativeVoteOneDenyVoteOneAbstainVoteGrantsAccess() throws Exception { - mgr = new AffirmativeBased(Arrays.> asList( - grant, deny, abstain)); + mgr = new AffirmativeBased(Arrays.>asList(grant, deny, abstain)); mgr.afterPropertiesSet(); mgr.decide(user, new Object(), attrs); } @Test public void oneDenyVoteOneAbstainVoteOneAffirmativeVoteGrantsAccess() { - mgr = new AffirmativeBased(Arrays.> asList( - deny, abstain, grant)); + mgr = new AffirmativeBased(Arrays.>asList(deny, abstain, grant)); mgr.decide(user, new Object(), attrs); } @Test public void oneAffirmativeVoteTwoAbstainVotesGrantsAccess() { - mgr = new AffirmativeBased(Arrays.> asList( - grant, abstain, abstain)); + mgr = new AffirmativeBased(Arrays.>asList(grant, abstain, abstain)); mgr.decide(user, new Object(), attrs); } @Test(expected = AccessDeniedException.class) public void oneDenyVoteTwoAbstainVotesDeniesAccess() { - mgr = new AffirmativeBased(Arrays.> asList( - deny, abstain, abstain)); + mgr = new AffirmativeBased(Arrays.>asList(deny, abstain, abstain)); mgr.decide(user, new Object(), attrs); } @Test(expected = AccessDeniedException.class) public void onlyAbstainVotesDeniesAccessWithDefault() { - mgr = new AffirmativeBased(Arrays.> asList( - abstain, abstain, abstain)); + mgr = new AffirmativeBased(Arrays.>asList(abstain, abstain, abstain)); assertThat(!mgr.isAllowIfAllAbstainDecisions()).isTrue(); // check default mgr.decide(user, new Object(), attrs); @@ -104,11 +103,11 @@ public class AffirmativeBasedTests { @Test public void testThreeAbstainVotesGrantsAccessIfAllowIfAllAbstainDecisionsIsSet() { - mgr = new AffirmativeBased(Arrays.> asList( - abstain, abstain, abstain)); + mgr = new AffirmativeBased(Arrays.>asList(abstain, abstain, abstain)); mgr.setAllowIfAllAbstainDecisions(true); assertThat(mgr.isAllowIfAllAbstainDecisions()).isTrue(); // check changed mgr.decide(user, new Object(), attrs); } + } diff --git a/core/src/test/java/org/springframework/security/access/vote/AuthenticatedVoterTests.java b/core/src/test/java/org/springframework/security/access/vote/AuthenticatedVoterTests.java index 8a8d3f4043..6d87a4a028 100644 --- a/core/src/test/java/org/springframework/security/access/vote/AuthenticatedVoterTests.java +++ b/core/src/test/java/org/springframework/security/access/vote/AuthenticatedVoterTests.java @@ -39,8 +39,7 @@ import org.springframework.security.core.authority.AuthorityUtils; public class AuthenticatedVoterTests { private Authentication createAnonymous() { - return new AnonymousAuthenticationToken("ignored", "ignored", - AuthorityUtils.createAuthorityList("ignored")); + return new AnonymousAuthenticationToken("ignored", "ignored", AuthorityUtils.createAuthorityList("ignored")); } private Authentication createFullyAuthenticated() { @@ -49,47 +48,34 @@ public class AuthenticatedVoterTests { } private Authentication createRememberMe() { - return new RememberMeAuthenticationToken("ignored", "ignored", - AuthorityUtils.createAuthorityList("ignored")); + return new RememberMeAuthenticationToken("ignored", "ignored", AuthorityUtils.createAuthorityList("ignored")); } @Test public void testAnonymousWorks() { AuthenticatedVoter voter = new AuthenticatedVoter(); - List def = SecurityConfig.createList( - AuthenticatedVoter.IS_AUTHENTICATED_ANONYMOUSLY); - assertThat(AccessDecisionVoter.ACCESS_GRANTED).isEqualTo( - voter.vote(createAnonymous(), null, def)); - assertThat(AccessDecisionVoter.ACCESS_GRANTED).isEqualTo( - voter.vote(createRememberMe(), null, def)); - assertThat(AccessDecisionVoter.ACCESS_GRANTED).isEqualTo( - voter.vote(createFullyAuthenticated(), null, def)); + List def = SecurityConfig.createList(AuthenticatedVoter.IS_AUTHENTICATED_ANONYMOUSLY); + assertThat(AccessDecisionVoter.ACCESS_GRANTED).isEqualTo(voter.vote(createAnonymous(), null, def)); + assertThat(AccessDecisionVoter.ACCESS_GRANTED).isEqualTo(voter.vote(createRememberMe(), null, def)); + assertThat(AccessDecisionVoter.ACCESS_GRANTED).isEqualTo(voter.vote(createFullyAuthenticated(), null, def)); } @Test public void testFullyWorks() { AuthenticatedVoter voter = new AuthenticatedVoter(); - List def = SecurityConfig.createList( - AuthenticatedVoter.IS_AUTHENTICATED_FULLY); - assertThat(AccessDecisionVoter.ACCESS_DENIED).isEqualTo( - voter.vote(createAnonymous(), null, def)); - assertThat(AccessDecisionVoter.ACCESS_DENIED).isEqualTo( - voter.vote(createRememberMe(), null, def)); - assertThat(AccessDecisionVoter.ACCESS_GRANTED).isEqualTo( - voter.vote(createFullyAuthenticated(), null, def)); + List def = SecurityConfig.createList(AuthenticatedVoter.IS_AUTHENTICATED_FULLY); + assertThat(AccessDecisionVoter.ACCESS_DENIED).isEqualTo(voter.vote(createAnonymous(), null, def)); + assertThat(AccessDecisionVoter.ACCESS_DENIED).isEqualTo(voter.vote(createRememberMe(), null, def)); + assertThat(AccessDecisionVoter.ACCESS_GRANTED).isEqualTo(voter.vote(createFullyAuthenticated(), null, def)); } @Test public void testRememberMeWorks() { AuthenticatedVoter voter = new AuthenticatedVoter(); - List def = SecurityConfig.createList( - AuthenticatedVoter.IS_AUTHENTICATED_REMEMBERED); - assertThat(AccessDecisionVoter.ACCESS_DENIED).isEqualTo( - voter.vote(createAnonymous(), null, def)); - assertThat(AccessDecisionVoter.ACCESS_GRANTED).isEqualTo( - voter.vote(createRememberMe(), null, def)); - assertThat(AccessDecisionVoter.ACCESS_GRANTED).isEqualTo( - voter.vote(createFullyAuthenticated(), null, def)); + List def = SecurityConfig.createList(AuthenticatedVoter.IS_AUTHENTICATED_REMEMBERED); + assertThat(AccessDecisionVoter.ACCESS_DENIED).isEqualTo(voter.vote(createAnonymous(), null, def)); + assertThat(AccessDecisionVoter.ACCESS_GRANTED).isEqualTo(voter.vote(createRememberMe(), null, def)); + assertThat(AccessDecisionVoter.ACCESS_GRANTED).isEqualTo(voter.vote(createFullyAuthenticated(), null, def)); } @Test @@ -109,12 +95,10 @@ public class AuthenticatedVoterTests { public void testSupports() { AuthenticatedVoter voter = new AuthenticatedVoter(); assertThat(voter.supports(String.class)).isTrue(); - assertThat(voter.supports(new SecurityConfig( - AuthenticatedVoter.IS_AUTHENTICATED_ANONYMOUSLY))).isTrue(); - assertThat(voter.supports( - new SecurityConfig(AuthenticatedVoter.IS_AUTHENTICATED_FULLY))).isTrue(); - assertThat(voter.supports(new SecurityConfig( - AuthenticatedVoter.IS_AUTHENTICATED_REMEMBERED))).isTrue(); + assertThat(voter.supports(new SecurityConfig(AuthenticatedVoter.IS_AUTHENTICATED_ANONYMOUSLY))).isTrue(); + assertThat(voter.supports(new SecurityConfig(AuthenticatedVoter.IS_AUTHENTICATED_FULLY))).isTrue(); + assertThat(voter.supports(new SecurityConfig(AuthenticatedVoter.IS_AUTHENTICATED_REMEMBERED))).isTrue(); assertThat(voter.supports(new SecurityConfig("FOO"))).isFalse(); } + } diff --git a/core/src/test/java/org/springframework/security/access/vote/ConsensusBasedTests.java b/core/src/test/java/org/springframework/security/access/vote/ConsensusBasedTests.java index e8fca78fc2..b2826d028b 100644 --- a/core/src/test/java/org/springframework/security/access/vote/ConsensusBasedTests.java +++ b/core/src/test/java/org/springframework/security/access/vote/ConsensusBasedTests.java @@ -41,8 +41,7 @@ public class ConsensusBasedTests { mgr.setAllowIfEqualGrantedDeniedDecisions(false); assertThat(!mgr.isAllowIfEqualGrantedDeniedDecisions()).isTrue(); // check changed - List config = SecurityConfig.createList("ROLE_1", - "DENY_FOR_SURE"); + List config = SecurityConfig.createList("ROLE_1", "DENY_FOR_SURE"); mgr.decide(auth, new Object(), config); } @@ -54,8 +53,7 @@ public class ConsensusBasedTests { assertThat(mgr.isAllowIfEqualGrantedDeniedDecisions()).isTrue(); // check default - List config = SecurityConfig.createList("ROLE_1", - "DENY_FOR_SURE"); + List config = SecurityConfig.createList("ROLE_1", "DENY_FOR_SURE"); mgr.decide(auth, new Object(), config); @@ -122,4 +120,5 @@ public class ConsensusBasedTests { private TestingAuthenticationToken makeTestToken() { return new TestingAuthenticationToken("somebody", "password", "ROLE_1", "ROLE_2"); } + } diff --git a/core/src/test/java/org/springframework/security/access/vote/DenyAgainVoter.java b/core/src/test/java/org/springframework/security/access/vote/DenyAgainVoter.java index e48e0548f1..c51074d0f0 100644 --- a/core/src/test/java/org/springframework/security/access/vote/DenyAgainVoter.java +++ b/core/src/test/java/org/springframework/security/access/vote/DenyAgainVoter.java @@ -34,6 +34,7 @@ import java.util.Iterator; * @author Ben Alex */ public class DenyAgainVoter implements AccessDecisionVoter { + // ~ Methods // ======================================================================================================== @@ -50,8 +51,7 @@ public class DenyAgainVoter implements AccessDecisionVoter { return true; } - public int vote(Authentication authentication, Object object, - Collection attributes) { + public int vote(Authentication authentication, Object object, Collection attributes) { Iterator iter = attributes.iterator(); while (iter.hasNext()) { diff --git a/core/src/test/java/org/springframework/security/access/vote/DenyVoter.java b/core/src/test/java/org/springframework/security/access/vote/DenyVoter.java index 2db4297778..d30ba67749 100644 --- a/core/src/test/java/org/springframework/security/access/vote/DenyVoter.java +++ b/core/src/test/java/org/springframework/security/access/vote/DenyVoter.java @@ -36,6 +36,7 @@ import java.util.Iterator; * @author Ben Alex */ public class DenyVoter implements AccessDecisionVoter { + // ~ Methods // ======================================================================================================== @@ -52,8 +53,7 @@ public class DenyVoter implements AccessDecisionVoter { return true; } - public int vote(Authentication authentication, Object object, - Collection attributes) { + public int vote(Authentication authentication, Object object, Collection attributes) { Iterator iter = attributes.iterator(); while (iter.hasNext()) { @@ -66,4 +66,5 @@ public class DenyVoter implements AccessDecisionVoter { return ACCESS_ABSTAIN; } + } diff --git a/core/src/test/java/org/springframework/security/access/vote/RoleHierarchyVoterTests.java b/core/src/test/java/org/springframework/security/access/vote/RoleHierarchyVoterTests.java index 681c61ff12..00264e5613 100644 --- a/core/src/test/java/org/springframework/security/access/vote/RoleHierarchyVoterTests.java +++ b/core/src/test/java/org/springframework/security/access/vote/RoleHierarchyVoterTests.java @@ -31,10 +31,11 @@ public class RoleHierarchyVoterTests { roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B"); // User has role A, role B is required - TestingAuthenticationToken auth = new TestingAuthenticationToken("user", - "password", "ROLE_A"); + TestingAuthenticationToken auth = new TestingAuthenticationToken("user", "password", "ROLE_A"); RoleHierarchyVoter voter = new RoleHierarchyVoter(roleHierarchyImpl); - assertThat(voter.vote(auth, new Object(), SecurityConfig.createList("ROLE_B"))).isEqualTo(RoleHierarchyVoter.ACCESS_GRANTED); + assertThat(voter.vote(auth, new Object(), SecurityConfig.createList("ROLE_B"))) + .isEqualTo(RoleHierarchyVoter.ACCESS_GRANTED); } + } diff --git a/core/src/test/java/org/springframework/security/access/vote/RoleVoterTests.java b/core/src/test/java/org/springframework/security/access/vote/RoleVoterTests.java index 741a7bcc7a..433766bd69 100644 --- a/core/src/test/java/org/springframework/security/access/vote/RoleVoterTests.java +++ b/core/src/test/java/org/springframework/security/access/vote/RoleVoterTests.java @@ -24,17 +24,18 @@ import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.core.Authentication; /** - * * @author Luke Taylor */ public class RoleVoterTests { + @Test public void oneMatchingAttributeGrantsAccess() { RoleVoter voter = new RoleVoter(); voter.setRolePrefix(""); Authentication userAB = new TestingAuthenticationToken("user", "pass", "A", "B"); // Vote on attribute list that has two attributes A and C (i.e. only one matching) - assertThat(voter.vote(userAB, this, SecurityConfig.createList("A", "C"))).isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); + assertThat(voter.vote(userAB, this, SecurityConfig.createList("A", "C"))) + .isEqualTo(AccessDecisionVoter.ACCESS_GRANTED); } // SEC-3128 @@ -43,6 +44,8 @@ public class RoleVoterTests { RoleVoter voter = new RoleVoter(); voter.setRolePrefix(""); Authentication notAuthenitcated = null; - assertThat(voter.vote(notAuthenitcated, this, SecurityConfig.createList("A"))).isEqualTo(AccessDecisionVoter.ACCESS_DENIED); + assertThat(voter.vote(notAuthenitcated, this, SecurityConfig.createList("A"))) + .isEqualTo(AccessDecisionVoter.ACCESS_DENIED); } + } diff --git a/core/src/test/java/org/springframework/security/access/vote/SomeDomainObject.java b/core/src/test/java/org/springframework/security/access/vote/SomeDomainObject.java index ab2b8f0c67..ab147f7399 100644 --- a/core/src/test/java/org/springframework/security/access/vote/SomeDomainObject.java +++ b/core/src/test/java/org/springframework/security/access/vote/SomeDomainObject.java @@ -22,6 +22,7 @@ package org.springframework.security.access.vote; * @author Ben Alex */ public class SomeDomainObject { + // ~ Instance fields // ================================================================================================ @@ -40,4 +41,5 @@ public class SomeDomainObject { public String getParent() { return "parentOf" + identity; } + } diff --git a/core/src/test/java/org/springframework/security/access/vote/SomeDomainObjectManager.java b/core/src/test/java/org/springframework/security/access/vote/SomeDomainObjectManager.java index f7431ff6a4..e8b4547c4e 100644 --- a/core/src/test/java/org/springframework/security/access/vote/SomeDomainObjectManager.java +++ b/core/src/test/java/org/springframework/security/access/vote/SomeDomainObjectManager.java @@ -23,9 +23,11 @@ package org.springframework.security.access.vote; * @author Ben Alex */ public class SomeDomainObjectManager { + // ~ Methods // ======================================================================================================== public void someServiceMethod(SomeDomainObject someDomainObject) { } + } diff --git a/core/src/test/java/org/springframework/security/access/vote/UnanimousBasedTests.java b/core/src/test/java/org/springframework/security/access/vote/UnanimousBasedTests.java index a00a611850..93e3112e37 100644 --- a/core/src/test/java/org/springframework/security/access/vote/UnanimousBasedTests.java +++ b/core/src/test/java/org/springframework/security/access/vote/UnanimousBasedTests.java @@ -68,8 +68,7 @@ public class UnanimousBasedTests { } private TestingAuthenticationToken makeTestTokenWithFooBarPrefix() { - return new TestingAuthenticationToken("somebody", "password", "FOOBAR_1", - "FOOBAR_2"); + return new TestingAuthenticationToken("somebody", "password", "FOOBAR_1", "FOOBAR_2"); } @Test @@ -77,8 +76,7 @@ public class UnanimousBasedTests { TestingAuthenticationToken auth = makeTestToken(); UnanimousBased mgr = makeDecisionManager(); - List config = SecurityConfig.createList( - new String[] { "ROLE_1", "DENY_FOR_SURE" }); + List config = SecurityConfig.createList(new String[] { "ROLE_1", "DENY_FOR_SURE" }); try { mgr.decide(auth, new Object(), config); @@ -118,8 +116,7 @@ public class UnanimousBasedTests { TestingAuthenticationToken auth = makeTestTokenWithFooBarPrefix(); UnanimousBased mgr = makeDecisionManagerWithFooBarPrefix(); - List config = SecurityConfig.createList( - new String[] { "FOOBAR_1", "FOOBAR_2" }); + List config = SecurityConfig.createList(new String[] { "FOOBAR_1", "FOOBAR_2" }); mgr.decide(auth, new Object(), config); } @@ -158,9 +155,9 @@ public class UnanimousBasedTests { TestingAuthenticationToken auth = makeTestToken(); UnanimousBased mgr = makeDecisionManager(); - List config = SecurityConfig.createList( - new String[] { "ROLE_1", "ROLE_2" }); + List config = SecurityConfig.createList(new String[] { "ROLE_1", "ROLE_2" }); mgr.decide(auth, new Object(), config); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/AbstractAuthenticationTokenTests.java b/core/src/test/java/org/springframework/security/authentication/AbstractAuthenticationTokenTests.java index 7f5638b31e..72c63c6aa9 100644 --- a/core/src/test/java/org/springframework/security/authentication/AbstractAuthenticationTokenTests.java +++ b/core/src/test/java/org/springframework/security/authentication/AbstractAuthenticationTokenTests.java @@ -33,6 +33,7 @@ import java.util.*; * @author Ben Alex */ public class AbstractAuthenticationTokenTests { + // ~ Instance fields // ================================================================================================ @@ -48,10 +49,8 @@ public class AbstractAuthenticationTokenTests { @Test(expected = UnsupportedOperationException.class) public void testAuthoritiesAreImmutable() { - MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", - authorities); - List gotAuthorities = (List) token - .getAuthorities(); + MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", authorities); + List gotAuthorities = (List) token.getAuthorities(); assertThat(gotAuthorities).isNotSameAs(authorities); gotAuthorities.set(0, new SimpleGrantedAuthority("ROLE_SUPER_USER")); @@ -59,8 +58,7 @@ public class AbstractAuthenticationTokenTests { @Test public void testGetters() { - MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", - authorities); + MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", authorities); assertThat(token.getPrincipal()).isEqualTo("Test"); assertThat(token.getCredentials()).isEqualTo("Password"); assertThat(token.getName()).isEqualTo("Test"); @@ -68,12 +66,9 @@ public class AbstractAuthenticationTokenTests { @Test public void testHashCode() { - MockAuthenticationImpl token1 = new MockAuthenticationImpl("Test", "Password", - authorities); - MockAuthenticationImpl token2 = new MockAuthenticationImpl("Test", "Password", - authorities); - MockAuthenticationImpl token3 = new MockAuthenticationImpl(null, null, - AuthorityUtils.NO_AUTHORITIES); + MockAuthenticationImpl token1 = new MockAuthenticationImpl("Test", "Password", authorities); + MockAuthenticationImpl token2 = new MockAuthenticationImpl("Test", "Password", authorities); + MockAuthenticationImpl token3 = new MockAuthenticationImpl(null, null, AuthorityUtils.NO_AUTHORITIES); assertThat(token2.hashCode()).isEqualTo(token1.hashCode()); assertThat(token1.hashCode() != token3.hashCode()).isTrue(); @@ -84,18 +79,14 @@ public class AbstractAuthenticationTokenTests { @Test public void testObjectsEquals() { - MockAuthenticationImpl token1 = new MockAuthenticationImpl("Test", "Password", - authorities); - MockAuthenticationImpl token2 = new MockAuthenticationImpl("Test", "Password", - authorities); + MockAuthenticationImpl token1 = new MockAuthenticationImpl("Test", "Password", authorities); + MockAuthenticationImpl token2 = new MockAuthenticationImpl("Test", "Password", authorities); assertThat(token2).isEqualTo(token1); - MockAuthenticationImpl token3 = new MockAuthenticationImpl("Test", - "Password_Changed", authorities); + MockAuthenticationImpl token3 = new MockAuthenticationImpl("Test", "Password_Changed", authorities); assertThat(!token1.equals(token3)).isTrue(); - MockAuthenticationImpl token4 = new MockAuthenticationImpl("Test_Changed", - "Password", authorities); + MockAuthenticationImpl token4 = new MockAuthenticationImpl("Test_Changed", "Password", authorities); assertThat(!token1.equals(token4)).isTrue(); MockAuthenticationImpl token5 = new MockAuthenticationImpl("Test", "Password", @@ -106,8 +97,7 @@ public class AbstractAuthenticationTokenTests { AuthorityUtils.createAuthorityList("ROLE_ONE")); assertThat(!token1.equals(token6)).isTrue(); - MockAuthenticationImpl token7 = new MockAuthenticationImpl("Test", "Password", - null); + MockAuthenticationImpl token7 = new MockAuthenticationImpl("Test", "Password", null); assertThat(!token1.equals(token7)).isTrue(); assertThat(!token7.equals(token1)).isTrue(); @@ -116,8 +106,7 @@ public class AbstractAuthenticationTokenTests { @Test public void testSetAuthenticated() { - MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", - authorities); + MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", authorities); assertThat(!token.isAuthenticated()).isTrue(); token.setAuthenticated(true); assertThat(token.isAuthenticated()).isTrue(); @@ -125,15 +114,13 @@ public class AbstractAuthenticationTokenTests { @Test public void testToStringWithAuthorities() { - MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", - authorities); + MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", authorities); assertThat(token.toString().lastIndexOf("ROLE_TWO") != -1).isTrue(); } @Test public void testToStringWithNullAuthorities() { - MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", - null); + MockAuthenticationImpl token = new MockAuthenticationImpl("Test", "Password", null); assertThat(token.toString().lastIndexOf("Not granted any authorities") != -1).isTrue(); } @@ -153,7 +140,9 @@ public class AbstractAuthenticationTokenTests { // ================================================================================================== private class MockAuthenticationImpl extends AbstractAuthenticationToken { + private Object credentials; + private Object principal; MockAuthenticationImpl(Object principal, Object credentials, List authorities) { @@ -169,5 +158,7 @@ public class AbstractAuthenticationTokenTests { public Object getPrincipal() { return this.principal; } + } + } diff --git a/core/src/test/java/org/springframework/security/authentication/AuthenticationTrustResolverImplTests.java b/core/src/test/java/org/springframework/security/authentication/AuthenticationTrustResolverImplTests.java index fbc05e04ac..963332b501 100644 --- a/core/src/test/java/org/springframework/security/authentication/AuthenticationTrustResolverImplTests.java +++ b/core/src/test/java/org/springframework/security/authentication/AuthenticationTrustResolverImplTests.java @@ -34,35 +34,36 @@ public class AuthenticationTrustResolverImplTests { @Test public void testCorrectOperationIsAnonymous() { AuthenticationTrustResolverImpl trustResolver = new AuthenticationTrustResolverImpl(); - assertThat(trustResolver.isAnonymous(new AnonymousAuthenticationToken("ignored", - "ignored", AuthorityUtils.createAuthorityList("ignored")))).isTrue(); - assertThat(trustResolver.isAnonymous(new TestingAuthenticationToken("ignored", - "ignored", AuthorityUtils.createAuthorityList("ignored")))).isFalse(); + assertThat(trustResolver.isAnonymous( + new AnonymousAuthenticationToken("ignored", "ignored", AuthorityUtils.createAuthorityList("ignored")))) + .isTrue(); + assertThat(trustResolver.isAnonymous( + new TestingAuthenticationToken("ignored", "ignored", AuthorityUtils.createAuthorityList("ignored")))) + .isFalse(); } @Test public void testCorrectOperationIsRememberMe() { AuthenticationTrustResolverImpl trustResolver = new AuthenticationTrustResolverImpl(); - assertThat(trustResolver.isRememberMe(new RememberMeAuthenticationToken("ignored", - "ignored", AuthorityUtils.createAuthorityList("ignored")))).isTrue(); - assertThat(trustResolver.isAnonymous(new TestingAuthenticationToken("ignored", - "ignored", AuthorityUtils.createAuthorityList("ignored")))).isFalse(); + assertThat(trustResolver.isRememberMe( + new RememberMeAuthenticationToken("ignored", "ignored", AuthorityUtils.createAuthorityList("ignored")))) + .isTrue(); + assertThat(trustResolver.isAnonymous( + new TestingAuthenticationToken("ignored", "ignored", AuthorityUtils.createAuthorityList("ignored")))) + .isFalse(); } @Test public void testGettersSetters() { AuthenticationTrustResolverImpl trustResolver = new AuthenticationTrustResolverImpl(); - assertThat(AnonymousAuthenticationToken.class).isEqualTo( - trustResolver.getAnonymousClass()); + assertThat(AnonymousAuthenticationToken.class).isEqualTo(trustResolver.getAnonymousClass()); trustResolver.setAnonymousClass(TestingAuthenticationToken.class); - assertThat(trustResolver.getAnonymousClass()).isEqualTo( - TestingAuthenticationToken.class); + assertThat(trustResolver.getAnonymousClass()).isEqualTo(TestingAuthenticationToken.class); - assertThat(RememberMeAuthenticationToken.class).isEqualTo( - trustResolver.getRememberMeClass()); + assertThat(RememberMeAuthenticationToken.class).isEqualTo(trustResolver.getRememberMeClass()); trustResolver.setRememberMeClass(TestingAuthenticationToken.class); - assertThat(trustResolver.getRememberMeClass()).isEqualTo( - TestingAuthenticationToken.class); + assertThat(trustResolver.getRememberMeClass()).isEqualTo(TestingAuthenticationToken.class); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisherTests.java b/core/src/test/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisherTests.java index a62ba0acef..a11c9980a9 100644 --- a/core/src/test/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisherTests.java +++ b/core/src/test/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisherTests.java @@ -39,6 +39,7 @@ import java.util.*; * @author Luke Taylor */ public class DefaultAuthenticationEventPublisherTests { + DefaultAuthenticationEventPublisher publisher; @Test @@ -52,12 +53,10 @@ public class DefaultAuthenticationEventPublisherTests { Object extraInfo = new Object(); publisher.publishAuthenticationFailure(new BadCredentialsException(""), a); publisher.publishAuthenticationFailure(new BadCredentialsException("", cause), a); - verify(appPublisher, times(2)).publishEvent( - isA(AuthenticationFailureBadCredentialsEvent.class)); + verify(appPublisher, times(2)).publishEvent(isA(AuthenticationFailureBadCredentialsEvent.class)); reset(appPublisher); publisher.publishAuthenticationFailure(new UsernameNotFoundException(""), a); - publisher.publishAuthenticationFailure(new UsernameNotFoundException("", cause), - a); + publisher.publishAuthenticationFailure(new UsernameNotFoundException("", cause), a); publisher.publishAuthenticationFailure(new AccountExpiredException(""), a); publisher.publishAuthenticationFailure(new AccountExpiredException("", cause), a); publisher.publishAuthenticationFailure(new ProviderNotFoundException(""), a); @@ -66,25 +65,16 @@ public class DefaultAuthenticationEventPublisherTests { publisher.publishAuthenticationFailure(new LockedException(""), a); publisher.publishAuthenticationFailure(new LockedException("", cause), a); publisher.publishAuthenticationFailure(new AuthenticationServiceException(""), a); - publisher.publishAuthenticationFailure(new AuthenticationServiceException("", - cause), a); + publisher.publishAuthenticationFailure(new AuthenticationServiceException("", cause), a); publisher.publishAuthenticationFailure(new CredentialsExpiredException(""), a); - publisher.publishAuthenticationFailure( - new CredentialsExpiredException("", cause), a); - verify(appPublisher, times(2)).publishEvent( - isA(AuthenticationFailureBadCredentialsEvent.class)); - verify(appPublisher, times(2)).publishEvent( - isA(AuthenticationFailureExpiredEvent.class)); - verify(appPublisher).publishEvent( - isA(AuthenticationFailureProviderNotFoundEvent.class)); - verify(appPublisher, times(2)).publishEvent( - isA(AuthenticationFailureDisabledEvent.class)); - verify(appPublisher, times(2)).publishEvent( - isA(AuthenticationFailureLockedEvent.class)); - verify(appPublisher, times(2)).publishEvent( - isA(AuthenticationFailureServiceExceptionEvent.class)); - verify(appPublisher, times(2)).publishEvent( - isA(AuthenticationFailureCredentialsExpiredEvent.class)); + publisher.publishAuthenticationFailure(new CredentialsExpiredException("", cause), a); + verify(appPublisher, times(2)).publishEvent(isA(AuthenticationFailureBadCredentialsEvent.class)); + verify(appPublisher, times(2)).publishEvent(isA(AuthenticationFailureExpiredEvent.class)); + verify(appPublisher).publishEvent(isA(AuthenticationFailureProviderNotFoundEvent.class)); + verify(appPublisher, times(2)).publishEvent(isA(AuthenticationFailureDisabledEvent.class)); + verify(appPublisher, times(2)).publishEvent(isA(AuthenticationFailureLockedEvent.class)); + verify(appPublisher, times(2)).publishEvent(isA(AuthenticationFailureServiceExceptionEvent.class)); + verify(appPublisher, times(2)).publishEvent(isA(AuthenticationFailureCredentialsExpiredEvent.class)); verifyNoMoreInteractions(appPublisher); } @@ -105,14 +95,12 @@ public class DefaultAuthenticationEventPublisherTests { public void additionalExceptionMappingsAreSupported() { publisher = new DefaultAuthenticationEventPublisher(); Properties p = new Properties(); - p.put(MockAuthenticationException.class.getName(), - AuthenticationFailureDisabledEvent.class.getName()); + p.put(MockAuthenticationException.class.getName(), AuthenticationFailureDisabledEvent.class.getName()); publisher.setAdditionalExceptionMappings(p); ApplicationEventPublisher appPublisher = mock(ApplicationEventPublisher.class); publisher.setApplicationEventPublisher(appPublisher); - publisher.publishAuthenticationFailure(new MockAuthenticationException("test"), - mock(Authentication.class)); + publisher.publishAuthenticationFailure(new MockAuthenticationException("test"), mock(Authentication.class)); verify(appPublisher).publishEvent(isA(AuthenticationFailureDisabledEvent.class)); } @@ -128,8 +116,7 @@ public class DefaultAuthenticationEventPublisherTests { public void unknownFailureExceptionIsIgnored() { publisher = new DefaultAuthenticationEventPublisher(); Properties p = new Properties(); - p.put(MockAuthenticationException.class.getName(), - AuthenticationFailureDisabledEvent.class.getName()); + p.put(MockAuthenticationException.class.getName(), AuthenticationFailureDisabledEvent.class.getName()); publisher.setAdditionalExceptionMappings(p); ApplicationEventPublisher appPublisher = mock(ApplicationEventPublisher.class); @@ -141,16 +128,14 @@ public class DefaultAuthenticationEventPublisherTests { @Test(expected = IllegalArgumentException.class) public void emptyMapCausesException() { - Map, - Class> mappings = new HashMap<>(); + Map, Class> mappings = new HashMap<>(); publisher = new DefaultAuthenticationEventPublisher(); publisher.setAdditionalExceptionMappings(mappings); } @Test(expected = IllegalArgumentException.class) public void missingExceptionClassCausesException() { - Map, - Class> mappings = new HashMap<>(); + Map, Class> mappings = new HashMap<>(); mappings.put(null, AuthenticationFailureLockedEvent.class); publisher = new DefaultAuthenticationEventPublisher(); publisher.setAdditionalExceptionMappings(mappings); @@ -158,8 +143,7 @@ public class DefaultAuthenticationEventPublisherTests { @Test(expected = IllegalArgumentException.class) public void missingEventClassAsMapValueCausesException() { - Map, - Class> mappings = new HashMap<>(); + Map, Class> mappings = new HashMap<>(); mappings.put(LockedException.class, null); publisher = new DefaultAuthenticationEventPublisher(); publisher.setAdditionalExceptionMappings(mappings); @@ -168,15 +152,13 @@ public class DefaultAuthenticationEventPublisherTests { @Test public void additionalExceptionMappingsUsingMapAreSupported() { publisher = new DefaultAuthenticationEventPublisher(); - Map, - Class> mappings = new HashMap<>(); + Map, Class> mappings = new HashMap<>(); mappings.put(MockAuthenticationException.class, AuthenticationFailureDisabledEvent.class); publisher.setAdditionalExceptionMappings(mappings); ApplicationEventPublisher appPublisher = mock(ApplicationEventPublisher.class); publisher.setApplicationEventPublisher(appPublisher); - publisher.publishAuthenticationFailure(new MockAuthenticationException("test"), - mock(Authentication.class)); + publisher.publishAuthenticationFailure(new MockAuthenticationException("test"), mock(Authentication.class)); verify(appPublisher).publishEvent(isA(AuthenticationFailureDisabledEvent.class)); } @@ -204,18 +186,22 @@ public class DefaultAuthenticationEventPublisherTests { publisher.setDefaultAuthenticationFailureEvent(AuthenticationFailureEventWithoutAppropriateConstructor.class); } - private static final class AuthenticationFailureEventWithoutAppropriateConstructor extends - AbstractAuthenticationFailureEvent { + private static final class AuthenticationFailureEventWithoutAppropriateConstructor + extends AbstractAuthenticationFailureEvent { + AuthenticationFailureEventWithoutAppropriateConstructor(Authentication auth) { - super(auth, new AuthenticationException("") {}); + super(auth, new AuthenticationException("") { + }); } + } - private static final class MockAuthenticationException extends - AuthenticationException { + private static final class MockAuthenticationException extends AuthenticationException { + MockAuthenticationException(String msg) { super(msg); } + } } diff --git a/core/src/test/java/org/springframework/security/authentication/DelegatingReactiveAuthenticationManagerTests.java b/core/src/test/java/org/springframework/security/authentication/DelegatingReactiveAuthenticationManagerTests.java index a9d89d7ac1..f5a7187403 100644 --- a/core/src/test/java/org/springframework/security/authentication/DelegatingReactiveAuthenticationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authentication/DelegatingReactiveAuthenticationManagerTests.java @@ -36,6 +36,7 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class DelegatingReactiveAuthenticationManagerTests { + @Mock ReactiveAuthenticationManager delegate1; @@ -50,31 +51,34 @@ public class DelegatingReactiveAuthenticationManagerTests { when(this.delegate1.authenticate(any())).thenReturn(Mono.empty()); when(this.delegate2.authenticate(any())).thenReturn(Mono.just(this.authentication)); - DelegatingReactiveAuthenticationManager manager = new DelegatingReactiveAuthenticationManager(this.delegate1, this.delegate2); + DelegatingReactiveAuthenticationManager manager = new DelegatingReactiveAuthenticationManager(this.delegate1, + this.delegate2); assertThat(manager.authenticate(this.authentication).block()).isEqualTo(this.authentication); } @Test public void authenticateWhenNotEmptyThenOtherDelegatesNotSubscribed() { - // delay to try and force delegate2 to finish (i.e. make sure we didn't use flatMap) - when(this.delegate1.authenticate(any())).thenReturn(Mono.just(this.authentication).delayElement(Duration.ofMillis(100))); + // delay to try and force delegate2 to finish (i.e. make sure we didn't use + // flatMap) + when(this.delegate1.authenticate(any())) + .thenReturn(Mono.just(this.authentication).delayElement(Duration.ofMillis(100))); - DelegatingReactiveAuthenticationManager manager = new DelegatingReactiveAuthenticationManager(this.delegate1, this.delegate2); + DelegatingReactiveAuthenticationManager manager = new DelegatingReactiveAuthenticationManager(this.delegate1, + this.delegate2); - StepVerifier.create(manager.authenticate(this.authentication)) - .expectNext(this.authentication) - .verifyComplete(); + StepVerifier.create(manager.authenticate(this.authentication)).expectNext(this.authentication).verifyComplete(); } @Test public void authenticateWhenBadCredentialsThenDelegate2NotInvokedAndError() { when(this.delegate1.authenticate(any())).thenReturn(Mono.error(new BadCredentialsException("Test"))); - DelegatingReactiveAuthenticationManager manager = new DelegatingReactiveAuthenticationManager(this.delegate1, this.delegate2); + DelegatingReactiveAuthenticationManager manager = new DelegatingReactiveAuthenticationManager(this.delegate1, + this.delegate2); - StepVerifier.create(manager.authenticate(this.authentication)) - .expectError(BadCredentialsException.class) - .verify(); + StepVerifier.create(manager.authenticate(this.authentication)).expectError(BadCredentialsException.class) + .verify(); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/ProviderManagerTests.java b/core/src/test/java/org/springframework/security/authentication/ProviderManagerTests.java index a28c1c4e41..8de0dfdcb0 100644 --- a/core/src/test/java/org/springframework/security/authentication/ProviderManagerTests.java +++ b/core/src/test/java/org/springframework/security/authentication/ProviderManagerTests.java @@ -63,8 +63,7 @@ public class ProviderManagerTests { @Test public void credentialsAreClearedByDefault() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "Test", "Password"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password"); ProviderManager mgr = makeProviderManager(); Authentication result = mgr.authenticate(token); assertThat(result.getCredentials()).isNull(); @@ -90,8 +89,8 @@ public class ProviderManagerTests { @Test public void authenticationSucceedsWhenFirstProviderReturnsNullButSecondAuthenticates() { final Authentication a = mock(Authentication.class); - ProviderManager mgr = new ProviderManager(Arrays.asList( - createProviderWhichReturns(null), createProviderWhichReturns(a))); + ProviderManager mgr = new ProviderManager( + Arrays.asList(createProviderWhichReturns(null), createProviderWhichReturns(a))); AuthenticationEventPublisher publisher = mock(AuthenticationEventPublisher.class); mgr.setAuthenticationEventPublisher(publisher); @@ -132,8 +131,7 @@ public class ProviderManagerTests { // A provider which sets the details object AuthenticationProvider provider = new AuthenticationProvider() { - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { ((TestingAuthenticationToken) authentication).setDetails(resultDetails); return authentication; } @@ -169,17 +167,16 @@ public class ProviderManagerTests { public void authenticationExceptionIsIgnoredIfLaterProviderAuthenticates() { final Authentication authReq = mock(Authentication.class); ProviderManager mgr = new ProviderManager( - createProviderWhichThrows(new BadCredentialsException("", - new Throwable())), createProviderWhichReturns(authReq)); + createProviderWhichThrows(new BadCredentialsException("", new Throwable())), + createProviderWhichReturns(authReq)); assertThat(mgr.authenticate(mock(Authentication.class))).isSameAs(authReq); } @Test public void authenticationExceptionIsRethrownIfNoLaterProviderAuthenticates() { - ProviderManager mgr = new ProviderManager(Arrays.asList( - createProviderWhichThrows(new BadCredentialsException("")), - createProviderWhichReturns(null))); + ProviderManager mgr = new ProviderManager(Arrays + .asList(createProviderWhichThrows(new BadCredentialsException("")), createProviderWhichReturns(null))); try { mgr.authenticate(mock(Authentication.class)); fail("Expected BadCredentialsException"); @@ -191,13 +188,11 @@ public class ProviderManagerTests { // SEC-546 @Test public void accountStatusExceptionPreventsCallsToSubsequentProviders() { - AuthenticationProvider iThrowAccountStatusException = createProviderWhichThrows(new AccountStatusException( - "") { + AuthenticationProvider iThrowAccountStatusException = createProviderWhichThrows(new AccountStatusException("") { }); AuthenticationProvider otherProvider = mock(AuthenticationProvider.class); - ProviderManager authMgr = new ProviderManager(Arrays.asList( - iThrowAccountStatusException, otherProvider)); + ProviderManager authMgr = new ProviderManager(Arrays.asList(iThrowAccountStatusException, otherProvider)); try { authMgr.authenticate(mock(Authentication.class)); @@ -213,19 +208,18 @@ public class ProviderManagerTests { AuthenticationManager parent = mock(AuthenticationManager.class); Authentication authReq = mock(Authentication.class); when(parent.authenticate(authReq)).thenReturn(authReq); - ProviderManager mgr = new ProviderManager( - Collections.singletonList(mock(AuthenticationProvider.class)), parent); + ProviderManager mgr = new ProviderManager(Collections.singletonList(mock(AuthenticationProvider.class)), + parent); assertThat(mgr.authenticate(authReq)).isSameAs(authReq); } @Test public void parentIsNotCalledIfAccountStatusExceptionIsThrown() { - AuthenticationProvider iThrowAccountStatusException = createProviderWhichThrows(new AccountStatusException( - "", new Throwable()) { - }); + AuthenticationProvider iThrowAccountStatusException = createProviderWhichThrows( + new AccountStatusException("", new Throwable()) { + }); AuthenticationManager parent = mock(AuthenticationManager.class); - ProviderManager mgr = new ProviderManager( - Collections.singletonList(iThrowAccountStatusException), parent); + ProviderManager mgr = new ProviderManager(Collections.singletonList(iThrowAccountStatusException), parent); try { mgr.authenticate(mock(Authentication.class)); fail("Expected exception"); @@ -245,8 +239,7 @@ public class ProviderManagerTests { // Set a provider that throws an exception - this is the exception we expect to be // propagated ProviderManager mgr = new ProviderManager( - Collections.singletonList(createProviderWhichThrows(new BadCredentialsException(""))), - parent); + Collections.singletonList(createProviderWhichThrows(new BadCredentialsException(""))), parent); mgr.setAuthenticationEventPublisher(publisher); try { @@ -262,15 +255,13 @@ public class ProviderManagerTests { public void authenticationExceptionFromParentOverridesPreviousOnes() { AuthenticationManager parent = mock(AuthenticationManager.class); ProviderManager mgr = new ProviderManager( - Collections.singletonList(createProviderWhichThrows(new BadCredentialsException(""))), - parent); + Collections.singletonList(createProviderWhichThrows(new BadCredentialsException(""))), parent); final Authentication authReq = mock(Authentication.class); AuthenticationEventPublisher publisher = mock(AuthenticationEventPublisher.class); mgr.setAuthenticationEventPublisher(publisher); // Set a provider that throws an exception - this is the exception we expect to be // propagated - final BadCredentialsException expected = new BadCredentialsException( - "I'm the one from the parent"); + final BadCredentialsException expected = new BadCredentialsException("I'm the one from the parent"); when(parent.authenticate(authReq)).thenThrow(expected); try { mgr.authenticate(authReq); @@ -285,8 +276,8 @@ public class ProviderManagerTests { public void statusExceptionIsPublished() { AuthenticationManager parent = mock(AuthenticationManager.class); final LockedException expected = new LockedException(""); - ProviderManager mgr = new ProviderManager( - Collections.singletonList(createProviderWhichThrows(expected)), parent); + ProviderManager mgr = new ProviderManager(Collections.singletonList(createProviderWhichThrows(expected)), + parent); final Authentication authReq = mock(Authentication.class); AuthenticationEventPublisher publisher = mock(AuthenticationEventPublisher.class); mgr.setAuthenticationEventPublisher(publisher); @@ -303,10 +294,8 @@ public class ProviderManagerTests { // SEC-2367 @Test public void providerThrowsInternalAuthenticationServiceException() { - InternalAuthenticationServiceException expected = new InternalAuthenticationServiceException( - "Expected"); - ProviderManager mgr = new ProviderManager(Arrays.asList( - createProviderWhichThrows(expected), + InternalAuthenticationServiceException expected = new InternalAuthenticationServiceException("Expected"); + ProviderManager mgr = new ProviderManager(Arrays.asList(createProviderWhichThrows(expected), createProviderWhichThrows(new BadCredentialsException("Oops"))), null); final Authentication authReq = mock(Authentication.class); @@ -323,8 +312,8 @@ public class ProviderManagerTests { public void authenticateWhenFailsInParentAndPublishesThenChildDoesNotPublish() { BadCredentialsException badCredentialsExParent = new BadCredentialsException("Bad Credentials in parent"); ProviderManager parentMgr = new ProviderManager(createProviderWhichThrows(badCredentialsExParent)); - ProviderManager childMgr = new ProviderManager(Collections.singletonList(createProviderWhichThrows( - new BadCredentialsException("Bad Credentials in child"))), parentMgr); + ProviderManager childMgr = new ProviderManager(Collections.singletonList( + createProviderWhichThrows(new BadCredentialsException("Bad Credentials in child"))), parentMgr); AuthenticationEventPublisher publisher = mock(AuthenticationEventPublisher.class); parentMgr.setAuthenticationEventPublisher(publisher); @@ -339,12 +328,12 @@ public class ProviderManagerTests { catch (BadCredentialsException e) { assertThat(e).isSameAs(badCredentialsExParent); } - verify(publisher).publishAuthenticationFailure(badCredentialsExParent, authReq); // Parent publishes - verifyNoMoreInteractions(publisher); // Child should not publish (duplicate event) + verify(publisher).publishAuthenticationFailure(badCredentialsExParent, authReq); // Parent + // publishes + verifyNoMoreInteractions(publisher); // Child should not publish (duplicate event) } - private AuthenticationProvider createProviderWhichThrows( - final AuthenticationException e) { + private AuthenticationProvider createProviderWhichThrows(final AuthenticationException e) { AuthenticationProvider provider = mock(AuthenticationProvider.class); when(provider.supports(any(Class.class))).thenReturn(true); when(provider.authenticate(any(Authentication.class))).thenThrow(e); @@ -361,8 +350,7 @@ public class ProviderManagerTests { } private TestingAuthenticationToken createAuthenticationToken() { - return new TestingAuthenticationToken("name", "password", - new ArrayList<>(0)); + return new TestingAuthenticationToken("name", "password", new ArrayList<>(0)); } private ProviderManager makeProviderManager() { @@ -374,8 +362,8 @@ public class ProviderManagerTests { // ================================================================================================== private static class MockProvider implements AuthenticationProvider { - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + + public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (supports(authentication.getClass())) { return authentication; } @@ -386,8 +374,9 @@ public class ProviderManagerTests { public boolean supports(Class authentication) { return TestingAuthenticationToken.class.isAssignableFrom(authentication) - || UsernamePasswordAuthenticationToken.class - .isAssignableFrom(authentication); + || UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication); } + } + } diff --git a/core/src/test/java/org/springframework/security/authentication/ReactiveAuthenticationManagerAdapterTests.java b/core/src/test/java/org/springframework/security/authentication/ReactiveAuthenticationManagerAdapterTests.java index 9f7390ab3d..42e02fa7a1 100644 --- a/core/src/test/java/org/springframework/security/authentication/ReactiveAuthenticationManagerAdapterTests.java +++ b/core/src/test/java/org/springframework/security/authentication/ReactiveAuthenticationManagerAdapterTests.java @@ -35,8 +35,10 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class ReactiveAuthenticationManagerAdapterTests { + @Mock AuthenticationManager delegate; + @Mock Authentication authentication; @@ -82,8 +84,7 @@ public class ReactiveAuthenticationManagerAdapterTests { Mono result = manager.authenticate(authentication); - StepVerifier.create(result) - .expectError(BadCredentialsException.class) - .verify(); + StepVerifier.create(result).expectError(BadCredentialsException.class).verify(); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/ReactiveUserDetailsServiceAuthenticationManagerTests.java b/core/src/test/java/org/springframework/security/authentication/ReactiveUserDetailsServiceAuthenticationManagerTests.java index d6352818cc..32e9db3f44 100644 --- a/core/src/test/java/org/springframework/security/authentication/ReactiveUserDetailsServiceAuthenticationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authentication/ReactiveUserDetailsServiceAuthenticationManagerTests.java @@ -41,11 +41,17 @@ import reactor.test.StepVerifier; */ @RunWith(MockitoJUnitRunner.class) public class ReactiveUserDetailsServiceAuthenticationManagerTests { - @Mock ReactiveUserDetailsService repository; + + @Mock + ReactiveUserDetailsService repository; + @Mock PasswordEncoder passwordEncoder; + UserDetailsRepositoryReactiveAuthenticationManager manager; + String username; + String password; @Before @@ -68,10 +74,7 @@ public class ReactiveUserDetailsServiceAuthenticationManagerTests { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password); Mono authentication = manager.authenticate(token); - StepVerifier - .create(authentication) - .expectError(BadCredentialsException.class) - .verify(); + StepVerifier.create(authentication).expectError(BadCredentialsException.class).verify(); } @Test @@ -84,13 +87,11 @@ public class ReactiveUserDetailsServiceAuthenticationManagerTests { // @formatter:on when(repository.findByUsername(user.getUsername())).thenReturn(Mono.just(user)); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, this.password + "INVALID"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, + this.password + "INVALID"); Mono authentication = manager.authenticate(token); - StepVerifier - .create(authentication) - .expectError(BadCredentialsException.class) - .verify(); + StepVerifier.create(authentication).expectError(BadCredentialsException.class).verify(); } @Test @@ -116,8 +117,8 @@ public class ReactiveUserDetailsServiceAuthenticationManagerTests { User user = new User(this.username, this.password, AuthorityUtils.createAuthorityList("ROLE_USER")); when(this.repository.findByUsername(user.getUsername())).thenReturn(Mono.just(user)); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - this.username, this.password); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(this.username, + this.password); Authentication authentication = this.manager.authenticate(token).block(); assertThat(authentication).isEqualTo(authentication); @@ -130,14 +131,12 @@ public class ReactiveUserDetailsServiceAuthenticationManagerTests { User user = new User(this.username, this.password, AuthorityUtils.createAuthorityList("ROLE_USER")); when(this.repository.findByUsername(user.getUsername())).thenReturn(Mono.just(user)); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - this.username, this.password); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(this.username, + this.password); Mono authentication = this.manager.authenticate(token); - StepVerifier - .create(authentication) - .expectError(BadCredentialsException.class) - .verify(); + StepVerifier.create(authentication).expectError(BadCredentialsException.class).verify(); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/TestAuthentication.java b/core/src/test/java/org/springframework/security/authentication/TestAuthentication.java index ade69f9ca3..0583c42a48 100644 --- a/core/src/test/java/org/springframework/security/authentication/TestAuthentication.java +++ b/core/src/test/java/org/springframework/security/authentication/TestAuthentication.java @@ -37,4 +37,5 @@ public class TestAuthentication extends PasswordEncodedUser { public static Authentication autheticated(UserDetails user) { return new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/TestingAuthenticationProviderTests.java b/core/src/test/java/org/springframework/security/authentication/TestingAuthenticationProviderTests.java index 875a8bbf3b..e9bb8af1a5 100644 --- a/core/src/test/java/org/springframework/security/authentication/TestingAuthenticationProviderTests.java +++ b/core/src/test/java/org/springframework/security/authentication/TestingAuthenticationProviderTests.java @@ -32,8 +32,7 @@ public class TestingAuthenticationProviderTests { @Test public void testAuthenticates() { TestingAuthenticationProvider provider = new TestingAuthenticationProvider(); - TestingAuthenticationToken token = new TestingAuthenticationToken("Test", - "Password", "ROLE_ONE", "ROLE_TWO"); + TestingAuthenticationToken token = new TestingAuthenticationToken("Test", "Password", "ROLE_ONE", "ROLE_TWO"); Authentication result = provider.authenticate(token); assertThat(result instanceof TestingAuthenticationToken).isTrue(); @@ -41,9 +40,7 @@ public class TestingAuthenticationProviderTests { TestingAuthenticationToken castResult = (TestingAuthenticationToken) result; assertThat(castResult.getPrincipal()).isEqualTo("Test"); assertThat(castResult.getCredentials()).isEqualTo("Password"); - assertThat( - AuthorityUtils.authorityListToSet(castResult.getAuthorities())).contains( - "ROLE_ONE", "ROLE_TWO"); + assertThat(AuthorityUtils.authorityListToSet(castResult.getAuthorities())).contains("ROLE_ONE", "ROLE_TWO"); } @Test @@ -52,4 +49,5 @@ public class TestingAuthenticationProviderTests { assertThat(provider.supports(TestingAuthenticationToken.class)).isTrue(); assertThat(!provider.supports(String.class)).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/TestingAuthenticationTokenTests.java b/core/src/test/java/org/springframework/security/authentication/TestingAuthenticationTokenTests.java index 473fa78945..822632aa69 100644 --- a/core/src/test/java/org/springframework/security/authentication/TestingAuthenticationTokenTests.java +++ b/core/src/test/java/org/springframework/security/authentication/TestingAuthenticationTokenTests.java @@ -26,28 +26,28 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Josh Cummings */ public class TestingAuthenticationTokenTests { + @Test public void constructorWhenNoAuthoritiesThenUnauthenticated() { - TestingAuthenticationToken unauthenticated = - new TestingAuthenticationToken("principal", "credentials"); + TestingAuthenticationToken unauthenticated = new TestingAuthenticationToken("principal", "credentials"); assertThat(unauthenticated.isAuthenticated()).isFalse(); } @Test public void constructorWhenArityAuthoritiesThenAuthenticated() { - TestingAuthenticationToken authenticated = - new TestingAuthenticationToken("principal", "credentials", "authority"); + TestingAuthenticationToken authenticated = new TestingAuthenticationToken("principal", "credentials", + "authority"); assertThat(authenticated.isAuthenticated()).isTrue(); } @Test public void constructorWhenCollectionAuthoritiesThenAuthenticated() { - TestingAuthenticationToken authenticated = - new TestingAuthenticationToken("principal", "credentials", + TestingAuthenticationToken authenticated = new TestingAuthenticationToken("principal", "credentials", Arrays.asList(new SimpleGrantedAuthority("authority"))); assertThat(authenticated.isAuthenticated()).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManagerTests.java b/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManagerTests.java index 937b61edb2..b221ff3609 100644 --- a/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManagerTests.java @@ -44,6 +44,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; */ @RunWith(MockitoJUnitRunner.class) public class UserDetailsRepositoryReactiveAuthenticationManagerTests { + @Mock private ReactiveUserDetailsService userDetailsService; @@ -79,8 +80,7 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests { @Test public void setSchedulerWhenNullThenIllegalArgumentException() { - assertThatCode(() -> this.manager.setScheduler(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> this.manager.setScheduler(null)).isInstanceOf(IllegalArgumentException.class); } @Test @@ -89,8 +89,8 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests { when(this.encoder.matches(any(), any())).thenReturn(true); this.manager.setScheduler(this.scheduler); this.manager.setPasswordEncoder(this.encoder); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - this.user, this.user.getPassword()); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(this.user, + this.user.getPassword()); Authentication result = this.manager.authenticate(token).block(); @@ -107,8 +107,8 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests { when(this.userDetailsPasswordService.updatePassword(any(), any())).thenReturn(Mono.just(this.user)); this.manager.setPasswordEncoder(this.encoder); this.manager.setUserDetailsPasswordService(this.userDetailsPasswordService); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - this.user, this.user.getPassword()); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(this.user, + this.user.getPassword()); Authentication result = this.manager.authenticate(token).block(); @@ -122,11 +122,10 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests { when(this.encoder.matches(any(), any())).thenReturn(false); this.manager.setPasswordEncoder(this.encoder); this.manager.setUserDetailsPasswordService(this.userDetailsPasswordService); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - this.user, this.user.getPassword()); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(this.user, + this.user.getPassword()); - assertThatThrownBy(() -> this.manager.authenticate(token).block()) - .isInstanceOf(BadCredentialsException.class); + assertThatThrownBy(() -> this.manager.authenticate(token).block()).isInstanceOf(BadCredentialsException.class); verifyZeroInteractions(this.userDetailsPasswordService); } @@ -138,8 +137,8 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests { when(this.encoder.upgradeEncoding(any())).thenReturn(false); this.manager.setPasswordEncoder(this.encoder); this.manager.setUserDetailsPasswordService(this.userDetailsPasswordService); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - this.user, this.user.getPassword()); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(this.user, + this.user.getPassword()); Authentication result = this.manager.authenticate(token).block(); @@ -154,8 +153,8 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests { this.manager.setPasswordEncoder(this.encoder); this.manager.setPostAuthenticationChecks(this.postAuthenticationChecks); - assertThatExceptionOfType(LockedException.class) - .isThrownBy(() -> this.manager.authenticate(new UsernamePasswordAuthenticationToken(this.user, this.user.getPassword())).block()) + assertThatExceptionOfType(LockedException.class).isThrownBy(() -> this.manager + .authenticate(new UsernamePasswordAuthenticationToken(this.user, this.user.getPassword())).block()) .withMessage("account is locked"); verify(this.postAuthenticationChecks).check(eq(this.user)); @@ -167,8 +166,8 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests { when(this.encoder.matches(any(), any())).thenReturn(true); this.manager.setPasswordEncoder(this.encoder); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - this.user, this.user.getPassword()); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(this.user, + this.user.getPassword()); this.manager.authenticate(token).block(); @@ -187,8 +186,8 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests { // @formatter:on when(this.userDetailsService.findByUsername(any())).thenReturn(Mono.just(expiredUser)); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - expiredUser, expiredUser.getPassword()); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(expiredUser, + expiredUser.getPassword()); this.manager.authenticate(token).block(); } @@ -205,8 +204,8 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests { // @formatter:on when(this.userDetailsService.findByUsername(any())).thenReturn(Mono.just(lockedUser)); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - lockedUser, lockedUser.getPassword()); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(lockedUser, + lockedUser.getPassword()); this.manager.authenticate(token).block(); } @@ -224,8 +223,8 @@ public class UserDetailsRepositoryReactiveAuthenticationManagerTests { // @formatter:on when(this.userDetailsService.findByUsername(any())).thenReturn(Mono.just(disabledUser)); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - disabledUser, disabledUser.getPassword()); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(disabledUser, + disabledUser.getPassword()); this.manager.authenticate(token).block(); } diff --git a/core/src/test/java/org/springframework/security/authentication/UsernamePasswordAuthenticationTokenTests.java b/core/src/test/java/org/springframework/security/authentication/UsernamePasswordAuthenticationTokenTests.java index 71d599f8d7..4f93382b33 100644 --- a/core/src/test/java/org/springframework/security/authentication/UsernamePasswordAuthenticationTokenTests.java +++ b/core/src/test/java/org/springframework/security/authentication/UsernamePasswordAuthenticationTokenTests.java @@ -34,8 +34,8 @@ public class UsernamePasswordAuthenticationTokenTests { @Test public void authenticatedPropertyContractIsSatisfied() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "Test", "Password", AuthorityUtils.NO_AUTHORITIES); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", + AuthorityUtils.NO_AUTHORITIES); // check default given we passed some GrantedAuthorty[]s (well, we passed empty // list) @@ -67,8 +67,7 @@ public class UsernamePasswordAuthenticationTokenTests { @Test public void gettersReturnCorrectData() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "Test", "Password", + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO")); assertThat(token.getPrincipal()).isEqualTo("Test"); assertThat(token.getCredentials()).isEqualTo("Password"); @@ -81,4 +80,5 @@ public class UsernamePasswordAuthenticationTokenTests { Class clazz = UsernamePasswordAuthenticationToken.class; clazz.getDeclaredConstructor((Class[]) null); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/anonymous/AnonymousAuthenticationProviderTests.java b/core/src/test/java/org/springframework/security/authentication/anonymous/AnonymousAuthenticationProviderTests.java index 11277b56bf..d1aed04429 100644 --- a/core/src/test/java/org/springframework/security/authentication/anonymous/AnonymousAuthenticationProviderTests.java +++ b/core/src/test/java/org/springframework/security/authentication/anonymous/AnonymousAuthenticationProviderTests.java @@ -38,12 +38,10 @@ public class AnonymousAuthenticationProviderTests { @Test public void testDetectsAnInvalidKey() { - AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider( - "qwerty"); + AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider("qwerty"); - AnonymousAuthenticationToken token = new AnonymousAuthenticationToken( - "WRONG_KEY", "Test", AuthorityUtils.createAuthorityList("ROLE_ONE", - "ROLE_TWO")); + AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("WRONG_KEY", "Test", + AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO")); try { aap.authenticate(token); @@ -66,18 +64,15 @@ public class AnonymousAuthenticationProviderTests { @Test public void testGettersSetters() { - AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider( - "qwerty"); + AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider("qwerty"); assertThat(aap.getKey()).isEqualTo("qwerty"); } @Test public void testIgnoresClassesItDoesNotSupport() { - AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider( - "qwerty"); + AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider("qwerty"); - TestingAuthenticationToken token = new TestingAuthenticationToken("user", - "password", "ROLE_A"); + TestingAuthenticationToken token = new TestingAuthenticationToken("user", "password", "ROLE_A"); assertThat(aap.supports(TestingAuthenticationToken.class)).isFalse(); // Try it anyway @@ -86,11 +81,10 @@ public class AnonymousAuthenticationProviderTests { @Test public void testNormalOperation() { - AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider( - "qwerty"); + AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider("qwerty"); - AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("qwerty", - "Test", AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO")); + AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("qwerty", "Test", + AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO")); Authentication result = aap.authenticate(token); @@ -99,9 +93,9 @@ public class AnonymousAuthenticationProviderTests { @Test public void testSupports() { - AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider( - "qwerty"); + AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider("qwerty"); assertThat(aap.supports(AnonymousAuthenticationToken.class)).isTrue(); assertThat(aap.supports(TestingAuthenticationToken.class)).isFalse(); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/anonymous/AnonymousAuthenticationTokenTests.java b/core/src/test/java/org/springframework/security/authentication/anonymous/AnonymousAuthenticationTokenTests.java index 1fec11d0c4..544aaef640 100644 --- a/core/src/test/java/org/springframework/security/authentication/anonymous/AnonymousAuthenticationTokenTests.java +++ b/core/src/test/java/org/springframework/security/authentication/anonymous/AnonymousAuthenticationTokenTests.java @@ -35,8 +35,7 @@ import org.springframework.security.core.authority.AuthorityUtils; */ public class AnonymousAuthenticationTokenTests { - private final static List ROLES_12 = AuthorityUtils.createAuthorityList( - "ROLE_ONE", "ROLE_TWO"); + private final static List ROLES_12 = AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"); // ~ Methods // ======================================================================================================== @@ -57,16 +56,14 @@ public class AnonymousAuthenticationTokenTests { } try { - new AnonymousAuthenticationToken("key", "Test", - null); + new AnonymousAuthenticationToken("key", "Test", null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { } try { - new AnonymousAuthenticationToken("key", "Test", - AuthorityUtils.NO_AUTHORITIES); + new AnonymousAuthenticationToken("key", "Test", AuthorityUtils.NO_AUTHORITIES); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { @@ -75,24 +72,20 @@ public class AnonymousAuthenticationTokenTests { @Test public void testEqualsWhenEqual() { - AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", - "Test", ROLES_12); - AnonymousAuthenticationToken token2 = new AnonymousAuthenticationToken("key", - "Test", ROLES_12); + AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", "Test", ROLES_12); + AnonymousAuthenticationToken token2 = new AnonymousAuthenticationToken("key", "Test", ROLES_12); assertThat(token2).isEqualTo(token1); } @Test public void testGetters() { - AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", - "Test", ROLES_12); + AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", "Test", ROLES_12); assertThat(token.getKeyHash()).isEqualTo("key".hashCode()); assertThat(token.getPrincipal()).isEqualTo("Test"); assertThat(token.getCredentials()).isEqualTo(""); - assertThat(AuthorityUtils.authorityListToSet(token.getAuthorities())).contains( - "ROLE_ONE", "ROLE_TWO"); + assertThat(AuthorityUtils.authorityListToSet(token.getAuthorities())).contains("ROLE_ONE", "ROLE_TWO"); assertThat(token.isAuthenticated()).isTrue(); } @@ -110,39 +103,33 @@ public class AnonymousAuthenticationTokenTests { @Test public void testNotEqualsDueToAbstractParentEqualsCheck() { - AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", - "Test", ROLES_12); - AnonymousAuthenticationToken token2 = new AnonymousAuthenticationToken("key", - "DIFFERENT_PRINCIPAL", ROLES_12); + AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", "Test", ROLES_12); + AnonymousAuthenticationToken token2 = new AnonymousAuthenticationToken("key", "DIFFERENT_PRINCIPAL", ROLES_12); assertThat(token1.equals(token2)).isFalse(); } @Test public void testNotEqualsDueToDifferentAuthenticationClass() { - AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", - "Test", ROLES_12); - UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken( - "Test", "Password", ROLES_12); + AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", "Test", ROLES_12); + UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken("Test", "Password", + ROLES_12); assertThat(token1.equals(token2)).isFalse(); } @Test public void testNotEqualsDueToKey() { - AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", - "Test", ROLES_12); + AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", "Test", ROLES_12); - AnonymousAuthenticationToken token2 = new AnonymousAuthenticationToken( - "DIFFERENT_KEY", "Test", ROLES_12); + AnonymousAuthenticationToken token2 = new AnonymousAuthenticationToken("DIFFERENT_KEY", "Test", ROLES_12); assertThat(token1.equals(token2)).isFalse(); } @Test public void testSetAuthenticatedIgnored() { - AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", - "Test", ROLES_12); + AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", "Test", ROLES_12); assertThat(token.isAuthenticated()).isTrue(); token.setAuthenticated(false); assertThat(!token.isAuthenticated()).isTrue(); @@ -162,4 +149,5 @@ public class AnonymousAuthenticationTokenTests { public void constructorWhenPrincipalIsEmptyStringThenThrowIllegalArgumentException() { new AnonymousAuthenticationToken("key", "", ROLES_12); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/dao/DaoAuthenticationProviderTests.java b/core/src/test/java/org/springframework/security/authentication/dao/DaoAuthenticationProviderTests.java index 7d906af380..8ac4bc9f26 100644 --- a/core/src/test/java/org/springframework/security/authentication/dao/DaoAuthenticationProviderTests.java +++ b/core/src/test/java/org/springframework/security/authentication/dao/DaoAuthenticationProviderTests.java @@ -68,15 +68,13 @@ import org.springframework.security.core.userdetails.UserDetailsPasswordService; */ public class DaoAuthenticationProviderTests { - private static final List ROLES_12 = AuthorityUtils.createAuthorityList( - "ROLE_ONE", "ROLE_TWO"); + private static final List ROLES_12 = AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"); // ~ Methods // ======================================================================================================== @Test public void testAuthenticateFailsForIncorrectPasswordCase() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "rod", "KOala"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("rod", "KOala"); DaoAuthenticationProvider provider = createProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserRod()); @@ -98,8 +96,7 @@ public class DaoAuthenticationProviderTests { provider.setUserDetailsService(new MockUserDetailsServiceUserRod()); provider.setUserCache(new MockUserCache()); - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( - "rod", null); + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken("rod", null); try { provider.authenticate(authenticationToken); fail("Expected BadCredenialsException"); @@ -111,12 +108,10 @@ public class DaoAuthenticationProviderTests { @Test public void testAuthenticateFailsIfAccountExpired() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "peter", "opal"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal"); DaoAuthenticationProvider provider = createProvider(); - provider.setUserDetailsService( - new MockUserDetailsServiceUserPeterAccountExpired()); + provider.setUserDetailsService(new MockUserDetailsServiceUserPeterAccountExpired()); provider.setUserCache(new MockUserCache()); try { @@ -130,8 +125,7 @@ public class DaoAuthenticationProviderTests { @Test public void testAuthenticateFailsIfAccountLocked() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "peter", "opal"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal"); DaoAuthenticationProvider provider = createProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserPeterAccountLocked()); @@ -148,12 +142,10 @@ public class DaoAuthenticationProviderTests { @Test public void testAuthenticateFailsIfCredentialsExpired() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "peter", "opal"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal"); DaoAuthenticationProvider provider = createProvider(); - provider.setUserDetailsService( - new MockUserDetailsServiceUserPeterCredentialsExpired()); + provider.setUserDetailsService(new MockUserDetailsServiceUserPeterCredentialsExpired()); provider.setUserCache(new MockUserCache()); try { @@ -179,8 +171,7 @@ public class DaoAuthenticationProviderTests { @Test public void testAuthenticateFailsIfUserDisabled() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "peter", "opal"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal"); DaoAuthenticationProvider provider = createProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserPeter()); @@ -197,8 +188,7 @@ public class DaoAuthenticationProviderTests { @Test public void testAuthenticateFailsWhenAuthenticationDaoHasBackendFailure() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "rod", "koala"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("rod", "koala"); DaoAuthenticationProvider provider = createProvider(); provider.setUserDetailsService(new MockUserDetailsServiceSimulateBackendError()); @@ -214,8 +204,7 @@ public class DaoAuthenticationProviderTests { @Test public void testAuthenticateFailsWithEmptyUsername() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - null, "koala"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, "koala"); DaoAuthenticationProvider provider = createProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserRod()); @@ -232,8 +221,7 @@ public class DaoAuthenticationProviderTests { @Test public void testAuthenticateFailsWithInvalidPassword() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "rod", "INVALID_PASSWORD"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("rod", "INVALID_PASSWORD"); DaoAuthenticationProvider provider = createProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserRod()); @@ -250,8 +238,7 @@ public class DaoAuthenticationProviderTests { @Test public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionFalse() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "INVALID_USER", "koala"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER", "koala"); DaoAuthenticationProvider provider = createProvider(); provider.setHideUserNotFoundExceptions(false); // we want @@ -270,8 +257,7 @@ public class DaoAuthenticationProviderTests { @Test public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionsWithDefaultOfTrue() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "INVALID_USER", "koala"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER", "koala"); DaoAuthenticationProvider provider = createProvider(); assertThat(provider.isHideUserNotFoundExceptions()).isTrue(); @@ -289,8 +275,7 @@ public class DaoAuthenticationProviderTests { @Test public void testAuthenticateFailsWithInvalidUsernameAndChangePasswordEncoder() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "INVALID_USER", "koala"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER", "koala"); DaoAuthenticationProvider provider = createProvider(); assertThat(provider.isHideUserNotFoundExceptions()).isTrue(); @@ -318,8 +303,7 @@ public class DaoAuthenticationProviderTests { @Test public void testAuthenticateFailsWithMixedCaseUsernameIfDefaultChanged() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "RoD", "koala"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("RoD", "koala"); DaoAuthenticationProvider provider = createProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserRod()); @@ -336,8 +320,7 @@ public class DaoAuthenticationProviderTests { @Test public void testAuthenticates() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "rod", "koala"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("rod", "koala"); token.setDetails("192.168.0.1"); DaoAuthenticationProvider provider = createProvider(); @@ -353,16 +336,13 @@ public class DaoAuthenticationProviderTests { UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result; assertThat(castResult.getPrincipal().getClass()).isEqualTo(User.class); assertThat(castResult.getCredentials()).isEqualTo("koala"); - assertThat( - AuthorityUtils.authorityListToSet(castResult.getAuthorities())).contains( - "ROLE_ONE", "ROLE_TWO"); + assertThat(AuthorityUtils.authorityListToSet(castResult.getAuthorities())).contains("ROLE_ONE", "ROLE_TWO"); assertThat(castResult.getDetails()).isEqualTo("192.168.0.1"); } @Test public void testAuthenticatesASecondTime() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "rod", "koala"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("rod", "koala"); DaoAuthenticationProvider provider = createProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserRod()); @@ -386,8 +366,7 @@ public class DaoAuthenticationProviderTests { @Test public void testAuthenticatesWithForcePrincipalAsString() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "rod", "koala"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("rod", "koala"); DaoAuthenticationProvider provider = createProvider(); provider.setUserDetailsService(new MockUserDetailsServiceUserRod()); @@ -409,8 +388,7 @@ public class DaoAuthenticationProviderTests { public void authenticateWhenSuccessAndPasswordManagerThenUpdates() { String password = "password"; String encodedPassword = "encoded"; - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "user", password); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", password); PasswordEncoder encoder = mock(PasswordEncoder.class); UserDetailsService userDetailsService = mock(UserDetailsService.class); @@ -435,8 +413,7 @@ public class DaoAuthenticationProviderTests { @Test public void authenticateWhenBadCredentialsAndPasswordManagerThenNoUpdate() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "user", "password"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password"); PasswordEncoder encoder = mock(PasswordEncoder.class); UserDetailsService userDetailsService = mock(UserDetailsService.class); @@ -450,16 +427,14 @@ public class DaoAuthenticationProviderTests { when(encoder.matches(any(), any())).thenReturn(false); when(userDetailsService.loadUserByUsername(any())).thenReturn(user); - assertThatThrownBy(() -> provider.authenticate(token)) - .isInstanceOf(BadCredentialsException.class); + assertThatThrownBy(() -> provider.authenticate(token)).isInstanceOf(BadCredentialsException.class); verifyZeroInteractions(passwordManager); } @Test public void authenticateWhenNotUpgradeAndPasswordManagerThenNoUpdate() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "user", "password"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password"); PasswordEncoder encoder = mock(PasswordEncoder.class); UserDetailsService userDetailsService = mock(UserDetailsService.class); @@ -481,8 +456,7 @@ public class DaoAuthenticationProviderTests { @Test public void testDetectsNullBeingReturnedFromAuthenticationDao() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "rod", "koala"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("rod", "koala"); DaoAuthenticationProvider provider = createProvider(); provider.setUserDetailsService(new MockUserDetailsServiceReturnsNull()); @@ -492,9 +466,8 @@ public class DaoAuthenticationProviderTests { fail("Should have thrown AuthenticationServiceException"); } catch (AuthenticationServiceException expected) { - assertThat( - "UserDetailsService returned null, which is an interface contract violation").isEqualTo( - expected.getMessage()); + assertThat("UserDetailsService returned null, which is an interface contract violation") + .isEqualTo(expected.getMessage()); } } @@ -502,12 +475,10 @@ public class DaoAuthenticationProviderTests { public void testGettersSetters() { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setPasswordEncoder(new BCryptPasswordEncoder()); - assertThat(provider.getPasswordEncoder().getClass()).isEqualTo( - BCryptPasswordEncoder.class); + assertThat(provider.getPasswordEncoder().getClass()).isEqualTo(BCryptPasswordEncoder.class); provider.setUserCache(new EhCacheBasedUserCache()); - assertThat(provider.getUserCache().getClass()).isEqualTo( - EhCacheBasedUserCache.class); + assertThat(provider.getUserCache().getClass()).isEqualTo(EhCacheBasedUserCache.class); assertThat(provider.isForcePrincipalAsString()).isFalse(); provider.setForcePrincipalAsString(true); @@ -516,8 +487,7 @@ public class DaoAuthenticationProviderTests { @Test public void testGoesBackToAuthenticationDaoToObtainLatestPasswordIfCachedPasswordSeemsIncorrect() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "rod", "koala"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("rod", "koala"); MockUserDetailsServiceUserRod authenticationDao = new MockUserDetailsServiceUserRod(); MockUserCache cache = new MockUserCache(); @@ -540,8 +510,7 @@ public class DaoAuthenticationProviderTests { // To get this far, the new password was accepted // Check the cache was updated - assertThat(cache.getUserFromCache("rod").getPassword()).isEqualTo( - "easternLongNeckTurtle"); + assertThat(cache.getUserFromCache("rod").getPassword()).isEqualTo("easternLongNeckTurtle"); } @Test @@ -594,8 +563,7 @@ public class DaoAuthenticationProviderTests { // SEC-2056 @Test public void testUserNotFoundEncodesPassword() throws Exception { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "missing", "koala"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("missing", "koala"); PasswordEncoder encoder = mock(PasswordEncoder.class); when(encoder.encode(anyString())).thenReturn("koala"); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); @@ -617,15 +585,13 @@ public class DaoAuthenticationProviderTests { @Test public void testUserNotFoundBCryptPasswordEncoder() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "missing", "koala"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("missing", "koala"); PasswordEncoder encoder = new BCryptPasswordEncoder(); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setHideUserNotFoundExceptions(false); provider.setPasswordEncoder(encoder); MockUserDetailsServiceUserRod userDetailsService = new MockUserDetailsServiceUserRod(); - userDetailsService.password = encoder.encode( - (CharSequence) token.getCredentials()); + userDetailsService.password = encoder.encode((CharSequence) token.getCredentials()); provider.setUserDetailsService(userDetailsService); try { provider.authenticate(token); @@ -637,8 +603,7 @@ public class DaoAuthenticationProviderTests { @Test public void testUserNotFoundDefaultEncoder() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "missing", null); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("missing", null); DaoAuthenticationProvider provider = createProvider(); provider.setHideUserNotFoundExceptions(false); provider.setUserDetailsService(new MockUserDetailsServiceUserRod()); @@ -656,17 +621,14 @@ public class DaoAuthenticationProviderTests { * SEC-2056 is fixed. */ public void IGNOREtestSec2056() { - UsernamePasswordAuthenticationToken foundUser = new UsernamePasswordAuthenticationToken( - "rod", "koala"); - UsernamePasswordAuthenticationToken notFoundUser = new UsernamePasswordAuthenticationToken( - "notFound", "koala"); + UsernamePasswordAuthenticationToken foundUser = new UsernamePasswordAuthenticationToken("rod", "koala"); + UsernamePasswordAuthenticationToken notFoundUser = new UsernamePasswordAuthenticationToken("notFound", "koala"); PasswordEncoder encoder = new BCryptPasswordEncoder(10, new SecureRandom()); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setHideUserNotFoundExceptions(false); provider.setPasswordEncoder(encoder); MockUserDetailsServiceUserRod userDetailsService = new MockUserDetailsServiceUserRod(); - userDetailsService.password = encoder.encode( - (CharSequence) foundUser.getCredentials()); + userDetailsService.password = encoder.encode((CharSequence) foundUser.getCredentials()); provider.setUserDetailsService(userDetailsService); int sampleSize = 100; @@ -692,10 +654,8 @@ public class DaoAuthenticationProviderTests { double userFoundAvg = avg(userFoundTimes); double userNotFoundAvg = avg(userNotFoundTimes); - assertThat(Math.abs(userNotFoundAvg - userFoundAvg) <= 3).withFailMessage( - "User not found average " + userNotFoundAvg - + " should be within 3ms of user found average " - + userFoundAvg).isTrue(); + assertThat(Math.abs(userNotFoundAvg - userFoundAvg) <= 3).withFailMessage("User not found average " + + userNotFoundAvg + " should be within 3ms of user found average " + userFoundAvg).isTrue(); } private double avg(List counts) { @@ -708,8 +668,7 @@ public class DaoAuthenticationProviderTests { @Test public void testUserNotFoundNullCredentials() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "missing", null); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("missing", null); PasswordEncoder encoder = mock(PasswordEncoder.class); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setHideUserNotFoundExceptions(false); @@ -733,15 +692,15 @@ public class DaoAuthenticationProviderTests { public UserDetails loadUserByUsername(String username) { return null; } + } - private class MockUserDetailsServiceSimulateBackendError - implements UserDetailsService { + private class MockUserDetailsServiceSimulateBackendError implements UserDetailsService { public UserDetails loadUserByUsername(String username) { - throw new DataRetrievalFailureException( - "This mock simulator is designed to fail"); + throw new DataRetrievalFailureException("This mock simulator is designed to fail"); } + } private class MockUserDetailsServiceUserRod implements UserDetailsService { @@ -758,6 +717,7 @@ public class DaoAuthenticationProviderTests { public void setPassword(String password) { this.password = password; } + } private class MockUserDetailsServiceUserPeter implements UserDetailsService { @@ -768,10 +728,10 @@ public class DaoAuthenticationProviderTests { } throw new UsernameNotFoundException("Could not find: " + username); } + } - private class MockUserDetailsServiceUserPeterAccountExpired - implements UserDetailsService { + private class MockUserDetailsServiceUserPeterAccountExpired implements UserDetailsService { public UserDetails loadUserByUsername(String username) { if ("peter".equals(username)) { @@ -779,10 +739,10 @@ public class DaoAuthenticationProviderTests { } throw new UsernameNotFoundException("Could not find: " + username); } + } - private class MockUserDetailsServiceUserPeterAccountLocked - implements UserDetailsService { + private class MockUserDetailsServiceUserPeterAccountLocked implements UserDetailsService { public UserDetails loadUserByUsername(String username) { if ("peter".equals(username)) { @@ -790,10 +750,10 @@ public class DaoAuthenticationProviderTests { } throw new UsernameNotFoundException("Could not find: " + username); } + } - private class MockUserDetailsServiceUserPeterCredentialsExpired - implements UserDetailsService { + private class MockUserDetailsServiceUserPeterCredentialsExpired implements UserDetailsService { public UserDetails loadUserByUsername(String username) { if ("peter".equals(username)) { @@ -801,6 +761,7 @@ public class DaoAuthenticationProviderTests { } throw new UsernameNotFoundException("Could not find: " + username); } + } private DaoAuthenticationProvider createProvider() { @@ -808,4 +769,5 @@ public class DaoAuthenticationProviderTests { provider.setPasswordEncoder(NoOpPasswordEncoder.getInstance()); return provider; } + } diff --git a/core/src/test/java/org/springframework/security/authentication/dao/MockUserCache.java b/core/src/test/java/org/springframework/security/authentication/dao/MockUserCache.java index ea7132f53b..68e2c068d8 100644 --- a/core/src/test/java/org/springframework/security/authentication/dao/MockUserCache.java +++ b/core/src/test/java/org/springframework/security/authentication/dao/MockUserCache.java @@ -25,6 +25,7 @@ import org.springframework.security.core.userdetails.UserCache; import org.springframework.security.core.userdetails.UserDetails; public class MockUserCache implements UserCache { + private Map cache = new HashMap<>(); public UserDetails getUserFromCache(String username) { @@ -38,4 +39,5 @@ public class MockUserCache implements UserCache { public void removeUserFromCache(String username) { cache.remove(username); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/event/AuthenticationEventTests.java b/core/src/test/java/org/springframework/security/authentication/event/AuthenticationEventTests.java index 1b08f45878..786ebd3e12 100644 --- a/core/src/test/java/org/springframework/security/authentication/event/AuthenticationEventTests.java +++ b/core/src/test/java/org/springframework/security/authentication/event/AuthenticationEventTests.java @@ -31,12 +31,13 @@ import org.springframework.security.core.AuthenticationException; * @author Ben Alex */ public class AuthenticationEventTests { + // ~ Methods // ======================================================================================================== private Authentication getAuthentication() { - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( - "Principal", "Credentials"); + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken("Principal", + "Credentials"); authentication.setDetails("127.0.0.1"); return authentication; @@ -53,8 +54,7 @@ public class AuthenticationEventTests { public void testAbstractAuthenticationFailureEvent() { Authentication auth = getAuthentication(); AuthenticationException exception = new DisabledException("TEST"); - AbstractAuthenticationFailureEvent event = new AuthenticationFailureDisabledEvent( - auth, exception); + AbstractAuthenticationFailureEvent event = new AuthenticationFailureDisabledEvent(auth, exception); assertThat(event.getAuthentication()).isEqualTo(auth); assertThat(event.getException()).isEqualTo(exception); } @@ -82,4 +82,5 @@ public class AuthenticationEventTests { } } + } diff --git a/core/src/test/java/org/springframework/security/authentication/event/LoggerListenerTests.java b/core/src/test/java/org/springframework/security/authentication/event/LoggerListenerTests.java index fd8ac22222..1d31a2990a 100644 --- a/core/src/test/java/org/springframework/security/authentication/event/LoggerListenerTests.java +++ b/core/src/test/java/org/springframework/security/authentication/event/LoggerListenerTests.java @@ -27,12 +27,13 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ public class LoggerListenerTests { + // ~ Methods // ======================================================================================================== private Authentication getAuthentication() { - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( - "Principal", "Credentials"); + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken("Principal", + "Credentials"); authentication.setDetails("127.0.0.1"); return authentication; @@ -40,10 +41,11 @@ public class LoggerListenerTests { @Test public void testLogsEvents() { - AuthenticationFailureDisabledEvent event = new AuthenticationFailureDisabledEvent( - getAuthentication(), new LockedException("TEST")); + AuthenticationFailureDisabledEvent event = new AuthenticationFailureDisabledEvent(getAuthentication(), + new LockedException("TEST")); LoggerListener listener = new LoggerListener(); listener.onApplicationEvent(event); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/jaas/DefaultJaasAuthenticationProviderTests.java b/core/src/test/java/org/springframework/security/authentication/jaas/DefaultJaasAuthenticationProviderTests.java index 66b117651a..ebe69f1e77 100644 --- a/core/src/test/java/org/springframework/security/authentication/jaas/DefaultJaasAuthenticationProviderTests.java +++ b/core/src/test/java/org/springframework/security/authentication/jaas/DefaultJaasAuthenticationProviderTests.java @@ -53,9 +53,13 @@ import org.springframework.security.core.session.SessionDestroyedEvent; import org.springframework.test.util.ReflectionTestUtils; public class DefaultJaasAuthenticationProviderTests { + private DefaultJaasAuthenticationProvider provider; + private UsernamePasswordAuthenticationToken token; + private ApplicationEventPublisher publisher; + private Log log; @Before @@ -68,11 +72,10 @@ public class DefaultJaasAuthenticationProviderTests { provider.setApplicationEventPublisher(publisher); provider.setAuthorityGranters(new AuthorityGranter[] { new TestAuthorityGranter() }); provider.afterPropertiesSet(); - AppConfigurationEntry[] aces = new AppConfigurationEntry[] { new AppConfigurationEntry( - TestLoginModule.class.getName(), LoginModuleControlFlag.REQUIRED, - Collections. emptyMap()) }; - when(configuration.getAppConfigurationEntry(provider.getLoginContextName())) - .thenReturn(aces); + AppConfigurationEntry[] aces = new AppConfigurationEntry[] { + new AppConfigurationEntry(TestLoginModule.class.getName(), LoginModuleControlFlag.REQUIRED, + Collections.emptyMap()) }; + when(configuration.getAppConfigurationEntry(provider.getLoginContextName())).thenReturn(aces); token = new UsernamePasswordAuthenticationToken("user", "password"); ReflectionTestUtils.setField(provider, "log", log); @@ -121,8 +124,7 @@ public class DefaultJaasAuthenticationProviderTests { @Test public void authenticateBadUser() { try { - provider.authenticate(new UsernamePasswordAuthenticationToken("asdf", - "password")); + provider.authenticate(new UsernamePasswordAuthenticationToken("asdf", "password")); fail("LoginException should have been thrown for the bad user"); } catch (AuthenticationException success) { @@ -245,8 +247,7 @@ public class DefaultJaasAuthenticationProviderTests { @Test public void javadocExample() { String resName = "/" + getClass().getName().replace('.', '/') + ".xml"; - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - resName); + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(resName); context.registerShutdownHook(); try { provider = context.getBean(DefaultJaasAuthenticationProvider.class); @@ -260,10 +261,12 @@ public class DefaultJaasAuthenticationProviderTests { } private void verifyFailedLogin() { - ArgumentCaptor event = ArgumentCaptor.forClass(JaasAuthenticationFailedEvent.class); + ArgumentCaptor event = ArgumentCaptor + .forClass(JaasAuthenticationFailedEvent.class); verify(publisher).publishEvent(event.capture()); assertThat(event.getValue()).isInstanceOf(JaasAuthenticationFailedEvent.class); assertThat(event.getValue().getException()).isNotNull(); verifyNoMoreInteractions(publisher); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/jaas/JaasAuthenticationProviderTests.java b/core/src/test/java/org/springframework/security/authentication/jaas/JaasAuthenticationProviderTests.java index ea794e8126..fb4c832ec7 100644 --- a/core/src/test/java/org/springframework/security/authentication/jaas/JaasAuthenticationProviderTests.java +++ b/core/src/test/java/org/springframework/security/authentication/jaas/JaasAuthenticationProviderTests.java @@ -51,11 +51,14 @@ import org.springframework.security.core.session.SessionDestroyedEvent; * @author Ray Krueger */ public class JaasAuthenticationProviderTests { + // ~ Instance fields // ================================================================================================ private ApplicationContext context; + private JaasAuthenticationProvider jaasProvider; + private JaasEventCheck eventCheck; // ~ Methods @@ -66,37 +69,36 @@ public class JaasAuthenticationProviderTests { String resName = "/" + getClass().getName().replace('.', '/') + ".xml"; context = new ClassPathXmlApplicationContext(resName); eventCheck = (JaasEventCheck) context.getBean("eventCheck"); - jaasProvider = (JaasAuthenticationProvider) context - .getBean("jaasAuthenticationProvider"); + jaasProvider = (JaasAuthenticationProvider) context.getBean("jaasAuthenticationProvider"); } @Test public void testBadPassword() { try { - jaasProvider.authenticate(new UsernamePasswordAuthenticationToken("user", - "asdf")); + jaasProvider.authenticate(new UsernamePasswordAuthenticationToken("user", "asdf")); fail("LoginException should have been thrown for the bad password"); } catch (AuthenticationException e) { } assertThat(eventCheck.failedEvent).as("Failure event not fired").isNotNull(); - assertThat(eventCheck.failedEvent.getException()).withFailMessage("Failure event exception was null").isNotNull(); + assertThat(eventCheck.failedEvent.getException()).withFailMessage("Failure event exception was null") + .isNotNull(); assertThat(eventCheck.successEvent).as("Success event was fired").isNull(); } @Test public void testBadUser() { try { - jaasProvider.authenticate(new UsernamePasswordAuthenticationToken("asdf", - "password")); + jaasProvider.authenticate(new UsernamePasswordAuthenticationToken("asdf", "password")); fail("LoginException should have been thrown for the bad user"); } catch (AuthenticationException e) { } assertThat(eventCheck.failedEvent).as("Failure event not fired").isNotNull(); - assertThat(eventCheck.failedEvent.getException()).withFailMessage("Failure event exception was null").isNotNull(); + assertThat(eventCheck.failedEvent.getException()).withFailMessage("Failure event exception was null") + .isNotNull(); assertThat(eventCheck.successEvent).as("Success event was fired").isNull(); } @@ -133,8 +135,7 @@ public class JaasAuthenticationProviderTests { public void spacesInLoginConfigPathAreAccepted() throws Exception { File configFile; // Create temp directory with a space in the name - File configDir = new File(System.getProperty("java.io.tmpdir") + File.separator - + "jaas test"); + File configDir = new File(System.getProperty("java.io.tmpdir") + File.separator + "jaas test"); configDir.deleteOnExit(); if (configDir.exists()) { @@ -145,9 +146,8 @@ public class JaasAuthenticationProviderTests { configFile.deleteOnExit(); FileOutputStream fos = new FileOutputStream(configFile); PrintWriter pw = new PrintWriter(fos); - pw.append("JAASTestBlah {" - + "org.springframework.security.authentication.jaas.TestLoginModule required;" - + "};"); + pw.append( + "JAASTestBlah {" + "org.springframework.security.authentication.jaas.TestLoginModule required;" + "};"); pw.flush(); pw.close(); @@ -191,8 +191,8 @@ public class JaasAuthenticationProviderTests { @Test public void testFull() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "user", "password", AuthorityUtils.createAuthorityList("ROLE_ONE")); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password", + AuthorityUtils.createAuthorityList("ROLE_ONE")); assertThat(jaasProvider.supports(UsernamePasswordAuthenticationToken.class)).isTrue(); @@ -206,7 +206,8 @@ public class JaasAuthenticationProviderTests { Collection list = auth.getAuthorities(); Set set = AuthorityUtils.authorityListToSet(list); - assertThat(set.contains("ROLE_ONE")).withFailMessage("GrantedAuthorities should not contain ROLE_ONE").isFalse(); + assertThat(set.contains("ROLE_ONE")).withFailMessage("GrantedAuthorities should not contain ROLE_ONE") + .isFalse(); assertThat(set.contains("ROLE_TEST1")).withFailMessage("GrantedAuthorities should contain ROLE_TEST1").isTrue(); assertThat(set.contains("ROLE_TEST2")).withFailMessage("GrantedAuthorities should contain ROLE_TEST2").isTrue(); boolean foundit = false; @@ -214,7 +215,8 @@ public class JaasAuthenticationProviderTests { for (GrantedAuthority a : list) { if (a instanceof JaasGrantedAuthority) { JaasGrantedAuthority grant = (JaasGrantedAuthority) a; - assertThat(grant.getPrincipal()).withFailMessage("Principal was null on JaasGrantedAuthority").isNotNull(); + assertThat(grant.getPrincipal()).withFailMessage("Principal was null on JaasGrantedAuthority") + .isNotNull(); foundit = true; } } @@ -222,7 +224,8 @@ public class JaasAuthenticationProviderTests { assertThat(foundit).as("Could not find a JaasGrantedAuthority").isTrue(); assertThat(eventCheck.successEvent).as("Success event should be fired").isNotNull(); - assertThat(eventCheck.successEvent.getAuthentication()).withFailMessage("Auth objects should be equal").isEqualTo(auth); + assertThat(eventCheck.successEvent.getAuthentication()).withFailMessage("Auth objects should be equal") + .isEqualTo(auth); assertThat(eventCheck.failedEvent).as("Failure event should not be fired").isNull(); } @@ -237,8 +240,7 @@ public class JaasAuthenticationProviderTests { jaasProvider.setLoginExceptionResolver(e -> new LockedException("This is just a test!")); try { - jaasProvider.authenticate(new UsernamePasswordAuthenticationToken("user", - "password")); + jaasProvider.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); } catch (LockedException e) { } @@ -249,11 +251,9 @@ public class JaasAuthenticationProviderTests { @Test public void testLogout() throws Exception { - MockLoginContext loginContext = new MockLoginContext( - jaasProvider.getLoginContextName()); + MockLoginContext loginContext = new MockLoginContext(jaasProvider.getLoginContextName()); - JaasAuthenticationToken token = new JaasAuthenticationToken(null, null, - loginContext); + JaasAuthenticationToken token = new JaasAuthenticationToken(null, null, loginContext); SecurityContext context = SecurityContextHolder.createEmptyContext(); context.setAuthentication(token); @@ -268,26 +268,27 @@ public class JaasAuthenticationProviderTests { @Test public void testNullDefaultAuthorities() { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "user", "password"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password"); assertThat(jaasProvider.supports(UsernamePasswordAuthenticationToken.class)).isTrue(); Authentication auth = jaasProvider.authenticate(token); - assertThat(auth - .getAuthorities()).withFailMessage("Only ROLE_TEST1 and ROLE_TEST2 should have been returned").hasSize(2); + assertThat(auth.getAuthorities()).withFailMessage("Only ROLE_TEST1 and ROLE_TEST2 should have been returned") + .hasSize(2); } @Test public void testUnsupportedAuthenticationObjectReturnsNull() { - assertThat(jaasProvider.authenticate(new TestingAuthenticationToken("foo", "bar", - AuthorityUtils.NO_AUTHORITIES))).isNull(); + assertThat( + jaasProvider.authenticate(new TestingAuthenticationToken("foo", "bar", AuthorityUtils.NO_AUTHORITIES))) + .isNull(); } // ~ Inner Classes // ================================================================================================== private static class MockLoginContext extends LoginContext { + boolean loggedOut = false; MockLoginContext(String loginModule) throws LoginException { @@ -297,5 +298,7 @@ public class JaasAuthenticationProviderTests { public void logout() { this.loggedOut = true; } + } + } diff --git a/core/src/test/java/org/springframework/security/authentication/jaas/JaasEventCheck.java b/core/src/test/java/org/springframework/security/authentication/jaas/JaasEventCheck.java index 9760f2863c..68c5b61613 100644 --- a/core/src/test/java/org/springframework/security/authentication/jaas/JaasEventCheck.java +++ b/core/src/test/java/org/springframework/security/authentication/jaas/JaasEventCheck.java @@ -25,10 +25,12 @@ import org.springframework.security.authentication.jaas.event.JaasAuthentication * @author Ray Krueger */ public class JaasEventCheck implements ApplicationListener { + // ~ Instance fields // ================================================================================================ JaasAuthenticationFailedEvent failedEvent; + JaasAuthenticationSuccessEvent successEvent; // ~ Methods @@ -43,4 +45,5 @@ public class JaasEventCheck implements ApplicationListener new JaasGrantedAuthority(null, null)) - .isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> new JaasGrantedAuthority(null, null)).isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("role cannot be null"); } @@ -41,8 +39,8 @@ public class JaasGrantedAuthorityTests { */ @Test public void authorityWithNullPrincipleFailsAssertion() { - assertThatThrownBy(() -> new JaasGrantedAuthority("role", null)) - .isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> new JaasGrantedAuthority("role", null)).isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("principal cannot be null"); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/jaas/Sec760Tests.java b/core/src/test/java/org/springframework/security/authentication/jaas/Sec760Tests.java index e1d0010d4a..d33018425c 100644 --- a/core/src/test/java/org/springframework/security/authentication/jaas/Sec760Tests.java +++ b/core/src/test/java/org/springframework/security/authentication/jaas/Sec760Tests.java @@ -37,36 +37,31 @@ import org.springframework.security.core.authority.AuthorityUtils; public class Sec760Tests { public String resolveConfigFile(String filename) { - String resName = "/" + getClass().getPackage().getName().replace('.', '/') - + filename; + String resName = "/" + getClass().getPackage().getName().replace('.', '/') + filename; return resName; } - private void testConfigureJaasCase(JaasAuthenticationProvider p1, - JaasAuthenticationProvider p2) throws Exception { + private void testConfigureJaasCase(JaasAuthenticationProvider p1, JaasAuthenticationProvider p2) throws Exception { p1.setLoginConfig(new ClassPathResource(resolveConfigFile("/test1.conf"))); p1.setLoginContextName("test1"); - p1.setCallbackHandlers(new JaasAuthenticationCallbackHandler[] { - new TestCallbackHandler(), new JaasNameCallbackHandler(), - new JaasPasswordCallbackHandler() }); + p1.setCallbackHandlers(new JaasAuthenticationCallbackHandler[] { new TestCallbackHandler(), + new JaasNameCallbackHandler(), new JaasPasswordCallbackHandler() }); p1.setAuthorityGranters(new AuthorityGranter[] { new TestAuthorityGranter() }); p1.afterPropertiesSet(); testAuthenticate(p1); p2.setLoginConfig(new ClassPathResource(resolveConfigFile("/test2.conf"))); p2.setLoginContextName("test2"); - p2.setCallbackHandlers(new JaasAuthenticationCallbackHandler[] { - new TestCallbackHandler(), new JaasNameCallbackHandler(), - new JaasPasswordCallbackHandler() }); + p2.setCallbackHandlers(new JaasAuthenticationCallbackHandler[] { new TestCallbackHandler(), + new JaasNameCallbackHandler(), new JaasPasswordCallbackHandler() }); p2.setAuthorityGranters(new AuthorityGranter[] { new TestAuthorityGranter() }); p2.afterPropertiesSet(); testAuthenticate(p2); } private void testAuthenticate(JaasAuthenticationProvider p1) { - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - "user", "password", AuthorityUtils.createAuthorityList("ROLE_ONE", - "ROLE_TWO")); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password", + AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO")); Authentication auth = p1.authenticate(token); assertThat(auth).isNotNull(); @@ -74,8 +69,7 @@ public class Sec760Tests { @Test public void testConfigureJaas() throws Exception { - testConfigureJaasCase(new JaasAuthenticationProvider(), - new JaasAuthenticationProvider()); + testConfigureJaasCase(new JaasAuthenticationProvider(), new JaasAuthenticationProvider()); } } diff --git a/core/src/test/java/org/springframework/security/authentication/jaas/SecurityContextLoginModuleTests.java b/core/src/test/java/org/springframework/security/authentication/jaas/SecurityContextLoginModuleTests.java index f34222e28c..9d47287550 100644 --- a/core/src/test/java/org/springframework/security/authentication/jaas/SecurityContextLoginModuleTests.java +++ b/core/src/test/java/org/springframework/security/authentication/jaas/SecurityContextLoginModuleTests.java @@ -39,14 +39,16 @@ import static org.assertj.core.api.Assertions.fail; * @author Ray Krueger */ public class SecurityContextLoginModuleTests { + // ~ Instance fields // ================================================================================================ private SecurityContextLoginModule module = null; - private Subject subject = new Subject(false, new HashSet<>(), - new HashSet<>(), new HashSet<>()); - private UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken( - "principal", "credentials"); + + private Subject subject = new Subject(false, new HashSet<>(), new HashSet<>(), new HashSet<>()); + + private UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("principal", + "credentials"); // ~ Methods // ======================================================================================================== @@ -66,8 +68,7 @@ public class SecurityContextLoginModuleTests { @Test public void testAbort() throws Exception { - assertThat(this.module.abort()).as("Should return false, no auth is set") - .isFalse(); + assertThat(this.module.abort()).as("Should return false, no auth is set").isFalse(); SecurityContextHolder.getContext().setAuthentication(this.auth); this.module.login(); this.module.commit(); @@ -87,11 +88,8 @@ public class SecurityContextLoginModuleTests { @Test public void testLoginSuccess() throws Exception { SecurityContextHolder.getContext().setAuthentication(this.auth); - assertThat(this.module.login()) - .as("Login should succeed, there is an authentication set").isTrue(); - assertThat(this.module.commit()) - .withFailMessage( - "The authentication is not null, this should return true") + assertThat(this.module.login()).as("Login should succeed, there is an authentication set").isTrue(); + assertThat(this.module.commit()).withFailMessage("The authentication is not null, this should return true") .isTrue(); assertThat(this.subject.getPrincipals().contains(this.auth)) .withFailMessage("Principals should contain the authentication").isTrue(); @@ -102,13 +100,10 @@ public class SecurityContextLoginModuleTests { SecurityContextHolder.getContext().setAuthentication(this.auth); this.module.login(); assertThat(this.module.logout()).as("Should return true as it succeeds").isTrue(); - assertThat(this.module.getAuthentication()).as("Authentication should be null") - .isNull(); + assertThat(this.module.getAuthentication()).as("Authentication should be null").isNull(); assertThat(this.subject.getPrincipals().contains(this.auth)) - .withFailMessage( - "Principals should not contain the authentication after logout") - .isFalse(); + .withFailMessage("Principals should not contain the authentication after logout").isFalse(); } @Test @@ -131,12 +126,12 @@ public class SecurityContextLoginModuleTests { this.module.initialize(this.subject, null, null, options); SecurityContextHolder.getContext().setAuthentication(null); - assertThat(this.module.login()).as("Should return false and ask to be ignored") - .isFalse(); + assertThat(this.module.login()).as("Should return false and ask to be ignored").isFalse(); } @Test public void testNullLogout() throws Exception { assertThat(this.module.logout()).isFalse(); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/jaas/TestAuthorityGranter.java b/core/src/test/java/org/springframework/security/authentication/jaas/TestAuthorityGranter.java index 2f82d9ea53..e8ab46cf2a 100644 --- a/core/src/test/java/org/springframework/security/authentication/jaas/TestAuthorityGranter.java +++ b/core/src/test/java/org/springframework/security/authentication/jaas/TestAuthorityGranter.java @@ -24,10 +24,10 @@ import java.util.Set; import org.springframework.security.authentication.jaas.AuthorityGranter; /** - * * @author Ray Krueger */ public class TestAuthorityGranter implements AuthorityGranter { + // ~ Methods // ======================================================================================================== @@ -41,4 +41,5 @@ public class TestAuthorityGranter implements AuthorityGranter { return rtnSet; } + } diff --git a/core/src/test/java/org/springframework/security/authentication/jaas/TestCallbackHandler.java b/core/src/test/java/org/springframework/security/authentication/jaas/TestCallbackHandler.java index a32494f5fd..1d222f0689 100644 --- a/core/src/test/java/org/springframework/security/authentication/jaas/TestCallbackHandler.java +++ b/core/src/test/java/org/springframework/security/authentication/jaas/TestCallbackHandler.java @@ -28,6 +28,7 @@ import javax.security.auth.callback.TextInputCallback; * @author Ray Krueger */ public class TestCallbackHandler implements JaasAuthenticationCallbackHandler { + // ~ Methods // ======================================================================================================== @@ -37,4 +38,5 @@ public class TestCallbackHandler implements JaasAuthenticationCallbackHandler { tic.setText(auth.getPrincipal().toString()); } } + } diff --git a/core/src/test/java/org/springframework/security/authentication/jaas/TestLoginModule.java b/core/src/test/java/org/springframework/security/authentication/jaas/TestLoginModule.java index 53ff92c19b..d7a6c4f3e3 100644 --- a/core/src/test/java/org/springframework/security/authentication/jaas/TestLoginModule.java +++ b/core/src/test/java/org/springframework/security/authentication/jaas/TestLoginModule.java @@ -27,11 +27,14 @@ import javax.security.auth.spi.LoginModule; * @author Ray Krueger */ public class TestLoginModule implements LoginModule { + // ~ Instance fields // ================================================================================================ private String password; + private String user; + private Subject subject; // ~ Methods @@ -46,8 +49,7 @@ public class TestLoginModule implements LoginModule { } @SuppressWarnings("unchecked") - public void initialize(Subject subject, CallbackHandler callbackHandler, - Map sharedState, Map options) { + public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { this.subject = subject; try { @@ -55,8 +57,7 @@ public class TestLoginModule implements LoginModule { NameCallback nameCallback = new NameCallback("prompt"); PasswordCallback passwordCallback = new PasswordCallback("prompt", false); - callbackHandler.handle(new Callback[] { textCallback, nameCallback, - passwordCallback }); + callbackHandler.handle(new Callback[] { textCallback, nameCallback, passwordCallback }); password = new String(passwordCallback.getPassword()); user = nameCallback.getName(); @@ -85,4 +86,5 @@ public class TestLoginModule implements LoginModule { public boolean logout() { return true; } + } diff --git a/core/src/test/java/org/springframework/security/authentication/jaas/memory/InMemoryConfigurationTests.java b/core/src/test/java/org/springframework/security/authentication/jaas/memory/InMemoryConfigurationTests.java index 6384c0a922..7b4a690151 100644 --- a/core/src/test/java/org/springframework/security/authentication/jaas/memory/InMemoryConfigurationTests.java +++ b/core/src/test/java/org/springframework/security/authentication/jaas/memory/InMemoryConfigurationTests.java @@ -37,25 +37,22 @@ import static org.assertj.core.api.Assertions.assertThat; public class InMemoryConfigurationTests { private AppConfigurationEntry[] defaultEntries; + private Map mappedEntries; @Before public void setUp() { - this.defaultEntries = new AppConfigurationEntry[] { new AppConfigurationEntry( - TestLoginModule.class.getName(), LoginModuleControlFlag.REQUIRED, - Collections.emptyMap()) }; + this.defaultEntries = new AppConfigurationEntry[] { new AppConfigurationEntry(TestLoginModule.class.getName(), + LoginModuleControlFlag.REQUIRED, Collections.emptyMap()) }; - this.mappedEntries = Collections.singletonMap( - "name", - new AppConfigurationEntry[] { new AppConfigurationEntry( - TestLoginModule.class.getName(), LoginModuleControlFlag.OPTIONAL, - Collections.emptyMap()) }); + this.mappedEntries = Collections.singletonMap("name", + new AppConfigurationEntry[] { new AppConfigurationEntry(TestLoginModule.class.getName(), + LoginModuleControlFlag.OPTIONAL, Collections.emptyMap()) }); } @Test public void constructorNullDefault() { - assertThat(new InMemoryConfiguration((AppConfigurationEntry[]) null) - .getAppConfigurationEntry("name")).isNull(); + assertThat(new InMemoryConfiguration((AppConfigurationEntry[]) null).getAppConfigurationEntry("name")).isNull(); } @Test(expected = IllegalArgumentException.class) @@ -65,16 +62,14 @@ public class InMemoryConfigurationTests { @Test public void constructorEmptyMap() { - assertThat(new InMemoryConfiguration( - Collections.emptyMap()) - .getAppConfigurationEntry("name")).isNull(); + assertThat(new InMemoryConfiguration(Collections.emptyMap()) + .getAppConfigurationEntry("name")).isNull(); } @Test public void constructorEmptyMapNullDefault() { - assertThat(new InMemoryConfiguration( - Collections.emptyMap(), null) - .getAppConfigurationEntry("name")).isNull(); + assertThat(new InMemoryConfiguration(Collections.emptyMap(), null) + .getAppConfigurationEntry("name")).isNull(); } @Test(expected = IllegalArgumentException.class) @@ -84,20 +79,15 @@ public class InMemoryConfigurationTests { @Test public void nonnullDefault() { - InMemoryConfiguration configuration = new InMemoryConfiguration( - this.defaultEntries); - assertThat(configuration.getAppConfigurationEntry("name")) - .isEqualTo(this.defaultEntries); + InMemoryConfiguration configuration = new InMemoryConfiguration(this.defaultEntries); + assertThat(configuration.getAppConfigurationEntry("name")).isEqualTo(this.defaultEntries); } @Test public void mappedNonnullDefault() { - InMemoryConfiguration configuration = new InMemoryConfiguration( - this.mappedEntries, this.defaultEntries); - assertThat(this.defaultEntries) - .isEqualTo(configuration.getAppConfigurationEntry("missing")); - assertThat(this.mappedEntries.get("name")) - .isEqualTo(configuration.getAppConfigurationEntry("name")); + InMemoryConfiguration configuration = new InMemoryConfiguration(this.mappedEntries, this.defaultEntries); + assertThat(this.defaultEntries).isEqualTo(configuration.getAppConfigurationEntry("missing")); + assertThat(this.mappedEntries.get("name")).isEqualTo(configuration.getAppConfigurationEntry("name")); } @Test @@ -105,4 +95,5 @@ public class InMemoryConfigurationTests { Method method = InMemoryConfiguration.class.getDeclaredMethod("refresh"); assertThat(method.getDeclaringClass()).isEqualTo(InMemoryConfiguration.class); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImplTests.java b/core/src/test/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImplTests.java index a7f5f25732..cd50afa5b6 100644 --- a/core/src/test/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImplTests.java +++ b/core/src/test/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImplTests.java @@ -31,6 +31,7 @@ import org.springframework.security.core.Authentication; * @author Ben Alex */ public class RemoteAuthenticationManagerImplTests { + // ~ Methods // ======================================================================================================== @@ -38,8 +39,7 @@ public class RemoteAuthenticationManagerImplTests { public void testFailedAuthenticationReturnsRemoteAuthenticationException() { RemoteAuthenticationManagerImpl manager = new RemoteAuthenticationManagerImpl(); AuthenticationManager am = mock(AuthenticationManager.class); - when(am.authenticate(any(Authentication.class))).thenThrow( - new BadCredentialsException("")); + when(am.authenticate(any(Authentication.class))).thenThrow(new BadCredentialsException("")); manager.setAuthenticationManager(am); manager.attemptAuthentication("rod", "password"); @@ -65,10 +65,10 @@ public class RemoteAuthenticationManagerImplTests { public void testSuccessfulAuthentication() { RemoteAuthenticationManagerImpl manager = new RemoteAuthenticationManagerImpl(); AuthenticationManager am = mock(AuthenticationManager.class); - when(am.authenticate(any(Authentication.class))).thenReturn( - new TestingAuthenticationToken("u", "p", "A")); + when(am.authenticate(any(Authentication.class))).thenReturn(new TestingAuthenticationToken("u", "p", "A")); manager.setAuthenticationManager(am); manager.attemptAuthentication("rod", "password"); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/rcp/RemoteAuthenticationProviderTests.java b/core/src/test/java/org/springframework/security/authentication/rcp/RemoteAuthenticationProviderTests.java index c66f3b503f..8e35e05037 100644 --- a/core/src/test/java/org/springframework/security/authentication/rcp/RemoteAuthenticationProviderTests.java +++ b/core/src/test/java/org/springframework/security/authentication/rcp/RemoteAuthenticationProviderTests.java @@ -34,18 +34,17 @@ import static org.assertj.core.api.Assertions.fail; * @author Ben Alex */ public class RemoteAuthenticationProviderTests { + // ~ Methods // ======================================================================================================== @Test public void testExceptionsGetPassedBackToCaller() { RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider(); - provider.setRemoteAuthenticationManager( - new MockRemoteAuthenticationManager(false)); + provider.setRemoteAuthenticationManager(new MockRemoteAuthenticationManager(false)); try { - provider.authenticate( - new UsernamePasswordAuthenticationToken("rod", "password")); + provider.authenticate(new UsernamePasswordAuthenticationToken("rod", "password")); fail("Should have thrown RemoteAuthenticationException"); } catch (RemoteAuthenticationException expected) { @@ -56,8 +55,7 @@ public class RemoteAuthenticationProviderTests { @Test public void testGettersSetters() { RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider(); - provider.setRemoteAuthenticationManager( - new MockRemoteAuthenticationManager(true)); + provider.setRemoteAuthenticationManager(new MockRemoteAuthenticationManager(true)); assertThat(provider.getRemoteAuthenticationManager()).isNotNull(); } @@ -73,8 +71,7 @@ public class RemoteAuthenticationProviderTests { } - provider.setRemoteAuthenticationManager( - new MockRemoteAuthenticationManager(true)); + provider.setRemoteAuthenticationManager(new MockRemoteAuthenticationManager(true)); provider.afterPropertiesSet(); } @@ -82,11 +79,9 @@ public class RemoteAuthenticationProviderTests { @Test public void testSuccessfulAuthenticationCreatesObject() { RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider(); - provider.setRemoteAuthenticationManager( - new MockRemoteAuthenticationManager(true)); + provider.setRemoteAuthenticationManager(new MockRemoteAuthenticationManager(true)); - Authentication result = provider - .authenticate(new UsernamePasswordAuthenticationToken("rod", "password")); + Authentication result = provider.authenticate(new UsernamePasswordAuthenticationToken("rod", "password")); assertThat(result.getPrincipal()).isEqualTo("rod"); assertThat(result.getCredentials()).isEqualTo("password"); assertThat(AuthorityUtils.authorityListToSet(result.getAuthorities())).contains("foo"); @@ -95,8 +90,7 @@ public class RemoteAuthenticationProviderTests { @Test public void testNullCredentialsDoesNotCauseNullPointerException() { RemoteAuthenticationProvider provider = new RemoteAuthenticationProvider(); - provider.setRemoteAuthenticationManager( - new MockRemoteAuthenticationManager(false)); + provider.setRemoteAuthenticationManager(new MockRemoteAuthenticationManager(false)); try { provider.authenticate(new UsernamePasswordAuthenticationToken("rod", null)); @@ -117,14 +111,15 @@ public class RemoteAuthenticationProviderTests { // ================================================================================================== private class MockRemoteAuthenticationManager implements RemoteAuthenticationManager { + private boolean grantAccess; MockRemoteAuthenticationManager(boolean grantAccess) { this.grantAccess = grantAccess; } - public Collection attemptAuthentication( - String username, String password) throws RemoteAuthenticationException { + public Collection attemptAuthentication(String username, String password) + throws RemoteAuthenticationException { if (this.grantAccess) { return AuthorityUtils.createAuthorityList("foo"); } @@ -132,5 +127,7 @@ public class RemoteAuthenticationProviderTests { throw new RemoteAuthenticationException("as requested"); } } + } + } diff --git a/core/src/test/java/org/springframework/security/authentication/rememberme/RememberMeAuthenticationProviderTests.java b/core/src/test/java/org/springframework/security/authentication/rememberme/RememberMeAuthenticationProviderTests.java index c6a948e913..e481cb8a91 100644 --- a/core/src/test/java/org/springframework/security/authentication/rememberme/RememberMeAuthenticationProviderTests.java +++ b/core/src/test/java/org/springframework/security/authentication/rememberme/RememberMeAuthenticationProviderTests.java @@ -34,15 +34,14 @@ import static org.assertj.core.api.Assertions.fail; * @author Ben Alex */ public class RememberMeAuthenticationProviderTests { + // ~ Methods // ======================================================================================================== @Test public void testDetectsAnInvalidKey() { - RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider( - "qwerty"); + RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider("qwerty"); - RememberMeAuthenticationToken token = new RememberMeAuthenticationToken( - "WRONG_KEY", "Test", + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("WRONG_KEY", "Test", AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO")); try { @@ -66,19 +65,16 @@ public class RememberMeAuthenticationProviderTests { @Test public void testGettersSetters() throws Exception { - RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider( - "qwerty"); + RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider("qwerty"); aap.afterPropertiesSet(); assertThat(aap.getKey()).isEqualTo("qwerty"); } @Test public void testIgnoresClassesItDoesNotSupport() { - RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider( - "qwerty"); + RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider("qwerty"); - TestingAuthenticationToken token = new TestingAuthenticationToken("user", - "password", "ROLE_A"); + TestingAuthenticationToken token = new TestingAuthenticationToken("user", "password", "ROLE_A"); assertThat(aap.supports(TestingAuthenticationToken.class)).isFalse(); // Try it anyway @@ -87,11 +83,10 @@ public class RememberMeAuthenticationProviderTests { @Test public void testNormalOperation() { - RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider( - "qwerty"); + RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider("qwerty"); - RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("qwerty", - "Test", AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO")); + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("qwerty", "Test", + AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO")); Authentication result = aap.authenticate(token); @@ -100,9 +95,9 @@ public class RememberMeAuthenticationProviderTests { @Test public void testSupports() { - RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider( - "qwerty"); + RememberMeAuthenticationProvider aap = new RememberMeAuthenticationProvider("qwerty"); assertThat(aap.supports(RememberMeAuthenticationToken.class)).isTrue(); assertThat(aap.supports(TestingAuthenticationToken.class)).isFalse(); } + } diff --git a/core/src/test/java/org/springframework/security/authentication/rememberme/RememberMeAuthenticationTokenTests.java b/core/src/test/java/org/springframework/security/authentication/rememberme/RememberMeAuthenticationTokenTests.java index dcd7ac2c8c..b5ef5417d4 100644 --- a/core/src/test/java/org/springframework/security/authentication/rememberme/RememberMeAuthenticationTokenTests.java +++ b/core/src/test/java/org/springframework/security/authentication/rememberme/RememberMeAuthenticationTokenTests.java @@ -16,7 +16,6 @@ package org.springframework.security.authentication.rememberme; - import static org.assertj.core.api.Assertions.*; import java.util.ArrayList; @@ -34,8 +33,8 @@ import org.springframework.security.core.authority.AuthorityUtils; * @author Ben Alex */ public class RememberMeAuthenticationTokenTests { - private static final List ROLES_12 = AuthorityUtils - .createAuthorityList("ROLE_ONE", "ROLE_TWO"); + + private static final List ROLES_12 = AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"); // ~ Methods // ======================================================================================================== @@ -70,18 +69,15 @@ public class RememberMeAuthenticationTokenTests { @Test public void testEqualsWhenEqual() { - RememberMeAuthenticationToken token1 = new RememberMeAuthenticationToken("key", - "Test", ROLES_12); - RememberMeAuthenticationToken token2 = new RememberMeAuthenticationToken("key", - "Test", ROLES_12); + RememberMeAuthenticationToken token1 = new RememberMeAuthenticationToken("key", "Test", ROLES_12); + RememberMeAuthenticationToken token2 = new RememberMeAuthenticationToken("key", "Test", ROLES_12); assertThat(token2).isEqualTo(token1); } @Test public void testGetters() { - RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("key", - "Test", ROLES_12); + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("key", "Test", ROLES_12); assertThat(token.getKeyHash()).isEqualTo("key".hashCode()); assertThat(token.getPrincipal()).isEqualTo("Test"); @@ -93,40 +89,36 @@ public class RememberMeAuthenticationTokenTests { @Test public void testNotEqualsDueToAbstractParentEqualsCheck() { - RememberMeAuthenticationToken token1 = new RememberMeAuthenticationToken("key", - "Test", ROLES_12); - RememberMeAuthenticationToken token2 = new RememberMeAuthenticationToken("key", - "DIFFERENT_PRINCIPAL", ROLES_12); + RememberMeAuthenticationToken token1 = new RememberMeAuthenticationToken("key", "Test", ROLES_12); + RememberMeAuthenticationToken token2 = new RememberMeAuthenticationToken("key", "DIFFERENT_PRINCIPAL", + ROLES_12); assertThat(token1.equals(token2)).isFalse(); } @Test public void testNotEqualsDueToDifferentAuthenticationClass() { - RememberMeAuthenticationToken token1 = new RememberMeAuthenticationToken("key", - "Test", ROLES_12); - UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken( - "Test", "Password", ROLES_12); + RememberMeAuthenticationToken token1 = new RememberMeAuthenticationToken("key", "Test", ROLES_12); + UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken("Test", "Password", + ROLES_12); assertThat(token1.equals(token2)).isFalse(); } @Test public void testNotEqualsDueToKey() { - RememberMeAuthenticationToken token1 = new RememberMeAuthenticationToken("key", - "Test", ROLES_12); - RememberMeAuthenticationToken token2 = new RememberMeAuthenticationToken( - "DIFFERENT_KEY", "Test", ROLES_12); + RememberMeAuthenticationToken token1 = new RememberMeAuthenticationToken("key", "Test", ROLES_12); + RememberMeAuthenticationToken token2 = new RememberMeAuthenticationToken("DIFFERENT_KEY", "Test", ROLES_12); assertThat(token1.equals(token2)).isFalse(); } @Test public void testSetAuthenticatedIgnored() { - RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("key", - "Test", ROLES_12); + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken("key", "Test", ROLES_12); assertThat(token.isAuthenticated()).isTrue(); token.setAuthenticated(false); assertThat(!token.isAuthenticated()).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/authorization/AuthenticatedReactiveAuthorizationManagerTests.java b/core/src/test/java/org/springframework/security/authorization/AuthenticatedReactiveAuthorizationManagerTests.java index cb05abb276..4b2d9867d9 100644 --- a/core/src/test/java/org/springframework/security/authorization/AuthenticatedReactiveAuthorizationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authorization/AuthenticatedReactiveAuthorizationManagerTests.java @@ -35,11 +35,12 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class AuthenticatedReactiveAuthorizationManagerTests { + @Mock Authentication authentication; AuthenticatedReactiveAuthorizationManager manager = AuthenticatedReactiveAuthorizationManager - .authenticated(); + .authenticated(); @Test public void checkWhenAuthenticatedThenReturnTrue() { @@ -77,9 +78,7 @@ public class AuthenticatedReactiveAuthorizationManagerTests { public void checkWhenErrorThenError() { Mono result = manager.check(Mono.error(new RuntimeException("ooops")), null); - StepVerifier - .create(result) - .expectError() - .verify(); + StepVerifier.create(result).expectError().verify(); } + } diff --git a/core/src/test/java/org/springframework/security/authorization/AuthorityReactiveAuthorizationManagerTests.java b/core/src/test/java/org/springframework/security/authorization/AuthorityReactiveAuthorizationManagerTests.java index 2fb371fa35..8fddc9d217 100644 --- a/core/src/test/java/org/springframework/security/authorization/AuthorityReactiveAuthorizationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authorization/AuthorityReactiveAuthorizationManagerTests.java @@ -36,11 +36,11 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class AuthorityReactiveAuthorizationManagerTests { + @Mock Authentication authentication; - AuthorityReactiveAuthorizationManager manager = AuthorityReactiveAuthorizationManager - .hasAuthority("ADMIN"); + AuthorityReactiveAuthorizationManager manager = AuthorityReactiveAuthorizationManager.hasAuthority("ADMIN"); @Test public void checkWhenHasAuthorityAndNotAuthenticatedThenReturnFalse() { @@ -60,10 +60,7 @@ public class AuthorityReactiveAuthorizationManagerTests { public void checkWhenHasAuthorityAndErrorThenError() { Mono result = manager.check(Mono.error(new RuntimeException("ooops")), null); - StepVerifier - .create(result) - .expectError() - .verify(); + StepVerifier.create(result).expectError().verify(); } @Test @@ -171,4 +168,5 @@ public class AuthorityReactiveAuthorizationManagerTests { String authority2 = null; AuthorityReactiveAuthorizationManager.hasAnyAuthority(authority1, authority2); } + } diff --git a/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextExecutorServiceTests.java b/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextExecutorServiceTests.java index a88d1dadab..e2df987e42 100644 --- a/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextExecutorServiceTests.java +++ b/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextExecutorServiceTests.java @@ -39,10 +39,12 @@ import org.mockito.Mock; * @see CurrentDelegatingSecurityContextExecutorServiceTests * @see ExplicitDelegatingSecurityContextExecutorServiceTests */ -public abstract class AbstractDelegatingSecurityContextExecutorServiceTests extends - AbstractDelegatingSecurityContextExecutorTests { +public abstract class AbstractDelegatingSecurityContextExecutorServiceTests + extends AbstractDelegatingSecurityContextExecutorTests { + @Mock private Future expectedFutureObject; + @Mock private Object resultArg; @@ -89,8 +91,7 @@ public abstract class AbstractDelegatingSecurityContextExecutorServiceTests exte public void awaitTermination() throws InterruptedException { boolean result = executor.awaitTermination(1, TimeUnit.SECONDS); verify(delegate).awaitTermination(1, TimeUnit.SECONDS); - assertThat(result).isEqualTo(delegate.awaitTermination(1, TimeUnit.SECONDS)) - .isNotNull(); + assertThat(result).isEqualTo(delegate.awaitTermination(1, TimeUnit.SECONDS)).isNotNull(); } @Test @@ -103,8 +104,7 @@ public abstract class AbstractDelegatingSecurityContextExecutorServiceTests exte @Test public void submitRunnableWithResult() { - when(delegate.submit(wrappedRunnable, resultArg)) - .thenReturn(expectedFutureObject); + when(delegate.submit(wrappedRunnable, resultArg)).thenReturn(expectedFutureObject); Future result = executor.submit(runnable, resultArg); verify(delegate).submit(wrappedRunnable, resultArg); assertThat(result).isEqualTo(expectedFutureObject); @@ -113,8 +113,7 @@ public abstract class AbstractDelegatingSecurityContextExecutorServiceTests exte @Test @SuppressWarnings("unchecked") public void submitRunnable() { - when((Future) delegate.submit(wrappedRunnable)).thenReturn( - expectedFutureObject); + when((Future) delegate.submit(wrappedRunnable)).thenReturn(expectedFutureObject); Future result = executor.submit(runnable); verify(delegate).submit(wrappedRunnable); assertThat(result).isEqualTo(expectedFutureObject); @@ -136,10 +135,8 @@ public abstract class AbstractDelegatingSecurityContextExecutorServiceTests exte public void invokeAllTimeout() throws Exception { List> exectedResult = Arrays.asList(expectedFutureObject); List> wrappedCallables = Arrays.asList(wrappedCallable); - when(delegate.invokeAll(wrappedCallables, 1, TimeUnit.SECONDS)).thenReturn( - exectedResult); - List> result = executor.invokeAll(Arrays.asList(callable), 1, - TimeUnit.SECONDS); + when(delegate.invokeAll(wrappedCallables, 1, TimeUnit.SECONDS)).thenReturn(exectedResult); + List> result = executor.invokeAll(Arrays.asList(callable), 1, TimeUnit.SECONDS); verify(delegate).invokeAll(wrappedCallables, 1, TimeUnit.SECONDS); assertThat(result).isEqualTo(exectedResult); } @@ -160,12 +157,12 @@ public abstract class AbstractDelegatingSecurityContextExecutorServiceTests exte public void invokeAnyTimeout() throws Exception { List> exectedResult = Arrays.asList(expectedFutureObject); List> wrappedCallables = Arrays.asList(wrappedCallable); - when(delegate.invokeAny(wrappedCallables, 1, TimeUnit.SECONDS)).thenReturn( - exectedResult); + when(delegate.invokeAny(wrappedCallables, 1, TimeUnit.SECONDS)).thenReturn(exectedResult); Object result = executor.invokeAny(Arrays.asList(callable), 1, TimeUnit.SECONDS); verify(delegate).invokeAny(wrappedCallables, 1, TimeUnit.SECONDS); assertThat(result).isEqualTo(exectedResult); } protected abstract DelegatingSecurityContextExecutorService create(); + } diff --git a/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextExecutorTests.java b/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextExecutorTests.java index 3e3dfc5d4e..6932a78920 100644 --- a/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextExecutorTests.java +++ b/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextExecutorTests.java @@ -33,8 +33,9 @@ import org.mockito.Mock; * @see CurrentDelegatingSecurityContextExecutorTests * @see ExplicitDelegatingSecurityContextExecutorTests */ -public abstract class AbstractDelegatingSecurityContextExecutorTests extends - AbstractDelegatingSecurityContextTestSupport { +public abstract class AbstractDelegatingSecurityContextExecutorTests + extends AbstractDelegatingSecurityContextTestSupport { + @Mock protected ScheduledExecutorService delegate; @@ -61,4 +62,5 @@ public abstract class AbstractDelegatingSecurityContextExecutorTests extends } protected abstract DelegatingSecurityContextExecutor create(); + } diff --git a/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextScheduledExecutorServiceTests.java b/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextScheduledExecutorServiceTests.java index ec0d114bb7..a02b3f2500 100644 --- a/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextScheduledExecutorServiceTests.java +++ b/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextScheduledExecutorServiceTests.java @@ -38,6 +38,7 @@ import org.mockito.Mock; */ public abstract class AbstractDelegatingSecurityContextScheduledExecutorServiceTests extends AbstractDelegatingSecurityContextExecutorServiceTests { + @Mock private ScheduledFuture expectedResult; @@ -51,9 +52,8 @@ public abstract class AbstractDelegatingSecurityContextScheduledExecutorServiceT @Test @SuppressWarnings("unchecked") public void scheduleRunnable() { - when( - (ScheduledFuture) delegate.schedule(wrappedRunnable, 1, - TimeUnit.SECONDS)).thenReturn(expectedResult); + when((ScheduledFuture) delegate.schedule(wrappedRunnable, 1, TimeUnit.SECONDS)) + .thenReturn(expectedResult); ScheduledFuture result = executor.schedule(runnable, 1, TimeUnit.SECONDS); assertThat(result).isEqualTo(expectedResult); verify(delegate).schedule(wrappedRunnable, 1, TimeUnit.SECONDS); @@ -61,9 +61,7 @@ public abstract class AbstractDelegatingSecurityContextScheduledExecutorServiceT @Test public void scheduleCallable() { - when( - delegate.schedule(wrappedCallable, 1, - TimeUnit.SECONDS)).thenReturn(expectedResult); + when(delegate.schedule(wrappedCallable, 1, TimeUnit.SECONDS)).thenReturn(expectedResult); ScheduledFuture result = executor.schedule(callable, 1, TimeUnit.SECONDS); assertThat(result).isEqualTo(expectedResult); verify(delegate).schedule(wrappedCallable, 1, TimeUnit.SECONDS); @@ -72,11 +70,9 @@ public abstract class AbstractDelegatingSecurityContextScheduledExecutorServiceT @Test @SuppressWarnings("unchecked") public void scheduleAtFixedRate() { - when( - (ScheduledFuture) delegate.scheduleAtFixedRate(wrappedRunnable, - 1, 2, TimeUnit.SECONDS)).thenReturn(expectedResult); - ScheduledFuture result = executor.scheduleAtFixedRate(runnable, 1, 2, - TimeUnit.SECONDS); + when((ScheduledFuture) delegate.scheduleAtFixedRate(wrappedRunnable, 1, 2, TimeUnit.SECONDS)) + .thenReturn(expectedResult); + ScheduledFuture result = executor.scheduleAtFixedRate(runnable, 1, 2, TimeUnit.SECONDS); assertThat(result).isEqualTo(expectedResult); verify(delegate).scheduleAtFixedRate(wrappedRunnable, 1, 2, TimeUnit.SECONDS); } @@ -84,16 +80,14 @@ public abstract class AbstractDelegatingSecurityContextScheduledExecutorServiceT @Test @SuppressWarnings("unchecked") public void scheduleWithFixedDelay() { - when( - (ScheduledFuture) delegate.scheduleWithFixedDelay( - wrappedRunnable, 1, 2, TimeUnit.SECONDS)).thenReturn( - expectedResult); - ScheduledFuture result = executor.scheduleWithFixedDelay(runnable, 1, 2, - TimeUnit.SECONDS); + when((ScheduledFuture) delegate.scheduleWithFixedDelay(wrappedRunnable, 1, 2, TimeUnit.SECONDS)) + .thenReturn(expectedResult); + ScheduledFuture result = executor.scheduleWithFixedDelay(runnable, 1, 2, TimeUnit.SECONDS); assertThat(result).isEqualTo(expectedResult); verify(delegate).scheduleWithFixedDelay(wrappedRunnable, 1, 2, TimeUnit.SECONDS); } @Override protected abstract DelegatingSecurityContextScheduledExecutorService create(); + } diff --git a/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextTestSupport.java b/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextTestSupport.java index cead9643bb..2f048529ae 100644 --- a/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextTestSupport.java +++ b/core/src/test/java/org/springframework/security/concurrent/AbstractDelegatingSecurityContextTestSupport.java @@ -41,9 +41,9 @@ import org.springframework.security.core.context.SecurityContextHolder; * */ @RunWith(PowerMockRunner.class) -@PrepareForTest({ DelegatingSecurityContextRunnable.class, - DelegatingSecurityContextCallable.class }) +@PrepareForTest({ DelegatingSecurityContextRunnable.class, DelegatingSecurityContextCallable.class }) public abstract class AbstractDelegatingSecurityContextTestSupport { + @Mock protected SecurityContext securityContext; @@ -67,20 +67,18 @@ public abstract class AbstractDelegatingSecurityContextTestSupport { public final void explicitSecurityContextPowermockSetup() throws Exception { spy(DelegatingSecurityContextCallable.class); - doReturn(wrappedCallable).when(DelegatingSecurityContextCallable.class, "create", - eq(callable), securityContextCaptor.capture()); + doReturn(wrappedCallable).when(DelegatingSecurityContextCallable.class, "create", eq(callable), + securityContextCaptor.capture()); spy(DelegatingSecurityContextRunnable.class); - doReturn(wrappedRunnable).when(DelegatingSecurityContextRunnable.class, "create", - eq(runnable), securityContextCaptor.capture()); + doReturn(wrappedRunnable).when(DelegatingSecurityContextRunnable.class, "create", eq(runnable), + securityContextCaptor.capture()); } public final void currentSecurityContextPowermockSetup() throws Exception { spy(DelegatingSecurityContextCallable.class); - doReturn(wrappedCallable).when(DelegatingSecurityContextCallable.class, "create", - callable, null); + doReturn(wrappedCallable).when(DelegatingSecurityContextCallable.class, "create", callable, null); spy(DelegatingSecurityContextRunnable.class); - doReturn(wrappedRunnable).when(DelegatingSecurityContextRunnable.class, "create", - runnable, null); + doReturn(wrappedRunnable).when(DelegatingSecurityContextRunnable.class, "create", runnable, null); } @Before @@ -92,4 +90,5 @@ public abstract class AbstractDelegatingSecurityContextTestSupport { public final void clearContext() { SecurityContextHolder.clearContext(); } + } diff --git a/core/src/test/java/org/springframework/security/concurrent/CurrentDelegatingSecurityContextExecutorServiceTests.java b/core/src/test/java/org/springframework/security/concurrent/CurrentDelegatingSecurityContextExecutorServiceTests.java index 6e757524ff..dc99dd7e23 100644 --- a/core/src/test/java/org/springframework/security/concurrent/CurrentDelegatingSecurityContextExecutorServiceTests.java +++ b/core/src/test/java/org/springframework/security/concurrent/CurrentDelegatingSecurityContextExecutorServiceTests.java @@ -25,8 +25,8 @@ import org.junit.Before; * @since 3.2 * */ -public class CurrentDelegatingSecurityContextExecutorServiceTests extends - AbstractDelegatingSecurityContextExecutorServiceTests { +public class CurrentDelegatingSecurityContextExecutorServiceTests + extends AbstractDelegatingSecurityContextExecutorServiceTests { @Before public void setUp() throws Exception { @@ -37,4 +37,5 @@ public class CurrentDelegatingSecurityContextExecutorServiceTests extends protected DelegatingSecurityContextExecutorService create() { return new DelegatingSecurityContextExecutorService(delegate); } + } \ No newline at end of file diff --git a/core/src/test/java/org/springframework/security/concurrent/CurrentDelegatingSecurityContextExecutorTests.java b/core/src/test/java/org/springframework/security/concurrent/CurrentDelegatingSecurityContextExecutorTests.java index 6e25d87ef9..69e3a42cb9 100644 --- a/core/src/test/java/org/springframework/security/concurrent/CurrentDelegatingSecurityContextExecutorTests.java +++ b/core/src/test/java/org/springframework/security/concurrent/CurrentDelegatingSecurityContextExecutorTests.java @@ -25,8 +25,7 @@ import org.junit.Before; * @since 3.2 * */ -public class CurrentDelegatingSecurityContextExecutorTests extends - AbstractDelegatingSecurityContextExecutorTests { +public class CurrentDelegatingSecurityContextExecutorTests extends AbstractDelegatingSecurityContextExecutorTests { @Before public void setUp() throws Exception { @@ -37,4 +36,5 @@ public class CurrentDelegatingSecurityContextExecutorTests extends protected DelegatingSecurityContextExecutor create() { return new DelegatingSecurityContextExecutor(getExecutor()); } + } diff --git a/core/src/test/java/org/springframework/security/concurrent/CurrentDelegatingSecurityContextScheduledExecutorServiceTests.java b/core/src/test/java/org/springframework/security/concurrent/CurrentDelegatingSecurityContextScheduledExecutorServiceTests.java index 29b19cc47b..c0b7dd2d77 100644 --- a/core/src/test/java/org/springframework/security/concurrent/CurrentDelegatingSecurityContextScheduledExecutorServiceTests.java +++ b/core/src/test/java/org/springframework/security/concurrent/CurrentDelegatingSecurityContextScheduledExecutorServiceTests.java @@ -25,8 +25,8 @@ import org.junit.Before; * @since 3.2 * */ -public class CurrentDelegatingSecurityContextScheduledExecutorServiceTests extends - AbstractDelegatingSecurityContextScheduledExecutorServiceTests { +public class CurrentDelegatingSecurityContextScheduledExecutorServiceTests + extends AbstractDelegatingSecurityContextScheduledExecutorServiceTests { @Before public void setUp() throws Exception { diff --git a/core/src/test/java/org/springframework/security/concurrent/DelegatingSecurityContextCallableTests.java b/core/src/test/java/org/springframework/security/concurrent/DelegatingSecurityContextCallableTests.java index f121c47e91..5ee2b80b75 100644 --- a/core/src/test/java/org/springframework/security/concurrent/DelegatingSecurityContextCallableTests.java +++ b/core/src/test/java/org/springframework/security/concurrent/DelegatingSecurityContextCallableTests.java @@ -36,16 +36,18 @@ import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; /** - * * @author Rob Winch * @since 3.2 */ @RunWith(MockitoJUnitRunner.class) public class DelegatingSecurityContextCallableTests { + @Mock private Callable delegate; + @Mock private SecurityContext securityContext; + @Mock private Object callableResult; @@ -100,8 +102,7 @@ public class DelegatingSecurityContextCallableTests { @Test public void call() throws Exception { - callable = new DelegatingSecurityContextCallable<>(delegate, - securityContext); + callable = new DelegatingSecurityContextCallable<>(delegate, securityContext); assertWrapped(callable); } @@ -119,8 +120,7 @@ public class DelegatingSecurityContextCallableTests { public void callOnSameThread() throws Exception { originalSecurityContext = securityContext; SecurityContextHolder.setContext(originalSecurityContext); - callable = new DelegatingSecurityContextCallable<>(delegate, - securityContext); + callable = new DelegatingSecurityContextCallable<>(delegate, securityContext); assertWrapped(callable.call()); } @@ -156,8 +156,7 @@ public class DelegatingSecurityContextCallableTests { // SEC-2682 @Test public void toStringDelegates() { - callable = new DelegatingSecurityContextCallable<>(delegate, - securityContext); + callable = new DelegatingSecurityContextCallable<>(delegate, securityContext); assertThat(callable.toString()).isEqualTo(delegate.toString()); } @@ -168,7 +167,7 @@ public class DelegatingSecurityContextCallableTests { private void assertWrapped(Object callableResult) throws Exception { verify(delegate).call(); - assertThat(SecurityContextHolder.getContext()).isEqualTo( - originalSecurityContext); + assertThat(SecurityContextHolder.getContext()).isEqualTo(originalSecurityContext); } + } diff --git a/core/src/test/java/org/springframework/security/concurrent/DelegatingSecurityContextRunnableTests.java b/core/src/test/java/org/springframework/security/concurrent/DelegatingSecurityContextRunnableTests.java index 0540b568a9..2e92014df1 100644 --- a/core/src/test/java/org/springframework/security/concurrent/DelegatingSecurityContextRunnableTests.java +++ b/core/src/test/java/org/springframework/security/concurrent/DelegatingSecurityContextRunnableTests.java @@ -36,16 +36,18 @@ import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; /** - * * @author Rob Winch * @since 3.2 */ @RunWith(MockitoJUnitRunner.class) public class DelegatingSecurityContextRunnableTests { + @Mock private Runnable delegate; + @Mock private SecurityContext securityContext; + @Mock private Object callableResult; @@ -116,8 +118,7 @@ public class DelegatingSecurityContextRunnableTests { originalSecurityContext = securityContext; SecurityContextHolder.setContext(originalSecurityContext); executor = synchronousExecutor(); - runnable = new DelegatingSecurityContextRunnable(delegate, - securityContext); + runnable = new DelegatingSecurityContextRunnable(delegate, securityContext); assertWrapped(runnable); } @@ -161,11 +162,11 @@ public class DelegatingSecurityContextRunnableTests { Future submit = executor.submit(runnable); submit.get(); verify(delegate).run(); - assertThat(SecurityContextHolder.getContext()).isEqualTo( - originalSecurityContext); + assertThat(SecurityContextHolder.getContext()).isEqualTo(originalSecurityContext); } private static ExecutorService synchronousExecutor() { return new ExecutorServiceAdapter(new SyncTaskExecutor()); } + } diff --git a/core/src/test/java/org/springframework/security/concurrent/DelegatingSecurityContextSupportTests.java b/core/src/test/java/org/springframework/security/concurrent/DelegatingSecurityContextSupportTests.java index f18ecb1c9c..5bb2c7330d 100644 --- a/core/src/test/java/org/springframework/security/concurrent/DelegatingSecurityContextSupportTests.java +++ b/core/src/test/java/org/springframework/security/concurrent/DelegatingSecurityContextSupportTests.java @@ -21,13 +21,12 @@ import org.junit.Test; import org.springframework.security.core.context.SecurityContext; /** - * * @author Rob Winch * @since 3.2 * */ -public class DelegatingSecurityContextSupportTests extends - AbstractDelegatingSecurityContextTestSupport { +public class DelegatingSecurityContextSupportTests extends AbstractDelegatingSecurityContextTestSupport { + private AbstractDelegatingSecurityContextSupport support; @Test @@ -60,10 +59,12 @@ public class DelegatingSecurityContextSupportTests extends assertThat(support.wrap(runnable)).isSameAs(wrappedRunnable); } - private static class ConcreteDelegatingSecurityContextSupport extends - AbstractDelegatingSecurityContextSupport { + private static class ConcreteDelegatingSecurityContextSupport extends AbstractDelegatingSecurityContextSupport { + ConcreteDelegatingSecurityContextSupport(SecurityContext securityContext) { super(securityContext); } + } + } diff --git a/core/src/test/java/org/springframework/security/concurrent/ExplicitDelegatingSecurityContextExecutorServiceTests.java b/core/src/test/java/org/springframework/security/concurrent/ExplicitDelegatingSecurityContextExecutorServiceTests.java index 46f4d2be28..925308fa8a 100644 --- a/core/src/test/java/org/springframework/security/concurrent/ExplicitDelegatingSecurityContextExecutorServiceTests.java +++ b/core/src/test/java/org/springframework/security/concurrent/ExplicitDelegatingSecurityContextExecutorServiceTests.java @@ -25,8 +25,8 @@ import org.junit.Before; * @since 3.2 * */ -public class ExplicitDelegatingSecurityContextExecutorServiceTests extends - AbstractDelegatingSecurityContextExecutorServiceTests { +public class ExplicitDelegatingSecurityContextExecutorServiceTests + extends AbstractDelegatingSecurityContextExecutorServiceTests { @Before public void setUp() throws Exception { @@ -37,4 +37,5 @@ public class ExplicitDelegatingSecurityContextExecutorServiceTests extends protected DelegatingSecurityContextExecutorService create() { return new DelegatingSecurityContextExecutorService(delegate, securityContext); } + } \ No newline at end of file diff --git a/core/src/test/java/org/springframework/security/concurrent/ExplicitDelegatingSecurityContextExecutorTests.java b/core/src/test/java/org/springframework/security/concurrent/ExplicitDelegatingSecurityContextExecutorTests.java index f4eb4fc0bd..adbda1e0c8 100644 --- a/core/src/test/java/org/springframework/security/concurrent/ExplicitDelegatingSecurityContextExecutorTests.java +++ b/core/src/test/java/org/springframework/security/concurrent/ExplicitDelegatingSecurityContextExecutorTests.java @@ -26,8 +26,7 @@ import org.springframework.security.core.context.SecurityContext; * @since 3.2 * */ -public class ExplicitDelegatingSecurityContextExecutorTests extends - AbstractDelegatingSecurityContextExecutorTests { +public class ExplicitDelegatingSecurityContextExecutorTests extends AbstractDelegatingSecurityContextExecutorTests { @Before public void setUp() throws Exception { @@ -38,4 +37,5 @@ public class ExplicitDelegatingSecurityContextExecutorTests extends protected DelegatingSecurityContextExecutor create() { return new DelegatingSecurityContextExecutor(getExecutor(), securityContext); } + } diff --git a/core/src/test/java/org/springframework/security/concurrent/ExplicitDelegatingSecurityContextScheduledExecutorServiceTests.java b/core/src/test/java/org/springframework/security/concurrent/ExplicitDelegatingSecurityContextScheduledExecutorServiceTests.java index a8058a6e0a..10076665e1 100644 --- a/core/src/test/java/org/springframework/security/concurrent/ExplicitDelegatingSecurityContextScheduledExecutorServiceTests.java +++ b/core/src/test/java/org/springframework/security/concurrent/ExplicitDelegatingSecurityContextScheduledExecutorServiceTests.java @@ -26,8 +26,8 @@ import org.springframework.security.core.context.SecurityContext; * @since 3.2 * */ -public class ExplicitDelegatingSecurityContextScheduledExecutorServiceTests extends - AbstractDelegatingSecurityContextScheduledExecutorServiceTests { +public class ExplicitDelegatingSecurityContextScheduledExecutorServiceTests + extends AbstractDelegatingSecurityContextScheduledExecutorServiceTests { @Before public void setUp() throws Exception { @@ -36,7 +36,7 @@ public class ExplicitDelegatingSecurityContextScheduledExecutorServiceTests exte @Override protected DelegatingSecurityContextScheduledExecutorService create() { - return new DelegatingSecurityContextScheduledExecutorService(delegate, - securityContext); + return new DelegatingSecurityContextScheduledExecutorService(delegate, securityContext); } + } \ No newline at end of file diff --git a/core/src/test/java/org/springframework/security/context/DelegatingApplicationListenerTests.java b/core/src/test/java/org/springframework/security/context/DelegatingApplicationListenerTests.java index ed3cd8bbdc..a15367dc53 100644 --- a/core/src/test/java/org/springframework/security/context/DelegatingApplicationListenerTests.java +++ b/core/src/test/java/org/springframework/security/context/DelegatingApplicationListenerTests.java @@ -30,6 +30,7 @@ import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class DelegatingApplicationListenerTests { + @Mock SmartApplicationListener delegate; diff --git a/core/src/test/java/org/springframework/security/converter/RsaKeyConvertersTests.java b/core/src/test/java/org/springframework/security/converter/RsaKeyConvertersTests.java index 90a4450149..62017aa038 100644 --- a/core/src/test/java/org/springframework/security/converter/RsaKeyConvertersTests.java +++ b/core/src/test/java/org/springframework/security/converter/RsaKeyConvertersTests.java @@ -33,63 +33,60 @@ import org.springframework.core.convert.converter.Converter; * Tests for {@link RsaKeyConverters} */ public class RsaKeyConvertersTests { - private static final String PKCS8_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" + - "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCMk7CKSTfu3QoV\n" + - "HoPVXxwZO+qweztd36cVWYqGOZinrOR2crWFu50AgR2CsdIH0+cqo7F4Vx7/3O8i\n" + - "RpYYZPe2VoO5sumzJt8P6fS80/TAKjhJDAqgZKRJTgGN8KxCM6p/aJli1ZeDBqiV\n" + - "v7vJJe+ZgJuPGRS+HMNa/wPxEkqqXsglcJcQV1ZEtfKXSHB7jizKpRL38185SyAC\n" + - "pwyjvBu6Cmm1URfhQo88mf239ONh4dZ2HoDfzN1q6Ssu4F4hgutxr9B0DVLDP5u+\n" + - "WFrm3nsJ76zf99uJ+ntMUHJ+bY+gOjSlVWIVBIZeAaEGKCNWRk/knjvjbijpvm3U\n" + - "acGlgdL3AgMBAAECggEACxxxS7zVyu91qI2s5eSKmAQAXMqgup6+2hUluc47nqUv\n" + - "uZz/c/6MPkn2Ryo+65d4IgqmMFjSfm68B/2ER5FTcvoLl1Xo2twrrVpUmcg3BClS\n" + - "IZPuExdhVNnxjYKEWwcyZrehyAoR261fDdcFxLRW588efIUC+rPTTRHzAc7sT+Ln\n" + - "t/uFeYNWJm3LaegOLoOmlMAhJ5puAWSN1F0FxtRf/RVgzbLA9QC975SKHJsfWCSr\n" + - "IZyPsdeaqomKaF65l8nfqlE0Ua2L35gIOGKjUwb7uUE8nI362RWMtYdoi3zDDyoY\n" + - "hSFbgjylCHDM0u6iSh6KfqOHtkYyJ8tUYgVWl787wQKBgQDYO3wL7xuDdD101Lyl\n" + - "AnaDdFB9fxp83FG1cWr+t7LYm9YxGfEUsKHAJXN6TIayDkOOoVwIl+Gz0T3Z06Bm\n" + - "eBGLrB9mrVA7+C7NJwu5gTMlzP6HxUR9zKJIQ/VB1NUGM77LSmvOFbHc9Q0+z8EH\n" + - "X5WO516a3Z7lNtZJcCoPOtu2rwKBgQCmbj41Fh+SSEUApCEKms5ETRpe7LXQlJgx\n" + - "yW7zcJNNuIb1C3vBLPxjiOTMgYKOeMg5rtHTGLT43URHLh9ArjawasjSAr4AM3J4\n" + - "xpoi/sKGDdiKOsuDWIGfzdYL8qyTHSdpZLQsCTMRiRYgAHZFPgNa7SLZRfZicGlr\n" + - "GHN1rJW6OQKBgEjiM/upyrJSWeypUDSmUeAZMpA6aWkwsfHgmtnkfUn5rQa74cDB\n" + - "kKO9e+D7LmOR3z+SL/1NhGwh2SE07dncGr3jdGodfO/ZxZyszozmeaECKcEFwwJM\n" + - "GV8WWPKplGwUwPiwywmZ0mvRxXcoe73KgBS88+xrSwWjqDL0tZiQlEJNAoGATkei\n" + - "GMQMG3jEg9Wu+NbxV6zQT3+U0MNjhl9RQU1c63x0dcNt9OFc4NAdlZcAulRTENaK\n" + - "OHjxffBM0hH+fySx8m53gFfr2BpaqDX5f6ZGBlly1SlsWZ4CchCVsc71nshipi7I\n" + - "k8HL9F5/OpQdDNprJ5RMBNfkWE65Nrcsb1e6oPkCgYAxwgdiSOtNg8PjDVDmAhwT\n" + - "Mxj0Dtwi2fAqQ76RVrrXpNp3uCOIAu4CfruIb5llcJ3uak0ZbnWri32AxSgk80y3\n" + - "EWiRX/WEDu5znejF+5O3pI02atWWcnxifEKGGlxwkcMbQdA67MlrJLFaSnnGpNXo\n" + - "yPfcul058SOqhafIZQMEKQ==\n" + - "-----END PRIVATE KEY-----"; - private static final String PKCS1_PRIVATE_KEY = - "-----BEGIN RSA PRIVATE KEY-----\n" + - "MIICWwIBAAKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw\n" + - "33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW\n" + - "+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB\n" + - "AoGAD+onAtVye4ic7VR7V50DF9bOnwRwNXrARcDhq9LWNRrRGElESYYTQ6EbatXS\n" + - "3MCyjjX2eMhu/aF5YhXBwkppwxg+EOmXeh+MzL7Zh284OuPbkglAaGhV9bb6/5Cp\n" + - "uGb1esyPbYW+Ty2PC0GSZfIXkXs76jXAu9TOBvD0ybc2YlkCQQDywg2R/7t3Q2OE\n" + - "2+yo382CLJdrlSLVROWKwb4tb2PjhY4XAwV8d1vy0RenxTB+K5Mu57uVSTHtrMK0\n" + - "GAtFr833AkEA6avx20OHo61Yela/4k5kQDtjEf1N0LfI+BcWZtxsS3jDM3i1Hp0K\n" + - "Su5rsCPb8acJo5RO26gGVrfAsDcIXKC+bQJAZZ2XIpsitLyPpuiMOvBbzPavd4gY\n" + - "6Z8KWrfYzJoI/Q9FuBo6rKwl4BFoToD7WIUS+hpkagwWiz+6zLoX1dbOZwJACmH5\n" + - "fSSjAkLRi54PKJ8TFUeOP15h9sQzydI8zJU+upvDEKZsZc/UhT/SySDOxQ4G/523\n" + - "Y0sz/OZtSWcol/UMgQJALesy++GdvoIDLfJX5GBQpuFgFenRiRDabxrE9MNUZ2aP\n" + - "FaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw==\n" + - "-----END RSA PRIVATE KEY-----"; + private static final String PKCS8_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" + + "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCMk7CKSTfu3QoV\n" + + "HoPVXxwZO+qweztd36cVWYqGOZinrOR2crWFu50AgR2CsdIH0+cqo7F4Vx7/3O8i\n" + + "RpYYZPe2VoO5sumzJt8P6fS80/TAKjhJDAqgZKRJTgGN8KxCM6p/aJli1ZeDBqiV\n" + + "v7vJJe+ZgJuPGRS+HMNa/wPxEkqqXsglcJcQV1ZEtfKXSHB7jizKpRL38185SyAC\n" + + "pwyjvBu6Cmm1URfhQo88mf239ONh4dZ2HoDfzN1q6Ssu4F4hgutxr9B0DVLDP5u+\n" + + "WFrm3nsJ76zf99uJ+ntMUHJ+bY+gOjSlVWIVBIZeAaEGKCNWRk/knjvjbijpvm3U\n" + + "acGlgdL3AgMBAAECggEACxxxS7zVyu91qI2s5eSKmAQAXMqgup6+2hUluc47nqUv\n" + + "uZz/c/6MPkn2Ryo+65d4IgqmMFjSfm68B/2ER5FTcvoLl1Xo2twrrVpUmcg3BClS\n" + + "IZPuExdhVNnxjYKEWwcyZrehyAoR261fDdcFxLRW588efIUC+rPTTRHzAc7sT+Ln\n" + + "t/uFeYNWJm3LaegOLoOmlMAhJ5puAWSN1F0FxtRf/RVgzbLA9QC975SKHJsfWCSr\n" + + "IZyPsdeaqomKaF65l8nfqlE0Ua2L35gIOGKjUwb7uUE8nI362RWMtYdoi3zDDyoY\n" + + "hSFbgjylCHDM0u6iSh6KfqOHtkYyJ8tUYgVWl787wQKBgQDYO3wL7xuDdD101Lyl\n" + + "AnaDdFB9fxp83FG1cWr+t7LYm9YxGfEUsKHAJXN6TIayDkOOoVwIl+Gz0T3Z06Bm\n" + + "eBGLrB9mrVA7+C7NJwu5gTMlzP6HxUR9zKJIQ/VB1NUGM77LSmvOFbHc9Q0+z8EH\n" + + "X5WO516a3Z7lNtZJcCoPOtu2rwKBgQCmbj41Fh+SSEUApCEKms5ETRpe7LXQlJgx\n" + + "yW7zcJNNuIb1C3vBLPxjiOTMgYKOeMg5rtHTGLT43URHLh9ArjawasjSAr4AM3J4\n" + + "xpoi/sKGDdiKOsuDWIGfzdYL8qyTHSdpZLQsCTMRiRYgAHZFPgNa7SLZRfZicGlr\n" + + "GHN1rJW6OQKBgEjiM/upyrJSWeypUDSmUeAZMpA6aWkwsfHgmtnkfUn5rQa74cDB\n" + + "kKO9e+D7LmOR3z+SL/1NhGwh2SE07dncGr3jdGodfO/ZxZyszozmeaECKcEFwwJM\n" + + "GV8WWPKplGwUwPiwywmZ0mvRxXcoe73KgBS88+xrSwWjqDL0tZiQlEJNAoGATkei\n" + + "GMQMG3jEg9Wu+NbxV6zQT3+U0MNjhl9RQU1c63x0dcNt9OFc4NAdlZcAulRTENaK\n" + + "OHjxffBM0hH+fySx8m53gFfr2BpaqDX5f6ZGBlly1SlsWZ4CchCVsc71nshipi7I\n" + + "k8HL9F5/OpQdDNprJ5RMBNfkWE65Nrcsb1e6oPkCgYAxwgdiSOtNg8PjDVDmAhwT\n" + + "Mxj0Dtwi2fAqQ76RVrrXpNp3uCOIAu4CfruIb5llcJ3uak0ZbnWri32AxSgk80y3\n" + + "EWiRX/WEDu5znejF+5O3pI02atWWcnxifEKGGlxwkcMbQdA67MlrJLFaSnnGpNXo\n" + "yPfcul058SOqhafIZQMEKQ==\n" + + "-----END PRIVATE KEY-----"; - private static final String X509_PUBLIC_KEY = - "-----BEGIN PUBLIC KEY-----\n" + - "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugd\n" + - "UWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQs\n" + - "HUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5D\n" + - "o2kQ+X5xK9cipRgEKwIDAQAB\n" + - "-----END PUBLIC KEY-----"; + private static final String PKCS1_PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\n" + + "MIICWwIBAAKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw\n" + + "33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW\n" + + "+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB\n" + + "AoGAD+onAtVye4ic7VR7V50DF9bOnwRwNXrARcDhq9LWNRrRGElESYYTQ6EbatXS\n" + + "3MCyjjX2eMhu/aF5YhXBwkppwxg+EOmXeh+MzL7Zh284OuPbkglAaGhV9bb6/5Cp\n" + + "uGb1esyPbYW+Ty2PC0GSZfIXkXs76jXAu9TOBvD0ybc2YlkCQQDywg2R/7t3Q2OE\n" + + "2+yo382CLJdrlSLVROWKwb4tb2PjhY4XAwV8d1vy0RenxTB+K5Mu57uVSTHtrMK0\n" + + "GAtFr833AkEA6avx20OHo61Yela/4k5kQDtjEf1N0LfI+BcWZtxsS3jDM3i1Hp0K\n" + + "Su5rsCPb8acJo5RO26gGVrfAsDcIXKC+bQJAZZ2XIpsitLyPpuiMOvBbzPavd4gY\n" + + "6Z8KWrfYzJoI/Q9FuBo6rKwl4BFoToD7WIUS+hpkagwWiz+6zLoX1dbOZwJACmH5\n" + + "fSSjAkLRi54PKJ8TFUeOP15h9sQzydI8zJU+upvDEKZsZc/UhT/SySDOxQ4G/523\n" + + "Y0sz/OZtSWcol/UMgQJALesy++GdvoIDLfJX5GBQpuFgFenRiRDabxrE9MNUZ2aP\n" + + "FaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw==\n" + "-----END RSA PRIVATE KEY-----"; + + private static final String X509_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n" + + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugd\n" + + "UWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQs\n" + + "HUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5D\n" + "o2kQ+X5xK9cipRgEKwIDAQAB\n" + + "-----END PUBLIC KEY-----"; private static final String MALFORMED_X509_KEY = "malformed"; private final Converter x509 = RsaKeyConverters.x509(); + private final Converter pkcs8 = RsaKeyConverters.pkcs8(); @Test @@ -120,4 +117,5 @@ public class RsaKeyConvertersTests { private static InputStream toInputStream(String string) { return new ByteArrayInputStream(string.getBytes(StandardCharsets.UTF_8)); } + } diff --git a/core/src/test/java/org/springframework/security/core/JavaVersionTests.java b/core/src/test/java/org/springframework/security/core/JavaVersionTests.java index f7a6ab7057..c9d2dbd645 100644 --- a/core/src/test/java/org/springframework/security/core/JavaVersionTests.java +++ b/core/src/test/java/org/springframework/security/core/JavaVersionTests.java @@ -23,7 +23,6 @@ import java.io.InputStream; import static org.assertj.core.api.Assertions.assertThat; /** - * * @author Rob Winch * */ @@ -47,4 +46,5 @@ public class JavaVersionTests { assertThat(major).isEqualTo(JDK8_CLASS_VERSION); } } + } diff --git a/core/src/test/java/org/springframework/security/core/SpringSecurityCoreVersionTests.java b/core/src/test/java/org/springframework/security/core/SpringSecurityCoreVersionTests.java index 27d137b690..3d8eb20c6d 100644 --- a/core/src/test/java/org/springframework/security/core/SpringSecurityCoreVersionTests.java +++ b/core/src/test/java/org/springframework/security/core/SpringSecurityCoreVersionTests.java @@ -71,8 +71,7 @@ public class SpringSecurityCoreVersionTests { String version = System.getProperty("springSecurityVersion"); // Strip patch version - String serialVersion = String.valueOf( - SpringSecurityCoreVersion.SERIAL_VERSION_UID).substring(0, 2); + String serialVersion = String.valueOf(SpringSecurityCoreVersion.SERIAL_VERSION_UID).substring(0, 2); assertThat(serialVersion.charAt(0)).isEqualTo(version.charAt(0)); assertThat(serialVersion.charAt(1)).isEqualTo(version.charAt(2)); @@ -165,7 +164,7 @@ public class SpringSecurityCoreVersionTests { } private void performChecks(String minSpringVersion) throws Exception { - Whitebox.invokeMethod(SpringSecurityCoreVersion.class, "performVersionChecks", - minSpringVersion); + Whitebox.invokeMethod(SpringSecurityCoreVersion.class, "performVersionChecks", minSpringVersion); } + } diff --git a/core/src/test/java/org/springframework/security/core/SpringSecurityMessageSourceTests.java b/core/src/test/java/org/springframework/security/core/SpringSecurityMessageSourceTests.java index dca405de83..909ab4e9cf 100644 --- a/core/src/test/java/org/springframework/security/core/SpringSecurityMessageSourceTests.java +++ b/core/src/test/java/org/springframework/security/core/SpringSecurityMessageSourceTests.java @@ -35,8 +35,7 @@ public class SpringSecurityMessageSourceTests { public void testOperation() { SpringSecurityMessageSource msgs = new SpringSecurityMessageSource(); assertThat("\u4E0D\u5141\u8BB8\u8BBF\u95EE").isEqualTo( - msgs.getMessage("AbstractAccessDecisionManager.accessDenied", null, - Locale.SIMPLIFIED_CHINESE)); + msgs.getMessage("AbstractAccessDecisionManager.accessDenied", null, Locale.SIMPLIFIED_CHINESE)); } @Test @@ -47,9 +46,8 @@ public class SpringSecurityMessageSourceTests { // Cause a message to be generated MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); - assertThat("Le jeton nonce est compromis FOOBAR").isEqualTo( - messages.getMessage("DigestAuthenticationFilter.nonceCompromised", - new Object[] { "FOOBAR" }, "ERROR - FAILED TO LOOKUP")); + assertThat("Le jeton nonce est compromis FOOBAR").isEqualTo(messages.getMessage( + "DigestAuthenticationFilter.nonceCompromised", new Object[] { "FOOBAR" }, "ERROR - FAILED TO LOOKUP")); // Revert to original Locale LocaleContextHolder.setLocale(before); @@ -65,11 +63,12 @@ public class SpringSecurityMessageSourceTests { LocaleContextHolder.setLocale(Locale.US); MessageSourceAccessor msgs = SpringSecurityMessageSource.getAccessor(); - assertThat("Access is denied").isEqualTo( - msgs.getMessage("AbstractAccessDecisionManager.accessDenied", "Ooops")); + assertThat("Access is denied") + .isEqualTo(msgs.getMessage("AbstractAccessDecisionManager.accessDenied", "Ooops")); // Revert to original Locale Locale.setDefault(beforeSystem); LocaleContextHolder.setLocale(beforeHolder); } + } diff --git a/core/src/test/java/org/springframework/security/core/authority/AuthorityUtilsTests.java b/core/src/test/java/org/springframework/security/core/authority/AuthorityUtilsTests.java index 34ad79bf24..52248befcd 100644 --- a/core/src/test/java/org/springframework/security/core/authority/AuthorityUtilsTests.java +++ b/core/src/test/java/org/springframework/security/core/authority/AuthorityUtilsTests.java @@ -42,4 +42,5 @@ public class AuthorityUtilsTests { assertThat(authorities.contains("ROLE_A")).isTrue(); assertThat(authorities.contains("ROLE_D")).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/core/authority/mapping/MapBasedAttributes2GrantedAuthoritiesMapperTests.java b/core/src/test/java/org/springframework/security/core/authority/mapping/MapBasedAttributes2GrantedAuthoritiesMapperTests.java index dba49f94a2..7c35d547fa 100644 --- a/core/src/test/java/org/springframework/security/core/authority/mapping/MapBasedAttributes2GrantedAuthoritiesMapperTests.java +++ b/core/src/test/java/org/springframework/security/core/authority/mapping/MapBasedAttributes2GrantedAuthoritiesMapperTests.java @@ -24,7 +24,6 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import java.util.*; /** - * * @author Ruud Senden */ @SuppressWarnings("unchecked") @@ -164,10 +163,10 @@ public class MapBasedAttributes2GrantedAuthoritiesMapperTests { @Test public void testMappingCombination() throws Exception { - String[] roles = { "role1", "role2", "role3", "role4", "role5", "role6", "role7", - "role8", "role9", "role10", "role11" }; - String[] expectedGas = { "ga1", "ga2", "ga3", "ga4", "ga5", "ga6", "ga7", "ga8", - "ga9", "ga10", "ga11", "ga12", "ga13", "ga14" }; + String[] roles = { "role1", "role2", "role3", "role4", "role5", "role6", "role7", "role8", "role9", "role10", + "role11" }; + String[] expectedGas = { "ga1", "ga2", "ga3", "ga4", "ga5", "ga6", "ga7", "ga8", "ga9", "ga10", "ga11", "ga12", + "ga13", "ga14" }; testGetGrantedAuthorities(getDefaultMapper(), roles, expectedGas); } @@ -177,10 +176,8 @@ public class MapBasedAttributes2GrantedAuthoritiesMapperTests { m.put("role2", new SimpleGrantedAuthority("ga2")); m.put("role3", Arrays.asList("ga3", new SimpleGrantedAuthority("ga4"))); m.put("role4", "ga5,ga6"); - m.put("role5", Arrays.asList("ga7", "ga8", - new Object[] { new SimpleGrantedAuthority("ga9") })); - m.put("role6", new Object[] { "ga10", "ga11", - new Object[] { new SimpleGrantedAuthority("ga12") } }); + m.put("role5", Arrays.asList("ga7", "ga8", new Object[] { new SimpleGrantedAuthority("ga9") })); + m.put("role6", new Object[] { "ga10", "ga11", new Object[] { new SimpleGrantedAuthority("ga12") } }); m.put("role7", new String[] { "ga13", "ga14" }); m.put("role8", new String[] { "ga13", "ga14", null }); m.put("role9", null); @@ -189,25 +186,24 @@ public class MapBasedAttributes2GrantedAuthoritiesMapperTests { return m; } - private MapBasedAttributes2GrantedAuthoritiesMapper getDefaultMapper() - throws Exception { + private MapBasedAttributes2GrantedAuthoritiesMapper getDefaultMapper() throws Exception { MapBasedAttributes2GrantedAuthoritiesMapper mapper = new MapBasedAttributes2GrantedAuthoritiesMapper(); mapper.setAttributes2grantedAuthoritiesMap(getValidAttributes2GrantedAuthoritiesMap()); mapper.afterPropertiesSet(); return mapper; } - private void testGetGrantedAuthorities( - MapBasedAttributes2GrantedAuthoritiesMapper mapper, String[] roles, + private void testGetGrantedAuthorities(MapBasedAttributes2GrantedAuthoritiesMapper mapper, String[] roles, String[] expectedGas) { - List result = mapper - .getGrantedAuthorities(Arrays.asList(roles)); + List result = mapper.getGrantedAuthorities(Arrays.asList(roles)); Collection resultColl = new ArrayList(result.size()); for (GrantedAuthority auth : result) { resultColl.add(auth.getAuthority()); } Collection expectedColl = Arrays.asList(expectedGas); - assertThat(resultColl.containsAll(expectedColl)).withFailMessage("Role collections should match; result: " + resultColl - + ", expected: " + expectedColl).isTrue(); + assertThat(resultColl.containsAll(expectedColl)) + .withFailMessage("Role collections should match; result: " + resultColl + ", expected: " + expectedColl) + .isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/core/authority/mapping/SimpleAuthoritiesMapperTests.java b/core/src/test/java/org/springframework/security/core/authority/mapping/SimpleAuthoritiesMapperTests.java index c70474b70e..6a5ed58e8b 100644 --- a/core/src/test/java/org/springframework/security/core/authority/mapping/SimpleAuthoritiesMapperTests.java +++ b/core/src/test/java/org/springframework/security/core/authority/mapping/SimpleAuthoritiesMapperTests.java @@ -39,8 +39,8 @@ public class SimpleAuthoritiesMapperTests { @Test public void defaultPrefixIsCorrectlyApplied() { SimpleAuthorityMapper mapper = new SimpleAuthorityMapper(); - Set mapped = AuthorityUtils.authorityListToSet(mapper - .mapAuthorities(AuthorityUtils.createAuthorityList("AaA", "ROLE_bbb"))); + Set mapped = AuthorityUtils + .authorityListToSet(mapper.mapAuthorities(AuthorityUtils.createAuthorityList("AaA", "ROLE_bbb"))); assertThat(mapped.contains("ROLE_AaA")).isTrue(); assertThat(mapped.contains("ROLE_bbb")).isTrue(); } @@ -50,8 +50,7 @@ public class SimpleAuthoritiesMapperTests { SimpleAuthorityMapper mapper = new SimpleAuthorityMapper(); mapper.setPrefix(""); List toMap = AuthorityUtils.createAuthorityList("AaA", "Bbb"); - Set mapped = AuthorityUtils.authorityListToSet(mapper - .mapAuthorities(toMap)); + Set mapped = AuthorityUtils.authorityListToSet(mapper.mapAuthorities(toMap)); assertThat(mapped).hasSize(2); assertThat(mapped.contains("AaA")).isTrue(); assertThat(mapped.contains("Bbb")).isTrue(); @@ -75,8 +74,8 @@ public class SimpleAuthoritiesMapperTests { SimpleAuthorityMapper mapper = new SimpleAuthorityMapper(); mapper.setConvertToUpperCase(true); - Set mapped = AuthorityUtils.authorityListToSet(mapper - .mapAuthorities(AuthorityUtils.createAuthorityList("AaA", "AAA"))); + Set mapped = AuthorityUtils + .authorityListToSet(mapper.mapAuthorities(AuthorityUtils.createAuthorityList("AaA", "AAA"))); assertThat(mapped).hasSize(1); } @@ -84,9 +83,9 @@ public class SimpleAuthoritiesMapperTests { public void defaultAuthorityIsAssignedIfSet() { SimpleAuthorityMapper mapper = new SimpleAuthorityMapper(); mapper.setDefaultAuthority("ROLE_USER"); - Set mapped = AuthorityUtils.authorityListToSet(mapper - .mapAuthorities(AuthorityUtils.NO_AUTHORITIES)); + Set mapped = AuthorityUtils.authorityListToSet(mapper.mapAuthorities(AuthorityUtils.NO_AUTHORITIES)); assertThat(mapped).hasSize(1); assertThat(mapped.contains("ROLE_USER")).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/core/authority/mapping/SimpleMappableRolesRetrieverTests.java b/core/src/test/java/org/springframework/security/core/authority/mapping/SimpleMappableRolesRetrieverTests.java index 3bee9e2f02..ee569b3bfe 100644 --- a/core/src/test/java/org/springframework/security/core/authority/mapping/SimpleMappableRolesRetrieverTests.java +++ b/core/src/test/java/org/springframework/security/core/authority/mapping/SimpleMappableRolesRetrieverTests.java @@ -23,7 +23,6 @@ import org.junit.Test; import org.springframework.util.StringUtils; /** - * * @author TSARDD * @since 18-okt-2007 */ @@ -35,10 +34,8 @@ public class SimpleMappableRolesRetrieverTests { SimpleMappableAttributesRetriever r = new SimpleMappableAttributesRetriever(); r.setMappableAttributes(roles); Set result = r.getMappableAttributes(); - assertThat( - roles.containsAll(result) && result.containsAll(roles)).withFailMessage( - "Role collections do not match; result: " + result - + ", expected: " + roles).isTrue(); + assertThat(roles.containsAll(result) && result.containsAll(roles)) + .withFailMessage("Role collections do not match; result: " + result + ", expected: " + roles).isTrue(); } } diff --git a/core/src/test/java/org/springframework/security/core/authority/mapping/SimpleRoles2GrantedAuthoritiesMapperTests.java b/core/src/test/java/org/springframework/security/core/authority/mapping/SimpleRoles2GrantedAuthoritiesMapperTests.java index 7388c594fb..07b61b5e22 100644 --- a/core/src/test/java/org/springframework/security/core/authority/mapping/SimpleRoles2GrantedAuthoritiesMapperTests.java +++ b/core/src/test/java/org/springframework/security/core/authority/mapping/SimpleRoles2GrantedAuthoritiesMapperTests.java @@ -23,7 +23,6 @@ import org.springframework.security.core.GrantedAuthority; import java.util.*; /** - * * @author TSARDD * @since 18-okt-2007 */ @@ -123,19 +122,17 @@ public class SimpleRoles2GrantedAuthoritiesMapperTests { testGetGrantedAuthorities(mapper, roles, expectedGas); } - private void testGetGrantedAuthorities( - SimpleAttributes2GrantedAuthoritiesMapper mapper, String[] roles, + private void testGetGrantedAuthorities(SimpleAttributes2GrantedAuthoritiesMapper mapper, String[] roles, String[] expectedGas) { - List result = mapper - .getGrantedAuthorities(Arrays.asList(roles)); + List result = mapper.getGrantedAuthorities(Arrays.asList(roles)); Collection resultColl = new ArrayList<>(result.size()); for (GrantedAuthority grantedAuthority : result) { resultColl.add(grantedAuthority.getAuthority()); } Collection expectedColl = Arrays.asList(expectedGas); - assertThat(expectedColl.containsAll(resultColl) - && resultColl.containsAll(expectedColl)).withFailMessage("Role collections do not match; result: " + resultColl - + ", expected: " + expectedColl).isTrue(); + assertThat(expectedColl.containsAll(resultColl) && resultColl.containsAll(expectedColl)) + .withFailMessage("Role collections do not match; result: " + resultColl + ", expected: " + expectedColl) + .isTrue(); } private SimpleAttributes2GrantedAuthoritiesMapper getDefaultMapper() { diff --git a/core/src/test/java/org/springframework/security/core/context/ReactiveSecurityContextHolderTests.java b/core/src/test/java/org/springframework/security/core/context/ReactiveSecurityContextHolderTests.java index 92414c6668..86770b215f 100644 --- a/core/src/test/java/org/springframework/security/core/context/ReactiveSecurityContextHolderTests.java +++ b/core/src/test/java/org/springframework/security/core/context/ReactiveSecurityContextHolderTests.java @@ -32,22 +32,19 @@ public class ReactiveSecurityContextHolderTests { public void getContextWhenEmpty() { Mono context = ReactiveSecurityContextHolder.getContext(); - StepVerifier.create(context) - .verifyComplete(); + StepVerifier.create(context).verifyComplete(); } @Test public void setContextAndGetContextThenEmitsContext() { SecurityContext expectedContext = new SecurityContextImpl( - new TestingAuthenticationToken("user", "password", "ROLE_USER")); + new TestingAuthenticationToken("user", "password", "ROLE_USER")); Mono context = Mono.subscriberContext() - .flatMap( c -> ReactiveSecurityContextHolder.getContext()) - .subscriberContext(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(expectedContext))); + .flatMap(c -> ReactiveSecurityContextHolder.getContext()) + .subscriberContext(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(expectedContext))); - StepVerifier.create(context) - .expectNext(expectedContext) - .verifyComplete(); + StepVerifier.create(context).expectNext(expectedContext).verifyComplete(); } @Test @@ -55,14 +52,11 @@ public class ReactiveSecurityContextHolderTests { Authentication authentication = new TestingAuthenticationToken("user", "password", "ROLE_USER"); Mono messageByUsername = ReactiveSecurityContextHolder.getContext() - .map(SecurityContext::getAuthentication) - .map(Authentication::getName) - .flatMap(this::findMessageByUsername) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)); + .map(SecurityContext::getAuthentication).map(Authentication::getName) + .flatMap(this::findMessageByUsername) + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)); - StepVerifier.create(messageByUsername) - .expectNext("Hi user") - .verifyComplete(); + StepVerifier.create(messageByUsername).expectNext("Hi user").verifyComplete(); } private Mono findMessageByUsername(String username) { @@ -72,29 +66,25 @@ public class ReactiveSecurityContextHolderTests { @Test public void setContextAndClearAndGetContextThenEmitsEmpty() { SecurityContext expectedContext = new SecurityContextImpl( - new TestingAuthenticationToken("user", "password", "ROLE_USER")); + new TestingAuthenticationToken("user", "password", "ROLE_USER")); Mono context = Mono.subscriberContext() - .flatMap( c -> ReactiveSecurityContextHolder.getContext()) - .subscriberContext(ReactiveSecurityContextHolder.clearContext()) - .subscriberContext(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(expectedContext))); + .flatMap(c -> ReactiveSecurityContextHolder.getContext()) + .subscriberContext(ReactiveSecurityContextHolder.clearContext()) + .subscriberContext(ReactiveSecurityContextHolder.withSecurityContext(Mono.just(expectedContext))); - StepVerifier.create(context) - .verifyComplete(); + StepVerifier.create(context).verifyComplete(); } @Test public void setAuthenticationAndGetContextThenEmitsContext() { - Authentication expectedAuthentication = new TestingAuthenticationToken("user", - "password", "ROLE_USER"); + Authentication expectedAuthentication = new TestingAuthenticationToken("user", "password", "ROLE_USER"); Mono authentication = Mono.subscriberContext() - .flatMap( c -> ReactiveSecurityContextHolder.getContext()) - .map(SecurityContext::getAuthentication) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(expectedAuthentication)); + .flatMap(c -> ReactiveSecurityContextHolder.getContext()).map(SecurityContext::getAuthentication) + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(expectedAuthentication)); - StepVerifier.create(authentication) - .expectNext(expectedAuthentication) - .verifyComplete(); + StepVerifier.create(authentication).expectNext(expectedAuthentication).verifyComplete(); } + } diff --git a/core/src/test/java/org/springframework/security/core/context/SecurityContextHolderTests.java b/core/src/test/java/org/springframework/security/core/context/SecurityContextHolderTests.java index 00a1b2cf6e..b1141b60c9 100644 --- a/core/src/test/java/org/springframework/security/core/context/SecurityContextHolderTests.java +++ b/core/src/test/java/org/springframework/security/core/context/SecurityContextHolderTests.java @@ -34,8 +34,7 @@ public class SecurityContextHolderTests { // ======================================================================================================== @Before public final void setUp() { - SecurityContextHolder - .setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); + SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); } @Test @@ -65,4 +64,5 @@ public class SecurityContextHolderTests { } } + } diff --git a/core/src/test/java/org/springframework/security/core/context/SecurityContextImplTests.java b/core/src/test/java/org/springframework/security/core/context/SecurityContextImplTests.java index 2cd01bf098..e012fb4a12 100644 --- a/core/src/test/java/org/springframework/security/core/context/SecurityContextImplTests.java +++ b/core/src/test/java/org/springframework/security/core/context/SecurityContextImplTests.java @@ -46,4 +46,5 @@ public class SecurityContextImplTests { assertThat(context.getAuthentication()).isEqualTo(auth); assertThat(context.toString().lastIndexOf("rod") != -1).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscovererTests.java b/core/src/test/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscovererTests.java index 3627451887..f8cf44d9bf 100644 --- a/core/src/test/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscovererTests.java +++ b/core/src/test/java/org/springframework/security/core/parameters/AnnotationParameterNameDiscovererTests.java @@ -23,6 +23,7 @@ import org.springframework.security.access.method.P; import org.springframework.util.ReflectionUtils; public class AnnotationParameterNameDiscovererTests { + private AnnotationParameterNameDiscoverer discoverer; @Before @@ -32,48 +33,42 @@ public class AnnotationParameterNameDiscovererTests { @Test public void getParameterNamesInterfaceSingleParam() { - assertThat( - discoverer.getParameterNames(ReflectionUtils.findMethod(Dao.class, - "findMessageByTo", String.class))).isEqualTo( - new String[] { "to" }); + assertThat(discoverer.getParameterNames(ReflectionUtils.findMethod(Dao.class, "findMessageByTo", String.class))) + .isEqualTo(new String[] { "to" }); } @Test public void getParameterNamesInterfaceSingleParamAnnotatedWithMultiParams() { - assertThat( - discoverer.getParameterNames(ReflectionUtils.findMethod(Dao.class, - "findMessageByToAndFrom", String.class, String.class))) - .isEqualTo(new String[] { "to", null }); + assertThat(discoverer.getParameterNames( + ReflectionUtils.findMethod(Dao.class, "findMessageByToAndFrom", String.class, String.class))) + .isEqualTo(new String[] { "to", null }); } @Test public void getParameterNamesInterfaceNoAnnotation() { - assertThat( - discoverer.getParameterNames(ReflectionUtils.findMethod(Dao.class, - "findMessageByIdNoAnnotation", String.class))).isNull(); + assertThat(discoverer + .getParameterNames(ReflectionUtils.findMethod(Dao.class, "findMessageByIdNoAnnotation", String.class))) + .isNull(); } @Test public void getParameterNamesClassSingleParam() { - assertThat( - discoverer.getParameterNames(ReflectionUtils.findMethod(Dao.class, - "findMessageByTo", String.class))).isEqualTo( - new String[] { "to" }); + assertThat(discoverer.getParameterNames(ReflectionUtils.findMethod(Dao.class, "findMessageByTo", String.class))) + .isEqualTo(new String[] { "to" }); } @Test public void getParameterNamesClassSingleParamAnnotatedWithMultiParams() { - assertThat( - discoverer.getParameterNames(ReflectionUtils.findMethod(Dao.class, - "findMessageByToAndFrom", String.class, String.class))) - .isEqualTo(new String[] { "to", null }); + assertThat(discoverer.getParameterNames( + ReflectionUtils.findMethod(Dao.class, "findMessageByToAndFrom", String.class, String.class))) + .isEqualTo(new String[] { "to", null }); } @Test public void getParameterNamesClassNoAnnotation() { - assertThat( - discoverer.getParameterNames(ReflectionUtils.findMethod(Dao.class, - "findMessageByIdNoAnnotation", String.class))).isNull(); + assertThat(discoverer + .getParameterNames(ReflectionUtils.findMethod(Dao.class, "findMessageByIdNoAnnotation", String.class))) + .isNull(); } @Test @@ -84,60 +79,58 @@ public class AnnotationParameterNameDiscovererTests { @Test public void getParameterNamesConstructorNoAnnotation() throws Exception { - assertThat(discoverer.getParameterNames(Impl.class.getDeclaredConstructor(Long.class))) - .isNull(); + assertThat(discoverer.getParameterNames(Impl.class.getDeclaredConstructor(Long.class))).isNull(); } @Test public void getParameterNamesClassAnnotationOnInterface() { - assertThat( - discoverer.getParameterNames(ReflectionUtils.findMethod(DaoImpl.class, - "findMessageByTo", String.class))).isEqualTo( - new String[] { "to" }); - assertThat( - discoverer.getParameterNames(ReflectionUtils.findMethod(Dao.class, - "findMessageByTo", String.class))).isEqualTo( - new String[] { "to" }); + assertThat(discoverer + .getParameterNames(ReflectionUtils.findMethod(DaoImpl.class, "findMessageByTo", String.class))) + .isEqualTo(new String[] { "to" }); + assertThat(discoverer.getParameterNames(ReflectionUtils.findMethod(Dao.class, "findMessageByTo", String.class))) + .isEqualTo(new String[] { "to" }); } @Test public void getParameterNamesClassAnnotationOnImpl() { - assertThat( - discoverer.getParameterNames(ReflectionUtils.findMethod(Dao.class, - "findMessageByToAndFrom", String.class, String.class))) - .isEqualTo(new String[] { "to", null }); - assertThat( - discoverer.getParameterNames(ReflectionUtils.findMethod(DaoImpl.class, - "findMessageByToAndFrom", String.class, String.class))) - .isEqualTo(new String[] { "to", "from" }); + assertThat(discoverer.getParameterNames( + ReflectionUtils.findMethod(Dao.class, "findMessageByToAndFrom", String.class, String.class))) + .isEqualTo(new String[] { "to", null }); + assertThat(discoverer.getParameterNames( + ReflectionUtils.findMethod(DaoImpl.class, "findMessageByToAndFrom", String.class, String.class))) + .isEqualTo(new String[] { "to", "from" }); } @Test public void getParameterNamesClassAnnotationOnBaseClass() { - assertThat( - discoverer.getParameterNames(ReflectionUtils.findMethod(Dao.class, - "findMessageByIdNoAnnotation", String.class))).isNull(); - assertThat( - discoverer.getParameterNames(ReflectionUtils.findMethod(DaoImpl.class, - "findMessageByIdNoAnnotation", String.class))).isEqualTo( - new String[] { "id" }); + assertThat(discoverer + .getParameterNames(ReflectionUtils.findMethod(Dao.class, "findMessageByIdNoAnnotation", String.class))) + .isNull(); + assertThat(discoverer.getParameterNames( + ReflectionUtils.findMethod(DaoImpl.class, "findMessageByIdNoAnnotation", String.class))) + .isEqualTo(new String[] { "id" }); } interface Dao { + String findMessageByTo(@P("to") String to); String findMessageByToAndFrom(@P("to") String to, String from); String findMessageByIdNoAnnotation(String id); + } static class BaseDaoImpl { + public String findMessageByIdNoAnnotation(@P("id") String id) { return null; } + } static class DaoImpl extends BaseDaoImpl implements Dao { + public String findMessageByTo(String to) { return null; } @@ -145,9 +138,11 @@ public class AnnotationParameterNameDiscovererTests { public String findMessageByToAndFrom(@P("to") String to, @P("from") String from) { return null; } + } static class Impl { + Impl(Long dataSourceId) { } @@ -165,5 +160,7 @@ public class AnnotationParameterNameDiscovererTests { String findMessageByIdNoAnnotation(String id) { return null; } + } + } diff --git a/core/src/test/java/org/springframework/security/core/parameters/DefaultSecurityParameterNameDiscovererTests.java b/core/src/test/java/org/springframework/security/core/parameters/DefaultSecurityParameterNameDiscovererTests.java index b929f457f4..fdfc95b4e2 100644 --- a/core/src/test/java/org/springframework/security/core/parameters/DefaultSecurityParameterNameDiscovererTests.java +++ b/core/src/test/java/org/springframework/security/core/parameters/DefaultSecurityParameterNameDiscovererTests.java @@ -29,12 +29,12 @@ import org.springframework.core.ParameterNameDiscoverer; import org.springframework.test.util.ReflectionTestUtils; /** - * * @author Rob Winch * @since 3.2 */ @SuppressWarnings("unchecked") public class DefaultSecurityParameterNameDiscovererTests { + private DefaultSecurityParameterNameDiscoverer discoverer; @Before @@ -51,12 +51,11 @@ public class DefaultSecurityParameterNameDiscovererTests { ParameterNameDiscoverer annotationDisc = discoverers.get(0); assertThat(annotationDisc).isInstanceOf(AnnotationParameterNameDiscoverer.class); - Set annotationsToUse = (Set) ReflectionTestUtils.getField( - annotationDisc, "annotationClassesToUse"); + Set annotationsToUse = (Set) ReflectionTestUtils.getField(annotationDisc, + "annotationClassesToUse"); assertThat(annotationsToUse).containsOnly("org.springframework.security.access.method.P", P.class.getName()); - assertThat(discoverers.get(1).getClass()).isEqualTo( - DefaultParameterNameDiscoverer.class); + assertThat(discoverers.get(1).getClass()).isEqualTo(DefaultParameterNameDiscoverer.class); } @Test @@ -68,16 +67,15 @@ public class DefaultSecurityParameterNameDiscovererTests { .getField(discoverer, "parameterNameDiscoverers"); assertThat(discoverers).hasSize(3); - assertThat(discoverers.get(0)).isInstanceOf( - LocalVariableTableParameterNameDiscoverer.class); + assertThat(discoverers.get(0)).isInstanceOf(LocalVariableTableParameterNameDiscoverer.class); ParameterNameDiscoverer annotationDisc = discoverers.get(1); assertThat(annotationDisc).isInstanceOf(AnnotationParameterNameDiscoverer.class); - Set annotationsToUse = (Set) ReflectionTestUtils.getField( - annotationDisc, "annotationClassesToUse"); + Set annotationsToUse = (Set) ReflectionTestUtils.getField(annotationDisc, + "annotationClassesToUse"); assertThat(annotationsToUse).containsOnly("org.springframework.security.access.method.P", P.class.getName()); - assertThat(discoverers.get(2)).isInstanceOf( - DefaultParameterNameDiscoverer.class); + assertThat(discoverers.get(2)).isInstanceOf(DefaultParameterNameDiscoverer.class); } + } diff --git a/core/src/test/java/org/springframework/security/core/session/SessionInformationTests.java b/core/src/test/java/org/springframework/security/core/session/SessionInformationTests.java index 3cfcf86c5b..c7123048aa 100644 --- a/core/src/test/java/org/springframework/security/core/session/SessionInformationTests.java +++ b/core/src/test/java/org/springframework/security/core/session/SessionInformationTests.java @@ -37,8 +37,7 @@ public class SessionInformationTests { String sessionId = "1234567890"; Date currentDate = new Date(); - SessionInformation info = new SessionInformation(principal, sessionId, - currentDate); + SessionInformation info = new SessionInformation(principal, sessionId, currentDate); assertThat(info.getPrincipal()).isEqualTo(principal); assertThat(info.getSessionId()).isEqualTo(sessionId); assertThat(info.getLastRequest()).isEqualTo(currentDate); @@ -49,4 +48,5 @@ public class SessionInformationTests { assertThat(info.getLastRequest().after(currentDate)).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/core/session/SessionRegistryImplTests.java b/core/src/test/java/org/springframework/security/core/session/SessionRegistryImplTests.java index 7ed19b2bc6..411b982293 100644 --- a/core/src/test/java/org/springframework/security/core/session/SessionRegistryImplTests.java +++ b/core/src/test/java/org/springframework/security/core/session/SessionRegistryImplTests.java @@ -34,6 +34,7 @@ import org.springframework.security.core.session.SessionRegistryImpl; * @author Ben Alex */ public class SessionRegistryImplTests { + private SessionRegistryImpl sessionRegistry; // ~ Methods @@ -121,8 +122,7 @@ public class SessionRegistryImplTests { sessionRegistry.registerNewSession(sessionId, principal); // Retrieve existing session by session ID - Date currentDateTime = sessionRegistry.getSessionInformation(sessionId) - .getLastRequest(); + Date currentDateTime = sessionRegistry.getSessionInformation(sessionId).getLastRequest(); assertThat(sessionRegistry.getSessionInformation(sessionId).getPrincipal()).isEqualTo(principal); assertThat(sessionRegistry.getSessionInformation(sessionId).getSessionId()).isEqualTo(sessionId); assertThat(sessionRegistry.getSessionInformation(sessionId).getLastRequest()).isNotNull(); @@ -136,12 +136,12 @@ public class SessionRegistryImplTests { // Update request date/time sessionRegistry.refreshLastRequest(sessionId); - Date retrieved = sessionRegistry.getSessionInformation(sessionId) - .getLastRequest(); + Date retrieved = sessionRegistry.getSessionInformation(sessionId).getLastRequest(); assertThat(retrieved.after(currentDateTime)).isTrue(); // Check it retrieves correctly when looked up via principal - assertThat(sessionRegistry.getAllSessions(principal, false).get(0).getLastRequest()).isCloseTo(retrieved, 2000L); + assertThat(sessionRegistry.getAllSessions(principal, false).get(0).getLastRequest()).isCloseTo(retrieved, + 2000L); // Clear session information sessionRegistry.removeSessionInformation(sessionId); @@ -158,8 +158,7 @@ public class SessionRegistryImplTests { String sessionId2 = "9876543210"; sessionRegistry.registerNewSession(sessionId1, principal); - List sessions = sessionRegistry.getAllSessions(principal, - false); + List sessions = sessionRegistry.getAllSessions(principal, false); assertThat(sessions).hasSize(1); assertThat(contains(sessionId1, principal)).isTrue(); @@ -184,8 +183,7 @@ public class SessionRegistryImplTests { String sessionId2 = "9876543210"; sessionRegistry.registerNewSession(sessionId1, principal); - List sessions = sessionRegistry.getAllSessions(principal, - false); + List sessions = sessionRegistry.getAllSessions(principal, false); assertThat(sessions).hasSize(1); assertThat(contains(sessionId1, principal)).isTrue(); @@ -215,4 +213,5 @@ public class SessionRegistryImplTests { return false; } + } diff --git a/core/src/test/java/org/springframework/security/core/token/DefaultTokenTests.java b/core/src/test/java/org/springframework/security/core/token/DefaultTokenTests.java index 6d2adf21a4..3c9521bd0f 100644 --- a/core/src/test/java/org/springframework/security/core/token/DefaultTokenTests.java +++ b/core/src/test/java/org/springframework/security/core/token/DefaultTokenTests.java @@ -29,6 +29,7 @@ import org.springframework.security.core.token.DefaultToken; * */ public class DefaultTokenTests { + @Test public void testEquality() { String key = "key"; @@ -56,4 +57,5 @@ public class DefaultTokenTests { DefaultToken t2 = new DefaultToken(key, created, "longerLength2"); assertThat(t1).isNotEqualTo(t2); } + } diff --git a/core/src/test/java/org/springframework/security/core/token/KeyBasedPersistenceTokenServiceTests.java b/core/src/test/java/org/springframework/security/core/token/KeyBasedPersistenceTokenServiceTests.java index 4b9cfc0fb0..62db61afd5 100644 --- a/core/src/test/java/org/springframework/security/core/token/KeyBasedPersistenceTokenServiceTests.java +++ b/core/src/test/java/org/springframework/security/core/token/KeyBasedPersistenceTokenServiceTests.java @@ -98,4 +98,5 @@ public class KeyBasedPersistenceTokenServiceTests { Token token = new DefaultToken(fake, new Date().getTime(), ""); service.verifyToken(token.getKey()); } + } diff --git a/core/src/test/java/org/springframework/security/core/token/SecureRandomFactoryBeanTests.java b/core/src/test/java/org/springframework/security/core/token/SecureRandomFactoryBeanTests.java index da7144dd11..b5220f488c 100644 --- a/core/src/test/java/org/springframework/security/core/token/SecureRandomFactoryBeanTests.java +++ b/core/src/test/java/org/springframework/security/core/token/SecureRandomFactoryBeanTests.java @@ -31,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat; * */ public class SecureRandomFactoryBeanTests { + @Test public void testObjectType() { SecureRandomFactoryBean factory = new SecureRandomFactoryBean(); @@ -61,9 +62,7 @@ public class SecureRandomFactoryBeanTests { factory.setSeed(resource); SecureRandom first = factory.getObject(); SecureRandom second = factory.getObject(); - assertThat(first.nextInt()) - .isNotEqualTo(0) - .isNotEqualTo(second.nextInt()); + assertThat(first.nextInt()).isNotEqualTo(0).isNotEqualTo(second.nextInt()); } } diff --git a/core/src/test/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsServiceTests.java b/core/src/test/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsServiceTests.java index 3bf1fd7007..2bce22d627 100644 --- a/core/src/test/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsServiceTests.java +++ b/core/src/test/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsServiceTests.java @@ -15,7 +15,6 @@ */ package org.springframework.security.core.userdetails; - import static org.assertj.core.api.Assertions.assertThat; import java.util.Arrays; @@ -27,6 +26,7 @@ import org.junit.Test; import reactor.core.publisher.Mono; public class MapReactiveUserDetailsServiceTests { + // @formatter:off private static final UserDetails USER_DETAILS = User.withUsername("user") .password("password") @@ -86,4 +86,5 @@ public class MapReactiveUserDetailsServiceTests { users.updatePassword(USER_DETAILS, "new").block(); assertThat(users.findByUsername(USER_DETAILS.getUsername()).block().getPassword()).isEqualTo("new"); } + } diff --git a/core/src/test/java/org/springframework/security/core/userdetails/MockUserDetailsService.java b/core/src/test/java/org/springframework/security/core/userdetails/MockUserDetailsService.java index 98e81972ec..6a51285265 100644 --- a/core/src/test/java/org/springframework/security/core/userdetails/MockUserDetailsService.java +++ b/core/src/test/java/org/springframework/security/core/userdetails/MockUserDetailsService.java @@ -30,16 +30,16 @@ import org.springframework.security.core.authority.AuthorityUtils; * @author Luke Taylor */ public class MockUserDetailsService implements UserDetailsService { + private Map users = new HashMap<>(); - private List auths = AuthorityUtils - .createAuthorityList("ROLE_USER"); + + private List auths = AuthorityUtils.createAuthorityList("ROLE_USER"); public MockUserDetailsService() { users.put("valid", new User("valid", "", true, true, true, true, auths)); users.put("locked", new User("locked", "", true, true, true, false, auths)); users.put("disabled", new User("disabled", "", false, true, true, true, auths)); - users.put("credentialsExpired", new User("credentialsExpired", "", true, true, - false, true, auths)); + users.put("credentialsExpired", new User("credentialsExpired", "", true, true, false, true, auths)); users.put("expired", new User("expired", "", true, false, true, true, auths)); } @@ -50,4 +50,5 @@ public class MockUserDetailsService implements UserDetailsService { return users.get(username); } + } diff --git a/core/src/test/java/org/springframework/security/core/userdetails/PasswordEncodedUser.java b/core/src/test/java/org/springframework/security/core/userdetails/PasswordEncodedUser.java index b5261ba561..60c190c40a 100644 --- a/core/src/test/java/org/springframework/security/core/userdetails/PasswordEncodedUser.java +++ b/core/src/test/java/org/springframework/security/core/userdetails/PasswordEncodedUser.java @@ -23,6 +23,7 @@ import java.util.function.Function; * @since 5.0 */ public class PasswordEncodedUser { + private static final UserDetails USER = withUsername("user").password("password").roles("USER").build(); private static final UserDetails ADMIN = withUsername("admin").password("password").roles("USER", "ADMIN").build(); @@ -44,13 +45,14 @@ public class PasswordEncodedUser { } public static User.UserBuilder withUserDetails(UserDetails userDetails) { - return User.withUserDetails(userDetails) - .passwordEncoder(passwordEncoder()); + return User.withUserDetails(userDetails).passwordEncoder(passwordEncoder()); } private static Function passwordEncoder() { return rawPassword -> "{noop}" + rawPassword; } - protected PasswordEncodedUser() {} + protected PasswordEncodedUser() { + } + } diff --git a/core/src/test/java/org/springframework/security/core/userdetails/UserDetailsByNameServiceWrapperTests.java b/core/src/test/java/org/springframework/security/core/userdetails/UserDetailsByNameServiceWrapperTests.java index 6da8ad2af0..2b0a9eb0a7 100644 --- a/core/src/test/java/org/springframework/security/core/userdetails/UserDetailsByNameServiceWrapperTests.java +++ b/core/src/test/java/org/springframework/security/core/userdetails/UserDetailsByNameServiceWrapperTests.java @@ -22,12 +22,11 @@ import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.core.authority.AuthorityUtils; /** - * * @author TSARDD * @since 18-okt-2007 */ @SuppressWarnings("unchecked") -public class UserDetailsByNameServiceWrapperTests { +public class UserDetailsByNameServiceWrapperTests { @Test public final void testAfterPropertiesSet() { @@ -46,8 +45,7 @@ public class UserDetailsByNameServiceWrapperTests { @Test public final void testGetUserDetails() throws Exception { UserDetailsByNameServiceWrapper svc = new UserDetailsByNameServiceWrapper(); - final User user = new User("dummy", "dummy", true, true, true, true, - AuthorityUtils.NO_AUTHORITIES); + final User user = new User("dummy", "dummy", true, true, true, true, AuthorityUtils.NO_AUTHORITIES); svc.setUserDetailsService(name -> { if (user != null && user.getUsername().equals(name)) { return user; @@ -57,11 +55,9 @@ public class UserDetailsByNameServiceWrapperTests { } }); svc.afterPropertiesSet(); - UserDetails result1 = svc.loadUserDetails(new TestingAuthenticationToken("dummy", - "dummy")); + UserDetails result1 = svc.loadUserDetails(new TestingAuthenticationToken("dummy", "dummy")); assertThat(result1).as("Result doesn't match original user").isEqualTo(user); - UserDetails result2 = svc.loadUserDetails(new TestingAuthenticationToken( - "dummy2", "dummy")); + UserDetails result2 = svc.loadUserDetails(new TestingAuthenticationToken("dummy2", "dummy")); assertThat(result2).as("Result should have been null").isNull(); } diff --git a/core/src/test/java/org/springframework/security/core/userdetails/UserTests.java b/core/src/test/java/org/springframework/security/core/userdetails/UserTests.java index 36f4ce417e..52d3503d63 100644 --- a/core/src/test/java/org/springframework/security/core/userdetails/UserTests.java +++ b/core/src/test/java/org/springframework/security/core/userdetails/UserTests.java @@ -36,8 +36,8 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; * @author Ben Alex */ public class UserTests { - private static final List ROLE_12 = AuthorityUtils - .createAuthorityList("ROLE_ONE", "ROLE_TWO"); + + private static final List ROLE_12 = AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"); // ~ Methods // ======================================================================================================== @@ -49,8 +49,7 @@ public class UserTests { assertThat(user1).isNotNull(); assertThat(user1).isNotEqualTo("A STRING"); assertThat(user1).isEqualTo(user1); - assertThat(user1).isEqualTo((new User("rod", "notthesame", true, true, true, true, - ROLE_12))); + assertThat(user1).isEqualTo((new User("rod", "notthesame", true, true, true, true, ROLE_12))); } @Test @@ -59,12 +58,10 @@ public class UserTests { Set users = new HashSet<>(); users.add(user1); - assertThat(users).contains(new User("rod", "koala", true, true, true, true, - ROLE_12)); - assertThat(users).contains(new User("rod", "anotherpass", false, false, false, - false, AuthorityUtils.createAuthorityList("ROLE_X"))); - assertThat(users).doesNotContain(new User("bod", "koala", true, true, true, true, - ROLE_12)); + assertThat(users).contains(new User("rod", "koala", true, true, true, true, ROLE_12)); + assertThat(users).contains(new User("rod", "anotherpass", false, false, false, false, + AuthorityUtils.createAuthorityList("ROLE_X"))); + assertThat(users).doesNotContain(new User("bod", "koala", true, true, true, true, ROLE_12)); } @Test @@ -125,10 +122,8 @@ public class UserTests { assertThat(user.getUsername()).isEqualTo("rod"); assertThat(user.getPassword()).isEqualTo("koala"); assertThat(user.isEnabled()).isTrue(); - assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).contains( - "ROLE_ONE"); - assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).contains( - "ROLE_TWO"); + assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).contains("ROLE_ONE"); + assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).contains("ROLE_TWO"); assertThat(user.toString()).contains("rod"); } @@ -163,7 +158,6 @@ public class UserTests { assertThat(actual.isEnabled()).isEqualTo(expected.isEnabled()); } - @Test public void withUserDetailsWhenAllDisabled() { User expected = new User("rob", "pass", false, false, false, false, ROLE_12); @@ -183,20 +177,15 @@ public class UserTests { public void withUserWhenDetailsPasswordEncoderThenEncodes() { UserDetails userDetails = User.withUsername("user").password("password").roles("USER").build(); - UserDetails withEncodedPassword = User.withUserDetails(userDetails) - .passwordEncoder(p -> p + "encoded") - .build(); + UserDetails withEncodedPassword = User.withUserDetails(userDetails).passwordEncoder(p -> p + "encoded").build(); assertThat(withEncodedPassword.getPassword()).isEqualTo("passwordencoded"); } @Test public void withUsernameWhenPasswordEncoderAndPasswordThenEncodes() { - UserDetails withEncodedPassword = User.withUsername("user") - .password("password") - .passwordEncoder(p -> p + "encoded") - .roles("USER") - .build(); + UserDetails withEncodedPassword = User.withUsername("user").password("password") + .passwordEncoder(p -> p + "encoded").roles("USER").build(); assertThat(withEncodedPassword.getPassword()).isEqualTo("passwordencoded"); } @@ -228,4 +217,5 @@ public class UserTests { assertThat(withEncodedPassword.getPassword()).isEqualTo("passwordencoded"); } + } diff --git a/core/src/test/java/org/springframework/security/core/userdetails/cache/EhCacheBasedUserCacheTests.java b/core/src/test/java/org/springframework/security/core/userdetails/cache/EhCacheBasedUserCacheTests.java index 2336eb7ed5..5f77e6137b 100644 --- a/core/src/test/java/org/springframework/security/core/userdetails/cache/EhCacheBasedUserCacheTests.java +++ b/core/src/test/java/org/springframework/security/core/userdetails/cache/EhCacheBasedUserCacheTests.java @@ -34,6 +34,7 @@ import org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache * @author Ben Alex */ public class EhCacheBasedUserCacheTests { + private static CacheManager cacheManager; // ~ Methods @@ -41,8 +42,7 @@ public class EhCacheBasedUserCacheTests { @BeforeClass public static void initCacheManaer() { cacheManager = CacheManager.create(); - cacheManager.addCache(new Cache("ehcacheusercachetests", 500, false, false, 30, - 30)); + cacheManager.addCache(new Cache("ehcacheusercachetests", 500, false, false, 30, 30)); } @AfterClass @@ -93,4 +93,5 @@ public class EhCacheBasedUserCacheTests { cache.setCache(myCache); assertThat(cache.getCache()).isEqualTo(myCache); } + } diff --git a/core/src/test/java/org/springframework/security/core/userdetails/cache/NullUserCacheTests.java b/core/src/test/java/org/springframework/security/core/userdetails/cache/NullUserCacheTests.java index 809edd2bca..a61a797ab9 100644 --- a/core/src/test/java/org/springframework/security/core/userdetails/cache/NullUserCacheTests.java +++ b/core/src/test/java/org/springframework/security/core/userdetails/cache/NullUserCacheTests.java @@ -44,4 +44,5 @@ public class NullUserCacheTests { assertThat(cache.getUserFromCache(null)).isNull(); cache.removeUserFromCache(null); } + } diff --git a/core/src/test/java/org/springframework/security/core/userdetails/cache/SpringCacheBasedUserCacheTests.java b/core/src/test/java/org/springframework/security/core/userdetails/cache/SpringCacheBasedUserCacheTests.java index 1346bc879f..c4135724f4 100644 --- a/core/src/test/java/org/springframework/security/core/userdetails/cache/SpringCacheBasedUserCacheTests.java +++ b/core/src/test/java/org/springframework/security/core/userdetails/cache/SpringCacheBasedUserCacheTests.java @@ -36,6 +36,7 @@ import static org.assertj.core.api.Assertions.*; * */ public class SpringCacheBasedUserCacheTests { + private static CacheManager cacheManager; // ~ Methods @@ -82,4 +83,5 @@ public class SpringCacheBasedUserCacheTests { public void startupDetectsMissingCache() throws Exception { new SpringCacheBasedUserCache(null); } + } diff --git a/core/src/test/java/org/springframework/security/core/userdetails/jdbc/JdbcDaoImplTests.java b/core/src/test/java/org/springframework/security/core/userdetails/jdbc/JdbcDaoImplTests.java index e7a479e2b6..0980ba1ee0 100644 --- a/core/src/test/java/org/springframework/security/core/userdetails/jdbc/JdbcDaoImplTests.java +++ b/core/src/test/java/org/springframework/security/core/userdetails/jdbc/JdbcDaoImplTests.java @@ -67,20 +67,16 @@ public class JdbcDaoImplTests { assertThat(user.getPassword()).isEqualTo("koala"); assertThat(user.isEnabled()).isTrue(); - assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())) - .contains("ROLE_TELLER"); - assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())) - .contains("ROLE_SUPERVISOR"); + assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).contains("ROLE_TELLER"); + assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).contains("ROLE_SUPERVISOR"); } @Test - public void testCheckDaoOnlyReturnsGrantedAuthoritiesGrantedToUser() - throws Exception { + public void testCheckDaoOnlyReturnsGrantedAuthoritiesGrantedToUser() throws Exception { JdbcDaoImpl dao = makePopulatedJdbcDao(); UserDetails user = dao.loadUserByUsername("scott"); assertThat(user.getAuthorities()).hasSize(1); - assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())) - .contains("ROLE_TELLER"); + assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).contains("ROLE_TELLER"); } @Test @@ -141,8 +137,7 @@ public class JdbcDaoImplTests { assertThat(user.getUsername()).isEqualTo("rod"); assertThat(user.getAuthorities()).hasSize(2); - assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())) - .contains("ARBITRARY_PREFIX_ROLE_TELLER"); + assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).contains("ARBITRARY_PREFIX_ROLE_TELLER"); assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())) .contains("ARBITRARY_PREFIX_ROLE_SUPERVISOR"); } @@ -212,4 +207,5 @@ public class JdbcDaoImplTests { verify(source).getMessage(eq(code), any(), any()); } + } diff --git a/core/src/test/java/org/springframework/security/core/userdetails/memory/UserAttributeEditorTests.java b/core/src/test/java/org/springframework/security/core/userdetails/memory/UserAttributeEditorTests.java index e92a382dd7..07a9a1c444 100644 --- a/core/src/test/java/org/springframework/security/core/userdetails/memory/UserAttributeEditorTests.java +++ b/core/src/test/java/org/springframework/security/core/userdetails/memory/UserAttributeEditorTests.java @@ -125,4 +125,5 @@ public class UserAttributeEditorTests { UserAttribute user = (UserAttribute) editor.getValue(); assertThat(user == null).isTrue(); } + } diff --git a/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java index 89302f2687..f89ae7475a 100644 --- a/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/AbstractMixinTests.java @@ -27,6 +27,7 @@ import org.springframework.security.core.userdetails.User; * @since 4.2 */ public abstract class AbstractMixinTests { + protected ObjectMapper mapper; @Before @@ -43,4 +44,5 @@ public abstract class AbstractMixinTests { User createUser(String username, String password, String authority) { return new User(username, password, AuthorityUtils.createAuthorityList(authority)); } + } diff --git a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java index 7225c03aa1..9eb5b46e26 100644 --- a/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/AnonymousAuthenticationTokenMixinTests.java @@ -52,17 +52,14 @@ public class AnonymousAuthenticationTokenMixinTests extends AbstractMixinTests { @Test public void serializeAnonymousAuthenticationTokenTest() throws JsonProcessingException, JSONException { User user = createDefaultUser(); - AnonymousAuthenticationToken token = new AnonymousAuthenticationToken( - HASH_KEY, user, user.getAuthorities() - ); + AnonymousAuthenticationToken token = new AnonymousAuthenticationToken(HASH_KEY, user, user.getAuthorities()); String actualJson = mapper.writeValueAsString(token); JSONAssert.assertEquals(ANONYMOUS_JSON, actualJson, true); } @Test public void deserializeAnonymousAuthenticationTokenTest() throws IOException { - AnonymousAuthenticationToken token = mapper - .readValue(ANONYMOUS_JSON, AnonymousAuthenticationToken.class); + AnonymousAuthenticationToken token = mapper.readValue(ANONYMOUS_JSON, AnonymousAuthenticationToken.class); assertThat(token).isNotNull(); assertThat(token.getKeyHash()).isEqualTo(HASH_KEY.hashCode()); assertThat(token.getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); @@ -70,20 +67,20 @@ public class AnonymousAuthenticationTokenMixinTests extends AbstractMixinTests { @Test(expected = JsonMappingException.class) public void deserializeAnonymousAuthenticationTokenWithoutAuthoritiesTest() throws IOException { - String jsonString = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null," + - "\"principal\": \"user\", \"authenticated\": true, \"keyHash\": " + HASH_KEY.hashCode() + "," + - "\"authorities\": [\"java.util.ArrayList\", []]}"; + String jsonString = "{\"@class\": \"org.springframework.security.authentication.AnonymousAuthenticationToken\", \"details\": null," + + "\"principal\": \"user\", \"authenticated\": true, \"keyHash\": " + HASH_KEY.hashCode() + "," + + "\"authorities\": [\"java.util.ArrayList\", []]}"; mapper.readValue(jsonString, AnonymousAuthenticationToken.class); } @Test - public void serializeAnonymousAuthenticationTokenMixinAfterEraseCredentialTest() throws JsonProcessingException, JSONException { + public void serializeAnonymousAuthenticationTokenMixinAfterEraseCredentialTest() + throws JsonProcessingException, JSONException { User user = createDefaultUser(); - AnonymousAuthenticationToken token = new AnonymousAuthenticationToken( - HASH_KEY, user, user.getAuthorities() - ); + AnonymousAuthenticationToken token = new AnonymousAuthenticationToken(HASH_KEY, user, user.getAuthorities()); token.eraseCredentials(); String actualJson = mapper.writeValueAsString(token); JSONAssert.assertEquals(ANONYMOUS_JSON.replace(UserDeserializerTests.USER_PASSWORD, "null"), actualJson, true); } + } diff --git a/core/src/test/java/org/springframework/security/jackson2/BadCredentialsExceptionMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/BadCredentialsExceptionMixinTests.java index 44d0bb6784..b4b8b87e43 100644 --- a/core/src/test/java/org/springframework/security/jackson2/BadCredentialsExceptionMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/BadCredentialsExceptionMixinTests.java @@ -55,4 +55,5 @@ public class BadCredentialsExceptionMixinTests extends AbstractMixinTests { assertThat(exception.getMessage()).isEqualTo("message"); assertThat(exception.getLocalizedMessage()).isEqualTo("message"); } + } diff --git a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java index 41a54b17c4..0fed8d8ac5 100644 --- a/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/RememberMeAuthenticationTokenMixinTests.java @@ -71,7 +71,8 @@ public class RememberMeAuthenticationTokenMixinTests extends AbstractMixinTests @Test public void serializeRememberMeAuthenticationToken() throws JsonProcessingException, JSONException { - RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(REMEMBERME_KEY, "admin", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(REMEMBERME_KEY, "admin", + Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); String actualJson = mapper.writeValueAsString(token); JSONAssert.assertEquals(REMEMBERME_AUTH_STRINGPRINCIPAL_JSON, actualJson, true); } @@ -79,23 +80,28 @@ public class RememberMeAuthenticationTokenMixinTests extends AbstractMixinTests @Test public void serializeRememberMeAuthenticationWithUserToken() throws JsonProcessingException, JSONException { User user = createDefaultUser(); - RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(REMEMBERME_KEY, user, user.getAuthorities()); + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(REMEMBERME_KEY, user, + user.getAuthorities()); String actualJson = mapper.writeValueAsString(token); JSONAssert.assertEquals(String.format(REMEMBERME_AUTH_JSON, "\"password\""), actualJson, true); } @Test - public void serializeRememberMeAuthenticationWithUserTokenAfterEraseCredential() throws JsonProcessingException, JSONException { + public void serializeRememberMeAuthenticationWithUserTokenAfterEraseCredential() + throws JsonProcessingException, JSONException { User user = createDefaultUser(); - RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(REMEMBERME_KEY, user, user.getAuthorities()); + RememberMeAuthenticationToken token = new RememberMeAuthenticationToken(REMEMBERME_KEY, user, + user.getAuthorities()); token.eraseCredentials(); String actualJson = mapper.writeValueAsString(token); - JSONAssert.assertEquals(REMEMBERME_AUTH_JSON.replace(UserDeserializerTests.USER_PASSWORD, "null"), actualJson, true); + JSONAssert.assertEquals(REMEMBERME_AUTH_JSON.replace(UserDeserializerTests.USER_PASSWORD, "null"), actualJson, + true); } @Test public void deserializeRememberMeAuthenticationToken() throws IOException { - RememberMeAuthenticationToken token = mapper.readValue(REMEMBERME_AUTH_STRINGPRINCIPAL_JSON, RememberMeAuthenticationToken.class); + RememberMeAuthenticationToken token = mapper.readValue(REMEMBERME_AUTH_STRINGPRINCIPAL_JSON, + RememberMeAuthenticationToken.class); assertThat(token).isNotNull(); assertThat(token.getPrincipal()).isNotNull().isEqualTo("admin").isEqualTo(token.getName()); assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); @@ -103,14 +109,16 @@ public class RememberMeAuthenticationTokenMixinTests extends AbstractMixinTests @Test public void deserializeRememberMeAuthenticationTokenWithUserTest() throws IOException { - RememberMeAuthenticationToken token = mapper - .readValue(String.format(REMEMBERME_AUTH_JSON, "\"password\""), RememberMeAuthenticationToken.class); + RememberMeAuthenticationToken token = mapper.readValue(String.format(REMEMBERME_AUTH_JSON, "\"password\""), + RememberMeAuthenticationToken.class); assertThat(token).isNotNull(); assertThat(token.getPrincipal()).isNotNull().isInstanceOf(User.class); assertThat(((User) token.getPrincipal()).getUsername()).isEqualTo("admin"); assertThat(((User) token.getPrincipal()).getPassword()).isEqualTo("1234"); - assertThat(((User) token.getPrincipal()).getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + assertThat(((User) token.getPrincipal()).getAuthorities()).hasSize(1) + .contains(new SimpleGrantedAuthority("ROLE_USER")); assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); assertThat(((User) token.getPrincipal()).isEnabled()).isEqualTo(true); } + } diff --git a/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTests.java index d0757828c6..47c3dfa75f 100644 --- a/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/SecurityContextMixinTests.java @@ -48,7 +48,8 @@ public class SecurityContextMixinTests extends AbstractMixinTests { @Test public void securityContextSerializeTest() throws JsonProcessingException, JSONException { SecurityContext context = new SecurityContextImpl(); - context.setAuthentication(new UsernamePasswordAuthenticationToken("admin", "1234", Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")))); + context.setAuthentication(new UsernamePasswordAuthenticationToken("admin", "1234", + Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")))); String actualJson = mapper.writeValueAsString(context); JSONAssert.assertEquals(SECURITY_CONTEXT_JSON, actualJson, true); } @@ -65,4 +66,5 @@ public class SecurityContextMixinTests extends AbstractMixinTests { assertThat(authorities).hasSize(1); assertThat(authorities).contains(new SimpleGrantedAuthority("ROLE_USER")); } + } diff --git a/core/src/test/java/org/springframework/security/jackson2/SecurityJackson2ModulesTests.java b/core/src/test/java/org/springframework/security/jackson2/SecurityJackson2ModulesTests.java index e28aaf0ffd..41b713aba2 100644 --- a/core/src/test/java/org/springframework/security/jackson2/SecurityJackson2ModulesTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/SecurityJackson2ModulesTests.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package org.springframework.security.jackson2; import com.fasterxml.jackson.annotation.JsonAutoDetect; @@ -31,10 +30,11 @@ import java.util.HashMap; import static org.assertj.core.api.Assertions.*; /** -* @author Rob Winch -* @since 5.0 -*/ + * @author Rob Winch + * @since 5.0 + */ public class SecurityJackson2ModulesTests { + private ObjectMapper mapper; @Before @@ -47,9 +47,8 @@ public class SecurityJackson2ModulesTests { public void readValueWhenNotAllowedOrMappedThenThrowsException() { String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotAllowlisted\",\"property\":\"bar\"}"; assertThatThrownBy(() -> { - mapper.readValue(content, Object.class); - } - ).hasStackTraceContaining("allowlist"); + mapper.readValue(content, Object.class); + }).hasStackTraceContaining("allowlist"); } @Test @@ -96,10 +95,13 @@ public class SecurityJackson2ModulesTests { @Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented - public @interface NotJacksonAnnotation {} + public @interface NotJacksonAnnotation { + + } @NotJacksonAnnotation static class NotAllowlisted { + private String property = "bar"; public String getProperty() { @@ -108,10 +110,12 @@ public class SecurityJackson2ModulesTests { public void setProperty(String property) { } + } @JsonIgnoreType(false) static class NotAllowlistedButAnnotated { + private String property = "bar"; public String getProperty() { @@ -120,13 +124,15 @@ public class SecurityJackson2ModulesTests { public void setProperty(String property) { } + } @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, - isGetterVisibility = JsonAutoDetect.Visibility.NONE) + isGetterVisibility = JsonAutoDetect.Visibility.NONE) @JsonIgnoreProperties(ignoreUnknown = true) abstract class NotAllowlistedMixin { } + } diff --git a/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTests.java index a7699e2d20..e56e4be0b1 100644 --- a/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/SimpleGrantedAuthorityMixinTests.java @@ -66,4 +66,5 @@ public class SimpleGrantedAuthorityMixinTests extends AbstractMixinTests { String json = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\"}"; mapper.readValue(json, SimpleGrantedAuthority.class); } + } diff --git a/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java b/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java index 397491ee0a..b3aa03f696 100644 --- a/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/UserDeserializerTests.java @@ -38,6 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @since 4.2 */ public class UserDeserializerTests extends AbstractMixinTests { + public static final String USER_PASSWORD = "\"1234\""; // @formatter:off @@ -69,7 +70,8 @@ public class UserDeserializerTests extends AbstractMixinTests { @Test(expected = IllegalArgumentException.class) public void deserializeUserWithNullPasswordEmptyAuthorityTest() throws IOException { - String userJsonWithoutPasswordString = USER_JSON.replace(SimpleGrantedAuthorityMixinTests.AUTHORITIES_SET_JSON, "[]"); + String userJsonWithoutPasswordString = USER_JSON.replace(SimpleGrantedAuthorityMixinTests.AUTHORITIES_SET_JSON, + "[]"); mapper.readValue(userJsonWithoutPasswordString, User.class); } @@ -88,7 +90,8 @@ public class UserDeserializerTests extends AbstractMixinTests { @Test(expected = IllegalArgumentException.class) public void deserializeUserWithNoClassIdInAuthoritiesTest() throws Exception { - String userJson = USER_JSON.replace(SimpleGrantedAuthorityMixinTests.AUTHORITIES_SET_JSON, "[{\"authority\": \"ROLE_USER\"}]"); + String userJson = USER_JSON.replace(SimpleGrantedAuthorityMixinTests.AUTHORITIES_SET_JSON, + "[{\"authority\": \"ROLE_USER\"}]"); mapper.readValue(userJson, User.class); } @@ -115,10 +118,12 @@ public class UserDeserializerTests extends AbstractMixinTests { } public static String userWithPasswordJson(String password) { - return userJson().replaceAll(Pattern.quote(USER_PASSWORD), "\""+ password +"\""); + return userJson().replaceAll(Pattern.quote(USER_PASSWORD), "\"" + password + "\""); } public static String userWithNoAuthoritiesJson() { - return userJson().replace(SimpleGrantedAuthorityMixinTests.AUTHORITIES_SET_JSON, SimpleGrantedAuthorityMixinTests.NO_AUTHORITIES_SET_JSON); + return userJson().replace(SimpleGrantedAuthorityMixinTests.AUTHORITIES_SET_JSON, + SimpleGrantedAuthorityMixinTests.NO_AUTHORITIES_SET_JSON); } + } diff --git a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java index 7475476fe6..1b5791ecc9 100644 --- a/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java +++ b/core/src/test/java/org/springframework/security/jackson2/UsernamePasswordAuthenticationTokenMixinTests.java @@ -42,6 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @since 4.2 */ public class UsernamePasswordAuthenticationTokenMixinTests extends AbstractMixinTests { + // @formatter:off private static final String AUTHENTICATED_JSON = "{" + "\"@class\": \"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"," @@ -82,24 +83,27 @@ public class UsernamePasswordAuthenticationTokenMixinTests extends AbstractMixin // @formatter:on @Test - public void serializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws JsonProcessingException, JSONException { + public void serializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTest() + throws JsonProcessingException, JSONException { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("admin", "1234"); String serializedJson = mapper.writeValueAsString(token); JSONAssert.assertEquals(UNAUTHENTICATED_STRINGPRINCIPAL_JSON, serializedJson, true); } @Test - public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws JsonProcessingException, JSONException { + public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinTest() + throws JsonProcessingException, JSONException { User user = createDefaultUser(); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), user.getAuthorities()); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.getUsername(), + user.getPassword(), user.getAuthorities()); String serializedJson = mapper.writeValueAsString(token); JSONAssert.assertEquals(AUTHENTICATED_STRINGPRINCIPAL_JSON, serializedJson, true); } @Test public void deserializeUnauthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws IOException { - UsernamePasswordAuthenticationToken token = mapper - .readValue(UNAUTHENTICATED_STRINGPRINCIPAL_JSON, UsernamePasswordAuthenticationToken.class); + UsernamePasswordAuthenticationToken token = mapper.readValue(UNAUTHENTICATED_STRINGPRINCIPAL_JSON, + UsernamePasswordAuthenticationToken.class); assertThat(token).isNotNull(); assertThat(token.isAuthenticated()).isEqualTo(false); assertThat(token.getAuthorities()).isNotNull().hasSize(0); @@ -108,15 +112,16 @@ public class UsernamePasswordAuthenticationTokenMixinTests extends AbstractMixin @Test public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenMixinTest() throws IOException { UsernamePasswordAuthenticationToken expectedToken = createToken(); - UsernamePasswordAuthenticationToken token = mapper - .readValue(AUTHENTICATED_STRINGPRINCIPAL_JSON, UsernamePasswordAuthenticationToken.class); + UsernamePasswordAuthenticationToken token = mapper.readValue(AUTHENTICATED_STRINGPRINCIPAL_JSON, + UsernamePasswordAuthenticationToken.class); assertThat(token).isNotNull(); assertThat(token.isAuthenticated()).isTrue(); assertThat(token.getAuthorities()).isEqualTo(expectedToken.getAuthorities()); } @Test - public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinWithUserTest() throws JsonProcessingException, JSONException { + public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinWithUserTest() + throws JsonProcessingException, JSONException { UsernamePasswordAuthenticationToken token = createToken(); String actualJson = mapper.writeValueAsString(token); JSONAssert.assertEquals(AUTHENTICATED_JSON, actualJson, true); @@ -124,48 +129,54 @@ public class UsernamePasswordAuthenticationTokenMixinTests extends AbstractMixin @Test public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenWithUserTest() throws IOException { - UsernamePasswordAuthenticationToken token = mapper - .readValue(AUTHENTICATED_JSON, UsernamePasswordAuthenticationToken.class); + UsernamePasswordAuthenticationToken token = mapper.readValue(AUTHENTICATED_JSON, + UsernamePasswordAuthenticationToken.class); assertThat(token).isNotNull(); assertThat(token.getPrincipal()).isNotNull().isInstanceOf(User.class); - assertThat(((User) token.getPrincipal()).getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + assertThat(((User) token.getPrincipal()).getAuthorities()).isNotNull().hasSize(1) + .contains(new SimpleGrantedAuthority("ROLE_USER")); assertThat(token.isAuthenticated()).isEqualTo(true); assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); } @Test - public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinAfterEraseCredentialInvoked() throws JsonProcessingException, JSONException { + public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinAfterEraseCredentialInvoked() + throws JsonProcessingException, JSONException { UsernamePasswordAuthenticationToken token = createToken(); token.eraseCredentials(); String actualJson = mapper.writeValueAsString(token); - JSONAssert.assertEquals(AUTHENTICATED_JSON.replaceAll(UserDeserializerTests.USER_PASSWORD, "null"), actualJson, true); + JSONAssert.assertEquals(AUTHENTICATED_JSON.replaceAll(UserDeserializerTests.USER_PASSWORD, "null"), actualJson, + true); } @Test - public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinWithNonUserPrincipalTest() throws JsonProcessingException, JSONException { + public void serializeAuthenticatedUsernamePasswordAuthenticationTokenMixinWithNonUserPrincipalTest() + throws JsonProcessingException, JSONException { NonUserPrincipal principal = new NonUserPrincipal(); principal.setUsername("admin"); - UsernamePasswordAuthenticationToken token = - new UsernamePasswordAuthenticationToken(principal, null, new ArrayList<>()); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(principal, null, + new ArrayList<>()); String actualJson = mapper.writeValueAsString(token); JSONAssert.assertEquals(AUTHENTICATED_NON_USER_PRINCIPAL_JSON, actualJson, true); } @Test - public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenWithNonUserPrincipalTest() throws IOException { - UsernamePasswordAuthenticationToken token = mapper - .readValue(AUTHENTICATED_NON_USER_PRINCIPAL_JSON, UsernamePasswordAuthenticationToken.class); + public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenWithNonUserPrincipalTest() + throws IOException { + UsernamePasswordAuthenticationToken token = mapper.readValue(AUTHENTICATED_NON_USER_PRINCIPAL_JSON, + UsernamePasswordAuthenticationToken.class); assertThat(token).isNotNull(); assertThat(token.getPrincipal()).isNotNull().isInstanceOf(NonUserPrincipal.class); } @Test public void deserializeAuthenticatedUsernamePasswordAuthenticationTokenWithDetailsTest() throws IOException { - UsernamePasswordAuthenticationToken token = mapper - .readValue(AUTHENTICATED_STRINGDETAILS_JSON, UsernamePasswordAuthenticationToken.class); + UsernamePasswordAuthenticationToken token = mapper.readValue(AUTHENTICATED_STRINGDETAILS_JSON, + UsernamePasswordAuthenticationToken.class); assertThat(token).isNotNull(); assertThat(token.getPrincipal()).isNotNull().isInstanceOf(User.class); - assertThat(((User) token.getPrincipal()).getAuthorities()).isNotNull().hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); + assertThat(((User) token.getPrincipal()).getAuthorities()).isNotNull().hasSize(1) + .contains(new SimpleGrantedAuthority("ROLE_USER")); assertThat(token.isAuthenticated()).isEqualTo(true); assertThat(token.getAuthorities()).hasSize(1).contains(new SimpleGrantedAuthority("ROLE_USER")); assertThat(token.getDetails()).isExactlyInstanceOf(String.class).isEqualTo("details"); @@ -178,7 +189,8 @@ public class UsernamePasswordAuthenticationTokenMixinTests extends AbstractMixin // when String serialized = this.mapper.writeValueAsString(original); - UsernamePasswordAuthenticationToken deserialized = this.mapper.readValue(serialized, UsernamePasswordAuthenticationToken.class); + UsernamePasswordAuthenticationToken deserialized = this.mapper.readValue(serialized, + UsernamePasswordAuthenticationToken.class); // then assertThat(deserialized).isEqualTo(original); @@ -192,8 +204,8 @@ public class UsernamePasswordAuthenticationTokenMixinTests extends AbstractMixin // when String serialized = this.mapper.writeValueAsString(original); - UsernamePasswordAuthenticationToken deserialized = - this.mapper.readValue(serialized, UsernamePasswordAuthenticationToken.class); + UsernamePasswordAuthenticationToken deserialized = this.mapper.readValue(serialized, + UsernamePasswordAuthenticationToken.class); // then assertThat(deserialized).isEqualTo(original); @@ -201,12 +213,14 @@ public class UsernamePasswordAuthenticationTokenMixinTests extends AbstractMixin private UsernamePasswordAuthenticationToken createToken() { User user = createDefaultUser(); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities()); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, user.getPassword(), + user.getAuthorities()); return token; } @JsonClassDescription public static class NonUserPrincipal { + private String username; public String getUsername() { @@ -216,5 +230,7 @@ public class UsernamePasswordAuthenticationTokenMixinTests extends AbstractMixin public void setUsername(String username) { this.username = username; } + } + } diff --git a/core/src/test/java/org/springframework/security/provisioning/InMemoryUserDetailsManagerTests.java b/core/src/test/java/org/springframework/security/provisioning/InMemoryUserDetailsManagerTests.java index e86a2a55af..b0204a489b 100644 --- a/core/src/test/java/org/springframework/security/provisioning/InMemoryUserDetailsManagerTests.java +++ b/core/src/test/java/org/springframework/security/provisioning/InMemoryUserDetailsManagerTests.java @@ -28,6 +28,7 @@ import static org.assertj.core.api.Assertions.*; * @since 5.1 */ public class InMemoryUserDetailsManagerTests { + private final UserDetails user = PasswordEncodedUser.user(); private InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(this.user); @@ -41,12 +42,12 @@ public class InMemoryUserDetailsManagerTests { @Test public void changePasswordWhenUsernameIsNotInLowercase() { - UserDetails userNotLowerCase = User.withUserDetails(PasswordEncodedUser.user()) - .username("User") - .build(); + UserDetails userNotLowerCase = User.withUserDetails(PasswordEncodedUser.user()).username("User").build(); String newPassword = "newPassword"; this.manager.updatePassword(userNotLowerCase, newPassword); - assertThat(this.manager.loadUserByUsername(userNotLowerCase.getUsername()).getPassword()).isEqualTo(newPassword); + assertThat(this.manager.loadUserByUsername(userNotLowerCase.getUsername()).getPassword()) + .isEqualTo(newPassword); } + } diff --git a/core/src/test/java/org/springframework/security/provisioning/JdbcUserDetailsManagerTests.java b/core/src/test/java/org/springframework/security/provisioning/JdbcUserDetailsManagerTests.java index ebced08d6e..78b400ef53 100644 --- a/core/src/test/java/org/springframework/security/provisioning/JdbcUserDetailsManagerTests.java +++ b/core/src/test/java/org/springframework/security/provisioning/JdbcUserDetailsManagerTests.java @@ -50,15 +50,20 @@ import org.springframework.security.core.userdetails.UserDetails; * @author Luke Taylor */ public class JdbcUserDetailsManagerTests { + private static final String SELECT_JOE_SQL = "select * from users where username = 'joe'"; + private static final String SELECT_JOE_AUTHORITIES_SQL = "select * from authorities where username = 'joe'"; - private static final UserDetails joe = new User("joe", "password", true, true, true, - true, AuthorityUtils.createAuthorityList("A", "C", "B")); + private static final UserDetails joe = new User("joe", "password", true, true, true, true, + AuthorityUtils.createAuthorityList("A", "C", "B")); private static TestDataSource dataSource; + private JdbcUserDetailsManager manager; + private MockUserCache cache; + private JdbcTemplate template; @BeforeClass @@ -182,7 +187,6 @@ public class JdbcUserDetailsManagerTests { assertThat(cache.getUserMap().containsKey(newJoe.getUsername())).isFalse(); } - @Test public void userExistsReturnsFalseForNonExistentUsername() { assertThat(manager.userExists("joe")).isFalse(); @@ -236,8 +240,7 @@ public class JdbcUserDetailsManagerTests { insertJoe(); authenticateJoe(); AuthenticationManager am = mock(AuthenticationManager.class); - when(am.authenticate(any(Authentication.class))).thenThrow( - new BadCredentialsException("")); + when(am.authenticate(any(Authentication.class))).thenThrow(new BadCredentialsException("")); manager.setAuthenticationManager(am); @@ -279,12 +282,10 @@ public class JdbcUserDetailsManagerTests { @Test @SuppressWarnings("unchecked") public void createGroupInsertsCorrectData() { - manager.createGroup("TEST_GROUP", - AuthorityUtils.createAuthorityList("ROLE_X", "ROLE_Y")); + manager.createGroup("TEST_GROUP", AuthorityUtils.createAuthorityList("ROLE_X", "ROLE_Y")); - List roles = template - .queryForList("select ga.authority from groups g, group_authorities ga " - + "where ga.group_id = g.id " + "and g.group_name = 'TEST_GROUP'"); + List roles = template.queryForList("select ga.authority from groups g, group_authorities ga " + + "where ga.group_id = g.id " + "and g.group_name = 'TEST_GROUP'"); assertThat(roles).hasSize(2); } @@ -305,26 +306,22 @@ public class JdbcUserDetailsManagerTests { public void renameGroupIsSuccessful() { manager.renameGroup("GROUP_0", "GROUP_X"); - assertThat(template.queryForObject("select id from groups where group_name = 'GROUP_X'", - Integer.class)).isZero(); + assertThat(template.queryForObject("select id from groups where group_name = 'GROUP_X'", Integer.class)) + .isZero(); } @Test public void addingGroupUserSetsCorrectData() { manager.addUserToGroup("tom", "GROUP_0"); - assertThat( - template.queryForList( - "select username from group_members where group_id = 0")).hasSize(2); + assertThat(template.queryForList("select username from group_members where group_id = 0")).hasSize(2); } @Test public void removeUserFromGroupDeletesGroupMemberRow() { manager.removeUserFromGroup("jerry", "GROUP_1"); - assertThat( - template.queryForList( - "select group_id from group_members where username = 'jerry'")).hasSize(1); + assertThat(template.queryForList("select group_id from group_members where username = 'jerry'")).hasSize(1); } @Test @@ -337,8 +334,7 @@ public class JdbcUserDetailsManagerTests { GrantedAuthority auth = new SimpleGrantedAuthority("ROLE_X"); manager.addGroupAuthority("GROUP_0", auth); - template.queryForObject( - "select authority from group_authorities where authority = 'ROLE_X' and group_id = 0", + template.queryForObject("select authority from group_authorities where authority = 'ROLE_X' and group_id = 0", String.class); } @@ -346,14 +342,10 @@ public class JdbcUserDetailsManagerTests { public void deleteGroupAuthorityRemovesCorrectRows() { GrantedAuthority auth = new SimpleGrantedAuthority("ROLE_A"); manager.removeGroupAuthority("GROUP_0", auth); - assertThat( - template.queryForList( - "select authority from group_authorities where group_id = 0")).isEmpty(); + assertThat(template.queryForList("select authority from group_authorities where group_id = 0")).isEmpty(); manager.removeGroupAuthority("GROUP_2", auth); - assertThat( - template.queryForList( - "select authority from group_authorities where group_id = 2")).hasSize(2); + assertThat(template.queryForList("select authority from group_authorities where group_id = 2")).hasSize(2); } // SEC-1156 @@ -378,15 +370,15 @@ public class JdbcUserDetailsManagerTests { @Test public void createNewAuthenticationUsesNullPasswordToKeepPassordsSave() { insertJoe(); - UsernamePasswordAuthenticationToken currentAuth = new UsernamePasswordAuthenticationToken( - "joe", null, AuthorityUtils.createAuthorityList("ROLE_USER")); + UsernamePasswordAuthenticationToken currentAuth = new UsernamePasswordAuthenticationToken("joe", null, + AuthorityUtils.createAuthorityList("ROLE_USER")); Authentication updatedAuth = manager.createNewAuthentication(currentAuth, "new"); assertThat(updatedAuth.getCredentials()).isNull(); } private Authentication authenticateJoe() { - UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken( - "joe", "password", joe.getAuthorities()); + UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("joe", "password", + joe.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(auth); return auth; @@ -401,6 +393,7 @@ public class JdbcUserDetailsManagerTests { } private class MockUserCache implements UserCache { + private Map cache = new HashMap<>(); public UserDetails getUserFromCache(String username) { @@ -418,5 +411,7 @@ public class JdbcUserDetailsManagerTests { Map getUserMap() { return cache; } + } + } diff --git a/core/src/test/java/org/springframework/security/scheduling/AbstractSecurityContextSchedulingTaskExecutorTests.java b/core/src/test/java/org/springframework/security/scheduling/AbstractSecurityContextSchedulingTaskExecutorTests.java index 7ae6cfa990..12b4d0e3cb 100644 --- a/core/src/test/java/org/springframework/security/scheduling/AbstractSecurityContextSchedulingTaskExecutorTests.java +++ b/core/src/test/java/org/springframework/security/scheduling/AbstractSecurityContextSchedulingTaskExecutorTests.java @@ -32,8 +32,8 @@ import org.springframework.security.task.AbstractDelegatingSecurityContextAsyncT * @see CurrentSecurityContextSchedulingTaskExecutorTests * @see ExplicitSecurityContextSchedulingTaskExecutorTests */ -public abstract class AbstractSecurityContextSchedulingTaskExecutorTests extends - AbstractDelegatingSecurityContextAsyncTaskExecutorTests { +public abstract class AbstractSecurityContextSchedulingTaskExecutorTests + extends AbstractDelegatingSecurityContextAsyncTaskExecutorTests { @Mock protected SchedulingTaskExecutor taskExecutorDelegate; @@ -52,4 +52,5 @@ public abstract class AbstractSecurityContextSchedulingTaskExecutorTests extends } protected abstract DelegatingSecurityContextSchedulingTaskExecutor create(); + } diff --git a/core/src/test/java/org/springframework/security/scheduling/CurrentSecurityContextSchedulingTaskExecutorTests.java b/core/src/test/java/org/springframework/security/scheduling/CurrentSecurityContextSchedulingTaskExecutorTests.java index 3ee5bff24a..2134235050 100644 --- a/core/src/test/java/org/springframework/security/scheduling/CurrentSecurityContextSchedulingTaskExecutorTests.java +++ b/core/src/test/java/org/springframework/security/scheduling/CurrentSecurityContextSchedulingTaskExecutorTests.java @@ -26,8 +26,8 @@ import org.springframework.security.core.context.SecurityContext; * @since 3.2 * */ -public class CurrentSecurityContextSchedulingTaskExecutorTests extends - AbstractSecurityContextSchedulingTaskExecutorTests { +public class CurrentSecurityContextSchedulingTaskExecutorTests + extends AbstractSecurityContextSchedulingTaskExecutorTests { @Before public void setUp() throws Exception { @@ -37,4 +37,5 @@ public class CurrentSecurityContextSchedulingTaskExecutorTests extends protected DelegatingSecurityContextSchedulingTaskExecutor create() { return new DelegatingSecurityContextSchedulingTaskExecutor(taskExecutorDelegate); } + } diff --git a/core/src/test/java/org/springframework/security/scheduling/DelegatingSecurityContextTaskSchedulerTests.java b/core/src/test/java/org/springframework/security/scheduling/DelegatingSecurityContextTaskSchedulerTests.java index 33f49dce4e..4928c14ca3 100644 --- a/core/src/test/java/org/springframework/security/scheduling/DelegatingSecurityContextTaskSchedulerTests.java +++ b/core/src/test/java/org/springframework/security/scheduling/DelegatingSecurityContextTaskSchedulerTests.java @@ -30,7 +30,7 @@ import java.util.Date; import static org.mockito.Mockito.*; /** - * Test An implementation of {@link TaskScheduler} invoking it whenever the trigger + * Test An implementation of {@link TaskScheduler} invoking it whenever the trigger * indicates a next execution time. * * @author Richard Valdivieso @@ -40,8 +40,10 @@ public class DelegatingSecurityContextTaskSchedulerTests { @Mock private TaskScheduler scheduler; + @Mock private Runnable runnable; + @Mock private Trigger trigger; @@ -89,4 +91,5 @@ public class DelegatingSecurityContextTaskSchedulerTests { delegatingSecurityContextTaskScheduler.scheduleAtFixedRate(runnable, 1000L); verify(scheduler).scheduleAtFixedRate(isA(Runnable.class), eq(1000L)); } + } diff --git a/core/src/test/java/org/springframework/security/scheduling/ExplicitSecurityContextSchedulingTaskExecutorTests.java b/core/src/test/java/org/springframework/security/scheduling/ExplicitSecurityContextSchedulingTaskExecutorTests.java index d69f2ba664..02badbf9e5 100644 --- a/core/src/test/java/org/springframework/security/scheduling/ExplicitSecurityContextSchedulingTaskExecutorTests.java +++ b/core/src/test/java/org/springframework/security/scheduling/ExplicitSecurityContextSchedulingTaskExecutorTests.java @@ -26,8 +26,8 @@ import org.springframework.security.core.context.SecurityContext; * @since 3.2 * */ -public class ExplicitSecurityContextSchedulingTaskExecutorTests extends - AbstractSecurityContextSchedulingTaskExecutorTests { +public class ExplicitSecurityContextSchedulingTaskExecutorTests + extends AbstractSecurityContextSchedulingTaskExecutorTests { @Before public void setUp() throws Exception { @@ -35,7 +35,7 @@ public class ExplicitSecurityContextSchedulingTaskExecutorTests extends } protected DelegatingSecurityContextSchedulingTaskExecutor create() { - return new DelegatingSecurityContextSchedulingTaskExecutor(taskExecutorDelegate, - securityContext); + return new DelegatingSecurityContextSchedulingTaskExecutor(taskExecutorDelegate, securityContext); } + } diff --git a/core/src/test/java/org/springframework/security/task/AbstractDelegatingSecurityContextAsyncTaskExecutorTests.java b/core/src/test/java/org/springframework/security/task/AbstractDelegatingSecurityContextAsyncTaskExecutorTests.java index 29e4943a76..0636da970f 100644 --- a/core/src/test/java/org/springframework/security/task/AbstractDelegatingSecurityContextAsyncTaskExecutorTests.java +++ b/core/src/test/java/org/springframework/security/task/AbstractDelegatingSecurityContextAsyncTaskExecutorTests.java @@ -33,8 +33,9 @@ import org.springframework.security.concurrent.AbstractDelegatingSecurityContext * @see CurrentDelegatingSecurityContextAsyncTaskExecutorTests * @see ExplicitDelegatingSecurityContextAsyncTaskExecutorTests */ -public abstract class AbstractDelegatingSecurityContextAsyncTaskExecutorTests extends - AbstractDelegatingSecurityContextExecutorTests { +public abstract class AbstractDelegatingSecurityContextAsyncTaskExecutorTests + extends AbstractDelegatingSecurityContextExecutorTests { + @Mock protected AsyncTaskExecutor taskExecutorDelegate; @@ -68,4 +69,5 @@ public abstract class AbstractDelegatingSecurityContextAsyncTaskExecutorTests ex } protected abstract DelegatingSecurityContextAsyncTaskExecutor create(); + } diff --git a/core/src/test/java/org/springframework/security/task/CurrentDelegatingSecurityContextAsyncTaskExecutorTests.java b/core/src/test/java/org/springframework/security/task/CurrentDelegatingSecurityContextAsyncTaskExecutorTests.java index 059f09b912..e11ffad0f3 100644 --- a/core/src/test/java/org/springframework/security/task/CurrentDelegatingSecurityContextAsyncTaskExecutorTests.java +++ b/core/src/test/java/org/springframework/security/task/CurrentDelegatingSecurityContextAsyncTaskExecutorTests.java @@ -25,8 +25,8 @@ import org.junit.Before; * @since 3.2 * */ -public class CurrentDelegatingSecurityContextAsyncTaskExecutorTests extends - AbstractDelegatingSecurityContextAsyncTaskExecutorTests { +public class CurrentDelegatingSecurityContextAsyncTaskExecutorTests + extends AbstractDelegatingSecurityContextAsyncTaskExecutorTests { @Before public void setUp() throws Exception { diff --git a/core/src/test/java/org/springframework/security/task/CurrentDelegatingSecurityContextTaskExecutorTests.java b/core/src/test/java/org/springframework/security/task/CurrentDelegatingSecurityContextTaskExecutorTests.java index 402a098bfa..d4f9185a6d 100644 --- a/core/src/test/java/org/springframework/security/task/CurrentDelegatingSecurityContextTaskExecutorTests.java +++ b/core/src/test/java/org/springframework/security/task/CurrentDelegatingSecurityContextTaskExecutorTests.java @@ -31,8 +31,8 @@ import org.springframework.security.concurrent.AbstractDelegatingSecurityContext * @since 3.2 * */ -public class CurrentDelegatingSecurityContextTaskExecutorTests extends - AbstractDelegatingSecurityContextExecutorTests { +public class CurrentDelegatingSecurityContextTaskExecutorTests extends AbstractDelegatingSecurityContextExecutorTests { + @Mock private TaskExecutor taskExecutorDelegate; @@ -48,4 +48,5 @@ public class CurrentDelegatingSecurityContextTaskExecutorTests extends protected DelegatingSecurityContextExecutor create() { return new DelegatingSecurityContextTaskExecutor(taskExecutorDelegate); } + } diff --git a/core/src/test/java/org/springframework/security/task/ExplicitDelegatingSecurityContextAsyncTaskExecutorTests.java b/core/src/test/java/org/springframework/security/task/ExplicitDelegatingSecurityContextAsyncTaskExecutorTests.java index 05bee79214..55b4efe50c 100644 --- a/core/src/test/java/org/springframework/security/task/ExplicitDelegatingSecurityContextAsyncTaskExecutorTests.java +++ b/core/src/test/java/org/springframework/security/task/ExplicitDelegatingSecurityContextAsyncTaskExecutorTests.java @@ -25,8 +25,8 @@ import org.junit.Before; * @since 3.2 * */ -public class ExplicitDelegatingSecurityContextAsyncTaskExecutorTests extends - AbstractDelegatingSecurityContextAsyncTaskExecutorTests { +public class ExplicitDelegatingSecurityContextAsyncTaskExecutorTests + extends AbstractDelegatingSecurityContextAsyncTaskExecutorTests { @Before public void setUp() throws Exception { @@ -35,8 +35,7 @@ public class ExplicitDelegatingSecurityContextAsyncTaskExecutorTests extends @Override protected DelegatingSecurityContextAsyncTaskExecutor create() { - return new DelegatingSecurityContextAsyncTaskExecutor(taskExecutorDelegate, - securityContext); + return new DelegatingSecurityContextAsyncTaskExecutor(taskExecutorDelegate, securityContext); } } diff --git a/core/src/test/java/org/springframework/security/task/ExplicitDelegatingSecurityContextTaskExecutorTests.java b/core/src/test/java/org/springframework/security/task/ExplicitDelegatingSecurityContextTaskExecutorTests.java index 02d93d9aee..15b3de0557 100644 --- a/core/src/test/java/org/springframework/security/task/ExplicitDelegatingSecurityContextTaskExecutorTests.java +++ b/core/src/test/java/org/springframework/security/task/ExplicitDelegatingSecurityContextTaskExecutorTests.java @@ -31,8 +31,8 @@ import org.springframework.security.concurrent.AbstractDelegatingSecurityContext * @since 3.2 * */ -public class ExplicitDelegatingSecurityContextTaskExecutorTests extends - AbstractDelegatingSecurityContextExecutorTests { +public class ExplicitDelegatingSecurityContextTaskExecutorTests extends AbstractDelegatingSecurityContextExecutorTests { + @Mock private TaskExecutor taskExecutorDelegate; @@ -46,7 +46,7 @@ public class ExplicitDelegatingSecurityContextTaskExecutorTests extends } protected DelegatingSecurityContextExecutor create() { - return new DelegatingSecurityContextTaskExecutor(taskExecutorDelegate, - securityContext); + return new DelegatingSecurityContextTaskExecutor(taskExecutorDelegate, securityContext); } + } diff --git a/core/src/test/java/org/springframework/security/util/FieldUtilsTests.java b/core/src/test/java/org/springframework/security/util/FieldUtilsTests.java index 50b90c7886..a6c6746de9 100644 --- a/core/src/test/java/org/springframework/security/util/FieldUtilsTests.java +++ b/core/src/test/java/org/springframework/security/util/FieldUtilsTests.java @@ -15,7 +15,6 @@ */ package org.springframework.security.util; - import static org.assertj.core.api.Assertions.assertThat; import org.junit.*; @@ -42,15 +41,21 @@ public class FieldUtilsTests { catch (IllegalStateException expected) { } } + } @SuppressWarnings("unused") class TestClass { + private String protectedField = "x"; + private Nested nested = new Nested(); + } @SuppressWarnings("unused") class Nested { + private String protectedField = "z"; + } diff --git a/core/src/test/java/org/springframework/security/util/InMemoryResourceTests.java b/core/src/test/java/org/springframework/security/util/InMemoryResourceTests.java index b1b7fe8098..3b8f0062b3 100644 --- a/core/src/test/java/org/springframework/security/util/InMemoryResourceTests.java +++ b/core/src/test/java/org/springframework/security/util/InMemoryResourceTests.java @@ -38,4 +38,5 @@ public class InMemoryResourceTests { assertThat(new InMemoryResource("xxx").equals(new InMemoryResource("xxxx"))).isFalse(); assertThat(new InMemoryResource("xxx").equals(new Object())).isFalse(); } + } diff --git a/core/src/test/java/org/springframework/security/util/MethodInvocationUtilsTests.java b/core/src/test/java/org/springframework/security/util/MethodInvocationUtilsTests.java index 2c055d33a3..3aadc6bd64 100644 --- a/core/src/test/java/org/springframework/security/util/MethodInvocationUtilsTests.java +++ b/core/src/test/java/org/springframework/security/util/MethodInvocationUtilsTests.java @@ -25,7 +25,6 @@ import org.springframework.security.access.annotation.BusinessServiceImpl; import java.io.Serializable; /** - * * @author Luke Taylor */ public class MethodInvocationUtilsTests { @@ -34,28 +33,26 @@ public class MethodInvocationUtilsTests { public void createFromClassReturnsMethodWithNoArgInfoForMethodWithNoArgs() { new MethodInvocationUtils(); - MethodInvocation mi = MethodInvocationUtils.createFromClass(String.class, - "length"); + MethodInvocation mi = MethodInvocationUtils.createFromClass(String.class, "length"); assertThat(mi).isNotNull(); } @Test public void createFromClassReturnsMethodIfArgInfoOmittedAndMethodNameIsUnique() { - MethodInvocation mi = MethodInvocationUtils.createFromClass( - BusinessServiceImpl.class, "methodReturningAnArray"); + MethodInvocation mi = MethodInvocationUtils.createFromClass(BusinessServiceImpl.class, + "methodReturningAnArray"); assertThat(mi).isNotNull(); } @Test(expected = IllegalArgumentException.class) public void exceptionIsRaisedIfArgInfoOmittedAndMethodNameIsNotUnique() { - MethodInvocationUtils.createFromClass(BusinessServiceImpl.class, - "methodReturningAList"); + MethodInvocationUtils.createFromClass(BusinessServiceImpl.class, "methodReturningAList"); } @Test public void createFromClassReturnsMethodIfGivenArgInfoForMethodWithArgs() { - MethodInvocation mi = MethodInvocationUtils.createFromClass(null, String.class, - "compareTo", new Class[] { String.class }, new Object[] { "" }); + MethodInvocation mi = MethodInvocationUtils.createFromClass(null, String.class, "compareTo", + new Class[] { String.class }, new Object[] { "" }); assertThat(mi).isNotNull(); } @@ -63,8 +60,7 @@ public class MethodInvocationUtilsTests { public void createFromObjectLocatesExistingMethods() { AdvisedTarget t = new AdvisedTarget(); // Just lie about interfaces - t.setInterfaces(new Class[] { Serializable.class, MethodInvocation.class, - Blah.class }); + t.setInterfaces(new Class[] { Serializable.class, MethodInvocation.class, Blah.class }); MethodInvocation mi = MethodInvocationUtils.create(t, "blah"); assertThat(mi).isNotNull(); @@ -77,11 +73,16 @@ public class MethodInvocationUtilsTests { } interface Blah { + void blah(); + } class AdvisedTarget extends AdvisedSupport implements Blah { + public void blah() { } + } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2EncodingUtils.java b/crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2EncodingUtils.java index 9c1920e2bf..18efe2479f 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2EncodingUtils.java +++ b/crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2EncodingUtils.java @@ -28,22 +28,24 @@ import org.bouncycastle.util.Arrays; * @since 5.3 */ class Argon2EncodingUtils { + private static final Base64.Encoder b64encoder = Base64.getEncoder().withoutPadding(); + private static final Base64.Decoder b64decoder = Base64.getDecoder(); /** - * Encodes a raw Argon2-hash and its parameters into the standard Argon2-hash-string as specified in the reference - * implementation (https://github.com/P-H-C/phc-winner-argon2/blob/master/src/encoding.c#L244): + * Encodes a raw Argon2-hash and its parameters into the standard Argon2-hash-string + * as specified in the reference implementation + * (https://github.com/P-H-C/phc-winner-argon2/blob/master/src/encoding.c#L244): * * {@code $argon2[$v=]$m=,t=,p=$$} * - * where {@code } is either 'd', 'id', or 'i', {@code } is a decimal integer (positive, - * fits in an 'unsigned long'), and {@code } is Base64-encoded data (no '=' padding - * characters, no newline or whitespace). - * - * The last two binary chunks (encoded in Base64) are, in that order, - * the salt and the output. If no salt has been used, the salt will be omitted. + * where {@code } is either 'd', 'id', or 'i', {@code } is a decimal integer + * (positive, fits in an 'unsigned long'), and {@code } is Base64-encoded data + * (no '=' padding characters, no newline or whitespace). * + * The last two binary chunks (encoded in Base64) are, in that order, the salt and the + * output. If no salt has been used, the salt will be omitted. * @param hash the raw Argon2 hash in binary format * @param parameters the Argon2 parameters that were used to create the hash * @return the encoded Argon2-hash-string as described above @@ -53,44 +55,48 @@ class Argon2EncodingUtils { StringBuilder stringBuilder = new StringBuilder(); switch (parameters.getType()) { - case Argon2Parameters.ARGON2_d: stringBuilder.append("$argon2d"); break; - case Argon2Parameters.ARGON2_i: stringBuilder.append("$argon2i"); break; - case Argon2Parameters.ARGON2_id: stringBuilder.append("$argon2id"); break; - default: throw new IllegalArgumentException("Invalid algorithm type: "+parameters.getType()); + case Argon2Parameters.ARGON2_d: + stringBuilder.append("$argon2d"); + break; + case Argon2Parameters.ARGON2_i: + stringBuilder.append("$argon2i"); + break; + case Argon2Parameters.ARGON2_id: + stringBuilder.append("$argon2id"); + break; + default: + throw new IllegalArgumentException("Invalid algorithm type: " + parameters.getType()); } - stringBuilder.append("$v=").append(parameters.getVersion()) - .append("$m=").append(parameters.getMemory()) - .append(",t=").append(parameters.getIterations()) - .append(",p=").append(parameters.getLanes()); + stringBuilder.append("$v=").append(parameters.getVersion()).append("$m=").append(parameters.getMemory()) + .append(",t=").append(parameters.getIterations()).append(",p=").append(parameters.getLanes()); if (parameters.getSalt() != null) { - stringBuilder.append("$") - .append(b64encoder.encodeToString(parameters.getSalt())); + stringBuilder.append("$").append(b64encoder.encodeToString(parameters.getSalt())); } - stringBuilder.append("$") - .append(b64encoder.encodeToString(hash)); + stringBuilder.append("$").append(b64encoder.encodeToString(hash)); return stringBuilder.toString(); } /** * Decodes an Argon2 hash string as specified in the reference implementation - * (https://github.com/P-H-C/phc-winner-argon2/blob/master/src/encoding.c#L244) into the raw hash and the used - * parameters. + * (https://github.com/P-H-C/phc-winner-argon2/blob/master/src/encoding.c#L244) into + * the raw hash and the used parameters. * * The hash has to be formatted as follows: * {@code $argon2[$v=]$m=,t=,p=$$} * - * where {@code } is either 'd', 'id', or 'i', {@code } is a decimal integer (positive, - * fits in an 'unsigned long'), and {@code } is Base64-encoded data (no '=' padding - * characters, no newline or whitespace). + * where {@code } is either 'd', 'id', or 'i', {@code } is a decimal integer + * (positive, fits in an 'unsigned long'), and {@code } is Base64-encoded data + * (no '=' padding characters, no newline or whitespace). * - * The last two binary chunks (encoded in Base64) are, in that order, - * the salt and the output. Both are required. The binary salt length and the - * output length must be in the allowed ranges defined in argon2.h. + * The last two binary chunks (encoded in Base64) are, in that order, the salt and the + * output. Both are required. The binary salt length and the output length must be in + * the allowed ranges defined in argon2.h. * @param encodedHash the Argon2 hash string as described above - * @return an {@link Argon2Hash} object containing the raw hash and the {@link Argon2Parameters}. + * @return an {@link Argon2Hash} object containing the raw hash and the + * {@link Argon2Parameters}. * @throws IllegalArgumentException if the encoded hash is malformed */ public static Argon2Hash decode(String encodedHash) throws IllegalArgumentException { @@ -105,10 +111,17 @@ class Argon2EncodingUtils { int currentPart = 1; switch (parts[currentPart++]) { - case "argon2d": paramsBuilder = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_d); break; - case "argon2i": paramsBuilder = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_i); break; - case "argon2id": paramsBuilder = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id); break; - default: throw new IllegalArgumentException("Invalid algorithm type: "+parts[0]); + case "argon2d": + paramsBuilder = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_d); + break; + case "argon2i": + paramsBuilder = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_i); + break; + case "argon2id": + paramsBuilder = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id); + break; + default: + throw new IllegalArgumentException("Invalid algorithm type: " + parts[0]); } if (parts[currentPart].startsWith("v=")) { @@ -124,19 +137,22 @@ class Argon2EncodingUtils { if (performanceParams[0].startsWith("m=")) { paramsBuilder.withMemoryAsKB(Integer.parseInt(performanceParams[0].substring(2))); - } else { + } + else { throw new IllegalArgumentException("Invalid memory parameter"); } if (performanceParams[1].startsWith("t=")) { paramsBuilder.withIterations(Integer.parseInt(performanceParams[1].substring(2))); - } else { + } + else { throw new IllegalArgumentException("Invalid iterations parameter"); } if (performanceParams[2].startsWith("p=")) { paramsBuilder.withParallelism(Integer.parseInt(performanceParams[2].substring(2))); - } else { + } + else { throw new IllegalArgumentException("Invalid parallelity parameter"); } @@ -148,6 +164,7 @@ class Argon2EncodingUtils { public static class Argon2Hash { private byte[] hash; + private Argon2Parameters parameters; Argon2Hash(byte[] hash, Argon2Parameters parameters) { @@ -170,5 +187,7 @@ class Argon2EncodingUtils { public void setParameters(Argon2Parameters parameters) { this.parameters = parameters; } + } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoder.java b/crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoder.java index 0e38c1072b..f66e31e1ba 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoder.java +++ b/crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoder.java @@ -26,16 +26,19 @@ import org.springframework.security.crypto.password.PasswordEncoder; /** *

      - * Implementation of PasswordEncoder that uses the Argon2 hashing function. - * Clients can optionally supply the length of the salt to use, the length - * of the generated hash, a cpu cost parameter, a memory cost parameter - * and a parallelization parameter. + * Implementation of PasswordEncoder that uses the Argon2 hashing function. Clients can + * optionally supply the length of the salt to use, the length of the generated hash, a + * cpu cost parameter, a memory cost parameter and a parallelization parameter. *

      * - *

      Note:

      - *

      The currently implementation uses Bouncy castle which does not exploit - * parallelism/optimizations that password crackers will, so there is an - * unnecessary asymmetry between attacker and defender.

      + *

      + * Note: + *

      + *

      + * The currently implementation uses Bouncy castle which does not exploit + * parallelism/optimizations that password crackers will, so there is an unnecessary + * asymmetry between attacker and defender. + *

      * * @author Simeon Macke * @since 5.3 @@ -43,16 +46,23 @@ import org.springframework.security.crypto.password.PasswordEncoder; public class Argon2PasswordEncoder implements PasswordEncoder { private static final int DEFAULT_SALT_LENGTH = 16; + private static final int DEFAULT_HASH_LENGTH = 32; + private static final int DEFAULT_PARALLELISM = 1; + private static final int DEFAULT_MEMORY = 1 << 12; + private static final int DEFAULT_ITERATIONS = 3; private final Log logger = LogFactory.getLog(getClass()); private final int hashLength; + private final int parallelism; + private final int memory; + private final int iterations; private final BytesKeyGenerator saltGenerator; @@ -75,12 +85,8 @@ public class Argon2PasswordEncoder implements PasswordEncoder { byte[] salt = saltGenerator.generateKey(); byte[] hash = new byte[hashLength]; - Argon2Parameters params = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id). - withSalt(salt). - withParallelism(parallelism). - withMemoryAsKB(memory). - withIterations(iterations). - build(); + Argon2Parameters params = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id).withSalt(salt) + .withParallelism(parallelism).withMemoryAsKB(memory).withIterations(iterations).build(); Argon2BytesGenerator generator = new Argon2BytesGenerator(); generator.init(params); generator.generateBytes(rawPassword.toString().toCharArray(), hash); @@ -99,7 +105,8 @@ public class Argon2PasswordEncoder implements PasswordEncoder { try { decoded = Argon2EncodingUtils.decode(encodedPassword); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { logger.warn("Malformed password hash", e); return false; } diff --git a/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java b/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java index ab9a9d7a8a..0d57216641 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java +++ b/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java @@ -19,25 +19,23 @@ import java.util.Arrays; import java.security.SecureRandom; /** - * BCrypt implements OpenBSD-style Blowfish password hashing using - * the scheme described in "A Future-Adaptable Password Scheme" by - * Niels Provos and David Mazieres. + * BCrypt implements OpenBSD-style Blowfish password hashing using the scheme described in + * "A Future-Adaptable Password Scheme" by Niels Provos and David Mazieres. *

      - * This password hashing system tries to thwart off-line password - * cracking using a computationally-intensive hashing algorithm, - * based on Bruce Schneier's Blowfish cipher. The work factor of - * the algorithm is parameterised, so it can be increased as - * computers get faster. + * This password hashing system tries to thwart off-line password cracking using a + * computationally-intensive hashing algorithm, based on Bruce Schneier's Blowfish cipher. + * The work factor of the algorithm is parameterised, so it can be increased as computers + * get faster. *

      - * Usage is really simple. To hash a password for the first time, - * call the hashpw method with a random salt, like this: + * Usage is really simple. To hash a password for the first time, call the hashpw method + * with a random salt, like this: *

      * * String pw_hash = BCrypt.hashpw(plain_password, BCrypt.gensalt());
      *
      *

      - * To check whether a plaintext password matches one that has been - * hashed previously, use the checkpw method: + * To check whether a plaintext password matches one that has been hashed previously, use + * the checkpw method: *

      * * if (BCrypt.checkpw(candidate_password, stored_hash))
      @@ -46,347 +44,185 @@ import java.security.SecureRandom; *     System.out.println("It does not match");
      *
      *

      - * The gensalt() method takes an optional parameter (log_rounds) - * that determines the computational complexity of the hashing: + * The gensalt() method takes an optional parameter (log_rounds) that determines the + * computational complexity of the hashing: *

      * * String strong_salt = BCrypt.gensalt(10)
      * String stronger_salt = BCrypt.gensalt(12)
      *
      *

      - * The amount of work increases exponentially (2**log_rounds), so - * each increment is twice as much work. The default log_rounds is - * 10, and the valid range is 4 to 31. + * The amount of work increases exponentially (2**log_rounds), so each increment is twice + * as much work. The default log_rounds is 10, and the valid range is 4 to 31. * * @author Damien Miller * @version 0.3 */ public class BCrypt { + // BCrypt parameters private static final int GENSALT_DEFAULT_LOG2_ROUNDS = 10; + private static final int BCRYPT_SALT_LEN = 16; // Blowfish parameters private static final int BLOWFISH_NUM_ROUNDS = 16; // Initial contents of key schedule - private static final int P_orig[] = { - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, - 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, - 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, - 0x9216d5d9, 0x8979fb1b - }; - private static final int S_orig[] = { - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, - 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, - 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, - 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, - 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, - 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, - 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, - 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, - 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, - 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, - 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, - 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, - 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, - 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, - 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, - 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, - 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, - 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, - 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, - 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, - 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, - 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, - 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, - 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, - 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, - 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, - 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, - 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, - 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, - 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, - 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, - 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, - 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, - 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, - 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, - 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, - 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, - 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, - 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, - 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, - 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, - 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, - 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, - 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, - 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, - 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, - 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, - 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, - 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, - 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, - 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, - 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, - 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, - 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, - 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, - 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, - 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, - 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, - 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, - 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, - 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, - 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, - 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, - 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, - 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, - 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, - 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, - 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, - 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, - 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, - 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, - 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, - 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, - 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, - 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, - 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, - 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, - 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, - 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, - 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, - 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, - 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, - 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, - 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, - 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, - 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, - 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, - 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, - 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, - 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, - 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, - 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, - 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, - 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, - 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, - 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, - 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, - 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, - 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, - 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, - 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, - 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, - 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, - 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, - 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, - 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, - 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, - 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, - 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, - 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, - 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, - 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, - 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, - 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, - 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, - 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, - 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, - 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, - 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, - 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, - 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, - 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, - 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, - 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, - 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, - 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, - 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, - 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, - 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, - 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, - 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, - 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, - 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, - 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, - 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, - 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, - 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, - 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, - 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, - 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, - 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, - 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, - 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, - 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, - 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, - 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, - 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, - 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, - 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, - 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, - 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, - 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, - 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, - 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, - 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, - 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, - 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, - 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, - 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, - 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, - 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, - 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, - 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, - 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, - 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, - 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, - 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, - 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, - 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, - 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, - 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, - 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, - 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, - 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, - 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, - 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, - 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, - 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, - 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, - 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, - 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, - 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, - 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, - 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, - 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, - 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, - 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, - 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, - 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, - 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, - 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, - 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, - 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, - 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, - 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, - 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, - 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, - 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, - 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, - 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, - 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, - 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, - 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, - 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, - 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, - 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, - 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, - 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, - 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, - 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, - 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, - 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, - 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, - 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, - 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, - 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, - 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, - 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, - 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, - 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, - 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, - 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, - 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, - 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, - 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, - 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, - 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, - 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, - 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, - 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, - 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, - 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, - 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, - 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, - 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, - 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, - 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, - 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, - 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, - 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, - 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, - 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, - 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, - 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, - 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, - 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, - 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, - 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 - }; + private static final int P_orig[] = { 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, + 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, + 0xb5470917, 0x9216d5d9, 0x8979fb1b }; + + private static final int S_orig[] = { 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, + 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, + 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, + 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, + 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, + 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, + 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, + 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, + 0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, + 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, + 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, + 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, + 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, + 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, + 0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, + 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, + 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, + 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, + 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, + 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, + 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, + 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, 0x4b7a70e9, 0xb5b32944, + 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, + 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, + 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, + 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, + 0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, + 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, + 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, + 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, + 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, + 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, + 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, + 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170, + 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, + 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, + 0x97e32d77, 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, + 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, + 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, + 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, + 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, + 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, + 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, + 0xe6e39f2b, 0xdb83adf7, 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, + 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, + 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, + 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, + 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, + 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, + 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, + 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, + 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, + 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, 0x3a6f6eab, + 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, + 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, + 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, + 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, + 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, + 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, + 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, + 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, + 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, + 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, + 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, + 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, 0x3a39ce37, 0xd3faf5cf, 0xabc27737, + 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, + 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, + 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, + 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, + 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, + 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, + 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, + 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, + 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, + 0x09072166, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, + 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, + 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, + 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, + 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, + 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, + 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, + 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, + 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, + 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, + 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, + 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, + 0x3ac372e6 }; // bcrypt IV: "OrpheanBeholderScryDoubt" - static private final int bf_crypt_ciphertext[] = { - 0x4f727068, 0x65616e42, 0x65686f6c, - 0x64657253, 0x63727944, 0x6f756274 - }; + static private final int bf_crypt_ciphertext[] = { 0x4f727068, 0x65616e42, 0x65686f6c, 0x64657253, 0x63727944, + 0x6f756274 }; // Table for Base64 encoding - static private final char base64_code[] = { - '.', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', - 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', - 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', - 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', - '6', '7', '8', '9' - }; + static private final char base64_code[] = { '.', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', + '2', '3', '4', '5', '6', '7', '8', '9' }; // Table for Base64 decoding - static private final byte index_64[] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 0, 1, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, -1, -1, - -1, -1, -1, -1, -1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - -1, -1, -1, -1, -1, -1, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, -1, -1, -1, -1, -1 - }; + static private final byte index_64[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, -1, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1, -1, -1, -1, -1 }; static final int MIN_LOG_ROUNDS = 4; static final int MAX_LOG_ROUNDS = 31; // Expanded Blowfish key private int P[]; + private int S[]; /** * Encode a byte array using bcrypt's slightly-modified base64 encoding scheme. Note * that this is not compatible with the standard MIME-base64 * encoding. - * * @param d the byte array to encode * @param len the number of bytes to encode * @param rs the destination buffer for the base64-encoded string * @exception IllegalArgumentException if the length is invalid */ - static void encode_base64(byte d[], int len, StringBuilder rs) - throws IllegalArgumentException { + static void encode_base64(byte d[], int len, StringBuilder rs) throws IllegalArgumentException { int off = 0; int c1, c2; @@ -418,10 +254,10 @@ public class BCrypt { } /** - * Look up the 3 bits base64-encoded by the specified character, - * range-checking againt conversion table - * @param x the base64-encoded value - * @return the decoded value of x + * Look up the 3 bits base64-encoded by the specified character, range-checking againt + * conversion table + * @param x the base64-encoded value + * @return the decoded value of x */ private static byte char64(char x) { if ((int) x < 0 || (int) x >= index_64.length) @@ -430,23 +266,21 @@ public class BCrypt { } /** - * Decode a string encoded using bcrypt's base64 scheme to a - * byte array. Note that this is *not* compatible with - * the standard MIME-base64 encoding. - * @param s the string to decode - * @param maxolen the maximum number of bytes to decode - * @return an array containing the decoded bytes + * Decode a string encoded using bcrypt's base64 scheme to a byte array. Note that + * this is *not* compatible with the standard MIME-base64 encoding. + * @param s the string to decode + * @param maxolen the maximum number of bytes to decode + * @return an array containing the decoded bytes * @throws IllegalArgumentException if maxolen is invalid */ - static byte[] decode_base64(String s, int maxolen) - throws IllegalArgumentException { + static byte[] decode_base64(String s, int maxolen) throws IllegalArgumentException { StringBuilder rs = new StringBuilder(); int off = 0, slen = s.length(), olen = 0; byte ret[]; byte c1, c2, c3, c4, o; if (maxolen <= 0) - throw new IllegalArgumentException ("Invalid maxolen"); + throw new IllegalArgumentException("Invalid maxolen"); while (off < slen - 1 && olen < maxolen) { c1 = char64(s.charAt(off++)); @@ -480,10 +314,9 @@ public class BCrypt { } /** - * Blowfish encipher a single 64-bit block encoded as - * two 32-bit halves - * @param lr an array containing the two 32-bit half blocks - * @param off the position in the array of the blocks + * Blowfish encipher a single 64-bit block encoded as two 32-bit halves + * @param lr an array containing the two 32-bit half blocks + * @param off the position in the array of the blocks */ private void encipher(int lr[], int off) { int i, n, l = lr[off], r = lr[off + 1]; @@ -510,12 +343,11 @@ public class BCrypt { /** * Cycically extract a word of key material - * @param data the string to extract the data from - * @param offp a "pointer" (as a one-entry array) to the - * current offset into data - * @param signp a "pointer" (as a one-entry array) to the - * cumulative flag for non-benign sign extension - * @return correct and buggy next word of material from data as int[2] + * @param data the string to extract the data from + * @param offp a "pointer" (as a one-entry array) to the current offset into data + * @param signp a "pointer" (as a one-entry array) to the cumulative flag for + * non-benign sign extension + * @return correct and buggy next word of material from data as int[2] */ private static int[] streamtowords(byte data[], int offp[], int signp[]) { int i; @@ -526,7 +358,8 @@ public class BCrypt { for (i = 0; i < 4; i++) { words[0] = (words[0] << 8) | (data[off] & 0xff); words[1] = (words[1] << 8) | (int) data[off]; // sign extension bug - if (i > 0) sign |= words[1] & 0x80; + if (i > 0) + sign |= words[1] & 0x80; off = (off + 1) % data.length; } @@ -537,10 +370,9 @@ public class BCrypt { /** * Cycically extract a word of key material - * @param data the string to extract the data from - * @param offp a "pointer" (as a one-entry array) to the - * current offset into data - * @return the next word of material from data + * @param data the string to extract the data from + * @param offp a "pointer" (as a one-entry array) to the current offset into data + * @return the next word of material from data */ private static int streamtoword(byte data[], int offp[]) { int signp[] = { 0 }; @@ -549,10 +381,9 @@ public class BCrypt { /** * Cycically extract a word of key material, with sign-extension bug - * @param data the string to extract the data from - * @param offp a "pointer" (as a one-entry array) to the - * current offset into data - * @return the next word of material from data + * @param data the string to extract the data from + * @param offp a "pointer" (as a one-entry array) to the current offset into data + * @return the next word of material from data */ private static int streamtoword_bug(byte data[], int offp[]) { int signp[] = { 0 }; @@ -569,9 +400,9 @@ public class BCrypt { /** * Key the Blowfish cipher - * @param key an array containing the key - * @param sign_ext_bug true to implement the 2x bug - * @param safety bit 16 is set when the safety measure is requested + * @param key an array containing the key + * @param sign_ext_bug true to implement the 2x bug + * @param safety bit 16 is set when the safety measure is requested */ private void key(byte key[], boolean sign_ext_bug, int safety) { int i; @@ -599,22 +430,20 @@ public class BCrypt { } /** - * Perform the "enhanced key schedule" step described by - * Provos and Mazieres in "A Future-Adaptable Password Scheme" - * https://www.openbsd.org/papers/bcrypt-paper.ps - * @param data salt information - * @param key password information - * @param sign_ext_bug true to implement the 2x bug - * @param safety bit 16 is set when the safety measure is requested + * Perform the "enhanced key schedule" step described by Provos and Mazieres in "A + * Future-Adaptable Password Scheme" https://www.openbsd.org/papers/bcrypt-paper.ps + * @param data salt information + * @param key password information + * @param sign_ext_bug true to implement the 2x bug + * @param safety bit 16 is set when the safety measure is requested */ - private void ekskey(byte data[], byte key[], - boolean sign_ext_bug, int safety) { + private void ekskey(byte data[], byte key[], boolean sign_ext_bug, int safety) { int i; int koffp[] = { 0 }, doffp[] = { 0 }; int lr[] = { 0, 0 }; int plen = P.length, slen = S.length; int signp[] = { 0 }; // non-benign sign-extension flag - int diff = 0; // zero iff correct and buggy are same + int diff = 0; // zero iff correct and buggy are same for (i = 0; i < plen; i++) { int words[] = streamtowords(key, koffp, signp); @@ -626,12 +455,12 @@ public class BCrypt { /* * At this point, "diff" is zero iff the correct and buggy algorithms produced - * exactly the same result. If so and if "sign" is non-zero, which indicates - * that there was a non-benign sign extension, this means that we have a - * collision between the correctly computed hash for this password and a set of - * passwords that could be supplied to the buggy algorithm. Our safety measure - * is meant to protect from such many-buggy to one-correct collisions, by - * deviating from the correct algorithm in such cases. Let's check for this. + * exactly the same result. If so and if "sign" is non-zero, which indicates that + * there was a non-benign sign extension, this means that we have a collision + * between the correctly computed hash for this password and a set of passwords + * that could be supplied to the buggy algorithm. Our safety measure is meant to + * protect from such many-buggy to one-correct collisions, by deviating from the + * correct algorithm in such cases. Let's check for this. */ diff |= diff >> 16; /* still zero iff exact match */ diff &= 0xffff; /* ditto */ @@ -640,15 +469,15 @@ public class BCrypt { sign &= ~diff & safety; /* action needed? */ /* - * If we have determined that we need to deviate from the correct algorithm, - * flip bit 16 in initial expanded key. (The choice of 16 is arbitrary, but - * let's stick to it now. It came out of the approach we used above, and it's - * not any worse than any other choice we could make.) + * If we have determined that we need to deviate from the correct algorithm, flip + * bit 16 in initial expanded key. (The choice of 16 is arbitrary, but let's stick + * to it now. It came out of the approach we used above, and it's not any worse + * than any other choice we could make.) * * It is crucial that we don't do the same to the expanded key used in the main - * Eksblowfish loop. By doing it to only one of these two, we deviate from a - * state that could be directly specified by a password to the buggy algorithm - * (and to the fully correct one as well, but that's a side-effect). + * Eksblowfish loop. By doing it to only one of these two, we deviate from a state + * that could be directly specified by a password to the buggy algorithm (and to + * the fully correct one as well, but that's a side-effect). */ P[0] ^= sign; @@ -677,28 +506,25 @@ public class BCrypt { } /** - * Perform the central password hashing step in the - * bcrypt scheme - * @param password the password to hash - * @param salt the binary salt to hash with the password - * @param log_rounds the binary logarithm of the number - * of rounds of hashing to apply - * @param sign_ext_bug true to implement the 2x bug - * @param safety bit 16 is set when the safety measure is requested - * @return an array containing the binary hashed password + * Perform the central password hashing step in the bcrypt scheme + * @param password the password to hash + * @param salt the binary salt to hash with the password + * @param log_rounds the binary logarithm of the number of rounds of hashing to apply + * @param sign_ext_bug true to implement the 2x bug + * @param safety bit 16 is set when the safety measure is requested + * @return an array containing the binary hashed password */ - private byte[] crypt_raw(byte password[], byte salt[], int log_rounds, - boolean sign_ext_bug, int safety) { + private byte[] crypt_raw(byte password[], byte salt[], int log_rounds, boolean sign_ext_bug, int safety) { int rounds, i, j; - int cdata[] = bf_crypt_ciphertext.clone(); + int cdata[] = bf_crypt_ciphertext.clone(); int clen = cdata.length; byte ret[]; if (log_rounds < 4 || log_rounds > 31) - throw new IllegalArgumentException ("Bad number of rounds"); + throw new IllegalArgumentException("Bad number of rounds"); rounds = 1 << log_rounds; if (salt.length != BCRYPT_SALT_LEN) - throw new IllegalArgumentException ("Bad salt length"); + throw new IllegalArgumentException("Bad salt length"); init_key(); ekskey(salt, password, sign_ext_bug, safety); @@ -724,10 +550,9 @@ public class BCrypt { /** * Hash a password using the OpenBSD bcrypt scheme - * @param password the password to hash - * @param salt the salt to hash with (perhaps generated - * using BCrypt.gensalt) - * @return the hashed password + * @param password the password to hash + * @param salt the salt to hash with (perhaps generated using BCrypt.gensalt) + * @return the hashed password */ public static String hashpw(String password, String salt) { byte passwordb[]; @@ -739,10 +564,9 @@ public class BCrypt { /** * Hash a password using the OpenBSD bcrypt scheme - * @param passwordb the password to hash, as a byte array - * @param salt the salt to hash with (perhaps generated - * using BCrypt.gensalt) - * @return the hashed password + * @param passwordb the password to hash, as a byte array + * @param salt the salt to hash with (perhaps generated using BCrypt.gensalt) + * @return the hashed password */ public static String hashpw(byte passwordb[], String salt) { BCrypt B; @@ -763,20 +587,19 @@ public class BCrypt { } if (salt.charAt(0) != '$' || salt.charAt(1) != '2') - throw new IllegalArgumentException ("Invalid salt version"); + throw new IllegalArgumentException("Invalid salt version"); if (salt.charAt(2) == '$') off = 3; else { minor = salt.charAt(2); - if ((minor != 'a' && minor != 'x' && minor != 'y' && minor != 'b') - || salt.charAt(3) != '$') - throw new IllegalArgumentException ("Invalid salt revision"); + if ((minor != 'a' && minor != 'x' && minor != 'y' && minor != 'b') || salt.charAt(3) != '$') + throw new IllegalArgumentException("Invalid salt revision"); off = 4; } // Extract number of rounds if (salt.charAt(off + 2) > '$') - throw new IllegalArgumentException ("Missing salt rounds"); + throw new IllegalArgumentException("Missing salt rounds"); if (off == 4 && saltLength < 29) { throw new IllegalArgumentException("Invalid salt"); @@ -807,26 +630,23 @@ public class BCrypt { /** * Generate a salt for use with the BCrypt.hashpw() method - * @param prefix the prefix value (default $2a) - * @param log_rounds the log2 of the number of rounds of - * hashing to apply - the work factor therefore increases as - * 2**log_rounds. - * @param random an instance of SecureRandom to use - * @return an encoded salt value + * @param prefix the prefix value (default $2a) + * @param log_rounds the log2 of the number of rounds of hashing to apply - the work + * factor therefore increases as 2**log_rounds. + * @param random an instance of SecureRandom to use + * @return an encoded salt value * @exception IllegalArgumentException if prefix or log_rounds is invalid */ - public static String gensalt(String prefix, int log_rounds, SecureRandom random) - throws IllegalArgumentException { + public static String gensalt(String prefix, int log_rounds, SecureRandom random) throws IllegalArgumentException { StringBuilder rs = new StringBuilder(); byte rnd[] = new byte[BCRYPT_SALT_LEN]; - if (!prefix.startsWith("$2") || - (prefix.charAt(2) != 'a' && prefix.charAt(2) != 'y' && - prefix.charAt(2) != 'b')) { - throw new IllegalArgumentException ("Invalid prefix"); + if (!prefix.startsWith("$2") + || (prefix.charAt(2) != 'a' && prefix.charAt(2) != 'y' && prefix.charAt(2) != 'b')) { + throw new IllegalArgumentException("Invalid prefix"); } if (log_rounds < 4 || log_rounds > 31) { - throw new IllegalArgumentException ("Invalid log_rounds"); + throw new IllegalArgumentException("Invalid log_rounds"); } random.nextBytes(rnd); @@ -844,42 +664,36 @@ public class BCrypt { /** * Generate a salt for use with the BCrypt.hashpw() method - * @param prefix the prefix value (default $2a) - * @param log_rounds the log2 of the number of rounds of - * hashing to apply - the work factor therefore increases as - * 2**log_rounds. - * @return an encoded salt value + * @param prefix the prefix value (default $2a) + * @param log_rounds the log2 of the number of rounds of hashing to apply - the work + * factor therefore increases as 2**log_rounds. + * @return an encoded salt value * @exception IllegalArgumentException if prefix or log_rounds is invalid */ - public static String gensalt(String prefix, int log_rounds) - throws IllegalArgumentException { + public static String gensalt(String prefix, int log_rounds) throws IllegalArgumentException { return gensalt(prefix, log_rounds, new SecureRandom()); } /** * Generate a salt for use with the BCrypt.hashpw() method - * @param log_rounds the log2 of the number of rounds of - * hashing to apply - the work factor therefore increases as - * 2**log_rounds. - * @param random an instance of SecureRandom to use - * @return an encoded salt value + * @param log_rounds the log2 of the number of rounds of hashing to apply - the work + * factor therefore increases as 2**log_rounds. + * @param random an instance of SecureRandom to use + * @return an encoded salt value * @exception IllegalArgumentException if log_rounds is invalid */ - public static String gensalt(int log_rounds, SecureRandom random) - throws IllegalArgumentException { + public static String gensalt(int log_rounds, SecureRandom random) throws IllegalArgumentException { return gensalt("$2a", log_rounds, random); } /** * Generate a salt for use with the BCrypt.hashpw() method - * @param log_rounds the log2 of the number of rounds of - * hashing to apply - the work factor therefore increases as - * 2**log_rounds. - * @return an encoded salt value + * @param log_rounds the log2 of the number of rounds of hashing to apply - the work + * factor therefore increases as 2**log_rounds. + * @return an encoded salt value * @exception IllegalArgumentException if log_rounds is invalid */ - public static String gensalt(int log_rounds) - throws IllegalArgumentException { + public static String gensalt(int log_rounds) throws IllegalArgumentException { return gensalt(log_rounds, new SecureRandom()); } @@ -888,32 +702,29 @@ public class BCrypt { } /** - * Generate a salt for use with the BCrypt.hashpw() method, - * selecting a reasonable default for the number of hashing - * rounds to apply - * @return an encoded salt value + * Generate a salt for use with the BCrypt.hashpw() method, selecting a reasonable + * default for the number of hashing rounds to apply + * @return an encoded salt value */ public static String gensalt() { return gensalt(GENSALT_DEFAULT_LOG2_ROUNDS); } /** - * Check that a plaintext password matches a previously hashed - * one - * @param plaintext the plaintext password to verify - * @param hashed the previously-hashed password - * @return true if the passwords match, false otherwise + * Check that a plaintext password matches a previously hashed one + * @param plaintext the plaintext password to verify + * @param hashed the previously-hashed password + * @return true if the passwords match, false otherwise */ public static boolean checkpw(String plaintext, String hashed) { return equalsNoEarlyReturn(hashed, hashpw(plaintext, hashed)); } /** - * Check that a password (as a byte array) matches a previously hashed - * one - * @param passwordb the password to verify, as a byte array - * @param hashed the previously-hashed password - * @return true if the passwords match, false otherwise + * Check that a password (as a byte array) matches a previously hashed one + * @param passwordb the password to verify, as a byte array + * @param hashed the previously-hashed password + * @return true if the passwords match, false otherwise * @since 5.3 */ public static boolean checkpw(byte[] passwordb, String hashed) { @@ -923,4 +734,5 @@ public class BCrypt { static boolean equalsNoEarlyReturn(String a, String b) { return MessageDigest.isEqual(a.getBytes(StandardCharsets.UTF_8), b.getBytes(StandardCharsets.UTF_8)); } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoder.java b/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoder.java index dd787a9ea4..3304a7d48b 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoder.java +++ b/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoder.java @@ -25,23 +25,24 @@ import java.util.regex.Pattern; /** * Implementation of PasswordEncoder that uses the BCrypt strong hashing function. Clients - * can optionally supply a "version" ($2a, $2b, $2y) and a "strength" (a.k.a. log rounds in BCrypt) - * and a SecureRandom instance. The larger the strength parameter the more work will have to be done - * (exponentially) to hash the passwords. The default value is 10. + * can optionally supply a "version" ($2a, $2b, $2y) and a "strength" (a.k.a. log rounds + * in BCrypt) and a SecureRandom instance. The larger the strength parameter the more work + * will have to be done (exponentially) to hash the passwords. The default value is 10. * * @author Dave Syer */ public class BCryptPasswordEncoder implements PasswordEncoder { - private Pattern BCRYPT_PATTERN = Pattern - .compile("\\A\\$2(a|y|b)?\\$(\\d\\d)\\$[./0-9A-Za-z]{53}"); + + private Pattern BCRYPT_PATTERN = Pattern.compile("\\A\\$2(a|y|b)?\\$(\\d\\d)\\$[./0-9A-Za-z]{53}"); + private final Log logger = LogFactory.getLog(getClass()); private final int strength; + private final BCryptVersion version; private final SecureRandom random; - public BCryptPasswordEncoder() { this(-1); } @@ -62,7 +63,7 @@ public class BCryptPasswordEncoder implements PasswordEncoder { /** * @param version the version of bcrypt, can be 2a,2b,2y - * @param random the secure random instance to use + * @param random the secure random instance to use */ public BCryptPasswordEncoder(BCryptVersion version, SecureRandom random) { this(version, -1, random); @@ -70,14 +71,14 @@ public class BCryptPasswordEncoder implements PasswordEncoder { /** * @param strength the log rounds to use, between 4 and 31 - * @param random the secure random instance to use + * @param random the secure random instance to use */ public BCryptPasswordEncoder(int strength, SecureRandom random) { this(BCryptVersion.$2A, strength, random); } /** - * @param version the version of bcrypt, can be 2a,2b,2y + * @param version the version of bcrypt, can be 2a,2b,2y * @param strength the log rounds to use, between 4 and 31 */ public BCryptPasswordEncoder(BCryptVersion version, int strength) { @@ -85,9 +86,9 @@ public class BCryptPasswordEncoder implements PasswordEncoder { } /** - * @param version the version of bcrypt, can be 2a,2b,2y + * @param version the version of bcrypt, can be 2a,2b,2y * @param strength the log rounds to use, between 4 and 31 - * @param random the secure random instance to use + * @param random the secure random instance to use */ public BCryptPasswordEncoder(BCryptVersion version, int strength, SecureRandom random) { if (strength != -1 && (strength < BCrypt.MIN_LOG_ROUNDS || strength > BCrypt.MAX_LOG_ROUNDS)) { @@ -106,7 +107,8 @@ public class BCryptPasswordEncoder implements PasswordEncoder { String salt; if (random != null) { salt = BCrypt.gensalt(version.getVersion(), strength, random); - } else { + } + else { salt = BCrypt.gensalt(version.getVersion(), strength); } return BCrypt.hashpw(rawPassword.toString(), salt); @@ -153,9 +155,8 @@ public class BCryptPasswordEncoder implements PasswordEncoder { * @author Lin Feng */ public enum BCryptVersion { - $2A("$2a"), - $2Y("$2y"), - $2B("$2b"); + + $2A("$2a"), $2Y("$2y"), $2B("$2b"); private final String version; @@ -166,5 +167,7 @@ public class BCryptPasswordEncoder implements PasswordEncoder { public String getVersion() { return this.version; } + } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/codec/Base64.java b/crypto/src/main/java/org/springframework/security/crypto/codec/Base64.java index 8269e5f313..8256c510e8 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/codec/Base64.java +++ b/crypto/src/main/java/org/springframework/security/crypto/codec/Base64.java @@ -17,8 +17,9 @@ package org.springframework.security.crypto.codec; /** * Base64 encoder which is a reduced version of Robert Harder's public domain - * implementation (version 2.3.7). See http://iharder.sourceforge.net/current/java/base64/ for more information. + * implementation (version 2.3.7). See http://iharder.sourceforge.net/current/java/base64/ + * for more information. *

      * For internal use only. * @@ -43,12 +44,11 @@ public final class Base64 { /** * Encode using Base64-like encoding that is URL- and Filename-safe as described in - * Section 4 of RFC3548: https://tools.ietf.org/html/rfc3548. - * It is important to note that data encoded this way is - * not officially valid Base64, or at the very least should not be called - * Base64 without also specifying that is was encoded using the URL- and Filename-safe - * dialect. + * Section 4 of RFC3548: https://tools.ietf.org/html/rfc3548. It + * is important to note that data encoded this way is not officially valid + * Base64, or at the very least should not be called Base64 without also specifying + * that is was encoded using the URL- and Filename-safe dialect. */ public final static int URL_SAFE = 16; @@ -67,31 +67,30 @@ public final class Base64 { private final static byte NEW_LINE = (byte) '\n'; private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding + private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding /* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */ /** The 64 valid Base64 values. */ /* Host platform me be something funny like EBCDIC, so we hardcode these values. */ - private final static byte[] _STANDARD_ALPHABET = { (byte) 'A', (byte) 'B', - (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G', (byte) 'H', - (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', - (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', - (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', - (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', - (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', - (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', - (byte) 's', (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', - (byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', - (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9', - (byte) '+', (byte) '/' }; + private final static byte[] _STANDARD_ALPHABET = { (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', + (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', + (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V', (byte) 'W', + (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', + (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', + (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', + (byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', + (byte) '7', (byte) '8', (byte) '9', (byte) '+', (byte) '/' }; /** * Translates a Base64 value to either its 6-bit reconstruction value or a negative * number indicating some other meaning. **/ - private final static byte[] _STANDARD_DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, - -9, // Decimal 0 - 8 + private final static byte[] _STANDARD_DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal + // 0 + // - + // 8 -5, -5, // Whitespace: Tab and Linefeed -9, -9, // Decimal 11 - 12 -5, // Whitespace: Carriage Return @@ -127,30 +126,28 @@ public final class Base64 { /* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */ /** - * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548: https://tools.ietf.org/html/rfc3548. * Notice that the last two bytes become "hyphen" and "underscore" instead of "plus" * and "slash." */ - private final static byte[] _URL_SAFE_ALPHABET = { (byte) 'A', (byte) 'B', - (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G', (byte) 'H', - (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', - (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', - (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', - (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', - (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', - (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', - (byte) 's', (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', - (byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', - (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9', - (byte) '-', (byte) '_' }; + private final static byte[] _URL_SAFE_ALPHABET = { (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', + (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', + (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V', (byte) 'W', + (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', + (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', + (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', + (byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', + (byte) '7', (byte) '8', (byte) '9', (byte) '-', (byte) '_' }; /** * Used in decoding URL- and Filename-safe dialects of Base64. */ - private final static byte[] _URL_SAFE_DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, - -9, // Decimal 0 - 8 + private final static byte[] _URL_SAFE_DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal + // 0 + // - + // 8 -5, -5, // Whitespace: Tab and Linefeed -9, -9, // Decimal 11 - 12 -5, // Whitespace: Carriage Return @@ -189,24 +186,22 @@ public final class Base64 { /* ******** O R D E R E D B A S E 6 4 A L P H A B E T ******** */ - private final static byte[] _ORDERED_ALPHABET = { (byte) '-', (byte) '0', (byte) '1', - (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7', - (byte) '8', (byte) '9', (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', - (byte) 'E', (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', - (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', - (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V', - (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) '_', (byte) 'a', - (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', (byte) 'g', - (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', - (byte) 'n', (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', - (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', - (byte) 'z' }; + private final static byte[] _ORDERED_ALPHABET = { (byte) '-', (byte) '0', (byte) '1', (byte) '2', (byte) '3', + (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) 'A', (byte) 'B', (byte) 'C', + (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', + (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', + (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) '_', (byte) 'a', (byte) 'b', (byte) 'c', + (byte) 'd', (byte) 'e', (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', + (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', + (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z' }; /** * Used in decoding the "ordered" dialect of Base64. */ - private final static byte[] _ORDERED_DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, - -9, // Decimal 0 - 8 + private final static byte[] _ORDERED_DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal + // 0 + // - + // 8 -5, -5, // Whitespace: Tab and Linefeed -9, -9, // Decimal 11 - 12 -5, // Whitespace: Carriage Return @@ -312,7 +307,6 @@ public final class Base64 { *

      * This is the lowest level of the encoding methods with all possible parameters. *

      - * * @param source the array to convert * @param srcOffset the index where conversion begins * @param numSigBytes the number of significant bytes in your array @@ -321,8 +315,8 @@ public final class Base64 { * @return the destination array * @since 1.3 */ - private static byte[] encode3to4(byte[] source, int srcOffset, int numSigBytes, - byte[] destination, int destOffset, int options) { + private static byte[] encode3to4(byte[] source, int srcOffset, int numSigBytes, byte[] destination, int destOffset, + int options) { byte[] ALPHABET = getAlphabet(options); @@ -369,7 +363,6 @@ public final class Base64 { } /** - * * @param source The data to convert * @param off Offset in array where conversion should begin * @param len Length of data to convert @@ -397,8 +390,7 @@ public final class Base64 { if (off + len > source.length) { throw new IllegalArgumentException(String.format( - "Cannot have offset of %d and length of %d with array of length %d", - off, len, source.length)); + "Cannot have offset of %d and length of %d with array of length %d", off, len, source.length)); } // end if: off < 0 boolean breakLines = (options & DO_BREAK_LINES) > 0; @@ -464,8 +456,6 @@ public final class Base64 { *

      * This is the lowest level of the decoding methods with all possible parameters. *

      - * - * * @param source the array to convert * @param srcOffset the index where conversion begins * @param destination the array to hold the conversion @@ -477,8 +467,8 @@ public final class Base64 { * not enough room in the array. * @since 1.3 */ - private static int decode4to3(final byte[] source, final int srcOffset, - final byte[] destination, final int destOffset, final int options) { + private static int decode4to3(final byte[] source, final int srcOffset, final byte[] destination, + final int destOffset, final int options) { // Lots of error checking and exception throwing if (source == null) { @@ -489,15 +479,13 @@ public final class Base64 { } // end if if (srcOffset < 0 || srcOffset + 3 >= source.length) { throw new IllegalArgumentException( - String.format( - "Source array with length %d cannot have offset of %d and still process four bytes.", + String.format("Source array with length %d cannot have offset of %d and still process four bytes.", source.length, srcOffset)); } // end if if (destOffset < 0 || destOffset + 2 >= destination.length) { - throw new IllegalArgumentException( - String.format( - "Destination array with length %d cannot have offset of %d and still store three bytes.", - destination.length, destOffset)); + throw new IllegalArgumentException(String.format( + "Destination array with length %d cannot have offset of %d and still store three bytes.", + destination.length, destOffset)); } // end if byte[] DECODABET = getDecodabet(options); @@ -538,8 +526,7 @@ public final class Base64 { // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 ); int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) - | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6) - | ((DECODABET[source[srcOffset + 3]] & 0xFF)); + | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6) | ((DECODABET[source[srcOffset + 3]] & 0xFF)); destination[destOffset] = (byte) (outBuff >> 16); destination[destOffset + 1] = (byte) (outBuff >> 8); @@ -555,7 +542,6 @@ public final class Base64 { * recommended method, although it is used internally as part of the decoding process. * Special case: if len = 0, an empty array is returned. Still, if you need more speed * and reduced memory footprint (and aren't gzipping), consider this method. - * * @param source The Base64 encoded data * @param off The offset of where to begin decoding * @param len The length of characters to decode @@ -563,8 +549,7 @@ public final class Base64 { * @return decoded data * @throws IllegalArgumentException If bogus characters exist in source data */ - private static byte[] decode(final byte[] source, final int off, final int len, - final int options) { + private static byte[] decode(final byte[] source, final int off, final int len, final int options) { // Lots of error checking and exception throwing if (source == null) { @@ -572,8 +557,7 @@ public final class Base64 { } // end if if (off < 0 || off + len > source.length) { throw new IllegalArgumentException( - String.format( - "Source array with length %d cannot have offset of %d and process %d bytes.", + String.format("Source array with length %d cannot have offset of %d and process %d bytes.", source.length, off, len)); } // end if @@ -582,8 +566,7 @@ public final class Base64 { } else if (len < 4) { throw new IllegalArgumentException( - "Base64-encoded string must have at least four characters, but length specified was " - + len); + "Base64-encoded string must have at least four characters, but length specified was " + len); } // end if byte[] DECODABET = getDecodabet(options); @@ -621,8 +604,7 @@ public final class Base64 { else { // There's a bad input character in the Base64 stream. throw new InvalidBase64CharacterException(String.format( - "Bad Base64 input character decimal %d in array position %d", - ((int) source[i]) & 0xFF, i)); + "Bad Base64 input character decimal %d in array position %d", ((int) source[i]) & 0xFF, i)); } } @@ -630,6 +612,7 @@ public final class Base64 { System.arraycopy(outBuff, 0, out, 0, outBuffPosn); return out; } + } class InvalidBase64CharacterException extends IllegalArgumentException { @@ -637,4 +620,5 @@ class InvalidBase64CharacterException extends IllegalArgumentException { InvalidBase64CharacterException(String message) { super(message); } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/codec/Hex.java b/crypto/src/main/java/org/springframework/security/crypto/codec/Hex.java index 7555abd5b7..c896a12034 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/codec/Hex.java +++ b/crypto/src/main/java/org/springframework/security/crypto/codec/Hex.java @@ -26,8 +26,8 @@ package org.springframework.security.crypto.codec; */ public final class Hex { - private static final char[] HEX = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f' }; + private static final char[] HEX = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', + 'f' }; public static char[] encode(byte[] bytes) { final int nBytes = bytes.length; @@ -48,8 +48,7 @@ public final class Hex { int nChars = s.length(); if (nChars % 2 != 0) { - throw new IllegalArgumentException( - "Hex-encoded string must have an even number of characters"); + throw new IllegalArgumentException("Hex-encoded string must have an even number of characters"); } byte[] result = new byte[nChars / 2]; @@ -60,7 +59,7 @@ public final class Hex { if (msb < 0 || lsb < 0) { throw new IllegalArgumentException( - "Detected a Non-hex character at " + (i + 1) + " or " + (i + 2) + " position"); + "Detected a Non-hex character at " + (i + 1) + " or " + (i + 2) + " position"); } result[i / 2] = (byte) ((msb << 4) | lsb); } diff --git a/crypto/src/main/java/org/springframework/security/crypto/codec/Utf8.java b/crypto/src/main/java/org/springframework/security/crypto/codec/Utf8.java index a2274fa75d..b82bcdce66 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/codec/Utf8.java +++ b/crypto/src/main/java/org/springframework/security/crypto/codec/Utf8.java @@ -29,6 +29,7 @@ import java.nio.charset.StandardCharsets; * @author Luke Taylor */ public final class Utf8 { + private static final Charset CHARSET = StandardCharsets.UTF_8; /** @@ -58,4 +59,5 @@ public final class Utf8 { throw new IllegalArgumentException("Decoding failed", e); } } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/codec/package-info.java b/crypto/src/main/java/org/springframework/security/crypto/codec/package-info.java index 0875553e36..07941157f2 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/codec/package-info.java +++ b/crypto/src/main/java/org/springframework/security/crypto/codec/package-info.java @@ -17,4 +17,3 @@ * Internal codec classes. Only intended for use within the framework. */ package org.springframework.security.crypto.codec; - diff --git a/crypto/src/main/java/org/springframework/security/crypto/encrypt/AesBytesEncryptor.java b/crypto/src/main/java/org/springframework/security/crypto/encrypt/AesBytesEncryptor.java index 95c7b4067f..b2491e4fe3 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/encrypt/AesBytesEncryptor.java +++ b/crypto/src/main/java/org/springframework/security/crypto/encrypt/AesBytesEncryptor.java @@ -59,10 +59,10 @@ public final class AesBytesEncryptor implements BytesEncryptor { public enum CipherAlgorithm { - CBC(AES_CBC_ALGORITHM, NULL_IV_GENERATOR), GCM(AES_GCM_ALGORITHM, KeyGenerators - .secureRandom(16)); + CBC(AES_CBC_ALGORITHM, NULL_IV_GENERATOR), GCM(AES_GCM_ALGORITHM, KeyGenerators.secureRandom(16)); private BytesKeyGenerator ivGenerator; + private String name; CipherAlgorithm(String name, BytesKeyGenerator ivGenerator) { @@ -86,29 +86,28 @@ public final class AesBytesEncryptor implements BytesEncryptor { public BytesKeyGenerator defaultIvGenerator() { return this.ivGenerator; } + } public AesBytesEncryptor(String password, CharSequence salt) { this(password, salt, null); } - public AesBytesEncryptor(String password, CharSequence salt, - BytesKeyGenerator ivGenerator) { + public AesBytesEncryptor(String password, CharSequence salt, BytesKeyGenerator ivGenerator) { this(password, salt, ivGenerator, CipherAlgorithm.CBC); } - public AesBytesEncryptor(String password, CharSequence salt, - BytesKeyGenerator ivGenerator, CipherAlgorithm alg) { - this(newSecretKey("PBKDF2WithHmacSHA1", new PBEKeySpec(password.toCharArray(), Hex.decode(salt), - 1024, 256)), ivGenerator, alg); + public AesBytesEncryptor(String password, CharSequence salt, BytesKeyGenerator ivGenerator, CipherAlgorithm alg) { + this(newSecretKey("PBKDF2WithHmacSHA1", new PBEKeySpec(password.toCharArray(), Hex.decode(salt), 1024, 256)), + ivGenerator, alg); } /** * Constructs an encryptor that uses AES encryption. - * * @param secretKey the secret (symmetric) key - * @param ivGenerator the generator used to generate the initialization vector. If null, - * then a default algorithm will be used based on the provided {@link CipherAlgorithm} + * @param ivGenerator the generator used to generate the initialization vector. If + * null, then a default algorithm will be used based on the provided + * {@link CipherAlgorithm} * @param alg the {@link CipherAlgorithm} to be used */ public AesBytesEncryptor(SecretKey secretKey, BytesKeyGenerator ivGenerator, CipherAlgorithm alg) { @@ -122,31 +121,26 @@ public final class AesBytesEncryptor implements BytesEncryptor { public byte[] encrypt(byte[] bytes) { synchronized (this.encryptor) { byte[] iv = this.ivGenerator.generateKey(); - initCipher(this.encryptor, Cipher.ENCRYPT_MODE, this.secretKey, - this.alg.getParameterSpec(iv)); + initCipher(this.encryptor, Cipher.ENCRYPT_MODE, this.secretKey, this.alg.getParameterSpec(iv)); byte[] encrypted = doFinal(this.encryptor, bytes); - return this.ivGenerator != NULL_IV_GENERATOR ? concatenate(iv, encrypted) - : encrypted; + return this.ivGenerator != NULL_IV_GENERATOR ? concatenate(iv, encrypted) : encrypted; } } public byte[] decrypt(byte[] encryptedBytes) { synchronized (this.decryptor) { byte[] iv = iv(encryptedBytes); - initCipher(this.decryptor, Cipher.DECRYPT_MODE, this.secretKey, - this.alg.getParameterSpec(iv)); - return doFinal( - this.decryptor, - this.ivGenerator != NULL_IV_GENERATOR ? encrypted(encryptedBytes, - iv.length) : encryptedBytes); + initCipher(this.decryptor, Cipher.DECRYPT_MODE, this.secretKey, this.alg.getParameterSpec(iv)); + return doFinal(this.decryptor, + this.ivGenerator != NULL_IV_GENERATOR ? encrypted(encryptedBytes, iv.length) : encryptedBytes); } } // internal helpers private byte[] iv(byte[] encrypted) { - return this.ivGenerator != NULL_IV_GENERATOR ? subArray(encrypted, 0, - this.ivGenerator.getKeyLength()) : NULL_IV_GENERATOR.generateKey(); + return this.ivGenerator != NULL_IV_GENERATOR ? subArray(encrypted, 0, this.ivGenerator.getKeyLength()) + : NULL_IV_GENERATOR.generateKey(); } private byte[] encrypted(byte[] encryptedBytes, int ivLength) { @@ -166,4 +160,5 @@ public final class AesBytesEncryptor implements BytesEncryptor { } }; + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptor.java b/crypto/src/main/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptor.java index 6797854479..53e301eb94 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptor.java +++ b/crypto/src/main/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptor.java @@ -31,22 +31,22 @@ import org.springframework.security.crypto.keygen.KeyGenerators; abstract class BouncyCastleAesBytesEncryptor implements BytesEncryptor { final KeyParameter secretKey; + final BytesKeyGenerator ivGenerator; BouncyCastleAesBytesEncryptor(String password, CharSequence salt) { this(password, salt, KeyGenerators.secureRandom(16)); } - BouncyCastleAesBytesEncryptor(String password, CharSequence salt, - BytesKeyGenerator ivGenerator) { + BouncyCastleAesBytesEncryptor(String password, CharSequence salt, BytesKeyGenerator ivGenerator) { if (ivGenerator.getKeyLength() != 16) { throw new IllegalArgumentException("ivGenerator key length != block size 16"); } this.ivGenerator = ivGenerator; PBEParametersGenerator keyGenerator = new PKCS5S2ParametersGenerator(); - byte[] pkcs12PasswordBytes = PBEParametersGenerator - .PKCS5PasswordToUTF8Bytes(password.toCharArray()); + byte[] pkcs12PasswordBytes = PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(password.toCharArray()); keyGenerator.init(pkcs12PasswordBytes, Hex.decode(salt), 1024); this.secretKey = (KeyParameter) keyGenerator.generateDerivedParameters(256); } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/encrypt/BouncyCastleAesCbcBytesEncryptor.java b/crypto/src/main/java/org/springframework/security/crypto/encrypt/BouncyCastleAesCbcBytesEncryptor.java index d0e4c874c9..1394856c36 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/encrypt/BouncyCastleAesCbcBytesEncryptor.java +++ b/crypto/src/main/java/org/springframework/security/crypto/encrypt/BouncyCastleAesCbcBytesEncryptor.java @@ -28,9 +28,9 @@ import org.springframework.security.crypto.encrypt.AesBytesEncryptor.CipherAlgor import org.springframework.security.crypto.keygen.BytesKeyGenerator; /** - * An Encryptor equivalent to {@link AesBytesEncryptor} using - * {@link CipherAlgorithm#CBC} that uses Bouncy Castle instead of JCE. The - * algorithm is equivalent to "AES/CBC/PKCS5Padding". + * An Encryptor equivalent to {@link AesBytesEncryptor} using {@link CipherAlgorithm#CBC} + * that uses Bouncy Castle instead of JCE. The algorithm is equivalent to + * "AES/CBC/PKCS5Padding". * * @author William Tran * @@ -41,8 +41,7 @@ public class BouncyCastleAesCbcBytesEncryptor extends BouncyCastleAesBytesEncryp super(password, salt); } - public BouncyCastleAesCbcBytesEncryptor(String password, CharSequence salt, - BytesKeyGenerator ivGenerator) { + public BouncyCastleAesCbcBytesEncryptor(String password, CharSequence salt, BytesKeyGenerator ivGenerator) { super(password, salt, ivGenerator); } @@ -61,8 +60,7 @@ public class BouncyCastleAesCbcBytesEncryptor extends BouncyCastleAesBytesEncryp @Override public byte[] decrypt(byte[] encryptedBytes) { byte[] iv = subArray(encryptedBytes, 0, this.ivGenerator.getKeyLength()); - encryptedBytes = subArray(encryptedBytes, this.ivGenerator.getKeyLength(), - encryptedBytes.length); + encryptedBytes = subArray(encryptedBytes, this.ivGenerator.getKeyLength(), encryptedBytes.length); @SuppressWarnings("deprecation") PaddedBufferedBlockCipher blockCipher = new PaddedBufferedBlockCipher( @@ -87,4 +85,5 @@ public class BouncyCastleAesCbcBytesEncryptor extends BouncyCastleAesBytesEncryp System.arraycopy(buf, 0, out, 0, bytesWritten); return out; } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/encrypt/BouncyCastleAesGcmBytesEncryptor.java b/crypto/src/main/java/org/springframework/security/crypto/encrypt/BouncyCastleAesGcmBytesEncryptor.java index 5c81414117..71abc75e1d 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/encrypt/BouncyCastleAesGcmBytesEncryptor.java +++ b/crypto/src/main/java/org/springframework/security/crypto/encrypt/BouncyCastleAesGcmBytesEncryptor.java @@ -26,9 +26,9 @@ import org.springframework.security.crypto.encrypt.AesBytesEncryptor.CipherAlgor import org.springframework.security.crypto.keygen.BytesKeyGenerator; /** - * An Encryptor equivalent to {@link AesBytesEncryptor} using - * {@link CipherAlgorithm#GCM} that uses Bouncy Castle instead of JCE. The - * algorithm is equivalent to "AES/GCM/NoPadding". + * An Encryptor equivalent to {@link AesBytesEncryptor} using {@link CipherAlgorithm#GCM} + * that uses Bouncy Castle instead of JCE. The algorithm is equivalent to + * "AES/GCM/NoPadding". * * @author William Tran * @@ -39,8 +39,7 @@ public class BouncyCastleAesGcmBytesEncryptor extends BouncyCastleAesBytesEncryp super(password, salt); } - public BouncyCastleAesGcmBytesEncryptor(String password, CharSequence salt, - BytesKeyGenerator ivGenerator) { + public BouncyCastleAesGcmBytesEncryptor(String password, CharSequence salt, BytesKeyGenerator ivGenerator) { super(password, salt, ivGenerator); } @@ -59,8 +58,7 @@ public class BouncyCastleAesGcmBytesEncryptor extends BouncyCastleAesBytesEncryp @Override public byte[] decrypt(byte[] encryptedBytes) { byte[] iv = subArray(encryptedBytes, 0, this.ivGenerator.getKeyLength()); - encryptedBytes = subArray(encryptedBytes, this.ivGenerator.getKeyLength(), - encryptedBytes.length); + encryptedBytes = subArray(encryptedBytes, this.ivGenerator.getKeyLength(), encryptedBytes.length); @SuppressWarnings("deprecation") GCMBlockCipher blockCipher = new GCMBlockCipher(new org.bouncycastle.crypto.engines.AESFastEngine()); diff --git a/crypto/src/main/java/org/springframework/security/crypto/encrypt/BytesEncryptor.java b/crypto/src/main/java/org/springframework/security/crypto/encrypt/BytesEncryptor.java index 4285224627..7f8fbc0981 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/encrypt/BytesEncryptor.java +++ b/crypto/src/main/java/org/springframework/security/crypto/encrypt/BytesEncryptor.java @@ -17,6 +17,7 @@ package org.springframework.security.crypto.encrypt; /** * Service interface for symmetric data encryption. + * * @author Keith Donald */ public interface BytesEncryptor { diff --git a/crypto/src/main/java/org/springframework/security/crypto/encrypt/CipherUtils.java b/crypto/src/main/java/org/springframework/security/crypto/encrypt/CipherUtils.java index d77fd9f4fb..58a268abe7 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/encrypt/CipherUtils.java +++ b/crypto/src/main/java/org/springframework/security/crypto/encrypt/CipherUtils.java @@ -33,6 +33,7 @@ import javax.crypto.spec.PBEParameterSpec; /** * Static helper for working with the Cipher API. + * * @author Keith Donald */ class CipherUtils { @@ -78,8 +79,7 @@ class CipherUtils { /** * Initializes the Cipher for use. */ - public static T getParameterSpec(Cipher cipher, - Class parameterSpecClass) { + public static T getParameterSpec(Cipher cipher, Class parameterSpecClass) { try { return cipher.getParameters().getParameterSpec(parameterSpecClass); } @@ -98,16 +98,14 @@ class CipherUtils { /** * Initializes the Cipher for use. */ - public static void initCipher(Cipher cipher, int mode, SecretKey secretKey, - byte[] salt, int iterationCount) { + public static void initCipher(Cipher cipher, int mode, SecretKey secretKey, byte[] salt, int iterationCount) { initCipher(cipher, mode, secretKey, new PBEParameterSpec(salt, iterationCount)); } /** * Initializes the Cipher for use. */ - public static void initCipher(Cipher cipher, int mode, SecretKey secretKey, - AlgorithmParameterSpec parameterSpec) { + public static void initCipher(Cipher cipher, int mode, SecretKey secretKey, AlgorithmParameterSpec parameterSpec) { try { if (parameterSpec != null) { cipher.init(mode, secretKey, parameterSpec); @@ -117,12 +115,10 @@ class CipherUtils { } } catch (InvalidKeyException e) { - throw new IllegalArgumentException( - "Unable to initialize due to invalid secret key", e); + throw new IllegalArgumentException("Unable to initialize due to invalid secret key", e); } catch (InvalidAlgorithmParameterException e) { - throw new IllegalStateException( - "Unable to initialize due to invalid decryption parameter spec", e); + throw new IllegalStateException("Unable to initialize due to invalid decryption parameter spec", e); } } @@ -135,12 +131,10 @@ class CipherUtils { return cipher.doFinal(input); } catch (IllegalBlockSizeException e) { - throw new IllegalStateException( - "Unable to invoke Cipher due to illegal block size", e); + throw new IllegalStateException("Unable to invoke Cipher due to illegal block size", e); } catch (BadPaddingException e) { - throw new IllegalStateException("Unable to invoke Cipher due to bad padding", - e); + throw new IllegalStateException("Unable to invoke Cipher due to bad padding", e); } } diff --git a/crypto/src/main/java/org/springframework/security/crypto/encrypt/Encryptors.java b/crypto/src/main/java/org/springframework/security/crypto/encrypt/Encryptors.java index 7ebfb5a356..7ceef06107 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/encrypt/Encryptors.java +++ b/crypto/src/main/java/org/springframework/security/crypto/encrypt/Encryptors.java @@ -34,15 +34,13 @@ public class Encryptors { * hex-encoded; it should be random and at least 8 bytes in length. Also applies a * random 16-byte initialization vector to ensure each encrypted message will be * unique. Requires Java 6. - * * @param password the password used to generate the encryptor's secret key; should * not be shared * @param salt a hex-encoded, random, site-global salt value to use to generate the * key */ public static BytesEncryptor stronger(CharSequence password, CharSequence salt) { - return new AesBytesEncryptor(password.toString(), salt, - KeyGenerators.secureRandom(16), CipherAlgorithm.GCM); + return new AesBytesEncryptor(password.toString(), salt, KeyGenerators.secureRandom(16), CipherAlgorithm.GCM); } /** @@ -51,13 +49,11 @@ public class Encryptors { * Function #2). Salts the password to prevent dictionary attacks against the key. The * provided salt is expected to be hex-encoded; it should be random and at least 8 * bytes in length. Also applies a random 16-byte initialization vector to ensure each - * encrypted message will be unique. Requires Java 6. - * NOTE: This mode is not + * encrypted message will be unique. Requires Java 6. NOTE: This mode is not * authenticated - * and does not provide any guarantees about the authenticity of the data. - * For a more secure alternative, users should prefer + * and does not provide any guarantees about the authenticity of the data. For a more + * secure alternative, users should prefer * {@link #stronger(CharSequence, CharSequence)}. - * * @param password the password used to generate the encryptor's secret key; should * not be shared * @param salt a hex-encoded, random, site-global salt value to use to generate the @@ -67,14 +63,12 @@ public class Encryptors { * GCM (instead of CBC) */ public static BytesEncryptor standard(CharSequence password, CharSequence salt) { - return new AesBytesEncryptor(password.toString(), salt, - KeyGenerators.secureRandom(16)); + return new AesBytesEncryptor(password.toString(), salt, KeyGenerators.secureRandom(16)); } /** * Creates a text encryptor that uses "stronger" password-based encryption. Encrypted * text is hex-encoded. - * * @param password the password used to generate the encryptor's secret key; should * not be shared * @see Encryptors#stronger(CharSequence, CharSequence) @@ -86,7 +80,6 @@ public class Encryptors { /** * Creates a text encryptor that uses "standard" password-based encryption. Encrypted * text is hex-encoded. - * * @param password the password used to generate the encryptor's secret key; should * not be shared * @see Encryptors#standard(CharSequence, CharSequence) @@ -100,7 +93,6 @@ public class Encryptors { * encryption. Uses a 16-byte all-zero initialization vector so encrypting the same * data results in the same encryption result. This is done to allow encrypted data to * be queried against. Encrypted text is hex-encoded. - * * @param password the password used to generate the encryptor's secret key; should * not be shared * @param salt a hex-encoded, random, site-global salt value to use to generate the @@ -110,8 +102,7 @@ public class Encryptors { */ @Deprecated public static TextEncryptor queryableText(CharSequence password, CharSequence salt) { - return new HexEncodingTextEncryptor(new AesBytesEncryptor(password.toString(), - salt)); + return new HexEncodingTextEncryptor(new AesBytesEncryptor(password.toString(), salt)); } /** diff --git a/crypto/src/main/java/org/springframework/security/crypto/encrypt/HexEncodingTextEncryptor.java b/crypto/src/main/java/org/springframework/security/crypto/encrypt/HexEncodingTextEncryptor.java index a4ed4c8699..8407dd8704 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/encrypt/HexEncodingTextEncryptor.java +++ b/crypto/src/main/java/org/springframework/security/crypto/encrypt/HexEncodingTextEncryptor.java @@ -22,6 +22,7 @@ import org.springframework.security.crypto.codec.Utf8; * Delegates to an {@link BytesEncryptor} to encrypt text strings. Raw text strings are * UTF-8 encoded before being passed to the encryptor. Encrypted strings are returned * hex-encoded. + * * @author Keith Donald */ final class HexEncodingTextEncryptor implements TextEncryptor { diff --git a/crypto/src/main/java/org/springframework/security/crypto/factory/PasswordEncoderFactories.java b/crypto/src/main/java/org/springframework/security/crypto/factory/PasswordEncoderFactories.java index c0a54ba2cf..46678d65cb 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/factory/PasswordEncoderFactories.java +++ b/crypto/src/main/java/org/springframework/security/crypto/factory/PasswordEncoderFactories.java @@ -28,6 +28,7 @@ import java.util.Map; /** * Used for creating {@link PasswordEncoder} instances + * * @author Rob Winch * @since 5.0 */ @@ -41,18 +42,21 @@ public class PasswordEncoderFactories { * *
        *
      • bcrypt - {@link BCryptPasswordEncoder} (Also used for encoding)
      • - *
      • ldap - {@link org.springframework.security.crypto.password.LdapShaPasswordEncoder}
      • - *
      • MD4 - {@link org.springframework.security.crypto.password.Md4PasswordEncoder}
      • + *
      • ldap - + * {@link org.springframework.security.crypto.password.LdapShaPasswordEncoder}
      • + *
      • MD4 - + * {@link org.springframework.security.crypto.password.Md4PasswordEncoder}
      • *
      • MD5 - {@code new MessageDigestPasswordEncoder("MD5")}
      • - *
      • noop - {@link org.springframework.security.crypto.password.NoOpPasswordEncoder}
      • + *
      • noop - + * {@link org.springframework.security.crypto.password.NoOpPasswordEncoder}
      • *
      • pbkdf2 - {@link Pbkdf2PasswordEncoder}
      • *
      • scrypt - {@link SCryptPasswordEncoder}
      • *
      • SHA-1 - {@code new MessageDigestPasswordEncoder("SHA-1")}
      • *
      • SHA-256 - {@code new MessageDigestPasswordEncoder("SHA-256")}
      • - *
      • sha256 - {@link org.springframework.security.crypto.password.StandardPasswordEncoder}
      • + *
      • sha256 - + * {@link org.springframework.security.crypto.password.StandardPasswordEncoder}
      • *
      • argon2 - {@link Argon2PasswordEncoder}
      • *
      - * * @return the {@link PasswordEncoder} to use */ @SuppressWarnings("deprecation") @@ -67,12 +71,15 @@ public class PasswordEncoderFactories { encoders.put("pbkdf2", new Pbkdf2PasswordEncoder()); encoders.put("scrypt", new SCryptPasswordEncoder()); encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1")); - encoders.put("SHA-256", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256")); + encoders.put("SHA-256", + new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256")); encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder()); encoders.put("argon2", new Argon2PasswordEncoder()); return new DelegatingPasswordEncoder(encodingId, encoders); } - private PasswordEncoderFactories() {} + private PasswordEncoderFactories() { + } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/keygen/Base64StringKeyGenerator.java b/crypto/src/main/java/org/springframework/security/crypto/keygen/Base64StringKeyGenerator.java index bba2113ed9..1fc050c313 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/keygen/Base64StringKeyGenerator.java +++ b/crypto/src/main/java/org/springframework/security/crypto/keygen/Base64StringKeyGenerator.java @@ -26,8 +26,11 @@ import java.util.Base64; * @since 5.0 */ public class Base64StringKeyGenerator implements StringKeyGenerator { + private static final int DEFAULT_KEY_LENGTH = 32; + private final BytesKeyGenerator keyGenerator; + private final Base64.Encoder encoder; /** @@ -76,4 +79,5 @@ public class Base64StringKeyGenerator implements StringKeyGenerator { byte[] base64EncodedKey = this.encoder.encode(key); return new String(base64EncodedKey); } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/keygen/BytesKeyGenerator.java b/crypto/src/main/java/org/springframework/security/crypto/keygen/BytesKeyGenerator.java index 6dbff29f58..56a8e4f308 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/keygen/BytesKeyGenerator.java +++ b/crypto/src/main/java/org/springframework/security/crypto/keygen/BytesKeyGenerator.java @@ -17,6 +17,7 @@ package org.springframework.security.crypto.keygen; /** * A generator for unique byte array-based keys. + * * @author Keith Donald */ public interface BytesKeyGenerator { diff --git a/crypto/src/main/java/org/springframework/security/crypto/keygen/HexEncodingStringKeyGenerator.java b/crypto/src/main/java/org/springframework/security/crypto/keygen/HexEncodingStringKeyGenerator.java index 005a8e6e63..0ce886425c 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/keygen/HexEncodingStringKeyGenerator.java +++ b/crypto/src/main/java/org/springframework/security/crypto/keygen/HexEncodingStringKeyGenerator.java @@ -20,6 +20,7 @@ import org.springframework.security.crypto.codec.Hex; /** * A StringKeyGenerator that generates hex-encoded String keys. Delegates to a * {@link BytesKeyGenerator} for the actual key generation. + * * @author Keith Donald */ final class HexEncodingStringKeyGenerator implements StringKeyGenerator { diff --git a/crypto/src/main/java/org/springframework/security/crypto/keygen/KeyGenerators.java b/crypto/src/main/java/org/springframework/security/crypto/keygen/KeyGenerators.java index b5c5989704..4a70ccef19 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/keygen/KeyGenerators.java +++ b/crypto/src/main/java/org/springframework/security/crypto/keygen/KeyGenerators.java @@ -20,6 +20,7 @@ import java.security.SecureRandom; /** * Factory for commonly used key generators. Public API for constructing a * {@link BytesKeyGenerator} or {@link StringKeyGenerator}. + * * @author Keith Donald */ public class KeyGenerators { @@ -62,4 +63,5 @@ public class KeyGenerators { private KeyGenerators() { } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/keygen/StringKeyGenerator.java b/crypto/src/main/java/org/springframework/security/crypto/keygen/StringKeyGenerator.java index 53e3422f79..d23a092fc0 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/keygen/StringKeyGenerator.java +++ b/crypto/src/main/java/org/springframework/security/crypto/keygen/StringKeyGenerator.java @@ -17,6 +17,7 @@ package org.springframework.security.crypto.keygen; /** * A generator for unique string keys. + * * @author Keith Donald */ public interface StringKeyGenerator { diff --git a/crypto/src/main/java/org/springframework/security/crypto/password/AbstractPasswordEncoder.java b/crypto/src/main/java/org/springframework/security/crypto/password/AbstractPasswordEncoder.java index f70e289adc..7593e1942d 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/password/AbstractPasswordEncoder.java +++ b/crypto/src/main/java/org/springframework/security/crypto/password/AbstractPasswordEncoder.java @@ -63,4 +63,5 @@ public abstract class AbstractPasswordEncoder implements PasswordEncoder { protected static boolean matches(byte[] expected, byte[] actual) { return MessageDigest.isEqual(expected, actual); } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java b/crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java index 4bc4e68083..fc04a346ca 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java +++ b/crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java @@ -50,8 +50,8 @@ import java.util.Map; * {id}encodedPassword * * - * Such that "id" is an identifier used to look up which {@link PasswordEncoder} should - * be used and "encodedPassword" is the original encoded password for the selected + * Such that "id" is an identifier used to look up which {@link PasswordEncoder} should be + * used and "encodedPassword" is the original encoded password for the selected * {@link PasswordEncoder}. The "id" must be at the beginning of the password, start with * "{" and end with "}". If the "id" cannot be found, the "id" will be null. * @@ -70,8 +70,8 @@ import java.util.Map; * *
        *
      1. The first password would have a {@code PasswordEncoder} id of "bcrypt" and - * encodedPassword of "$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG". - * When matching it would delegate to + * encodedPassword of "$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG". When + * matching it would delegate to * {@link org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder}
      2. *
      3. The second password would have a {@code PasswordEncoder} id of "noop" and * encodedPassword of "password". When matching it would delegate to @@ -115,17 +115,22 @@ import java.util.Map; * {@link #setDefaultPasswordEncoderForMatches(PasswordEncoder)}. * * @see org.springframework.security.crypto.factory.PasswordEncoderFactories - * * @author Rob Winch * @author Michael Simons * @since 5.0 */ public class DelegatingPasswordEncoder implements PasswordEncoder { + private static final String PREFIX = "{"; + private static final String SUFFIX = "}"; + private final String idForEncode; + private final PasswordEncoder passwordEncoderForEncode; + private final Map idToPasswordEncoder; + private PasswordEncoder defaultPasswordEncoderForMatches = new UnmappedIdPasswordEncoder(); /** @@ -133,15 +138,16 @@ public class DelegatingPasswordEncoder implements PasswordEncoder { * @param idForEncode the id used to lookup which {@link PasswordEncoder} should be * used for {@link #encode(CharSequence)} * @param idToPasswordEncoder a Map of id to {@link PasswordEncoder} used to determine - * which {@link PasswordEncoder} should be used for {@link #matches(CharSequence, String)} + * which {@link PasswordEncoder} should be used for + * {@link #matches(CharSequence, String)} */ - public DelegatingPasswordEncoder(String idForEncode, - Map idToPasswordEncoder) { + public DelegatingPasswordEncoder(String idForEncode, Map idToPasswordEncoder) { if (idForEncode == null) { throw new IllegalArgumentException("idForEncode cannot be null"); } if (!idToPasswordEncoder.containsKey(idForEncode)) { - throw new IllegalArgumentException("idForEncode " + idForEncode + "is not found in idToPasswordEncoder " + idToPasswordEncoder); + throw new IllegalArgumentException( + "idForEncode " + idForEncode + "is not found in idToPasswordEncoder " + idToPasswordEncoder); } for (String id : idToPasswordEncoder.keySet()) { if (id == null) { @@ -165,16 +171,15 @@ public class DelegatingPasswordEncoder implements PasswordEncoder { * {@link PasswordEncoder}. * *

        - The encodedPassword provided will be the full password - * passed in including the {"id"} portion.* For example, if the password of - * "{notmapped}foobar" was used, the "id" would be "notmapped" and the encodedPassword - * passed into the {@link PasswordEncoder} would be "{notmapped}foobar". + * The encodedPassword provided will be the full password passed in including the + * {"id"} portion.* For example, if the password of "{notmapped}foobar" was used, the + * "id" would be "notmapped" and the encodedPassword passed into the + * {@link PasswordEncoder} would be "{notmapped}foobar". *

        - * @param defaultPasswordEncoderForMatches the encoder to use. The default is to - * throw an {@link IllegalArgumentException} + * @param defaultPasswordEncoderForMatches the encoder to use. The default is to throw + * an {@link IllegalArgumentException} */ - public void setDefaultPasswordEncoderForMatches( - PasswordEncoder defaultPasswordEncoderForMatches) { + public void setDefaultPasswordEncoderForMatches(PasswordEncoder defaultPasswordEncoderForMatches) { if (defaultPasswordEncoderForMatches == null) { throw new IllegalArgumentException("defaultPasswordEncoderForMatches cannot be null"); } @@ -194,8 +199,7 @@ public class DelegatingPasswordEncoder implements PasswordEncoder { String id = extractId(prefixEncodedPassword); PasswordEncoder delegate = this.idToPasswordEncoder.get(id); if (delegate == null) { - return this.defaultPasswordEncoderForMatches - .matches(rawPassword, prefixEncodedPassword); + return this.defaultPasswordEncoderForMatches.matches(rawPassword, prefixEncodedPassword); } String encodedPassword = extractEncodedPassword(prefixEncodedPassword); return delegate.matches(rawPassword, encodedPassword); @@ -244,10 +248,11 @@ public class DelegatingPasswordEncoder implements PasswordEncoder { } @Override - public boolean matches(CharSequence rawPassword, - String prefixEncodedPassword) { + public boolean matches(CharSequence rawPassword, String prefixEncodedPassword) { String id = extractId(prefixEncodedPassword); throw new IllegalArgumentException("There is no PasswordEncoder mapped for the id \"" + id + "\""); } + } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/password/Digester.java b/crypto/src/main/java/org/springframework/security/crypto/password/Digester.java index b0b57bc4b4..b14feb22e3 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/password/Digester.java +++ b/crypto/src/main/java/org/springframework/security/crypto/password/Digester.java @@ -68,4 +68,5 @@ final class Digester { throw new IllegalStateException("No such hashing algorithm", e); } } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/password/LdapShaPasswordEncoder.java b/crypto/src/main/java/org/springframework/security/crypto/password/LdapShaPasswordEncoder.java index 90252f3c14..0ee12c20eb 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/password/LdapShaPasswordEncoder.java +++ b/crypto/src/main/java/org/springframework/security/crypto/password/LdapShaPasswordEncoder.java @@ -39,19 +39,24 @@ import java.util.Base64; * @deprecated Digest based password encoding is not considered secure. Instead use an * adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or * SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports - * password upgrades. There are no plans to remove this support. It is deprecated to indicate - * that this is a legacy implementation and using it is considered insecure. + * password upgrades. There are no plans to remove this support. It is deprecated to + * indicate that this is a legacy implementation and using it is considered insecure. */ @Deprecated public class LdapShaPasswordEncoder implements PasswordEncoder { + // ~ Static fields/initializers // ===================================================================================== /** The number of bytes in a SHA hash */ private static final int SHA_LENGTH = 20; + private static final String SSHA_PREFIX = "{SSHA}"; + private static final String SSHA_PREFIX_LC = SSHA_PREFIX.toLowerCase(); + private static final String SHA_PREFIX = "{SHA}"; + private static final String SHA_PREFIX_LC = SHA_PREFIX.toLowerCase(); // ~ Instance fields @@ -93,9 +98,7 @@ public class LdapShaPasswordEncoder implements PasswordEncoder { * Calculates the hash of password (and salt bytes, if supplied) and returns a base64 * encoded concatenation of the hash and salt, prefixed with {SHA} (or {SSHA} if salt * was used). - * * @param rawPass the password to be encoded. - * * @return the encoded password in the specified format * */ @@ -104,7 +107,6 @@ public class LdapShaPasswordEncoder implements PasswordEncoder { return encode(rawPass, salt); } - private String encode(CharSequence rawPassword, byte[] salt) { MessageDigest sha; @@ -148,10 +150,8 @@ public class LdapShaPasswordEncoder implements PasswordEncoder { /** * Checks the validity of an unencoded password against an encoded one in the form * "{SSHA}sQuQF8vj8Eg2Y1hPdh3bkQhCKQBgjhQI". - * * @param rawPassword unencoded password to be verified. * @param encodedPassword the actual SSHA or SHA encoded password - * * @return true if they match (independent of the case of the prefix). */ public boolean matches(CharSequence rawPassword, String encodedPassword) { @@ -170,8 +170,7 @@ public class LdapShaPasswordEncoder implements PasswordEncoder { salt = extractSalt(encodedPassword); } else if (!prefix.equals(SHA_PREFIX) && !prefix.equals(SHA_PREFIX_LC)) { - throw new IllegalArgumentException("Unsupported password prefix '" + prefix - + "'"); + throw new IllegalArgumentException("Unsupported password prefix '" + prefix + "'"); } else { // Standard SHA @@ -182,8 +181,7 @@ public class LdapShaPasswordEncoder implements PasswordEncoder { String encodedRawPass = encode(rawPassword, salt).substring(startOfHash); - return PasswordEncoderUtils - .equals(encodedRawPass, encodedPassword.substring(startOfHash)); + return PasswordEncoderUtils.equals(encodedRawPass, encodedPassword.substring(startOfHash)); } /** @@ -197,8 +195,7 @@ public class LdapShaPasswordEncoder implements PasswordEncoder { int secondBrace = encPass.lastIndexOf('}'); if (secondBrace < 0) { - throw new IllegalArgumentException( - "Couldn't find closing brace for SHA prefix"); + throw new IllegalArgumentException("Couldn't find closing brace for SHA prefix"); } return encPass.substring(0, secondBrace + 1); @@ -207,4 +204,5 @@ public class LdapShaPasswordEncoder implements PasswordEncoder { public void setForceLowerCasePrefix(boolean forceLowerCasePrefix) { this.forceLowerCasePrefix = forceLowerCasePrefix; } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/password/Md4.java b/crypto/src/main/java/org/springframework/security/crypto/password/Md4.java index 89c4db51b0..ea5101cfb2 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/password/Md4.java +++ b/crypto/src/main/java/org/springframework/security/crypto/password/Md4.java @@ -22,12 +22,19 @@ package org.springframework.security.crypto.password; * @author Alan Stewart */ class Md4 { + private static final int BLOCK_SIZE = 64; + private static final int HASH_SIZE = 16; + private final byte[] buffer = new byte[BLOCK_SIZE]; + private int bufferOffset; + private long byteCount; + private final int[] state = new int[4]; + private final int[] tmp = new int[16]; Md4() { @@ -99,8 +106,8 @@ class Md4 { private void update(byte[] block, int offset) { for (int i = 0; i < 16; i++) { - tmp[i] = (block[offset++] & 0xFF) | (block[offset++] & 0xFF) << 8 - | (block[offset++] & 0xFF) << 16 | (block[offset++] & 0xFF) << 24; + tmp[i] = (block[offset++] & 0xFF) | (block[offset++] & 0xFF) << 8 | (block[offset++] & 0xFF) << 16 + | (block[offset++] & 0xFF) << 24; } int A = state[0]; @@ -179,4 +186,5 @@ class Md4 { int t = a + (b ^ c ^ d) + x + 0x6ED9EBA1; return t << s | t >>> (32 - s); } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/password/Md4PasswordEncoder.java b/crypto/src/main/java/org/springframework/security/crypto/password/Md4PasswordEncoder.java index 7fe06a979d..64e3e2e529 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/password/Md4PasswordEncoder.java +++ b/crypto/src/main/java/org/springframework/security/crypto/password/Md4PasswordEncoder.java @@ -23,7 +23,8 @@ import org.springframework.security.crypto.keygen.StringKeyGenerator; import java.util.Base64; /** - * This {@link PasswordEncoder} is provided for legacy purposes only and is not considered secure. + * This {@link PasswordEncoder} is provided for legacy purposes only and is not considered + * secure. * * Encodes passwords using MD4. The general format of the password is: * @@ -33,8 +34,7 @@ import java.util.Base64; * * * Such that "salt" is the salt, md4 is the digest method, and password is the actual - * password. For example with a password of "password", and a salt of - * "thisissalt": + * password. For example with a password of "password", and a salt of "thisissalt": * *
          * String s = salt == null ? "" : "{" + salt + "}";
        @@ -55,9 +55,9 @@ import java.util.Base64;
          * "{}" + md4(password + "{}")
          * 
        * - * The format is intended to work with the Md4PasswordEncoder that was found in the - * Spring Security core module. However, the passwords will need to be migrated to include - * any salt with the password since this API provides Salt internally vs making it the + * The format is intended to work with the Md4PasswordEncoder that was found in the Spring + * Security core module. However, the passwords will need to be migrated to include any + * salt with the password since this API provides Salt internally vs making it the * responsibility of the user. To migrate passwords from the SaltSource use the following: * *
        @@ -73,16 +73,19 @@ import java.util.Base64;
          * @deprecated Digest based password encoding is not considered secure. Instead use an
          * adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or
          * SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports
        - * password upgrades. There are no plans to remove this support. It is deprecated to indicate
        - * that this is a legacy implementation and using it is considered insecure.
        + * password upgrades. There are no plans to remove this support. It is deprecated to
        + * indicate that this is a legacy implementation and using it is considered insecure.
          */
         @Deprecated
         public class Md4PasswordEncoder implements PasswordEncoder {
        -	private static final String PREFIX = "{";
        -	private static final String SUFFIX = "}";
        -	private StringKeyGenerator saltGenerator = new Base64StringKeyGenerator();
        -	private boolean encodeHashAsBase64;
         
        +	private static final String PREFIX = "{";
        +
        +	private static final String SUFFIX = "}";
        +
        +	private StringKeyGenerator saltGenerator = new Base64StringKeyGenerator();
        +
        +	private boolean encodeHashAsBase64;
         
         	public void setEncodeHashAsBase64(boolean encodeHashAsBase64) {
         		this.encodeHashAsBase64 = encodeHashAsBase64;
        @@ -91,7 +94,6 @@ public class Md4PasswordEncoder implements PasswordEncoder {
         	/**
         	 * Encodes the rawPass using a MessageDigest. If a salt is specified it will be merged
         	 * with the password before encoding.
        -	 *
         	 * @param rawPassword The plain text password
         	 * @return Hex string of password digest (or base64 encoded string if
         	 * encodeHashAsBase64 is enabled.
        @@ -128,7 +130,6 @@ public class Md4PasswordEncoder implements PasswordEncoder {
         	/**
         	 * Takes a previously encoded password and compares it with a rawpassword after mixing
         	 * in the salt and encoding that value
        -	 *
         	 * @param rawPassword plain text password
         	 * @param encodedPassword previously encoded password
         	 * @return true or false
        @@ -150,4 +151,5 @@ public class Md4PasswordEncoder implements PasswordEncoder {
         		}
         		return prefixEncodedPassword.substring(start, end + 1);
         	}
        +
         }
        diff --git a/crypto/src/main/java/org/springframework/security/crypto/password/MessageDigestPasswordEncoder.java b/crypto/src/main/java/org/springframework/security/crypto/password/MessageDigestPasswordEncoder.java
        index 620bd6bf95..4f6a7f2af9 100644
        --- a/crypto/src/main/java/org/springframework/security/crypto/password/MessageDigestPasswordEncoder.java
        +++ b/crypto/src/main/java/org/springframework/security/crypto/password/MessageDigestPasswordEncoder.java
        @@ -24,7 +24,8 @@ import java.security.MessageDigest;
         import java.util.Base64;
         
         /**
        - * This {@link PasswordEncoder} is provided for legacy purposes only and is not considered secure.
        + * This {@link PasswordEncoder} is provided for legacy purposes only and is not considered
        + * secure.
          *
          * Encodes passwords using the passed in {@link MessageDigest}.
          *
        @@ -76,14 +77,18 @@ import java.util.Base64;
          * @deprecated Digest based password encoding is not considered secure. Instead use an
          * adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or
          * SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports
        - * password upgrades. There are no plans to remove this support. It is deprecated to indicate
        - * that this is a legacy implementation and using it is considered insecure.
        + * password upgrades. There are no plans to remove this support. It is deprecated to
        + * indicate that this is a legacy implementation and using it is considered insecure.
          */
         @Deprecated
         public class MessageDigestPasswordEncoder implements PasswordEncoder {
        +
         	private static final String PREFIX = "{";
        +
         	private static final String SUFFIX = "}";
        +
         	private StringKeyGenerator saltGenerator = new Base64StringKeyGenerator();
        +
         	private boolean encodeHashAsBase64;
         
         	private Digester digester;
        @@ -92,7 +97,6 @@ public class MessageDigestPasswordEncoder implements PasswordEncoder {
         	 * The digest algorithm to use Supports the named
         	 * 
         	 * Message Digest Algorithms in the Java environment.
        -	 *
         	 * @param algorithm
         	 */
         	public MessageDigestPasswordEncoder(String algorithm) {
        @@ -106,7 +110,6 @@ public class MessageDigestPasswordEncoder implements PasswordEncoder {
         	/**
         	 * Encodes the rawPass using a MessageDigest. If a salt is specified it will be merged
         	 * with the password before encoding.
        -	 *
         	 * @param rawPassword The plain text password
         	 * @return Hex string of password digest (or base64 encoded string if
         	 * encodeHashAsBase64 is enabled.
        @@ -136,7 +139,6 @@ public class MessageDigestPasswordEncoder implements PasswordEncoder {
         	/**
         	 * Takes a previously encoded password and compares it with a rawpassword after mixing
         	 * in the salt and encoding that value
        -	 *
         	 * @param rawPassword plain text password
         	 * @param encodedPassword previously encoded password
         	 * @return true or false
        @@ -152,7 +154,6 @@ public class MessageDigestPasswordEncoder implements PasswordEncoder {
         	 * "stretched". If this is greater than one, the initial digest is calculated, the
         	 * digest function will be called repeatedly on the result for the additional number
         	 * of iterations.
        -	 *
         	 * @param iterations the number of iterations which will be executed on the hashed
         	 * password/salt value. Defaults to 1.
         	 */
        @@ -171,4 +172,5 @@ public class MessageDigestPasswordEncoder implements PasswordEncoder {
         		}
         		return prefixEncodedPassword.substring(start, end + 1);
         	}
        +
         }
        diff --git a/crypto/src/main/java/org/springframework/security/crypto/password/NoOpPasswordEncoder.java b/crypto/src/main/java/org/springframework/security/crypto/password/NoOpPasswordEncoder.java
        index 3c28e16741..caffbb3a9d 100644
        --- a/crypto/src/main/java/org/springframework/security/crypto/password/NoOpPasswordEncoder.java
        +++ b/crypto/src/main/java/org/springframework/security/crypto/password/NoOpPasswordEncoder.java
        @@ -23,11 +23,11 @@ package org.springframework.security.crypto.password;
          * passwords may be preferred.
          *
          * @author Keith Donald
        - * @deprecated This PasswordEncoder is not secure. Instead use an
        - * adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or
        - * SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports
        - * password upgrades. There are no plans to remove this support. It is deprecated to indicate that
        - * this is a legacy implementation and using it is considered insecure.
        + * @deprecated This PasswordEncoder is not secure. Instead use an adaptive one way
        + * function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or SCryptPasswordEncoder.
        + * Even better use {@link DelegatingPasswordEncoder} which supports password upgrades.
        + * There are no plans to remove this support. It is deprecated to indicate that this is a
        + * legacy implementation and using it is considered insecure.
          */
         @Deprecated
         public final class NoOpPasswordEncoder implements PasswordEncoder {
        diff --git a/crypto/src/main/java/org/springframework/security/crypto/password/PasswordEncoder.java b/crypto/src/main/java/org/springframework/security/crypto/password/PasswordEncoder.java
        index 251acd0251..79fcf50ad4 100644
        --- a/crypto/src/main/java/org/springframework/security/crypto/password/PasswordEncoder.java
        +++ b/crypto/src/main/java/org/springframework/security/crypto/password/PasswordEncoder.java
        @@ -34,7 +34,6 @@ public interface PasswordEncoder {
         	 * Verify the encoded password obtained from storage matches the submitted raw
         	 * password after it too is encoded. Returns true if the passwords match, false if
         	 * they do not. The stored password itself is never decoded.
        -	 *
         	 * @param rawPassword the raw password to encode and match
         	 * @param encodedPassword the encoded password from storage to compare with
         	 * @return true if the raw password, after encoding, matches the encoded password from
        @@ -52,4 +51,5 @@ public interface PasswordEncoder {
         	default boolean upgradeEncoding(String encodedPassword) {
         		return false;
         	}
        +
         }
        diff --git a/crypto/src/main/java/org/springframework/security/crypto/password/PasswordEncoderUtils.java b/crypto/src/main/java/org/springframework/security/crypto/password/PasswordEncoderUtils.java
        index 6bf5b937ae..f808a0911e 100644
        --- a/crypto/src/main/java/org/springframework/security/crypto/password/PasswordEncoderUtils.java
        +++ b/crypto/src/main/java/org/springframework/security/crypto/password/PasswordEncoderUtils.java
        @@ -44,9 +44,11 @@ class PasswordEncoderUtils {
         			return null;
         		}
         
        -		return Utf8.encode(s); // need to check if Utf8.encode() runs in constant time (probably not). This may leak length of string.
        +		return Utf8.encode(s); // need to check if Utf8.encode() runs in constant time
        +								// (probably not). This may leak length of string.
         	}
         
         	private PasswordEncoderUtils() {
         	}
        +
         }
        diff --git a/crypto/src/main/java/org/springframework/security/crypto/password/Pbkdf2PasswordEncoder.java b/crypto/src/main/java/org/springframework/security/crypto/password/Pbkdf2PasswordEncoder.java
        index 3fa38e6774..53e56a1de8 100644
        --- a/crypto/src/main/java/org/springframework/security/crypto/password/Pbkdf2PasswordEncoder.java
        +++ b/crypto/src/main/java/org/springframework/security/crypto/password/Pbkdf2PasswordEncoder.java
        @@ -46,21 +46,27 @@ import static org.springframework.security.crypto.util.EncodingUtils.subArray;
         public class Pbkdf2PasswordEncoder implements PasswordEncoder {
         
         	private static final int DEFAULT_HASH_WIDTH = 256;
        +
         	private static final int DEFAULT_ITERATIONS = 185000;
         
         	private final BytesKeyGenerator saltGenerator = KeyGenerators.secureRandom();
         
         	private final byte[] secret;
        +
         	private final int hashWidth;
        +
         	private final int iterations;
        +
         	private String algorithm = SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA1.name();
        +
         	private boolean encodeHashAsBase64;
         
         	/**
         	 * Constructs a PBKDF2 password encoder with no additional secret value. There will be
        -	 * {@value DEFAULT_ITERATIONS} iterations and a hash width of {@value DEFAULT_HASH_WIDTH}. The default is based upon aiming for .5
        -	 * seconds to validate the password when this class was added.. Users should tune
        -	 * password verification to their own systems.
        +	 * {@value DEFAULT_ITERATIONS} iterations and a hash width of
        +	 * {@value DEFAULT_HASH_WIDTH}. The default is based upon aiming for .5 seconds to
        +	 * validate the password when this class was added.. Users should tune password
        +	 * verification to their own systems.
         	 */
         	public Pbkdf2PasswordEncoder() {
         		this("");
        @@ -68,8 +74,8 @@ public class Pbkdf2PasswordEncoder implements PasswordEncoder {
         
         	/**
         	 * Constructs a standard password encoder with a secret value which is also included
        -	 * in the password hash. There will be {@value DEFAULT_ITERATIONS} iterations and a hash width of {@value DEFAULT_HASH_WIDTH}.
        -	 *
        +	 * in the password hash. There will be {@value DEFAULT_ITERATIONS} iterations and a
        +	 * hash width of {@value DEFAULT_HASH_WIDTH}.
         	 * @param secret the secret key used in the encoding process (should not be shared)
         	 */
         	public Pbkdf2PasswordEncoder(CharSequence secret) {
        @@ -79,7 +85,6 @@ public class Pbkdf2PasswordEncoder implements PasswordEncoder {
         	/**
         	 * Constructs a standard password encoder with a secret value as well as iterations
         	 * and hash.
        -	 *
         	 * @param secret the secret
         	 * @param iterations the number of iterations. Users should aim for taking about .5
         	 * seconds on their own system.
        @@ -92,8 +97,9 @@ public class Pbkdf2PasswordEncoder implements PasswordEncoder {
         	}
         
         	/**
        -	 * Sets the algorithm to use. See
        -	 * SecretKeyFactory Algorithms
        +	 * Sets the algorithm to use. See SecretKeyFactory
        +	 * Algorithms
         	 * @param secretKeyFactoryAlgorithm the algorithm to use (i.e.
         	 * {@code SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA1},
         	 * {@code SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA256},
        @@ -154,8 +160,8 @@ public class Pbkdf2PasswordEncoder implements PasswordEncoder {
         
         	private byte[] encode(CharSequence rawPassword, byte[] salt) {
         		try {
        -			PBEKeySpec spec = new PBEKeySpec(rawPassword.toString().toCharArray(),
        -					concatenate(salt, this.secret), this.iterations, this.hashWidth);
        +			PBEKeySpec spec = new PBEKeySpec(rawPassword.toString().toCharArray(), concatenate(salt, this.secret),
        +					this.iterations, this.hashWidth);
         			SecretKeyFactory skf = SecretKeyFactory.getInstance(this.algorithm);
         			return concatenate(salt, skf.generateSecret(spec).getEncoded());
         		}
        @@ -170,8 +176,9 @@ public class Pbkdf2PasswordEncoder implements PasswordEncoder {
         	 * @since 5.0
         	 */
         	public enum SecretKeyFactoryAlgorithm {
        -		PBKDF2WithHmacSHA1,
        -		PBKDF2WithHmacSHA256,
        -		PBKDF2WithHmacSHA512
        +
        +		PBKDF2WithHmacSHA1, PBKDF2WithHmacSHA256, PBKDF2WithHmacSHA512
        +
         	}
        +
         }
        diff --git a/crypto/src/main/java/org/springframework/security/crypto/password/StandardPasswordEncoder.java b/crypto/src/main/java/org/springframework/security/crypto/password/StandardPasswordEncoder.java
        index c07fb5bf9f..7f64d2e225 100644
        --- a/crypto/src/main/java/org/springframework/security/crypto/password/StandardPasswordEncoder.java
        +++ b/crypto/src/main/java/org/springframework/security/crypto/password/StandardPasswordEncoder.java
        @@ -45,8 +45,8 @@ import java.security.MessageDigest;
          * @deprecated Digest based password encoding is not considered secure. Instead use an
          * adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or
          * SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports
        - * password upgrades. There are no plans to remove this support. It is deprecated to indicate
        - * that this is a legacy implementation and using it is considered insecure.
        + * password upgrades. There are no plans to remove this support. It is deprecated to
        + * indicate that this is a legacy implementation and using it is considered insecure.
          */
         @Deprecated
         public final class StandardPasswordEncoder implements PasswordEncoder {
        @@ -67,7 +67,6 @@ public final class StandardPasswordEncoder implements PasswordEncoder {
         	/**
         	 * Constructs a standard password encoder with a secret value which is also included
         	 * in the password hash.
        -	 *
         	 * @param secret the secret key used in the encoding process (should not be shared)
         	 */
         	public StandardPasswordEncoder(CharSequence secret) {
        @@ -98,8 +97,7 @@ public final class StandardPasswordEncoder implements PasswordEncoder {
         	}
         
         	private byte[] digest(CharSequence rawPassword, byte[] salt) {
        -		byte[] digest = digester.digest(concatenate(salt, secret,
        -				Utf8.encode(rawPassword)));
        +		byte[] digest = digester.digest(concatenate(salt, secret, Utf8.encode(rawPassword)));
         		return concatenate(salt, digest);
         	}
         
        diff --git a/crypto/src/main/java/org/springframework/security/crypto/scrypt/SCryptPasswordEncoder.java b/crypto/src/main/java/org/springframework/security/crypto/scrypt/SCryptPasswordEncoder.java
        index 189c0ab266..a7fcec4057 100644
        --- a/crypto/src/main/java/org/springframework/security/crypto/scrypt/SCryptPasswordEncoder.java
        +++ b/crypto/src/main/java/org/springframework/security/crypto/scrypt/SCryptPasswordEncoder.java
        @@ -28,9 +28,9 @@ import org.springframework.security.crypto.password.PasswordEncoder;
         
         /**
          * 

        - * Implementation of PasswordEncoder that uses the SCrypt hashing function. - * Clients can optionally supply a cpu cost parameter, a memory cost parameter - * and a parallelization parameter. + * Implementation of PasswordEncoder that uses the SCrypt hashing function. Clients can + * optionally supply a cpu cost parameter, a memory cost parameter and a parallelization + * parameter. *

        * *

        @@ -41,13 +41,13 @@ import org.springframework.security.crypto.password.PasswordEncoder; * *

          *
        • The currently implementation uses Bouncy castle which does not exploit - * parallelism/optimizations that password crackers will, so there is an - * unnecessary asymmetry between attacker and defender.
        • - *
        • Scrypt is based on Salsa20 which performs poorly in Java (on par with - * AES) but performs awesome (~4-5x faster) on SIMD capable platforms
        • + * parallelism/optimizations that password crackers will, so there is an unnecessary + * asymmetry between attacker and defender. + *
        • Scrypt is based on Salsa20 which performs poorly in Java (on par with AES) but + * performs awesome (~4-5x faster) on SIMD capable platforms
        • *
        • While there are some that would disagree, consider reading - - * - * Why I Don't Recommend Scrypt (for password storage)
        • + * Why I + * Don't Recommend Scrypt (for password storage) *
        * * @author Shazin Sadakath @@ -74,25 +74,17 @@ public class SCryptPasswordEncoder implements PasswordEncoder { /** * Creates a new instance - * - * @param cpuCost - * cpu cost of the algorithm (as defined in scrypt this is N). - * must be power of 2 greater than 1. Default is currently 16,384 - * or 2^14) - * @param memoryCost - * memory cost of the algorithm (as defined in scrypt this is r) - * Default is currently 8. - * @param parallelization - * the parallelization of the algorithm (as defined in scrypt - * this is p) Default is currently 1. Note that the - * implementation does not currently take advantage of - * parallelization. - * @param keyLength - * key length for the algorithm (as defined in scrypt this is - * dkLen). The default is currently 32. - * @param saltLength - * salt length (as defined in scrypt this is the length of S). - * The default is currently 64. + * @param cpuCost cpu cost of the algorithm (as defined in scrypt this is N). must be + * power of 2 greater than 1. Default is currently 16,384 or 2^14) + * @param memoryCost memory cost of the algorithm (as defined in scrypt this is r) + * Default is currently 8. + * @param parallelization the parallelization of the algorithm (as defined in scrypt + * this is p) Default is currently 1. Note that the implementation does not currently + * take advantage of parallelization. + * @param keyLength key length for the algorithm (as defined in scrypt this is dkLen). + * The default is currently 32. + * @param saltLength salt length (as defined in scrypt this is the length of S). The + * default is currently 64. */ public SCryptPasswordEncoder(int cpuCost, int memoryCost, int parallelization, int keyLength, int saltLength) { if (cpuCost <= 1) { @@ -153,9 +145,7 @@ public class SCryptPasswordEncoder implements PasswordEncoder { int memoryCost = (int) params >> 8 & 0xff; int parallelization = (int) params & 0xff; - return cpuCost < this.cpuCost - || memoryCost < this.memoryCost - || parallelization < this.parallelization; + return cpuCost < this.cpuCost || memoryCost < this.memoryCost || parallelization < this.parallelization; } private boolean decodeAndCheckMatches(CharSequence rawPassword, String encodedPassword) { @@ -180,7 +170,8 @@ public class SCryptPasswordEncoder implements PasswordEncoder { } private String digest(CharSequence rawPassword, byte[] salt) { - byte[] derived = SCrypt.generate(Utf8.encode(rawPassword), salt, cpuCost, memoryCost, parallelization, keyLength); + byte[] derived = SCrypt.generate(Utf8.encode(rawPassword), salt, cpuCost, memoryCost, parallelization, + keyLength); String params = Long .toString(((int) (Math.log(cpuCost) / Math.log(2)) << 16L) | memoryCost << 8 | parallelization, 16); @@ -200,4 +191,5 @@ public class SCryptPasswordEncoder implements PasswordEncoder { private String encodePart(byte[] part) { return Utf8.decode(Base64.getEncoder().encode(part)); } + } diff --git a/crypto/src/test/java/org/springframework/security/crypto/argon2/Argon2EncodingUtilsTests.java b/crypto/src/test/java/org/springframework/security/crypto/argon2/Argon2EncodingUtilsTests.java index 660bd5347f..86e5bd9d53 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/argon2/Argon2EncodingUtilsTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/argon2/Argon2EncodingUtilsTests.java @@ -31,18 +31,16 @@ public class Argon2EncodingUtilsTests { private TestDataEntry testDataEntry1 = new TestDataEntry( "$argon2i$v=19$m=1024,t=3,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs", new Argon2EncodingUtils.Argon2Hash(decoder.decode("cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"), - (new Argon2Parameters.Builder(Argon2Parameters.ARGON2_i)). - withVersion(19).withMemoryAsKB(1024).withIterations(3).withParallelism(2). - withSalt("cRdFbCw23gz2Mlxk".getBytes()).build() - )); + (new Argon2Parameters.Builder(Argon2Parameters.ARGON2_i)).withVersion(19).withMemoryAsKB(1024) + .withIterations(3).withParallelism(2).withSalt("cRdFbCw23gz2Mlxk".getBytes()).build())); private TestDataEntry testDataEntry2 = new TestDataEntry( "$argon2id$v=19$m=333,t=5,p=2$JDR8N3k1QWx0$+PrEoHOHsWkU9lnsxqnOFrWTVEuOh7ZRIUIbe2yUG8FgTYNCWJfHQI09JAAFKzr2JAvoejEpTMghUt0WsntQYA", - new Argon2EncodingUtils.Argon2Hash(decoder.decode("+PrEoHOHsWkU9lnsxqnOFrWTVEuOh7ZRIUIbe2yUG8FgTYNCWJfHQI09JAAFKzr2JAvoejEpTMghUt0WsntQYA"), - (new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id)). - withVersion(19).withMemoryAsKB(333).withIterations(5).withParallelism(2). - withSalt("$4|7y5Alt".getBytes()).build() - )); + new Argon2EncodingUtils.Argon2Hash( + decoder.decode( + "+PrEoHOHsWkU9lnsxqnOFrWTVEuOh7ZRIUIbe2yUG8FgTYNCWJfHQI09JAAFKzr2JAvoejEpTMghUt0WsntQYA"), + (new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id)).withVersion(19).withMemoryAsKB(333) + .withIterations(5).withParallelism(2).withSalt("$4|7y5Alt".getBytes()).build())); @Test public void decodeWhenValidEncodedHashWithIThenDecodeCorrectly() { @@ -56,22 +54,20 @@ public class Argon2EncodingUtilsTests { @Test public void encodeWhenValidArgumentsWithIThenEncodeToCorrectHash() { - assertThat(Argon2EncodingUtils - .encode(testDataEntry1.decoded.getHash(), testDataEntry1.decoded.getParameters())) + assertThat(Argon2EncodingUtils.encode(testDataEntry1.decoded.getHash(), testDataEntry1.decoded.getParameters())) .isEqualTo(testDataEntry1.encoded); } @Test public void encodeWhenValidArgumentsWithID2ThenEncodeToCorrectHash() { - assertThat(Argon2EncodingUtils - .encode(testDataEntry2.decoded.getHash(), testDataEntry2.decoded.getParameters())) + assertThat(Argon2EncodingUtils.encode(testDataEntry2.decoded.getHash(), testDataEntry2.decoded.getParameters())) .isEqualTo(testDataEntry2.encoded); } @Test(expected = IllegalArgumentException.class) public void encodeWhenNonexistingAlgorithmThenThrowException() { - Argon2EncodingUtils.encode(new byte[]{0, 1, 2, 3}, (new Argon2Parameters.Builder(3)). - withVersion(19).withMemoryAsKB(333).withIterations(5).withParallelism(2).build()); + Argon2EncodingUtils.encode(new byte[] { 0, 1, 2, 3 }, (new Argon2Parameters.Builder(3)).withVersion(19) + .withMemoryAsKB(333).withIterations(5).withParallelism(2).build()); } @Test(expected = IllegalArgumentException.class) @@ -81,70 +77,80 @@ public class Argon2EncodingUtilsTests { @Test(expected = IllegalArgumentException.class) public void decodeWhenNonexistingAlgorithmThenThrowException() { - Argon2EncodingUtils.decode("$argon2x$v=19$m=1024,t=3,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); + Argon2EncodingUtils.decode( + "$argon2x$v=19$m=1024,t=3,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); } @Test(expected = IllegalArgumentException.class) public void decodeWhenIllegalVersionParameterThenThrowException() { - Argon2EncodingUtils.decode("$argon2i$v=x$m=1024,t=3,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); + Argon2EncodingUtils.decode( + "$argon2i$v=x$m=1024,t=3,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); } @Test(expected = IllegalArgumentException.class) public void decodeWhenIllegalMemoryParameterThenThrowException() { - Argon2EncodingUtils.decode("$argon2i$v=19$m=x,t=3,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); + Argon2EncodingUtils + .decode("$argon2i$v=19$m=x,t=3,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); } @Test(expected = IllegalArgumentException.class) public void decodeWhenIllegalIterationsParameterThenThrowException() { - Argon2EncodingUtils.decode("$argon2i$v=19$m=1024,t=x,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); + Argon2EncodingUtils.decode( + "$argon2i$v=19$m=1024,t=x,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); } @Test(expected = IllegalArgumentException.class) public void decodeWhenIllegalParallelityParameterThenThrowException() { - Argon2EncodingUtils.decode("$argon2i$v=19$m=1024,t=3,p=x$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); + Argon2EncodingUtils.decode( + "$argon2i$v=19$m=1024,t=3,p=x$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); } @Test(expected = IllegalArgumentException.class) public void decodeWhenMissingVersionParameterThenThrowException() { - Argon2EncodingUtils.decode("$argon2i$m=1024,t=3,p=x$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); + Argon2EncodingUtils + .decode("$argon2i$m=1024,t=3,p=x$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); } @Test(expected = IllegalArgumentException.class) public void decodeWhenMissingMemoryParameterThenThrowException() { - Argon2EncodingUtils.decode("$argon2i$v=19$t=3,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); + Argon2EncodingUtils + .decode("$argon2i$v=19$t=3,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); } @Test(expected = IllegalArgumentException.class) public void decodeWhenMissingIterationsParameterThenThrowException() { - Argon2EncodingUtils.decode("$argon2i$v=19$m=1024,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); + Argon2EncodingUtils + .decode("$argon2i$v=19$m=1024,p=2$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); } @Test(expected = IllegalArgumentException.class) public void decodeWhenMissingParallelityParameterThenThrowException() { - Argon2EncodingUtils.decode("$argon2i$v=19$m=1024,t=3$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); + Argon2EncodingUtils + .decode("$argon2i$v=19$m=1024,t=3$Y1JkRmJDdzIzZ3oyTWx4aw$cGE5Cbd/cx7micVhXVBdH5qTr66JI1iUyuNNVAnErXs"); } - private void assertArgon2HashEquals(Argon2EncodingUtils.Argon2Hash expected, Argon2EncodingUtils.Argon2Hash actual) { + private void assertArgon2HashEquals(Argon2EncodingUtils.Argon2Hash expected, + Argon2EncodingUtils.Argon2Hash actual) { assertThat(actual.getHash()).isEqualTo(expected.getHash()); assertThat(actual.getParameters().getSalt()).isEqualTo(expected.getParameters().getSalt()); assertThat(actual.getParameters().getType()).isEqualTo(expected.getParameters().getType()); - assertThat(actual.getParameters().getVersion()) - .isEqualTo(expected.getParameters().getVersion()); - assertThat(actual.getParameters().getMemory()) - .isEqualTo(expected.getParameters().getMemory()); - assertThat(actual.getParameters().getIterations()) - .isEqualTo(expected.getParameters().getIterations()); - assertThat(actual.getParameters().getLanes()) - .isEqualTo(expected.getParameters().getLanes()); + assertThat(actual.getParameters().getVersion()).isEqualTo(expected.getParameters().getVersion()); + assertThat(actual.getParameters().getMemory()).isEqualTo(expected.getParameters().getMemory()); + assertThat(actual.getParameters().getIterations()).isEqualTo(expected.getParameters().getIterations()); + assertThat(actual.getParameters().getLanes()).isEqualTo(expected.getParameters().getLanes()); } private static class TestDataEntry { + String encoded; + Argon2EncodingUtils.Argon2Hash decoded; TestDataEntry(String encoded, Argon2EncodingUtils.Argon2Hash decoded) { this.encoded = encoded; this.decoded = decoded; } + } + } diff --git a/crypto/src/test/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoderTests.java b/crypto/src/test/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoderTests.java index 229b43227f..5de065357d 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoderTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoderTests.java @@ -198,17 +198,18 @@ public class Argon2PasswordEncoderTests { encoder.upgradeEncoding("thisIsNoValidHash"); } - private void injectPredictableSaltGen() throws Exception { byte[] bytes = new byte[16]; Arrays.fill(bytes, (byte) 0x41); Mockito.when(keyGeneratorMock.generateKey()).thenReturn(bytes); - //we can't use the @InjectMock-annotation because the salt-generator is set in the constructor - //and Mockito will only inject mocks if they are null + // we can't use the @InjectMock-annotation because the salt-generator is set in + // the constructor + // and Mockito will only inject mocks if they are null Field saltGen = encoder.getClass().getDeclaredField("saltGenerator"); saltGen.setAccessible(true); saltGen.set(encoder, keyGeneratorMock); saltGen.setAccessible(false); } + } diff --git a/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoderTests.java b/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoderTests.java index 1ae357f019..01eeebcb0a 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoderTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoderTests.java @@ -79,8 +79,7 @@ public class BCryptPasswordEncoderTests { @Test public void $2bUnicode() { - BCryptPasswordEncoder encoder = - new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2B); + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2B); String result = encoder.encode("passw\u9292rd"); assertThat(encoder.matches("pass\u9292\u9292rd", result)).isFalse(); assertThat(encoder.matches("passw\u9292rd", result)).isTrue(); @@ -96,16 +95,14 @@ public class BCryptPasswordEncoderTests { @Test public void $2aNotMatches() { - BCryptPasswordEncoder encoder = - new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2A); + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2A); String result = encoder.encode("password"); assertThat(encoder.matches("bogus", result)).isFalse(); } @Test public void $2bNotMatches() { - BCryptPasswordEncoder encoder = - new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2B); + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2B); String result = encoder.encode("password"); assertThat(encoder.matches("bogus", result)).isFalse(); } @@ -120,16 +117,14 @@ public class BCryptPasswordEncoderTests { @Test public void $2aCustomStrength() { - BCryptPasswordEncoder encoder = - new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2A, 8); + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2A, 8); String result = encoder.encode("password"); assertThat(encoder.matches("password", result)).isTrue(); } @Test public void $2bCustomStrength() { - BCryptPasswordEncoder encoder = - new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2B, 8); + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2B, 8); String result = encoder.encode("password"); assertThat(encoder.matches("password", result)).isTrue(); } @@ -182,7 +177,8 @@ public class BCryptPasswordEncoderTests { } /** - * @see https://github.com/spring-projects/spring-security/pull/7042#issuecomment-506755496 + * @see https://github.com/spring-projects/spring-security/pull/7042#issuecomment-506755496 */ @Test public void upgradeFromNullOrEmpty() { @@ -192,7 +188,8 @@ public class BCryptPasswordEncoderTests { } /** - * @see https://github.com/spring-projects/spring-security/pull/7042#issuecomment-506755496 + * @see https://github.com/spring-projects/spring-security/pull/7042#issuecomment-506755496 */ @Test(expected = IllegalArgumentException.class) public void upgradeFromNonBCrypt() { diff --git a/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptTests.java b/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptTests.java index 743a85fa8b..437f03330d 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptTests.java @@ -25,13 +25,17 @@ import static org.assertj.core.api.Assertions.assertThat; /** * JUnit unit tests for BCrypt routines + * * @author Damien Miller */ public class BCryptTests { private static class TestObject { + private final T password; + private final String salt; + private final String expected; private TestObject(T password, String salt, String expected) { @@ -39,6 +43,7 @@ public class BCryptTests { this.salt = salt; this.expected = expected; } + } private static void print(String s) { @@ -138,21 +143,21 @@ public class BCryptTests { "$2y$06$6Xm0gCw4g7ZNDCEp4yTisez0kSdpXEl66MvdxGidnmChIe8dFmMnq")); testObjectsByteArray = new ArrayList<>(); - testObjectsByteArray.add(new TestObject<>(new byte[] { }, "$2a$06$fPIsBO8qRqkjj273rfaOI.", + testObjectsByteArray.add(new TestObject<>(new byte[] {}, "$2a$06$fPIsBO8qRqkjj273rfaOI.", "$2a$06$fPIsBO8qRqkjj273rfaOI.uiVGfgi6Z1Iz.vZr11mi/38o09TUVCy")); - testObjectsByteArray.add(new TestObject<>(new byte[] { }, "$2a$08$Eq2r4G/76Wv39MzSX262hu", + testObjectsByteArray.add(new TestObject<>(new byte[] {}, "$2a$08$Eq2r4G/76Wv39MzSX262hu", "$2a$08$Eq2r4G/76Wv39MzSX262hu2lrqIItOWKIkPsMMvm5LAFD.iVB7Nmm")); - testObjectsByteArray.add(new TestObject<>(new byte[] { }, "$2a$10$LgfYWkbzEvQ4JakH7rOvHe", + testObjectsByteArray.add(new TestObject<>(new byte[] {}, "$2a$10$LgfYWkbzEvQ4JakH7rOvHe", "$2a$10$LgfYWkbzEvQ4JakH7rOvHeU6pINYiHnazYxe4GikGWx9MaUr27Vpa")); - testObjectsByteArray.add(new TestObject<>(new byte[] { }, "$2a$12$WApznUOJfkEGSmYRfnkrPO", + testObjectsByteArray.add(new TestObject<>(new byte[] {}, "$2a$12$WApznUOJfkEGSmYRfnkrPO", "$2a$12$WApznUOJfkEGSmYRfnkrPONS3wcUvmKuh3LpjxSs6g78T77gZta3W")); - testObjectsByteArray.add(new TestObject<>(new byte[] { }, "$2b$06$FGWA8OlY6RtQhXBXuCJ8Wu", + testObjectsByteArray.add(new TestObject<>(new byte[] {}, "$2b$06$FGWA8OlY6RtQhXBXuCJ8Wu", "$2b$06$FGWA8OlY6RtQhXBXuCJ8Wu5oPJaT8BeCRmS273I6cpp5RwwjAWn7S")); - testObjectsByteArray.add(new TestObject<>(new byte[] { }, "$2b$06$G6aYU7UhUEUDJBdTgq3CRe", + testObjectsByteArray.add(new TestObject<>(new byte[] {}, "$2b$06$G6aYU7UhUEUDJBdTgq3CRe", "$2b$06$G6aYU7UhUEUDJBdTgq3CRebzUYAyG8MCS3WdBk0CcPb9bfj1.3cSG")); - testObjectsByteArray.add(new TestObject<>(new byte[] { }, "$2y$06$sYDFHqOcXTjBgOsqC0WCKe", + testObjectsByteArray.add(new TestObject<>(new byte[] {}, "$2y$06$sYDFHqOcXTjBgOsqC0WCKe", "$2y$06$sYDFHqOcXTjBgOsqC0WCKeOv88fqPKkuV1yGVh./TROmn1mL8gYh2")); - testObjectsByteArray.add(new TestObject<>(new byte[] { }, "$2y$06$6Xm0gCw4g7ZNDCEp4yTise", + testObjectsByteArray.add(new TestObject<>(new byte[] {}, "$2y$06$6Xm0gCw4g7ZNDCEp4yTise", "$2y$06$6Xm0gCw4g7ZNDCEp4yTisecBqTHmLJBHxTNZa8w2hupJKsIhPWOgG")); testObjectsByteArray.add(new TestObject<>(new byte[] { -11 }, "$2a$06$fPIsBO8qRqkjj273rfaOI.", "$2a$06$fPIsBO8qRqkjj273rfaOI.AyMTPwvUEmZ2EdJM/p0S0eP3UQpBas.")); @@ -342,8 +347,7 @@ public class BCryptTests { BCrypt.decode_base64("", 0); } - private static String encode_base64(byte d[], int len) - throws IllegalArgumentException { + private static String encode_base64(byte d[], int len) throws IllegalArgumentException { StringBuilder rs = new StringBuilder(); BCrypt.encode_base64(d, len, rs); return rs.toString(); @@ -353,7 +357,7 @@ public class BCryptTests { public void testBase64EncodeSimpleByteArrays() { assertThat(encode_base64(new byte[] { 0 }, 1)).isEqualTo(".."); assertThat(encode_base64(new byte[] { 0, 0 }, 2)).isEqualTo("..."); - assertThat(encode_base64(new byte[] { 0, 0 , 0 }, 3)).isEqualTo("...."); + assertThat(encode_base64(new byte[] { 0, 0, 0 }, 3)).isEqualTo("...."); } @Test @@ -435,8 +439,8 @@ public class BCryptTests { @Test public void hashpwWorksWithOldRevision() { - assertThat(BCrypt.hashpw("password", "$2$05$......................")).isEqualTo( - "$2$05$......................bvpG2UfzdyW/S0ny/4YyEZrmczoJfVm"); + assertThat(BCrypt.hashpw("password", "$2$05$......................")) + .isEqualTo("$2$05$......................bvpG2UfzdyW/S0ny/4YyEZrmczoJfVm"); } @Test(expected = IllegalArgumentException.class) @@ -454,4 +458,5 @@ public class BCryptTests { assertThat(BCrypt.equalsNoEarlyReturn("test", "pass")).isFalse(); } + } diff --git a/crypto/src/test/java/org/springframework/security/crypto/codec/Base64Tests.java b/crypto/src/test/java/org/springframework/security/crypto/codec/Base64Tests.java index 8da8ffe9b8..3a96a9b0b0 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/codec/Base64Tests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/codec/Base64Tests.java @@ -29,15 +29,13 @@ public class Base64Tests { public void isBase64ReturnsTrueForValidBase64() { new Base64(); // unused - assertThat(Base64.isBase64(new byte[] { (byte) 'A', (byte) 'B', (byte) 'C', - (byte) 'D' })).isTrue(); + assertThat(Base64.isBase64(new byte[] { (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D' })).isTrue(); } @Test public void isBase64ReturnsFalseForInvalidBase64() { // Include invalid '`' character - assertThat(Base64.isBase64(new byte[] { (byte) 'A', (byte) 'B', (byte) 'C', - (byte) '`' })).isFalse(); + assertThat(Base64.isBase64(new byte[] { (byte) 'A', (byte) 'B', (byte) 'C', (byte) '`' })).isFalse(); } @Test(expected = NullPointerException.class) @@ -49,4 +47,5 @@ public class Base64Tests { public void isBase64RejectsInvalidLength() { Base64.isBase64(new byte[] { (byte) 'A' }); } + } diff --git a/crypto/src/test/java/org/springframework/security/crypto/codec/HexTests.java b/crypto/src/test/java/org/springframework/security/crypto/codec/HexTests.java index a85b69264a..ccfec27b5f 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/codec/HexTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/codec/HexTests.java @@ -33,8 +33,8 @@ public class HexTests { @Test public void encode() { - assertThat(Hex.encode(new byte[] { (byte) 'A', (byte) 'B', (byte) 'C', - (byte) 'D' })).isEqualTo(new char[] {'4', '1', '4', '2', '4', '3', '4', '4'}); + assertThat(Hex.encode(new byte[] { (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D' })) + .isEqualTo(new char[] { '4', '1', '4', '2', '4', '3', '4', '4' }); } @Test @@ -44,8 +44,7 @@ public class HexTests { @Test public void decode() { - assertThat(Hex.decode("41424344")).isEqualTo(new byte[] { (byte) 'A', (byte) 'B', (byte) 'C', - (byte) 'D' }); + assertThat(Hex.decode("41424344")).isEqualTo(new byte[] { (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D' }); } @Test diff --git a/crypto/src/test/java/org/springframework/security/crypto/codec/Utf8Tests.java b/crypto/src/test/java/org/springframework/security/crypto/codec/Utf8Tests.java index a78107ad87..9e7ef12b52 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/codec/Utf8Tests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/codec/Utf8Tests.java @@ -37,4 +37,5 @@ public class Utf8Tests { assertThat(decoded).isEqualTo("6048b75ed560785c"); } + } diff --git a/crypto/src/test/java/org/springframework/security/crypto/encrypt/AesBytesEncryptorTests.java b/crypto/src/test/java/org/springframework/security/crypto/encrypt/AesBytesEncryptorTests.java index ce95884e9d..44ed2570c9 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/encrypt/AesBytesEncryptorTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/encrypt/AesBytesEncryptorTests.java @@ -36,8 +36,11 @@ import static org.springframework.security.crypto.password.Pbkdf2PasswordEncoder * Tests for {@link AesBytesEncryptor} */ public class AesBytesEncryptorTests { + private String secret = "value"; + private String password = "password"; + private String hexSalt = "deadbeef"; private BytesKeyGenerator generator; @@ -86,8 +89,7 @@ public class AesBytesEncryptorTests { @Test public void roundtripWhenUsingSecretKeyThenEncryptsAndDecrypts() { CryptoAssumptions.assumeGCMJCE(); - PBEKeySpec keySpec = new PBEKeySpec(this.password.toCharArray(), Hex.decode(this.hexSalt), - 1024, 256); + PBEKeySpec keySpec = new PBEKeySpec(this.password.toCharArray(), Hex.decode(this.hexSalt), 1024, 256); SecretKey secretKey = newSecretKey(PBKDF2WithHmacSHA1.name(), keySpec); AesBytesEncryptor encryptor = new AesBytesEncryptor(secretKey, this.generator, GCM); diff --git a/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorEquivalencyTests.java b/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorEquivalencyTests.java index d4c5c73e72..7df6f80c27 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorEquivalencyTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorEquivalencyTests.java @@ -30,15 +30,18 @@ import org.springframework.security.crypto.keygen.KeyGenerators; public class BouncyCastleAesBytesEncryptorEquivalencyTests { private byte[] testData; + private String password; + private String salt; + private SecureRandom secureRandom = new SecureRandom(); @Before public void setup() { // generate random password, salt, and test data password = UUID.randomUUID().toString(); - /** insecure salt byte, recommend 64 or larger than 64*/ + /** insecure salt byte, recommend 64 or larger than 64 */ byte[] saltBytes = new byte[16]; secureRandom.nextBytes(saltBytes); salt = new String(Hex.encode(saltBytes)); @@ -49,8 +52,7 @@ public class BouncyCastleAesBytesEncryptorEquivalencyTests { CryptoAssumptions.assumeCBCJCE(); BytesEncryptor bcEncryptor = new BouncyCastleAesCbcBytesEncryptor(password, salt, new PredictableRandomBytesKeyGenerator(16)); - BytesEncryptor jceEncryptor = new AesBytesEncryptor(password, salt, - new PredictableRandomBytesKeyGenerator(16)); + BytesEncryptor jceEncryptor = new AesBytesEncryptor(password, salt, new PredictableRandomBytesKeyGenerator(16)); testEquivalence(bcEncryptor, jceEncryptor); } @@ -59,8 +61,7 @@ public class BouncyCastleAesBytesEncryptorEquivalencyTests { CryptoAssumptions.assumeCBCJCE(); BytesEncryptor bcEncryptor = new BouncyCastleAesCbcBytesEncryptor(password, salt, KeyGenerators.secureRandom(16)); - BytesEncryptor jceEncryptor = new AesBytesEncryptor(password, salt, - KeyGenerators.secureRandom(16)); + BytesEncryptor jceEncryptor = new AesBytesEncryptor(password, salt, KeyGenerators.secureRandom(16)); testCompatibility(bcEncryptor, jceEncryptor); } @@ -69,8 +70,8 @@ public class BouncyCastleAesBytesEncryptorEquivalencyTests { CryptoAssumptions.assumeGCMJCE(); BytesEncryptor bcEncryptor = new BouncyCastleAesGcmBytesEncryptor(password, salt, new PredictableRandomBytesKeyGenerator(16)); - BytesEncryptor jceEncryptor = new AesBytesEncryptor(password, salt, - new PredictableRandomBytesKeyGenerator(16), CipherAlgorithm.GCM); + BytesEncryptor jceEncryptor = new AesBytesEncryptor(password, salt, new PredictableRandomBytesKeyGenerator(16), + CipherAlgorithm.GCM); testEquivalence(bcEncryptor, jceEncryptor); } @@ -79,8 +80,8 @@ public class BouncyCastleAesBytesEncryptorEquivalencyTests { CryptoAssumptions.assumeGCMJCE(); BytesEncryptor bcEncryptor = new BouncyCastleAesGcmBytesEncryptor(password, salt, KeyGenerators.secureRandom(16)); - BytesEncryptor jceEncryptor = new AesBytesEncryptor(password, salt, - KeyGenerators.secureRandom(16), CipherAlgorithm.GCM); + BytesEncryptor jceEncryptor = new AesBytesEncryptor(password, salt, KeyGenerators.secureRandom(16), + CipherAlgorithm.GCM); testCompatibility(bcEncryptor, jceEncryptor); } diff --git a/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorTests.java b/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorTests.java index f4bd049c33..ff188a3561 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/encrypt/BouncyCastleAesBytesEncryptorTests.java @@ -28,7 +28,9 @@ import org.springframework.security.crypto.keygen.KeyGenerators; public class BouncyCastleAesBytesEncryptorTests { private byte[] testData; + private String password; + private String salt; @Before @@ -67,13 +69,12 @@ public class BouncyCastleAesBytesEncryptorTests { @Test(expected = IllegalArgumentException.class) public void bcCbcWithWrongLengthIv() { - new BouncyCastleAesCbcBytesEncryptor(password, salt, - KeyGenerators.secureRandom(8)); + new BouncyCastleAesCbcBytesEncryptor(password, salt, KeyGenerators.secureRandom(8)); } @Test(expected = IllegalArgumentException.class) public void bcGcmWithWrongLengthIv() { - new BouncyCastleAesGcmBytesEncryptor(password, salt, - KeyGenerators.secureRandom(8)); + new BouncyCastleAesGcmBytesEncryptor(password, salt, KeyGenerators.secureRandom(8)); } + } diff --git a/crypto/src/test/java/org/springframework/security/crypto/encrypt/CryptoAssumptions.java b/crypto/src/test/java/org/springframework/security/crypto/encrypt/CryptoAssumptions.java index 188e61385e..efa4c0eff1 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/encrypt/CryptoAssumptions.java +++ b/crypto/src/test/java/org/springframework/security/crypto/encrypt/CryptoAssumptions.java @@ -41,16 +41,12 @@ public class CryptoAssumptions { aes256Available = Cipher.getMaxAllowedKeyLength("AES") >= 256; } catch (NoSuchAlgorithmException e) { - throw new AssumptionViolatedException( - cipherAlgorithm + " not available, skipping test", e); + throw new AssumptionViolatedException(cipherAlgorithm + " not available, skipping test", e); } catch (NoSuchPaddingException e) { - throw new AssumptionViolatedException( - cipherAlgorithm + " padding not available, skipping test", e); + throw new AssumptionViolatedException(cipherAlgorithm + " padding not available, skipping test", e); } - Assume.assumeTrue( - "AES key length of 256 not allowed, skipping test", - aes256Available); + Assume.assumeTrue("AES key length of 256 not allowed, skipping test", aes256Available); } diff --git a/crypto/src/test/java/org/springframework/security/crypto/encrypt/EncryptorsTests.java b/crypto/src/test/java/org/springframework/security/crypto/encrypt/EncryptorsTests.java index d0c69da5ae..9b6a4ed3ed 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/encrypt/EncryptorsTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/encrypt/EncryptorsTests.java @@ -29,8 +29,7 @@ public class EncryptorsTests { assertThat(result).isNotNull(); assertThat(new String(result).equals("text")).isFalse(); assertThat(new String(encryptor.decrypt(result))).isEqualTo("text"); - assertThat(new String(result)).isNotEqualTo( - new String(encryptor.encrypt("text".getBytes()))); + assertThat(new String(result)).isNotEqualTo(new String(encryptor.encrypt("text".getBytes()))); } @Test @@ -41,8 +40,7 @@ public class EncryptorsTests { assertThat(result).isNotNull(); assertThat(new String(result).equals("text")).isFalse(); assertThat(new String(encryptor.decrypt(result))).isEqualTo("text"); - assertThat(new String(result)).isNotEqualTo( - new String(encryptor.encrypt("text".getBytes()))); + assertThat(new String(result)).isNotEqualTo(new String(encryptor.encrypt("text".getBytes()))); } @Test @@ -70,8 +68,7 @@ public class EncryptorsTests { @Test public void queryableText() { CryptoAssumptions.assumeCBCJCE(); - TextEncryptor encryptor = Encryptors.queryableText("password", - "5c0744940b5c369b"); + TextEncryptor encryptor = Encryptors.queryableText("password", "5c0744940b5c369b"); String result = encryptor.encrypt("text"); assertThat(result).isNotNull(); assertThat(result.equals("text")).isFalse(); diff --git a/crypto/src/test/java/org/springframework/security/crypto/factory/PasswordEncoderFactoriesTests.java b/crypto/src/test/java/org/springframework/security/crypto/factory/PasswordEncoderFactoriesTests.java index f11207784a..3df9d34563 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/factory/PasswordEncoderFactoriesTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/factory/PasswordEncoderFactoriesTests.java @@ -26,6 +26,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @since 5.0 */ public class PasswordEncoderFactoriesTests { + private PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); private String rawPassword = "password"; diff --git a/crypto/src/test/java/org/springframework/security/crypto/keygen/Base64StringKeyGeneratorTests.java b/crypto/src/test/java/org/springframework/security/crypto/keygen/Base64StringKeyGeneratorTests.java index 951622f2da..026c4398b0 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/keygen/Base64StringKeyGeneratorTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/keygen/Base64StringKeyGeneratorTests.java @@ -27,6 +27,7 @@ import static org.assertj.core.api.Assertions.*; * @since 5.0 */ public class Base64StringKeyGeneratorTests { + @Test(expected = IllegalArgumentException.class) public void constructorIntWhenLessThan32ThenIllegalArgumentException() { new Base64StringKeyGenerator(31); @@ -63,4 +64,5 @@ public class Base64StringKeyGeneratorTests { String result = new Base64StringKeyGenerator(Base64.getUrlEncoder(), size).generateKey(); assertThat(Base64.getUrlDecoder().decode(result.getBytes())).hasSize(size); } + } diff --git a/crypto/src/test/java/org/springframework/security/crypto/password/DelegatingPasswordEncoderTests.java b/crypto/src/test/java/org/springframework/security/crypto/password/DelegatingPasswordEncoderTests.java index 8bca684658..5274531101 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/password/DelegatingPasswordEncoderTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/password/DelegatingPasswordEncoderTests.java @@ -40,6 +40,7 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class DelegatingPasswordEncoderTests { + @Mock private PasswordEncoder bcrypt; @@ -128,8 +129,8 @@ public class DelegatingPasswordEncoderTests { @Test public void matchesWhenUnMappedThenIllegalArgumentException() { assertThatThrownBy(() -> this.passwordEncoder.matches(this.rawPassword, "{unmapped}" + this.rawPassword)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("There is no PasswordEncoder mapped for the id \"unmapped\""); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("There is no PasswordEncoder mapped for the id \"unmapped\""); verifyZeroInteractions(this.bcrypt, this.noop); } @@ -137,8 +138,8 @@ public class DelegatingPasswordEncoderTests { @Test public void matchesWhenNoClosingPrefixStringThenIllegalArgumentExcetion() { assertThatThrownBy(() -> this.passwordEncoder.matches(this.rawPassword, "{bcrypt" + this.rawPassword)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("There is no PasswordEncoder mapped for the id \"null\""); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("There is no PasswordEncoder mapped for the id \"null\""); verifyZeroInteractions(this.bcrypt, this.noop); } @@ -146,8 +147,8 @@ public class DelegatingPasswordEncoderTests { @Test public void matchesWhenNoStartingPrefixStringThenFalse() { assertThatThrownBy(() -> this.passwordEncoder.matches(this.rawPassword, "bcrypt}" + this.rawPassword)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("There is no PasswordEncoder mapped for the id \"null\""); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("There is no PasswordEncoder mapped for the id \"null\""); verifyZeroInteractions(this.bcrypt, this.noop); } @@ -155,8 +156,8 @@ public class DelegatingPasswordEncoderTests { @Test public void matchesWhenNoIdStringThenFalse() { assertThatThrownBy(() -> this.passwordEncoder.matches(this.rawPassword, "{}" + this.rawPassword)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("There is no PasswordEncoder mapped for the id \"\""); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("There is no PasswordEncoder mapped for the id \"\""); verifyZeroInteractions(this.bcrypt, this.noop); } @@ -164,8 +165,8 @@ public class DelegatingPasswordEncoderTests { @Test public void matchesWhenPrefixInMiddleThenFalse() { assertThatThrownBy(() -> this.passwordEncoder.matches(this.rawPassword, "invalid" + this.bcryptEncodedPassword)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("There is no PasswordEncoder mapped for the id \"null\""); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("There is no PasswordEncoder mapped for the id \"null\""); verifyZeroInteractions(this.bcrypt, this.noop); } @@ -177,8 +178,8 @@ public class DelegatingPasswordEncoderTests { DelegatingPasswordEncoder passwordEncoder = new DelegatingPasswordEncoder(this.bcryptId, this.delegates); assertThatThrownBy(() -> passwordEncoder.matches(this.rawPassword, this.rawPassword)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("There is no PasswordEncoder mapped for the id \"null\""); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("There is no PasswordEncoder mapped for the id \"null\""); verifyZeroInteractions(this.bcrypt, this.noop); } @@ -212,7 +213,7 @@ public class DelegatingPasswordEncoderTests { @Test public void upgradeEncodingWhenIdInvalidFormatThenTrue() { - assertThat(this.passwordEncoder.upgradeEncoding("{bcrypt"+ this.encodedPassword)).isTrue(); + assertThat(this.passwordEncoder.upgradeEncoding("{bcrypt" + this.encodedPassword)).isTrue(); } @Test @@ -237,4 +238,5 @@ public class DelegatingPasswordEncoderTests { verifyZeroInteractions(bcrypt); } + } diff --git a/crypto/src/test/java/org/springframework/security/crypto/password/LdapShaPasswordEncoderTests.java b/crypto/src/test/java/org/springframework/security/crypto/password/LdapShaPasswordEncoderTests.java index 36e900aabf..37c20b8956 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/password/LdapShaPasswordEncoderTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/password/LdapShaPasswordEncoderTests.java @@ -28,6 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat; */ @SuppressWarnings("deprecation") public class LdapShaPasswordEncoderTests { + // ~ Instance fields // ================================================================================================ @@ -109,4 +110,5 @@ public class LdapShaPasswordEncoderTests { // No right brace this.sha.matches("somepassword", "{SSHA25ro4PKC8jhQZ26jVsozhX/xaP0suHgX"); } + } diff --git a/crypto/src/test/java/org/springframework/security/crypto/password/Md4PasswordEncoderTests.java b/crypto/src/test/java/org/springframework/security/crypto/password/Md4PasswordEncoderTests.java index 4a4d9fe3f8..b3b4d2e09b 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/password/Md4PasswordEncoderTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/password/Md4PasswordEncoderTests.java @@ -16,7 +16,6 @@ package org.springframework.security.crypto.password; - import static org.assertj.core.api.Assertions.assertThat; import org.junit.Test; @@ -72,5 +71,5 @@ public class Md4PasswordEncoderTests { Md4PasswordEncoder encoder = new Md4PasswordEncoder(); assertThat(encoder.matches("password", "{thisissalt}6cc7924dad12ade79dfb99e424f25260")); } -} +} diff --git a/crypto/src/test/java/org/springframework/security/crypto/password/MessageDigestPasswordEncoderTests.java b/crypto/src/test/java/org/springframework/security/crypto/password/MessageDigestPasswordEncoderTests.java index 60d3001959..7e62c413fc 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/password/MessageDigestPasswordEncoderTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/password/MessageDigestPasswordEncoderTests.java @@ -32,6 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat; */ @SuppressWarnings("deprecation") public class MessageDigestPasswordEncoderTests { + // ~ Methods // ======================================================================================================== @@ -39,7 +40,7 @@ public class MessageDigestPasswordEncoderTests { public void md5BasicFunctionality() { MessageDigestPasswordEncoder pe = new MessageDigestPasswordEncoder("MD5"); String raw = "abc123"; - assertThat(pe.matches( raw, "{THIS_IS_A_SALT}a68aafd90299d0b137de28fb4bb68573")).isTrue(); + assertThat(pe.matches(raw, "{THIS_IS_A_SALT}a68aafd90299d0b137de28fb4bb68573")).isTrue(); } @Test @@ -119,4 +120,5 @@ public class MessageDigestPasswordEncoderTests { public void testInvalidStrength() { new MessageDigestPasswordEncoder("SHA-666"); } + } diff --git a/crypto/src/test/java/org/springframework/security/crypto/password/PasswordEncoderUtilsTests.java b/crypto/src/test/java/org/springframework/security/crypto/password/PasswordEncoderUtilsTests.java index 183bb1f088..99dd6a997f 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/password/PasswordEncoderUtilsTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/password/PasswordEncoderUtilsTests.java @@ -67,4 +67,5 @@ public class PasswordEncoderUtilsTests { public void equalsWhenSameThenTrue() { assertThat(PasswordEncoderUtils.equals("abcdef", "abcdef")).isTrue(); } + } diff --git a/crypto/src/test/java/org/springframework/security/crypto/password/Pbkdf2PasswordEncoderTests.java b/crypto/src/test/java/org/springframework/security/crypto/password/Pbkdf2PasswordEncoderTests.java index 51a499ebaf..00109b174d 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/password/Pbkdf2PasswordEncoderTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/password/Pbkdf2PasswordEncoderTests.java @@ -25,6 +25,7 @@ import org.springframework.security.crypto.keygen.KeyGenerators; import static org.assertj.core.api.Assertions.assertThat; public class Pbkdf2PasswordEncoderTests { + private Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder("secret"); @Test @@ -37,8 +38,7 @@ public class Pbkdf2PasswordEncoderTests { @Test public void matchesLengthChecked() { String result = this.encoder.encode("password"); - assertThat(this.encoder.matches("password", - result.substring(0, result.length() - 2))).isFalse(); + assertThat(this.encoder.matches("password", result.substring(0, result.length() - 2))).isFalse(); } @Test @@ -68,8 +68,7 @@ public class Pbkdf2PasswordEncoderTests { String encodedPassword = "ab1146a8458d4ce4e65789e5a3f60e423373cfa10b01abd23739e5ae2fdc37f8e9ede4ae6da65264"; String originalEncodedPassword = "ab1146a8458d4ce4ab1146a8458d4ce4e65789e5a3f60e423373cfa10b01abd23739e5ae2fdc37f8e9ede4ae6da65264"; byte[] originalBytes = Hex.decode(originalEncodedPassword); - byte[] fixedBytes = Arrays.copyOfRange(originalBytes, saltLength, - originalBytes.length); + byte[] fixedBytes = Arrays.copyOfRange(originalBytes, saltLength, originalBytes.length); String fixedHex = String.valueOf(Hex.encode(fixedBytes)); assertThat(fixedHex).isEqualTo(encodedPassword); @@ -91,7 +90,8 @@ public class Pbkdf2PasswordEncoderTests { String encodedPassword = "3FOwOMcDgxP+z1x/sv184LFY2WVD+ZGMgYP3LPOSmCcDmk1XPYvcCQ=="; assertThat(this.encoder.matches(rawPassword, encodedPassword)).isTrue(); - java.util.Base64.getDecoder().decode(encodedPassword); // validate can decode as Base64 + java.util.Base64.getDecoder().decode(encodedPassword); // validate can decode as + // Base64 } @Test @@ -111,6 +111,7 @@ public class Pbkdf2PasswordEncoderTests { String encodedPassword = "821447f994e2b04c5014e31fa9fca4ae1cc9f2188c4ed53d3ddb5ba7980982b51a0ecebfc0b81a79"; assertThat(this.encoder.matches(rawPassword, encodedPassword)).isTrue(); } + /** * Used to find the iteration count that takes .5 seconds. */ @@ -126,8 +127,7 @@ public class Pbkdf2PasswordEncoderTests { long avg = 0; while (avg < HALF_SECOND) { iterations += 10000; - Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder("", iterations, - 256); + Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder("", iterations, 256); String encoded = encoder.encode("password"); System.out.println("Trying " + iterations); long start = System.currentTimeMillis(); @@ -141,4 +141,5 @@ public class Pbkdf2PasswordEncoderTests { } System.out.println("Iterations " + iterations); } + } diff --git a/crypto/src/test/java/org/springframework/security/crypto/scrypt/SCryptPasswordEncoderTests.java b/crypto/src/test/java/org/springframework/security/crypto/scrypt/SCryptPasswordEncoderTests.java index 5ac30814bc..0bbaea7f68 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/scrypt/SCryptPasswordEncoderTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/scrypt/SCryptPasswordEncoderTests.java @@ -161,5 +161,5 @@ public class SCryptPasswordEncoderTests { public void upgradeEncodingWhenInvalidInputThenException() { new SCryptPasswordEncoder().upgradeEncoding("not-a-scrypt-password"); } -} +} diff --git a/crypto/src/test/java/org/springframework/security/crypto/util/EncodingUtilsTests.java b/crypto/src/test/java/org/springframework/security/crypto/util/EncodingUtilsTests.java index 3c6fe20f87..d05f6231c5 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/util/EncodingUtilsTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/util/EncodingUtilsTests.java @@ -26,35 +26,34 @@ public class EncodingUtilsTests { @Test public void hexEncode() { - byte[] bytes = new byte[] { (byte) 0x01, (byte) 0xFF, (byte) 65, (byte) 66, - (byte) 67, (byte) 0xC0, (byte) 0xC1, (byte) 0xC2 }; + byte[] bytes = new byte[] { (byte) 0x01, (byte) 0xFF, (byte) 65, (byte) 66, (byte) 67, (byte) 0xC0, (byte) 0xC1, + (byte) 0xC2 }; String result = new String(Hex.encode(bytes)); assertThat(result).isEqualTo("01ff414243c0c1c2"); } @Test public void hexDecode() { - byte[] bytes = new byte[] { (byte) 0x01, (byte) 0xFF, (byte) 65, (byte) 66, - (byte) 67, (byte) 0xC0, (byte) 0xC1, (byte) 0xC2 }; + byte[] bytes = new byte[] { (byte) 0x01, (byte) 0xFF, (byte) 65, (byte) 66, (byte) 67, (byte) 0xC0, (byte) 0xC1, + (byte) 0xC2 }; byte[] result = Hex.decode("01ff414243c0c1c2"); assertThat(Arrays.equals(bytes, result)).isTrue(); } @Test public void concatenate() { - byte[] bytes = new byte[] { (byte) 0x01, (byte) 0xFF, (byte) 65, (byte) 66, - (byte) 67, (byte) 0xC0, (byte) 0xC1, (byte) 0xC2 }; + byte[] bytes = new byte[] { (byte) 0x01, (byte) 0xFF, (byte) 65, (byte) 66, (byte) 67, (byte) 0xC0, (byte) 0xC1, + (byte) 0xC2 }; byte[] one = new byte[] { (byte) 0x01 }; byte[] two = new byte[] { (byte) 0xFF, (byte) 65, (byte) 66 }; byte[] three = new byte[] { (byte) 67, (byte) 0xC0, (byte) 0xC1, (byte) 0xC2 }; - assertThat(Arrays.equals(bytes, - EncodingUtils.concatenate(one, two, three))).isTrue(); + assertThat(Arrays.equals(bytes, EncodingUtils.concatenate(one, two, three))).isTrue(); } @Test public void subArray() { - byte[] bytes = new byte[] { (byte) 0x01, (byte) 0xFF, (byte) 65, (byte) 66, - (byte) 67, (byte) 0xC0, (byte) 0xC1, (byte) 0xC2 }; + byte[] bytes = new byte[] { (byte) 0x01, (byte) 0xFF, (byte) 65, (byte) 66, (byte) 67, (byte) 0xC0, (byte) 0xC1, + (byte) 0xC2 }; byte[] two = new byte[] { (byte) 0xFF, (byte) 65, (byte) 66 }; byte[] subArray = EncodingUtils.subArray(bytes, 1, 4); assertThat(subArray).hasSize(3); diff --git a/data/src/main/java/org/springframework/security/data/repository/query/SecurityEvaluationContextExtension.java b/data/src/main/java/org/springframework/security/data/repository/query/SecurityEvaluationContextExtension.java index 936ccf6f25..6840537f3e 100644 --- a/data/src/main/java/org/springframework/security/data/repository/query/SecurityEvaluationContextExtension.java +++ b/data/src/main/java/org/springframework/security/data/repository/query/SecurityEvaluationContextExtension.java @@ -78,8 +78,8 @@ import org.springframework.security.core.context.SecurityContextHolder; * @since 4.0 * @author Rob Winch */ -public class SecurityEvaluationContextExtension - implements EvaluationContextExtension { +public class SecurityEvaluationContextExtension implements EvaluationContextExtension { + private Authentication authentication; /** @@ -91,7 +91,6 @@ public class SecurityEvaluationContextExtension /** * Creates a new instance that always uses the same {@link Authentication} object. - * * @param authentication the {@link Authentication} to use */ public SecurityEvaluationContextExtension(Authentication authentication) { @@ -117,4 +116,5 @@ public class SecurityEvaluationContextExtension SecurityContext context = SecurityContextHolder.getContext(); return context.getAuthentication(); } + } diff --git a/data/src/test/java/org/springframework/security/data/repository/query/SecurityEvaluationContextExtensionTests.java b/data/src/test/java/org/springframework/security/data/repository/query/SecurityEvaluationContextExtensionTests.java index 2efcb97c7f..b5193f8396 100644 --- a/data/src/test/java/org/springframework/security/data/repository/query/SecurityEvaluationContextExtensionTests.java +++ b/data/src/test/java/org/springframework/security/data/repository/query/SecurityEvaluationContextExtensionTests.java @@ -25,6 +25,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import static org.assertj.core.api.Assertions.assertThat; public class SecurityEvaluationContextExtensionTests { + SecurityEvaluationContextExtension securityExtension; @Before @@ -44,8 +45,7 @@ public class SecurityEvaluationContextExtensionTests { @Test public void getRootObjectSecurityContextHolderAuthentication() { - TestingAuthenticationToken authentication = new TestingAuthenticationToken( - "user", "password", "ROLE_USER"); + TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "password", "ROLE_USER"); SecurityContextHolder.getContext().setAuthentication(authentication); assertThat(getRoot().getAuthentication()).isSameAs(authentication); @@ -53,12 +53,10 @@ public class SecurityEvaluationContextExtensionTests { @Test public void getRootObjectExplicitAuthenticationOverridesSecurityContextHolder() { - TestingAuthenticationToken explicit = new TestingAuthenticationToken("explicit", - "password", "ROLE_EXPLICIT"); + TestingAuthenticationToken explicit = new TestingAuthenticationToken("explicit", "password", "ROLE_EXPLICIT"); securityExtension = new SecurityEvaluationContextExtension(explicit); - TestingAuthenticationToken authentication = new TestingAuthenticationToken( - "user", "password", "ROLE_USER"); + TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "password", "ROLE_USER"); SecurityContextHolder.getContext().setAuthentication(authentication); assertThat(getRoot().getAuthentication()).isSameAs(explicit); @@ -66,8 +64,7 @@ public class SecurityEvaluationContextExtensionTests { @Test public void getRootObjectExplicitAuthentication() { - TestingAuthenticationToken explicit = new TestingAuthenticationToken("explicit", - "password", "ROLE_EXPLICIT"); + TestingAuthenticationToken explicit = new TestingAuthenticationToken("explicit", "password", "ROLE_EXPLICIT"); securityExtension = new SecurityEvaluationContextExtension(explicit); assertThat(getRoot().getAuthentication()).isSameAs(explicit); @@ -76,4 +73,5 @@ public class SecurityEvaluationContextExtensionTests { private SecurityExpressionRoot getRoot() { return (SecurityExpressionRoot) securityExtension.getRootObject(); } + } \ No newline at end of file diff --git a/itest/context/src/integration-test/java/org/springframework/security/integration/HttpNamespaceWithMultipleInterceptorsTests.java b/itest/context/src/integration-test/java/org/springframework/security/integration/HttpNamespaceWithMultipleInterceptorsTests.java index ecf8f79605..14cc63380e 100644 --- a/itest/context/src/integration-test/java/org/springframework/security/integration/HttpNamespaceWithMultipleInterceptorsTests.java +++ b/itest/context/src/integration-test/java/org/springframework/security/integration/HttpNamespaceWithMultipleInterceptorsTests.java @@ -65,10 +65,9 @@ public class HttpNamespaceWithMultipleInterceptorsTests { public HttpSession createAuthenticatedSession(String... roles) { MockHttpSession session = new MockHttpSession(); - SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken("bob", "bobspassword", roles)); - session.setAttribute( - HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("bob", "bobspassword", roles)); + session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext()); SecurityContextHolder.clearContext(); return session; diff --git a/itest/context/src/integration-test/java/org/springframework/security/integration/HttpPathParameterStrippingTests.java b/itest/context/src/integration-test/java/org/springframework/security/integration/HttpPathParameterStrippingTests.java index 79d1f2c4e7..40b13468cd 100644 --- a/itest/context/src/integration-test/java/org/springframework/security/integration/HttpPathParameterStrippingTests.java +++ b/itest/context/src/integration-test/java/org/springframework/security/integration/HttpPathParameterStrippingTests.java @@ -42,8 +42,7 @@ public class HttpPathParameterStrippingTests { private FilterChainProxy fcp; @Test(expected = RequestRejectedException.class) - public void securedFilterChainCannotBeBypassedByAddingPathParameters() - throws Exception { + public void securedFilterChainCannotBeBypassedByAddingPathParameters() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.setPathInfo("/secured;x=y/admin.html"); request.setSession(createAuthenticatedSession("ROLE_USER")); @@ -60,7 +59,6 @@ public class HttpPathParameterStrippingTests { fcp.doFilter(request, response, new MockFilterChain()); } - @Test(expected = RequestRejectedException.class) public void adminFilePatternCannotBeBypassedByAddingPathParametersWithPathInfo() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); @@ -74,10 +72,9 @@ public class HttpPathParameterStrippingTests { public HttpSession createAuthenticatedSession(String... roles) { MockHttpSession session = new MockHttpSession(); - SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken("bob", "bobspassword", roles)); - session.setAttribute( - HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken("bob", "bobspassword", roles)); + session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext()); SecurityContextHolder.clearContext(); return session; diff --git a/itest/context/src/integration-test/java/org/springframework/security/integration/MultiAnnotationTests.java b/itest/context/src/integration-test/java/org/springframework/security/integration/MultiAnnotationTests.java index 724790c65a..0a21e9b59a 100644 --- a/itest/context/src/integration-test/java/org/springframework/security/integration/MultiAnnotationTests.java +++ b/itest/context/src/integration-test/java/org/springframework/security/integration/MultiAnnotationTests.java @@ -35,15 +35,17 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration(locations = { "/multi-sec-annotation-app-context.xml" }) @RunWith(SpringJUnit4ClassRunner.class) public class MultiAnnotationTests { - private final TestingAuthenticationToken joe_a = new TestingAuthenticationToken( - "joe", "pass", "ROLE_A"); - private final TestingAuthenticationToken joe_b = new TestingAuthenticationToken( - "joe", "pass", "ROLE_B"); + + private final TestingAuthenticationToken joe_a = new TestingAuthenticationToken("joe", "pass", "ROLE_A"); + + private final TestingAuthenticationToken joe_b = new TestingAuthenticationToken("joe", "pass", "ROLE_B"); @Autowired MultiAnnotationService service; + @Autowired PreAuthorizeService preService; + @Autowired SecuredService secService; @@ -100,4 +102,5 @@ public class MultiAnnotationTests { SecurityContextHolder.getContext().setAuthentication(joe_b); secService.securedMethod(); } + } diff --git a/itest/context/src/integration-test/java/org/springframework/security/integration/SEC933ApplicationContextTests.java b/itest/context/src/integration-test/java/org/springframework/security/integration/SEC933ApplicationContextTests.java index 00c4fc62e2..ec32100369 100644 --- a/itest/context/src/integration-test/java/org/springframework/security/integration/SEC933ApplicationContextTests.java +++ b/itest/context/src/integration-test/java/org/springframework/security/integration/SEC933ApplicationContextTests.java @@ -35,4 +35,5 @@ public class SEC933ApplicationContextTests { public void testSimpleApplicationContextBootstrap() { assertThat(userDetailsService).isNotNull(); } + } diff --git a/itest/context/src/integration-test/java/org/springframework/security/integration/SEC936ApplicationContextTests.java b/itest/context/src/integration-test/java/org/springframework/security/integration/SEC936ApplicationContextTests.java index 861a98139d..24272de1c7 100644 --- a/itest/context/src/integration-test/java/org/springframework/security/integration/SEC936ApplicationContextTests.java +++ b/itest/context/src/integration-test/java/org/springframework/security/integration/SEC936ApplicationContextTests.java @@ -32,14 +32,17 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration(locations = { "/sec-936-app-context.xml" }) @RunWith(SpringJUnit4ClassRunner.class) public class SEC936ApplicationContextTests { + @Autowired - /** SessionRegistry is used as the test service interface (nothing to do with the test) */ + /** + * SessionRegistry is used as the test service interface (nothing to do with the test) + */ private SessionRegistry sessionRegistry; @Test(expected = AccessDeniedException.class) public void securityInterceptorHandlesCallWithNoTargetObject() { - SecurityContextHolder.getContext().setAuthentication( - new UsernamePasswordAuthenticationToken("bob", "bobspassword")); + SecurityContextHolder.getContext() + .setAuthentication(new UsernamePasswordAuthenticationToken("bob", "bobspassword")); sessionRegistry.getAllPrincipals(); } diff --git a/itest/context/src/integration-test/java/org/springframework/security/integration/StubUserRepository.java b/itest/context/src/integration-test/java/org/springframework/security/integration/StubUserRepository.java index 099fe44f09..8d272048b9 100644 --- a/itest/context/src/integration-test/java/org/springframework/security/integration/StubUserRepository.java +++ b/itest/context/src/integration-test/java/org/springframework/security/integration/StubUserRepository.java @@ -19,4 +19,5 @@ public class StubUserRepository implements UserRepository { public void doSomething() { } + } \ No newline at end of file diff --git a/itest/context/src/integration-test/java/org/springframework/security/integration/python/PythonInterpreterBasedSecurityTests.java b/itest/context/src/integration-test/java/org/springframework/security/integration/python/PythonInterpreterBasedSecurityTests.java index df288f1f4e..44d7f19b25 100644 --- a/itest/context/src/integration-test/java/org/springframework/security/integration/python/PythonInterpreterBasedSecurityTests.java +++ b/itest/context/src/integration-test/java/org/springframework/security/integration/python/PythonInterpreterBasedSecurityTests.java @@ -32,11 +32,12 @@ public class PythonInterpreterBasedSecurityTests { @Test public void serviceMethod() { - SecurityContextHolder.getContext().setAuthentication( - new UsernamePasswordAuthenticationToken("bob", "bobspassword")); + SecurityContextHolder.getContext() + .setAuthentication(new UsernamePasswordAuthenticationToken("bob", "bobspassword")); // for (int i=0; i < 1000; i++) { service.someMethod(); // } } + } diff --git a/itest/context/src/integration-test/java/org/springframework/security/performance/FilterChainPerformanceTests.java b/itest/context/src/integration-test/java/org/springframework/security/performance/FilterChainPerformanceTests.java index 9155ef1794..406d2f2d52 100644 --- a/itest/context/src/integration-test/java/org/springframework/security/performance/FilterChainPerformanceTests.java +++ b/itest/context/src/integration-test/java/org/springframework/security/performance/FilterChainPerformanceTests.java @@ -37,20 +37,23 @@ import javax.servlet.http.HttpSession; import java.util.*; /** - * * @author Luke Taylor * @since 2.0 */ @ContextConfiguration(locations = { "/filter-chain-performance-app-context.xml" }) @RunWith(SpringJUnit4ClassRunner.class) public class FilterChainPerformanceTests { + // Adjust as required private static final int N_INVOCATIONS = 1; // 1000 + private static final int N_AUTHORITIES = 2; // 200 + private static StopWatch sw = new StopWatch("Filter Chain Performance Tests"); - private final UsernamePasswordAuthenticationToken user = new UsernamePasswordAuthenticationToken( - "bob", "bobspassword", createRoles(N_AUTHORITIES)); + private final UsernamePasswordAuthenticationToken user = new UsernamePasswordAuthenticationToken("bob", + "bobspassword", createRoles(N_AUTHORITIES)); + private HttpSession session; @Autowired @@ -65,8 +68,7 @@ public class FilterChainPerformanceTests { public void createAuthenticatedSession() { session = new MockHttpSession(); SecurityContextHolder.getContext().setAuthentication(user); - session.setAttribute( - HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, + session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext()); SecurityContextHolder.clearContext(); } @@ -121,10 +123,8 @@ public class FilterChainPerformanceTests { for (int user = 0; user < N_AUTHORITIES / 10; user++) { int nAuthorities = user == 0 ? 1 : user * 10; SecurityContextHolder.getContext().setAuthentication( - new UsernamePasswordAuthenticationToken("bob", "bobspassword", - createRoles(nAuthorities))); - session.setAttribute( - HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, + new UsernamePasswordAuthenticationToken("bob", "bobspassword", createRoles(nAuthorities))); + session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext()); SecurityContextHolder.clearContext(); sw.start(nAuthorities + " authorities"); @@ -146,4 +146,5 @@ public class FilterChainPerformanceTests { return Arrays.asList(roles); } + } diff --git a/itest/context/src/integration-test/java/org/springframework/security/performance/ProtectPointcutPerformanceTests.java b/itest/context/src/integration-test/java/org/springframework/security/performance/ProtectPointcutPerformanceTests.java index 10a6d87e2c..9cc283202f 100644 --- a/itest/context/src/integration-test/java/org/springframework/security/performance/ProtectPointcutPerformanceTests.java +++ b/itest/context/src/integration-test/java/org/springframework/security/performance/ProtectPointcutPerformanceTests.java @@ -51,8 +51,7 @@ public class ProtectPointcutPerformanceTests implements ApplicationContextAware sw.start(); for (int i = 0; i < 1000; i++) { try { - SessionRegistry reg = (SessionRegistry) ctx.getBean( - "sessionRegistryPrototype"); + SessionRegistry reg = (SessionRegistry) ctx.getBean("sessionRegistryPrototype"); reg.getAllPrincipals(); fail("Expected AuthenticationCredentialsNotFoundException"); } @@ -64,8 +63,8 @@ public class ProtectPointcutPerformanceTests implements ApplicationContextAware } - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ctx = applicationContext; } + } diff --git a/itest/context/src/main/java/org/springframework/security/integration/UserDetailsServiceImpl.java b/itest/context/src/main/java/org/springframework/security/integration/UserDetailsServiceImpl.java index 8da64c0336..7aff3a25ba 100755 --- a/itest/context/src/main/java/org/springframework/security/integration/UserDetailsServiceImpl.java +++ b/itest/context/src/main/java/org/springframework/security/integration/UserDetailsServiceImpl.java @@ -34,4 +34,5 @@ public class UserDetailsServiceImpl implements UserDetailsService { public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } + } diff --git a/itest/context/src/main/java/org/springframework/security/integration/multiannotation/MultiAnnotationService.java b/itest/context/src/main/java/org/springframework/security/integration/multiannotation/MultiAnnotationService.java index 8e2bb8874d..6cb989c4aa 100644 --- a/itest/context/src/main/java/org/springframework/security/integration/multiannotation/MultiAnnotationService.java +++ b/itest/context/src/main/java/org/springframework/security/integration/multiannotation/MultiAnnotationService.java @@ -36,4 +36,5 @@ public interface MultiAnnotationService { @Secured("ROLE_A") void securedRoleAMethod(); + } diff --git a/itest/context/src/main/java/org/springframework/security/integration/multiannotation/PreAuthorizeService.java b/itest/context/src/main/java/org/springframework/security/integration/multiannotation/PreAuthorizeService.java index a12a0b4172..efe6264720 100644 --- a/itest/context/src/main/java/org/springframework/security/integration/multiannotation/PreAuthorizeService.java +++ b/itest/context/src/main/java/org/springframework/security/integration/multiannotation/PreAuthorizeService.java @@ -18,11 +18,11 @@ package org.springframework.security.integration.multiannotation; import org.springframework.security.access.prepost.PreAuthorize; /** - * * @author Luke Taylor */ public interface PreAuthorizeService { @PreAuthorize("hasRole('ROLE_A')") void preAuthorizedMethod(); + } diff --git a/itest/context/src/main/java/org/springframework/security/integration/multiannotation/PreAuthorizeServiceImpl.java b/itest/context/src/main/java/org/springframework/security/integration/multiannotation/PreAuthorizeServiceImpl.java index f8ff122e21..ff2b4c50b2 100644 --- a/itest/context/src/main/java/org/springframework/security/integration/multiannotation/PreAuthorizeServiceImpl.java +++ b/itest/context/src/main/java/org/springframework/security/integration/multiannotation/PreAuthorizeServiceImpl.java @@ -19,6 +19,8 @@ package org.springframework.security.integration.multiannotation; * @author Luke Taylor */ public class PreAuthorizeServiceImpl implements PreAuthorizeService { + public void preAuthorizedMethod() { } + } diff --git a/itest/context/src/main/java/org/springframework/security/integration/multiannotation/SecuredService.java b/itest/context/src/main/java/org/springframework/security/integration/multiannotation/SecuredService.java index ee5f36b6f3..d7bed1b697 100644 --- a/itest/context/src/main/java/org/springframework/security/integration/multiannotation/SecuredService.java +++ b/itest/context/src/main/java/org/springframework/security/integration/multiannotation/SecuredService.java @@ -18,10 +18,11 @@ package org.springframework.security.integration.multiannotation; import org.springframework.security.access.annotation.Secured; /** - * * @author Luke Taylor */ public interface SecuredService { + @Secured("ROLE_A") void securedMethod(); + } diff --git a/itest/context/src/main/java/org/springframework/security/integration/multiannotation/SecuredServiceImpl.java b/itest/context/src/main/java/org/springframework/security/integration/multiannotation/SecuredServiceImpl.java index d580b5867c..349f6da5d1 100644 --- a/itest/context/src/main/java/org/springframework/security/integration/multiannotation/SecuredServiceImpl.java +++ b/itest/context/src/main/java/org/springframework/security/integration/multiannotation/SecuredServiceImpl.java @@ -16,10 +16,11 @@ package org.springframework.security.integration.multiannotation; /** - * * @author Luke Taylor */ public class SecuredServiceImpl implements SecuredService { + public void securedMethod() { } + } diff --git a/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPostInvocationAdvice.java b/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPostInvocationAdvice.java index 7c180e5850..168a3f053b 100644 --- a/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPostInvocationAdvice.java +++ b/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPostInvocationAdvice.java @@ -21,12 +21,11 @@ import org.springframework.security.access.prepost.PostInvocationAttribute; import org.springframework.security.access.prepost.PostInvocationAuthorizationAdvice; import org.springframework.security.core.Authentication; -public class PythonInterpreterPostInvocationAdvice implements - PostInvocationAuthorizationAdvice { +public class PythonInterpreterPostInvocationAdvice implements PostInvocationAuthorizationAdvice { - public Object after(Authentication authentication, MethodInvocation mi, - PostInvocationAttribute pia, Object returnedObject) - throws AccessDeniedException { + public Object after(Authentication authentication, MethodInvocation mi, PostInvocationAttribute pia, + Object returnedObject) throws AccessDeniedException { return returnedObject; } + } diff --git a/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPreInvocationAdvice.java b/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPreInvocationAdvice.java index d72861f797..1ad4a6e78d 100644 --- a/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPreInvocationAdvice.java +++ b/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPreInvocationAdvice.java @@ -33,12 +33,11 @@ import org.springframework.security.access.prepost.PreInvocationAuthorizationAdv import org.springframework.security.core.Authentication; import org.springframework.util.ClassUtils; -public class PythonInterpreterPreInvocationAdvice implements - PreInvocationAuthorizationAdvice { +public class PythonInterpreterPreInvocationAdvice implements PreInvocationAuthorizationAdvice { + private final ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer(); - public boolean before(Authentication authentication, MethodInvocation mi, - PreInvocationAttribute preAttr) { + public boolean before(Authentication authentication, MethodInvocation mi, PreInvocationAttribute preAttr) { PythonInterpreterPreInvocationAttribute pythonAttr = (PythonInterpreterPreInvocationAttribute) preAttr; String script = pythonAttr.getScript(); @@ -46,8 +45,7 @@ public class PythonInterpreterPreInvocationAdvice implements python.set("authentication", authentication); python.set("args", createArgumentMap(mi)); python.set("method", mi.getMethod().getName()); - Resource scriptResource = new PathMatchingResourcePatternResolver() - .getResource(script); + Resource scriptResource = new PathMatchingResourcePatternResolver().getResource(script); try { python.execfile(scriptResource.getInputStream()); @@ -68,8 +66,7 @@ public class PythonInterpreterPreInvocationAdvice implements private Map createArgumentMap(MethodInvocation mi) { Object[] args = mi.getArguments(); Object targetObject = mi.getThis(); - Method method = ClassUtils.getMostSpecificMethod(mi.getMethod(), - targetObject.getClass()); + Method method = ClassUtils.getMostSpecificMethod(mi.getMethod(), targetObject.getClass()); String[] paramNames = parameterNameDiscoverer.getParameterNames(method); Map argMap = new HashMap<>(); @@ -79,4 +76,5 @@ public class PythonInterpreterPreInvocationAdvice implements return argMap; } + } diff --git a/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPreInvocationAttribute.java b/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPreInvocationAttribute.java index d033af1d4f..960a8475b8 100644 --- a/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPreInvocationAttribute.java +++ b/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPreInvocationAttribute.java @@ -18,6 +18,7 @@ package org.springframework.security.integration.python; import org.springframework.security.access.prepost.PreInvocationAttribute; public class PythonInterpreterPreInvocationAttribute implements PreInvocationAttribute { + private final String script; PythonInterpreterPreInvocationAttribute(String script) { @@ -31,4 +32,5 @@ public class PythonInterpreterPreInvocationAttribute implements PreInvocationAtt public String getScript() { return script; } + } diff --git a/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPrePostInvocationAttributeFactory.java b/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPrePostInvocationAttributeFactory.java index 84c11e94aa..d1997e7726 100644 --- a/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPrePostInvocationAttributeFactory.java +++ b/itest/context/src/main/java/org/springframework/security/integration/python/PythonInterpreterPrePostInvocationAttributeFactory.java @@ -20,20 +20,20 @@ import org.springframework.security.access.prepost.PostInvocationAttribute; import org.springframework.security.access.prepost.PreInvocationAttribute; import org.springframework.security.access.prepost.PrePostInvocationAttributeFactory; -public class PythonInterpreterPrePostInvocationAttributeFactory implements - PrePostInvocationAttributeFactory { +public class PythonInterpreterPrePostInvocationAttributeFactory implements PrePostInvocationAttributeFactory { public PythonInterpreterPrePostInvocationAttributeFactory() { PythonInterpreter.initialize(System.getProperties(), null, new String[] {}); } - public PreInvocationAttribute createPreInvocationAttribute(String preFilterAttribute, - String filterObject, String preAuthorizeAttribute) { + public PreInvocationAttribute createPreInvocationAttribute(String preFilterAttribute, String filterObject, + String preAuthorizeAttribute) { return new PythonInterpreterPreInvocationAttribute(preAuthorizeAttribute); } - public PostInvocationAttribute createPostInvocationAttribute( - String postFilterAttribute, String postAuthorizeAttribute) { + public PostInvocationAttribute createPostInvocationAttribute(String postFilterAttribute, + String postAuthorizeAttribute) { return null; } + } diff --git a/itest/web/src/integration-test/java/org/springframework/security/integration/AbstractWebServerIntegrationTests.java b/itest/web/src/integration-test/java/org/springframework/security/integration/AbstractWebServerIntegrationTests.java index 2d61b7ee89..f11648d9ee 100644 --- a/itest/web/src/integration-test/java/org/springframework/security/integration/AbstractWebServerIntegrationTests.java +++ b/itest/web/src/integration-test/java/org/springframework/security/integration/AbstractWebServerIntegrationTests.java @@ -33,6 +33,7 @@ import org.springframework.web.context.support.XmlWebApplicationContext; * @author Luke Taylor */ public abstract class AbstractWebServerIntegrationTests { + protected ConfigurableApplicationContext context; @After @@ -53,9 +54,7 @@ public abstract class AbstractWebServerIntegrationTests { context.refresh(); this.context = context; - return MockMvcBuilders - .webAppContextSetup(context) - .apply(springSecurity()) - .build(); + return MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build(); } + } diff --git a/itest/web/src/integration-test/java/org/springframework/security/integration/BasicAuthenticationTests.java b/itest/web/src/integration-test/java/org/springframework/security/integration/BasicAuthenticationTests.java index ddec15c81c..f1d71e48f8 100644 --- a/itest/web/src/integration-test/java/org/springframework/security/integration/BasicAuthenticationTests.java +++ b/itest/web/src/integration-test/java/org/springframework/security/integration/BasicAuthenticationTests.java @@ -28,17 +28,17 @@ public class BasicAuthenticationTests extends AbstractWebServerIntegrationTests @Test public void httpBasicWhenAuthenticationRequiredAndNotAuthenticatedThen401() throws Exception { - MockMvc mockMvc = createMockMvc("classpath:/spring/http-security-basic.xml", "classpath:/spring/in-memory-provider.xml", "classpath:/spring/testapp-servlet.xml"); - mockMvc.perform(get("/secure/index")) - .andExpect(status().isUnauthorized()); + MockMvc mockMvc = createMockMvc("classpath:/spring/http-security-basic.xml", + "classpath:/spring/in-memory-provider.xml", "classpath:/spring/testapp-servlet.xml"); + mockMvc.perform(get("/secure/index")).andExpect(status().isUnauthorized()); } @Test public void httpBasicWhenProvidedThen200() throws Exception { - MockMvc mockMvc = createMockMvc("classpath:/spring/http-security-basic.xml", "classpath:/spring/in-memory-provider.xml", "classpath:/spring/testapp-servlet.xml"); - MockHttpServletRequestBuilder request = get("/secure/index") - .with(httpBasic("johnc", "johncspassword")); - mockMvc.perform(request) - .andExpect(status().isOk()); + MockMvc mockMvc = createMockMvc("classpath:/spring/http-security-basic.xml", + "classpath:/spring/in-memory-provider.xml", "classpath:/spring/testapp-servlet.xml"); + MockHttpServletRequestBuilder request = get("/secure/index").with(httpBasic("johnc", "johncspassword")); + mockMvc.perform(request).andExpect(status().isOk()); } + } diff --git a/itest/web/src/integration-test/java/org/springframework/security/integration/ConcurrentSessionManagementTests.java b/itest/web/src/integration-test/java/org/springframework/security/integration/ConcurrentSessionManagementTests.java index bf6bb9153c..5a12ec245d 100644 --- a/itest/web/src/integration-test/java/org/springframework/security/integration/ConcurrentSessionManagementTests.java +++ b/itest/web/src/integration-test/java/org/springframework/security/integration/ConcurrentSessionManagementTests.java @@ -46,55 +46,44 @@ public class ConcurrentSessionManagementTests extends AbstractWebServerIntegrati final MockHttpSession session1 = new MockHttpSession(); final MockHttpSession session2 = new MockHttpSession(); - MockMvc mockMvc = createMockMvc("classpath:/spring/http-security-concurrency.xml", "classpath:/spring/in-memory-provider.xml", "classpath:/spring/testapp-servlet.xml"); + MockMvc mockMvc = createMockMvc("classpath:/spring/http-security-concurrency.xml", + "classpath:/spring/in-memory-provider.xml", "classpath:/spring/testapp-servlet.xml"); - mockMvc.perform(get("/secure/index").session(session1)) - .andExpect(status().is3xxRedirection()); + mockMvc.perform(get("/secure/index").session(session1)).andExpect(status().is3xxRedirection()); - MockHttpServletRequestBuilder login1 = login() - .session(session1); - mockMvc. - perform(login1) - .andExpect(authenticated().withUsername("jimi")); + MockHttpServletRequestBuilder login1 = login().session(session1); + mockMvc.perform(login1).andExpect(authenticated().withUsername("jimi")); - - MockHttpServletRequestBuilder login2 = login() - .session(session2); - mockMvc.perform(login2) - .andExpect(redirectedUrl("/login.jsp?login_error=true")); + MockHttpServletRequestBuilder login2 = login().session(session2); + mockMvc.perform(login2).andExpect(redirectedUrl("/login.jsp?login_error=true")); Exception exception = (Exception) session2.getAttribute("SPRING_SECURITY_LAST_EXCEPTION"); assertThat(exception).isNotNull(); assertThat(exception.getMessage()).contains("Maximum sessions of 1 for this principal exceeded"); // Now logout to kill first session - mockMvc.perform(post("/logout").with(csrf())) - .andExpect(status().is3xxRedirection()) - .andDo(result -> context.publishEvent(new SessionDestroyedEvent(session1) { - @Override - public List getSecurityContexts() { - return Collections.emptyList(); - } + mockMvc.perform(post("/logout").with(csrf())).andExpect(status().is3xxRedirection()) + .andDo(result -> context.publishEvent(new SessionDestroyedEvent(session1) { + @Override + public List getSecurityContexts() { + return Collections.emptyList(); + } - @Override - public String getId() { - return session1.getId(); - } - })); + @Override + public String getId() { + return session1.getId(); + } + })); // Try second session again - login2 = login() - .session(session2); - mockMvc.perform(login2) - .andExpect(authenticated().withUsername("jimi")); + login2 = login().session(session2); + mockMvc.perform(login2).andExpect(authenticated().withUsername("jimi")); mockMvc.perform(get("/secure/index").session(session2)) - .andExpect(content().string(containsString("A Secure Page"))); + .andExpect(content().string(containsString("A Secure Page"))); } private MockHttpServletRequestBuilder login() { - return post("/login") - .param("username", "jimi") - .param("password", "jimispassword") - .with(csrf()); + return post("/login").param("username", "jimi").param("password", "jimispassword").with(csrf()); } + } diff --git a/itest/web/src/main/java/org/springframework/security/itest/web/TestController.java b/itest/web/src/main/java/org/springframework/security/itest/web/TestController.java index 307ce68f6c..04381f890c 100644 --- a/itest/web/src/main/java/org/springframework/security/itest/web/TestController.java +++ b/itest/web/src/main/java/org/springframework/security/itest/web/TestController.java @@ -38,4 +38,5 @@ public class TestController { public String secure() { return "A Secure Page"; } + } diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/ApacheDsContainerConfig.java b/ldap/src/integration-test/java/org/springframework/security/ldap/ApacheDsContainerConfig.java index ec6cd0fc7a..42c7b2a74b 100644 --- a/ldap/src/integration-test/java/org/springframework/security/ldap/ApacheDsContainerConfig.java +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/ApacheDsContainerConfig.java @@ -32,16 +32,15 @@ public class ApacheDsContainerConfig { @Bean ApacheDSContainer ldapContainer() throws Exception { - this.container = new ApacheDSContainer("dc=springframework,dc=org", - "classpath:test-server.ldif"); + this.container = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif"); this.container.setPort(0); return this.container; } @Bean ContextSource contextSource(ApacheDSContainer ldapContainer) throws Exception { - return new DefaultSpringSecurityContextSource("ldap://127.0.0.1:" - + ldapContainer.getLocalPort() + "/dc=springframework,dc=org"); + return new DefaultSpringSecurityContextSource( + "ldap://127.0.0.1:" + ldapContainer.getLocalPort() + "/dc=springframework,dc=org"); } @PreDestroy diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/DefaultSpringSecurityContextSourceTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/DefaultSpringSecurityContextSourceTests.java index e2da339fcf..e993a200fe 100644 --- a/ldap/src/integration-test/java/org/springframework/security/ldap/DefaultSpringSecurityContextSourceTests.java +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/DefaultSpringSecurityContextSourceTests.java @@ -53,8 +53,7 @@ public class DefaultSpringSecurityContextSourceTests { @Test public void supportsSpacesInUrl() { - new DefaultSpringSecurityContextSource( - "ldap://myhost:10389/dc=spring%20framework,dc=org"); + new DefaultSpringSecurityContextSource("ldap://myhost:10389/dc=spring%20framework,dc=org"); } @Test @@ -64,8 +63,8 @@ public class DefaultSpringSecurityContextSourceTests { ctxSrc.setUserDn("manager"); ctxSrc.setPassword("password"); ctxSrc.afterPropertiesSet(); - assertThat(ctxSrc.getAuthenticatedEnvForTest("manager", "password")).containsKey( - AbstractContextSource.SUN_LDAP_POOLING_FLAG); + assertThat(ctxSrc.getAuthenticatedEnvForTest("manager", "password")) + .containsKey(AbstractContextSource.SUN_LDAP_POOLING_FLAG); } @Test @@ -75,18 +74,16 @@ public class DefaultSpringSecurityContextSourceTests { ctxSrc.setUserDn("manager"); ctxSrc.setPassword("password"); ctxSrc.afterPropertiesSet(); - assertThat(ctxSrc.getAuthenticatedEnvForTest("user", "password")).doesNotContainKey( - AbstractContextSource.SUN_LDAP_POOLING_FLAG); + assertThat(ctxSrc.getAuthenticatedEnvForTest("user", "password")) + .doesNotContainKey(AbstractContextSource.SUN_LDAP_POOLING_FLAG); } // SEC-1145. Confirms that there is no issue here with pooling. @Test(expected = AuthenticationException.class) - public void cantBindWithWrongPasswordImmediatelyAfterSuccessfulBind() - throws Exception { + public void cantBindWithWrongPasswordImmediatelyAfterSuccessfulBind() throws Exception { DirContext ctx = null; try { - ctx = this.contextSource.getContext( - "uid=Bob,ou=people,dc=springframework,dc=org", "bobspassword"); + ctx = this.contextSource.getContext("uid=Bob,ou=people,dc=springframework,dc=org", "bobspassword"); } catch (Exception e) { } @@ -95,27 +92,23 @@ public class DefaultSpringSecurityContextSourceTests { ctx.close(); // com.sun.jndi.ldap.LdapPoolManager.showStats(System.out); // Now get it gain, with wrong password. Should fail. - ctx = this.contextSource.getContext( - "uid=Bob,ou=people,dc=springframework,dc=org", "wrongpassword"); + ctx = this.contextSource.getContext("uid=Bob,ou=people,dc=springframework,dc=org", "wrongpassword"); ctx.close(); } @Test public void serverUrlWithSpacesIsSupported() { DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource( - this.contextSource.getUrls()[0] - + "ou=space%20cadets,dc=springframework,dc=org"); + this.contextSource.getUrls()[0] + "ou=space%20cadets,dc=springframework,dc=org"); contextSource.afterPropertiesSet(); - contextSource.getContext( - "uid=space cadet,ou=space cadets,dc=springframework,dc=org", - "spacecadetspassword"); + contextSource.getContext("uid=space cadet,ou=space cadets,dc=springframework,dc=org", "spacecadetspassword"); } @Test(expected = IllegalArgumentException.class) public void instantiationFailsWithEmptyServerList() { List serverUrls = new ArrayList<>(); - DefaultSpringSecurityContextSource ctxSrc = new DefaultSpringSecurityContextSource( - serverUrls, "dc=springframework,dc=org"); + DefaultSpringSecurityContextSource ctxSrc = new DefaultSpringSecurityContextSource(serverUrls, + "dc=springframework,dc=org"); ctxSrc.afterPropertiesSet(); } @@ -125,8 +118,8 @@ public class DefaultSpringSecurityContextSourceTests { serverUrls.add("ldap://foo:789"); serverUrls.add("ldap://bar:389"); serverUrls.add("ldaps://blah:636"); - DefaultSpringSecurityContextSource ctxSrc = new DefaultSpringSecurityContextSource( - serverUrls, "dc=springframework,dc=org"); + DefaultSpringSecurityContextSource ctxSrc = new DefaultSpringSecurityContextSource(serverUrls, + "dc=springframework,dc=org"); assertThat(ctxSrc.isAnonymousReadOnly()).isFalse(); assertThat(ctxSrc.isPooled()).isTrue(); @@ -140,8 +133,7 @@ public class DefaultSpringSecurityContextSourceTests { serverUrls.add("ldap://foo:789"); serverUrls.add("ldap://bar:389"); serverUrls.add("ldaps://blah:636"); - DefaultSpringSecurityContextSource ctxSrc = new DefaultSpringSecurityContextSource( - serverUrls, baseDn); + DefaultSpringSecurityContextSource ctxSrc = new DefaultSpringSecurityContextSource(serverUrls, baseDn); assertThat(ctxSrc.isAnonymousReadOnly()).isFalse(); assertThat(ctxSrc.isPooled()).isTrue(); @@ -154,12 +146,12 @@ public class DefaultSpringSecurityContextSourceTests { serverUrls.add("ldaps://blah:636/"); // this url should be rejected because the root DN goes into a separate parameter serverUrls.add("ldap://bar:389/dc=foobar,dc=org"); - DefaultSpringSecurityContextSource ctxSrc = new DefaultSpringSecurityContextSource( - serverUrls, "dc=springframework,dc=org"); + DefaultSpringSecurityContextSource ctxSrc = new DefaultSpringSecurityContextSource(serverUrls, + "dc=springframework,dc=org"); } - static class EnvExposingDefaultSpringSecurityContextSource extends - DefaultSpringSecurityContextSource { + static class EnvExposingDefaultSpringSecurityContextSource extends DefaultSpringSecurityContextSource { + EnvExposingDefaultSpringSecurityContextSource(String providerUrl) { super(providerUrl); } @@ -168,5 +160,7 @@ public class DefaultSpringSecurityContextSourceTests { Hashtable getAuthenticatedEnvForTest(String userDn, String password) { return getAuthenticatedEnv(userDn, password); } + } + } diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/SpringSecurityLdapTemplateITests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/SpringSecurityLdapTemplateITests.java index 697a9f9bfb..c4bfe8b50b 100644 --- a/ldap/src/integration-test/java/org/springframework/security/ldap/SpringSecurityLdapTemplateITests.java +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/SpringSecurityLdapTemplateITests.java @@ -45,11 +45,13 @@ import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @ContextConfiguration(classes = ApacheDsContainerConfig.class) public class SpringSecurityLdapTemplateITests { + // ~ Instance fields // ================================================================================================ @Autowired private DefaultSpringSecurityContextSource contextSource; + private SpringSecurityLdapTemplate template; // ~ Methods @@ -67,14 +69,12 @@ public class SpringSecurityLdapTemplateITests { @Test public void compareOfCorrectByteValueSucceeds() { - assertThat(template.compare("uid=bob,ou=people", "userPassword", - Utf8.encode("bobspassword"))).isTrue(); + assertThat(template.compare("uid=bob,ou=people", "userPassword", Utf8.encode("bobspassword"))).isTrue(); } @Test public void compareOfWrongByteValueFails() { - assertThat(template.compare("uid=bob,ou=people", "userPassword", - Utf8.encode("wrongvalue"))).isFalse(); + assertThat(template.compare("uid=bob,ou=people", "userPassword", Utf8.encode("wrongvalue"))).isFalse(); } @Test @@ -108,8 +108,8 @@ public class SpringSecurityLdapTemplateITests { public void roleSearchReturnsCorrectNumberOfRoles() { String param = "uid=ben,ou=people,dc=springframework,dc=org"; - Set values = template.searchForSingleAttributeValues("ou=groups", - "(member={0})", new String[] { param }, "ou"); + Set values = template.searchForSingleAttributeValues("ou=groups", "(member={0})", + new String[] { param }, "ou"); assertThat(values).as("Expected 3 results from search").hasSize(3); assertThat(values.contains("developer")).isTrue(); @@ -119,14 +119,12 @@ public class SpringSecurityLdapTemplateITests { @Test public void testMultiAttributeRetrievalWithNullAttributeNames() { - Set>> values = template - .searchForMultipleAttributeValues("ou=people", "(uid={0})", - new String[] { "bob" }, null); + Set>> values = template.searchForMultipleAttributeValues("ou=people", "(uid={0})", + new String[] { "bob" }, null); assertThat(values).hasSize(1); Map> record = values.iterator().next(); assertAttributeValue(record, "uid", "bob"); - assertAttributeValue(record, "objectclass", "top", "person", - "organizationalPerson", "inetOrgPerson"); + assertAttributeValue(record, "objectclass", "top", "person", "organizationalPerson", "inetOrgPerson"); assertAttributeValue(record, "cn", "Bob Hamilton"); assertAttributeValue(record, "sn", "Hamilton"); assertThat(record.containsKey("userPassword")).isFalse(); @@ -134,14 +132,12 @@ public class SpringSecurityLdapTemplateITests { @Test public void testMultiAttributeRetrievalWithZeroLengthAttributeNames() { - Set>> values = template - .searchForMultipleAttributeValues("ou=people", "(uid={0})", - new String[] { "bob" }, new String[0]); + Set>> values = template.searchForMultipleAttributeValues("ou=people", "(uid={0})", + new String[] { "bob" }, new String[0]); assertThat(values).hasSize(1); Map> record = values.iterator().next(); assertAttributeValue(record, "uid", "bob"); - assertAttributeValue(record, "objectclass", "top", "person", - "organizationalPerson", "inetOrgPerson"); + assertAttributeValue(record, "objectclass", "top", "person", "organizationalPerson", "inetOrgPerson"); assertAttributeValue(record, "cn", "Bob Hamilton"); assertAttributeValue(record, "sn", "Hamilton"); assertThat(record.containsKey("userPassword")).isFalse(); @@ -149,9 +145,8 @@ public class SpringSecurityLdapTemplateITests { @Test public void testMultiAttributeRetrievalWithSpecifiedAttributeNames() { - Set>> values = template - .searchForMultipleAttributeValues("ou=people", "(uid={0})", - new String[] { "bob" }, new String[] { "uid", "cn", "sn" }); + Set>> values = template.searchForMultipleAttributeValues("ou=people", "(uid={0})", + new String[] { "bob" }, new String[] { "uid", "cn", "sn" }); assertThat(values).hasSize(1); Map> record = values.iterator().next(); assertAttributeValue(record, "uid", "bob"); @@ -161,8 +156,7 @@ public class SpringSecurityLdapTemplateITests { assertThat(record.containsKey("objectclass")).isFalse(); } - protected void assertAttributeValue(Map> record, - String attributeName, String... values) { + protected void assertAttributeValue(Map> record, String attributeName, String... values) { assertThat(record.containsKey(attributeName)).isTrue(); assertThat(record.get(attributeName)).hasSize(values.length); for (int i = 0; i < values.length; i++) { @@ -174,8 +168,8 @@ public class SpringSecurityLdapTemplateITests { public void testRoleSearchForMissingAttributeFailsGracefully() { String param = "uid=ben,ou=people,dc=springframework,dc=org"; - Set values = template.searchForSingleAttributeValues("ou=groups", - "(member={0})", new String[] { param }, "mail"); + Set values = template.searchForSingleAttributeValues("ou=groups", "(member={0})", + new String[] { param }, "mail"); assertThat(values).isEmpty(); } @@ -184,8 +178,8 @@ public class SpringSecurityLdapTemplateITests { public void roleSearchWithEscapedCharacterSucceeds() { String param = "cn=mouse\\, jerry,ou=people,dc=springframework,dc=org"; - Set values = template.searchForSingleAttributeValues("ou=groups", - "(member={0})", new String[] { param }, "cn"); + Set values = template.searchForSingleAttributeValues("ou=groups", "(member={0})", + new String[] { param }, "cn"); assertThat(values).hasSize(1); } @@ -205,9 +199,8 @@ public class SpringSecurityLdapTemplateITests { controls.setReturningAttributes(null); String param = "cn=mouse\\, jerry,ou=people,dc=springframework,dc=org"; - javax.naming.NamingEnumeration results = ctx.search( - "ou=groups,dc=springframework,dc=org", "(member={0})", - new String[] { param }, controls); + javax.naming.NamingEnumeration results = ctx.search("ou=groups,dc=springframework,dc=org", + "(member={0})", new String[] { param }, controls); assertThat(results.hasMore()).as("Expected a result").isTrue(); } diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/BindAuthenticatorTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/BindAuthenticatorTests.java index 072cfebb96..6530c7794c 100644 --- a/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/BindAuthenticatorTests.java +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/BindAuthenticatorTests.java @@ -35,7 +35,6 @@ import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; - /** * Tests for {@link BindAuthenticator}. * @@ -45,12 +44,15 @@ import static org.assertj.core.api.Assertions.fail; @RunWith(SpringRunner.class) @ContextConfiguration(classes = ApacheDsContainerConfig.class) public class BindAuthenticatorTests { + // ~ Instance fields // ================================================================================================ @Autowired private DefaultSpringSecurityContextSource contextSource; + private BindAuthenticator authenticator; + private Authentication bob; // ~ Methods @@ -66,19 +68,16 @@ public class BindAuthenticatorTests { @Test(expected = BadCredentialsException.class) public void emptyPasswordIsRejected() { - this.authenticator - .authenticate(new UsernamePasswordAuthenticationToken("jen", "")); + this.authenticator.authenticate(new UsernamePasswordAuthenticationToken("jen", "")); } @Test public void testAuthenticationWithCorrectPasswordSucceeds() { - this.authenticator.setUserDnPatterns( - new String[] { "uid={0},ou=people", "cn={0},ou=people" }); + this.authenticator.setUserDnPatterns(new String[] { "uid={0},ou=people", "cn={0},ou=people" }); DirContextOperations user = this.authenticator.authenticate(this.bob); assertThat(user.getStringAttribute("uid")).isEqualTo("bob"); - this.authenticator.authenticate(new UsernamePasswordAuthenticationToken( - "mouse, jerry", "jerryspassword")); + this.authenticator.authenticate(new UsernamePasswordAuthenticationToken("mouse, jerry", "jerryspassword")); } @Test @@ -86,8 +85,7 @@ public class BindAuthenticatorTests { this.authenticator.setUserDnPatterns(new String[] { "uid={0},ou=people" }); try { - this.authenticator.authenticate(new UsernamePasswordAuthenticationToken( - "nonexistentsuser", "password")); + this.authenticator.authenticate(new UsernamePasswordAuthenticationToken("nonexistentsuser", "password")); fail("Shouldn't be able to bind with invalid username"); } catch (BadCredentialsException expected) { @@ -98,28 +96,21 @@ public class BindAuthenticatorTests { public void testAuthenticationWithUserSearch() throws Exception { // DirContextAdapter ctx = new DirContextAdapter(new // DistinguishedName("uid=bob,ou=people")); - this.authenticator.setUserSearch(new FilterBasedLdapUserSearch("ou=people", - "(uid={0})", this.contextSource)); + this.authenticator.setUserSearch(new FilterBasedLdapUserSearch("ou=people", "(uid={0})", this.contextSource)); this.authenticator.afterPropertiesSet(); DirContextOperations result = this.authenticator.authenticate(this.bob); - //ensure we are getting the same attributes back + // ensure we are getting the same attributes back assertThat(result.getStringAttribute("cn")).isEqualTo("Bob Hamilton"); // SEC-1444 - this.authenticator.setUserSearch(new FilterBasedLdapUserSearch("ou=people", - "(cn={0})", this.contextSource)); - this.authenticator.authenticate(new UsernamePasswordAuthenticationToken( - "mouse, jerry", "jerryspassword")); - this.authenticator.authenticate(new UsernamePasswordAuthenticationToken( - "slash/guy", "slashguyspassword")); + this.authenticator.setUserSearch(new FilterBasedLdapUserSearch("ou=people", "(cn={0})", this.contextSource)); + this.authenticator.authenticate(new UsernamePasswordAuthenticationToken("mouse, jerry", "jerryspassword")); + this.authenticator.authenticate(new UsernamePasswordAuthenticationToken("slash/guy", "slashguyspassword")); // SEC-1661 - this.authenticator.setUserSearch(new FilterBasedLdapUserSearch( - "ou=\\\"quoted people\\\"", "(cn={0})", this.contextSource)); - this.authenticator.authenticate(new UsernamePasswordAuthenticationToken( - "quote\"guy", "quoteguyspassword")); this.authenticator.setUserSearch( - new FilterBasedLdapUserSearch("", "(cn={0})", this.contextSource)); - this.authenticator.authenticate(new UsernamePasswordAuthenticationToken( - "quote\"guy", "quoteguyspassword")); + new FilterBasedLdapUserSearch("ou=\\\"quoted people\\\"", "(cn={0})", this.contextSource)); + this.authenticator.authenticate(new UsernamePasswordAuthenticationToken("quote\"guy", "quoteguyspassword")); + this.authenticator.setUserSearch(new FilterBasedLdapUserSearch("", "(cn={0})", this.contextSource)); + this.authenticator.authenticate(new UsernamePasswordAuthenticationToken("quote\"guy", "quoteguyspassword")); } /* @@ -148,8 +139,7 @@ public class BindAuthenticatorTests { this.authenticator.setUserDnPatterns(new String[] { "uid={0},ou=people" }); try { - this.authenticator.authenticate( - new UsernamePasswordAuthenticationToken("bob", "wrongpassword")); + this.authenticator.authenticate(new UsernamePasswordAuthenticationToken("bob", "wrongpassword")); fail("Shouldn't be able to bind with wrong password"); } catch (BadCredentialsException expected) { @@ -159,7 +149,7 @@ public class BindAuthenticatorTests { @Test public void testUserDnPatternReturnsCorrectDn() { this.authenticator.setUserDnPatterns(new String[] { "cn={0},ou=people" }); - assertThat(this.authenticator.getUserDns("Joe").get(0)) - .isEqualTo("cn=Joe,ou=people"); + assertThat(this.authenticator.getUserDns("Joe").get(0)).isEqualTo("cn=Joe,ou=people"); } + } diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticatorTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticatorTests.java index 1fe8f97f8f..11ecffcf65 100644 --- a/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticatorTests.java +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticatorTests.java @@ -46,13 +46,17 @@ import static org.assertj.core.api.Assertions.*; @RunWith(SpringRunner.class) @ContextConfiguration(classes = ApacheDsContainerConfig.class) public class PasswordComparisonAuthenticatorTests { + // ~ Instance fields // ================================================================================================ @Autowired private DefaultSpringSecurityContextSource contextSource; + private PasswordComparisonAuthenticator authenticator; + private Authentication bob; + private Authentication ben; // ~ Methods @@ -82,8 +86,7 @@ public class PasswordComparisonAuthenticatorTests { authenticator.afterPropertiesSet(); try { - authenticator.authenticate(new UsernamePasswordAuthenticationToken("Joe", - "pass")); + authenticator.authenticate(new UsernamePasswordAuthenticationToken("Joe", "pass")); fail("Expected exception on failed user search"); } catch (UsernameNotFoundException expected) { @@ -94,14 +97,12 @@ public class PasswordComparisonAuthenticatorTests { public void testLdapPasswordCompareFailsWithWrongPassword() { // Don't retrieve the password authenticator.setUserAttributes(new String[] { "uid", "cn", "sn" }); - authenticator.authenticate(new UsernamePasswordAuthenticationToken("bob", - "wrongpass")); + authenticator.authenticate(new UsernamePasswordAuthenticationToken("bob", "wrongpass")); } @Test public void testMultipleDnPatternsWorkOk() { - authenticator.setUserDnPatterns(new String[] { "uid={0},ou=nonexistent", - "uid={0},ou=people" }); + authenticator.setUserDnPatterns(new String[] { "uid={0},ou=nonexistent", "uid={0},ou=people" }); authenticator.authenticate(bob); } @@ -110,8 +111,7 @@ public class PasswordComparisonAuthenticatorTests { authenticator.setUserAttributes(new String[] { "uid", "userPassword" }); DirContextAdapter user = (DirContextAdapter) authenticator.authenticate(bob); - assertThat(user - .getAttributes().size()).withFailMessage("Should have retrieved 2 attribute (uid)").isEqualTo(2); + assertThat(user.getAttributes().size()).withFailMessage("Should have retrieved 2 attribute (uid)").isEqualTo(2); } @Test @@ -145,8 +145,7 @@ public class PasswordComparisonAuthenticatorTests { public void testLdapCompareWithDifferentPasswordAttributeSucceeds() { authenticator.setUserAttributes(new String[] { "uid" }); authenticator.setPasswordAttributeName("cn"); - authenticator.authenticate(new UsernamePasswordAuthenticationToken("ben", - "Ben Alex")); + authenticator.authenticate(new UsernamePasswordAuthenticationToken("ben", "Ben Alex")); } @Test @@ -155,12 +154,11 @@ public class PasswordComparisonAuthenticatorTests { authenticator.setPasswordEncoder(NoOpPasswordEncoder.getInstance()); assertThat(authenticator.getUserDns("Bob")).withFailMessage("User DN matches shouldn't be available").isEmpty(); - DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName( - "uid=Bob,ou=people")); + DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName("uid=Bob,ou=people")); ctx.setAttributeValue("userPassword", "bobspassword"); authenticator.setUserSearch(new MockUserSearch(ctx)); - authenticator.authenticate(new UsernamePasswordAuthenticationToken( - "shouldntbeused", "bobspassword")); + authenticator.authenticate(new UsernamePasswordAuthenticationToken("shouldntbeused", "bobspassword")); } + } diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/search/FilterBasedLdapUserSearchTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/search/FilterBasedLdapUserSearchTests.java index 789e89f4ee..8483981bde 100644 --- a/ldap/src/integration-test/java/org/springframework/security/ldap/search/FilterBasedLdapUserSearchTests.java +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/search/FilterBasedLdapUserSearchTests.java @@ -47,8 +47,7 @@ public class FilterBasedLdapUserSearchTests { @Test public void basicSearchSucceeds() throws Exception { - FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", - "(uid={0})", this.contextSource); + FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(uid={0})", this.contextSource); locator.setSearchSubtree(false); locator.setSearchTimeLimit(0); locator.setDerefLinkFlag(false); @@ -61,8 +60,7 @@ public class FilterBasedLdapUserSearchTests { @Test public void searchForNameWithCommaSucceeds() throws Exception { - FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", - "(uid={0})", this.contextSource); + FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(uid={0})", this.contextSource); locator.setSearchSubtree(false); DirContextOperations jerry = locator.searchForUser("jerry"); @@ -74,8 +72,7 @@ public class FilterBasedLdapUserSearchTests { // Try some funny business with filters. @Test public void extraFilterPartToExcludeBob() { - FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch( - "ou=people", + FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(&(cn=*)(!(|(uid={0})(uid=rod)(uid=jerry)(uid=slashguy)(uid=javadude)(uid=groovydude)(uid=closuredude)(uid=scaladude))))", this.contextSource); @@ -86,23 +83,20 @@ public class FilterBasedLdapUserSearchTests { @Test(expected = IncorrectResultSizeDataAccessException.class) public void searchFailsOnMultipleMatches() { - FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", - "(cn=*)", this.contextSource); + FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(cn=*)", this.contextSource); locator.searchForUser("Ignored"); } @Test(expected = UsernameNotFoundException.class) public void searchForInvalidUserFails() { - FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", - "(uid={0})", this.contextSource); + FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people", "(uid={0})", this.contextSource); locator.searchForUser("Joe"); } @Test public void subTreeSearchSucceeds() throws Exception { // Don't set the searchBase, so search from the root. - FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("", "(cn={0})", - this.contextSource); + FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("", "(cn={0})", this.contextSource); locator.setSearchSubtree(true); DirContextOperations ben = locator.searchForUser("Ben Alex"); @@ -113,8 +107,8 @@ public class FilterBasedLdapUserSearchTests { @Test public void searchWithDifferentSearchBaseIsSuccessful() { - FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch( - "ou=otherpeople", "(cn={0})", this.contextSource); + FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=otherpeople", "(cn={0})", + this.contextSource); DirContextOperations joe = locator.searchForUser("Joe Smeth"); assertThat(joe.getStringAttribute("cn")).isEqualTo("Joe Smeth"); } diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/server/ApacheDSContainerTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/server/ApacheDSContainerTests.java index add74ddf45..da2976563f 100644 --- a/ldap/src/integration-test/java/org/springframework/security/ldap/server/ApacheDSContainerTests.java +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/server/ApacheDSContainerTests.java @@ -50,10 +50,8 @@ public class ApacheDSContainerTests { // SEC-2162 @Test public void failsToStartThrowsException() throws Exception { - ApacheDSContainer server1 = new ApacheDSContainer("dc=springframework,dc=org", - "classpath:test-server.ldif"); - ApacheDSContainer server2 = new ApacheDSContainer("dc=springframework,dc=org", - "classpath:missing.ldif"); + ApacheDSContainer server1 = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif"); + ApacheDSContainer server2 = new ApacheDSContainer("dc=springframework,dc=org", "classpath:missing.ldif"); List ports = getDefaultPorts(1); server1.setPort(ports.get(0)); server2.setPort(ports.get(0)); @@ -83,10 +81,8 @@ public class ApacheDSContainerTests { // SEC-2161 @Test public void multipleInstancesSimultanciously() throws Exception { - ApacheDSContainer server1 = new ApacheDSContainer("dc=springframework,dc=org", - "classpath:test-server.ldif"); - ApacheDSContainer server2 = new ApacheDSContainer("dc=springframework,dc=org", - "classpath:test-server.ldif"); + ApacheDSContainer server1 = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif"); + ApacheDSContainer server2 = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif"); List ports = getDefaultPorts(2); server1.setPort(ports.get(0)); server2.setPort(ports.get(1)); @@ -110,8 +106,7 @@ public class ApacheDSContainerTests { @Test public void startWithLdapOverSslWithoutCertificate() throws Exception { - ApacheDSContainer server = new ApacheDSContainer("dc=springframework,dc=org", - "classpath:test-server.ldif"); + ApacheDSContainer server = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif"); List ports = getDefaultPorts(1); server.setPort(ports.get(0)); server.setLdapOverSslEnabled(true); @@ -120,21 +115,21 @@ public class ApacheDSContainerTests { server.afterPropertiesSet(); fail("Expected an IllegalArgumentException to be thrown."); } - catch (IllegalArgumentException e){ + catch (IllegalArgumentException e) { assertThat(e).hasMessage("When LdapOverSsl is enabled, the keyStoreFile property must be set."); } } @Test public void startWithLdapOverSslWithWrongPassword() throws Exception { - final ClassPathResource keyStoreResource = new ClassPathResource("/org/springframework/security/ldap/server/spring.keystore"); + final ClassPathResource keyStoreResource = new ClassPathResource( + "/org/springframework/security/ldap/server/spring.keystore"); final File temporaryKeyStoreFile = new File(temporaryFolder.getRoot(), "spring.keystore"); FileCopyUtils.copy(keyStoreResource.getInputStream(), new FileOutputStream(temporaryKeyStoreFile)); assertThat(temporaryKeyStoreFile).isFile(); - ApacheDSContainer server = new ApacheDSContainer("dc=springframework,dc=org", - "classpath:test-server.ldif"); + ApacheDSContainer server = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif"); List ports = getDefaultPorts(1); server.setPort(ports.get(0)); @@ -147,15 +142,15 @@ public class ApacheDSContainerTests { server.afterPropertiesSet(); fail("Expected a RuntimeException to be thrown."); } - catch (RuntimeException e){ + catch (RuntimeException e) { assertThat(e).hasMessage("Server startup failed"); assertThat(e).hasRootCauseInstanceOf(UnrecoverableKeyException.class); } } /** - * This test starts an LDAP server using LDAPs (LDAP over SSL). A self-signed certificate is being used, which was - * previously generated with: + * This test starts an LDAP server using LDAPs (LDAP over SSL). A self-signed + * certificate is being used, which was previously generated with: * *
         	 * {@code
        @@ -168,14 +163,14 @@ public class ApacheDSContainerTests {
         	@Test
         	public void startWithLdapOverSsl() throws Exception {
         
        -		final ClassPathResource keyStoreResource = new ClassPathResource("/org/springframework/security/ldap/server/spring.keystore");
        +		final ClassPathResource keyStoreResource = new ClassPathResource(
        +				"/org/springframework/security/ldap/server/spring.keystore");
         		final File temporaryKeyStoreFile = new File(temporaryFolder.getRoot(), "spring.keystore");
         		FileCopyUtils.copy(keyStoreResource.getInputStream(), new FileOutputStream(temporaryKeyStoreFile));
         
         		assertThat(temporaryKeyStoreFile).isFile();
         
        -		ApacheDSContainer server = new ApacheDSContainer("dc=springframework,dc=org",
        -				"classpath:test-server.ldif");
        +		ApacheDSContainer server = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
         
         		List ports = getDefaultPorts(1);
         		server.setPort(ports.get(0));
        @@ -216,8 +211,7 @@ public class ApacheDSContainerTests {
         
         	@Test
         	public void afterPropertiesSetWhenPortIsZeroThenRandomPortIsSelected() throws Exception {
        -		ApacheDSContainer server = new ApacheDSContainer("dc=springframework,dc=org",
        -				"classpath:test-server.ldif");
        +		ApacheDSContainer server = new ApacheDSContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
         		server.setPort(0);
         		try {
         			server.afterPropertiesSet();
        @@ -229,4 +223,5 @@ public class ApacheDSContainerTests {
         			server.destroy();
         		}
         	}
        +
         }
        diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/server/ApacheDSEmbeddedLdifTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/server/ApacheDSEmbeddedLdifTests.java
        index 09556a01bb..40a2882379 100644
        --- a/ldap/src/integration-test/java/org/springframework/security/ldap/server/ApacheDSEmbeddedLdifTests.java
        +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/server/ApacheDSEmbeddedLdifTests.java
        @@ -34,16 +34,17 @@ import static org.assertj.core.api.Assertions.assertThat;
         public class ApacheDSEmbeddedLdifTests {
         
         	private static final String LDAP_ROOT = "ou=ssattributes,dc=springframework,dc=org";
        +
         	private static final int LDAP_PORT = 52389;
         
         	private ApacheDSContainer server;
        +
         	private SpringSecurityLdapTemplate ldapTemplate;
         
         	@Before
         	public void setUp() throws Exception {
         		// TODO: InMemoryXmlApplicationContext would be useful here, but it is not visible
        -		this.server = new ApacheDSContainer(LDAP_ROOT,
        -				"classpath:test-server-custom-attribute-types.ldif");
        +		this.server = new ApacheDSContainer(LDAP_ROOT, "classpath:test-server-custom-attribute-types.ldif");
         		this.server.setPort(LDAP_PORT);
         		this.server.afterPropertiesSet();
         
        @@ -68,10 +69,10 @@ public class ApacheDSEmbeddedLdifTests {
         	@Ignore // Not fixed yet
         	@Test // SEC-2387
         	public void customAttributeTypesShouldBeProperlyCreatedWhenLoadedFromLdif() {
        -		assertThat(this.ldapTemplate.compare("uid=objectWithCustomAttribute1", "uid",
        -				"objectWithCustomAttribute1")).isTrue();
        -		assertThat(this.ldapTemplate.compare("uid=objectWithCustomAttribute1",
        -				"customAttribute", "I am custom")).isTrue();
        +		assertThat(this.ldapTemplate.compare("uid=objectWithCustomAttribute1", "uid", "objectWithCustomAttribute1"))
        +				.isTrue();
        +		assertThat(this.ldapTemplate.compare("uid=objectWithCustomAttribute1", "customAttribute", "I am custom"))
        +				.isTrue();
         	}
         
         }
        diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerLdifTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerLdifTests.java
        index e5346d56f5..5956506982 100644
        --- a/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerLdifTests.java
        +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerLdifTests.java
        @@ -59,6 +59,7 @@ public class UnboundIdContainerLdifTests {
         
         	@Configuration
         	static class CustomLdifConfig {
        +
         		private UnboundIdContainer container = new UnboundIdContainer("dc=springframework,dc=org",
         				"classpath:test-server.ldif");
         
        @@ -70,14 +71,15 @@ public class UnboundIdContainerLdifTests {
         
         		@Bean
         		ContextSource contextSource(UnboundIdContainer container) {
        -			return new DefaultSpringSecurityContextSource("ldap://127.0.0.1:"
        -					+ container.getPort() + "/dc=springframework,dc=org");
        +			return new DefaultSpringSecurityContextSource(
        +					"ldap://127.0.0.1:" + container.getPort() + "/dc=springframework,dc=org");
         		}
         
         		@PreDestroy
         		void shutdown() {
         			this.container.stop();
         		}
        +
         	}
         
         	@Test
        @@ -93,6 +95,7 @@ public class UnboundIdContainerLdifTests {
         
         	@Configuration
         	static class WildcardLdifConfig {
        +
         		private UnboundIdContainer container = new UnboundIdContainer("dc=springframework,dc=org",
         				"classpath*:test-server.ldif");
         
        @@ -104,14 +107,15 @@ public class UnboundIdContainerLdifTests {
         
         		@Bean
         		ContextSource contextSource(UnboundIdContainer container) {
        -			return new DefaultSpringSecurityContextSource("ldap://127.0.0.1:"
        -					+ container.getPort() + "/dc=springframework,dc=org");
        +			return new DefaultSpringSecurityContextSource(
        +					"ldap://127.0.0.1:" + container.getPort() + "/dc=springframework,dc=org");
         		}
         
         		@PreDestroy
         		void shutdown() {
         			this.container.stop();
         		}
        +
         	}
         
         	@Test
        @@ -119,7 +123,8 @@ public class UnboundIdContainerLdifTests {
         		try {
         			appCtx = new AnnotationConfigApplicationContext(MalformedLdifConfig.class);
         			failBecauseExceptionWasNotThrown(IllegalStateException.class);
        -		} catch (Exception e) {
        +		}
        +		catch (Exception e) {
         			assertThat(e.getCause()).isInstanceOf(IllegalStateException.class);
         			assertThat(e.getMessage()).contains("Unable to load LDIF classpath:test-server-malformed.txt");
         		}
        @@ -127,6 +132,7 @@ public class UnboundIdContainerLdifTests {
         
         	@Configuration
         	static class MalformedLdifConfig {
        +
         		private UnboundIdContainer container = new UnboundIdContainer("dc=springframework,dc=org",
         				"classpath:test-server-malformed.txt");
         
        @@ -140,6 +146,7 @@ public class UnboundIdContainerLdifTests {
         		void shutdown() {
         			this.container.stop();
         		}
        +
         	}
         
         	@Test
        @@ -147,7 +154,8 @@ public class UnboundIdContainerLdifTests {
         		try {
         			appCtx = new AnnotationConfigApplicationContext(MissingLdifConfig.class);
         			failBecauseExceptionWasNotThrown(IllegalStateException.class);
        -		} catch (Exception e) {
        +		}
        +		catch (Exception e) {
         			assertThat(e.getCause()).isInstanceOf(IllegalStateException.class);
         			assertThat(e.getMessage()).contains("Unable to load LDIF classpath:does-not-exist.ldif");
         		}
        @@ -155,6 +163,7 @@ public class UnboundIdContainerLdifTests {
         
         	@Configuration
         	static class MissingLdifConfig {
        +
         		private UnboundIdContainer container = new UnboundIdContainer("dc=springframework,dc=org",
         				"classpath:does-not-exist.ldif");
         
        @@ -168,6 +177,7 @@ public class UnboundIdContainerLdifTests {
         		void shutdown() {
         			this.container.stop();
         		}
        +
         	}
         
         	@Test
        @@ -177,6 +187,7 @@ public class UnboundIdContainerLdifTests {
         
         	@Configuration
         	static class WildcardNoLdifConfig {
        +
         		private UnboundIdContainer container = new UnboundIdContainer("dc=springframework,dc=org",
         				"classpath*:*.test.ldif");
         
        @@ -190,5 +201,7 @@ public class UnboundIdContainerLdifTests {
         		void shutdown() {
         			this.container.stop();
         		}
        +
         	}
        +
         }
        diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerTests.java
        index 5b1a7bc59d..fb72238a8c 100644
        --- a/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerTests.java
        +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerTests.java
        @@ -33,8 +33,7 @@ public class UnboundIdContainerTests {
         
         	@Test
         	public void startLdapServer() throws Exception {
        -		UnboundIdContainer server = new UnboundIdContainer("dc=springframework,dc=org",
        -				"classpath:test-server.ldif");
        +		UnboundIdContainer server = new UnboundIdContainer("dc=springframework,dc=org", "classpath:test-server.ldif");
         		server.setApplicationContext(new GenericApplicationContext());
         		List ports = getDefaultPorts(1);
         		server.setPort(ports.get(0));
        @@ -42,7 +41,8 @@ public class UnboundIdContainerTests {
         		try {
         			server.afterPropertiesSet();
         			assertThat(server.getPort()).isEqualTo(ports.get(0));
        -		} finally {
        +		}
        +		finally {
         			server.destroy();
         		}
         	}
        @@ -55,7 +55,8 @@ public class UnboundIdContainerTests {
         		try {
         			server.afterPropertiesSet();
         			assertThat(server.getPort()).isNotEqualTo(0);
        -		} finally {
        +		}
        +		finally {
         			server.destroy();
         		}
         	}
        @@ -70,7 +71,8 @@ public class UnboundIdContainerTests {
         				availablePorts.add(socket.getLocalPort());
         			}
         			return availablePorts;
        -		} finally {
        +		}
        +		finally {
         			for (ServerSocket conn : connections) {
         				conn.close();
         			}
        diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulatorTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulatorTests.java
        index f1789129ae..052c604af8 100644
        --- a/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulatorTests.java
        +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulatorTests.java
        @@ -37,7 +37,6 @@ import org.springframework.test.context.ContextConfiguration;
         import org.springframework.test.context.junit4.SpringRunner;
         
         /**
        - *
          * @author Luke Taylor
          * @author Eddú Meléndez
          */
        @@ -48,6 +47,7 @@ public class DefaultLdapAuthoritiesPopulatorTests {
         
         	@Autowired
         	private ContextSource contextSource;
        +
         	private DefaultLdapAuthoritiesPopulator populator;
         
         	// ~ Methods
        @@ -64,11 +64,9 @@ public class DefaultLdapAuthoritiesPopulatorTests {
         		populator.setDefaultRole("ROLE_USER");
         		assertThat(populator.getContextSource()).isSameAs(this.contextSource);
         
        -		DirContextAdapter ctx = new DirContextAdapter(
        -				new DistinguishedName("cn=notfound"));
        +		DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName("cn=notfound"));
         
        -		Collection authorities = populator.getGrantedAuthorities(ctx,
        -				"notfound");
        +		Collection authorities = populator.getGrantedAuthorities(ctx, "notfound");
         		assertThat(authorities).hasSize(1);
         		assertThat(AuthorityUtils.authorityListToSet(authorities).contains("ROLE_USER")).isTrue();
         	}
        @@ -78,8 +76,8 @@ public class DefaultLdapAuthoritiesPopulatorTests {
         		populator = new DefaultLdapAuthoritiesPopulator(this.contextSource, null);
         		populator.setDefaultRole("ROLE_USER");
         
        -		Collection authorities = populator.getGrantedAuthorities(
        -				new DirContextAdapter(new DistinguishedName("cn=notused")), "notused");
        +		Collection authorities = populator
        +				.getGrantedAuthorities(new DirContextAdapter(new DistinguishedName("cn=notused")), "notused");
         		assertThat(authorities).hasSize(1);
         		assertThat(AuthorityUtils.authorityListToSet(authorities).contains("ROLE_USER")).isTrue();
         	}
        @@ -93,11 +91,10 @@ public class DefaultLdapAuthoritiesPopulatorTests {
         		populator.setConvertToUpperCase(true);
         		populator.setGroupSearchFilter("(member={0})");
         
        -		DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName(
        -				"uid=ben,ou=people,dc=springframework,dc=org"));
        +		DirContextAdapter ctx = new DirContextAdapter(
        +				new DistinguishedName("uid=ben,ou=people,dc=springframework,dc=org"));
         
        -		Set authorities = AuthorityUtils.authorityListToSet(populator
        -				.getGrantedAuthorities(ctx, "ben"));
        +		Set authorities = AuthorityUtils.authorityListToSet(populator.getGrantedAuthorities(ctx, "ben"));
         
         		assertThat(authorities).as("Should have 2 roles").hasSize(2);
         
        @@ -111,11 +108,10 @@ public class DefaultLdapAuthoritiesPopulatorTests {
         		populator.setConvertToUpperCase(true);
         		populator.setGroupSearchFilter("(ou={1})");
         
        -		DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName(
        -				"uid=ben,ou=people,dc=springframework,dc=org"));
        +		DirContextAdapter ctx = new DirContextAdapter(
        +				new DistinguishedName("uid=ben,ou=people,dc=springframework,dc=org"));
         
        -		Set authorities = AuthorityUtils.authorityListToSet(populator
        -				.getGrantedAuthorities(ctx, "manager"));
        +		Set authorities = AuthorityUtils.authorityListToSet(populator.getGrantedAuthorities(ctx, "manager"));
         
         		assertThat(authorities).as("Should have 1 role").hasSize(1);
         		assertThat(authorities.contains("ROLE_MANAGER")).isTrue();
        @@ -126,11 +122,10 @@ public class DefaultLdapAuthoritiesPopulatorTests {
         		populator.setGroupRoleAttribute("ou");
         		populator.setConvertToUpperCase(true);
         
        -		DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName(
        -				"uid=ben,ou=people,dc=springframework,dc=org"));
        +		DirContextAdapter ctx = new DirContextAdapter(
        +				new DistinguishedName("uid=ben,ou=people,dc=springframework,dc=org"));
         
        -		Set authorities = AuthorityUtils.authorityListToSet(populator
        -				.getGrantedAuthorities(ctx, "manager"));
        +		Set authorities = AuthorityUtils.authorityListToSet(populator.getGrantedAuthorities(ctx, "manager"));
         
         		assertThat(authorities).as("Should have 2 roles").hasSize(2);
         		assertThat(authorities.contains("ROLE_MANAGER")).isTrue();
        @@ -143,11 +138,10 @@ public class DefaultLdapAuthoritiesPopulatorTests {
         		populator.setConvertToUpperCase(true);
         		populator.setSearchSubtree(true);
         
        -		DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName(
        -				"uid=ben,ou=people,dc=springframework,dc=org"));
        +		DirContextAdapter ctx = new DirContextAdapter(
        +				new DistinguishedName("uid=ben,ou=people,dc=springframework,dc=org"));
         
        -		Set authorities = AuthorityUtils.authorityListToSet(populator
        -				.getGrantedAuthorities(ctx, "manager"));
        +		Set authorities = AuthorityUtils.authorityListToSet(populator.getGrantedAuthorities(ctx, "manager"));
         
         		assertThat(authorities).as("Should have 3 roles").hasSize(3);
         		assertThat(authorities.contains("ROLE_MANAGER")).isTrue();
        @@ -159,15 +153,13 @@ public class DefaultLdapAuthoritiesPopulatorTests {
         	public void extraRolesAreAdded() {
         		populator = new DefaultLdapAuthoritiesPopulator(this.contextSource, null) {
         			@Override
        -			protected Set getAdditionalRoles(DirContextOperations user,
        -					String username) {
        -				return new HashSet<>(
        -						AuthorityUtils.createAuthorityList("ROLE_EXTRA"));
        +			protected Set getAdditionalRoles(DirContextOperations user, String username) {
        +				return new HashSet<>(AuthorityUtils.createAuthorityList("ROLE_EXTRA"));
         			}
         		};
         
        -		Collection authorities = populator.getGrantedAuthorities(
        -				new DirContextAdapter(new DistinguishedName("cn=notused")), "notused");
        +		Collection authorities = populator
        +				.getGrantedAuthorities(new DirContextAdapter(new DistinguishedName("cn=notused")), "notused");
         		assertThat(authorities).hasSize(1);
         		assertThat(AuthorityUtils.authorityListToSet(authorities).contains("ROLE_EXTRA")).isTrue();
         	}
        @@ -178,11 +170,10 @@ public class DefaultLdapAuthoritiesPopulatorTests {
         		populator.setConvertToUpperCase(true);
         		populator.setGroupSearchFilter("(member={0})");
         
        -		DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName(
        -				"cn=mouse\\, jerry,ou=people,dc=springframework,dc=org"));
        +		DirContextAdapter ctx = new DirContextAdapter(
        +				new DistinguishedName("cn=mouse\\, jerry,ou=people,dc=springframework,dc=org"));
         
        -		Set authorities = AuthorityUtils.authorityListToSet(populator
        -				.getGrantedAuthorities(ctx, "notused"));
        +		Set authorities = AuthorityUtils.authorityListToSet(populator.getGrantedAuthorities(ctx, "notused"));
         
         		assertThat(authorities).as("Should have 1 role").hasSize(1);
         		assertThat(authorities.contains("ROLE_MANAGER")).isTrue();
        @@ -196,8 +187,8 @@ public class DefaultLdapAuthoritiesPopulatorTests {
         			return new LdapAuthority(role, dn);
         		});
         
        -		DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName(
        -				"cn=mouse\\, jerry,ou=people,dc=springframework,dc=org"));
        +		DirContextAdapter ctx = new DirContextAdapter(
        +				new DistinguishedName("cn=mouse\\, jerry,ou=people,dc=springframework,dc=org"));
         
         		Collection authorities = populator.getGrantedAuthorities(ctx, "notused");
         
        @@ -208,4 +199,5 @@ public class DefaultLdapAuthoritiesPopulatorTests {
         	public void customAuthoritiesMappingFunctionThrowsIfNull() {
         		populator.setAuthorityMapper(null);
         	}
        +
         }
        diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManagerModifyPasswordTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManagerModifyPasswordTests.java
        index 72f2b7a109..99b05bb453 100644
        --- a/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManagerModifyPasswordTests.java
        +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManagerModifyPasswordTests.java
        @@ -44,7 +44,7 @@ import static org.assertj.core.api.Assertions.assertThatCode;
          * @author Josh Cummings
          */
         @RunWith(SpringRunner.class)
        -@ContextConfiguration(classes=LdapUserDetailsManagerModifyPasswordTests.UnboundIdContainerConfiguration.class)
        +@ContextConfiguration(classes = LdapUserDetailsManagerModifyPasswordTests.UnboundIdContainerConfiguration.class)
         public class LdapUserDetailsManagerModifyPasswordTests {
         
         	LdapUserDetailsManager userDetailsManager;
        @@ -60,15 +60,14 @@ public class LdapUserDetailsManagerModifyPasswordTests {
         	}
         
         	@Test
        -	@WithMockUser(username="bob", password="bobspassword", authorities="ROLE_USER")
        +	@WithMockUser(username = "bob", password = "bobspassword", authorities = "ROLE_USER")
         	public void changePasswordWhenOldPasswordIsIncorrectThenThrowsException() {
        -		assertThatCode(() ->
        -				this.userDetailsManager.changePassword("wrongoldpassword", "bobsnewpassword"))
        +		assertThatCode(() -> this.userDetailsManager.changePassword("wrongoldpassword", "bobsnewpassword"))
         				.isInstanceOf(BadCredentialsException.class);
         	}
         
         	@Test
        -	@WithMockUser(username="bob", password="bobspassword", authorities="ROLE_USER")
        +	@WithMockUser(username = "bob", password = "bobspassword", authorities = "ROLE_USER")
         	public void changePasswordWhenOldPasswordIsCorrectThenPasses() {
         		SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(this.contextSource);
         
        @@ -76,11 +75,13 @@ public class LdapUserDetailsManagerModifyPasswordTests {
         				"bobsshinynewandformidablylongandnearlyimpossibletorememberthoughdemonstrablyhardtocrackduetoitshighlevelofentropypasswordofjustice");
         
         		assertThat(template.compare("uid=bob,ou=people", "userPassword",
        -				"bobsshinynewandformidablylongandnearlyimpossibletorememberthoughdemonstrablyhardtocrackduetoitshighlevelofentropypasswordofjustice")).isTrue();
        +				"bobsshinynewandformidablylongandnearlyimpossibletorememberthoughdemonstrablyhardtocrackduetoitshighlevelofentropypasswordofjustice"))
        +						.isTrue();
         	}
         
         	@Configuration
         	static class UnboundIdContainerConfiguration {
        +
         		private UnboundIdContainer container = new UnboundIdContainer("dc=springframework,dc=org",
         				"classpath:test-server.ldif");
         
        @@ -92,13 +93,15 @@ public class LdapUserDetailsManagerModifyPasswordTests {
         
         		@Bean
         		ContextSource contextSource(UnboundIdContainer container) {
        -			return new DefaultSpringSecurityContextSource("ldap://127.0.0.1:"
        -					+ container.getPort() + "/dc=springframework,dc=org");
        +			return new DefaultSpringSecurityContextSource(
        +					"ldap://127.0.0.1:" + container.getPort() + "/dc=springframework,dc=org");
         		}
         
         		@PreDestroy
         		void shutdown() {
         			this.container.stop();
         		}
        +
         	}
        +
         }
        diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManagerTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManagerTests.java
        index eaf24d8b25..af95a939c0 100644
        --- a/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManagerTests.java
        +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManagerTests.java
        @@ -52,8 +52,8 @@ public class LdapUserDetailsManagerTests {
         	@Autowired
         	private ContextSource contextSource;
         
        -	private static final List TEST_AUTHORITIES = AuthorityUtils.createAuthorityList(
        -			"ROLE_CLOWNS", "ROLE_ACROBATS");
        +	private static final List TEST_AUTHORITIES = AuthorityUtils.createAuthorityList("ROLE_CLOWNS",
        +			"ROLE_ACROBATS");
         
         	private LdapUserDetailsManager mgr;
         
        @@ -76,8 +76,7 @@ public class LdapUserDetailsManagerTests {
         
         		group.setAttributeValue("objectclass", "groupOfNames");
         		group.setAttributeValue("cn", "clowns");
        -		group.setAttributeValue("member",
        -				"cn=nobody,ou=test people,dc=springframework,dc=org");
        +		group.setAttributeValue("member", "cn=nobody,ou=test people,dc=springframework,dc=org");
         		template.bind("cn=clowns,ou=testgroups", group, null);
         
         		group.setAttributeValue("cn", "acrobats");
        @@ -185,9 +184,7 @@ public class LdapUserDetailsManagerTests {
         		}
         
         		// Check that no authorities are left
        -		assertThat(
        -				mgr.getUserAuthorities(mgr.usernameMapper.buildDn("don"), "don")).hasSize(
        -						0);
        +		assertThat(mgr.getUserAuthorities(mgr.usernameMapper.buildDn("don"), "don")).hasSize(0);
         	}
         
         	@Test
        @@ -203,13 +200,12 @@ public class LdapUserDetailsManagerTests {
         		mgr.createUser(p.createUserDetails());
         
         		SecurityContextHolder.getContext().setAuthentication(
        -				new UsernamePasswordAuthenticationToken("johnyossarian",
        -						"yossarianspassword", TEST_AUTHORITIES));
        +				new UsernamePasswordAuthenticationToken("johnyossarian", "yossarianspassword", TEST_AUTHORITIES));
         
         		mgr.changePassword("yossarianspassword", "yossariansnewpassword");
         
        -		assertThat(template.compare("uid=johnyossarian,ou=test people", "userPassword",
        -				"yossariansnewpassword")).isTrue();
        +		assertThat(template.compare("uid=johnyossarian,ou=test people", "userPassword", "yossariansnewpassword"))
        +				.isTrue();
         	}
         
         	@Test(expected = BadCredentialsException.class)
        @@ -225,9 +221,9 @@ public class LdapUserDetailsManagerTests {
         		mgr.createUser(p.createUserDetails());
         
         		SecurityContextHolder.getContext().setAuthentication(
        -				new UsernamePasswordAuthenticationToken("johnyossarian",
        -						"yossarianspassword", TEST_AUTHORITIES));
        +				new UsernamePasswordAuthenticationToken("johnyossarian", "yossarianspassword", TEST_AUTHORITIES));
         
         		mgr.changePassword("wrongpassword", "yossariansnewpassword");
         	}
        +
         }
        diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/NestedLdapAuthoritiesPopulatorTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/NestedLdapAuthoritiesPopulatorTests.java
        index 70ff12f642..892b542ede 100644
        --- a/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/NestedLdapAuthoritiesPopulatorTests.java
        +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/NestedLdapAuthoritiesPopulatorTests.java
        @@ -43,12 +43,19 @@ public class NestedLdapAuthoritiesPopulatorTests {
         
         	@Autowired
         	private ContextSource contextSource;
        +
         	private NestedLdapAuthoritiesPopulator populator;
        +
         	private LdapAuthority javaDevelopers;
        +
         	private LdapAuthority groovyDevelopers;
        +
         	private LdapAuthority scalaDevelopers;
        +
         	private LdapAuthority closureDevelopers;
        +
         	private LdapAuthority jDevelopers;
        +
         	private LdapAuthority circularJavaDevelopers;
         
         	// ~ Methods
        @@ -56,15 +63,13 @@ public class NestedLdapAuthoritiesPopulatorTests {
         
         	@Before
         	public void setUp() {
        -		populator = new NestedLdapAuthoritiesPopulator(this.contextSource,
        -				"ou=jdeveloper");
        +		populator = new NestedLdapAuthoritiesPopulator(this.contextSource, "ou=jdeveloper");
         		populator.setGroupSearchFilter("(member={0})");
         		populator.setIgnorePartialResultException(false);
         		populator.setRolePrefix("");
         		populator.setSearchSubtree(true);
         		populator.setConvertToUpperCase(false);
        -		jDevelopers = new LdapAuthority("j-developers",
        -				"cn=j-developers,ou=jdeveloper,dc=springframework,dc=org");
        +		jDevelopers = new LdapAuthority("j-developers", "cn=j-developers,ou=jdeveloper,dc=springframework,dc=org");
         		javaDevelopers = new LdapAuthority("java-developers",
         				"cn=java-developers,ou=jdeveloper,dc=springframework,dc=org");
         		groovyDevelopers = new LdapAuthority("groovy-developers",
        @@ -79,21 +84,17 @@ public class NestedLdapAuthoritiesPopulatorTests {
         
         	@Test
         	public void testScalaDudeJDevelopersAuthorities() {
        -		DirContextAdapter ctx = new DirContextAdapter(
        -				"uid=scaladude,ou=people,dc=springframework,dc=org");
        -		Collection authorities = populator.getGrantedAuthorities(ctx,
        -				"scaladude");
        +		DirContextAdapter ctx = new DirContextAdapter("uid=scaladude,ou=people,dc=springframework,dc=org");
        +		Collection authorities = populator.getGrantedAuthorities(ctx, "scaladude");
         		assertThat(authorities).hasSize(5);
        -		assertThat(authorities).isEqualTo(Arrays.asList(javaDevelopers, circularJavaDevelopers,
        -				scalaDevelopers, groovyDevelopers, jDevelopers));
        +		assertThat(authorities).isEqualTo(
        +				Arrays.asList(javaDevelopers, circularJavaDevelopers, scalaDevelopers, groovyDevelopers, jDevelopers));
         	}
         
         	@Test
         	public void testJavaDudeJDevelopersAuthorities() {
        -		DirContextAdapter ctx = new DirContextAdapter(
        -				"uid=javadude,ou=people,dc=springframework,dc=org");
        -		Collection authorities = populator.getGrantedAuthorities(ctx,
        -				"javadude");
        +		DirContextAdapter ctx = new DirContextAdapter("uid=javadude,ou=people,dc=springframework,dc=org");
        +		Collection authorities = populator.getGrantedAuthorities(ctx, "javadude");
         		assertThat(authorities).hasSize(4);
         		assertThat(authorities).contains(javaDevelopers);
         	}
        @@ -101,36 +102,30 @@ public class NestedLdapAuthoritiesPopulatorTests {
         	@Test
         	public void testScalaDudeJDevelopersAuthoritiesWithSearchLimit() {
         		populator.setMaxSearchDepth(1);
        -		DirContextAdapter ctx = new DirContextAdapter(
        -				"uid=scaladude,ou=people,dc=springframework,dc=org");
        -		Collection authorities = populator.getGrantedAuthorities(ctx,
        -				"scaladude");
        +		DirContextAdapter ctx = new DirContextAdapter("uid=scaladude,ou=people,dc=springframework,dc=org");
        +		Collection authorities = populator.getGrantedAuthorities(ctx, "scaladude");
         		assertThat(authorities).hasSize(1);
         		assertThat(authorities).isEqualTo(Arrays.asList(scalaDevelopers));
         	}
         
         	@Test
         	public void testGroovyDudeJDevelopersAuthorities() {
        -		DirContextAdapter ctx = new DirContextAdapter(
        -				"uid=groovydude,ou=people,dc=springframework,dc=org");
        -		Collection authorities = populator.getGrantedAuthorities(ctx,
        -				"groovydude");
        +		DirContextAdapter ctx = new DirContextAdapter("uid=groovydude,ou=people,dc=springframework,dc=org");
        +		Collection authorities = populator.getGrantedAuthorities(ctx, "groovydude");
         		assertThat(authorities).hasSize(4);
        -		assertThat(authorities).isEqualTo(Arrays.asList(javaDevelopers, circularJavaDevelopers, groovyDevelopers,
        -				jDevelopers));
        +		assertThat(authorities)
        +				.isEqualTo(Arrays.asList(javaDevelopers, circularJavaDevelopers, groovyDevelopers, jDevelopers));
         	}
         
         	@Test
         	public void testClosureDudeJDevelopersWithMembershipAsAttributeValues() {
         		populator.setAttributeNames(new HashSet(Arrays.asList("member")));
         
        -		DirContextAdapter ctx = new DirContextAdapter(
        -				"uid=closuredude,ou=people,dc=springframework,dc=org");
        -		Collection authorities = populator.getGrantedAuthorities(ctx,
        -				"closuredude");
        +		DirContextAdapter ctx = new DirContextAdapter("uid=closuredude,ou=people,dc=springframework,dc=org");
        +		Collection authorities = populator.getGrantedAuthorities(ctx, "closuredude");
         		assertThat(authorities).hasSize(5);
        -		assertThat(authorities).isEqualTo(Arrays.asList(javaDevelopers, circularJavaDevelopers,
        -				closureDevelopers, groovyDevelopers, jDevelopers));
        +		assertThat(authorities).isEqualTo(Arrays.asList(javaDevelopers, circularJavaDevelopers, closureDevelopers,
        +				groovyDevelopers, jDevelopers));
         
         		LdapAuthority[] ldapAuthorities = authorities.toArray(new LdapAuthority[0]);
         		assertThat(ldapAuthorities).hasSize(5);
        @@ -138,15 +133,16 @@ public class NestedLdapAuthoritiesPopulatorTests {
         		assertThat(ldapAuthorities[0].getAttributes().containsKey("member")).isTrue();
         		assertThat(ldapAuthorities[0].getAttributes().get("member")).isNotNull();
         		assertThat(ldapAuthorities[0].getAttributes().get("member")).hasSize(3);
        -		assertThat(ldapAuthorities[0].getFirstAttributeValue("member")).isEqualTo("cn=groovy-developers,ou=jdeveloper,dc=springframework,dc=org");
        +		assertThat(ldapAuthorities[0].getFirstAttributeValue("member"))
        +				.isEqualTo("cn=groovy-developers,ou=jdeveloper,dc=springframework,dc=org");
         
         		// java group
         		assertThat(ldapAuthorities[1].getAttributes().containsKey("member")).isTrue();
         		assertThat(ldapAuthorities[1].getAttributes().get("member")).isNotNull();
         		assertThat(ldapAuthorities[1].getAttributes().get("member")).hasSize(3);
         		assertThat(groovyDevelopers.getDn()).isEqualTo(ldapAuthorities[1].getFirstAttributeValue("member"));
        -		assertThat(ldapAuthorities[2]
        -				.getAttributes().get("member")).contains("uid=closuredude,ou=people,dc=springframework,dc=org");
        +		assertThat(ldapAuthorities[2].getAttributes().get("member"))
        +				.contains("uid=closuredude,ou=people,dc=springframework,dc=org");
         
         		// test non existent attribute
         		assertThat(ldapAuthorities[2].getFirstAttributeValue("test")).isNull();
        @@ -155,4 +151,5 @@ public class NestedLdapAuthoritiesPopulatorTests {
         		// test role name
         		assertThat(ldapAuthorities[3].getAuthority()).isEqualTo(groovyDevelopers.getAuthority());
         	}
        +
         }
        diff --git a/ldap/src/main/java/org/springframework/security/ldap/DefaultLdapUsernameToDnMapper.java b/ldap/src/main/java/org/springframework/security/ldap/DefaultLdapUsernameToDnMapper.java
        index bbb80ccf3d..2b7a68bac0 100644
        --- a/ldap/src/main/java/org/springframework/security/ldap/DefaultLdapUsernameToDnMapper.java
        +++ b/ldap/src/main/java/org/springframework/security/ldap/DefaultLdapUsernameToDnMapper.java
        @@ -26,7 +26,9 @@ import org.springframework.ldap.core.DistinguishedName;
          * @author Luke Taylor
          */
         public class DefaultLdapUsernameToDnMapper implements LdapUsernameToDnMapper {
        +
         	private final String userDnBase;
        +
         	private final String usernameAttribute;
         
         	/**
        @@ -48,4 +50,5 @@ public class DefaultLdapUsernameToDnMapper implements LdapUsernameToDnMapper {
         
         		return dn;
         	}
        +
         }
        diff --git a/ldap/src/main/java/org/springframework/security/ldap/DefaultSpringSecurityContextSource.java b/ldap/src/main/java/org/springframework/security/ldap/DefaultSpringSecurityContextSource.java
        index f9790d606d..f815ce06d5 100644
        --- a/ldap/src/main/java/org/springframework/security/ldap/DefaultSpringSecurityContextSource.java
        +++ b/ldap/src/main/java/org/springframework/security/ldap/DefaultSpringSecurityContextSource.java
        @@ -47,6 +47,7 @@ import org.springframework.util.Assert;
          * @since 2.0
          */
         public class DefaultSpringSecurityContextSource extends LdapContextSource {
        +
         	protected final Log logger = LogFactory.getLog(getClass());
         
         	private String rootDn;
        @@ -55,7 +56,6 @@ public class DefaultSpringSecurityContextSource extends LdapContextSource {
         	 * Create and initialize an instance which will connect to the supplied LDAP URL. If
         	 * you want to use more than one server for fail-over, rather use the
         	 * {@link #DefaultSpringSecurityContextSource(List, String)} constructor.
        -	 *
         	 * @param providerUrl an LDAP URL of the form
         	 * ldap://localhost:389/base_dn
         	 */
        @@ -79,8 +79,7 @@ public class DefaultSpringSecurityContextSource extends LdapContextSource {
         				this.rootDn = urlRootDn;
         			}
         			else if (!this.rootDn.equals(urlRootDn)) {
        -				throw new IllegalArgumentException(
        -						"Root DNs must be the same when using multiple URLs");
        +				throw new IllegalArgumentException("Root DNs must be the same when using multiple URLs");
         			}
         		}
         
        @@ -96,8 +95,7 @@ public class DefaultSpringSecurityContextSource extends LdapContextSource {
         				// user.
         				if (!DefaultSpringSecurityContextSource.this.userDn.equals(dn)
         						&& env.containsKey(SUN_LDAP_POOLING_FLAG)) {
        -					DefaultSpringSecurityContextSource.this.logger
        -							.debug("Removing pooling flag for user " + dn);
        +					DefaultSpringSecurityContextSource.this.logger.debug("Removing pooling flag for user " + dn);
         					env.remove(SUN_LDAP_POOLING_FLAG);
         				}
         			}
        @@ -107,7 +105,6 @@ public class DefaultSpringSecurityContextSource extends LdapContextSource {
         	/**
         	 * Create and initialize an instance which will connect of the LDAP Spring Security
         	 * Context Source. It will connect to any of the provided LDAP server URLs.
        -	 *
         	 * @param urls A list of string values which are LDAP server URLs. An example would be
         	 * ldap://ldap.company.com:389. LDAPS URLs (SSL-secured) may be used as
         	 * well, given that Spring Security is able to connect to the server. Note that these
        @@ -128,7 +125,6 @@ public class DefaultSpringSecurityContextSource extends LdapContextSource {
         	 * Builds a Spring LDAP-compliant Provider URL string, i.e. a space-separated list of
         	 * LDAP servers with their base DNs. As the base DN must be identical for all servers,
         	 * it needs to be supplied only once.
        -	 *
         	 * @param urls A list of string values which are LDAP server URLs. An example would be
         	 *
         	 * 
        diff --git a/ldap/src/main/java/org/springframework/security/ldap/LdapEncoder.java b/ldap/src/main/java/org/springframework/security/ldap/LdapEncoder.java
        index 43316dab64..4e9b9be1e5 100644
        --- a/ldap/src/main/java/org/springframework/security/ldap/LdapEncoder.java
        +++ b/ldap/src/main/java/org/springframework/security/ldap/LdapEncoder.java
        @@ -1,245 +1,241 @@
        -/*
        - * Copyright 2005-2010 the original author or authors.
        - *
        - * Licensed under the Apache License, Version 2.0 (the "License");
        - * you may not use this file except in compliance with the License.
        - * You may obtain a copy of the License at
        - *
        - *      https://www.apache.org/licenses/LICENSE-2.0
        - *
        - * Unless required by applicable law or agreed to in writing, software
        - * distributed under the License is distributed on an "AS IS" BASIS,
        - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
        - * See the License for the specific language governing permissions and
        - * limitations under the License.
        - */
        -
        -package org.springframework.security.ldap;
        -
        -import org.springframework.ldap.BadLdapGrammarException;
        -
        -/**
        - * Helper class to encode and decode ldap names and values.
        - *
        - * 

        - * NOTE: This is a copy from Spring LDAP so that both Spring LDAP 1.x and 2.x can be - * supported without reflection. - *

        - * - * @author Adam Skogman - * @author Mattias Hellborg Arthursson - */ -final class LdapEncoder { - - private static final int HEX = 16; - private static String[] NAME_ESCAPE_TABLE = new String[96]; - - private static String[] FILTER_ESCAPE_TABLE = new String['\\' + 1]; - - static { - - // Name encoding table ------------------------------------- - - // all below 0x20 (control chars) - for (char c = 0; c < ' '; c++) { - NAME_ESCAPE_TABLE[c] = "\\" + toTwoCharHex(c); - } - - NAME_ESCAPE_TABLE['#'] = "\\#"; - NAME_ESCAPE_TABLE[','] = "\\,"; - NAME_ESCAPE_TABLE[';'] = "\\;"; - NAME_ESCAPE_TABLE['='] = "\\="; - NAME_ESCAPE_TABLE['+'] = "\\+"; - NAME_ESCAPE_TABLE['<'] = "\\<"; - NAME_ESCAPE_TABLE['>'] = "\\>"; - NAME_ESCAPE_TABLE['\"'] = "\\\""; - NAME_ESCAPE_TABLE['\\'] = "\\\\"; - - // Filter encoding table ------------------------------------- - - // fill with char itself - for (char c = 0; c < FILTER_ESCAPE_TABLE.length; c++) { - FILTER_ESCAPE_TABLE[c] = String.valueOf(c); - } - - // escapes (RFC2254) - FILTER_ESCAPE_TABLE['*'] = "\\2a"; - FILTER_ESCAPE_TABLE['('] = "\\28"; - FILTER_ESCAPE_TABLE[')'] = "\\29"; - FILTER_ESCAPE_TABLE['\\'] = "\\5c"; - FILTER_ESCAPE_TABLE[0] = "\\00"; - - } - - /** - * All static methods - not to be instantiated. - */ - private LdapEncoder() { - } - - protected static String toTwoCharHex(char c) { - - String raw = Integer.toHexString(c).toUpperCase(); - - if (raw.length() > 1) { - return raw; - } - else { - return "0" + raw; - } - } - - /** - * Escape a value for use in a filter. - * - * @param value the value to escape. - * @return a properly escaped representation of the supplied value. - */ - public static String filterEncode(String value) { - - if (value == null) { - return null; - } - - // make buffer roomy - StringBuilder encodedValue = new StringBuilder(value.length() * 2); - - int length = value.length(); - - for (int i = 0; i < length; i++) { - - char c = value.charAt(i); - - if (c < FILTER_ESCAPE_TABLE.length) { - encodedValue.append(FILTER_ESCAPE_TABLE[c]); - } - else { - // default: add the char - encodedValue.append(c); - } - } - - return encodedValue.toString(); - } - - /** - * LDAP Encodes a value for use with a DN. Escapes for LDAP, not JNDI! - * - *
        - * Escapes:
        - * ' ' [space] - "\ " [if first or last]
        - * '#' [hash] - "\#"
        - * ',' [comma] - "\,"
        - * ';' [semicolon] - "\;"
        - * '= [equals] - "\="
        - * '+' [plus] - "\+"
        - * '<' [less than] - "\<"
        - * '>' [greater than] - "\>"
        - * '"' [double quote] - "\""
        - * '\' [backslash] - "\\"
        - * - * @param value the value to escape. - * @return The escaped value. - */ - public static String nameEncode(String value) { - - if (value == null) { - return null; - } - - // make buffer roomy - StringBuilder encodedValue = new StringBuilder(value.length() * 2); - - int length = value.length(); - int last = length - 1; - - for (int i = 0; i < length; i++) { - - char c = value.charAt(i); - - // space first or last - if (c == ' ' && (i == 0 || i == last)) { - encodedValue.append("\\ "); - continue; - } - - if (c < NAME_ESCAPE_TABLE.length) { - // check in table for escapes - String esc = NAME_ESCAPE_TABLE[c]; - - if (esc != null) { - encodedValue.append(esc); - continue; - } - } - - // default: add the char - encodedValue.append(c); - } - - return encodedValue.toString(); - - } - - /** - * Decodes a value. Converts escaped chars to ordinary chars. - * - * @param value Trimmed value, so no leading an trailing blanks, except an escaped - * space last. - * @return The decoded value as a string. - * @throws BadLdapGrammarException - */ - static public String nameDecode(String value) throws BadLdapGrammarException { - - if (value == null) { - return null; - } - - // make buffer same size - StringBuilder decoded = new StringBuilder(value.length()); - - int i = 0; - while (i < value.length()) { - char currentChar = value.charAt(i); - if (currentChar == '\\') { - if (value.length() <= i + 1) { - // Ending with a single backslash is not allowed - throw new BadLdapGrammarException( - "Unexpected end of value " + "unterminated '\\'"); - } - else { - char nextChar = value.charAt(i + 1); - if (nextChar == ',' || nextChar == '=' || nextChar == '+' - || nextChar == '<' || nextChar == '>' || nextChar == '#' - || nextChar == ';' || nextChar == '\\' || nextChar == '\"' - || nextChar == ' ') { - // Normal backslash escape - decoded.append(nextChar); - i += 2; - } - else { - if (value.length() <= i + 2) { - throw new BadLdapGrammarException("Unexpected end of value " - + "expected special or hex, found '" + nextChar - + "'"); - } - else { - // This should be a hex value - String hexString = "" + nextChar + value.charAt(i + 2); - decoded.append((char) Integer.parseInt(hexString, HEX)); - i += 3; - } - } - } - } - else { - // This character wasn't escaped - just append it - decoded.append(currentChar); - i++; - } - } - - return decoded.toString(); - - } -} +/* + * Copyright 2005-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.ldap; + +import org.springframework.ldap.BadLdapGrammarException; + +/** + * Helper class to encode and decode ldap names and values. + * + *

        + * NOTE: This is a copy from Spring LDAP so that both Spring LDAP 1.x and 2.x can be + * supported without reflection. + *

        + * + * @author Adam Skogman + * @author Mattias Hellborg Arthursson + */ +final class LdapEncoder { + + private static final int HEX = 16; + + private static String[] NAME_ESCAPE_TABLE = new String[96]; + + private static String[] FILTER_ESCAPE_TABLE = new String['\\' + 1]; + + static { + + // Name encoding table ------------------------------------- + + // all below 0x20 (control chars) + for (char c = 0; c < ' '; c++) { + NAME_ESCAPE_TABLE[c] = "\\" + toTwoCharHex(c); + } + + NAME_ESCAPE_TABLE['#'] = "\\#"; + NAME_ESCAPE_TABLE[','] = "\\,"; + NAME_ESCAPE_TABLE[';'] = "\\;"; + NAME_ESCAPE_TABLE['='] = "\\="; + NAME_ESCAPE_TABLE['+'] = "\\+"; + NAME_ESCAPE_TABLE['<'] = "\\<"; + NAME_ESCAPE_TABLE['>'] = "\\>"; + NAME_ESCAPE_TABLE['\"'] = "\\\""; + NAME_ESCAPE_TABLE['\\'] = "\\\\"; + + // Filter encoding table ------------------------------------- + + // fill with char itself + for (char c = 0; c < FILTER_ESCAPE_TABLE.length; c++) { + FILTER_ESCAPE_TABLE[c] = String.valueOf(c); + } + + // escapes (RFC2254) + FILTER_ESCAPE_TABLE['*'] = "\\2a"; + FILTER_ESCAPE_TABLE['('] = "\\28"; + FILTER_ESCAPE_TABLE[')'] = "\\29"; + FILTER_ESCAPE_TABLE['\\'] = "\\5c"; + FILTER_ESCAPE_TABLE[0] = "\\00"; + + } + + /** + * All static methods - not to be instantiated. + */ + private LdapEncoder() { + } + + protected static String toTwoCharHex(char c) { + + String raw = Integer.toHexString(c).toUpperCase(); + + if (raw.length() > 1) { + return raw; + } + else { + return "0" + raw; + } + } + + /** + * Escape a value for use in a filter. + * @param value the value to escape. + * @return a properly escaped representation of the supplied value. + */ + public static String filterEncode(String value) { + + if (value == null) { + return null; + } + + // make buffer roomy + StringBuilder encodedValue = new StringBuilder(value.length() * 2); + + int length = value.length(); + + for (int i = 0; i < length; i++) { + + char c = value.charAt(i); + + if (c < FILTER_ESCAPE_TABLE.length) { + encodedValue.append(FILTER_ESCAPE_TABLE[c]); + } + else { + // default: add the char + encodedValue.append(c); + } + } + + return encodedValue.toString(); + } + + /** + * LDAP Encodes a value for use with a DN. Escapes for LDAP, not JNDI! + * + *
        + * Escapes:
        + * ' ' [space] - "\ " [if first or last]
        + * '#' [hash] - "\#"
        + * ',' [comma] - "\,"
        + * ';' [semicolon] - "\;"
        + * '= [equals] - "\="
        + * '+' [plus] - "\+"
        + * '<' [less than] - "\<"
        + * '>' [greater than] - "\>"
        + * '"' [double quote] - "\""
        + * '\' [backslash] - "\\"
        + * @param value the value to escape. + * @return The escaped value. + */ + public static String nameEncode(String value) { + + if (value == null) { + return null; + } + + // make buffer roomy + StringBuilder encodedValue = new StringBuilder(value.length() * 2); + + int length = value.length(); + int last = length - 1; + + for (int i = 0; i < length; i++) { + + char c = value.charAt(i); + + // space first or last + if (c == ' ' && (i == 0 || i == last)) { + encodedValue.append("\\ "); + continue; + } + + if (c < NAME_ESCAPE_TABLE.length) { + // check in table for escapes + String esc = NAME_ESCAPE_TABLE[c]; + + if (esc != null) { + encodedValue.append(esc); + continue; + } + } + + // default: add the char + encodedValue.append(c); + } + + return encodedValue.toString(); + + } + + /** + * Decodes a value. Converts escaped chars to ordinary chars. + * @param value Trimmed value, so no leading an trailing blanks, except an escaped + * space last. + * @return The decoded value as a string. + * @throws BadLdapGrammarException + */ + static public String nameDecode(String value) throws BadLdapGrammarException { + + if (value == null) { + return null; + } + + // make buffer same size + StringBuilder decoded = new StringBuilder(value.length()); + + int i = 0; + while (i < value.length()) { + char currentChar = value.charAt(i); + if (currentChar == '\\') { + if (value.length() <= i + 1) { + // Ending with a single backslash is not allowed + throw new BadLdapGrammarException("Unexpected end of value " + "unterminated '\\'"); + } + else { + char nextChar = value.charAt(i + 1); + if (nextChar == ',' || nextChar == '=' || nextChar == '+' || nextChar == '<' || nextChar == '>' + || nextChar == '#' || nextChar == ';' || nextChar == '\\' || nextChar == '\"' + || nextChar == ' ') { + // Normal backslash escape + decoded.append(nextChar); + i += 2; + } + else { + if (value.length() <= i + 2) { + throw new BadLdapGrammarException( + "Unexpected end of value " + "expected special or hex, found '" + nextChar + "'"); + } + else { + // This should be a hex value + String hexString = "" + nextChar + value.charAt(i + 2); + decoded.append((char) Integer.parseInt(hexString, HEX)); + i += 3; + } + } + } + } + else { + // This character wasn't escaped - just append it + decoded.append(currentChar); + i++; + } + } + + return decoded.toString(); + + } + +} diff --git a/ldap/src/main/java/org/springframework/security/ldap/LdapUsernameToDnMapper.java b/ldap/src/main/java/org/springframework/security/ldap/LdapUsernameToDnMapper.java index c8521e359a..6a7abc1213 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/LdapUsernameToDnMapper.java +++ b/ldap/src/main/java/org/springframework/security/ldap/LdapUsernameToDnMapper.java @@ -23,5 +23,7 @@ import org.springframework.ldap.core.DistinguishedName; * @author Luke Taylor */ public interface LdapUsernameToDnMapper { + DistinguishedName buildDn(String username); + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/LdapUtils.java b/ldap/src/main/java/org/springframework/security/ldap/LdapUtils.java index b4a7a7ae82..bab3457013 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/LdapUtils.java +++ b/ldap/src/main/java/org/springframework/security/ldap/LdapUtils.java @@ -36,6 +36,7 @@ import java.net.URISyntaxException; * @author Luke Taylor */ public final class LdapUtils { + // ~ Static fields/initializers // ===================================================================================== @@ -82,16 +83,12 @@ public final class LdapUtils { * If the DN is "cn=bob,ou=people,dc=springframework,dc=org" and the base context name * is "ou=people,dc=springframework,dc=org" it would return "cn=bob". *

        - * * @param fullDn the DN * @param baseCtx the context to work out the name relative to. - * * @return the - * * @throws NamingException any exceptions thrown by the context are propagated. */ - public static String getRelativeName(String fullDn, Context baseCtx) - throws NamingException { + public static String getRelativeName(String fullDn, Context baseCtx) throws NamingException { String baseDn = baseCtx.getNameInNamespace(); @@ -117,8 +114,7 @@ public final class LdapUtils { * Gets the full dn of a name by prepending the name of the context it is relative to. * If the name already contains the base name, it is returned unaltered. */ - public static DistinguishedName getFullDn(DistinguishedName dn, Context baseCtx) - throws NamingException { + public static DistinguishedName getFullDn(DistinguishedName dn, Context baseCtx) throws NamingException { DistinguishedName baseDn = new DistinguishedName(baseCtx.getNameInNamespace()); if (dn.contains(baseDn)) { @@ -140,8 +136,7 @@ public final class LdapUtils { return (String) passObj; } else { - throw new IllegalArgumentException( - "Password object was not a String or byte array."); + throw new IllegalArgumentException("Password object was not a String or byte array."); } } @@ -151,9 +146,7 @@ public final class LdapUtils { * For example, the URL ldap://monkeymachine:11389/dc=springframework,dc=org * has the root DN "dc=springframework,dc=org". *

        - * * @param url the LDAP URL - * * @return the root DN */ public static String parseRootDnFromUrl(String url) { @@ -193,10 +186,10 @@ public final class LdapUtils { return new URI(url); } catch (URISyntaxException e) { - IllegalArgumentException iae = new IllegalArgumentException( - "Unable to parse url: " + url); + IllegalArgumentException iae = new IllegalArgumentException("Unable to parse url: " + url); iae.initCause(e); throw iae; } } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/SpringSecurityLdapTemplate.java b/ldap/src/main/java/org/springframework/security/ldap/SpringSecurityLdapTemplate.java index fe0d9c0002..1d447287f3 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/SpringSecurityLdapTemplate.java +++ b/ldap/src/main/java/org/springframework/security/ldap/SpringSecurityLdapTemplate.java @@ -54,6 +54,7 @@ import java.util.Set; * @since 2.0 */ public class SpringSecurityLdapTemplate extends LdapTemplate { + // ~ Static fields/initializers // ===================================================================================== private static final Log logger = LogFactory.getLog(SpringSecurityLdapTemplate.class); @@ -90,11 +91,9 @@ public class SpringSecurityLdapTemplate extends LdapTemplate { /** * Performs an LDAP compare operation of the value of an attribute for a particular * directory entry. - * * @param dn the entry who's attribute is to be used * @param attributeName the attribute who's value we want to compare * @param value the value to be checked against the directory value - * * @return true if the supplied value matches that in the directory */ public boolean compare(final String dn, final String attributeName, final Object value) { @@ -107,14 +106,15 @@ public class SpringSecurityLdapTemplate extends LdapTemplate { ctls.setReturningAttributes(NO_ATTRS); ctls.setSearchScope(SearchControls.OBJECT_SCOPE); - NamingEnumeration results = ctx.search(dn, - comparisonFilter, new Object[] { value }, ctls); + NamingEnumeration results = ctx.search(dn, comparisonFilter, new Object[] { value }, + ctls); Boolean match = results.hasMore(); LdapUtils.closeEnumeration(results); return match; } + } Boolean matches = (Boolean) executeReadOnly(new LdapCompareCallback()); @@ -124,15 +124,12 @@ public class SpringSecurityLdapTemplate extends LdapTemplate { /** * Composes an object from the attributes of the given DN. - * * @param dn the directory entry which will be read * @param attributesToRetrieve the named attributes which will be retrieved from the * directory entry. - * * @return the object created by the mapper */ - public DirContextOperations retrieveEntry(final String dn, - final String[] attributesToRetrieve) { + public DirContextOperations retrieveEntry(final String dn, final String[] attributesToRetrieve) { return (DirContextOperations) executeReadOnly((ContextExecutor) ctx -> { Attributes attrs = ctx.getAttributes(dn, attributesToRetrieve); @@ -149,20 +146,18 @@ public class SpringSecurityLdapTemplate extends LdapTemplate { * the named attribute found in all entries matched by the search. Note that one * directory entry may have several values for the attribute. Intended for role * searches and similar scenarios. - * * @param base the DN to search in * @param filter search filter to use * @param params the parameters to substitute in the search filter * @param attributeName the attribute who's values are to be retrieved. - * * @return the set of String values for the attribute as a union of the values found * in all the matching entries. */ - public Set searchForSingleAttributeValues(final String base, - final String filter, final Object[] params, final String attributeName) { + public Set searchForSingleAttributeValues(final String base, final String filter, final Object[] params, + final String attributeName) { String[] attributeNames = new String[] { attributeName }; - Set>> multipleAttributeValues = searchForMultipleAttributeValues( - base, filter, params, attributeNames); + Set>> multipleAttributeValues = searchForMultipleAttributeValues(base, filter, params, + attributeNames); Set result = new HashSet<>(); for (Map> map : multipleAttributeValues) { List values = map.get(attributeName); @@ -178,19 +173,16 @@ public class SpringSecurityLdapTemplate extends LdapTemplate { * attribute found in all entries matched by the search. Note that one directory entry * may have several values for the attribute. Intended for role searches and similar * scenarios. - * * @param base the DN to search in * @param filter search filter to use * @param params the parameters to substitute in the search filter * @param attributeNames the attributes' values that are to be retrieved. - * * @return the set of String values for each attribute found in all the matching * entries. The attribute name is the key for each set of values. In addition each map * contains the DN as a String with the key predefined key {@link #DN_KEY}. */ - public Set>> searchForMultipleAttributeValues( - final String base, final String filter, final Object[] params, - final String[] attributeNames) { + public Set>> searchForMultipleAttributeValues(final String base, final String filter, + final Object[] params, final String[] attributeNames) { // Escape the params acording to RFC2254 Object[] encodedParams = new String[params.length]; @@ -208,15 +200,13 @@ public class SpringSecurityLdapTemplate extends LdapTemplate { Map> record = new HashMap<>(); if (attributeNames == null || attributeNames.length == 0) { try { - for (NamingEnumeration ae = adapter.getAttributes().getAll(); ae - .hasMore();) { + for (NamingEnumeration ae = adapter.getAttributes().getAll(); ae.hasMore();) { Attribute attr = (Attribute) ae.next(); extractStringAttributeValues(adapter, record, attr.getID()); } } catch (NamingException x) { - org.springframework.ldap.support.LdapUtils - .convertLdapException(x); + org.springframework.ldap.support.LdapUtils.convertLdapException(x); } } else { @@ -231,8 +221,7 @@ public class SpringSecurityLdapTemplate extends LdapTemplate { SearchControls ctls = new SearchControls(); ctls.setSearchScope(searchControls.getSearchScope()); - ctls.setReturningAttributes(attributeNames != null && attributeNames.length > 0 ? attributeNames - : null); + ctls.setReturningAttributes(attributeNames != null && attributeNames.length > 0 ? attributeNames : null); search(base, formattedFilter, ctls, roleMapper); @@ -256,13 +245,12 @@ public class SpringSecurityLdapTemplate extends LdapTemplate { * Extracts String values for a specified attribute name and places them in the map * representing the ldap record If a value is not of type String, it will derive it's * value from the {@link Object#toString()} - * * @param adapter - the adapter that contains the values * @param record - the map holding the attribute names and values * @param attributeName - the name for which to fetch the values from */ - private void extractStringAttributeValues(DirContextAdapter adapter, - Map> record, String attributeName) { + private void extractStringAttributeValues(DirContextAdapter adapter, Map> record, + String attributeName) { Object[] values = adapter.getObjectAttributes(attributeName); if (values == null || values.length == 0) { if (logger.isDebugEnabled()) { @@ -278,9 +266,8 @@ public class SpringSecurityLdapTemplate extends LdapTemplate { } else { if (logger.isDebugEnabled()) { - logger.debug("Attribute:" + attributeName - + " contains a non string value of type[" + o.getClass() - + "]"); + logger.debug("Attribute:" + attributeName + " contains a non string value of type[" + + o.getClass() + "]"); } svalues.add(o.toString()); } @@ -295,39 +282,33 @@ public class SpringSecurityLdapTemplate extends LdapTemplate { *

        * Ignores PartialResultException if thrown, for compatibility with Active * Directory (see {@link LdapTemplate#setIgnorePartialResultException(boolean)}). - * * @param base the search base, relative to the base context supplied by the context * source. * @param filter the LDAP search filter * @param params parameters to be substituted in the search. - * * @return a DirContextOperations instance created from the matching entry. - * * @throws IncorrectResultSizeDataAccessException if no results are found or the * search returns more than one result. */ - public DirContextOperations searchForSingleEntry(final String base, - final String filter, final Object[] params) { + public DirContextOperations searchForSingleEntry(final String base, final String filter, final Object[] params) { - return (DirContextOperations) executeReadOnly((ContextExecutor) ctx -> searchForSingleEntryInternal(ctx, searchControls, base, filter, - params)); + return (DirContextOperations) executeReadOnly( + (ContextExecutor) ctx -> searchForSingleEntryInternal(ctx, searchControls, base, filter, params)); } /** * Internal method extracted to avoid code duplication in AD search. */ - public static DirContextOperations searchForSingleEntryInternal(DirContext ctx, - SearchControls searchControls, String base, String filter, Object[] params) - throws NamingException { - final DistinguishedName ctxBaseDn = new DistinguishedName( - ctx.getNameInNamespace()); + public static DirContextOperations searchForSingleEntryInternal(DirContext ctx, SearchControls searchControls, + String base, String filter, Object[] params) throws NamingException { + final DistinguishedName ctxBaseDn = new DistinguishedName(ctx.getNameInNamespace()); final DistinguishedName searchBaseDn = new DistinguishedName(base); - final NamingEnumeration resultsEnum = ctx.search(searchBaseDn, - filter, params, buildControls(searchControls)); + final NamingEnumeration resultsEnum = ctx.search(searchBaseDn, filter, params, + buildControls(searchControls)); if (logger.isDebugEnabled()) { - logger.debug("Searching for entry under DN '" + ctxBaseDn + "', base = '" - + searchBaseDn + "', filter = '" + filter + "'"); + logger.debug("Searching for entry under DN '" + ctxBaseDn + "', base = '" + searchBaseDn + "', filter = '" + + filter + "'"); } Set results = new HashSet<>(); @@ -335,8 +316,7 @@ public class SpringSecurityLdapTemplate extends LdapTemplate { while (resultsEnum.hasMore()) { SearchResult searchResult = resultsEnum.next(); DirContextAdapter dca = (DirContextAdapter) searchResult.getObject(); - Assert.notNull(dca, - "No object returned by search, DirContext is not correctly configured"); + Assert.notNull(dca, "No object returned by search, DirContext is not correctly configured"); if (logger.isDebugEnabled()) { logger.debug("Found DN: " + dca.getDn()); @@ -367,19 +347,18 @@ public class SpringSecurityLdapTemplate extends LdapTemplate { * @return */ private static SearchControls buildControls(SearchControls originalControls) { - return new SearchControls(originalControls.getSearchScope(), - originalControls.getCountLimit(), originalControls.getTimeLimit(), - originalControls.getReturningAttributes(), RETURN_OBJECT, + return new SearchControls(originalControls.getSearchScope(), originalControls.getCountLimit(), + originalControls.getTimeLimit(), originalControls.getReturningAttributes(), RETURN_OBJECT, originalControls.getDerefLinkFlag()); } /** * Sets the search controls which will be used for search operations by the template. - * * @param searchControls the SearchControls instance which will be cached in the * template. */ public void setSearchControls(SearchControls searchControls) { this.searchControls = searchControls; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/AbstractLdapAuthenticationProvider.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/AbstractLdapAuthenticationProvider.java index 7fc3544929..957fd007e9 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/AbstractLdapAuthenticationProvider.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/AbstractLdapAuthenticationProvider.java @@ -46,16 +46,19 @@ import org.springframework.util.StringUtils; * @author Luke Taylor * @since 3.1 */ -public abstract class AbstractLdapAuthenticationProvider - implements AuthenticationProvider, MessageSourceAware { +public abstract class AbstractLdapAuthenticationProvider implements AuthenticationProvider, MessageSourceAware { + protected final Log logger = LogFactory.getLog(getClass()); + protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); + private boolean useAuthenticationRequestCredentials = true; + private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper(); + protected UserDetailsContextMapper userDetailsContextMapper = new LdapUserDetailsMapper(); - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, () -> this.messages.getMessage("LdapAuthenticationProvider.onlySupports", "Only UsernamePasswordAuthenticationToken is supported")); @@ -70,50 +73,44 @@ public abstract class AbstractLdapAuthenticationProvider } if (!StringUtils.hasLength(username)) { - throw new BadCredentialsException(this.messages.getMessage( - "LdapAuthenticationProvider.emptyUsername", "Empty Username")); + throw new BadCredentialsException( + this.messages.getMessage("LdapAuthenticationProvider.emptyUsername", "Empty Username")); } if (!StringUtils.hasLength(password)) { - throw new BadCredentialsException(this.messages.getMessage( - "AbstractLdapAuthenticationProvider.emptyPassword", - "Empty Password")); + throw new BadCredentialsException( + this.messages.getMessage("AbstractLdapAuthenticationProvider.emptyPassword", "Empty Password")); } Assert.notNull(password, "Null password was supplied in authentication token"); DirContextOperations userData = doAuthentication(userToken); - UserDetails user = this.userDetailsContextMapper.mapUserFromContext(userData, - authentication.getName(), - loadUserAuthorities(userData, authentication.getName(), - (String) authentication.getCredentials())); + UserDetails user = this.userDetailsContextMapper.mapUserFromContext(userData, authentication.getName(), + loadUserAuthorities(userData, authentication.getName(), (String) authentication.getCredentials())); return createSuccessfulAuthentication(userToken, user); } - protected abstract DirContextOperations doAuthentication( - UsernamePasswordAuthenticationToken auth); + protected abstract DirContextOperations doAuthentication(UsernamePasswordAuthenticationToken auth); - protected abstract Collection loadUserAuthorities( - DirContextOperations userData, String username, String password); + protected abstract Collection loadUserAuthorities(DirContextOperations userData, + String username, String password); /** * Creates the final {@code Authentication} object which will be returned from the * {@code authenticate} method. - * * @param authentication the original authentication request token * @param user the UserDetails instance returned by the configured * UserDetailsContextMapper. * @return the Authentication object for the fully authenticated user. */ - protected Authentication createSuccessfulAuthentication( - UsernamePasswordAuthenticationToken authentication, UserDetails user) { - Object password = this.useAuthenticationRequestCredentials - ? authentication.getCredentials() : user.getPassword(); + protected Authentication createSuccessfulAuthentication(UsernamePasswordAuthenticationToken authentication, + UserDetails user) { + Object password = this.useAuthenticationRequestCredentials ? authentication.getCredentials() + : user.getPassword(); - UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken( - user, password, + UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(user, password, this.authoritiesMapper.mapAuthorities(user.getAuthorities())); result.setDetails(authentication.getDetails()); @@ -130,11 +127,9 @@ public abstract class AbstractLdapAuthenticationProvider * obtained from the UserDetails object created by the configured * {@code UserDetailsContextMapper}. Often it will not be possible to read the * password from the directory, so defaults to true. - * * @param useAuthenticationRequestCredentials */ - public void setUseAuthenticationRequestCredentials( - boolean useAuthenticationRequestCredentials) { + public void setUseAuthenticationRequestCredentials(boolean useAuthenticationRequestCredentials) { this.useAuthenticationRequestCredentials = useAuthenticationRequestCredentials; } @@ -151,14 +146,11 @@ public abstract class AbstractLdapAuthenticationProvider * will be stored as the principal in the Authentication returned by the * {@link #createSuccessfulAuthentication(org.springframework.security.authentication.UsernamePasswordAuthenticationToken, org.springframework.security.core.userdetails.UserDetails)} * method. - * * @param userDetailsContextMapper the strategy instance. If not set, defaults to a * simple LdapUserDetailsMapper. */ - public void setUserDetailsContextMapper( - UserDetailsContextMapper userDetailsContextMapper) { - Assert.notNull(userDetailsContextMapper, - "UserDetailsContextMapper must not be null"); + public void setUserDetailsContextMapper(UserDetailsContextMapper userDetailsContextMapper) { + Assert.notNull(userDetailsContextMapper, "UserDetailsContextMapper must not be null"); this.userDetailsContextMapper = userDetailsContextMapper; } @@ -169,4 +161,5 @@ public abstract class AbstractLdapAuthenticationProvider protected UserDetailsContextMapper getUserDetailsContextMapper() { return this.userDetailsContextMapper; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/AbstractLdapAuthenticator.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/AbstractLdapAuthenticator.java index 0fb836a6ae..43d13eb4dc 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/AbstractLdapAuthenticator.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/AbstractLdapAuthenticator.java @@ -35,8 +35,8 @@ import java.util.List; * * @author Luke Taylor */ -public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, - InitializingBean, MessageSourceAware { +public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, InitializingBean, MessageSourceAware { + // ~ Instance fields // ================================================================================================ @@ -47,6 +47,7 @@ public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, * isn't sufficient */ private LdapUserSearch userSearch; + protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); /** @@ -64,7 +65,6 @@ public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, /** * Create an initialized instance with the {@link ContextSource} provided. - * * @param contextSource */ public AbstractLdapAuthenticator(ContextSource contextSource) { @@ -91,9 +91,7 @@ public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, /** * Builds list of possible DNs for the user, worked out from the * userDnPatterns property. - * * @param username the user's login name - * * @return the list of possible DN matches, empty if userDnPatterns wasn't * set. */ @@ -125,12 +123,10 @@ public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, /** * Sets the user attributes which will be retrieved from the directory. - * * @param userAttributes */ public void setUserAttributes(String[] userAttributes) { - Assert.notNull(userAttributes, - "The userAttributes property cannot be set to null"); + Assert.notNull(userAttributes, "The userAttributes property cannot be set to null"); this.userAttributes = userAttributes; } @@ -138,7 +134,6 @@ public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, * Sets the pattern which will be used to supply a DN for the user. The pattern should * be the name relative to the root DN. The pattern argument {0} will contain the * username. An example would be "cn={0},ou=people". - * * @param dnPattern the array of patterns which will be tried when converting a * username to a DN. */ @@ -156,4 +151,5 @@ public abstract class AbstractLdapAuthenticator implements LdapAuthenticator, Assert.notNull(userSearch, "The userSearch cannot be set to null"); this.userSearch = userSearch; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/BindAuthenticator.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/BindAuthenticator.java index 26dea8c4a7..a3433f094a 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/BindAuthenticator.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/BindAuthenticator.java @@ -39,10 +39,10 @@ import javax.naming.directory.DirContext; * An authenticator which binds as a user. * * @author Luke Taylor - * * @see AbstractLdapAuthenticator */ public class BindAuthenticator extends AbstractLdapAuthenticator { + // ~ Static fields/initializers // ===================================================================================== @@ -54,7 +54,6 @@ public class BindAuthenticator extends AbstractLdapAuthenticator { /** * Create an initialized instance using the {@link BaseLdapPathContextSource} * provided. - * * @param contextSource the BaseLdapPathContextSource instance against which bind * operations will be performed. * @@ -76,8 +75,7 @@ public class BindAuthenticator extends AbstractLdapAuthenticator { if (!StringUtils.hasLength(password)) { logger.debug("Rejecting empty password for user " + username); - throw new BadCredentialsException(messages.getMessage( - "BindAuthenticator.emptyPassword", "Empty Password")); + throw new BadCredentialsException(messages.getMessage("BindAuthenticator.emptyPassword", "Empty Password")); } // If DN patterns are configured, try authenticating with them directly @@ -93,25 +91,22 @@ public class BindAuthenticator extends AbstractLdapAuthenticator { // with the returned DN. if (user == null && getUserSearch() != null) { DirContextOperations userFromSearch = getUserSearch().searchForUser(username); - user = bindWithDn(userFromSearch.getDn().toString(), username, password, - userFromSearch.getAttributes()); + user = bindWithDn(userFromSearch.getDn().toString(), username, password, userFromSearch.getAttributes()); } if (user == null) { - throw new BadCredentialsException(messages.getMessage( - "BindAuthenticator.badCredentials", "Bad credentials")); + throw new BadCredentialsException( + messages.getMessage("BindAuthenticator.badCredentials", "Bad credentials")); } return user; } - private DirContextOperations bindWithDn(String userDnStr, String username, - String password) { + private DirContextOperations bindWithDn(String userDnStr, String username, String password) { return bindWithDn(userDnStr, username, password, null); } - private DirContextOperations bindWithDn(String userDnStr, String username, - String password, Attributes attrs) { + private DirContextOperations bindWithDn(String userDnStr, String username, String password, Attributes attrs) { BaseLdapPathContextSource ctxSource = (BaseLdapPathContextSource) getContextSource(); DistinguishedName userDn = new DistinguishedName(userDnStr); DistinguishedName fullDn = new DistinguishedName(userDn); @@ -123,16 +118,14 @@ public class BindAuthenticator extends AbstractLdapAuthenticator { try { ctx = getContextSource().getContext(fullDn.toString(), password); // Check for password policy control - PasswordPolicyControl ppolicy = PasswordPolicyControlExtractor - .extractControl(ctx); + PasswordPolicyControl ppolicy = PasswordPolicyControlExtractor.extractControl(ctx); logger.debug("Retrieving attributes..."); - if (attrs == null || attrs.size()==0) { + if (attrs == null || attrs.size() == 0) { attrs = ctx.getAttributes(userDn, getUserAttributes()); } - DirContextAdapter result = new DirContextAdapter(attrs, userDn, - ctxSource.getBaseLdapPath()); + DirContextAdapter result = new DirContextAdapter(attrs, userDn, ctxSource.getBaseLdapPath()); if (ppolicy != null) { result.setAttributeValue(ppolicy.getID(), ppolicy); @@ -172,4 +165,5 @@ public class BindAuthenticator extends AbstractLdapAuthenticator { logger.debug("Failed to bind as " + userDn + ": " + cause); } } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/LdapAuthenticationProvider.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/LdapAuthenticationProvider.java index 8381f2efcb..f2ab6ae526 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/LdapAuthenticationProvider.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/LdapAuthenticationProvider.java @@ -108,21 +108,22 @@ import org.springframework.util.Assert; * this means that if the LDAP directory is configured to allow unauthenticated access, it * might be possible to authenticate as any user just by supplying an empty * password. More information on the misuse of unauthenticated access can be found in - * draft - * -ietf-ldapbis-authmeth-19.txt. - * + * + * draft -ietf-ldapbis-authmeth-19.txt. * * @author Luke Taylor - * * @see BindAuthenticator * @see DefaultLdapAuthoritiesPopulator */ public class LdapAuthenticationProvider extends AbstractLdapAuthenticationProvider { + // ~ Instance fields // ================================================================================================ private LdapAuthenticator authenticator; + private LdapAuthoritiesPopulator authoritiesPopulator; + private boolean hideUserNotFoundExceptions = true; // ~ Constructors @@ -131,14 +132,12 @@ public class LdapAuthenticationProvider extends AbstractLdapAuthenticationProvid /** * Create an instance with the supplied authenticator and authorities populator * implementations. - * * @param authenticator the authentication strategy (bind, password comparison, etc) * to be used by this provider for authenticating users. * @param authoritiesPopulator the strategy for obtaining the authorities for a given * user after they've been authenticated. */ - public LdapAuthenticationProvider(LdapAuthenticator authenticator, - LdapAuthoritiesPopulator authoritiesPopulator) { + public LdapAuthenticationProvider(LdapAuthenticator authenticator, LdapAuthoritiesPopulator authoritiesPopulator) { this.setAuthenticator(authenticator); this.setAuthoritiesPopulator(authoritiesPopulator); } @@ -146,7 +145,6 @@ public class LdapAuthenticationProvider extends AbstractLdapAuthenticationProvid /** * Creates an instance with the supplied authenticator and a null authorities * populator. In this case, the authorities must be mapped from the user context. - * * @param authenticator the authenticator strategy. */ public LdapAuthenticationProvider(LdapAuthenticator authenticator) { @@ -167,8 +165,7 @@ public class LdapAuthenticationProvider extends AbstractLdapAuthenticationProvid } private void setAuthoritiesPopulator(LdapAuthoritiesPopulator authoritiesPopulator) { - Assert.notNull(authoritiesPopulator, - "An LdapAuthoritiesPopulator must be supplied"); + Assert.notNull(authoritiesPopulator, "An LdapAuthoritiesPopulator must be supplied"); this.authoritiesPopulator = authoritiesPopulator; } @@ -181,35 +178,33 @@ public class LdapAuthenticationProvider extends AbstractLdapAuthenticationProvid } @Override - protected DirContextOperations doAuthentication( - UsernamePasswordAuthenticationToken authentication) { + protected DirContextOperations doAuthentication(UsernamePasswordAuthenticationToken authentication) { try { return getAuthenticator().authenticate(authentication); } catch (PasswordPolicyException ppe) { // The only reason a ppolicy exception can occur during a bind is that the // account is locked. - throw new LockedException(this.messages.getMessage( - ppe.getStatus().getErrorCode(), ppe.getStatus().getDefaultMessage())); + throw new LockedException( + this.messages.getMessage(ppe.getStatus().getErrorCode(), ppe.getStatus().getDefaultMessage())); } catch (UsernameNotFoundException notFound) { if (this.hideUserNotFoundExceptions) { - throw new BadCredentialsException(this.messages.getMessage( - "LdapAuthenticationProvider.badCredentials", "Bad credentials")); + throw new BadCredentialsException( + this.messages.getMessage("LdapAuthenticationProvider.badCredentials", "Bad credentials")); } else { throw notFound; } } catch (NamingException ldapAccessFailure) { - throw new InternalAuthenticationServiceException( - ldapAccessFailure.getMessage(), ldapAccessFailure); + throw new InternalAuthenticationServiceException(ldapAccessFailure.getMessage(), ldapAccessFailure); } } @Override - protected Collection loadUserAuthorities( - DirContextOperations userData, String username, String password) { + protected Collection loadUserAuthorities(DirContextOperations userData, String username, + String password) { return getAuthoritiesPopulator().getGrantedAuthorities(userData, username); } diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/LdapAuthenticator.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/LdapAuthenticator.java index 93cd57730c..2bbfd295e8 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/LdapAuthenticator.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/LdapAuthenticator.java @@ -26,19 +26,19 @@ import org.springframework.ldap.core.DirContextOperations; * the information for that user from the directory. * * @author Luke Taylor - * * @see org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator * @see org.springframework.security.ldap.authentication.UserDetailsServiceLdapAuthoritiesPopulator */ public interface LdapAuthenticator { + // ~ Methods // ======================================================================================================== /** * Authenticates as a user and obtains additional user information from the directory. - * * @param authentication * @return the details of the successfully authenticated user. */ DirContextOperations authenticate(Authentication authentication); + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/LdapEncoder.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/LdapEncoder.java index 30ed9e4493..f7f4a4ccad 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/LdapEncoder.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/LdapEncoder.java @@ -1,245 +1,241 @@ -/* - * Copyright 2005-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.ldap.authentication; - -import org.springframework.ldap.BadLdapGrammarException; - -/** - * Helper class to encode and decode ldap names and values. - * - *

        - * NOTE: This is a copy from Spring LDAP so that both Spring LDAP 1.x and 2.x can be - * supported without reflection. - *

        - * - * @author Adam Skogman - * @author Mattias Hellborg Arthursson - */ -final class LdapEncoder { - - private static final int HEX = 16; - private static String[] NAME_ESCAPE_TABLE = new String[96]; - - private static String[] FILTER_ESCAPE_TABLE = new String['\\' + 1]; - - static { - - // Name encoding table ------------------------------------- - - // all below 0x20 (control chars) - for (char c = 0; c < ' '; c++) { - NAME_ESCAPE_TABLE[c] = "\\" + toTwoCharHex(c); - } - - NAME_ESCAPE_TABLE['#'] = "\\#"; - NAME_ESCAPE_TABLE[','] = "\\,"; - NAME_ESCAPE_TABLE[';'] = "\\;"; - NAME_ESCAPE_TABLE['='] = "\\="; - NAME_ESCAPE_TABLE['+'] = "\\+"; - NAME_ESCAPE_TABLE['<'] = "\\<"; - NAME_ESCAPE_TABLE['>'] = "\\>"; - NAME_ESCAPE_TABLE['\"'] = "\\\""; - NAME_ESCAPE_TABLE['\\'] = "\\\\"; - - // Filter encoding table ------------------------------------- - - // fill with char itself - for (char c = 0; c < FILTER_ESCAPE_TABLE.length; c++) { - FILTER_ESCAPE_TABLE[c] = String.valueOf(c); - } - - // escapes (RFC2254) - FILTER_ESCAPE_TABLE['*'] = "\\2a"; - FILTER_ESCAPE_TABLE['('] = "\\28"; - FILTER_ESCAPE_TABLE[')'] = "\\29"; - FILTER_ESCAPE_TABLE['\\'] = "\\5c"; - FILTER_ESCAPE_TABLE[0] = "\\00"; - - } - - /** - * All static methods - not to be instantiated. - */ - private LdapEncoder() { - } - - protected static String toTwoCharHex(char c) { - - String raw = Integer.toHexString(c).toUpperCase(); - - if (raw.length() > 1) { - return raw; - } - else { - return "0" + raw; - } - } - - /** - * Escape a value for use in a filter. - * - * @param value the value to escape. - * @return a properly escaped representation of the supplied value. - */ - public static String filterEncode(String value) { - - if (value == null) { - return null; - } - - // make buffer roomy - StringBuilder encodedValue = new StringBuilder(value.length() * 2); - - int length = value.length(); - - for (int i = 0; i < length; i++) { - - char c = value.charAt(i); - - if (c < FILTER_ESCAPE_TABLE.length) { - encodedValue.append(FILTER_ESCAPE_TABLE[c]); - } - else { - // default: add the char - encodedValue.append(c); - } - } - - return encodedValue.toString(); - } - - /** - * LDAP Encodes a value for use with a DN. Escapes for LDAP, not JNDI! - * - *
        - * Escapes:
        - * ' ' [space] - "\ " [if first or last]
        - * '#' [hash] - "\#"
        - * ',' [comma] - "\,"
        - * ';' [semicolon] - "\;"
        - * '= [equals] - "\="
        - * '+' [plus] - "\+"
        - * '<' [less than] - "\<"
        - * '>' [greater than] - "\>"
        - * '"' [double quote] - "\""
        - * '\' [backslash] - "\\"
        - * - * @param value the value to escape. - * @return The escaped value. - */ - public static String nameEncode(String value) { - - if (value == null) { - return null; - } - - // make buffer roomy - StringBuilder encodedValue = new StringBuilder(value.length() * 2); - - int length = value.length(); - int last = length - 1; - - for (int i = 0; i < length; i++) { - - char c = value.charAt(i); - - // space first or last - if (c == ' ' && (i == 0 || i == last)) { - encodedValue.append("\\ "); - continue; - } - - if (c < NAME_ESCAPE_TABLE.length) { - // check in table for escapes - String esc = NAME_ESCAPE_TABLE[c]; - - if (esc != null) { - encodedValue.append(esc); - continue; - } - } - - // default: add the char - encodedValue.append(c); - } - - return encodedValue.toString(); - - } - - /** - * Decodes a value. Converts escaped chars to ordinary chars. - * - * @param value Trimmed value, so no leading an trailing blanks, except an escaped - * space last. - * @return The decoded value as a string. - * @throws BadLdapGrammarException - */ - static public String nameDecode(String value) throws BadLdapGrammarException { - - if (value == null) { - return null; - } - - // make buffer same size - StringBuilder decoded = new StringBuilder(value.length()); - - int i = 0; - while (i < value.length()) { - char currentChar = value.charAt(i); - if (currentChar == '\\') { - if (value.length() <= i + 1) { - // Ending with a single backslash is not allowed - throw new BadLdapGrammarException( - "Unexpected end of value " + "unterminated '\\'"); - } - else { - char nextChar = value.charAt(i + 1); - if (nextChar == ',' || nextChar == '=' || nextChar == '+' - || nextChar == '<' || nextChar == '>' || nextChar == '#' - || nextChar == ';' || nextChar == '\\' || nextChar == '\"' - || nextChar == ' ') { - // Normal backslash escape - decoded.append(nextChar); - i += 2; - } - else { - if (value.length() <= i + 2) { - throw new BadLdapGrammarException("Unexpected end of value " - + "expected special or hex, found '" + nextChar - + "'"); - } - else { - // This should be a hex value - String hexString = "" + nextChar + value.charAt(i + 2); - decoded.append((char) Integer.parseInt(hexString, HEX)); - i += 3; - } - } - } - } - else { - // This character wasn't escaped - just append it - decoded.append(currentChar); - i++; - } - } - - return decoded.toString(); - - } -} +/* + * Copyright 2005-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.ldap.authentication; + +import org.springframework.ldap.BadLdapGrammarException; + +/** + * Helper class to encode and decode ldap names and values. + * + *

        + * NOTE: This is a copy from Spring LDAP so that both Spring LDAP 1.x and 2.x can be + * supported without reflection. + *

        + * + * @author Adam Skogman + * @author Mattias Hellborg Arthursson + */ +final class LdapEncoder { + + private static final int HEX = 16; + + private static String[] NAME_ESCAPE_TABLE = new String[96]; + + private static String[] FILTER_ESCAPE_TABLE = new String['\\' + 1]; + + static { + + // Name encoding table ------------------------------------- + + // all below 0x20 (control chars) + for (char c = 0; c < ' '; c++) { + NAME_ESCAPE_TABLE[c] = "\\" + toTwoCharHex(c); + } + + NAME_ESCAPE_TABLE['#'] = "\\#"; + NAME_ESCAPE_TABLE[','] = "\\,"; + NAME_ESCAPE_TABLE[';'] = "\\;"; + NAME_ESCAPE_TABLE['='] = "\\="; + NAME_ESCAPE_TABLE['+'] = "\\+"; + NAME_ESCAPE_TABLE['<'] = "\\<"; + NAME_ESCAPE_TABLE['>'] = "\\>"; + NAME_ESCAPE_TABLE['\"'] = "\\\""; + NAME_ESCAPE_TABLE['\\'] = "\\\\"; + + // Filter encoding table ------------------------------------- + + // fill with char itself + for (char c = 0; c < FILTER_ESCAPE_TABLE.length; c++) { + FILTER_ESCAPE_TABLE[c] = String.valueOf(c); + } + + // escapes (RFC2254) + FILTER_ESCAPE_TABLE['*'] = "\\2a"; + FILTER_ESCAPE_TABLE['('] = "\\28"; + FILTER_ESCAPE_TABLE[')'] = "\\29"; + FILTER_ESCAPE_TABLE['\\'] = "\\5c"; + FILTER_ESCAPE_TABLE[0] = "\\00"; + + } + + /** + * All static methods - not to be instantiated. + */ + private LdapEncoder() { + } + + protected static String toTwoCharHex(char c) { + + String raw = Integer.toHexString(c).toUpperCase(); + + if (raw.length() > 1) { + return raw; + } + else { + return "0" + raw; + } + } + + /** + * Escape a value for use in a filter. + * @param value the value to escape. + * @return a properly escaped representation of the supplied value. + */ + public static String filterEncode(String value) { + + if (value == null) { + return null; + } + + // make buffer roomy + StringBuilder encodedValue = new StringBuilder(value.length() * 2); + + int length = value.length(); + + for (int i = 0; i < length; i++) { + + char c = value.charAt(i); + + if (c < FILTER_ESCAPE_TABLE.length) { + encodedValue.append(FILTER_ESCAPE_TABLE[c]); + } + else { + // default: add the char + encodedValue.append(c); + } + } + + return encodedValue.toString(); + } + + /** + * LDAP Encodes a value for use with a DN. Escapes for LDAP, not JNDI! + * + *
        + * Escapes:
        + * ' ' [space] - "\ " [if first or last]
        + * '#' [hash] - "\#"
        + * ',' [comma] - "\,"
        + * ';' [semicolon] - "\;"
        + * '= [equals] - "\="
        + * '+' [plus] - "\+"
        + * '<' [less than] - "\<"
        + * '>' [greater than] - "\>"
        + * '"' [double quote] - "\""
        + * '\' [backslash] - "\\"
        + * @param value the value to escape. + * @return The escaped value. + */ + public static String nameEncode(String value) { + + if (value == null) { + return null; + } + + // make buffer roomy + StringBuilder encodedValue = new StringBuilder(value.length() * 2); + + int length = value.length(); + int last = length - 1; + + for (int i = 0; i < length; i++) { + + char c = value.charAt(i); + + // space first or last + if (c == ' ' && (i == 0 || i == last)) { + encodedValue.append("\\ "); + continue; + } + + if (c < NAME_ESCAPE_TABLE.length) { + // check in table for escapes + String esc = NAME_ESCAPE_TABLE[c]; + + if (esc != null) { + encodedValue.append(esc); + continue; + } + } + + // default: add the char + encodedValue.append(c); + } + + return encodedValue.toString(); + + } + + /** + * Decodes a value. Converts escaped chars to ordinary chars. + * @param value Trimmed value, so no leading an trailing blanks, except an escaped + * space last. + * @return The decoded value as a string. + * @throws BadLdapGrammarException + */ + static public String nameDecode(String value) throws BadLdapGrammarException { + + if (value == null) { + return null; + } + + // make buffer same size + StringBuilder decoded = new StringBuilder(value.length()); + + int i = 0; + while (i < value.length()) { + char currentChar = value.charAt(i); + if (currentChar == '\\') { + if (value.length() <= i + 1) { + // Ending with a single backslash is not allowed + throw new BadLdapGrammarException("Unexpected end of value " + "unterminated '\\'"); + } + else { + char nextChar = value.charAt(i + 1); + if (nextChar == ',' || nextChar == '=' || nextChar == '+' || nextChar == '<' || nextChar == '>' + || nextChar == '#' || nextChar == ';' || nextChar == '\\' || nextChar == '\"' + || nextChar == ' ') { + // Normal backslash escape + decoded.append(nextChar); + i += 2; + } + else { + if (value.length() <= i + 2) { + throw new BadLdapGrammarException( + "Unexpected end of value " + "expected special or hex, found '" + nextChar + "'"); + } + else { + // This should be a hex value + String hexString = "" + nextChar + value.charAt(i + 2); + decoded.append((char) Integer.parseInt(hexString, HEX)); + i += 3; + } + } + } + } + else { + // This character wasn't escaped - just append it + decoded.append(currentChar); + i++; + } + } + + return decoded.toString(); + + } + +} diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/NullLdapAuthoritiesPopulator.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/NullLdapAuthoritiesPopulator.java index a14f1ffb3c..8f32bc29e3 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/NullLdapAuthoritiesPopulator.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/NullLdapAuthoritiesPopulator.java @@ -23,13 +23,13 @@ import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator; /** - * * @author Luke Taylor * @since 3.0 */ public final class NullLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator { - public Collection getGrantedAuthorities( - DirContextOperations userDetails, String username) { + + public Collection getGrantedAuthorities(DirContextOperations userDetails, String username) { return AuthorityUtils.NO_AUTHORITIES; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java index 348c16dcb4..1b9e765a86 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java @@ -47,17 +47,19 @@ import org.springframework.util.Assert; * @author Luke Taylor */ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthenticator { + // ~ Static fields/initializers // ===================================================================================== - private static final Log logger = LogFactory - .getLog(PasswordComparisonAuthenticator.class); + private static final Log logger = LogFactory.getLog(PasswordComparisonAuthenticator.class); // ~ Instance fields // ================================================================================================ private PasswordEncoder passwordEncoder = new LdapShaPasswordEncoder(KeyGenerators.shared(0)); + private String passwordAttributeName = "userPassword"; + private boolean usePasswordAttrCompare = false; // ~ Constructors @@ -79,8 +81,7 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic String username = authentication.getName(); String password = (String) authentication.getCredentials(); - SpringSecurityLdapTemplate ldapTemplate = new SpringSecurityLdapTemplate( - getContextSource()); + SpringSecurityLdapTemplate ldapTemplate = new SpringSecurityLdapTemplate(getContextSource()); for (String userDn : getUserDns(username)) { try { @@ -102,8 +103,8 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic } if (logger.isDebugEnabled()) { - logger.debug("Performing LDAP compare of password attribute '" - + passwordAttributeName + "' for user '" + user.getDn() + "'"); + logger.debug("Performing LDAP compare of password attribute '" + passwordAttributeName + "' for user '" + + user.getDn() + "'"); } if (usePasswordAttrCompare && isPasswordAttrCompare(user, password)) { @@ -112,8 +113,8 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic else if (isLdapPasswordCompare(user, ldapTemplate, password)) { return user; } - throw new BadCredentialsException(messages.getMessage( - "PasswordComparisonAuthenticator.badCredentials", "Bad credentials")); + throw new BadCredentialsException( + messages.getMessage("PasswordComparisonAuthenticator.badCredentials", "Bad credentials")); } private boolean isPasswordAttrCompare(DirContextOperations user, String password) { @@ -132,17 +133,15 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic return String.valueOf(passwordAttrValue); } - private boolean isLdapPasswordCompare(DirContextOperations user, - SpringSecurityLdapTemplate ldapTemplate, String password) { + private boolean isLdapPasswordCompare(DirContextOperations user, SpringSecurityLdapTemplate ldapTemplate, + String password) { String encodedPassword = passwordEncoder.encode(password); byte[] passwordBytes = Utf8.encode(encodedPassword); - return ldapTemplate.compare(user.getDn().toString(), passwordAttributeName, - passwordBytes); + return ldapTemplate.compare(user.getDn().toString(), passwordAttributeName, passwordBytes); } public void setPasswordAttributeName(String passwordAttribute) { - Assert.hasLength(passwordAttribute, - "passwordAttributeName must not be empty or null"); + Assert.hasLength(passwordAttribute, "passwordAttributeName must not be empty or null"); this.passwordAttributeName = passwordAttribute; } @@ -155,4 +154,5 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic this.passwordEncoder = passwordEncoder; setUsePasswordAttrCompare(true); } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/SpringSecurityAuthenticationSource.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/SpringSecurityAuthenticationSource.java index 0ee20693e0..164b032fcc 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/SpringSecurityAuthenticationSource.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/SpringSecurityAuthenticationSource.java @@ -36,17 +36,15 @@ import org.apache.commons.logging.LogFactory; * @since 2.0 */ public class SpringSecurityAuthenticationSource implements AuthenticationSource { - private static final Log log = LogFactory - .getLog(SpringSecurityAuthenticationSource.class); + + private static final Log log = LogFactory.getLog(SpringSecurityAuthenticationSource.class); /** * Get the principals of the logged in user, in this case the distinguished name. - * * @return the distinguished name of the logged in user. */ public String getPrincipal() { - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { log.warn("No Authentication object set in SecurityContext - returning empty String as Principal"); @@ -67,8 +65,7 @@ public class SpringSecurityAuthenticationSource implements AuthenticationSource } else { throw new IllegalArgumentException( - "The principal property of the authentication object" - + "needs to be an LdapUserDetails."); + "The principal property of the authentication object" + "needs to be an LdapUserDetails."); } } @@ -76,8 +73,7 @@ public class SpringSecurityAuthenticationSource implements AuthenticationSource * @see org.springframework.ldap.core.AuthenticationSource#getCredentials() */ public String getCredentials() { - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { log.warn("No Authentication object set in SecurityContext - returning empty String as Credentials"); @@ -86,4 +82,5 @@ public class SpringSecurityAuthenticationSource implements AuthenticationSource return (String) authentication.getCredentials(); } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/UserDetailsServiceLdapAuthoritiesPopulator.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/UserDetailsServiceLdapAuthoritiesPopulator.java index 3f91dedfb4..d845eaafb0 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/UserDetailsServiceLdapAuthoritiesPopulator.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/UserDetailsServiceLdapAuthoritiesPopulator.java @@ -27,12 +27,11 @@ import org.springframework.util.Assert; * Simple LdapAuthoritiesPopulator which delegates to a UserDetailsService, using the name * which was supplied at login as the username. * - * * @author Luke Taylor * @since 2.0 */ -public class UserDetailsServiceLdapAuthoritiesPopulator implements - LdapAuthoritiesPopulator { +public class UserDetailsServiceLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator { + private final UserDetailsService userDetailsService; public UserDetailsServiceLdapAuthoritiesPopulator(UserDetailsService userService) { @@ -40,8 +39,9 @@ public class UserDetailsServiceLdapAuthoritiesPopulator implements this.userDetailsService = userService; } - public Collection getGrantedAuthorities( - DirContextOperations userData, String username) { + public Collection getGrantedAuthorities(DirContextOperations userData, + String username) { return userDetailsService.loadUserByUsername(username).getAuthorities(); } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryAuthenticationException.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryAuthenticationException.java index 9f5c287e71..b6473ceaff 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryAuthenticationException.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryAuthenticationException.java @@ -41,10 +41,10 @@ import org.springframework.security.core.AuthenticationException; */ @SuppressWarnings("serial") public final class ActiveDirectoryAuthenticationException extends AuthenticationException { + private final String dataCode; - ActiveDirectoryAuthenticationException(String dataCode, String message, - Throwable cause) { + ActiveDirectoryAuthenticationException(String dataCode, String message, Throwable cause) { super(message, cause); this.dataCode = dataCode; } @@ -52,4 +52,5 @@ public final class ActiveDirectoryAuthenticationException extends Authentication public String getDataCode() { return dataCode; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider.java index afcb2fa87e..241ebcde4b 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider.java @@ -53,8 +53,8 @@ import java.util.regex.Pattern; * Specialized LDAP authentication provider which uses Active Directory configuration * conventions. *

        - * It will authenticate using the Active Directory + * It will authenticate using the Active Directory + * * {@code userPrincipalName} or a custom {@link #setSearchFilter(String) searchFilter} * in the form {@code username@domain}. If the username does not already end with the * domain name, the {@code userPrincipalName} will be built by appending the configured @@ -90,26 +90,37 @@ import java.util.regex.Pattern; * @author Rob Winch * @since 3.1 */ -public final class ActiveDirectoryLdapAuthenticationProvider extends - AbstractLdapAuthenticationProvider { - private static final Pattern SUB_ERROR_CODE = Pattern - .compile(".*data\\s([0-9a-f]{3,4}).*"); +public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLdapAuthenticationProvider { + + private static final Pattern SUB_ERROR_CODE = Pattern.compile(".*data\\s([0-9a-f]{3,4}).*"); // Error codes private static final int USERNAME_NOT_FOUND = 0x525; + private static final int INVALID_PASSWORD = 0x52e; + private static final int NOT_PERMITTED = 0x530; + private static final int PASSWORD_EXPIRED = 0x532; + private static final int ACCOUNT_DISABLED = 0x533; + private static final int ACCOUNT_EXPIRED = 0x701; + private static final int PASSWORD_NEEDS_RESET = 0x773; + private static final int ACCOUNT_LOCKED = 0x775; private final String domain; + private final String rootDn; + private final String url; + private boolean convertSubErrorCodesToExceptions; + private String searchFilter = "(&(objectClass=user)(userPrincipalName={0}))"; + private Map contextEnvironmentProperties = new HashMap<>(); // Only used to allow tests to substitute a mock LdapContext @@ -120,8 +131,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends * @param url an LDAP url (or multiple URLs) * @param rootDn the root DN (may be null or empty) */ - public ActiveDirectoryLdapAuthenticationProvider(String domain, String url, - String rootDn) { + public ActiveDirectoryLdapAuthenticationProvider(String domain, String url, String rootDn) { Assert.isTrue(StringUtils.hasText(url), "Url cannot be empty"); this.domain = StringUtils.hasText(domain) ? domain.toLowerCase() : null; this.url = url; @@ -140,8 +150,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends } @Override - protected DirContextOperations doAuthentication( - UsernamePasswordAuthenticationToken auth) { + protected DirContextOperations doAuthentication(UsernamePasswordAuthenticationToken auth) { String username = auth.getName(); String password = (String) auth.getCredentials(); DirContext ctx = null; @@ -154,8 +163,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends throw badLdapConnection(e); } catch (NamingException e) { - logger.error("Failed to locate directory entry for authenticated user: " - + username, e); + logger.error("Failed to locate directory entry for authenticated user: " + username, e); throw badCredentials(e); } finally { @@ -168,8 +176,8 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends * obtained from the user's Active Directory entry. */ @Override - protected Collection loadUserAuthorities( - DirContextOperations userData, String username, String password) { + protected Collection loadUserAuthorities(DirContextOperations userData, String username, + String password) { String[] groups = userData.getStringAttributes("memberOf"); if (groups == null) { @@ -182,12 +190,10 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends logger.debug("'memberOf' attribute values: " + Arrays.asList(groups)); } - ArrayList authorities = new ArrayList<>( - groups.length); + ArrayList authorities = new ArrayList<>(groups.length); for (String group : groups) { - authorities.add(new SimpleGrantedAuthority(new DistinguishedName(group) - .removeLast().getValue())); + authorities.add(new SimpleGrantedAuthority(new DistinguishedName(group).removeLast().getValue())); } return authorities; @@ -211,11 +217,11 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends return contextFactory.createContext(env); } catch (NamingException e) { - if ((e instanceof AuthenticationException) - || (e instanceof OperationNotSupportedException)) { + if ((e instanceof AuthenticationException) || (e instanceof OperationNotSupportedException)) { handleBindException(bindPrincipal, e); throw badCredentials(e); - } else { + } + else { throw LdapUtils.convertLdapException(e); } } @@ -235,8 +241,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends return; } - logger.info("Active Directory authentication failed: " - + subCodeToLogMessage(subErrorCode)); + logger.info("Active Directory authentication failed: " + subCodeToLogMessage(subErrorCode)); if (convertSubErrorCodesToExceptions) { raiseExceptionForErrorCode(subErrorCode, exception); @@ -263,23 +268,20 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends private void raiseExceptionForErrorCode(int code, NamingException exception) { String hexString = Integer.toHexString(code); - Throwable cause = new ActiveDirectoryAuthenticationException(hexString, - exception.getMessage(), exception); + Throwable cause = new ActiveDirectoryAuthenticationException(hexString, exception.getMessage(), exception); switch (code) { case PASSWORD_EXPIRED: - throw new CredentialsExpiredException(messages.getMessage( - "LdapAuthenticationProvider.credentialsExpired", + throw new CredentialsExpiredException(messages.getMessage("LdapAuthenticationProvider.credentialsExpired", "User credentials have expired"), cause); case ACCOUNT_DISABLED: - throw new DisabledException(messages.getMessage( - "LdapAuthenticationProvider.disabled", "User is disabled"), cause); - case ACCOUNT_EXPIRED: - throw new AccountExpiredException(messages.getMessage( - "LdapAuthenticationProvider.expired", "User account has expired"), + throw new DisabledException(messages.getMessage("LdapAuthenticationProvider.disabled", "User is disabled"), cause); + case ACCOUNT_EXPIRED: + throw new AccountExpiredException( + messages.getMessage("LdapAuthenticationProvider.expired", "User account has expired"), cause); case ACCOUNT_LOCKED: - throw new LockedException(messages.getMessage( - "LdapAuthenticationProvider.locked", "User account is locked"), cause); + throw new LockedException( + messages.getMessage("LdapAuthenticationProvider.locked", "User account is locked"), cause); default: throw badCredentials(cause); } @@ -309,8 +311,8 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends } private BadCredentialsException badCredentials() { - return new BadCredentialsException(messages.getMessage( - "LdapAuthenticationProvider.badCredentials", "Bad credentials")); + return new BadCredentialsException( + messages.getMessage("LdapAuthenticationProvider.badCredentials", "Bad credentials")); } private BadCredentialsException badCredentials(Throwable cause) { @@ -319,23 +321,19 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends private InternalAuthenticationServiceException badLdapConnection(Throwable cause) { return new InternalAuthenticationServiceException(messages.getMessage( - "LdapAuthenticationProvider.badLdapConnection", - "Connection to LDAP server failed."), cause); + "LdapAuthenticationProvider.badLdapConnection", "Connection to LDAP server failed."), cause); } - private DirContextOperations searchForUser(DirContext context, String username) - throws NamingException { + private DirContextOperations searchForUser(DirContext context, String username) throws NamingException { SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); String bindPrincipal = createBindPrincipal(username); - String searchRoot = rootDn != null ? rootDn - : searchRootFromPrincipal(bindPrincipal); + String searchRoot = rootDn != null ? rootDn : searchRootFromPrincipal(bindPrincipal); try { - return SpringSecurityLdapTemplate.searchForSingleEntryInternal(context, - searchControls, searchRoot, searchFilter, - new Object[] { bindPrincipal, username }); + return SpringSecurityLdapTemplate.searchForSingleEntryInternal(context, searchControls, searchRoot, + searchFilter, new Object[] { bindPrincipal, username }); } catch (CommunicationException ldapCommunicationException) { throw badLdapConnection(ldapCommunicationException); @@ -362,8 +360,7 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends throw badCredentials(); } - return rootDnFromDomain(bindPrincipal.substring(atChar + 1, - bindPrincipal.length())); + return rootDnFromDomain(bindPrincipal.substring(atChar + 1, bindPrincipal.length())); } private String rootDnFromDomain(String domain) { @@ -398,12 +395,10 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends * {@link AccountExpiredException} or {@link LockedException} will be thrown for the * corresponding codes. All other codes will result in the default * {@code BadCredentialsException}. - * * @param convertSubErrorCodesToExceptions {@code true} to raise an exception based on * the AD error code. */ - public void setConvertSubErrorCodesToExceptions( - boolean convertSubErrorCodesToExceptions) { + public void setConvertSubErrorCodesToExceptions(boolean convertSubErrorCodesToExceptions) { this.convertSubErrorCodesToExceptions = convertSubErrorCodesToExceptions; } @@ -414,7 +409,6 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends *

        * Defaults to: {@code (&(objectClass=user)(userPrincipalName={0}))} *

        - * * @param searchFilter the filter string * * @since 3.2.6 @@ -426,8 +420,8 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends /** * Allows a custom environment properties to be used to create initial LDAP context. - * - * @param environment the additional environment parameters to use when creating the LDAP Context + * @param environment the additional environment parameters to use when creating the + * LDAP Context */ public void setContextEnvironmentProperties(Map environment) { Assert.notEmpty(environment, "environment must not be empty"); @@ -435,8 +429,11 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends } static class ContextFactory { + DirContext createContext(Hashtable env) throws NamingException { return new InitialLdapContext(env, null); } + } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/package-info.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/package-info.java index fee0732440..b1331c2ed2 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/package-info.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/package-info.java @@ -14,13 +14,11 @@ * limitations under the License. */ /** - * The LDAP authentication provider package. Interfaces are provided for - * both authentication and retrieval of user roles from an LDAP server. + * The LDAP authentication provider package. Interfaces are provided for both + * authentication and retrieval of user roles from an LDAP server. *

        - * The main provider class is LdapAuthenticationProvider. - * This is configured with an LdapAuthenticator instance and - * an LdapAuthoritiesPopulator. The latter is used to obtain the - * list of roles for the user. + * The main provider class is LdapAuthenticationProvider. This is configured with + * an LdapAuthenticator instance and an LdapAuthoritiesPopulator. The + * latter is used to obtain the list of roles for the user. */ package org.springframework.security.ldap.authentication; - diff --git a/ldap/src/main/java/org/springframework/security/ldap/package-info.java b/ldap/src/main/java/org/springframework/security/ldap/package-info.java index 70dc7c7526..75cb5f4eeb 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/package-info.java +++ b/ldap/src/main/java/org/springframework/security/ldap/package-info.java @@ -17,4 +17,3 @@ * Spring Security's LDAP module. */ package org.springframework.security.ldap; - diff --git a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSource.java b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSource.java index 249f3736a0..173582036d 100755 --- a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSource.java +++ b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSource.java @@ -44,8 +44,7 @@ public class PasswordPolicyAwareContextSource extends DefaultSpringSecurityConte } @Override - public DirContext getContext(String principal, String credentials) - throws PasswordPolicyException { + public DirContext getContext(String principal, String credentials) throws PasswordPolicyException { if (principal.equals(userDn)) { return super.getContext(principal, credentials); } @@ -53,8 +52,7 @@ public class PasswordPolicyAwareContextSource extends DefaultSpringSecurityConte final boolean debug = logger.isDebugEnabled(); if (debug) { - logger.debug("Binding as '" + userDn + "', prior to reconnect as user '" - + principal + "'"); + logger.debug("Binding as '" + userDn + "', prior to reconnect as user '" + principal + "'"); } // First bind as manager user before rebinding as the specific principal. @@ -68,8 +66,7 @@ public class PasswordPolicyAwareContextSource extends DefaultSpringSecurityConte ctx.reconnect(rctls); } catch (javax.naming.NamingException ne) { - PasswordPolicyResponseControl ctrl = PasswordPolicyControlExtractor - .extractControl(ctx); + PasswordPolicyResponseControl ctrl = PasswordPolicyControlExtractor.extractControl(ctx); if (debug) { logger.debug("Failed to obtain context", ne); logger.debug("Password policy response: " + ctrl); @@ -87,8 +84,7 @@ public class PasswordPolicyAwareContextSource extends DefaultSpringSecurityConte } if (debug) { - logger.debug("PPolicy control returned: " - + PasswordPolicyControlExtractor.extractControl(ctx)); + logger.debug("PPolicy control returned: " + PasswordPolicyControlExtractor.extractControl(ctx)); } return ctx; @@ -99,9 +95,9 @@ public class PasswordPolicyAwareContextSource extends DefaultSpringSecurityConte protected Hashtable getAuthenticatedEnv(String principal, String credentials) { Hashtable env = super.getAuthenticatedEnv(principal, credentials); - env.put(LdapContext.CONTROL_FACTORIES, - PasswordPolicyControlFactory.class.getName()); + env.put(LdapContext.CONTROL_FACTORIES, PasswordPolicyControlFactory.class.getName()); return env; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControl.java b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControl.java index 9d45957fa3..4e070a0337 100755 --- a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControl.java +++ b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControl.java @@ -28,10 +28,10 @@ import javax.naming.ldap.Control; * * @author Stefan Zoerner * @author Luke Taylor - * * @see PasswordPolicyResponseControl */ public class PasswordPolicyControl implements Control { + // ~ Static fields/initializers // ===================================================================================== @@ -55,7 +55,6 @@ public class PasswordPolicyControl implements Control { /** * Creates a (request) control. - * * @param critical indicates whether the control is critical for the client */ public PasswordPolicyControl(boolean critical) { @@ -68,7 +67,6 @@ public class PasswordPolicyControl implements Control { /** * Retrieves the ASN.1 BER encoded value of the LDAP control. The request value for * this control is always empty. - * * @return always null */ public byte[] getEncodedValue() { @@ -88,4 +86,5 @@ public class PasswordPolicyControl implements Control { public boolean isCritical() { return critical; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControlExtractor.java b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControlExtractor.java index 715972ecf9..b69802d368 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControlExtractor.java +++ b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControlExtractor.java @@ -29,8 +29,8 @@ import org.apache.commons.logging.LogFactory; * @since 3.0 */ public class PasswordPolicyControlExtractor { - private static final Log logger = LogFactory - .getLog(PasswordPolicyControlExtractor.class); + + private static final Log logger = LogFactory.getLog(PasswordPolicyControlExtractor.class); public static PasswordPolicyResponseControl extractControl(DirContext dirCtx) { LdapContext ctx = (LdapContext) dirCtx; diff --git a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControlFactory.java b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControlFactory.java index 8584e1e42e..ea8d3927e9 100755 --- a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControlFactory.java +++ b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControlFactory.java @@ -26,6 +26,7 @@ import javax.naming.ldap.ControlFactory; * @author Luke Taylor */ public class PasswordPolicyControlFactory extends ControlFactory { + // ~ Methods // ======================================================================================================== @@ -33,9 +34,7 @@ public class PasswordPolicyControlFactory extends ControlFactory { * Creates an instance of PasswordPolicyResponseControl if the passed control is a * response control of this type. Attributes of the result are filled with the correct * values (e.g. error code). - * * @param ctl the control the check - * * @return a response control of type PasswordPolicyResponseControl, or null */ public Control getControlInstance(Control ctl) { @@ -45,4 +44,5 @@ public class PasswordPolicyControlFactory extends ControlFactory { return null; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyData.java b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyData.java index 0a69477b9f..343744e3c1 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyData.java +++ b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyData.java @@ -20,7 +20,9 @@ package org.springframework.security.ldap.ppolicy; * @since 3.0 */ public interface PasswordPolicyData { + int getTimeBeforeExpiration(); int getGraceLoginsRemaining(); + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyErrorStatus.java b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyErrorStatus.java index 02a289e29a..a9e52267a6 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyErrorStatus.java +++ b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyErrorStatus.java @@ -39,20 +39,24 @@ package org.springframework.security.ldap.ppolicy; * @since 3.0 */ public enum PasswordPolicyErrorStatus { - PASSWORD_EXPIRED("ppolicy.expired", "Your password has expired"), ACCOUNT_LOCKED( - "ppolicy.locked", "Account is locked"), CHANGE_AFTER_RESET( - "ppolicy.change.after.reset", - "Your password must be changed after being reset"), PASSWORD_MOD_NOT_ALLOWED( - "ppolicy.mod.not.allowed", "Password cannot be changed"), MUST_SUPPLY_OLD_PASSWORD( - "ppolicy.must.supply.old.password", "The old password must be supplied"), INSUFFICIENT_PASSWORD_QUALITY( - "ppolicy.insufficient.password.quality", - "The supplied password is of insufficient quality"), PASSWORD_TOO_SHORT( - "ppolicy.password.too.short", "The supplied password is too short"), PASSWORD_TOO_YOUNG( - "ppolicy.password.too.young", - "Your password was changed too recently to be changed again"), PASSWORD_IN_HISTORY( - "ppolicy.password.in.history", "The supplied password has already been used"); + + PASSWORD_EXPIRED("ppolicy.expired", "Your password has expired"), ACCOUNT_LOCKED("ppolicy.locked", + "Account is locked"), CHANGE_AFTER_RESET("ppolicy.change.after.reset", + "Your password must be changed after being reset"), PASSWORD_MOD_NOT_ALLOWED( + "ppolicy.mod.not.allowed", + "Password cannot be changed"), MUST_SUPPLY_OLD_PASSWORD("ppolicy.must.supply.old.password", + "The old password must be supplied"), INSUFFICIENT_PASSWORD_QUALITY( + "ppolicy.insufficient.password.quality", + "The supplied password is of insufficient quality"), PASSWORD_TOO_SHORT( + "ppolicy.password.too.short", + "The supplied password is too short"), PASSWORD_TOO_YOUNG( + "ppolicy.password.too.young", + "Your password was changed too recently to be changed again"), PASSWORD_IN_HISTORY( + "ppolicy.password.in.history", + "The supplied password has already been used"); private final String errorCode; + private final String defaultMessage; PasswordPolicyErrorStatus(String errorCode, String defaultMessage) { @@ -67,4 +71,5 @@ public enum PasswordPolicyErrorStatus { public String getDefaultMessage() { return defaultMessage; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyException.java b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyException.java index c276a71b02..62d4106d1b 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyException.java +++ b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyException.java @@ -25,6 +25,7 @@ package org.springframework.security.ldap.ppolicy; * @since 3.0 */ public class PasswordPolicyException extends RuntimeException { + private final PasswordPolicyErrorStatus status; public PasswordPolicyException(PasswordPolicyErrorStatus status) { @@ -35,4 +36,5 @@ public class PasswordPolicyException extends RuntimeException { public PasswordPolicyErrorStatus getStatus() { return status; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyResponseControl.java b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyResponseControl.java index f2c92d7b64..103df7161d 100755 --- a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyResponseControl.java +++ b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/PasswordPolicyResponseControl.java @@ -41,20 +41,19 @@ import org.springframework.dao.DataRetrievalFailureException; * graceLoginsRemaining. *

        * - * * @author Stefan Zoerner * @author Luke Taylor - * * @see org.springframework.security.ldap.ppolicy.PasswordPolicyControl - * @see Stefan - * Zoerner's IBM developerworks article on LDAP controls. + * @see Stefan Zoerner's + * IBM developerworks article on LDAP controls. */ public class PasswordPolicyResponseControl extends PasswordPolicyControl { + // ~ Static fields/initializers // ===================================================================================== - private static final Log logger = LogFactory - .getLog(PasswordPolicyResponseControl.class); + private static final Log logger = LogFactory.getLog(PasswordPolicyResponseControl.class); // ~ Instance fields // ================================================================================================ @@ -64,6 +63,7 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl { private PasswordPolicyErrorStatus errorStatus; private int graceLoginsRemaining = Integer.MAX_VALUE; + private int timeBeforeExpiration = Integer.MAX_VALUE; // ~ Constructors @@ -116,7 +116,6 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl { /** * Returns the graceLoginsRemaining. - * * @return Returns the graceLoginsRemaining. */ public int getGraceLoginsRemaining() { @@ -125,7 +124,6 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl { /** * Returns the timeBeforeExpiration. - * * @return Returns the time before expiration in seconds */ public int getTimeBeforeExpiration() { @@ -134,7 +132,6 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl { /** * Checks whether an error is present. - * * @return true, if an error is present */ public boolean hasError() { @@ -143,12 +140,10 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl { /** * Checks whether a warning is present. - * * @return true, if a warning is present */ public boolean hasWarning() { - return (this.graceLoginsRemaining != Integer.MAX_VALUE) - || (this.timeBeforeExpiration != Integer.MAX_VALUE); + return (this.graceLoginsRemaining != Integer.MAX_VALUE) || (this.timeBeforeExpiration != Integer.MAX_VALUE); } public boolean isExpired() { @@ -165,7 +160,6 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl { /** * Determines whether an account locked error has been returned. - * * @return true if the account is locked. */ public boolean isLocked() { @@ -175,7 +169,6 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl { /** * Create a textual representation containing error and warning messages, if any are * present. - * * @return error and warning messages */ @Override @@ -187,13 +180,11 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl { } if (this.graceLoginsRemaining != Integer.MAX_VALUE) { - sb.append(", warning: ").append(this.graceLoginsRemaining) - .append(" grace logins remain"); + sb.append(", warning: ").append(this.graceLoginsRemaining).append(" grace logins remain"); } if (this.timeBeforeExpiration != Integer.MAX_VALUE) { - sb.append(", warning: time before expiration is ") - .append(this.timeBeforeExpiration); + sb.append(", warning: time before expiration is ").append(this.timeBeforeExpiration); } if (!hasError() && !hasWarning()) { @@ -207,7 +198,9 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl { // =============================================================================================== private interface PPolicyDecoder { + void decode() throws IOException; + } // ~ Inner Classes @@ -217,19 +210,16 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl { * Decoder based on Netscape ldapsdk library */ private class NetscapeDecoder implements PPolicyDecoder { + public void decode() throws IOException { int[] bread = { 0 }; - BERSequence seq = (BERSequence) BERElement - .getElement(new SpecificTagDecoder(), - new ByteArrayInputStream( - PasswordPolicyResponseControl.this.encodedValue), - bread); + BERSequence seq = (BERSequence) BERElement.getElement(new SpecificTagDecoder(), + new ByteArrayInputStream(PasswordPolicyResponseControl.this.encodedValue), bread); int size = seq.size(); if (logger.isDebugEnabled()) { - logger.debug("PasswordPolicyResponse, ASN.1 sequence has " + size - + " elements"); + logger.debug("PasswordPolicyResponse, ASN.1 sequence has " + size + " elements"); } for (int i = 0; i < seq.size(); i++) { @@ -252,20 +242,20 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl { } else if (tag == 1) { BERIntegral error = (BERIntegral) elt.getValue(); - PasswordPolicyResponseControl.this.errorStatus = PasswordPolicyErrorStatus - .values()[error.getValue()]; + PasswordPolicyResponseControl.this.errorStatus = PasswordPolicyErrorStatus.values()[error + .getValue()]; } } } class SpecificTagDecoder extends BERTagDecoder { + /** Allows us to remember which of the two options we're decoding */ private Boolean inChoice = null; @Override - public BERElement getElement(BERTagDecoder decoder, int tag, - InputStream stream, int[] bytesRead, boolean[] implicit) - throws IOException { + public BERElement getElement(BERTagDecoder decoder, int tag, InputStream stream, int[] bytesRead, + boolean[] implicit) throws IOException { tag &= 0x1F; implicit[0] = false; @@ -278,8 +268,7 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl { BERElement.readLengthOctets(stream, bytesRead); int[] componentLength = new int[1]; - BERElement choice = new BERChoice(decoder, stream, - componentLength); + BERElement choice = new BERChoice(decoder, stream, componentLength); bytesRead[0] += componentLength[0]; // inChoice = null; @@ -312,7 +301,9 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl { private void setInChoice(boolean inChoice) { this.inChoice = inChoice; } + } + } /** Decoder based on the OpenLDAP/Novell JLDAP library */ @@ -377,4 +368,5 @@ public class PasswordPolicyResponseControl extends PasswordPolicyControl { // } // } // } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/package-info.java b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/package-info.java index 8bbbc99b7a..398ff32cbc 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/ppolicy/package-info.java +++ b/ldap/src/main/java/org/springframework/security/ldap/ppolicy/package-info.java @@ -14,11 +14,11 @@ * limitations under the License. */ /** - * Implementation of password policy functionality based on the - * + * Implementation of password policy functionality based on the * Password Policy for LDAP Directories. *

        - * This code will not work with servers such as Active Directory, which do not implement this standard. + * This code will not work with servers such as Active Directory, which do not implement + * this standard. */ package org.springframework.security.ldap.ppolicy; - diff --git a/ldap/src/main/java/org/springframework/security/ldap/search/FilterBasedLdapUserSearch.java b/ldap/src/main/java/org/springframework/security/ldap/search/FilterBasedLdapUserSearch.java index b58b884f00..dcb8de53ce 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/search/FilterBasedLdapUserSearch.java +++ b/ldap/src/main/java/org/springframework/security/ldap/search/FilterBasedLdapUserSearch.java @@ -37,10 +37,10 @@ import javax.naming.directory.SearchControls; * * @author Robert Sanders * @author Luke Taylor - * * @see SearchControls */ public class FilterBasedLdapUserSearch implements LdapUserSearch { + // ~ Static fields/initializers // ===================================================================================== @@ -57,7 +57,9 @@ public class FilterBasedLdapUserSearch implements LdapUserSearch { */ private final SearchControls searchControls = new SearchControls(); - /** Context name to search in, relative to the base of the configured ContextSource. */ + /** + * Context name to search in, relative to the base of the configured ContextSource. + */ private String searchBase = ""; /** @@ -79,12 +81,10 @@ public class FilterBasedLdapUserSearch implements LdapUserSearch { // ~ Constructors // =================================================================================================== - public FilterBasedLdapUserSearch(String searchBase, String searchFilter, - BaseLdapPathContextSource contextSource) { + public FilterBasedLdapUserSearch(String searchBase, String searchFilter, BaseLdapPathContextSource contextSource) { Assert.notNull(contextSource, "contextSource must not be null"); Assert.notNull(searchFilter, "searchFilter must not be null."); - Assert.notNull(searchBase, - "searchBase must not be null (an empty string is acceptable)."); + Assert.notNull(searchBase, "searchBase must not be null (an empty string is acceptable)."); this.searchFilter = searchFilter; this.contextSource = contextSource; @@ -93,8 +93,8 @@ public class FilterBasedLdapUserSearch implements LdapUserSearch { setSearchSubtree(true); if (searchBase.length() == 0) { - logger.info("SearchBase not set. Searches will be performed from the root: " - + contextSource.getBaseLdapPath()); + logger.info( + "SearchBase not set. Searches will be performed from the root: " + contextSource.getBaseLdapPath()); } } @@ -103,36 +103,29 @@ public class FilterBasedLdapUserSearch implements LdapUserSearch { /** * Return the LdapUserDetails containing the user's information - * * @param username the username to search for. - * * @return An LdapUserDetails object containing the details of the located user's * directory entry - * * @throws UsernameNotFoundException if no matching entry is found. */ @Override public DirContextOperations searchForUser(String username) { if (logger.isDebugEnabled()) { - logger.debug("Searching for user '" + username + "', with user search " - + this); + logger.debug("Searching for user '" + username + "', with user search " + this); } - SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate( - contextSource); + SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(contextSource); template.setSearchControls(searchControls); try { - return template.searchForSingleEntry(searchBase, searchFilter, - new String[] { username }); + return template.searchForSingleEntry(searchBase, searchFilter, new String[] { username }); } catch (IncorrectResultSizeDataAccessException notFound) { if (notFound.getActualSize() == 0) { - throw new UsernameNotFoundException("User " + username - + " not found in directory."); + throw new UsernameNotFoundException("User " + username + " not found in directory."); } // Search should never return multiple results if properly configured, so just // rethrow @@ -143,7 +136,6 @@ public class FilterBasedLdapUserSearch implements LdapUserSearch { /** * Sets the corresponding property on the {@link SearchControls} instance used in the * search. - * * @param deref the derefLinkFlag value as defined in SearchControls.. */ public void setDerefLinkFlag(boolean deref) { @@ -153,18 +145,15 @@ public class FilterBasedLdapUserSearch implements LdapUserSearch { /** * If true then searches the entire subtree as identified by context, if false (the * default) then only searches the level identified by the context. - * * @param searchSubtree true the underlying search controls should be set to * SearchControls.SUBTREE_SCOPE rather than SearchControls.ONELEVEL_SCOPE. */ public void setSearchSubtree(boolean searchSubtree) { - searchControls.setSearchScope(searchSubtree ? SearchControls.SUBTREE_SCOPE - : SearchControls.ONELEVEL_SCOPE); + searchControls.setSearchScope(searchSubtree ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE); } /** * The time to wait before the search fails; the default is zero, meaning forever. - * * @param searchTimeLimit the time limit for the search (in milliseconds). */ public void setSearchTimeLimit(int searchTimeLimit) { @@ -176,7 +165,6 @@ public class FilterBasedLdapUserSearch implements LdapUserSearch { *

        * null indicates that all attributes will be returned. An empty array indicates no * attributes are returned. - * * @param attrs An array of attribute names identifying the attributes that will be * returned. Can be null. */ @@ -191,11 +179,10 @@ public class FilterBasedLdapUserSearch implements LdapUserSearch { sb.append("[ searchFilter: '").append(searchFilter).append("', "); sb.append("searchBase: '").append(searchBase).append("'"); sb.append(", scope: ") - .append(searchControls.getSearchScope() == SearchControls.SUBTREE_SCOPE ? "subtree" - : "single-level, "); + .append(searchControls.getSearchScope() == SearchControls.SUBTREE_SCOPE ? "subtree" : "single-level, "); sb.append(", searchTimeLimit: ").append(searchControls.getTimeLimit()); - sb.append(", derefLinkFlag: ").append(searchControls.getDerefLinkFlag()) - .append(" ]"); + sb.append(", derefLinkFlag: ").append(searchControls.getDerefLinkFlag()).append(" ]"); return sb.toString(); } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/search/LdapUserSearch.java b/ldap/src/main/java/org/springframework/security/ldap/search/LdapUserSearch.java index e0d86b8eaf..73524f679f 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/search/LdapUserSearch.java +++ b/ldap/src/main/java/org/springframework/security/ldap/search/LdapUserSearch.java @@ -28,19 +28,19 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException; * @author Luke Taylor */ public interface LdapUserSearch { + // ~ Methods // ======================================================================================================== /** * Locates a single user in the directory and returns the LDAP information for that * user. - * * @param username the login name supplied to the authentication service. - * * @return a DirContextOperations object containing the user's full DN and requested * attributes. * @throws UsernameNotFoundException if no user with the supplied name could be * located by the search. */ DirContextOperations searchForUser(String username) throws UsernameNotFoundException; + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/search/package-info.java b/ldap/src/main/java/org/springframework/security/ldap/search/package-info.java index 0aa23b3e4e..bb8675406e 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/search/package-info.java +++ b/ldap/src/main/java/org/springframework/security/ldap/search/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * {@code LdapUserSearch} implementations. These may be used to locate the user in the directory. + * {@code LdapUserSearch} implementations. These may be used to locate the user in the + * directory. */ package org.springframework.security.ldap.search; - diff --git a/ldap/src/main/java/org/springframework/security/ldap/server/ApacheDSContainer.java b/ldap/src/main/java/org/springframework/security/ldap/server/ApacheDSContainer.java index f02dd51edc..7b5401da77 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/server/ApacheDSContainer.java +++ b/ldap/src/main/java/org/springframework/security/ldap/server/ApacheDSContainer.java @@ -65,8 +65,8 @@ import org.springframework.util.Assert; * application context is closed to allow the bean to be disposed of and the server * shutdown prior to attempting to start it again. *

        - * This class is intended for testing and internal security namespace use, only, and is not - * considered part of the framework's public API. + * This class is intended for testing and internal security namespace use, only, and is + * not considered part of the framework's public API. * * @author Luke Taylor * @author Rob Winch @@ -76,26 +76,36 @@ import org.springframework.util.Assert; * supported with no GA version to replace it. */ @Deprecated -public class ApacheDSContainer implements InitializingBean, DisposableBean, Lifecycle, - ApplicationContextAware { +public class ApacheDSContainer implements InitializingBean, DisposableBean, Lifecycle, ApplicationContextAware { + private final Log logger = LogFactory.getLog(getClass()); final DefaultDirectoryService service; + LdapServer server; private TcpTransport transport; + private ApplicationContext ctxt; + private File workingDir; private boolean running; + private final String ldifResources; + private final JdbmPartition partition; + private final String root; + private int port = 53389; + private int localPort; private boolean ldapOverSslEnabled; + private File keyStoreFile; + private String certificatePassord; public ApacheDSContainer(String root, String ldifs) throws Exception { @@ -150,9 +160,9 @@ public class ApacheDSContainer implements InitializingBean, DisposableBean, Life this.transport = new TcpTransport(port); if (ldapOverSslEnabled) { - transport.setEnableSSL(true); - server.setKeystoreFile(this.keyStoreFile.getAbsolutePath()); - server.setCertificatePassword(this.certificatePassord); + transport.setEnableSSL(true); + server.setKeystoreFile(this.keyStoreFile.getAbsolutePath()); + server.setCertificatePassword(this.certificatePassord); } server.setTransports(transport); start(); @@ -162,24 +172,20 @@ public class ApacheDSContainer implements InitializingBean, DisposableBean, Life stop(); } - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ctxt = applicationContext; } public void setWorkingDirectory(File workingDir) { Assert.notNull(workingDir, "workingDir cannot be null"); - logger.info("Setting working directory for LDAP_PROVIDER: " - + workingDir.getAbsolutePath()); + logger.info("Setting working directory for LDAP_PROVIDER: " + workingDir.getAbsolutePath()); if (workingDir.exists()) { - throw new IllegalArgumentException( - "The specified working directory '" - + workingDir.getAbsolutePath() - + "' already exists. Another directory service instance may be using it or it may be from a " - + " previous unclean shutdown. Please confirm and delete it or configure a different " - + "working directory"); + throw new IllegalArgumentException("The specified working directory '" + workingDir.getAbsolutePath() + + "' already exists. Another directory service instance may be using it or it may be from a " + + " previous unclean shutdown. Please confirm and delete it or configure a different " + + "working directory"); } this.workingDir = workingDir; @@ -197,7 +203,6 @@ public class ApacheDSContainer implements InitializingBean, DisposableBean, Life /** * Returns the port that is resolved by {@link TcpTransport}. - * * @return the port that is resolved by {@link TcpTransport} */ public int getLocalPort() { @@ -207,7 +212,6 @@ public class ApacheDSContainer implements InitializingBean, DisposableBean, Life /** * If set to {@code true} will enable LDAP over SSL (LDAPs). If set to {@code true} * {@link ApacheDSContainer#setCertificatePassord(String)} must be set as well. - * * @param ldapOverSslEnabled If not set, will default to false */ public void setLdapOverSslEnabled(boolean ldapOverSslEnabled) { @@ -215,7 +219,8 @@ public class ApacheDSContainer implements InitializingBean, DisposableBean, Life } /** - * The keyStore must not be null and must be a valid file. Will set the keyStore file on the underlying {@link LdapServer}. + * The keyStore must not be null and must be a valid file. Will set the keyStore file + * on the underlying {@link LdapServer}. * @param keyStoreFile Mandatory if LDAPs is enabled */ public void setKeyStoreFile(File keyStoreFile) { @@ -226,7 +231,6 @@ public class ApacheDSContainer implements InitializingBean, DisposableBean, Life /** * Will set the certificate password on the underlying {@link LdapServer}. - * * @param certificatePassord May be null */ public void setCertificatePassord(String certificatePassord) { @@ -345,14 +349,13 @@ public class ApacheDSContainer implements InitializingBean, DisposableBean, Life ldifFile = ldifs[0].getURI().toString(); } logger.info("Loading LDIF file: " + ldifFile); - LdifFileLoader loader = new LdifFileLoader(service.getAdminSession(), - new File(ldifFile), null, getClass().getClassLoader()); + LdifFileLoader loader = new LdifFileLoader(service.getAdminSession(), new File(ldifFile), null, + getClass().getClassLoader()); loader.execute(); } else { - throw new IllegalArgumentException( - "More than one LDIF resource found with the supplied pattern:" - + ldifResources + " Got " + Arrays.toString(ldifs)); + throw new IllegalArgumentException("More than one LDIF resource found with the supplied pattern:" + + ldifResources + " Got " + Arrays.toString(ldifs)); } } @@ -369,8 +372,8 @@ public class ApacheDSContainer implements InitializingBean, DisposableBean, Life fileName = fileNamePrefix + "~" + i; } - throw new IOException("Failed to create a temporary directory for file at " - + new File(parentTempDir, fileNamePrefix)); + throw new IOException( + "Failed to create a temporary directory for file at " + new File(parentTempDir, fileNamePrefix)); } private boolean deleteDir(File dir) { @@ -390,4 +393,5 @@ public class ApacheDSContainer implements InitializingBean, DisposableBean, Life public boolean isRunning() { return running; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/server/UnboundIdContainer.java b/ldap/src/main/java/org/springframework/security/ldap/server/UnboundIdContainer.java index 9d5794be27..7055cf98ac 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/server/UnboundIdContainer.java +++ b/ldap/src/main/java/org/springframework/security/ldap/server/UnboundIdContainer.java @@ -37,8 +37,7 @@ import org.springframework.util.StringUtils; /** * @author Eddú Meléndez */ -public class UnboundIdContainer implements InitializingBean, DisposableBean, Lifecycle, - ApplicationContextAware { +public class UnboundIdContainer implements InitializingBean, DisposableBean, Lifecycle, ApplicationContextAware { private InMemoryDirectoryServer directoryServer; @@ -106,7 +105,8 @@ public class UnboundIdContainer implements InitializingBean, DisposableBean, Lif this.port = directoryServer.getListenPort(); this.directoryServer = directoryServer; this.running = true; - } catch (LDAPException ex) { + } + catch (LDAPException ex) { throw new RuntimeException("Server startup failed", ex); } @@ -124,7 +124,8 @@ public class UnboundIdContainer implements InitializingBean, DisposableBean, Lif directoryServer.importFromLDIF(false, new LDIFReader(inputStream)); } } - } catch (Exception ex) { + } + catch (Exception ex) { throw new IllegalStateException("Unable to load LDIF " + this.ldif, ex); } } @@ -139,4 +140,5 @@ public class UnboundIdContainer implements InitializingBean, DisposableBean, Lif public boolean isRunning() { return this.running; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/server/package-info.java b/ldap/src/main/java/org/springframework/security/ldap/server/package-info.java index 8b1c1f1484..00ac9262f7 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/server/package-info.java +++ b/ldap/src/main/java/org/springframework/security/ldap/server/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Embedded Apache Directory Server implementation, as used by the configuration namespace. + * Embedded Apache Directory Server implementation, as used by the configuration + * namespace. */ package org.springframework.security.ldap.server; - diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulator.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulator.java index 12f311f1c8..b0856d8d19 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulator.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/DefaultLdapAuthoritiesPopulator.java @@ -99,11 +99,11 @@ import org.springframework.util.Assert; * @author Filip Hanik */ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator { + // ~ Static fields/initializers // ===================================================================================== - private static final Log logger = LogFactory - .getLog(DefaultLdapAuthoritiesPopulator.class); + private static final Log logger = LogFactory.getLog(DefaultLdapAuthoritiesPopulator.class); // ~ Instance fields // ================================================================================================ @@ -160,13 +160,11 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator /** * Constructor for group search scenarios. userRoleAttributes may still be * set as a property. - * * @param contextSource supplies the contexts used to search for user roles. * @param groupSearchBase if this is an empty string the search will be performed from * the root DN of the context factory. If null, no search will be performed. */ - public DefaultLdapAuthoritiesPopulator(ContextSource contextSource, - String groupSearchBase) { + public DefaultLdapAuthoritiesPopulator(ContextSource contextSource, String groupSearchBase) { Assert.notNull(contextSource, "contextSource must not be null"); this.ldapTemplate = new SpringSecurityLdapTemplate(contextSource); getLdapTemplate().setSearchControls(getSearchControls()); @@ -176,8 +174,7 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator logger.info("groupSearchBase is null. No group search will be performed."); } else if (groupSearchBase.length() == 0) { - logger.info( - "groupSearchBase is empty. Searches will be performed from the context source base"); + logger.info("groupSearchBase is empty. Searches will be performed from the context source base"); } this.authorityMapper = record -> { @@ -198,27 +195,23 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator * This method should be overridden if required to obtain any additional roles for the * given user (on top of those obtained from the standard search implemented by this * class). - * * @param user the context representing the user who's roles are required * @return the extra roles which will be merged with those returned by the group * search */ - protected Set getAdditionalRoles(DirContextOperations user, - String username) { + protected Set getAdditionalRoles(DirContextOperations user, String username) { return null; } /** * Obtains the authorities for the user who's directory entry is represented by the * supplied LdapUserDetails object. - * * @param user the user who's authorities are required * @return the set of roles granted to the user. */ @Override - public final Collection getGrantedAuthorities( - DirContextOperations user, String username) { + public final Collection getGrantedAuthorities(DirContextOperations user, String username) { String userDn = user.getNameInNamespace(); if (logger.isDebugEnabled()) { @@ -251,16 +244,13 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator Set authorities = new HashSet<>(); if (logger.isDebugEnabled()) { - logger.debug("Searching for roles for user '" + username + "', DN = " + "'" - + userDn + "', with filter " + this.groupSearchFilter - + " in search base '" + getGroupSearchBase() + "'"); + logger.debug("Searching for roles for user '" + username + "', DN = " + "'" + userDn + "', with filter " + + this.groupSearchFilter + " in search base '" + getGroupSearchBase() + "'"); } - Set>> userRoles = getLdapTemplate() - .searchForMultipleAttributeValues(getGroupSearchBase(), - this.groupSearchFilter, - new String[] { userDn, username }, - new String[] { this.groupRoleAttribute }); + Set>> userRoles = getLdapTemplate().searchForMultipleAttributeValues( + getGroupSearchBase(), this.groupSearchFilter, new String[] { userDn, username }, + new String[] { this.groupRoleAttribute }); if (logger.isDebugEnabled()) { logger.debug("Roles from search: " + userRoles); @@ -290,7 +280,6 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator /** * The default role which will be assigned to all users. - * * @param defaultRole the role name, including any desired prefix. */ public void setDefaultRole(String defaultRole) { @@ -320,13 +309,11 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator /** * If set to true, a subtree scope search will be performed. If false a single-level * search is used. - * * @param searchSubtree set to true to enable searching of the entire tree below the * groupSearchBase. */ public void setSearchSubtree(boolean searchSubtree) { - int searchScope = searchSubtree ? SearchControls.SUBTREE_SCOPE - : SearchControls.ONELEVEL_SCOPE; + int searchScope = searchSubtree ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE; this.searchControls.setSearchScope(searchScope); } @@ -341,9 +328,8 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator } /** - * Sets the mapping function which will be used to create instances of {@link GrantedAuthority} - * given the context record. - * + * Sets the mapping function which will be used to create instances of + * {@link GrantedAuthority} given the context record. * @param authorityMapper the mapping function */ public void setAuthorityMapper(Function>, GrantedAuthority> authorityMapper) { @@ -419,4 +405,5 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator private SearchControls getSearchControls() { return this.searchControls; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/InetOrgPerson.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/InetOrgPerson.java index dc0969115b..4f28e05ae5 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/InetOrgPerson.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/InetOrgPerson.java @@ -33,26 +33,43 @@ public class InetOrgPerson extends Person { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private String carLicense; + // Person.cn private String destinationIndicator; + private String departmentNumber; + // Person.description private String displayName; + private String employeeNumber; + private String homePhone; + private String homePostalAddress; + private String initials; + private String mail; + private String mobile; + private String o; + private String ou; + private String postalAddress; + private String postalCode; + private String roomNumber; + private String street; + // Person.sn // Person.telephoneNumber private String title; + private String uid; public String getUid() { @@ -146,11 +163,12 @@ public class InetOrgPerson extends Person { adapter.setAttributeValue("roomNumber", roomNumber); adapter.setAttributeValue("street", street); adapter.setAttributeValue("uid", uid); - adapter.setAttributeValues("objectclass", new String[] { "top", "person", - "organizationalPerson", "inetOrgPerson" }); + adapter.setAttributeValues("objectclass", + new String[] { "top", "person", "organizationalPerson", "inetOrgPerson" }); } public static class Essence extends Person.Essence { + public Essence() { } @@ -277,5 +295,7 @@ public class InetOrgPerson extends Person { public void setHomePostalAddress(String homePostalAddress) { ((InetOrgPerson) instance).homePostalAddress = homePostalAddress; } + } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/InetOrgPersonContextMapper.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/InetOrgPersonContextMapper.java index f75cbfca58..e3bc69af94 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/InetOrgPersonContextMapper.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/InetOrgPersonContextMapper.java @@ -40,10 +40,10 @@ public class InetOrgPersonContextMapper implements UserDetailsContextMapper { } public void mapUserToContext(UserDetails user, DirContextAdapter ctx) { - Assert.isInstanceOf(InetOrgPerson.class, user, - "UserDetails must be an InetOrgPerson instance"); + Assert.isInstanceOf(InetOrgPerson.class, user, "UserDetails must be an InetOrgPerson instance"); InetOrgPerson p = (InetOrgPerson) user; p.populateContext(ctx); } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapAuthoritiesPopulator.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapAuthoritiesPopulator.java index 0a18f2c36a..fc2562c4b5 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapAuthoritiesPopulator.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapAuthoritiesPopulator.java @@ -32,17 +32,16 @@ import org.springframework.ldap.core.DirContextOperations; * @author Luke Taylor */ public interface LdapAuthoritiesPopulator { + // ~ Methods // ======================================================================================================== /** * Get the list of authorities for the user. - * * @param userData the context object which was returned by the LDAP authenticator. - * * @return the granted authorities for the given user. * */ - Collection getGrantedAuthorities( - DirContextOperations userData, String username); + Collection getGrantedAuthorities(DirContextOperations userData, String username); + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapAuthority.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapAuthority.java index 362bf0e874..dc8c80a0ff 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapAuthority.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapAuthority.java @@ -31,12 +31,13 @@ import java.util.Map; public class LdapAuthority implements GrantedAuthority { private String dn; + private String role; + private Map> attributes; /** * Constructs an LdapAuthority that has a role and a DN but no other attributes - * * @param role * @param dn */ @@ -46,7 +47,6 @@ public class LdapAuthority implements GrantedAuthority { /** * Constructs an LdapAuthority with the given role, DN and other LDAP attributes - * * @param role * @param dn * @param attributes @@ -62,7 +62,6 @@ public class LdapAuthority implements GrantedAuthority { /** * Returns the LDAP attributes - * * @return the LDAP attributes, map can be null */ public Map> getAttributes() { @@ -71,7 +70,6 @@ public class LdapAuthority implements GrantedAuthority { /** * Returns the DN for this LDAP authority - * * @return */ public String getDn() { @@ -80,7 +78,6 @@ public class LdapAuthority implements GrantedAuthority { /** * Returns the values for a specific attribute - * * @param name the attribute name * @return a String array, never null but may be zero length */ @@ -97,7 +94,6 @@ public class LdapAuthority implements GrantedAuthority { /** * Returns the first attribute value for a specified attribute - * * @param name * @return the first attribute value for a specified attribute, may be null */ @@ -151,4 +147,5 @@ public class LdapAuthority implements GrantedAuthority { public String toString() { return "LdapAuthority{" + "dn='" + dn + '\'' + ", role='" + role + '\'' + '}'; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetails.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetails.java index 4729184fca..f3963adc6a 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetails.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetails.java @@ -25,13 +25,14 @@ import org.springframework.security.core.userdetails.UserDetails; * @author Luke Taylor */ public interface LdapUserDetails extends UserDetails, CredentialsContainer { + // ~ Methods // ======================================================================================================== /** * The DN of the entry for this user's account. - * * @return the user's DN */ String getDn(); + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsImpl.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsImpl.java index 831aa3c1ac..543e769013 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsImpl.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsImpl.java @@ -55,15 +55,24 @@ public class LdapUserDetailsImpl implements LdapUserDetails, PasswordPolicyData // ================================================================================================ private String dn; + private String password; + private String username; + private Collection authorities = AuthorityUtils.NO_AUTHORITIES; + private boolean accountNonExpired = true; + private boolean accountNonLocked = true; + private boolean credentialsNonExpired = true; + private boolean enabled = true; + // PPolicy data private int timeBeforeExpiration = Integer.MAX_VALUE; + private int graceLoginsRemaining = Integer.MAX_VALUE; // ~ Constructors @@ -152,8 +161,7 @@ public class LdapUserDetailsImpl implements LdapUserDetails, PasswordPolicyData sb.append("Password: [PROTECTED]; "); sb.append("Enabled: ").append(this.enabled).append("; "); sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; "); - sb.append("CredentialsNonExpired: ").append(this.credentialsNonExpired) - .append("; "); + sb.append("CredentialsNonExpired: ").append(this.credentialsNonExpired).append("; "); sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; "); if (this.getAuthorities() != null && !this.getAuthorities().isEmpty()) { @@ -185,7 +193,9 @@ public class LdapUserDetailsImpl implements LdapUserDetails, PasswordPolicyData * Variation of essence pattern. Used to create mutable intermediate object */ public static class Essence { + protected LdapUserDetailsImpl instance = createTarget(); + private List mutableAuthorities = new ArrayList<>(); public Essence() { @@ -230,8 +240,7 @@ public class LdapUserDetailsImpl implements LdapUserDetails, PasswordPolicyData } public LdapUserDetails createUserDetails() { - Assert.notNull(instance, - "Essence can only be used to create a single instance"); + Assert.notNull(instance, "Essence can only be used to create a single instance"); Assert.notNull(instance.username, "username must not be null"); Assert.notNull(instance.getDn(), "Distinguished name must not be null"); @@ -292,5 +301,7 @@ public class LdapUserDetailsImpl implements LdapUserDetails, PasswordPolicyData public void setGraceLoginsRemaining(int graceLoginsRemaining) { instance.graceLoginsRemaining = graceLoginsRemaining; } + } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManager.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManager.java index af8f214591..37d4078219 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManager.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManager.java @@ -76,14 +76,14 @@ import org.springframework.util.Assert; * @since 2.0 */ public class LdapUserDetailsManager implements UserDetailsManager { + private final Log logger = LogFactory.getLog(LdapUserDetailsManager.class); /** * The strategy for mapping usernames to LDAP distinguished names. This will be used * when building DNs for creating new users etc. */ - LdapUsernameToDnMapper usernameMapper = new DefaultLdapUsernameToDnMapper("cn=users", - "uid"); + LdapUsernameToDnMapper usernameMapper = new DefaultLdapUsernameToDnMapper("cn=users", "uid"); /** The DN under which groups are stored */ private DistinguishedName groupSearchBase = new DistinguishedName("cn=groups"); @@ -93,6 +93,7 @@ public class LdapUserDetailsManager implements UserDetailsManager { /** The attribute which corresponds to the role name of a group. */ private String groupRoleAttributeName = "cn"; + /** The attribute which contains members of a group */ private String groupMemberAttributeName = "uniquemember"; @@ -100,6 +101,7 @@ public class LdapUserDetailsManager implements UserDetailsManager { /** The pattern to be used for the user search. {0} is the user's DN */ private String groupSearchFilter = "(uniquemember={0})"; + /** * The strategy used to create a UserDetails object from the LDAP context, username * and list of authorities. This should be set to match the required UserDetails @@ -140,16 +142,14 @@ public class LdapUserDetailsManager implements UserDetailsManager { return userDetailsMapper.mapUserFromContext(userCtx, username, authorities); } - private DirContextAdapter loadUserAsContext(final DistinguishedName dn, - final String username) { + private DirContextAdapter loadUserAsContext(final DistinguishedName dn, final String username) { return (DirContextAdapter) template.executeReadOnly((ContextExecutor) ctx -> { try { Attributes attrs = ctx.getAttributes(dn, attributesToRetrieve); return new DirContextAdapter(attrs, LdapUtils.getFullDn(dn, ctx)); } catch (NameNotFoundException notFound) { - throw new UsernameNotFoundException( - "User " + username + " not found", notFound); + throw new UsernameNotFoundException("User " + username + " not found", notFound); } }); } @@ -163,28 +163,25 @@ public class LdapUserDetailsManager implements UserDetailsManager { * *

        * Configured one way, this method will modify the user's password via the - * - * LDAP Password Modify Extended Operation - * . + * LDAP Password Modify + * Extended Operation . * - * See {@link LdapUserDetailsManager#setUsePasswordModifyExtensionOperation(boolean)} for details. + * See {@link LdapUserDetailsManager#setUsePasswordModifyExtensionOperation(boolean)} + * for details. *

        * *

        - * By default, though, if the old password is supplied, the update will be made by rebinding as the user, - * thus modifying the password using the user's permissions. If + * By default, though, if the old password is supplied, the update will be made by + * rebinding as the user, thus modifying the password using the user's permissions. If * oldPassword is null, the update will be attempted using a standard * read/write context supplied by the context source. *

        - * * @param oldPassword the old password * @param newPassword the new value of the password. */ public void changePassword(final String oldPassword, final String newPassword) { - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); - Assert.notNull( - authentication, + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Assert.notNull(authentication, "No authentication object found in security context. Can't change current user's password!"); String username = authentication.getName(); @@ -195,32 +192,29 @@ public class LdapUserDetailsManager implements UserDetailsManager { if (usePasswordModifyExtensionOperation) { changePasswordUsingExtensionOperation(userDn, oldPassword, newPassword); - } else { + } + else { changePasswordUsingAttributeModification(userDn, oldPassword, newPassword); } } /** - * * @param dn the distinguished name of the entry - may be either relative to the base * context or a complete DN including the name of the context (either is supported). * @param username the user whose roles are required. * @return the granted authorities returned by the group search */ @SuppressWarnings("unchecked") - List getUserAuthorities(final DistinguishedName dn, - final String username) { + List getUserAuthorities(final DistinguishedName dn, final String username) { SearchExecutor se = ctx -> { DistinguishedName fullDn = LdapUtils.getFullDn(dn, ctx); SearchControls ctrls = new SearchControls(); ctrls.setReturningAttributes(new String[] { groupRoleAttributeName }); - return ctx.search(groupSearchBase, groupSearchFilter, new String[] { - fullDn.toUrl(), username }, ctrls); + return ctx.search(groupSearchBase, groupSearchFilter, new String[] { fullDn.toUrl(), username }, ctrls); }; - AttributesMapperCallbackHandler roleCollector = new AttributesMapperCallbackHandler( - roleMapper); + AttributesMapperCallbackHandler roleCollector = new AttributesMapperCallbackHandler(roleMapper); template.search(se, roleCollector); return roleCollector.getList(); @@ -231,8 +225,7 @@ public class LdapUserDetailsManager implements UserDetailsManager { copyToContext(user, ctx); DistinguishedName dn = usernameMapper.buildDn(user.getUsername()); - logger.debug("Creating new user '" + user.getUsername() + "' with DN '" + dn - + "'"); + logger.debug("Creating new user '" + user.getUsername() + "' with DN '" + dn + "'"); template.bind(dn, ctx, null); @@ -259,8 +252,7 @@ public class LdapUserDetailsManager implements UserDetailsManager { copyToContext(user, ctx); // Remove the objectclass attribute from the list of mods (if present). - List mods = new LinkedList<>(Arrays.asList(ctx - .getModificationItems())); + List mods = new LinkedList<>(Arrays.asList(ctx.getModificationItems())); ListIterator modIt = mods.listIterator(); while (modIt.hasNext()) { @@ -302,7 +294,6 @@ public class LdapUserDetailsManager implements UserDetailsManager { /** * Creates a DN from a group name. - * * @param group the name of the group * @return the DN of the corresponding group, including the groupSearchBase */ @@ -317,13 +308,11 @@ public class LdapUserDetailsManager implements UserDetailsManager { userDetailsMapper.mapUserToContext(user, ctx); } - protected void addAuthorities(DistinguishedName userDn, - Collection authorities) { + protected void addAuthorities(DistinguishedName userDn, Collection authorities) { modifyAuthorities(userDn, authorities, DirContext.ADD_ATTRIBUTE); } - protected void removeAuthorities(DistinguishedName userDn, - Collection authorities) { + protected void removeAuthorities(DistinguishedName userDn, Collection authorities) { modifyAuthorities(userDn, authorities, DirContext.REMOVE_ATTRIBUTE); } @@ -336,8 +325,7 @@ public class LdapUserDetailsManager implements UserDetailsManager { ModificationItem addGroup = new ModificationItem(modType, new BasicAttribute(groupMemberAttributeName, fullDn.toUrl())); - ctx.modifyAttributes(buildGroupDn(group), - new ModificationItem[] { addGroup }); + ctx.modifyAttributes(buildGroupDn(group), new ModificationItem[] { addGroup }); } return null; }); @@ -384,7 +372,6 @@ public class LdapUserDetailsManager implements UserDetailsManager { *

        * Usually this will be uniquemember (the default value) or member. *

        - * * @param groupMemberAttributeName the name of the attribute used to store group * members. */ @@ -401,17 +388,19 @@ public class LdapUserDetailsManager implements UserDetailsManager { /** * Sets the method by which a user's password gets modified. * - * If set to {@code true}, then {@link LdapUserDetailsManager#changePassword} will modify - * the user's password by way of the - * Password Modify Extension Operation. + * If set to {@code true}, then {@link LdapUserDetailsManager#changePassword} will + * modify the user's password by way of the + * Password Modify + * Extension Operation. * - * If set to {@code false}, then {@link LdapUserDetailsManager#changePassword} will modify - * the user's password by directly modifying attributes on the corresponding entry. + * If set to {@code false}, then {@link LdapUserDetailsManager#changePassword} will + * modify the user's password by directly modifying attributes on the corresponding + * entry. * - * Before using this setting, ensure that the corresponding LDAP server supports this extended operation. + * Before using this setting, ensure that the corresponding LDAP server supports this + * extended operation. * * By default, {@code usePasswordModifyExtensionOperation} is false. - * * @param usePasswordModifyExtensionOperation * @since 4.2.9 */ @@ -419,12 +408,11 @@ public class LdapUserDetailsManager implements UserDetailsManager { this.usePasswordModifyExtensionOperation = usePasswordModifyExtensionOperation; } - private void changePasswordUsingAttributeModification - (DistinguishedName userDn, String oldPassword, String newPassword) { + private void changePasswordUsingAttributeModification(DistinguishedName userDn, String oldPassword, + String newPassword) { final ModificationItem[] passwordChange = new ModificationItem[] { new ModificationItem( - DirContext.REPLACE_ATTRIBUTE, new BasicAttribute(passwordAttributeName, - newPassword)) }; + DirContext.REPLACE_ATTRIBUTE, new BasicAttribute(passwordAttributeName, newPassword)) }; if (oldPassword == null) { template.modifyAttributes(userDn, passwordChange); @@ -434,15 +422,14 @@ public class LdapUserDetailsManager implements UserDetailsManager { template.executeReadWrite(dirCtx -> { LdapContext ctx = (LdapContext) dirCtx; ctx.removeFromEnvironment("com.sun.jndi.ldap.connect.pool"); - ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, - LdapUtils.getFullDn(userDn, ctx).toString()); + ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, LdapUtils.getFullDn(userDn, ctx).toString()); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, oldPassword); // TODO: reconnect doesn't appear to actually change the credentials try { ctx.reconnect(null); - } catch (javax.naming.AuthenticationException e) { - throw new BadCredentialsException( - "Authentication for password change failed."); + } + catch (javax.naming.AuthenticationException e) { + throw new BadCredentialsException("Authentication for password change failed."); } ctx.modifyAttributes(userDn, passwordChange); @@ -452,43 +439,45 @@ public class LdapUserDetailsManager implements UserDetailsManager { } - private void changePasswordUsingExtensionOperation - (DistinguishedName userDn, String oldPassword, String newPassword) { + private void changePasswordUsingExtensionOperation(DistinguishedName userDn, String oldPassword, + String newPassword) { template.executeReadWrite(dirCtx -> { LdapContext ctx = (LdapContext) dirCtx; String userIdentity = LdapUtils.getFullDn(userDn, ctx).encode(); - PasswordModifyRequest request = - new PasswordModifyRequest(userIdentity, oldPassword, newPassword); + PasswordModifyRequest request = new PasswordModifyRequest(userIdentity, oldPassword, newPassword); try { return ctx.extendedOperation(request); - } catch (javax.naming.AuthenticationException e) { - throw new BadCredentialsException( - "Authentication for password change failed."); + } + catch (javax.naming.AuthenticationException e) { + throw new BadCredentialsException("Authentication for password change failed."); } }); } /** * An implementation of the - * - * LDAP Password Modify Extended Operation - * - * client request. + * LDAP Password Modify + * Extended Operation client request. * - * Can be directed at any LDAP server that supports the Password Modify Extended Operation. + * Can be directed at any LDAP server that supports the Password Modify Extended + * Operation. * * @author Josh Cummings * @since 4.2.9 */ private static class PasswordModifyRequest implements ExtendedRequest { + private static final byte SEQUENCE_TYPE = 48; private static final String PASSWORD_MODIFY_OID = "1.3.6.1.4.1.4203.1.11.1"; + private static final byte USER_IDENTITY_OCTET_TYPE = -128; + private static final byte OLD_PASSWORD_OCTET_TYPE = -127; + private static final byte NEW_PASSWORD_OCTET_TYPE = -126; private final ByteArrayOutputStream value = new ByteArrayOutputStream(); @@ -527,10 +516,9 @@ public class LdapUserDetailsManager implements UserDetailsManager { } /** - * Only minimal support for - * - * BER encoding - * ; just what is necessary for the Password Modify request. + * Only minimal support for BER + * encoding ; just what is necessary for the Password Modify request. * */ private void berEncode(byte type, byte[] src, ByteArrayOutputStream dest) { @@ -540,19 +528,23 @@ public class LdapUserDetailsManager implements UserDetailsManager { if (length < 128) { dest.write(length); - } else if ((length & 0x0000_00FF) == length) { + } + else if ((length & 0x0000_00FF) == length) { dest.write((byte) 0x81); dest.write((byte) (length & 0xFF)); - } else if ((length & 0x0000_FFFF) == length) { + } + else if ((length & 0x0000_FFFF) == length) { dest.write((byte) 0x82); dest.write((byte) ((length >> 8) & 0xFF)); dest.write((byte) (length & 0xFF)); - } else if ((length & 0x00FF_FFFF) == length) { + } + else if ((length & 0x00FF_FFFF) == length) { dest.write((byte) 0x83); dest.write((byte) ((length >> 16) & 0xFF)); dest.write((byte) ((length >> 8) & 0xFF)); dest.write((byte) (length & 0xFF)); - } else { + } + else { dest.write((byte) 0x84); dest.write((byte) ((length >> 24) & 0xFF)); dest.write((byte) ((length >> 16) & 0xFF)); @@ -562,9 +554,12 @@ public class LdapUserDetailsManager implements UserDetailsManager { try { dest.write(src); - } catch (IOException e) { + } + catch (IOException e) { throw new IllegalArgumentException("Failed to BER encode provided value of type: " + type); } } + } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapper.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapper.java index 89df68fca1..970717bd58 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapper.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapper.java @@ -38,13 +38,18 @@ import org.springframework.util.Assert; * @author Eddú Meléndez */ public class LdapUserDetailsMapper implements UserDetailsContextMapper { + // ~ Instance fields // ================================================================================================ private final Log logger = LogFactory.getLog(LdapUserDetailsMapper.class); + private String passwordAttributeName = "userPassword"; + private String rolePrefix = "ROLE_"; + private String[] roleAttributes = null; + private boolean convertToUpperCase = true; // ~ Methods @@ -69,13 +74,11 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper { essence.setUsername(username); // Map the roles - for (int i = 0; (this.roleAttributes != null) - && (i < this.roleAttributes.length); i++) { + for (int i = 0; (this.roleAttributes != null) && (i < this.roleAttributes.length); i++) { String[] rolesForAttribute = ctx.getStringAttributes(this.roleAttributes[i]); if (rolesForAttribute == null) { - this.logger.debug("Couldn't read role attribute '" - + this.roleAttributes[i] + "' for user " + dn); + this.logger.debug("Couldn't read role attribute '" + this.roleAttributes[i] + "' for user " + dn); continue; } @@ -110,15 +113,13 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper { @Override public void mapUserToContext(UserDetails user, DirContextAdapter ctx) { - throw new UnsupportedOperationException( - "LdapUserDetailsMapper only supports reading from a context. Please" - + " use a subclass if mapUserToContext() is required."); + throw new UnsupportedOperationException("LdapUserDetailsMapper only supports reading from a context. Please" + + " use a subclass if mapUserToContext() is required."); } /** * Extension point to allow customized creation of the user's password from the * attribute stored in the directory. - * * @param passwordValue the value of the password attribute * @return a String representation of the password. */ @@ -141,7 +142,6 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper { * rolePrefix and convertToUpperCase properties. Non-String * attributes are ignored. *

        - * * @param role the attribute returned from * @return the authority to be added to the list of authorities for the user, or null * if this attribute should be ignored. @@ -159,7 +159,6 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper { /** * Determines whether role field values will be converted to upper case when loaded. * The default is true. - * * @param convertToUpperCase true if the roles should be converted to upper case. */ public void setConvertToUpperCase(boolean convertToUpperCase) { @@ -169,7 +168,6 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper { /** * The name of the attribute which contains the user's password. Defaults to * "userPassword". - * * @param passwordAttributeName the name of the attribute */ public void setPasswordAttributeName(String passwordAttributeName) { @@ -180,7 +178,6 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper { * The names of any attributes in the user's entry which represent application roles. * These will be converted to GrantedAuthoritys and added to the list in the * returned LdapUserDetails object. The attribute values must be Strings by default. - * * @param roleAttributes the names of the role attributes. */ public void setRoleAttributes(String[] roleAttributes) { @@ -195,4 +192,5 @@ public class LdapUserDetailsMapper implements UserDetailsContextMapper { public void setRolePrefix(String rolePrefix) { this.rolePrefix = rolePrefix; } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsService.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsService.java index 8a91097353..a02f714b94 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsService.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsService.java @@ -35,24 +35,25 @@ import org.springframework.util.Assert; * @author Luke Taylor */ public class LdapUserDetailsService implements UserDetailsService { + private final LdapUserSearch userSearch; + private final LdapAuthoritiesPopulator authoritiesPopulator; + private UserDetailsContextMapper userDetailsMapper = new LdapUserDetailsMapper(); public LdapUserDetailsService(LdapUserSearch userSearch) { this(userSearch, new NullLdapAuthoritiesPopulator()); } - public LdapUserDetailsService(LdapUserSearch userSearch, - LdapAuthoritiesPopulator authoritiesPopulator) { + public LdapUserDetailsService(LdapUserSearch userSearch, LdapAuthoritiesPopulator authoritiesPopulator) { Assert.notNull(userSearch, "userSearch must not be null"); Assert.notNull(authoritiesPopulator, "authoritiesPopulator must not be null"); this.userSearch = userSearch; this.authoritiesPopulator = authoritiesPopulator; } - public UserDetails loadUserByUsername(String username) - throws UsernameNotFoundException { + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { DirContextOperations userData = userSearch.searchForUser(username); return userDetailsMapper.mapUserFromContext(userData, username, @@ -64,11 +65,12 @@ public class LdapUserDetailsService implements UserDetailsService { this.userDetailsMapper = userDetailsMapper; } - private static final class NullLdapAuthoritiesPopulator implements - LdapAuthoritiesPopulator { - public Collection getGrantedAuthorities( - DirContextOperations userDetails, String username) { + private static final class NullLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator { + + public Collection getGrantedAuthorities(DirContextOperations userDetails, String username) { return AuthorityUtils.NO_AUTHORITIES; } + } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/NestedLdapAuthoritiesPopulator.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/NestedLdapAuthoritiesPopulator.java index 07e37b4cef..4aa2f0c61f 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/NestedLdapAuthoritiesPopulator.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/NestedLdapAuthoritiesPopulator.java @@ -119,8 +119,8 @@ import org.springframework.util.StringUtils; */ public class NestedLdapAuthoritiesPopulator extends DefaultLdapAuthoritiesPopulator { - private static final Log logger = LogFactory - .getLog(NestedLdapAuthoritiesPopulator.class); + + private static final Log logger = LogFactory.getLog(NestedLdapAuthoritiesPopulator.class); /** * The attribute names to retrieve for each LDAP group @@ -135,13 +135,11 @@ public class NestedLdapAuthoritiesPopulator extends DefaultLdapAuthoritiesPopula /** * Constructor for group search scenarios. userRoleAttributes may still be * set as a property. - * * @param contextSource supplies the contexts used to search for user roles. * @param groupSearchBase if this is an empty string the search will be performed from * the root DN of the */ - public NestedLdapAuthoritiesPopulator(ContextSource contextSource, - String groupSearchBase) { + public NestedLdapAuthoritiesPopulator(ContextSource contextSource, String groupSearchBase) { super(contextSource, groupSearchBase); } @@ -163,45 +161,38 @@ public class NestedLdapAuthoritiesPopulator extends DefaultLdapAuthoritiesPopula /** * Performs the nested group search - * * @param userDn - the userDN to search for, will become the group DN for subsequent * searches * @param username - the username of the user * @param authorities - the authorities set that will be populated, must not be null * @param depth - the depth remaining, when 0 recursion will end */ - private void performNestedSearch(String userDn, String username, - Set authorities, int depth) { + private void performNestedSearch(String userDn, String username, Set authorities, int depth) { if (depth == 0) { // back out of recursion if (logger.isDebugEnabled()) { - logger.debug("Search aborted, max depth reached," - + " for roles for user '" + username + "', DN = " + "'" + userDn - + "', with filter " + getGroupSearchFilter() + " in search base '" + logger.debug("Search aborted, max depth reached," + " for roles for user '" + username + "', DN = " + + "'" + userDn + "', with filter " + getGroupSearchFilter() + " in search base '" + getGroupSearchBase() + "'"); } return; } if (logger.isDebugEnabled()) { - logger.debug("Searching for roles for user '" + username + "', DN = " + "'" - + userDn + "', with filter " + getGroupSearchFilter() - + " in search base '" + getGroupSearchBase() + "'"); + logger.debug("Searching for roles for user '" + username + "', DN = " + "'" + userDn + "', with filter " + + getGroupSearchFilter() + " in search base '" + getGroupSearchBase() + "'"); } if (getAttributeNames() == null) { setAttributeNames(new HashSet<>()); } - if (StringUtils.hasText(getGroupRoleAttribute()) - && !getAttributeNames().contains(getGroupRoleAttribute())) { + if (StringUtils.hasText(getGroupRoleAttribute()) && !getAttributeNames().contains(getGroupRoleAttribute())) { getAttributeNames().add(getGroupRoleAttribute()); } - Set>> userRoles = getLdapTemplate() - .searchForMultipleAttributeValues(getGroupSearchBase(), - getGroupSearchFilter(), new String[] { userDn, username }, - getAttributeNames() - .toArray(new String[0])); + Set>> userRoles = getLdapTemplate().searchForMultipleAttributeValues( + getGroupSearchBase(), getGroupSearchFilter(), new String[] { userDn, username }, + getAttributeNames().toArray(new String[0])); if (logger.isDebugEnabled()) { logger.debug("Roles from search: " + userRoles); @@ -222,8 +213,7 @@ public class NestedLdapAuthoritiesPopulator extends DefaultLdapAuthoritiesPopula role = getRolePrefix() + role; // if the group already exist, we will not search for it's parents again. // this prevents a forever loop for a misconfigured ldap directory - circular = circular - | (!authorities.add(new LdapAuthority(role, dn, record))); + circular = circular | (!authorities.add(new LdapAuthority(role, dn, record))); } String roleName = roles.size() > 0 ? roles.iterator().next() : dn; if (!circular) { @@ -236,7 +226,6 @@ public class NestedLdapAuthoritiesPopulator extends DefaultLdapAuthoritiesPopula /** * Returns the attribute names that this populator has been configured to retrieve * Value can be null, represents fetch all attributes - * * @return the attribute names or null for all */ private Set getAttributeNames() { @@ -245,7 +234,6 @@ public class NestedLdapAuthoritiesPopulator extends DefaultLdapAuthoritiesPopula /** * Sets the attribute names to retrieve for each ldap groups. Null means retrieve all - * * @param attributeNames - the names of the LDAP attributes to retrieve */ public void setAttributeNames(Set attributeNames) { @@ -255,7 +243,6 @@ public class NestedLdapAuthoritiesPopulator extends DefaultLdapAuthoritiesPopula /** * How far should a nested search go. Depth is calculated in the number of levels we * search up for parent groups. - * * @return the max search depth, default is 10 */ private int getMaxSearchDepth() { @@ -265,7 +252,6 @@ public class NestedLdapAuthoritiesPopulator extends DefaultLdapAuthoritiesPopula /** * How far should a nested search go. Depth is calculated in the number of levels we * search up for parent groups. - * * @param maxSearchDepth the max search depth */ public void setMaxSearchDepth(int maxSearchDepth) { diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/Person.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/Person.java index f68f5a6736..d8726e16ea 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/Person.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/Person.java @@ -39,9 +39,13 @@ public class Person extends LdapUserDetailsImpl { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private String givenName; + private String sn; + private String description; + private String telephoneNumber; + private List cn = new ArrayList<>(); protected Person() { @@ -144,5 +148,7 @@ public class Person extends LdapUserDetailsImpl { // TODO: Check contents for null entries return p; } + } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/PersonContextMapper.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/PersonContextMapper.java index ba09ac79a0..288d34af9b 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/PersonContextMapper.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/PersonContextMapper.java @@ -45,4 +45,5 @@ public class PersonContextMapper implements UserDetailsContextMapper { Person p = (Person) user; p.populateContext(ctx); } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/UserDetailsContextMapper.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/UserDetailsContextMapper.java index 6c59f10ac2..81632818a1 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/UserDetailsContextMapper.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/UserDetailsContextMapper.java @@ -36,7 +36,6 @@ public interface UserDetailsContextMapper { /** * Creates a fully populated UserDetails object for use by the security framework. - * * @param ctx the context object which contains the user information. * @param username the user's supplied login name. * @param authorities @@ -50,4 +49,5 @@ public interface UserDetailsContextMapper { * object. Called when saving a user, for example. */ void mapUserToContext(UserDetails user, DirContextAdapter ctx); + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/package-info.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/package-info.java index e53eeade05..d6c5da261f 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/package-info.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/package-info.java @@ -18,4 +18,3 @@ * contained in some of the standard LDAP types (such as {@code InetOrgPerson}). */ package org.springframework.security.ldap.userdetails; - diff --git a/ldap/src/test/java/org/springframework/security/ldap/LdapUtilsTests.java b/ldap/src/test/java/org/springframework/security/ldap/LdapUtilsTests.java index 8c9175a04a..3f260f4b7f 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/LdapUtilsTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/LdapUtilsTests.java @@ -43,8 +43,7 @@ public class LdapUtilsTests { } @Test - public void testGetRelativeNameReturnsEmptyStringForDnEqualToBaseName() - throws Exception { + public void testGetRelativeNameReturnsEmptyStringForDnEqualToBaseName() throws Exception { final DirContext mockCtx = mock(DirContext.class); when(mockCtx.getNameInNamespace()).thenReturn("dc=springframework,dc=org"); @@ -57,7 +56,8 @@ public class LdapUtilsTests { final DirContext mockCtx = mock(DirContext.class); when(mockCtx.getNameInNamespace()).thenReturn(""); - assertThat(LdapUtils.getRelativeName("cn=jane,dc=springframework,dc=org", mockCtx)).isEqualTo("cn=jane,dc=springframework,dc=org"); + assertThat(LdapUtils.getRelativeName("cn=jane,dc=springframework,dc=org", mockCtx)) + .isEqualTo("cn=jane,dc=springframework,dc=org"); } @Test @@ -65,8 +65,8 @@ public class LdapUtilsTests { final DirContext mockCtx = mock(DirContext.class); when(mockCtx.getNameInNamespace()).thenReturn("dc=springsecurity,dc = org"); - assertThat(LdapUtils.getRelativeName( - "cn=jane smith, dc = springsecurity , dc=org", mockCtx)).isEqualTo("cn=jane smith"); + assertThat(LdapUtils.getRelativeName("cn=jane smith, dc = springsecurity , dc=org", mockCtx)) + .isEqualTo("cn=jane smith"); } @Test @@ -75,19 +75,16 @@ public class LdapUtilsTests { assertThat(LdapUtils.parseRootDnFromUrl("ldap://monkeymachine:11389")).isEqualTo(""); assertThat(LdapUtils.parseRootDnFromUrl("ldap://monkeymachine/")).isEqualTo(""); assertThat(LdapUtils.parseRootDnFromUrl("ldap://monkeymachine.co.uk/")).isEqualTo(""); - assertThat( - LdapUtils - .parseRootDnFromUrl("ldaps://monkeymachine.co.uk/dc=springframework,dc=org")).isEqualTo("dc=springframework,dc=org"); - assertThat( - LdapUtils.parseRootDnFromUrl("ldap:///dc=springframework,dc=org")).isEqualTo("dc=springframework,dc=org"); - assertThat( - LdapUtils - .parseRootDnFromUrl("ldap://monkeymachine/dc=springframework,dc=org")).isEqualTo("dc=springframework,dc=org"); - assertThat( - LdapUtils - .parseRootDnFromUrl("ldap://monkeymachine.co.uk/dc=springframework,dc=org/ou=blah")).isEqualTo("dc=springframework,dc=org/ou=blah"); - assertThat( - LdapUtils - .parseRootDnFromUrl("ldap://monkeymachine.co.uk:389/dc=springframework,dc=org/ou=blah")).isEqualTo("dc=springframework,dc=org/ou=blah"); + assertThat(LdapUtils.parseRootDnFromUrl("ldaps://monkeymachine.co.uk/dc=springframework,dc=org")) + .isEqualTo("dc=springframework,dc=org"); + assertThat(LdapUtils.parseRootDnFromUrl("ldap:///dc=springframework,dc=org")) + .isEqualTo("dc=springframework,dc=org"); + assertThat(LdapUtils.parseRootDnFromUrl("ldap://monkeymachine/dc=springframework,dc=org")) + .isEqualTo("dc=springframework,dc=org"); + assertThat(LdapUtils.parseRootDnFromUrl("ldap://monkeymachine.co.uk/dc=springframework,dc=org/ou=blah")) + .isEqualTo("dc=springframework,dc=org/ou=blah"); + assertThat(LdapUtils.parseRootDnFromUrl("ldap://monkeymachine.co.uk:389/dc=springframework,dc=org/ou=blah")) + .isEqualTo("dc=springframework,dc=org/ou=blah"); } + } diff --git a/ldap/src/test/java/org/springframework/security/ldap/SpringSecurityAuthenticationSourceTests.java b/ldap/src/test/java/org/springframework/security/ldap/SpringSecurityAuthenticationSourceTests.java index 664a05dde7..e90379289e 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/SpringSecurityAuthenticationSourceTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/SpringSecurityAuthenticationSourceTests.java @@ -33,6 +33,7 @@ import org.junit.Test; * @author Luke Taylor */ public class SpringSecurityAuthenticationSourceTests { + @Before @After public void clearContext() { @@ -51,16 +52,14 @@ public class SpringSecurityAuthenticationSourceTests { AuthenticationSource source = new SpringSecurityAuthenticationSource(); SecurityContextHolder.getContext().setAuthentication( - new AnonymousAuthenticationToken("key", "anonUser", AuthorityUtils - .createAuthorityList("ignored"))); + new AnonymousAuthenticationToken("key", "anonUser", AuthorityUtils.createAuthorityList("ignored"))); assertThat(source.getPrincipal()).isEqualTo(""); } @Test(expected = IllegalArgumentException.class) public void getPrincipalRejectsNonLdapUserDetailsObject() { AuthenticationSource source = new SpringSecurityAuthenticationSource(); - SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken(new Object(), "password")); + SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken(new Object(), "password")); source.getPrincipal(); } @@ -68,8 +67,7 @@ public class SpringSecurityAuthenticationSourceTests { @Test public void expectedCredentialsAreReturned() { AuthenticationSource source = new SpringSecurityAuthenticationSource(); - SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken(new Object(), "password")); + SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken(new Object(), "password")); assertThat(source.getCredentials()).isEqualTo("password"); } @@ -80,9 +78,10 @@ public class SpringSecurityAuthenticationSourceTests { user.setUsername("joe"); user.setDn(new DistinguishedName("uid=joe,ou=users")); AuthenticationSource source = new SpringSecurityAuthenticationSource(); - SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken(user.createUserDetails(), null)); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken(user.createUserDetails(), null)); assertThat(source.getPrincipal()).isEqualTo("uid=joe,ou=users"); } + } diff --git a/ldap/src/test/java/org/springframework/security/ldap/SpringSecurityLdapTemplateTests.java b/ldap/src/test/java/org/springframework/security/ldap/SpringSecurityLdapTemplateTests.java index 5b7e362392..45afb11dd8 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/SpringSecurityLdapTemplateTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/SpringSecurityLdapTemplateTests.java @@ -37,10 +37,13 @@ public class SpringSecurityLdapTemplateTests { @Mock private DirContext ctx; + @Captor private ArgumentCaptor searchControls; + @Mock private NamingEnumeration resultsEnum; + @Mock private SearchResult searchResult; @@ -53,15 +56,13 @@ public class SpringSecurityLdapTemplateTests { Object[] params = new Object[] {}; DirContextAdapter searchResultObject = mock(DirContextAdapter.class); - when( - ctx.search(any(DistinguishedName.class), eq(filter), eq(params), - searchControls.capture())).thenReturn(resultsEnum); + when(ctx.search(any(DistinguishedName.class), eq(filter), eq(params), searchControls.capture())) + .thenReturn(resultsEnum); when(resultsEnum.hasMore()).thenReturn(true, false); when(resultsEnum.next()).thenReturn(searchResult); when(searchResult.getObject()).thenReturn(searchResultObject); - SpringSecurityLdapTemplate.searchForSingleEntryInternal(ctx, - mock(SearchControls.class), base, filter, params); + SpringSecurityLdapTemplate.searchForSingleEntryInternal(ctx, mock(SearchControls.class), base, filter, params); assertThat(searchControls.getValue().getReturningObjFlag()).isTrue(); } diff --git a/ldap/src/test/java/org/springframework/security/ldap/authentication/LdapAuthenticationProviderTests.java b/ldap/src/test/java/org/springframework/security/ldap/authentication/LdapAuthenticationProviderTests.java index 87fd372b8b..0e367024c4 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/authentication/LdapAuthenticationProviderTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/authentication/LdapAuthenticationProviderTests.java @@ -51,36 +51,34 @@ public class LdapAuthenticationProviderTests { @Test public void testSupportsUsernamePasswordAuthenticationToken() { - LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider( - new MockAuthenticator(), new MockAuthoritiesPopulator()); + LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(), + new MockAuthoritiesPopulator()); assertThat(ldapProvider.supports(UsernamePasswordAuthenticationToken.class)).isTrue(); } @Test public void testDefaultMapperIsSet() { - LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider( - new MockAuthenticator(), new MockAuthoritiesPopulator()); + LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(), + new MockAuthoritiesPopulator()); assertThat(ldapProvider.getUserDetailsContextMapper() instanceof LdapUserDetailsMapper).isTrue(); } @Test public void testEmptyOrNullUserNameThrowsException() { - LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider( - new MockAuthenticator(), new MockAuthoritiesPopulator()); + LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(), + new MockAuthoritiesPopulator()); try { - ldapProvider.authenticate(new UsernamePasswordAuthenticationToken(null, - "password")); + ldapProvider.authenticate(new UsernamePasswordAuthenticationToken(null, "password")); fail("Expected BadCredentialsException for empty username"); } catch (BadCredentialsException expected) { } try { - ldapProvider.authenticate(new UsernamePasswordAuthenticationToken("", - "bobspassword")); + ldapProvider.authenticate(new UsernamePasswordAuthenticationToken("", "bobspassword")); fail("Expected BadCredentialsException for null username"); } catch (BadCredentialsException expected) { @@ -90,26 +88,20 @@ public class LdapAuthenticationProviderTests { @Test(expected = BadCredentialsException.class) public void usernameNotFoundExceptionIsHiddenByDefault() { final LdapAuthenticator authenticator = mock(LdapAuthenticator.class); - final UsernamePasswordAuthenticationToken joe = new UsernamePasswordAuthenticationToken( - "joe", "password"); - when(authenticator.authenticate(joe)).thenThrow( - new UsernameNotFoundException("nobody")); + final UsernamePasswordAuthenticationToken joe = new UsernamePasswordAuthenticationToken("joe", "password"); + when(authenticator.authenticate(joe)).thenThrow(new UsernameNotFoundException("nobody")); - LdapAuthenticationProvider provider = new LdapAuthenticationProvider( - authenticator); + LdapAuthenticationProvider provider = new LdapAuthenticationProvider(authenticator); provider.authenticate(joe); } @Test(expected = UsernameNotFoundException.class) public void usernameNotFoundExceptionIsNotHiddenIfConfigured() { final LdapAuthenticator authenticator = mock(LdapAuthenticator.class); - final UsernamePasswordAuthenticationToken joe = new UsernamePasswordAuthenticationToken( - "joe", "password"); - when(authenticator.authenticate(joe)).thenThrow( - new UsernameNotFoundException("nobody")); + final UsernamePasswordAuthenticationToken joe = new UsernamePasswordAuthenticationToken("joe", "password"); + when(authenticator.authenticate(joe)).thenThrow(new UsernameNotFoundException("nobody")); - LdapAuthenticationProvider provider = new LdapAuthenticationProvider( - authenticator); + LdapAuthenticationProvider provider = new LdapAuthenticationProvider(authenticator); provider.setHideUserNotFoundExceptions(false); provider.authenticate(joe); } @@ -117,16 +109,15 @@ public class LdapAuthenticationProviderTests { @Test public void normalUsage() { MockAuthoritiesPopulator populator = new MockAuthoritiesPopulator(); - LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider( - new MockAuthenticator(), populator); + LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(), populator); LdapUserDetailsMapper userMapper = new LdapUserDetailsMapper(); userMapper.setRoleAttributes(new String[] { "ou" }); ldapProvider.setUserDetailsContextMapper(userMapper); assertThat(ldapProvider.getAuthoritiesPopulator()).isNotNull(); - UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( - "ben", "benspassword"); + UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken("ben", + "benspassword"); Object authDetails = new Object(); authRequest.setDetails(authDetails); Authentication authResult = ldapProvider.authenticate(authRequest); @@ -138,20 +129,18 @@ public class LdapAuthenticationProviderTests { assertThat(user.getUsername()).isEqualTo("ben"); assertThat(populator.getRequestedUsername()).isEqualTo("ben"); - assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())) - .contains("ROLE_FROM_ENTRY"); - assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())) - .contains("ROLE_FROM_POPULATOR"); + assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).contains("ROLE_FROM_ENTRY"); + assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).contains("ROLE_FROM_POPULATOR"); } @Test public void passwordIsSetFromUserDataIfUseAuthenticationRequestCredentialsIsFalse() { - LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider( - new MockAuthenticator(), new MockAuthoritiesPopulator()); + LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator(), + new MockAuthoritiesPopulator()); ldapProvider.setUseAuthenticationRequestCredentials(false); - UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( - "ben", "benspassword"); + UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken("ben", + "benspassword"); Authentication authResult = ldapProvider.authenticate(authRequest); assertThat(authResult.getCredentials()).isEqualTo("{SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ="); @@ -159,31 +148,26 @@ public class LdapAuthenticationProviderTests { @Test public void useWithNullAuthoritiesPopulatorReturnsCorrectRole() { - LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider( - new MockAuthenticator()); + LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(new MockAuthenticator()); LdapUserDetailsMapper userMapper = new LdapUserDetailsMapper(); userMapper.setRoleAttributes(new String[] { "ou" }); ldapProvider.setUserDetailsContextMapper(userMapper); - UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( - "ben", "benspassword"); - UserDetails user = (UserDetails) ldapProvider.authenticate(authRequest) - .getPrincipal(); + UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken("ben", + "benspassword"); + UserDetails user = (UserDetails) ldapProvider.authenticate(authRequest).getPrincipal(); assertThat(user.getAuthorities()).hasSize(1); - assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())) - .contains("ROLE_FROM_ENTRY"); + assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).contains("ROLE_FROM_ENTRY"); } @Test public void authenticateWithNamingException() { - UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( - "ben", "benspassword"); + UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken("ben", + "benspassword"); LdapAuthenticator mockAuthenticator = mock(LdapAuthenticator.class); - CommunicationException expectedCause = new CommunicationException( - new javax.naming.CommunicationException()); + CommunicationException expectedCause = new CommunicationException(new javax.naming.CommunicationException()); when(mockAuthenticator.authenticate(authRequest)).thenThrow(expectedCause); - LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider( - mockAuthenticator); + LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(mockAuthenticator); try { ldapProvider.authenticate(authRequest); fail("Expected Exception"); @@ -205,28 +189,27 @@ public class LdapAuthenticationProviderTests { String password = (String) authentication.getCredentials(); if (username.equals("ben") && password.equals("benspassword")) { - ctx.setDn(new DistinguishedName( - "cn=ben,ou=people,dc=springframework,dc=org")); + ctx.setDn(new DistinguishedName("cn=ben,ou=people,dc=springframework,dc=org")); ctx.setAttributeValue("userPassword", "{SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ="); return ctx; } else if (username.equals("jen") && password.equals("")) { - ctx.setDn(new DistinguishedName( - "cn=jen,ou=people,dc=springframework,dc=org")); + ctx.setDn(new DistinguishedName("cn=jen,ou=people,dc=springframework,dc=org")); return ctx; } throw new BadCredentialsException("Authentication failed."); } + } class MockAuthoritiesPopulator implements LdapAuthoritiesPopulator { + String username; - public Collection getGrantedAuthorities( - DirContextOperations userCtx, String username) { + public Collection getGrantedAuthorities(DirContextOperations userCtx, String username) { this.username = username; return AuthorityUtils.createAuthorityList("ROLE_FROM_POPULATOR"); } @@ -234,5 +217,7 @@ public class LdapAuthenticationProviderTests { String getRequestedUsername() { return username; } + } + } diff --git a/ldap/src/test/java/org/springframework/security/ldap/authentication/MockUserSearch.java b/ldap/src/test/java/org/springframework/security/ldap/authentication/MockUserSearch.java index cc846d9889..d22d6f2244 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/authentication/MockUserSearch.java +++ b/ldap/src/test/java/org/springframework/security/ldap/authentication/MockUserSearch.java @@ -21,11 +21,10 @@ import org.springframework.security.ldap.search.LdapUserSearch; import org.springframework.ldap.core.DirContextOperations; /** - * - * * @author Luke Taylor */ public class MockUserSearch implements LdapUserSearch { + // ~ Instance fields // ================================================================================================ @@ -47,4 +46,5 @@ public class MockUserSearch implements LdapUserSearch { public DirContextOperations searchForUser(String username) { return user; } + } diff --git a/ldap/src/test/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticatorMockTests.java b/ldap/src/test/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticatorMockTests.java index e2aff2a5f3..c7e92fa5b3 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticatorMockTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticatorMockTests.java @@ -29,7 +29,6 @@ import org.springframework.ldap.core.support.BaseLdapPathContextSource; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; /** - * * @author Luke Taylor */ public class PasswordComparisonAuthenticatorMockTests { @@ -44,26 +43,22 @@ public class PasswordComparisonAuthenticatorMockTests { final BasicAttributes attrs = new BasicAttributes(); attrs.put(new BasicAttribute("uid", "bob")); - PasswordComparisonAuthenticator authenticator = new PasswordComparisonAuthenticator( - source); + PasswordComparisonAuthenticator authenticator = new PasswordComparisonAuthenticator(source); authenticator.setUserDnPatterns(new String[] { "cn={0},ou=people" }); // Get the mock to return an empty attribute set when(source.getReadOnlyContext()).thenReturn(dirCtx); - when(dirCtx.getAttributes(eq("cn=Bob,ou=people"), any(String[].class))) - .thenReturn(attrs); + when(dirCtx.getAttributes(eq("cn=Bob,ou=people"), any(String[].class))).thenReturn(attrs); when(dirCtx.getNameInNamespace()).thenReturn("dc=springframework,dc=org"); // Setup a single return value (i.e. success) final NamingEnumeration searchResults = new BasicAttributes("", null).getAll(); - when( - dirCtx.search(eq("cn=Bob,ou=people"), eq("(userPassword={0})"), - any(Object[].class), any(SearchControls.class))).thenReturn( - searchResults); + when(dirCtx.search(eq("cn=Bob,ou=people"), eq("(userPassword={0})"), any(Object[].class), + any(SearchControls.class))).thenReturn(searchResults); - authenticator.authenticate(new UsernamePasswordAuthenticationToken("Bob", - "bobspassword")); + authenticator.authenticate(new UsernamePasswordAuthenticationToken("Bob", "bobspassword")); } + } diff --git a/ldap/src/test/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProviderTests.java b/ldap/src/test/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProviderTests.java index 27226bd631..cfcd2a18e3 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProviderTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProviderTests.java @@ -64,20 +64,21 @@ import static org.springframework.security.ldap.authentication.ad.ActiveDirector * @author Rob Winch */ public class ActiveDirectoryLdapAuthenticationProviderTests { + public static final String EXISTING_LDAP_PROVIDER = "ldap://192.168.1.200/"; + public static final String NON_EXISTING_LDAP_PROVIDER = "ldap://192.168.1.201/"; @Rule public ExpectedException thrown = ExpectedException.none(); ActiveDirectoryLdapAuthenticationProvider provider; - UsernamePasswordAuthenticationToken joe = new UsernamePasswordAuthenticationToken( - "joe", "password"); + + UsernamePasswordAuthenticationToken joe = new UsernamePasswordAuthenticationToken("joe", "password"); @Before public void setUp() { - provider = new ActiveDirectoryLdapAuthenticationProvider("mydomain.eu", - "ldap://192.168.1.200/"); + provider = new ActiveDirectoryLdapAuthenticationProvider("mydomain.eu", "ldap://192.168.1.200/"); } @Test @@ -101,12 +102,9 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { when(ctx.getNameInNamespace()).thenReturn(""); DirContextAdapter dca = new DirContextAdapter(); - SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", dca, - dca.getAttributes()); - when( - ctx.search(any(Name.class), eq(customSearchFilter), any(Object[].class), - any(SearchControls.class))).thenReturn( - new MockNamingEnumeration(sr)); + SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", dca, dca.getAttributes()); + when(ctx.search(any(Name.class), eq(customSearchFilter), any(Object[].class), any(SearchControls.class))) + .thenReturn(new MockNamingEnumeration(sr)); ActiveDirectoryLdapAuthenticationProvider customProvider = new ActiveDirectoryLdapAuthenticationProvider( "mydomain.eu", "ldap://192.168.1.200/"); @@ -129,12 +127,9 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { when(ctx.getNameInNamespace()).thenReturn(""); DirContextAdapter dca = new DirContextAdapter(); - SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", dca, - dca.getAttributes()); - when( - ctx.search(any(Name.class), eq(defaultSearchFilter), any(Object[].class), - any(SearchControls.class))).thenReturn( - new MockNamingEnumeration(sr)); + SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", dca, dca.getAttributes()); + when(ctx.search(any(Name.class), eq(defaultSearchFilter), any(Object[].class), any(SearchControls.class))) + .thenReturn(new MockNamingEnumeration(sr)); ActiveDirectoryLdapAuthenticationProvider customProvider = new ActiveDirectoryLdapAuthenticationProvider( "mydomain.eu", "ldap://192.168.1.200/"); @@ -145,8 +140,8 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { // then assertThat(result.isAuthenticated()).isTrue(); - verify(ctx).search(any(DistinguishedName.class), eq(defaultSearchFilter), - any(Object[].class), any(SearchControls.class)); + verify(ctx).search(any(DistinguishedName.class), eq(defaultSearchFilter), any(Object[].class), + any(SearchControls.class)); } // SEC-2897,SEC-2224 @@ -160,12 +155,9 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { when(ctx.getNameInNamespace()).thenReturn(""); DirContextAdapter dca = new DirContextAdapter(); - SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", dca, - dca.getAttributes()); - when( - ctx.search(any(Name.class), eq(defaultSearchFilter), captor.capture(), - any(SearchControls.class))).thenReturn( - new MockNamingEnumeration(sr)); + SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", dca, dca.getAttributes()); + when(ctx.search(any(Name.class), eq(defaultSearchFilter), captor.capture(), any(SearchControls.class))) + .thenReturn(new MockNamingEnumeration(sr)); ActiveDirectoryLdapAuthenticationProvider customProvider = new ActiveDirectoryLdapAuthenticationProvider( "mydomain.eu", "ldap://192.168.1.200/"); @@ -190,20 +182,15 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { } @Test - public void nullDomainIsSupportedIfAuthenticatingWithFullUserPrincipal() - throws Exception { - provider = new ActiveDirectoryLdapAuthenticationProvider(null, - "ldap://192.168.1.200/"); + public void nullDomainIsSupportedIfAuthenticatingWithFullUserPrincipal() throws Exception { + provider = new ActiveDirectoryLdapAuthenticationProvider(null, "ldap://192.168.1.200/"); DirContext ctx = mock(DirContext.class); when(ctx.getNameInNamespace()).thenReturn(""); DirContextAdapter dca = new DirContextAdapter(); - SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", dca, - dca.getAttributes()); - when( - ctx.search(eq(new DistinguishedName("DC=mydomain,DC=eu")), - any(String.class), any(Object[].class), any(SearchControls.class))) - .thenReturn(new MockNamingEnumeration(sr)); + SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", dca, dca.getAttributes()); + when(ctx.search(eq(new DistinguishedName("DC=mydomain,DC=eu")), any(String.class), any(Object[].class), + any(SearchControls.class))).thenReturn(new MockNamingEnumeration(sr)); provider.contextFactory = createContextFactoryReturning(ctx); try { @@ -213,17 +200,14 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { catch (BadCredentialsException expected) { } - provider.authenticate(new UsernamePasswordAuthenticationToken("joe@mydomain.eu", - "password")); + provider.authenticate(new UsernamePasswordAuthenticationToken("joe@mydomain.eu", "password")); } @Test(expected = BadCredentialsException.class) public void failedUserSearchCausesBadCredentials() throws Exception { DirContext ctx = mock(DirContext.class); when(ctx.getNameInNamespace()).thenReturn(""); - when( - ctx.search(any(Name.class), any(String.class), any(Object[].class), - any(SearchControls.class))) + when(ctx.search(any(Name.class), any(String.class), any(Object[].class), any(SearchControls.class))) .thenThrow(new NameNotFoundException()); provider.contextFactory = createContextFactoryReturning(ctx); @@ -236,10 +220,8 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { public void noUserSearchCausesUsernameNotFound() throws Exception { DirContext ctx = mock(DirContext.class); when(ctx.getNameInNamespace()).thenReturn(""); - when( - ctx.search(any(Name.class), any(String.class), any(Object[].class), - any(SearchControls.class))).thenReturn( - new EmptyEnumeration<>()); + when(ctx.search(any(Name.class), any(String.class), any(Object[].class), any(SearchControls.class))) + .thenReturn(new EmptyEnumeration<>()); provider.contextFactory = createContextFactoryReturning(ctx); @@ -260,12 +242,10 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { NamingEnumeration searchResults = mock(NamingEnumeration.class); when(searchResults.hasMore()).thenReturn(true, true, false); SearchResult searchResult = mock(SearchResult.class); - when(searchResult.getObject()).thenReturn(new DirContextAdapter("ou=1"), - new DirContextAdapter("ou=2")); + when(searchResult.getObject()).thenReturn(new DirContextAdapter("ou=1"), new DirContextAdapter("ou=2")); when(searchResults.next()).thenReturn(searchResult); - when( - ctx.search(any(Name.class), any(String.class), any(Object[].class), - any(SearchControls.class))).thenReturn(searchResults); + when(ctx.search(any(Name.class), any(String.class), any(Object[].class), any(SearchControls.class))) + .thenReturn(searchResults); provider.contextFactory = createContextFactoryReturning(ctx); @@ -276,24 +256,21 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { @Test(expected = BadCredentialsException.class) public void userNotFoundIsCorrectlyMapped() { - provider.contextFactory = createContextFactoryThrowing(new AuthenticationException( - msg + "525, xxxx]")); + provider.contextFactory = createContextFactoryThrowing(new AuthenticationException(msg + "525, xxxx]")); provider.setConvertSubErrorCodesToExceptions(true); provider.authenticate(joe); } @Test(expected = BadCredentialsException.class) public void incorrectPasswordIsCorrectlyMapped() { - provider.contextFactory = createContextFactoryThrowing(new AuthenticationException( - msg + "52e, xxxx]")); + provider.contextFactory = createContextFactoryThrowing(new AuthenticationException(msg + "52e, xxxx]")); provider.setConvertSubErrorCodesToExceptions(true); provider.authenticate(joe); } @Test(expected = BadCredentialsException.class) public void notPermittedIsCorrectlyMapped() { - provider.contextFactory = createContextFactoryThrowing(new AuthenticationException( - msg + "530, xxxx]")); + provider.contextFactory = createContextFactoryThrowing(new AuthenticationException(msg + "530, xxxx]")); provider.setConvertSubErrorCodesToExceptions(true); provider.authenticate(joe); } @@ -301,22 +278,20 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { @Test public void passwordNeedsResetIsCorrectlyMapped() { final String dataCode = "773"; - provider.contextFactory = createContextFactoryThrowing(new AuthenticationException( - msg + dataCode + ", xxxx]")); + provider.contextFactory = createContextFactoryThrowing(new AuthenticationException(msg + dataCode + ", xxxx]")); provider.setConvertSubErrorCodesToExceptions(true); thrown.expect(BadCredentialsException.class); thrown.expect(new BaseMatcher() { private Matcher causeInstance = CoreMatchers .instanceOf(ActiveDirectoryAuthenticationException.class); + private Matcher causeDataCode = CoreMatchers.equalTo(dataCode); public boolean matches(Object that) { Throwable t = (Throwable) that; - ActiveDirectoryAuthenticationException cause = (ActiveDirectoryAuthenticationException) t - .getCause(); - return causeInstance.matches(cause) - && causeDataCode.matches(cause.getDataCode()); + ActiveDirectoryAuthenticationException cause = (ActiveDirectoryAuthenticationException) t.getCause(); + return causeInstance.matches(cause) && causeDataCode.matches(cause.getDataCode()); } public void describeTo(Description desc) { @@ -332,8 +307,7 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { @Test(expected = CredentialsExpiredException.class) public void expiredPasswordIsCorrectlyMapped() { - provider.contextFactory = createContextFactoryThrowing(new AuthenticationException( - msg + "532, xxxx]")); + provider.contextFactory = createContextFactoryThrowing(new AuthenticationException(msg + "532, xxxx]")); try { provider.authenticate(joe); @@ -348,40 +322,35 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { @Test(expected = DisabledException.class) public void accountDisabledIsCorrectlyMapped() { - provider.contextFactory = createContextFactoryThrowing(new AuthenticationException( - msg + "533, xxxx]")); + provider.contextFactory = createContextFactoryThrowing(new AuthenticationException(msg + "533, xxxx]")); provider.setConvertSubErrorCodesToExceptions(true); provider.authenticate(joe); } @Test(expected = AccountExpiredException.class) public void accountExpiredIsCorrectlyMapped() { - provider.contextFactory = createContextFactoryThrowing(new AuthenticationException( - msg + "701, xxxx]")); + provider.contextFactory = createContextFactoryThrowing(new AuthenticationException(msg + "701, xxxx]")); provider.setConvertSubErrorCodesToExceptions(true); provider.authenticate(joe); } @Test(expected = LockedException.class) public void accountLockedIsCorrectlyMapped() { - provider.contextFactory = createContextFactoryThrowing(new AuthenticationException( - msg + "775, xxxx]")); + provider.contextFactory = createContextFactoryThrowing(new AuthenticationException(msg + "775, xxxx]")); provider.setConvertSubErrorCodesToExceptions(true); provider.authenticate(joe); } @Test(expected = BadCredentialsException.class) public void unknownErrorCodeIsCorrectlyMapped() { - provider.contextFactory = createContextFactoryThrowing(new AuthenticationException( - msg + "999, xxxx]")); + provider.contextFactory = createContextFactoryThrowing(new AuthenticationException(msg + "999, xxxx]")); provider.setConvertSubErrorCodesToExceptions(true); provider.authenticate(joe); } @Test(expected = BadCredentialsException.class) public void errorWithNoSubcodeIsHandledCleanly() { - provider.contextFactory = createContextFactoryThrowing(new AuthenticationException( - msg)); + provider.contextFactory = createContextFactoryThrowing(new AuthenticationException(msg)); provider.setConvertSubErrorCodesToExceptions(true); provider.authenticate(joe); } @@ -389,22 +358,23 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { @Test(expected = org.springframework.ldap.CommunicationException.class) public void nonAuthenticationExceptionIsConvertedToSpringLdapException() throws Throwable { try { - provider.contextFactory = createContextFactoryThrowing(new CommunicationException( - msg)); + provider.contextFactory = createContextFactoryThrowing(new CommunicationException(msg)); provider.authenticate(joe); - } catch (InternalAuthenticationServiceException e) { - // Since GH-8418 ldap communication exception is wrapped into InternalAuthenticationServiceException. + } + catch (InternalAuthenticationServiceException e) { + // Since GH-8418 ldap communication exception is wrapped into + // InternalAuthenticationServiceException. // This test is about the wrapped exception, so we throw it. throw e.getCause(); } } - @Test(expected = org.springframework.security.authentication.InternalAuthenticationServiceException.class ) + @Test(expected = org.springframework.security.authentication.InternalAuthenticationServiceException.class) public void connectionExceptionIsWrappedInInternalException() throws Exception { ActiveDirectoryLdapAuthenticationProvider noneReachableProvider = new ActiveDirectoryLdapAuthenticationProvider( "mydomain.eu", NON_EXISTING_LDAP_PROVIDER, "dc=ad,dc=eu,dc=mydomain"); - noneReachableProvider.setContextEnvironmentProperties( - Collections.singletonMap("com.sun.jndi.ldap.connect.timeout", "5")); + noneReachableProvider + .setContextEnvironmentProperties(Collections.singletonMap("com.sun.jndi.ldap.connect.timeout", "5")); noneReachableProvider.doAuthentication(joe); } @@ -439,8 +409,8 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { } catch (InternalAuthenticationServiceException expected) { assertThat(expected.getCause()).isInstanceOf(org.springframework.ldap.CommunicationException.class); - org.springframework.ldap.CommunicationException cause = - (org.springframework.ldap.CommunicationException) expected.getCause(); + org.springframework.ldap.CommunicationException cause = (org.springframework.ldap.CommunicationException) expected + .getCause(); assertThat(cause.getRootCause()).isInstanceOf(ClassNotFoundException.class); } } @@ -463,20 +433,17 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { }; } - private void checkAuthentication(String rootDn, - ActiveDirectoryLdapAuthenticationProvider provider) throws NamingException { + private void checkAuthentication(String rootDn, ActiveDirectoryLdapAuthenticationProvider provider) + throws NamingException { DirContext ctx = mock(DirContext.class); when(ctx.getNameInNamespace()).thenReturn(""); DirContextAdapter dca = new DirContextAdapter(); - SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", dca, - dca.getAttributes()); + SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", dca, dca.getAttributes()); @SuppressWarnings("deprecation") DistinguishedName searchBaseDn = new DistinguishedName(rootDn); - when( - ctx.search(eq(searchBaseDn), any(String.class), any(Object[].class), - any(SearchControls.class))).thenReturn( - new MockNamingEnumeration(sr)).thenReturn(new MockNamingEnumeration(sr)); + when(ctx.search(eq(searchBaseDn), any(String.class), any(Object[].class), any(SearchControls.class))) + .thenReturn(new MockNamingEnumeration(sr)).thenReturn(new MockNamingEnumeration(sr)); provider.contextFactory = createContextFactoryReturning(ctx); @@ -492,6 +459,7 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { } static class MockNamingEnumeration implements NamingEnumeration { + private SearchResult sr; MockNamingEnumeration(SearchResult sr) { @@ -518,5 +486,7 @@ public class ActiveDirectoryLdapAuthenticationProviderTests { public SearchResult nextElement() { return next(); } + } + } diff --git a/ldap/src/test/java/org/springframework/security/ldap/ppolicy/OpenLDAPIntegrationTestSuite.java b/ldap/src/test/java/org/springframework/security/ldap/ppolicy/OpenLDAPIntegrationTestSuite.java index 02ed0e1c8f..4f6668d90c 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/ppolicy/OpenLDAPIntegrationTestSuite.java +++ b/ldap/src/test/java/org/springframework/security/ldap/ppolicy/OpenLDAPIntegrationTestSuite.java @@ -27,6 +27,7 @@ package org.springframework.security.ldap.ppolicy; public class OpenLDAPIntegrationTestSuite { PasswordPolicyAwareContextSource cs; + /* * @Before public void createContextSource() throws Exception { cs = new * PasswordPolicyAwareContextSource("ldap://localhost:22389/dc=springsource,dc=com"); @@ -60,4 +61,5 @@ public class OpenLDAPIntegrationTestSuite { * = (LdapUserDetailsImpl) a.getPrincipal(); assertTrue(ud.getTimeBeforeExpiration() < * Integer.MAX_VALUE && ud.getTimeBeforeExpiration() > 0); } */ + } diff --git a/ldap/src/test/java/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSourceTests.java b/ldap/src/test/java/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSourceTests.java index fbe36fc031..c90ab5f98f 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSourceTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/ppolicy/PasswordPolicyAwareContextSourceTests.java @@ -32,14 +32,15 @@ import java.util.*; * @author Luke Taylor */ public class PasswordPolicyAwareContextSourceTests { + private PasswordPolicyAwareContextSource ctxSource; + private final LdapContext ctx = mock(LdapContext.class); @Before public void setUp() { reset(ctx); - ctxSource = new PasswordPolicyAwareContextSource( - "ldap://blah:789/dc=springframework,dc=org") { + ctxSource = new PasswordPolicyAwareContextSource("ldap://blah:789/dc=springframework,dc=org") { @Override protected DirContext createContext(Hashtable env) { if ("manager".equals(env.get(Context.SECURITY_PRINCIPAL))) { @@ -60,24 +61,20 @@ public class PasswordPolicyAwareContextSourceTests { } @Test(expected = UncategorizedLdapException.class) - public void standardExceptionIsPropagatedWhenExceptionRaisedAndNoControlsAreSet() - throws Exception { - doThrow(new NamingException("some LDAP exception")).when(ctx).reconnect( - any(Control[].class)); + public void standardExceptionIsPropagatedWhenExceptionRaisedAndNoControlsAreSet() throws Exception { + doThrow(new NamingException("some LDAP exception")).when(ctx).reconnect(any(Control[].class)); ctxSource.getContext("user", "ignored"); } @Test(expected = PasswordPolicyException.class) - public void lockedPasswordPolicyControlRaisesPasswordPolicyException() - throws Exception { - when(ctx.getResponseControls()).thenReturn( - new Control[] { new PasswordPolicyResponseControl( - PasswordPolicyResponseControlTests.OPENLDAP_LOCKED_CTRL) }); + public void lockedPasswordPolicyControlRaisesPasswordPolicyException() throws Exception { + when(ctx.getResponseControls()).thenReturn(new Control[] { + new PasswordPolicyResponseControl(PasswordPolicyResponseControlTests.OPENLDAP_LOCKED_CTRL) }); - doThrow(new NamingException("locked message")).when(ctx).reconnect( - any(Control[].class)); + doThrow(new NamingException("locked message")).when(ctx).reconnect(any(Control[].class)); ctxSource.getContext("user", "ignored"); } + } diff --git a/ldap/src/test/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControlFactoryTests.java b/ldap/src/test/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControlFactoryTests.java index c29f13b34f..e8a687fa52 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControlFactoryTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/ppolicy/PasswordPolicyControlFactoryTests.java @@ -42,10 +42,10 @@ public class PasswordPolicyControlFactoryTests { Control control = mock(Control.class); when(control.getID()).thenReturn(PasswordPolicyControl.OID); - when(control.getEncodedValue()).thenReturn( - PasswordPolicyResponseControlTests.OPENLDAP_LOCKED_CTRL); + when(control.getEncodedValue()).thenReturn(PasswordPolicyResponseControlTests.OPENLDAP_LOCKED_CTRL); Control result = ctrlFactory.getControlInstance(control); assertThat(result).isNotNull(); assertThat(PasswordPolicyResponseControlTests.OPENLDAP_LOCKED_CTRL).isEqualTo(result.getEncodedValue()); } + } diff --git a/ldap/src/test/java/org/springframework/security/ldap/ppolicy/PasswordPolicyResponseControlTests.java b/ldap/src/test/java/org/springframework/security/ldap/ppolicy/PasswordPolicyResponseControlTests.java index 9ed6c7cd31..d76ea93e19 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/ppolicy/PasswordPolicyResponseControlTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/ppolicy/PasswordPolicyResponseControlTests.java @@ -26,6 +26,7 @@ import org.junit.Test; * @author Luke Taylor */ public class PasswordPolicyResponseControlTests { + // ~ Methods // ======================================================================================================== @@ -94,8 +95,7 @@ public class PasswordPolicyResponseControlTests { @Test public void openLDAP496GraceLoginsRemainingCtrlIsParsedCorrectly() { - byte[] ctrlBytes = { 0x30, 0x06, (byte) 0xA0, 0x04, (byte) 0xA1, 0x02, 0x01, - (byte) 0xF0 }; + byte[] ctrlBytes = { 0x30, 0x06, (byte) 0xA0, 0x04, (byte) 0xA1, 0x02, 0x01, (byte) 0xF0 }; PasswordPolicyResponseControl ctrl = new PasswordPolicyResponseControl(ctrlBytes); @@ -103,13 +103,11 @@ public class PasswordPolicyResponseControlTests { assertThat(ctrl.getGraceLoginsRemaining()).isEqualTo(496); } - static final byte[] OPENLDAP_5_LOGINS_REMAINING_CTRL = { 0x30, 0x05, (byte) 0xA0, - 0x03, (byte) 0xA1, 0x01, 0x05 }; + static final byte[] OPENLDAP_5_LOGINS_REMAINING_CTRL = { 0x30, 0x05, (byte) 0xA0, 0x03, (byte) 0xA1, 0x01, 0x05 }; @Test public void openLDAP5GraceLoginsRemainingCtrlIsParsedCorrectly() { - PasswordPolicyResponseControl ctrl = new PasswordPolicyResponseControl( - OPENLDAP_5_LOGINS_REMAINING_CTRL); + PasswordPolicyResponseControl ctrl = new PasswordPolicyResponseControl(OPENLDAP_5_LOGINS_REMAINING_CTRL); assertThat(ctrl.hasWarning()).isTrue(); assertThat(ctrl.getGraceLoginsRemaining()).isEqualTo(5); @@ -119,8 +117,7 @@ public class PasswordPolicyResponseControlTests { @Test public void openLDAPAccountLockedCtrlIsParsedCorrectly() { - PasswordPolicyResponseControl ctrl = new PasswordPolicyResponseControl( - OPENLDAP_LOCKED_CTRL); + PasswordPolicyResponseControl ctrl = new PasswordPolicyResponseControl(OPENLDAP_LOCKED_CTRL); assertThat(ctrl.hasError() && ctrl.isLocked()).isTrue(); assertThat(ctrl.hasWarning()).isFalse(); @@ -135,4 +132,5 @@ public class PasswordPolicyResponseControlTests { assertThat(ctrl.hasError() && ctrl.isExpired()).isTrue(); assertThat(ctrl.hasWarning()).isFalse(); } + } diff --git a/ldap/src/test/java/org/springframework/security/ldap/userdetails/InetOrgPersonTests.java b/ldap/src/test/java/org/springframework/security/ldap/userdetails/InetOrgPersonTests.java index 168f725460..bb30851175 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/userdetails/InetOrgPersonTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/userdetails/InetOrgPersonTests.java @@ -95,11 +95,10 @@ public class InetOrgPersonTests { public void mappingBackToContextMatchesOriginalData() { DirContextAdapter ctx1 = createUserContext(); DirContextAdapter ctx2 = new DirContextAdapter(); - ctx1.setAttributeValues("objectclass", new String[] { "top", "person", - "organizationalPerson", "inetOrgPerson" }); + ctx1.setAttributeValues("objectclass", + new String[] { "top", "person", "organizationalPerson", "inetOrgPerson" }); ctx2.setDn(new DistinguishedName("ignored=ignored")); - InetOrgPerson p = (InetOrgPerson) (new InetOrgPerson.Essence(ctx1)) - .createUserDetails(); + InetOrgPerson p = (InetOrgPerson) (new InetOrgPerson.Essence(ctx1)).createUserDetails(); p.populateContext(ctx2); assertThat(ctx2).isEqualTo(ctx1); @@ -110,12 +109,10 @@ public class InetOrgPersonTests { DirContextAdapter ctx1 = createUserContext(); DirContextAdapter ctx2 = new DirContextAdapter(); ctx2.setDn(new DistinguishedName("ignored=ignored")); - ctx1.setAttributeValues("objectclass", new String[] { "top", "person", - "organizationalPerson", "inetOrgPerson" }); - InetOrgPerson p = (InetOrgPerson) (new InetOrgPerson.Essence(ctx1)) - .createUserDetails(); - InetOrgPerson p2 = (InetOrgPerson) new InetOrgPerson.Essence(p) - .createUserDetails(); + ctx1.setAttributeValues("objectclass", + new String[] { "top", "person", "organizationalPerson", "inetOrgPerson" }); + InetOrgPerson p = (InetOrgPerson) (new InetOrgPerson.Essence(ctx1)).createUserDetails(); + InetOrgPerson p2 = (InetOrgPerson) new InetOrgPerson.Essence(p).createUserDetails(); p2.populateContext(ctx2); assertThat(ctx2).isEqualTo(ctx1); diff --git a/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapAuthorityTests.java b/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapAuthorityTests.java index c6727986c7..b2d51183f2 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapAuthorityTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapAuthorityTests.java @@ -32,14 +32,14 @@ import static org.assertj.core.api.Assertions.assertThat; public class LdapAuthorityTests { public static final String DN = "cn=filip,ou=Users,dc=test,dc=com"; + LdapAuthority authority; @Before public void setUp() { Map> attributes = new HashMap<>(); attributes.put(SpringSecurityLdapTemplate.DN_KEY, Arrays.asList(DN)); - attributes.put("mail", - Arrays.asList("filip@ldap.test.org", "filip@ldap.test2.org")); + attributes.put("mail", Arrays.asList("filip@ldap.test.org", "filip@ldap.test2.org")); authority = new LdapAuthority("testRole", DN, attributes); } @@ -66,4 +66,5 @@ public class LdapAuthorityTests { assertThat(authority.getAuthority()).isNotNull(); assertThat(authority.getAuthority()).isEqualTo("testRole"); } + } diff --git a/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapperTests.java b/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapperTests.java index 1c8ca9e384..40dfe14fc9 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapperTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsMapperTests.java @@ -48,8 +48,8 @@ public class LdapUserDetailsMapperTests { ctx.setAttributeValues("userRole", new String[] { "X", "Y", "Z" }); ctx.setAttributeValue("uid", "ani"); - LdapUserDetailsImpl user = (LdapUserDetailsImpl) mapper.mapUserFromContext(ctx, - "ani", AuthorityUtils.NO_AUTHORITIES); + LdapUserDetailsImpl user = (LdapUserDetailsImpl) mapper.mapUserFromContext(ctx, "ani", + AuthorityUtils.NO_AUTHORITIES); assertThat(user.getAuthorities()).hasSize(3); } @@ -66,12 +66,11 @@ public class LdapUserDetailsMapperTests { BasicAttributes attrs = new BasicAttributes(); attrs.put(new BasicAttribute("userRole", "x")); - DirContextAdapter ctx = new DirContextAdapter(attrs, - new DistinguishedName("cn=someName")); + DirContextAdapter ctx = new DirContextAdapter(attrs, new DistinguishedName("cn=someName")); ctx.setAttributeValue("uid", "ani"); - LdapUserDetailsImpl user = (LdapUserDetailsImpl) mapper.mapUserFromContext(ctx, - "ani", AuthorityUtils.NO_AUTHORITIES); + LdapUserDetailsImpl user = (LdapUserDetailsImpl) mapper.mapUserFromContext(ctx, "ani", + AuthorityUtils.NO_AUTHORITIES); assertThat(user.getAuthorities()).hasSize(1); assertThat(AuthorityUtils.authorityListToSet(user.getAuthorities())).contains("ROLE_X"); @@ -85,8 +84,7 @@ public class LdapUserDetailsMapperTests { BasicAttributes attrs = new BasicAttributes(); attrs.put(new BasicAttribute("myappsPassword", "mypassword".getBytes())); - DirContextAdapter ctx = new DirContextAdapter(attrs, - new DistinguishedName("cn=someName")); + DirContextAdapter ctx = new DirContextAdapter(attrs, new DistinguishedName("cn=someName")); ctx.setAttributeValue("uid", "ani"); LdapUserDetails user = (LdapUserDetailsImpl) mapper.mapUserFromContext(ctx, "ani", diff --git a/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsServiceTests.java b/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsServiceTests.java index d8ff18881a..5c283eb01b 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsServiceTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsServiceTests.java @@ -49,36 +49,34 @@ public class LdapUserDetailsServiceTests { @Test public void correctAuthoritiesAreReturned() { - DirContextAdapter userData = new DirContextAdapter(new DistinguishedName( - "uid=joe")); + DirContextAdapter userData = new DirContextAdapter(new DistinguishedName("uid=joe")); - LdapUserDetailsService service = new LdapUserDetailsService(new MockUserSearch( - userData), new MockAuthoritiesPopulator()); + LdapUserDetailsService service = new LdapUserDetailsService(new MockUserSearch(userData), + new MockAuthoritiesPopulator()); service.setUserDetailsMapper(new LdapUserDetailsMapper()); UserDetails user = service.loadUserByUsername("doesntmatterwegetjoeanyway"); - Set authorities = AuthorityUtils - .authorityListToSet(user.getAuthorities()); + Set authorities = AuthorityUtils.authorityListToSet(user.getAuthorities()); assertThat(authorities).hasSize(1); assertThat(authorities.contains("ROLE_FROM_POPULATOR")).isTrue(); } @Test public void nullPopulatorConstructorReturnsEmptyAuthoritiesList() { - DirContextAdapter userData = new DirContextAdapter(new DistinguishedName( - "uid=joe")); + DirContextAdapter userData = new DirContextAdapter(new DistinguishedName("uid=joe")); - LdapUserDetailsService service = new LdapUserDetailsService(new MockUserSearch( - userData)); + LdapUserDetailsService service = new LdapUserDetailsService(new MockUserSearch(userData)); UserDetails user = service.loadUserByUsername("doesntmatterwegetjoeanyway"); assertThat(user.getAuthorities()).isEmpty(); } class MockAuthoritiesPopulator implements LdapAuthoritiesPopulator { - public Collection getGrantedAuthorities( - DirContextOperations userCtx, String username) { + + public Collection getGrantedAuthorities(DirContextOperations userCtx, String username) { return AuthorityUtils.createAuthorityList("ROLE_FROM_POPULATOR"); } + } + } diff --git a/ldap/src/test/java/org/springframework/security/ldap/userdetails/UserDetailsServiceLdapAuthoritiesPopulatorTests.java b/ldap/src/test/java/org/springframework/security/ldap/userdetails/UserDetailsServiceLdapAuthoritiesPopulatorTests.java index 083f91c32d..cc96cfeefc 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/userdetails/UserDetailsServiceLdapAuthoritiesPopulatorTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/userdetails/UserDetailsServiceLdapAuthoritiesPopulatorTests.java @@ -42,12 +42,11 @@ public class UserDetailsServiceLdapAuthoritiesPopulatorTests { List authorities = AuthorityUtils.createAuthorityList("ROLE_USER"); when(user.getAuthorities()).thenReturn(authorities); - UserDetailsServiceLdapAuthoritiesPopulator populator = new UserDetailsServiceLdapAuthoritiesPopulator( - uds); - Collection auths = populator.getGrantedAuthorities( - new DirContextAdapter(), "joe"); + UserDetailsServiceLdapAuthoritiesPopulator populator = new UserDetailsServiceLdapAuthoritiesPopulator(uds); + Collection auths = populator.getGrantedAuthorities(new DirContextAdapter(), "joe"); assertThat(auths).hasSize(1); assertThat(AuthorityUtils.authorityListToSet(auths).contains("ROLE_USER")).isTrue(); } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/expression/DefaultMessageSecurityExpressionHandler.java b/messaging/src/main/java/org/springframework/security/messaging/access/expression/DefaultMessageSecurityExpressionHandler.java index dee415443a..c287fc8bf9 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/access/expression/DefaultMessageSecurityExpressionHandler.java +++ b/messaging/src/main/java/org/springframework/security/messaging/access/expression/DefaultMessageSecurityExpressionHandler.java @@ -29,20 +29,17 @@ import org.springframework.util.Assert; * {@link MessageSecurityExpressionRoot}. * * @param the type for the body of the Message - * * @since 4.0 * @author Rob Winch */ -public class DefaultMessageSecurityExpressionHandler extends - AbstractSecurityExpressionHandler> { +public class DefaultMessageSecurityExpressionHandler extends AbstractSecurityExpressionHandler> { private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); @Override - protected SecurityExpressionOperations createSecurityExpressionRoot( - Authentication authentication, Message invocation) { - MessageSecurityExpressionRoot root = new MessageSecurityExpressionRoot( - authentication, invocation); + protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, + Message invocation) { + MessageSecurityExpressionRoot root = new MessageSecurityExpressionRoot(authentication, invocation); root.setPermissionEvaluator(getPermissionEvaluator()); root.setTrustResolver(trustResolver); root.setRoleHierarchy(getRoleHierarchy()); @@ -53,4 +50,5 @@ public class DefaultMessageSecurityExpressionHandler extends Assert.notNull(trustResolver, "trustResolver cannot be null"); this.trustResolver = trustResolver; } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/expression/EvaluationContextPostProcessor.java b/messaging/src/main/java/org/springframework/security/messaging/access/expression/EvaluationContextPostProcessor.java index 847969bca2..6009fe07a6 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/access/expression/EvaluationContextPostProcessor.java +++ b/messaging/src/main/java/org/springframework/security/messaging/access/expression/EvaluationContextPostProcessor.java @@ -19,8 +19,7 @@ import org.springframework.expression.EvaluationContext; /** * -/** - * Allows post processing the {@link EvaluationContext} + * /** Allows post processing the {@link EvaluationContext} * *

        * This API is intentionally kept package scope as it may evolve over time. @@ -32,15 +31,13 @@ import org.springframework.expression.EvaluationContext; interface EvaluationContextPostProcessor { /** - * Allows post processing of the {@link EvaluationContext}. Implementations - * may return a new instance of {@link EvaluationContext} or modify the - * {@link EvaluationContext} that was passed in. - * - * @param context - * the original {@link EvaluationContext} - * @param invocation - * the security invocation object (i.e. Message) + * Allows post processing of the {@link EvaluationContext}. Implementations may return + * a new instance of {@link EvaluationContext} or modify the {@link EvaluationContext} + * that was passed in. + * @param context the original {@link EvaluationContext} + * @param invocation the security invocation object (i.e. Message) * @return the upated context. */ EvaluationContext postProcess(EvaluationContext context, I invocation); + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactory.java b/messaging/src/main/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactory.java index 69934b64b4..b56c9de3ea 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactory.java +++ b/messaging/src/main/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactory.java @@ -61,7 +61,6 @@ public final class ExpressionBasedMessageSecurityMetadataSourceFactory { * *

        * For a complete listing of expressions see {@link MessageSecurityExpressionRoot} - * * @param matcherToExpression an ordered mapping of {@link MessageMatcher} to Strings * that are turned into an Expression using * {@link DefaultMessageSecurityExpressionHandler#getExpressionParser()} @@ -69,7 +68,8 @@ public final class ExpressionBasedMessageSecurityMetadataSourceFactory { */ public static MessageSecurityMetadataSource createExpressionMessageMetadataSource( LinkedHashMap, String> matcherToExpression) { - return createExpressionMessageMetadataSource(matcherToExpression, new DefaultMessageSecurityExpressionHandler<>()); + return createExpressionMessageMetadataSource(matcherToExpression, + new DefaultMessageSecurityExpressionHandler<>()); } /** @@ -98,7 +98,6 @@ public final class ExpressionBasedMessageSecurityMetadataSourceFactory { *

        * For a complete listing of expressions see {@link MessageSecurityExpressionRoot} *

        - * * @param matcherToExpression an ordered mapping of {@link MessageMatcher} to Strings * that are turned into an Expression using * {@link DefaultMessageSecurityExpressionHandler#getExpressionParser()} @@ -106,15 +105,15 @@ public final class ExpressionBasedMessageSecurityMetadataSourceFactory { * @return the {@link MessageSecurityMetadataSource} to use. Cannot be null. */ public static MessageSecurityMetadataSource createExpressionMessageMetadataSource( - LinkedHashMap, String> matcherToExpression, SecurityExpressionHandler> handler) { + LinkedHashMap, String> matcherToExpression, + SecurityExpressionHandler> handler) { LinkedHashMap, Collection> matcherToAttrs = new LinkedHashMap<>(); for (Map.Entry, String> entry : matcherToExpression.entrySet()) { MessageMatcher matcher = entry.getKey(); String rawExpression = entry.getValue(); - Expression expression = handler.getExpressionParser().parseExpression( - rawExpression); + Expression expression = handler.getExpressionParser().parseExpression(rawExpression); ConfigAttribute attribute = new MessageExpressionConfigAttribute(expression, matcher); matcherToAttrs.put(matcher, Arrays.asList(attribute)); } @@ -123,4 +122,5 @@ public final class ExpressionBasedMessageSecurityMetadataSourceFactory { private ExpressionBasedMessageSecurityMetadataSourceFactory() { } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttribute.java b/messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttribute.java index 51a599c7f0..84ffed8135 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttribute.java +++ b/messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttribute.java @@ -34,13 +34,13 @@ import java.util.Map; */ @SuppressWarnings("serial") class MessageExpressionConfigAttribute implements ConfigAttribute, EvaluationContextPostProcessor> { - private final Expression authorizeExpression; - private final MessageMatcher matcher; + private final Expression authorizeExpression; + + private final MessageMatcher matcher; /** * Creates a new instance - * * @param authorizeExpression the {@link Expression} to use. Cannot be null * @param matcher the {@link MessageMatcher} used to match the messages. */ @@ -51,7 +51,6 @@ class MessageExpressionConfigAttribute implements ConfigAttribute, EvaluationCon this.matcher = matcher; } - Expression getAuthorizeExpression() { return authorizeExpression; } @@ -68,11 +67,13 @@ class MessageExpressionConfigAttribute implements ConfigAttribute, EvaluationCon @Override public EvaluationContext postProcess(EvaluationContext ctx, Message message) { if (matcher instanceof SimpDestinationMessageMatcher) { - final Map variables = ((SimpDestinationMessageMatcher) matcher).extractPathVariables(message); - for (Map.Entry entry : variables.entrySet()){ + final Map variables = ((SimpDestinationMessageMatcher) matcher) + .extractPathVariables(message); + for (Map.Entry entry : variables.entrySet()) { ctx.setVariable(entry.getKey(), entry.getValue()); } } return ctx; } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionVoter.java b/messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionVoter.java index 0d06873e59..401ee8ae7a 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionVoter.java +++ b/messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageExpressionVoter.java @@ -38,10 +38,10 @@ import java.util.Collection; * @author Daniel Bustamante Ospina */ public class MessageExpressionVoter implements AccessDecisionVoter> { + private SecurityExpressionHandler> expressionHandler = new DefaultMessageSecurityExpressionHandler<>(); - public int vote(Authentication authentication, Message message, - Collection attributes) { + public int vote(Authentication authentication, Message message, Collection attributes) { assert authentication != null; assert message != null; assert attributes != null; @@ -52,16 +52,13 @@ public class MessageExpressionVoter implements AccessDecisionVoter return ACCESS_ABSTAIN; } - EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, - message); + EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, message); ctx = attr.postProcess(ctx, message); - return ExpressionUtils.evaluateAsBoolean(attr.getAuthorizeExpression(), ctx) ? ACCESS_GRANTED - : ACCESS_DENIED; + return ExpressionUtils.evaluateAsBoolean(attr.getAuthorizeExpression(), ctx) ? ACCESS_GRANTED : ACCESS_DENIED; } - private MessageExpressionConfigAttribute findConfigAttribute( - Collection attributes) { + private MessageExpressionConfigAttribute findConfigAttribute(Collection attributes) { for (ConfigAttribute attribute : attributes) { if (attribute instanceof MessageExpressionConfigAttribute) { return (MessageExpressionConfigAttribute) attribute; @@ -78,9 +75,9 @@ public class MessageExpressionVoter implements AccessDecisionVoter return Message.class.isAssignableFrom(clazz); } - public void setExpressionHandler( - SecurityExpressionHandler> expressionHandler) { + public void setExpressionHandler(SecurityExpressionHandler> expressionHandler) { Assert.notNull(expressionHandler, "expressionHandler cannot be null"); this.expressionHandler = expressionHandler; } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageSecurityExpressionRoot.java b/messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageSecurityExpressionRoot.java index 2a7580f778..82ba70c3b8 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageSecurityExpressionRoot.java +++ b/messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageSecurityExpressionRoot.java @@ -33,4 +33,5 @@ public class MessageSecurityExpressionRoot extends SecurityExpressionRoot { super(authentication); this.message = message; } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptor.java b/messaging/src/main/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptor.java index 8efd76b741..77d6c31c13 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptor.java +++ b/messaging/src/main/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptor.java @@ -36,15 +36,14 @@ import org.springframework.util.Assert; * @since 4.0 * @author Rob Winch */ -public final class ChannelSecurityInterceptor extends AbstractSecurityInterceptor - implements ChannelInterceptor { +public final class ChannelSecurityInterceptor extends AbstractSecurityInterceptor implements ChannelInterceptor { + private static final ThreadLocal tokenHolder = new ThreadLocal<>(); private final MessageSecurityMetadataSource metadataSource; /** * Creates a new instance - * * @param metadataSource the MessageSecurityMetadataSource to use. Cannot be null. * * @see DefaultMessageSecurityMetadataSource @@ -78,8 +77,7 @@ public final class ChannelSecurityInterceptor extends AbstractSecurityIntercepto afterInvocation(token, null); } - public void afterSendCompletion(Message message, MessageChannel channel, - boolean sent, Exception ex) { + public void afterSendCompletion(Message message, MessageChannel channel, boolean sent, Exception ex) { InterceptorStatusToken token = clearToken(); finallyInvocation(token); } @@ -92,8 +90,7 @@ public final class ChannelSecurityInterceptor extends AbstractSecurityIntercepto return message; } - public void afterReceiveCompletion(Message message, MessageChannel channel, - Exception ex) { + public void afterReceiveCompletion(Message message, MessageChannel channel, Exception ex) { } private InterceptorStatusToken clearToken() { @@ -101,4 +98,5 @@ public final class ChannelSecurityInterceptor extends AbstractSecurityIntercepto tokenHolder.remove(); return token; } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSource.java b/messaging/src/main/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSource.java index 13c661a0c1..f3ccfc7474 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSource.java +++ b/messaging/src/main/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSource.java @@ -33,12 +33,11 @@ import java.util.*; * * @see ChannelSecurityInterceptor * @see ExpressionBasedMessageSecurityMetadataSourceFactory - * * @since 4.0 * @author Rob Winch */ -public final class DefaultMessageSecurityMetadataSource implements - MessageSecurityMetadataSource { +public final class DefaultMessageSecurityMetadataSource implements MessageSecurityMetadataSource { + private final Map, Collection> messageMap; public DefaultMessageSecurityMetadataSource( @@ -47,11 +46,9 @@ public final class DefaultMessageSecurityMetadataSource implements } @SuppressWarnings({ "rawtypes", "unchecked" }) - public Collection getAttributes(Object object) - throws IllegalArgumentException { + public Collection getAttributes(Object object) throws IllegalArgumentException { final Message message = (Message) object; - for (Map.Entry, Collection> entry : messageMap - .entrySet()) { + for (Map.Entry, Collection> entry : messageMap.entrySet()) { if (entry.getKey().matches(message)) { return entry.getValue(); } @@ -72,4 +69,5 @@ public final class DefaultMessageSecurityMetadataSource implements public boolean supports(Class clazz) { return Message.class.isAssignableFrom(clazz); } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource.java b/messaging/src/main/java/org/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource.java index fefca0620d..0b48b857f9 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource.java +++ b/messaging/src/main/java/org/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource.java @@ -23,9 +23,9 @@ import org.springframework.security.access.SecurityMetadataSource; * * @see ChannelSecurityInterceptor * @see DefaultMessageSecurityMetadataSource - * * @since 4.0 * @author Rob Winch */ public interface MessageSecurityMetadataSource extends SecurityMetadataSource { + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/context/AuthenticationPrincipalArgumentResolver.java b/messaging/src/main/java/org/springframework/security/messaging/context/AuthenticationPrincipalArgumentResolver.java index faebd3d2d9..ea1869a3d2 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/context/AuthenticationPrincipalArgumentResolver.java +++ b/messaging/src/main/java/org/springframework/security/messaging/context/AuthenticationPrincipalArgumentResolver.java @@ -81,8 +81,7 @@ import org.springframework.util.StringUtils; * @author Rob Winch * @since 4.0 */ -public final class AuthenticationPrincipalArgumentResolver - implements HandlerMethodArgumentResolver { +public final class AuthenticationPrincipalArgumentResolver implements HandlerMethodArgumentResolver { private ExpressionParser parser = new SpelExpressionParser(); @@ -106,15 +105,13 @@ public final class AuthenticationPrincipalArgumentResolver * org.springframework.messaging.Message) */ public Object resolveArgument(MethodParameter parameter, Message message) { - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { return null; } Object principal = authentication.getPrincipal(); - AuthenticationPrincipal authPrincipal = findMethodAnnotation( - AuthenticationPrincipal.class, parameter); + AuthenticationPrincipal authPrincipal = findMethodAnnotation(AuthenticationPrincipal.class, parameter); String expressionToParse = authPrincipal.expression(); if (StringUtils.hasLength(expressionToParse)) { @@ -126,11 +123,9 @@ public final class AuthenticationPrincipalArgumentResolver principal = expression.getValue(context); } - if (principal != null - && !parameter.getParameterType().isAssignableFrom(principal.getClass())) { + if (principal != null && !parameter.getParameterType().isAssignableFrom(principal.getClass())) { if (authPrincipal.errorOnInvalidType()) { - throw new ClassCastException(principal + " is not assignable to " - + parameter.getParameterType()); + throw new ClassCastException(principal + " is not assignable to " + parameter.getParameterType()); } else { return null; @@ -141,26 +136,24 @@ public final class AuthenticationPrincipalArgumentResolver /** * Obtains the specified {@link Annotation} on the specified {@link MethodParameter}. - * * @param annotationClass the class of the {@link Annotation} to find on the * {@link MethodParameter} * @param parameter the {@link MethodParameter} to search for an {@link Annotation} * @return the {@link Annotation} that was found or null. */ - private T findMethodAnnotation(Class annotationClass, - MethodParameter parameter) { + private T findMethodAnnotation(Class annotationClass, MethodParameter parameter) { T annotation = parameter.getParameterAnnotation(annotationClass); if (annotation != null) { return annotation; } Annotation[] annotationsToSearch = parameter.getParameterAnnotations(); for (Annotation toSearch : annotationsToSearch) { - annotation = AnnotationUtils.findAnnotation(toSearch.annotationType(), - annotationClass); + annotation = AnnotationUtils.findAnnotation(toSearch.annotationType(), annotationClass); if (annotation != null) { return annotation; } } return null; } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/context/SecurityContextChannelInterceptor.java b/messaging/src/main/java/org/springframework/security/messaging/context/SecurityContextChannelInterceptor.java index 50f5113dd9..c391e39727 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/context/SecurityContextChannelInterceptor.java +++ b/messaging/src/main/java/org/springframework/security/messaging/context/SecurityContextChannelInterceptor.java @@ -41,14 +41,15 @@ import org.springframework.util.Assert; */ public final class SecurityContextChannelInterceptor extends ChannelInterceptorAdapter implements ExecutorChannelInterceptor { - private final SecurityContext EMPTY_CONTEXT = SecurityContextHolder - .createEmptyContext(); + + private final SecurityContext EMPTY_CONTEXT = SecurityContextHolder.createEmptyContext(); + private static final ThreadLocal> ORIGINAL_CONTEXT = new ThreadLocal<>(); private final String authenticationHeaderName; - private Authentication anonymous = new AnonymousAuthenticationToken("key", - "anonymous", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); + private Authentication anonymous = new AnonymousAuthenticationToken("key", "anonymous", + AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); /** * Creates a new instance using the header of the name @@ -61,13 +62,11 @@ public final class SecurityContextChannelInterceptor extends ChannelInterceptorA /** * Creates a new instance that uses the specified header to obtain the * {@link Authentication}. - * * @param authenticationHeaderName the header name to obtain the * {@link Authentication}. Cannot be null. */ public SecurityContextChannelInterceptor(String authenticationHeaderName) { - Assert.notNull(authenticationHeaderName, - "authenticationHeaderName cannot be null"); + Assert.notNull(authenticationHeaderName, "authenticationHeaderName cannot be null"); this.authenticationHeaderName = authenticationHeaderName; } @@ -78,7 +77,6 @@ public final class SecurityContextChannelInterceptor extends ChannelInterceptorA * new AnonymousAuthenticationToken("key", "anonymous", * AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); * - * * @param authentication the Authentication used for anonymous authentication. Cannot * be null. */ @@ -94,19 +92,16 @@ public final class SecurityContextChannelInterceptor extends ChannelInterceptorA } @Override - public void afterSendCompletion(Message message, MessageChannel channel, - boolean sent, Exception ex) { + public void afterSendCompletion(Message message, MessageChannel channel, boolean sent, Exception ex) { cleanup(); } - public Message beforeHandle(Message message, MessageChannel channel, - MessageHandler handler) { + public Message beforeHandle(Message message, MessageChannel channel, MessageHandler handler) { setup(message); return message; } - public void afterMessageHandled(Message message, MessageChannel channel, - MessageHandler handler, Exception ex) { + public void afterMessageHandled(Message message, MessageChannel channel, MessageHandler handler, Exception ex) { cleanup(); } @@ -158,4 +153,5 @@ public final class SecurityContextChannelInterceptor extends ChannelInterceptorA SecurityContextHolder.clearContext(); } } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/handler/invocation/reactive/AuthenticationPrincipalArgumentResolver.java b/messaging/src/main/java/org/springframework/security/messaging/handler/invocation/reactive/AuthenticationPrincipalArgumentResolver.java index c34fb576ac..a62bae337e 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/handler/invocation/reactive/AuthenticationPrincipalArgumentResolver.java +++ b/messaging/src/main/java/org/springframework/security/messaging/handler/invocation/reactive/AuthenticationPrincipalArgumentResolver.java @@ -86,18 +86,17 @@ import java.lang.annotation.Annotation; * } * } * + * * @author Rob Winch * @since 5.2 */ -public class AuthenticationPrincipalArgumentResolver - implements HandlerMethodArgumentResolver { +public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArgumentResolver { private ExpressionParser parser = new SpelExpressionParser(); private BeanResolver beanResolver; - private ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry - .getSharedInstance(); + private ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); /** * Sets the {@link BeanResolver} to be used on the expressions @@ -109,8 +108,8 @@ public class AuthenticationPrincipalArgumentResolver /** * Sets the {@link ReactiveAdapterRegistry} to be used. - * @param adapterRegistry the {@link ReactiveAdapterRegistry} to use. Cannot be null. Default is - * {@link ReactiveAdapterRegistry#getSharedInstance()} + * @param adapterRegistry the {@link ReactiveAdapterRegistry} to use. Cannot be null. + * Default is {@link ReactiveAdapterRegistry#getSharedInstance()} */ public void setAdapterRegistry(ReactiveAdapterRegistry adapterRegistry) { Assert.notNull(adapterRegistry, "adapterRegistry cannot be null"); @@ -123,21 +122,16 @@ public class AuthenticationPrincipalArgumentResolver } public Mono resolveArgument(MethodParameter parameter, Message message) { - ReactiveAdapter adapter = this.adapterRegistry - .getAdapter(parameter.getParameterType()); - return ReactiveSecurityContextHolder.getContext() - .map(SecurityContext::getAuthentication).flatMap(a -> { - Object p = resolvePrincipal(parameter, a.getPrincipal()); - Mono principal = Mono.justOrEmpty(p); - return adapter == null ? - principal : - Mono.just(adapter.fromPublisher(principal)); - }); + ReactiveAdapter adapter = this.adapterRegistry.getAdapter(parameter.getParameterType()); + return ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication).flatMap(a -> { + Object p = resolvePrincipal(parameter, a.getPrincipal()); + Mono principal = Mono.justOrEmpty(p); + return adapter == null ? principal : Mono.just(adapter.fromPublisher(principal)); + }); } private Object resolvePrincipal(MethodParameter parameter, Object principal) { - AuthenticationPrincipal authPrincipal = findMethodAnnotation( - AuthenticationPrincipal.class, parameter); + AuthenticationPrincipal authPrincipal = findMethodAnnotation(AuthenticationPrincipal.class, parameter); String expressionToParse = authPrincipal.expression(); if (StringUtils.hasLength(expressionToParse)) { @@ -153,9 +147,7 @@ public class AuthenticationPrincipalArgumentResolver if (isInvalidType(parameter, principal)) { if (authPrincipal.errorOnInvalidType()) { - throw new ClassCastException( - principal + " is not assignable to " + parameter - .getParameterType()); + throw new ClassCastException(principal + " is not assignable to " + parameter.getParameterType()); } else { return null; @@ -170,8 +162,7 @@ public class AuthenticationPrincipalArgumentResolver return false; } Class typeToCheck = parameter.getParameterType(); - boolean isParameterPublisher = Publisher.class - .isAssignableFrom(parameter.getParameterType()); + boolean isParameterPublisher = Publisher.class.isAssignableFrom(parameter.getParameterType()); if (isParameterPublisher) { ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter); Class genericType = resolvableType.resolveGeneric(0); @@ -185,26 +176,24 @@ public class AuthenticationPrincipalArgumentResolver /** * Obtains the specified {@link Annotation} on the specified {@link MethodParameter}. - * * @param annotationClass the class of the {@link Annotation} to find on the - * {@link MethodParameter} - * @param parameter the {@link MethodParameter} to search for an {@link Annotation} + * {@link MethodParameter} + * @param parameter the {@link MethodParameter} to search for an {@link Annotation} * @return the {@link Annotation} that was found or null. */ - private T findMethodAnnotation(Class annotationClass, - MethodParameter parameter) { + private T findMethodAnnotation(Class annotationClass, MethodParameter parameter) { T annotation = parameter.getParameterAnnotation(annotationClass); if (annotation != null) { return annotation; } Annotation[] annotationsToSearch = parameter.getParameterAnnotations(); for (Annotation toSearch : annotationsToSearch) { - annotation = AnnotationUtils - .findAnnotation(toSearch.annotationType(), annotationClass); + annotation = AnnotationUtils.findAnnotation(toSearch.annotationType(), annotationClass); if (annotation != null) { return annotation; } } return null; } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/handler/invocation/reactive/CurrentSecurityContextArgumentResolver.java b/messaging/src/main/java/org/springframework/security/messaging/handler/invocation/reactive/CurrentSecurityContextArgumentResolver.java index f771a7d03a..02c7e6a375 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/handler/invocation/reactive/CurrentSecurityContextArgumentResolver.java +++ b/messaging/src/main/java/org/springframework/security/messaging/handler/invocation/reactive/CurrentSecurityContextArgumentResolver.java @@ -56,9 +56,9 @@ import java.lang.annotation.Annotation; * * *

        - * Will resolve the SecurityContext argument using the {@link ReactiveSecurityContextHolder}. - * If the {@link SecurityContext} is empty, it will return null. If the types do not - * match, null will be returned unless + * Will resolve the SecurityContext argument using the + * {@link ReactiveSecurityContextHolder}. If the {@link SecurityContext} is empty, it will + * return null. If the types do not match, null will be returned unless * {@link CurrentSecurityContext#errorOnInvalidType()} is true in which case a * {@link ClassCastException} will be thrown. * @@ -85,18 +85,17 @@ import java.lang.annotation.Annotation; * } * } * + * * @author Rob Winch * @since 5.2 */ -public class CurrentSecurityContextArgumentResolver - implements HandlerMethodArgumentResolver { +public class CurrentSecurityContextArgumentResolver implements HandlerMethodArgumentResolver { private ExpressionParser parser = new SpelExpressionParser(); private BeanResolver beanResolver; - private ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry - .getSharedInstance(); + private ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); /** * Sets the {@link BeanResolver} to be used on the expressions @@ -108,8 +107,8 @@ public class CurrentSecurityContextArgumentResolver /** * Sets the {@link ReactiveAdapterRegistry} to be used. - * @param adapterRegistry the {@link ReactiveAdapterRegistry} to use. Cannot be null. Default is - * {@link ReactiveAdapterRegistry#getSharedInstance()} + * @param adapterRegistry the {@link ReactiveAdapterRegistry} to use. Cannot be null. + * Default is {@link ReactiveAdapterRegistry#getSharedInstance()} */ public void setAdapterRegistry(ReactiveAdapterRegistry adapterRegistry) { Assert.notNull(adapterRegistry, "adapterRegistry cannot be null"); @@ -122,21 +121,16 @@ public class CurrentSecurityContextArgumentResolver } public Mono resolveArgument(MethodParameter parameter, Message message) { - ReactiveAdapter adapter = this.adapterRegistry - .getAdapter(parameter.getParameterType()); - return ReactiveSecurityContextHolder.getContext() - .flatMap(securityContext -> { - Object sc = resolveSecurityContext(parameter, securityContext); - Mono result = Mono.justOrEmpty(sc); - return adapter == null ? - result : - Mono.just(adapter.fromPublisher(result)); - }); + ReactiveAdapter adapter = this.adapterRegistry.getAdapter(parameter.getParameterType()); + return ReactiveSecurityContextHolder.getContext().flatMap(securityContext -> { + Object sc = resolveSecurityContext(parameter, securityContext); + Mono result = Mono.justOrEmpty(sc); + return adapter == null ? result : Mono.just(adapter.fromPublisher(result)); + }); } private Object resolveSecurityContext(MethodParameter parameter, Object securityContext) { - CurrentSecurityContext contextAnno = findMethodAnnotation( - CurrentSecurityContext.class, parameter); + CurrentSecurityContext contextAnno = findMethodAnnotation(CurrentSecurityContext.class, parameter); String expressionToParse = contextAnno.expression(); if (StringUtils.hasLength(expressionToParse)) { @@ -152,9 +146,7 @@ public class CurrentSecurityContextArgumentResolver if (isInvalidType(parameter, securityContext)) { if (contextAnno.errorOnInvalidType()) { - throw new ClassCastException( - securityContext + " is not assignable to " + parameter - .getParameterType()); + throw new ClassCastException(securityContext + " is not assignable to " + parameter.getParameterType()); } else { return null; @@ -169,8 +161,7 @@ public class CurrentSecurityContextArgumentResolver return false; } Class typeToCheck = parameter.getParameterType(); - boolean isParameterPublisher = Publisher.class - .isAssignableFrom(parameter.getParameterType()); + boolean isParameterPublisher = Publisher.class.isAssignableFrom(parameter.getParameterType()); if (isParameterPublisher) { ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter); Class genericType = resolvableType.resolveGeneric(0); @@ -184,26 +175,24 @@ public class CurrentSecurityContextArgumentResolver /** * Obtains the specified {@link Annotation} on the specified {@link MethodParameter}. - * * @param annotationClass the class of the {@link Annotation} to find on the - * {@link MethodParameter} - * @param parameter the {@link MethodParameter} to search for an {@link Annotation} + * {@link MethodParameter} + * @param parameter the {@link MethodParameter} to search for an {@link Annotation} * @return the {@link Annotation} that was found or null. */ - private T findMethodAnnotation(Class annotationClass, - MethodParameter parameter) { + private T findMethodAnnotation(Class annotationClass, MethodParameter parameter) { T annotation = parameter.getParameterAnnotation(annotationClass); if (annotation != null) { return annotation; } Annotation[] annotationsToSearch = parameter.getParameterAnnotations(); for (Annotation toSearch : annotationsToSearch) { - annotation = AnnotationUtils - .findAnnotation(toSearch.annotationType(), annotationClass); + annotation = AnnotationUtils.findAnnotation(toSearch.annotationType(), annotationClass); if (annotation != null) { return annotation; } } return null; } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/util/matcher/AbstractMessageMatcherComposite.java b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/AbstractMessageMatcherComposite.java index 7f13a639ba..9f03c4abc1 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/util/matcher/AbstractMessageMatcherComposite.java +++ b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/AbstractMessageMatcherComposite.java @@ -29,20 +29,19 @@ import org.apache.commons.logging.Log; * @since 4.0 */ abstract class AbstractMessageMatcherComposite implements MessageMatcher { + protected final Log LOGGER = getLog(getClass()); private final List> messageMatchers; /** * Creates a new instance - * * @param messageMatchers the {@link MessageMatcher} instances to try */ AbstractMessageMatcherComposite(List> messageMatchers) { notEmpty(messageMatchers, "messageMatchers must contain a value"); if (messageMatchers.contains(null)) { - throw new IllegalArgumentException( - "messageMatchers cannot contain null values"); + throw new IllegalArgumentException("messageMatchers cannot contain null values"); } this.messageMatchers = messageMatchers; @@ -50,7 +49,6 @@ abstract class AbstractMessageMatcherComposite implements MessageMatcher { /** * Creates a new instance - * * @param messageMatchers the {@link MessageMatcher} instances to try */ @SafeVarargs @@ -66,4 +64,5 @@ abstract class AbstractMessageMatcherComposite implements MessageMatcher { public String toString() { return getClass().getSimpleName() + "[messageMatchers=" + messageMatchers + "]"; } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/util/matcher/AndMessageMatcher.java b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/AndMessageMatcher.java index 03cbc3c98c..9210f59347 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/util/matcher/AndMessageMatcher.java +++ b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/AndMessageMatcher.java @@ -26,9 +26,9 @@ import org.springframework.messaging.Message; * @since 4.0 */ public final class AndMessageMatcher extends AbstractMessageMatcherComposite { + /** * Creates a new instance - * * @param messageMatchers the {@link MessageMatcher} instances to try */ public AndMessageMatcher(List> messageMatchers) { @@ -37,7 +37,6 @@ public final class AndMessageMatcher extends AbstractMessageMatcherComposite< /** * Creates a new instance - * * @param messageMatchers the {@link MessageMatcher} instances to try */ @SafeVarargs @@ -59,4 +58,5 @@ public final class AndMessageMatcher extends AbstractMessageMatcherComposite< LOGGER.debug("All messageMatchers returned true"); return true; } + } \ No newline at end of file diff --git a/messaging/src/main/java/org/springframework/security/messaging/util/matcher/MessageMatcher.java b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/MessageMatcher.java index 41e2a36229..cab226bb9f 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/util/matcher/MessageMatcher.java +++ b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/MessageMatcher.java @@ -46,4 +46,5 @@ public interface MessageMatcher { return "ANY_MESSAGE"; } }; + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/util/matcher/OrMessageMatcher.java b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/OrMessageMatcher.java index b60a8d3d4d..90db0be394 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/util/matcher/OrMessageMatcher.java +++ b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/OrMessageMatcher.java @@ -26,9 +26,9 @@ import org.springframework.messaging.Message; * @since 4.0 */ public final class OrMessageMatcher extends AbstractMessageMatcherComposite { + /** * Creates a new instance - * * @param messageMatchers the {@link MessageMatcher} instances to try */ public OrMessageMatcher(List> messageMatchers) { @@ -37,7 +37,6 @@ public final class OrMessageMatcher extends AbstractMessageMatcherComposite extends AbstractMessageMatcherComposite { + public static final MessageMatcher NULL_DESTINATION_MATCHER = message -> { - String destination = SimpMessageHeaderAccessor.getDestination(message - .getHeaders()); + String destination = SimpMessageHeaderAccessor.getDestination(message.getHeaders()); return destination == null; }; @@ -49,6 +49,7 @@ public final class SimpDestinationMessageMatcher implements MessageMatcher messageTypeMatcher; + private final String pattern; /** @@ -77,7 +78,6 @@ public final class SimpDestinationMessageMatcher implements MessageMatcher{@code com/**/test} - matches all destinations ending with {@code test} * underneath the {@code com} path * - * * @param pattern the pattern to use */ public SimpDestinationMessageMatcher(String pattern) { @@ -87,7 +87,6 @@ public final class SimpDestinationMessageMatcher implements MessageMatcher * Creates a new instance with the specified pattern and {@link PathMatcher}. - * * @param pattern the pattern to use * @param pathMatcher the {@link PathMatcher} to use. */ @@ -99,24 +98,21 @@ public final class SimpDestinationMessageMatcher implements MessageMatcher * Creates a new instance with the specified pattern, {@link SimpMessageType}, and * {@link PathMatcher}. - * * @param pattern the pattern to use * @param type the {@link SimpMessageType} to match on or null if any * {@link SimpMessageType} should be matched. * @param pathMatcher the {@link PathMatcher} to use. */ - private SimpDestinationMessageMatcher(String pattern, SimpMessageType type, - PathMatcher pathMatcher) { + private SimpDestinationMessageMatcher(String pattern, SimpMessageType type, PathMatcher pathMatcher) { Assert.notNull(pattern, "pattern cannot be null"); Assert.notNull(pathMatcher, "pathMatcher cannot be null"); if (!isTypeWithDestination(type)) { - throw new IllegalArgumentException("SimpMessageType " + type - + " does not contain a destination and so cannot be matched on."); + throw new IllegalArgumentException( + "SimpMessageType " + type + " does not contain a destination and so cannot be matched on."); } this.matcher = pathMatcher; - this.messageTypeMatcher = type == null ? ANY_MESSAGE - : new SimpMessageTypeMatcher(type); + this.messageTypeMatcher = type == null ? ANY_MESSAGE : new SimpMessageTypeMatcher(type); this.pattern = pattern; } @@ -125,17 +121,13 @@ public final class SimpDestinationMessageMatcher implements MessageMatcher extractPathVariables(Message message){ - final String destination = SimpMessageHeaderAccessor.getDestination(message - .getHeaders()); - return destination != null ? matcher.extractUriTemplateVariables(pattern, destination) - : Collections.emptyMap(); + public Map extractPathVariables(Message message) { + final String destination = SimpMessageHeaderAccessor.getDestination(message.getHeaders()); + return destination != null ? matcher.extractUriTemplateVariables(pattern, destination) : Collections.emptyMap(); } public MessageMatcher getMessageTypeMatcher() { @@ -144,44 +136,37 @@ public final class SimpDestinationMessageMatcher implements MessageMatcher * Creates a new instance with the specified pattern, * {@code SimpMessageType.SUBSCRIBE}, and {@link PathMatcher}. - * * @param pattern the pattern to use * @param matcher the {@link PathMatcher} to use. */ - public static SimpDestinationMessageMatcher createSubscribeMatcher(String pattern, - PathMatcher matcher) { - return new SimpDestinationMessageMatcher(pattern, SimpMessageType.SUBSCRIBE, - matcher); + public static SimpDestinationMessageMatcher createSubscribeMatcher(String pattern, PathMatcher matcher) { + return new SimpDestinationMessageMatcher(pattern, SimpMessageType.SUBSCRIBE, matcher); } /** *

        * Creates a new instance with the specified pattern, {@code SimpMessageType.MESSAGE}, * and {@link PathMatcher}. - * * @param pattern the pattern to use * @param matcher the {@link PathMatcher} to use. */ - public static SimpDestinationMessageMatcher createMessageMatcher(String pattern, - PathMatcher matcher) { - return new SimpDestinationMessageMatcher(pattern, SimpMessageType.MESSAGE, - matcher); + public static SimpDestinationMessageMatcher createMessageMatcher(String pattern, PathMatcher matcher) { + return new SimpDestinationMessageMatcher(pattern, SimpMessageType.MESSAGE, matcher); } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/util/matcher/SimpMessageTypeMatcher.java b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/SimpMessageTypeMatcher.java index 24a66b8f3e..41af99f63b 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/util/matcher/SimpMessageTypeMatcher.java +++ b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/SimpMessageTypeMatcher.java @@ -31,11 +31,11 @@ import org.springframework.util.ObjectUtils; * */ public class SimpMessageTypeMatcher implements MessageMatcher { + private final SimpMessageType typeToMatch; /** * Creates a new instance - * * @param typeToMatch the {@link SimpMessageType} that will result in a match. Cannot * be null. */ @@ -75,4 +75,5 @@ public class SimpMessageTypeMatcher implements MessageMatcher { public String toString() { return "SimpMessageTypeMatcher [typeToMatch=" + typeToMatch + "]"; } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/web/csrf/CsrfChannelInterceptor.java b/messaging/src/main/java/org/springframework/security/messaging/web/csrf/CsrfChannelInterceptor.java index c59858e1a3..0e1a4623b2 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/web/csrf/CsrfChannelInterceptor.java +++ b/messaging/src/main/java/org/springframework/security/messaging/web/csrf/CsrfChannelInterceptor.java @@ -37,8 +37,8 @@ import org.springframework.security.web.csrf.MissingCsrfTokenException; * @since 4.0 */ public final class CsrfChannelInterceptor extends ChannelInterceptorAdapter { - private final MessageMatcher matcher = new SimpMessageTypeMatcher( - SimpMessageType.CONNECT); + + private final MessageMatcher matcher = new SimpMessageTypeMatcher(SimpMessageType.CONNECT); @Override public Message preSend(Message message, MessageChannel channel) { @@ -46,8 +46,7 @@ public final class CsrfChannelInterceptor extends ChannelInterceptorAdapter { return message; } - Map sessionAttributes = SimpMessageHeaderAccessor - .getSessionAttributes(message.getHeaders()); + Map sessionAttributes = SimpMessageHeaderAccessor.getSessionAttributes(message.getHeaders()); CsrfToken expectedToken = sessionAttributes == null ? null : (CsrfToken) sessionAttributes.get(CsrfToken.class.getName()); @@ -64,4 +63,5 @@ public final class CsrfChannelInterceptor extends ChannelInterceptorAdapter { } throw new InvalidCsrfTokenException(expectedToken, actualTokenValue); } + } diff --git a/messaging/src/main/java/org/springframework/security/messaging/web/socket/server/CsrfTokenHandshakeInterceptor.java b/messaging/src/main/java/org/springframework/security/messaging/web/socket/server/CsrfTokenHandshakeInterceptor.java index 591b87dbb6..0918f6f2bb 100644 --- a/messaging/src/main/java/org/springframework/security/messaging/web/socket/server/CsrfTokenHandshakeInterceptor.java +++ b/messaging/src/main/java/org/springframework/security/messaging/web/socket/server/CsrfTokenHandshakeInterceptor.java @@ -36,11 +36,9 @@ import org.springframework.web.socket.server.HandshakeInterceptor; */ public final class CsrfTokenHandshakeInterceptor implements HandshakeInterceptor { - public boolean beforeHandshake(ServerHttpRequest request, - ServerHttpResponse response, WebSocketHandler wsHandler, + public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) { - HttpServletRequest httpRequest = ((ServletServerHttpRequest) request) - .getServletRequest(); + HttpServletRequest httpRequest = ((ServletServerHttpRequest) request).getServletRequest(); CsrfToken token = (CsrfToken) httpRequest.getAttribute(CsrfToken.class.getName()); if (token == null) { return true; @@ -49,7 +47,8 @@ public final class CsrfTokenHandshakeInterceptor implements HandshakeInterceptor return true; } - public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, - WebSocketHandler wsHandler, Exception exception) { + public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, + Exception exception) { } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/access/expression/DefaultMessageSecurityExpressionHandlerTests.java b/messaging/src/test/java/org/springframework/security/messaging/access/expression/DefaultMessageSecurityExpressionHandlerTests.java index d5dcdfc2c7..03f8b45913 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/access/expression/DefaultMessageSecurityExpressionHandlerTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/access/expression/DefaultMessageSecurityExpressionHandlerTests.java @@ -38,8 +38,10 @@ import org.springframework.security.core.authority.AuthorityUtils; @RunWith(MockitoJUnitRunner.class) public class DefaultMessageSecurityExpressionHandlerTests { + @Mock AuthenticationTrustResolver trustResolver; + @Mock PermissionEvaluator permissionEvaluator; @@ -61,10 +63,8 @@ public class DefaultMessageSecurityExpressionHandlerTests { // SEC-2705 @Test public void trustResolverPopulated() { - EvaluationContext context = handler.createEvaluationContext(authentication, - message); - Expression expression = handler.getExpressionParser().parseExpression( - "authenticated"); + EvaluationContext context = handler.createEvaluationContext(authentication, message); + Expression expression = handler.getExpressionParser().parseExpression("authenticated"); assertThat(ExpressionUtils.evaluateAsBoolean(expression, context)).isFalse(); } @@ -77,10 +77,8 @@ public class DefaultMessageSecurityExpressionHandlerTests { @Test public void trustResolverCustom() { handler.setTrustResolver(trustResolver); - EvaluationContext context = handler.createEvaluationContext(authentication, - message); - Expression expression = handler.getExpressionParser().parseExpression( - "authenticated"); + EvaluationContext context = handler.createEvaluationContext(authentication, message); + Expression expression = handler.getExpressionParser().parseExpression("authenticated"); when(trustResolver.isAnonymous(authentication)).thenReturn(false); assertThat(ExpressionUtils.evaluateAsBoolean(expression, context)).isTrue(); @@ -92,10 +90,8 @@ public class DefaultMessageSecurityExpressionHandlerTests { RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER"); handler.setRoleHierarchy(roleHierarchy); - EvaluationContext context = handler.createEvaluationContext(authentication, - message); - Expression expression = handler.getExpressionParser().parseExpression( - "hasRole('ROLE_USER')"); + EvaluationContext context = handler.createEvaluationContext(authentication, message); + Expression expression = handler.getExpressionParser().parseExpression("hasRole('ROLE_USER')"); assertThat(ExpressionUtils.evaluateAsBoolean(expression, context)).isTrue(); } @@ -103,13 +99,11 @@ public class DefaultMessageSecurityExpressionHandlerTests { @Test public void permissionEvaluator() { handler.setPermissionEvaluator(permissionEvaluator); - EvaluationContext context = handler.createEvaluationContext(authentication, - message); - Expression expression = handler.getExpressionParser().parseExpression( - "hasPermission(message, 'read')"); - when(permissionEvaluator.hasPermission(authentication, message, "read")) - .thenReturn(true); + EvaluationContext context = handler.createEvaluationContext(authentication, message); + Expression expression = handler.getExpressionParser().parseExpression("hasPermission(message, 'read')"); + when(permissionEvaluator.hasPermission(authentication, message, "read")).thenReturn(true); assertThat(ExpressionUtils.evaluateAsBoolean(expression, context)).isTrue(); } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactoryTests.java b/messaging/src/test/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactoryTests.java index 3d5f813866..61f9d05a4d 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactoryTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/access/expression/ExpressionBasedMessageSecurityMetadataSourceFactoryTests.java @@ -35,12 +35,16 @@ import java.util.LinkedHashMap; @RunWith(MockitoJUnitRunner.class) public class ExpressionBasedMessageSecurityMetadataSourceFactoryTests { + @Mock MessageMatcher matcher1; + @Mock MessageMatcher matcher2; + @Mock Message message; + @Mock Authentication authentication; @@ -83,9 +87,8 @@ public class ExpressionBasedMessageSecurityMetadataSourceFactoryTests { assertThat(attrs).hasSize(1); ConfigAttribute attr = attrs.iterator().next(); assertThat(attr).isInstanceOf(MessageExpressionConfigAttribute.class); - assertThat( - ((MessageExpressionConfigAttribute) attr).getAuthorizeExpression() - .getValue(rootObject)).isEqualTo(true); + assertThat(((MessageExpressionConfigAttribute) attr).getAuthorizeExpression().getValue(rootObject)) + .isEqualTo(true); } @Test @@ -97,8 +100,8 @@ public class ExpressionBasedMessageSecurityMetadataSourceFactoryTests { assertThat(attrs).hasSize(1); ConfigAttribute attr = attrs.iterator().next(); assertThat(attr).isInstanceOf(MessageExpressionConfigAttribute.class); - assertThat( - ((MessageExpressionConfigAttribute) attr).getAuthorizeExpression() - .getValue(rootObject)).isEqualTo(false); + assertThat(((MessageExpressionConfigAttribute) attr).getAuthorizeExpression().getValue(rootObject)) + .isEqualTo(false); } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttributeTests.java b/messaging/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttributeTests.java index 95d9a9f901..799aaf3df0 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttributeTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionConfigAttributeTests.java @@ -33,6 +33,7 @@ import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) public class MessageExpressionConfigAttributeTests { + @Mock Expression expression; @@ -76,7 +77,8 @@ public class MessageExpressionConfigAttributeTests { @Test public void postProcessContext() { SimpDestinationMessageMatcher matcher = new SimpDestinationMessageMatcher("/topics/{topic}/**"); - Message message = MessageBuilder.withPayload("M").setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "/topics/someTopic/sub1").build(); + Message message = MessageBuilder.withPayload("M") + .setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "/topics/someTopic/sub1").build(); EvaluationContext context = mock(EvaluationContext.class); attribute = new MessageExpressionConfigAttribute(expression, matcher); @@ -84,4 +86,5 @@ public class MessageExpressionConfigAttributeTests { verify(context).setVariable("topic", "someTopic"); } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionVoterTests.java b/messaging/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionVoterTests.java index 93104c608a..b2daa2c874 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionVoterTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/access/expression/MessageExpressionVoterTests.java @@ -38,17 +38,24 @@ import static org.springframework.security.access.AccessDecisionVoter.*; @RunWith(MockitoJUnitRunner.class) public class MessageExpressionVoterTests { + @Mock Authentication authentication; + @Mock Message message; + Collection attributes; + @Mock Expression expression; + @Mock MessageMatcher matcher; + @Mock SecurityExpressionHandler expressionHandler; + @Mock EvaluationContext evaluationContext; @@ -56,33 +63,27 @@ public class MessageExpressionVoterTests { @Before public void setup() { - attributes = Arrays - . asList(new MessageExpressionConfigAttribute(expression, matcher)); + attributes = Arrays.asList(new MessageExpressionConfigAttribute(expression, matcher)); voter = new MessageExpressionVoter(); } @Test public void voteGranted() { - when(expression.getValue(any(EvaluationContext.class), eq(Boolean.class))) - .thenReturn(true); - assertThat(voter.vote(authentication, message, attributes)).isEqualTo( - ACCESS_GRANTED); + when(expression.getValue(any(EvaluationContext.class), eq(Boolean.class))).thenReturn(true); + assertThat(voter.vote(authentication, message, attributes)).isEqualTo(ACCESS_GRANTED); } @Test public void voteDenied() { - when(expression.getValue(any(EvaluationContext.class), eq(Boolean.class))) - .thenReturn(false); - assertThat(voter.vote(authentication, message, attributes)).isEqualTo( - ACCESS_DENIED); + when(expression.getValue(any(EvaluationContext.class), eq(Boolean.class))).thenReturn(false); + assertThat(voter.vote(authentication, message, attributes)).isEqualTo(ACCESS_DENIED); } @Test public void voteAbstain() { - attributes = Arrays. asList(new SecurityConfig("ROLE_USER")); - assertThat(voter.vote(authentication, message, attributes)).isEqualTo( - ACCESS_ABSTAIN); + attributes = Arrays.asList(new SecurityConfig("ROLE_USER")); + assertThat(voter.vote(authentication, message, attributes)).isEqualTo(ACCESS_ABSTAIN); } @Test @@ -102,8 +103,7 @@ public class MessageExpressionVoterTests { @Test public void supportsMessageExpressionConfigAttributeTrue() { - assertThat(voter.supports(new MessageExpressionConfigAttribute(expression, matcher))) - .isTrue(); + assertThat(voter.supports(new MessageExpressionConfigAttribute(expression, matcher))).isTrue(); } @Test(expected = IllegalArgumentException.class) @@ -114,29 +114,26 @@ public class MessageExpressionVoterTests { @Test public void customExpressionHandler() { voter.setExpressionHandler(expressionHandler); - when(expressionHandler.createEvaluationContext(authentication, message)) - .thenReturn(evaluationContext); + when(expressionHandler.createEvaluationContext(authentication, message)).thenReturn(evaluationContext); when(expression.getValue(evaluationContext, Boolean.class)).thenReturn(true); - assertThat(voter.vote(authentication, message, attributes)).isEqualTo( - ACCESS_GRANTED); + assertThat(voter.vote(authentication, message, attributes)).isEqualTo(ACCESS_GRANTED); verify(expressionHandler).createEvaluationContext(authentication, message); } @Test - public void postProcessEvaluationContext(){ + public void postProcessEvaluationContext() { final MessageExpressionConfigAttribute configAttribute = mock(MessageExpressionConfigAttribute.class); voter.setExpressionHandler(expressionHandler); when(expressionHandler.createEvaluationContext(authentication, message)).thenReturn(evaluationContext); when(configAttribute.getAuthorizeExpression()).thenReturn(expression); - attributes = Arrays. asList(configAttribute); + attributes = Arrays.asList(configAttribute); when(configAttribute.postProcess(evaluationContext, message)).thenReturn(evaluationContext); - when(expression.getValue(any(EvaluationContext.class), eq(Boolean.class))) - .thenReturn(true); + when(expression.getValue(any(EvaluationContext.class), eq(Boolean.class))).thenReturn(true); - assertThat(voter.vote(authentication, message, attributes)).isEqualTo( - ACCESS_GRANTED); + assertThat(voter.vote(authentication, message, attributes)).isEqualTo(ACCESS_GRANTED); verify(configAttribute).postProcess(evaluationContext, message); } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptorTests.java b/messaging/src/test/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptorTests.java index 991186ea48..d961ecc141 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptorTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/access/intercept/ChannelSecurityInterceptorTests.java @@ -44,16 +44,22 @@ import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class ChannelSecurityInterceptorTests { + @Mock Message message; + @Mock MessageChannel channel; + @Mock MessageSecurityMetadataSource source; + @Mock AccessDecisionManager accessDecisionManager; + @Mock RunAsManager runAsManager; + @Mock Authentication runAs; @@ -65,7 +71,7 @@ public class ChannelSecurityInterceptorTests { @Before public void setup() { - attrs = Arrays. asList(new SecurityConfig("ROLE_USER")); + attrs = Arrays.asList(new SecurityConfig("ROLE_USER")); interceptor = new ChannelSecurityInterceptor(source); interceptor.setAccessDecisionManager(accessDecisionManager); interceptor.setRunAsManager(runAsManager); @@ -111,8 +117,8 @@ public class ChannelSecurityInterceptorTests { @Test(expected = AccessDeniedException.class) public void preSendDeny() { when(source.getAttributes(message)).thenReturn(attrs); - doThrow(new AccessDeniedException("")).when(accessDecisionManager).decide( - any(Authentication.class), eq(message), eq(attrs)); + doThrow(new AccessDeniedException("")).when(accessDecisionManager).decide(any(Authentication.class), + eq(message), eq(attrs)); interceptor.preSend(message, channel); } @@ -121,19 +127,15 @@ public class ChannelSecurityInterceptorTests { @Test public void preSendPostSendRunAs() { when(source.getAttributes(message)).thenReturn(attrs); - when( - runAsManager.buildRunAs(any(Authentication.class), any(), - any(Collection.class))).thenReturn(runAs); + when(runAsManager.buildRunAs(any(Authentication.class), any(), any(Collection.class))).thenReturn(runAs); Message preSend = interceptor.preSend(message, channel); - assertThat(SecurityContextHolder.getContext().getAuthentication()) - .isSameAs(runAs); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(runAs); interceptor.postSend(preSend, channel, true); - assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs( - originalAuth); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(originalAuth); } @Test @@ -145,19 +147,15 @@ public class ChannelSecurityInterceptorTests { @Test public void preSendFinallySendRunAs() { when(source.getAttributes(message)).thenReturn(attrs); - when( - runAsManager.buildRunAs(any(Authentication.class), any(), - any(Collection.class))).thenReturn(runAs); + when(runAsManager.buildRunAs(any(Authentication.class), any(), any(Collection.class))).thenReturn(runAs); Message preSend = interceptor.preSend(message, channel); - assertThat(SecurityContextHolder.getContext().getAuthentication()) - .isSameAs(runAs); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(runAs); interceptor.afterSendCompletion(preSend, channel, true, new RuntimeException()); - assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs( - originalAuth); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(originalAuth); } @Test @@ -174,4 +172,5 @@ public class ChannelSecurityInterceptorTests { public void afterReceiveCompletionNullExceptionNoExceptionThrown() { interceptor.afterReceiveCompletion(message, channel, null); } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSourceTests.java b/messaging/src/test/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSourceTests.java index 6702abe267..a38dadc8f6 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSourceTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/access/intercept/DefaultMessageSecurityMetadataSourceTests.java @@ -35,12 +35,16 @@ import static org.powermock.api.mockito.PowerMockito.when; @RunWith(MockitoJUnitRunner.class) public class DefaultMessageSecurityMetadataSourceTests { + @Mock MessageMatcher matcher1; + @Mock MessageMatcher matcher2; + @Mock Message message; + @Mock Authentication authentication; @@ -55,8 +59,8 @@ public class DefaultMessageSecurityMetadataSourceTests { @Before public void setup() { messageMap = new LinkedHashMap<>(); - messageMap.put(matcher1, Arrays. asList(config1)); - messageMap.put(matcher2, Arrays. asList(config2)); + messageMap.put(matcher1, Arrays.asList(config1)); + messageMap.put(matcher2, Arrays.asList(config2)); source = new DefaultMessageSecurityMetadataSource(messageMap); } @@ -94,4 +98,5 @@ public class DefaultMessageSecurityMetadataSourceTests { public void supportsTrue() { assertThat(source.supports(Message.class)).isTrue(); } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/context/AuthenticationPrincipalArgumentResolverTests.java b/messaging/src/test/java/org/springframework/security/messaging/context/AuthenticationPrincipalArgumentResolverTests.java index 55e31111b1..36628ad6d3 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/context/AuthenticationPrincipalArgumentResolverTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/context/AuthenticationPrincipalArgumentResolverTests.java @@ -40,7 +40,9 @@ import org.springframework.util.ReflectionUtils; * */ public class AuthenticationPrincipalArgumentResolverTests { + private Object expectedPrincipal; + private AuthenticationPrincipalArgumentResolver resolver; @Before @@ -82,38 +84,32 @@ public class AuthenticationPrincipalArgumentResolverTests { @Test public void resolveArgumentString() throws Exception { setAuthenticationPrincipal("john"); - assertThat(resolver.resolveArgument(showUserAnnotationString(), null)).isEqualTo( - expectedPrincipal); + assertThat(resolver.resolveArgument(showUserAnnotationString(), null)).isEqualTo(expectedPrincipal); } @Test public void resolveArgumentPrincipalStringOnObject() throws Exception { setAuthenticationPrincipal("john"); - assertThat(resolver.resolveArgument(showUserAnnotationObject(), null)).isEqualTo( - expectedPrincipal); + assertThat(resolver.resolveArgument(showUserAnnotationObject(), null)).isEqualTo(expectedPrincipal); } @Test public void resolveArgumentUserDetails() throws Exception { - setAuthenticationPrincipal(new User("user", "password", - AuthorityUtils.createAuthorityList("ROLE_USER"))); - assertThat(resolver.resolveArgument(showUserAnnotationUserDetails(), null)) - .isEqualTo(expectedPrincipal); + setAuthenticationPrincipal(new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))); + assertThat(resolver.resolveArgument(showUserAnnotationUserDetails(), null)).isEqualTo(expectedPrincipal); } @Test public void resolveArgumentCustomUserPrincipal() throws Exception { setAuthenticationPrincipal(new CustomUserPrincipal()); - assertThat( - resolver.resolveArgument(showUserAnnotationCustomUserPrincipal(), null)) + assertThat(resolver.resolveArgument(showUserAnnotationCustomUserPrincipal(), null)) .isEqualTo(expectedPrincipal); } @Test public void resolveArgumentCustomAnnotation() throws Exception { setAuthenticationPrincipal(new CustomUserPrincipal()); - assertThat(resolver.resolveArgument(showUserCustomAnnotation(), null)).isEqualTo( - expectedPrincipal); + assertThat(resolver.resolveArgument(showUserCustomAnnotation(), null)).isEqualTo(expectedPrincipal); } @Test @@ -121,8 +117,7 @@ public class AuthenticationPrincipalArgumentResolverTests { CustomUserPrincipal principal = new CustomUserPrincipal(); setAuthenticationPrincipal(principal); this.expectedPrincipal = principal.property; - assertThat(this.resolver.resolveArgument(showUserSpel(), null)) - .isEqualTo(this.expectedPrincipal); + assertThat(this.resolver.resolveArgument(showUserSpel(), null)).isEqualTo(this.expectedPrincipal); } @Test @@ -155,8 +150,7 @@ public class AuthenticationPrincipalArgumentResolverTests { @Test public void resolveArgumentObject() throws Exception { setAuthenticationPrincipal(new Object()); - assertThat(resolver.resolveArgument(showUserAnnotationObject(), null)).isEqualTo( - expectedPrincipal); + assertThat(resolver.resolveArgument(showUserAnnotationObject(), null)).isEqualTo(expectedPrincipal); } private MethodParameter showUserNoAnnotation() { @@ -172,8 +166,7 @@ public class AuthenticationPrincipalArgumentResolverTests { } private MethodParameter showUserAnnotationCurrentUserErrorOnInvalidType() { - return getMethodParameter("showUserAnnotationCurrentUserErrorOnInvalidType", - String.class); + return getMethodParameter("showUserAnnotationCurrentUserErrorOnInvalidType", String.class); } private MethodParameter showUserAnnotationUserDetails() { @@ -201,8 +194,7 @@ public class AuthenticationPrincipalArgumentResolverTests { } private MethodParameter getMethodParameter(String methodName, Class... paramTypes) { - Method method = ReflectionUtils.findMethod(TestController.class, methodName, - paramTypes); + Method method = ReflectionUtils.findMethod(TestController.class, methodName, paramTypes); return new MethodParameter(method, 0); } @@ -210,15 +202,18 @@ public class AuthenticationPrincipalArgumentResolverTests { @Retention(RetentionPolicy.RUNTIME) @AuthenticationPrincipal static @interface CurrentUser { + } @Target({ ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @AuthenticationPrincipal(errorOnInvalidType = true) static @interface CurrentUserErrorOnInvalidType { + } public static class TestController { + public void showUserNoAnnotation(String user) { } @@ -229,8 +224,7 @@ public class AuthenticationPrincipalArgumentResolverTests { @AuthenticationPrincipal(errorOnInvalidType = true) String user) { } - public void showUserAnnotationCurrentUserErrorOnInvalidType( - @CurrentUserErrorOnInvalidType String user) { + public void showUserAnnotationCurrentUserErrorOnInvalidType(@CurrentUserErrorOnInvalidType String user) { } public void showUserAnnotation(@AuthenticationPrincipal UserDetails user) { @@ -245,20 +239,23 @@ public class AuthenticationPrincipalArgumentResolverTests { public void showUserAnnotation(@AuthenticationPrincipal Object user) { } - public void showUserSpel( - @AuthenticationPrincipal(expression = "property") String user) { + public void showUserSpel(@AuthenticationPrincipal(expression = "property") String user) { } - public void showUserSpelCopy( - @AuthenticationPrincipal(expression = "new org.springframework.security.messaging.context.AuthenticationPrincipalArgumentResolverTests$CopyUserPrincipal(#this)") CopyUserPrincipal user) { + public void showUserSpelCopy(@AuthenticationPrincipal( + expression = "new org.springframework.security.messaging.context.AuthenticationPrincipalArgumentResolverTests$CopyUserPrincipal(#this)") CopyUserPrincipal user) { } + } static class CustomUserPrincipal { + public final String property = "property"; + } public static class CopyUserPrincipal { + public final String property; public CopyUserPrincipal(String property) { @@ -273,8 +270,7 @@ public class AuthenticationPrincipalArgumentResolverTests { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result - + ((this.property == null) ? 0 : this.property.hashCode()); + result = prime * result + ((this.property == null) ? 0 : this.property.hashCode()); return result; } @@ -300,13 +296,13 @@ public class AuthenticationPrincipalArgumentResolverTests { } return true; } + } private void setAuthenticationPrincipal(Object principal) { this.expectedPrincipal = principal; SecurityContextHolder.getContext() - .setAuthentication( - new TestingAuthenticationToken(expectedPrincipal, "password", - "ROLE_USER")); + .setAuthentication(new TestingAuthenticationToken(expectedPrincipal, "password", "ROLE_USER")); } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/context/SecurityContextChannelInterceptorTests.java b/messaging/src/test/java/org/springframework/security/messaging/context/SecurityContextChannelInterceptorTests.java index 56e784bc6a..8352806911 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/context/SecurityContextChannelInterceptorTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/context/SecurityContextChannelInterceptorTests.java @@ -39,10 +39,13 @@ import static org.springframework.security.core.context.SecurityContextHolder.*; @RunWith(MockitoJUnitRunner.class) public class SecurityContextChannelInterceptorTests { + @Mock MessageChannel channel; + @Mock MessageHandler handler; + @Mock Principal principal; @@ -82,8 +85,7 @@ public class SecurityContextChannelInterceptorTests { interceptor.preSend(messageBuilder.build(), channel); - assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs( - authentication); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(authentication); } @Test @@ -92,8 +94,7 @@ public class SecurityContextChannelInterceptorTests { interceptor.preSend(messageBuilder.build(), channel); - assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs( - authentication); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(authentication); } @Test(expected = IllegalArgumentException.class) @@ -103,8 +104,8 @@ public class SecurityContextChannelInterceptorTests { @Test public void preSendUsesCustomAnonymous() { - expectedAnonymous = new AnonymousAuthenticationToken("customKey", - "customAnonymous", AuthorityUtils.createAuthorityList("ROLE_CUSTOM")); + expectedAnonymous = new AnonymousAuthenticationToken("customKey", "customAnonymous", + AuthorityUtils.createAuthorityList("ROLE_CUSTOM")); interceptor.setAnonymousAuthentication(expectedAnonymous); interceptor.preSend(messageBuilder.build(), channel); @@ -160,8 +161,7 @@ public class SecurityContextChannelInterceptorTests { interceptor.beforeHandle(messageBuilder.build(), channel, handler); - assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs( - authentication); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(authentication); } // SEC-2845 @@ -201,20 +201,17 @@ public class SecurityContextChannelInterceptorTests { // SEC-2829 @Test public void restoresOriginalContext() { - TestingAuthenticationToken original = new TestingAuthenticationToken("original", - "original", "ROLE_USER"); + TestingAuthenticationToken original = new TestingAuthenticationToken("original", "original", "ROLE_USER"); SecurityContextHolder.getContext().setAuthentication(original); messageBuilder.setHeader(SimpMessageHeaderAccessor.USER_HEADER, authentication); interceptor.beforeHandle(messageBuilder.build(), channel, handler); - assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs( - authentication); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(authentication); interceptor.afterMessageHandled(messageBuilder.build(), channel, handler, null); - assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs( - original); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(original); } /** @@ -223,48 +220,41 @@ public class SecurityContextChannelInterceptorTests { */ @Test public void restoresOriginalContextNestedThreeDeep() { - AnonymousAuthenticationToken anonymous = new AnonymousAuthenticationToken("key", - "anonymous", AuthorityUtils.createAuthorityList("ROLE_USER")); + AnonymousAuthenticationToken anonymous = new AnonymousAuthenticationToken("key", "anonymous", + AuthorityUtils.createAuthorityList("ROLE_USER")); - TestingAuthenticationToken origional = new TestingAuthenticationToken("original", - "origional", "ROLE_USER"); + TestingAuthenticationToken origional = new TestingAuthenticationToken("original", "origional", "ROLE_USER"); SecurityContextHolder.getContext().setAuthentication(origional); messageBuilder.setHeader(SimpMessageHeaderAccessor.USER_HEADER, authentication); interceptor.beforeHandle(messageBuilder.build(), channel, handler); - assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs( - authentication); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(authentication); // start send websocket messageBuilder.setHeader(SimpMessageHeaderAccessor.USER_HEADER, null); interceptor.beforeHandle(messageBuilder.build(), channel, handler); - assertThat(SecurityContextHolder.getContext().getAuthentication().getName()) - .isEqualTo(anonymous.getName()); + assertThat(SecurityContextHolder.getContext().getAuthentication().getName()).isEqualTo(anonymous.getName()); interceptor.afterMessageHandled(messageBuilder.build(), channel, handler, null); - assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs( - authentication); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(authentication); // end send websocket interceptor.afterMessageHandled(messageBuilder.build(), channel, handler, null); - assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs( - origional); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(origional); } private void assertAnonymous() { - Authentication currentAuthentication = SecurityContextHolder.getContext() - .getAuthentication(); - assertThat(currentAuthentication) - .isInstanceOf(AnonymousAuthenticationToken.class); + Authentication currentAuthentication = SecurityContextHolder.getContext().getAuthentication(); + assertThat(currentAuthentication).isInstanceOf(AnonymousAuthenticationToken.class); AnonymousAuthenticationToken anonymous = (AnonymousAuthenticationToken) currentAuthentication; assertThat(anonymous.getName()).isEqualTo(expectedAnonymous.getName()); - assertThat(anonymous.getAuthorities()).containsOnlyElementsOf( - expectedAnonymous.getAuthorities()); + assertThat(anonymous.getAuthorities()).containsOnlyElementsOf(expectedAnonymous.getAuthorities()); assertThat(anonymous.getKeyHash()).isEqualTo(expectedAnonymous.getKeyHash()); } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/ResolvableMethod.java b/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/ResolvableMethod.java index 7651e2eb2b..9f969752e4 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/ResolvableMethod.java +++ b/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/ResolvableMethod.java @@ -57,27 +57,29 @@ import org.springframework.util.ReflectionUtils; import static java.util.stream.Collectors.joining; /** - * NOTE: This class is a replica of the same class in spring-web so it can - * be used for tests in spring-messaging. + * NOTE: This class is a replica of the same class in spring-web so it can be used for + * tests in spring-messaging. * - *

        Convenience class to resolve method parameters from hints. + *

        + * Convenience class to resolve method parameters from hints. * *

        Background

        * - *

        When testing annotated methods we create test classes such as - * "TestController" with a diverse range of method signatures representing - * supported annotations and argument types. It becomes challenging to use - * naming strategies to keep track of methods and arguments especially in - * combination with variables for reflection metadata. + *

        + * When testing annotated methods we create test classes such as "TestController" with a + * diverse range of method signatures representing supported annotations and argument + * types. It becomes challenging to use naming strategies to keep track of methods and + * arguments especially in combination with variables for reflection metadata. * - *

        The idea with {@link ResolvableMethod} is NOT to rely on naming techniques - * but to use hints to zero in on method parameters. Such hints can be strongly - * typed and explicit about what is being tested. + *

        + * The idea with {@link ResolvableMethod} is NOT to rely on naming techniques but to use + * hints to zero in on method parameters. Such hints can be strongly typed and explicit + * about what is being tested. * *

        1. Declared Return Type

        * - * When testing return types it's likely to have many methods with a unique - * return type, possibly with or without an annotation. + * When testing return types it's likely to have many methods with a unique return type, + * possibly with or without an annotation. * *
          * import static org.springframework.web.method.ResolvableMethod.on;
        @@ -100,8 +102,8 @@ import static java.util.stream.Collectors.joining;
          *
          * 

        2. Method Arguments

        * - * When testing method arguments it's more likely to have one or a small number - * of methods with a wide array of argument types and parameter annotations. + * When testing method arguments it's more likely to have one or a small number of methods + * with a wide array of argument types and parameter annotations. * *
          * import static org.springframework.web.method.MvcAnnotationPredicates.requestParam;
        @@ -136,16 +138,13 @@ public class ResolvableMethod {
         	// Matches ValueConstants.DEFAULT_NONE (spring-web and spring-messaging)
         	private static final String DEFAULT_VALUE_NONE = "\n\t\t\n\t\t\n\uE000\uE001\uE002\n\t\t\t\t\n";
         
        -
         	private final Method method;
         
        -
         	private ResolvableMethod(Method method) {
         		Assert.notNull(method, "'method' is required");
         		this.method = method;
         	}
         
        -
         	/**
         	 * Return the resolved method.
         	 */
        @@ -188,8 +187,8 @@ public class ResolvableMethod {
         	}
         
         	/**
        -	 * Filter on method arguments with annotation.
        -	 * See {@link org.springframework.web.method.MvcAnnotationPredicates}.
        +	 * Filter on method arguments with annotation. See
        +	 * {@link org.springframework.web.method.MvcAnnotationPredicates}.
         	 */
         	@SafeVarargs
         	public final ArgResolver annot(Predicate... filter) {
        @@ -210,25 +209,21 @@ public class ResolvableMethod {
         		return new ArgResolver().annotNotPresent(annotationTypes);
         	}
         
        -
         	@Override
         	public String toString() {
         		return "ResolvableMethod=" + formatMethod();
         	}
         
        -
         	private String formatMethod() {
        -		return (method().getName() +
        -				Arrays.stream(this.method.getParameters())
        -						.map(this::formatParameter)
        -						.collect(joining(",\n\t", "(\n\t", "\n)")));
        +		return (method().getName() + Arrays.stream(this.method.getParameters()).map(this::formatParameter)
        +				.collect(joining(",\n\t", "(\n\t", "\n)")));
         	}
         
         	private String formatParameter(Parameter param) {
         		Annotation[] anns = param.getAnnotations();
        -		return (anns.length > 0 ?
        -				Arrays.stream(anns).map(this::formatAnnotation).collect(joining(",", "[", "]")) + " " + param :
        -				param.toString());
        +		return (anns.length > 0
        +				? Arrays.stream(anns).map(this::formatAnnotation).collect(joining(",", "[", "]")) + " " + param
        +				: param.toString());
         	}
         
         	private String formatAnnotation(Annotation annotation) {
        @@ -242,8 +237,8 @@ public class ResolvableMethod {
         	}
         
         	private static ResolvableType toResolvableType(Class type, Class... generics) {
        -		return (ObjectUtils.isEmpty(generics) ? ResolvableType.forClass(type) :
        -				ResolvableType.forClassWithGenerics(type, generics));
        +		return (ObjectUtils.isEmpty(generics) ? ResolvableType.forClass(type)
        +				: ResolvableType.forClassWithGenerics(type, generics));
         	}
         
         	private static ResolvableType toResolvableType(Class type, ResolvableType generic, ResolvableType... generics) {
        @@ -253,7 +248,6 @@ public class ResolvableMethod {
         		return ResolvableType.forClassWithGenerics(type, genericTypes);
         	}
         
        -
         	/**
         	 * Create a {@code ResolvableMethod} builder for the given handler class.
         	 */
        @@ -261,7 +255,6 @@ public class ResolvableMethod {
         		return new Builder<>(objectClass);
         	}
         
        -
         	/**
         	 * Builder for {@code ResolvableMethod}.
         	 */
        @@ -271,13 +264,11 @@ public class ResolvableMethod {
         
         		private final List> filters = new ArrayList<>(4);
         
        -
         		private Builder(Class objectClass) {
         			Assert.notNull(objectClass, "Class must not be null");
         			this.objectClass = objectClass;
         		}
         
        -
         		private void addFilter(String message, Predicate filter) {
         			this.filters.add(new LabeledPredicate<>(message, filter));
         		}
        @@ -294,15 +285,14 @@ public class ResolvableMethod {
         		 * Filter on methods with the given parameter types.
         		 */
         		public Builder argTypes(Class... argTypes) {
        -			addFilter("argTypes=" + Arrays.toString(argTypes), method ->
        -					ObjectUtils.isEmpty(argTypes) ? method.getParameterCount() == 0 :
        -							Arrays.equals(method.getParameterTypes(), argTypes));
        +			addFilter("argTypes=" + Arrays.toString(argTypes), method -> ObjectUtils.isEmpty(argTypes)
        +					? method.getParameterCount() == 0 : Arrays.equals(method.getParameterTypes(), argTypes));
         			return this;
         		}
         
         		/**
        -		 * Filter on annotated methods.
        -		 * See {@link org.springframework.web.method.MvcAnnotationPredicates}.
        +		 * Filter on annotated methods. See
        +		 * {@link org.springframework.web.method.MvcAnnotationPredicates}.
         		 */
         		@SafeVarargs
         		public final Builder annot(Predicate... filters) {
        @@ -312,15 +302,14 @@ public class ResolvableMethod {
         
         		/**
         		 * Filter on methods annotated with the given annotation type.
        -		 * @see #annot(Predicate[])
        -		 * See {@link org.springframework.web.method.MvcAnnotationPredicates}.
        +		 * @see #annot(Predicate[]) See
        +		 * {@link org.springframework.web.method.MvcAnnotationPredicates}.
         		 */
         		@SafeVarargs
         		public final Builder annotPresent(Class... annotationTypes) {
         			String message = "annotationPresent=" + Arrays.toString(annotationTypes);
        -			addFilter(message, method ->
        -					Arrays.stream(annotationTypes).allMatch(annotType ->
        -							AnnotatedElementUtils.findMergedAnnotation(method, annotType) != null));
        +			addFilter(message, method -> Arrays.stream(annotationTypes)
        +					.allMatch(annotType -> AnnotatedElementUtils.findMergedAnnotation(method, annotType) != null));
         			return this;
         		}
         
        @@ -332,8 +321,8 @@ public class ResolvableMethod {
         			String message = "annotationNotPresent=" + Arrays.toString(annotationTypes);
         			addFilter(message, method -> {
         				if (annotationTypes.length != 0) {
        -					return Arrays.stream(annotationTypes).noneMatch(annotType ->
        -							AnnotatedElementUtils.findMergedAnnotation(method, annotType) != null);
        +					return Arrays.stream(annotationTypes).noneMatch(
        +							annotType -> AnnotatedElementUtils.findMergedAnnotation(method, annotType) != null);
         				}
         				else {
         					return method.getAnnotations().length == 0;
        @@ -373,10 +362,11 @@ public class ResolvableMethod {
         		}
         
         		/**
        -		 * Build a {@code ResolvableMethod} from the provided filters which must
        -		 * resolve to a unique, single method.
        -		 * 

        See additional resolveXxx shortcut methods going directly to - * {@link Method} or return type parameter. + * Build a {@code ResolvableMethod} from the provided filters which must resolve + * to a unique, single method. + *

        + * See additional resolveXxx shortcut methods going directly to {@link Method} or + * return type parameter. * @throws IllegalStateException for no match or multiple matches */ public ResolvableMethod method() { @@ -391,8 +381,8 @@ public class ResolvableMethod { } private String formatMethods(Set methods) { - return "\nMatched:\n" + methods.stream() - .map(Method::toGenericString).collect(joining(",\n\t", "[\n\t", "\n]")); + return "\nMatched:\n" + + methods.stream().map(Method::toGenericString).collect(joining(",\n\t", "[\n\t", "\n]")); } public ResolvableMethod mockCall(Consumer invoker) { @@ -403,12 +393,12 @@ public class ResolvableMethod { return new ResolvableMethod(method); } - // Build & resolve shortcuts... /** * Resolve and return the {@code Method} equivalent to: - *

        {@code build().method()} + *

        + * {@code build().method()} */ public final Method resolveMethod() { return method().method(); @@ -416,7 +406,8 @@ public class ResolvableMethod { /** * Resolve and return the {@code Method} equivalent to: - *

        {@code named(methodName).build().method()} + *

        + * {@code named(methodName).build().method()} */ public Method resolveMethod(String methodName) { return named(methodName).method().method(); @@ -424,7 +415,8 @@ public class ResolvableMethod { /** * Resolve and return the declared return type equivalent to: - *

        {@code build().returnType()} + *

        + * {@code build().returnType()} */ public final MethodParameter resolveReturnType() { return method().returnType(); @@ -432,7 +424,8 @@ public class ResolvableMethod { /** * Shortcut to the unique return type equivalent to: - *

        {@code returning(returnType).build().returnType()} + *

        + * {@code returning(returnType).build().returnType()} * @param returnType the return type * @param generics optional array of generic types */ @@ -442,7 +435,8 @@ public class ResolvableMethod { /** * Shortcut to the unique return type equivalent to: - *

        {@code returning(returnType).build().returnType()} + *

        + * {@code returning(returnType).build().returnType()} * @param returnType the return type * @param generic at least one generic type * @param generics optional extra generic types @@ -457,20 +451,17 @@ public class ResolvableMethod { return returning(returnType).method().returnType(); } - @Override public String toString() { - return "ResolvableMethod.Builder[\n" + - "\tobjectClass = " + this.objectClass.getName() + ",\n" + - "\tfilters = " + formatFilters() + "\n]"; + return "ResolvableMethod.Builder[\n" + "\tobjectClass = " + this.objectClass.getName() + ",\n" + + "\tfilters = " + formatFilters() + "\n]"; } private String formatFilters() { - return this.filters.stream().map(Object::toString) - .collect(joining(",\n\t\t", "[\n\t\t", "\n\t]")); + return this.filters.stream().map(Object::toString).collect(joining(",\n\t\t", "[\n\t\t", "\n\t]")); } - } + } /** * Predicate with a descriptive label. @@ -481,13 +472,11 @@ public class ResolvableMethod { private final Predicate delegate; - private LabeledPredicate(String label, Predicate delegate) { this.label = label; this.delegate = delegate; } - @Override public boolean test(T method) { return this.delegate.test(method); @@ -512,8 +501,8 @@ public class ResolvableMethod { public String toString() { return this.label; } - } + } /** * Resolver for method arguments. @@ -522,15 +511,14 @@ public class ResolvableMethod { private final List> filters = new ArrayList<>(4); - @SafeVarargs private ArgResolver(Predicate... filter) { this.filters.addAll(Arrays.asList(filter)); } /** - * Filter on method arguments with annotations. - * See {@link org.springframework.web.method.MvcAnnotationPredicates}. + * Filter on method arguments with annotations. See + * {@link org.springframework.web.method.MvcAnnotationPredicates}. */ @SafeVarargs public final ArgResolver annot(Predicate... filters) { @@ -541,8 +529,8 @@ public class ResolvableMethod { /** * Filter on method arguments that have the given annotations. * @param annotationTypes the annotation types - * @see #annot(Predicate[]) - * See {@link org.springframework.web.method.MvcAnnotationPredicates}. + * @see #annot(Predicate[]) See + * {@link org.springframework.web.method.MvcAnnotationPredicates}. */ @SafeVarargs public final ArgResolver annotPresent(Class... annotationTypes) { @@ -556,10 +544,9 @@ public class ResolvableMethod { */ @SafeVarargs public final ArgResolver annotNotPresent(Class... annotationTypes) { - this.filters.add(param -> - (annotationTypes.length > 0 ? - Arrays.stream(annotationTypes).noneMatch(param::hasParameterAnnotation) : - param.getParameterAnnotations().length == 0)); + this.filters.add(param -> (annotationTypes.length > 0 + ? Arrays.stream(annotationTypes).noneMatch(param::hasParameterAnnotation) + : param.getParameterAnnotations().length == 0)); return this; } @@ -593,14 +580,12 @@ public class ResolvableMethod { */ public final MethodParameter arg() { List matches = applyFilters(); - Assert.state(!matches.isEmpty(), () -> - "No matching arg in method\n" + formatMethod()); - Assert.state(matches.size() == 1, () -> - "Multiple matching args in method\n" + formatMethod() + "\nMatches:\n\t" + matches); + Assert.state(!matches.isEmpty(), () -> "No matching arg in method\n" + formatMethod()); + Assert.state(matches.size() == 1, + () -> "Multiple matching args in method\n" + formatMethod() + "\nMatches:\n\t" + matches); return matches.get(0); } - private List applyFilters() { List matches = new ArrayList<>(); for (int i = 0; i < method.getParameterCount(); i++) { @@ -612,15 +597,14 @@ public class ResolvableMethod { } return matches; } - } + } private static class MethodInvocationInterceptor implements org.springframework.cglib.proxy.MethodInterceptor, MethodInterceptor { private Method invokedMethod; - Method getInvokedMethod() { return this.invokedMethod; } @@ -642,6 +626,7 @@ public class ResolvableMethod { public Object invoke(org.aopalliance.intercept.MethodInvocation inv) throws Throwable { return intercept(inv.getThis(), inv.getMethod(), inv.getArguments(), null); } + } @SuppressWarnings("unchecked") @@ -658,7 +643,7 @@ public class ResolvableMethod { else { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(type); - enhancer.setInterfaces(new Class[] {Supplier.class}); + enhancer.setInterfaces(new Class[] { Supplier.class }); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setCallbackType(org.springframework.cglib.proxy.MethodInterceptor.class); @@ -679,12 +664,13 @@ public class ResolvableMethod { proxy = ReflectionUtils.accessibleConstructor(proxyClass).newInstance(); } catch (Throwable ex) { - throw new IllegalStateException("Unable to instantiate proxy " + - "via both Objenesis and default constructor fails as well", ex); + throw new IllegalStateException( + "Unable to instantiate proxy " + "via both Objenesis and default constructor fails as well", + ex); } } - ((Factory) proxy).setCallbacks(new Callback[] {interceptor}); + ((Factory) proxy).setCallbacks(new Callback[] { interceptor }); return (T) proxy; } } diff --git a/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/reactive/AuthenticationPrincipalArgumentResolverTests.java b/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/reactive/AuthenticationPrincipalArgumentResolverTests.java index c2748493cf..73ae9dfa76 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/reactive/AuthenticationPrincipalArgumentResolverTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/reactive/AuthenticationPrincipalArgumentResolverTests.java @@ -36,6 +36,7 @@ import static org.assertj.core.api.Assertions.*; * @author Rob Winch */ public class AuthenticationPrincipalArgumentResolverTests { + private AuthenticationPrincipalArgumentResolver resolver = new AuthenticationPrincipalArgumentResolver(); @Test @@ -52,9 +53,9 @@ public class AuthenticationPrincipalArgumentResolverTests { @Test public void resolveArgumentWhenAuthenticationPrincipalThenFound() { Authentication authentication = TestAuthentication.authenticatedUser(); - Mono result = (Mono) this.resolver.resolveArgument(arg0("authenticationPrincipalOnMonoUserDetails"), null) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) - .block(); + Mono result = (Mono) this.resolver + .resolveArgument(arg0("authenticationPrincipalOnMonoUserDetails"), null) + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)).block(); assertThat(result.block()).isEqualTo(authentication.getPrincipal()); } @@ -70,9 +71,9 @@ public class AuthenticationPrincipalArgumentResolverTests { @Test public void resolveArgumentWhenMonoAndAuthenticationPrincipalThenFound() { Authentication authentication = TestAuthentication.authenticatedUser(); - Mono result = (Mono) this.resolver.resolveArgument(arg0("currentUserOnMonoUserDetails"), null) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) - .block(); + Mono result = (Mono) this.resolver + .resolveArgument(arg0("currentUserOnMonoUserDetails"), null) + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)).block(); assertThat(result.block()).isEqualTo(authentication.getPrincipal()); } @@ -83,14 +84,15 @@ public class AuthenticationPrincipalArgumentResolverTests { @Test public void resolveArgumentWhenExpressionThenFound() { Authentication authentication = TestAuthentication.authenticatedUser(); - Mono result = (Mono) this.resolver.resolveArgument(arg0("authenticationPrincipalExpression"), null) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) - .block(); + Mono result = (Mono) this.resolver + .resolveArgument(arg0("authenticationPrincipalExpression"), null) + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)).block(); assertThat(result.block()).isEqualTo(authentication.getName()); } @SuppressWarnings("unused") - private void authenticationPrincipalExpression(@AuthenticationPrincipal(expression = "username") Mono username) { + private void authenticationPrincipalExpression( + @AuthenticationPrincipal(expression = "username") Mono username) { } @Test @@ -109,5 +111,8 @@ public class AuthenticationPrincipalArgumentResolverTests { @AuthenticationPrincipal @Retention(RetentionPolicy.RUNTIME) - @interface CurrentUser {} + @interface CurrentUser { + + } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/reactive/CurrentSecurityContextArgumentResolverTests.java b/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/reactive/CurrentSecurityContextArgumentResolverTests.java index dba93aa552..d24540ceca 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/reactive/CurrentSecurityContextArgumentResolverTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/reactive/CurrentSecurityContextArgumentResolverTests.java @@ -37,6 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Rob Winch */ public class CurrentSecurityContextArgumentResolverTests { + private CurrentSecurityContextArgumentResolver resolver = new CurrentSecurityContextArgumentResolver(); @Test @@ -46,16 +47,17 @@ public class CurrentSecurityContextArgumentResolverTests { @Test public void resolveArgumentWhenAuthenticationPrincipalAndEmptyContextThenNull() { - Object result = this.resolver.resolveArgument(arg0("currentSecurityContextOnMonoSecurityContext"), null).block(); + Object result = this.resolver.resolveArgument(arg0("currentSecurityContextOnMonoSecurityContext"), null) + .block(); assertThat(result).isNull(); } @Test public void resolveArgumentWhenAuthenticationPrincipalThenFound() { Authentication authentication = TestAuthentication.authenticatedUser(); - Mono result = (Mono) this.resolver.resolveArgument(arg0("currentSecurityContextOnMonoSecurityContext"), null) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) - .block(); + Mono result = (Mono) this.resolver + .resolveArgument(arg0("currentSecurityContextOnMonoSecurityContext"), null) + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)).block(); assertThat(result.block().getAuthentication()).isEqualTo(authentication); } @@ -71,9 +73,9 @@ public class CurrentSecurityContextArgumentResolverTests { @Test public void resolveArgumentWhenMonoAndAuthenticationPrincipalThenFound() { Authentication authentication = TestAuthentication.authenticatedUser(); - Mono result = (Mono) this.resolver.resolveArgument(arg0("currentUserOnMonoUserDetails"), null) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) - .block(); + Mono result = (Mono) this.resolver + .resolveArgument(arg0("currentUserOnMonoUserDetails"), null) + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)).block(); assertThat(result.block()).isEqualTo(authentication.getPrincipal()); } @@ -84,14 +86,15 @@ public class CurrentSecurityContextArgumentResolverTests { @Test public void resolveArgumentWhenExpressionThenFound() { Authentication authentication = TestAuthentication.authenticatedUser(); - Mono result = (Mono) this.resolver.resolveArgument(arg0("authenticationPrincipalExpression"), null) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) - .block(); + Mono result = (Mono) this.resolver + .resolveArgument(arg0("authenticationPrincipalExpression"), null) + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)).block(); assertThat(result.block()).isEqualTo(authentication.getName()); } @SuppressWarnings("unused") - private void authenticationPrincipalExpression(@CurrentSecurityContext(expression = "authentication?.principal?.username") Mono username) { + private void authenticationPrincipalExpression( + @CurrentSecurityContext(expression = "authentication?.principal?.username") Mono username) { } @Test @@ -110,5 +113,8 @@ public class CurrentSecurityContextArgumentResolverTests { @CurrentSecurityContext(expression = "authentication?.principal") @Retention(RetentionPolicy.RUNTIME) - @interface CurrentUser {} + @interface CurrentUser { + + } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/util/matcher/AndMessageMatcherTests.java b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/AndMessageMatcherTests.java index f0d3777729..0a637e4fc4 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/util/matcher/AndMessageMatcherTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/AndMessageMatcherTests.java @@ -30,6 +30,7 @@ import org.springframework.messaging.Message; @RunWith(MockitoJUnitRunner.class) public class AndMessageMatcherTests { + @Mock private MessageMatcher delegate; @@ -113,4 +114,5 @@ public class AndMessageMatcherTests { assertThat(matcher.matches(message)).isFalse(); } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/util/matcher/OrMessageMatcherTests.java b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/OrMessageMatcherTests.java index 8f4843ab43..87295c0c58 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/util/matcher/OrMessageMatcherTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/OrMessageMatcherTests.java @@ -30,6 +30,7 @@ import org.springframework.messaging.Message; @RunWith(MockitoJUnitRunner.class) public class OrMessageMatcherTests { + @Mock private MessageMatcher delegate; @@ -112,4 +113,5 @@ public class OrMessageMatcherTests { assertThat(matcher.matches(message)).isTrue(); } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/util/matcher/SimpDestinationMessageMatcherTests.java b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/SimpDestinationMessageMatcherTests.java index 4ebe6cf797..daa8ba19de 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/util/matcher/SimpDestinationMessageMatcherTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/SimpDestinationMessageMatcherTests.java @@ -26,6 +26,7 @@ import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; public class SimpDestinationMessageMatcherTests { + MessageBuilder messageBuilder; SimpDestinationMessageMatcher matcher; @@ -55,8 +56,7 @@ public class SimpDestinationMessageMatcherTests { @Test public void matchesAllWithDestination() { - messageBuilder.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, - "/destination/1"); + messageBuilder.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "/destination/1"); assertThat(matcher.matches(messageBuilder.build())).isTrue(); } @@ -65,8 +65,7 @@ public class SimpDestinationMessageMatcherTests { public void matchesSpecificWithDestination() { matcher = new SimpDestinationMessageMatcher("/destination/1"); - messageBuilder.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, - "/destination/1"); + messageBuilder.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "/destination/1"); assertThat(matcher.matches(messageBuilder.build())).isTrue(); } @@ -75,43 +74,36 @@ public class SimpDestinationMessageMatcherTests { public void matchesFalseWithDestination() { matcher = new SimpDestinationMessageMatcher("/nomatch"); - messageBuilder.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, - "/destination/1"); + messageBuilder.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "/destination/1"); assertThat(matcher.matches(messageBuilder.build())).isFalse(); } @Test public void matchesFalseMessageTypeNotDisconnectType() { - matcher = SimpDestinationMessageMatcher.createMessageMatcher("/match", - pathMatcher); + matcher = SimpDestinationMessageMatcher.createMessageMatcher("/match", pathMatcher); - messageBuilder.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, - SimpMessageType.DISCONNECT); + messageBuilder.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.DISCONNECT); assertThat(matcher.matches(messageBuilder.build())).isFalse(); } @Test public void matchesTrueMessageType() { - matcher = SimpDestinationMessageMatcher.createMessageMatcher("/match", - pathMatcher); + matcher = SimpDestinationMessageMatcher.createMessageMatcher("/match", pathMatcher); messageBuilder.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "/match"); - messageBuilder.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, - SimpMessageType.MESSAGE); + messageBuilder.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.MESSAGE); assertThat(matcher.matches(messageBuilder.build())).isTrue(); } @Test public void matchesTrueSubscribeType() { - matcher = SimpDestinationMessageMatcher.createSubscribeMatcher("/match", - pathMatcher); + matcher = SimpDestinationMessageMatcher.createSubscribeMatcher("/match", pathMatcher); messageBuilder.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "/match"); - messageBuilder.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, - SimpMessageType.SUBSCRIBE); + messageBuilder.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.SUBSCRIBE); assertThat(matcher.matches(messageBuilder.build())).isTrue(); } @@ -121,8 +113,7 @@ public class SimpDestinationMessageMatcherTests { matcher = new SimpDestinationMessageMatcher("/match"); messageBuilder.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "/match"); - messageBuilder.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, - SimpMessageType.MESSAGE); + messageBuilder.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.MESSAGE); assertThat(matcher.matches(messageBuilder.build())).isTrue(); } @@ -132,8 +123,7 @@ public class SimpDestinationMessageMatcherTests { matcher = new SimpDestinationMessageMatcher("/topics/{topic}/**"); messageBuilder.setHeader(SimpMessageHeaderAccessor.DESTINATION_HEADER, "/topics/someTopic/sub1"); - messageBuilder.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, - SimpMessageType.MESSAGE); + messageBuilder.setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.MESSAGE); assertThat(matcher.extractPathVariables(messageBuilder.build()).get("topic")).isEqualTo("someTopic"); } @@ -146,11 +136,9 @@ public class SimpDestinationMessageMatcherTests { @Test public void typeConstructorParameterIsTransmitted() { - matcher = SimpDestinationMessageMatcher.createMessageMatcher("/match", - pathMatcher); + matcher = SimpDestinationMessageMatcher.createMessageMatcher("/match", pathMatcher); - MessageMatcher expectedTypeMatcher = new SimpMessageTypeMatcher( - SimpMessageType.MESSAGE); + MessageMatcher expectedTypeMatcher = new SimpMessageTypeMatcher(SimpMessageType.MESSAGE); assertThat(matcher.getMessageTypeMatcher()).isEqualTo(expectedTypeMatcher); diff --git a/messaging/src/test/java/org/springframework/security/messaging/util/matcher/SimpMessageTypeMatcherTests.java b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/SimpMessageTypeMatcherTests.java index 0ef2cf05a4..57115af1b3 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/util/matcher/SimpMessageTypeMatcherTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/SimpMessageTypeMatcherTests.java @@ -25,6 +25,7 @@ import org.springframework.messaging.simp.SimpMessageType; import org.springframework.messaging.support.MessageBuilder; public class SimpMessageTypeMatcherTests { + private SimpMessageTypeMatcher matcher; @Before @@ -39,20 +40,16 @@ public class SimpMessageTypeMatcherTests { @Test public void matchesMessageMessageTrue() { - Message message = MessageBuilder - .withPayload("Hi") - .setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, - SimpMessageType.MESSAGE).build(); + Message message = MessageBuilder.withPayload("Hi") + .setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.MESSAGE).build(); assertThat(matcher.matches(message)).isTrue(); } @Test public void matchesMessageConnectFalse() { - Message message = MessageBuilder - .withPayload("Hi") - .setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, - SimpMessageType.CONNECT).build(); + Message message = MessageBuilder.withPayload("Hi") + .setHeader(SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER, SimpMessageType.CONNECT).build(); assertThat(matcher.matches(message)).isFalse(); } @@ -63,4 +60,5 @@ public class SimpMessageTypeMatcherTests { assertThat(matcher.matches(message)).isFalse(); } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/web/csrf/CsrfChannelInterceptorTests.java b/messaging/src/test/java/org/springframework/security/messaging/web/csrf/CsrfChannelInterceptorTests.java index 7c37cd4c60..71aab036d0 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/web/csrf/CsrfChannelInterceptorTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/web/csrf/CsrfChannelInterceptorTests.java @@ -35,6 +35,7 @@ import org.springframework.security.web.csrf.MissingCsrfTokenException; @RunWith(MockitoJUnitRunner.class) public class CsrfChannelInterceptorTests { + @Mock MessageChannel channel; @@ -125,8 +126,7 @@ public class CsrfChannelInterceptorTests { @Test(expected = InvalidCsrfTokenException.class) public void preSendInvalidToken() { - messageHeaders.setNativeHeader(token.getHeaderName(), token.getToken() - + "invalid"); + messageHeaders.setNativeHeader(token.getHeaderName(), token.getToken() + "invalid"); interceptor.preSend(message(), channel); } @@ -149,4 +149,5 @@ public class CsrfChannelInterceptorTests { Map headersToCopy = messageHeaders.toMap(); return MessageBuilder.withPayload("hi").copyHeaders(headersToCopy).build(); } + } diff --git a/messaging/src/test/java/org/springframework/security/messaging/web/socket/server/CsrfTokenHandshakeInterceptorTests.java b/messaging/src/test/java/org/springframework/security/messaging/web/socket/server/CsrfTokenHandshakeInterceptorTests.java index 6a36e5de8c..027da27ecf 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/web/socket/server/CsrfTokenHandshakeInterceptorTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/web/socket/server/CsrfTokenHandshakeInterceptorTests.java @@ -34,13 +34,14 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; /** - * * @author Rob Winch */ @RunWith(MockitoJUnitRunner.class) public class CsrfTokenHandshakeInterceptorTests { + @Mock WebSocketHandler wsHandler; + @Mock ServerHttpResponse response; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizationCodeOAuth2AuthorizedClientProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizationCodeOAuth2AuthorizedClientProvider.java index 7ff23c3ceb..ff6d24e17b 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizationCodeOAuth2AuthorizedClientProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizationCodeOAuth2AuthorizedClientProvider.java @@ -21,8 +21,8 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.util.Assert; /** - * An implementation of an {@link OAuth2AuthorizedClientProvider} - * for the {@link AuthorizationGrantType#AUTHORIZATION_CODE authorization_code} grant. + * An implementation of an {@link OAuth2AuthorizedClientProvider} for the + * {@link AuthorizationGrantType#AUTHORIZATION_CODE authorization_code} grant. * * @author Joe Grandja * @since 5.2 @@ -31,24 +31,28 @@ import org.springframework.util.Assert; public final class AuthorizationCodeOAuth2AuthorizedClientProvider implements OAuth2AuthorizedClientProvider { /** - * Attempt to authorize the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}. - * Returns {@code null} if authorization is not supported, - * e.g. the client's {@link ClientRegistration#getAuthorizationGrantType() authorization grant type} - * is not {@link AuthorizationGrantType#AUTHORIZATION_CODE authorization_code} OR the client is already authorized. - * + * Attempt to authorize the {@link OAuth2AuthorizationContext#getClientRegistration() + * client} in the provided {@code context}. Returns {@code null} if authorization is + * not supported, e.g. the client's + * {@link ClientRegistration#getAuthorizationGrantType() authorization grant type} is + * not {@link AuthorizationGrantType#AUTHORIZATION_CODE authorization_code} OR the + * client is already authorized. * @param context the context that holds authorization-specific state for the client - * @return the {@link OAuth2AuthorizedClient} or {@code null} if authorization is not supported + * @return the {@link OAuth2AuthorizedClient} or {@code null} if authorization is not + * supported */ @Override @Nullable public OAuth2AuthorizedClient authorize(OAuth2AuthorizationContext context) { Assert.notNull(context, "context cannot be null"); - if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(context.getClientRegistration().getAuthorizationGrantType()) && - context.getAuthorizedClient() == null) { - // ClientAuthorizationRequiredException is caught by OAuth2AuthorizationRequestRedirectFilter which initiates authorization + if (AuthorizationGrantType.AUTHORIZATION_CODE.equals( + context.getClientRegistration().getAuthorizationGrantType()) && context.getAuthorizedClient() == null) { + // ClientAuthorizationRequiredException is caught by + // OAuth2AuthorizationRequestRedirectFilter which initiates authorization throw new ClientAuthorizationRequiredException(context.getClientRegistration().getRegistrationId()); } return null; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizationCodeReactiveOAuth2AuthorizedClientProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizationCodeReactiveOAuth2AuthorizedClientProvider.java index 002432bd37..d49feb2e6c 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizationCodeReactiveOAuth2AuthorizedClientProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizationCodeReactiveOAuth2AuthorizedClientProvider.java @@ -21,33 +21,39 @@ import org.springframework.util.Assert; import reactor.core.publisher.Mono; /** - * An implementation of a {@link ReactiveOAuth2AuthorizedClientProvider} - * for the {@link AuthorizationGrantType#AUTHORIZATION_CODE authorization_code} grant. + * An implementation of a {@link ReactiveOAuth2AuthorizedClientProvider} for the + * {@link AuthorizationGrantType#AUTHORIZATION_CODE authorization_code} grant. * * @author Joe Grandja * @since 5.2 * @see ReactiveOAuth2AuthorizedClientProvider */ -public final class AuthorizationCodeReactiveOAuth2AuthorizedClientProvider implements ReactiveOAuth2AuthorizedClientProvider { +public final class AuthorizationCodeReactiveOAuth2AuthorizedClientProvider + implements ReactiveOAuth2AuthorizedClientProvider { /** - * Attempt to authorize the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}. - * Returns an empty {@code Mono} if authorization is not supported, - * e.g. the client's {@link ClientRegistration#getAuthorizationGrantType() authorization grant type} - * is not {@link AuthorizationGrantType#AUTHORIZATION_CODE authorization_code} OR the client is already authorized. - * + * Attempt to authorize the {@link OAuth2AuthorizationContext#getClientRegistration() + * client} in the provided {@code context}. Returns an empty {@code Mono} if + * authorization is not supported, e.g. the client's + * {@link ClientRegistration#getAuthorizationGrantType() authorization grant type} is + * not {@link AuthorizationGrantType#AUTHORIZATION_CODE authorization_code} OR the + * client is already authorized. * @param context the context that holds authorization-specific state for the client - * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if authorization is not supported + * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if + * authorization is not supported */ @Override public Mono authorize(OAuth2AuthorizationContext context) { Assert.notNull(context, "context cannot be null"); - if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(context.getClientRegistration().getAuthorizationGrantType()) && - context.getAuthorizedClient() == null) { - // ClientAuthorizationRequiredException is caught by OAuth2AuthorizationRequestRedirectWebFilter which initiates authorization - return Mono.error(() -> new ClientAuthorizationRequiredException(context.getClientRegistration().getRegistrationId())); + if (AuthorizationGrantType.AUTHORIZATION_CODE.equals( + context.getClientRegistration().getAuthorizationGrantType()) && context.getAuthorizedClient() == null) { + // ClientAuthorizationRequiredException is caught by + // OAuth2AuthorizationRequestRedirectWebFilter which initiates authorization + return Mono.error(() -> new ClientAuthorizationRequiredException( + context.getClientRegistration().getRegistrationId())); } return Mono.empty(); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizedClientServiceOAuth2AuthorizedClientManager.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizedClientServiceOAuth2AuthorizedClientManager.java index 179e4f40a8..cc3eebd80c 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizedClientServiceOAuth2AuthorizedClientManager.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizedClientServiceOAuth2AuthorizedClientManager.java @@ -33,35 +33,35 @@ import java.util.Map; import java.util.function.Function; /** - * An implementation of an {@link OAuth2AuthorizedClientManager} - * that is capable of operating outside of the context of a {@code HttpServletRequest}, - * e.g. in a scheduled/background thread and/or in the service-tier. + * An implementation of an {@link OAuth2AuthorizedClientManager} that is capable of + * operating outside of the context of a {@code HttpServletRequest}, e.g. in a + * scheduled/background thread and/or in the service-tier. * *

        - * (When operating within the context of a {@code HttpServletRequest}, - * use {@link DefaultOAuth2AuthorizedClientManager} instead.) + * (When operating within the context of a {@code HttpServletRequest}, use + * {@link DefaultOAuth2AuthorizedClientManager} instead.) * *

        Authorized Client Persistence

        * *

        - * This manager utilizes an {@link OAuth2AuthorizedClientService} - * to persist {@link OAuth2AuthorizedClient}s. + * This manager utilizes an {@link OAuth2AuthorizedClientService} to persist + * {@link OAuth2AuthorizedClient}s. * *

        * By default, when an authorization attempt succeeds, the {@link OAuth2AuthorizedClient} - * will be saved in the {@link OAuth2AuthorizedClientService}. - * This functionality can be changed by configuring a custom {@link OAuth2AuthorizationSuccessHandler} - * via {@link #setAuthorizationSuccessHandler(OAuth2AuthorizationSuccessHandler)}. + * will be saved in the {@link OAuth2AuthorizedClientService}. This functionality can be + * changed by configuring a custom {@link OAuth2AuthorizationSuccessHandler} via + * {@link #setAuthorizationSuccessHandler(OAuth2AuthorizationSuccessHandler)}. * *

        * By default, when an authorization attempt fails due to an - * {@value OAuth2ErrorCodes#INVALID_GRANT} error, - * the previously saved {@link OAuth2AuthorizedClient} - * will be removed from the {@link OAuth2AuthorizedClientService}. - * (The {@value OAuth2ErrorCodes#INVALID_GRANT} error can occur - * when a refresh token that is no longer valid is used to retrieve a new access token.) - * This functionality can be changed by configuring a custom {@link OAuth2AuthorizationFailureHandler} - * via {@link #setAuthorizationFailureHandler(OAuth2AuthorizationFailureHandler)}. + * {@value OAuth2ErrorCodes#INVALID_GRANT} error, the previously saved + * {@link OAuth2AuthorizedClient} will be removed from the + * {@link OAuth2AuthorizedClientService}. (The {@value OAuth2ErrorCodes#INVALID_GRANT} + * error can occur when a refresh token that is no longer valid is used to retrieve a new + * access token.) This functionality can be changed by configuring a custom + * {@link OAuth2AuthorizationFailureHandler} via + * {@link #setAuthorizationFailureHandler(OAuth2AuthorizationFailureHandler)}. * * @author Joe Grandja * @since 5.2 @@ -72,36 +72,42 @@ import java.util.function.Function; * @see OAuth2AuthorizationFailureHandler */ public final class AuthorizedClientServiceOAuth2AuthorizedClientManager implements OAuth2AuthorizedClientManager { - private static final OAuth2AuthorizedClientProvider DEFAULT_AUTHORIZED_CLIENT_PROVIDER = - OAuth2AuthorizedClientProviderBuilder.builder() - .clientCredentials() - .build(); + + private static final OAuth2AuthorizedClientProvider DEFAULT_AUTHORIZED_CLIENT_PROVIDER = OAuth2AuthorizedClientProviderBuilder + .builder().clientCredentials().build(); + private final ClientRegistrationRepository clientRegistrationRepository; + private final OAuth2AuthorizedClientService authorizedClientService; + private OAuth2AuthorizedClientProvider authorizedClientProvider; + private Function> contextAttributesMapper; + private OAuth2AuthorizationSuccessHandler authorizationSuccessHandler; + private OAuth2AuthorizationFailureHandler authorizationFailureHandler; /** - * Constructs an {@code AuthorizedClientServiceOAuth2AuthorizedClientManager} using the provided parameters. - * + * Constructs an {@code AuthorizedClientServiceOAuth2AuthorizedClientManager} using + * the provided parameters. * @param clientRegistrationRepository the repository of client registrations * @param authorizedClientService the authorized client service */ - public AuthorizedClientServiceOAuth2AuthorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, - OAuth2AuthorizedClientService authorizedClientService) { + public AuthorizedClientServiceOAuth2AuthorizedClientManager( + ClientRegistrationRepository clientRegistrationRepository, + OAuth2AuthorizedClientService authorizedClientService) { Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null"); Assert.notNull(authorizedClientService, "authorizedClientService cannot be null"); this.clientRegistrationRepository = clientRegistrationRepository; this.authorizedClientService = authorizedClientService; this.authorizedClientProvider = DEFAULT_AUTHORIZED_CLIENT_PROVIDER; this.contextAttributesMapper = new DefaultContextAttributesMapper(); - this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> - authorizedClientService.saveAuthorizedClient(authorizedClient, principal); + this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> authorizedClientService + .saveAuthorizedClient(authorizedClient, principal); this.authorizationFailureHandler = new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( - (clientRegistrationId, principal, attributes) -> - authorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName())); + (clientRegistrationId, principal, attributes) -> authorizedClientService + .removeAuthorizedClient(clientRegistrationId, principal.getName())); } @Nullable @@ -116,39 +122,45 @@ public final class AuthorizedClientServiceOAuth2AuthorizedClientManager implemen OAuth2AuthorizationContext.Builder contextBuilder; if (authorizedClient != null) { contextBuilder = OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient); - } else { - ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId); - Assert.notNull(clientRegistration, "Could not find ClientRegistration with id '" + clientRegistrationId + "'"); - authorizedClient = this.authorizedClientService.loadAuthorizedClient(clientRegistrationId, principal.getName()); + } + else { + ClientRegistration clientRegistration = this.clientRegistrationRepository + .findByRegistrationId(clientRegistrationId); + Assert.notNull(clientRegistration, + "Could not find ClientRegistration with id '" + clientRegistrationId + "'"); + authorizedClient = this.authorizedClientService.loadAuthorizedClient(clientRegistrationId, + principal.getName()); if (authorizedClient != null) { contextBuilder = OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient); - } else { + } + else { contextBuilder = OAuth2AuthorizationContext.withClientRegistration(clientRegistration); } } - OAuth2AuthorizationContext authorizationContext = contextBuilder - .principal(principal) - .attributes(attributes -> { - Map contextAttributes = this.contextAttributesMapper.apply(authorizeRequest); - if (!CollectionUtils.isEmpty(contextAttributes)) { - attributes.putAll(contextAttributes); - } - }) - .build(); + OAuth2AuthorizationContext authorizationContext = contextBuilder.principal(principal).attributes(attributes -> { + Map contextAttributes = this.contextAttributesMapper.apply(authorizeRequest); + if (!CollectionUtils.isEmpty(contextAttributes)) { + attributes.putAll(contextAttributes); + } + }).build(); try { authorizedClient = this.authorizedClientProvider.authorize(authorizationContext); - } catch (OAuth2AuthorizationException ex) { + } + catch (OAuth2AuthorizationException ex) { this.authorizationFailureHandler.onAuthorizationFailure(ex, principal, Collections.emptyMap()); throw ex; } if (authorizedClient != null) { - this.authorizationSuccessHandler.onAuthorizationSuccess( - authorizedClient, principal, Collections.emptyMap()); - } else { - // In the case of re-authorization, the returned `authorizedClient` may be null if re-authorization is not supported. - // For these cases, return the provided `authorizationContext.authorizedClient`. + this.authorizationSuccessHandler.onAuthorizationSuccess(authorizedClient, principal, + Collections.emptyMap()); + } + else { + // In the case of re-authorization, the returned `authorizedClient` may be + // null if re-authorization is not supported. + // For these cases, return the provided + // `authorizationContext.authorizedClient`. if (authorizationContext.getAuthorizedClient() != null) { return authorizationContext.getAuthorizedClient(); } @@ -158,9 +170,10 @@ public final class AuthorizedClientServiceOAuth2AuthorizedClientManager implemen } /** - * Sets the {@link OAuth2AuthorizedClientProvider} used for authorizing (or re-authorizing) an OAuth 2.0 Client. - * - * @param authorizedClientProvider the {@link OAuth2AuthorizedClientProvider} used for authorizing (or re-authorizing) an OAuth 2.0 Client + * Sets the {@link OAuth2AuthorizedClientProvider} used for authorizing (or + * re-authorizing) an OAuth 2.0 Client. + * @param authorizedClientProvider the {@link OAuth2AuthorizedClientProvider} used for + * authorizing (or re-authorizing) an OAuth 2.0 Client */ public void setAuthorizedClientProvider(OAuth2AuthorizedClientProvider authorizedClientProvider) { Assert.notNull(authorizedClientProvider, "authorizedClientProvider cannot be null"); @@ -168,24 +181,28 @@ public final class AuthorizedClientServiceOAuth2AuthorizedClientManager implemen } /** - * Sets the {@code Function} used for mapping attribute(s) from the {@link OAuth2AuthorizeRequest} to a {@code Map} of attributes - * to be associated to the {@link OAuth2AuthorizationContext#getAttributes() authorization context}. - * - * @param contextAttributesMapper the {@code Function} used for supplying the {@code Map} of attributes - * to the {@link OAuth2AuthorizationContext#getAttributes() authorization context} + * Sets the {@code Function} used for mapping attribute(s) from the + * {@link OAuth2AuthorizeRequest} to a {@code Map} of attributes to be associated to + * the {@link OAuth2AuthorizationContext#getAttributes() authorization context}. + * @param contextAttributesMapper the {@code Function} used for supplying the + * {@code Map} of attributes to the {@link OAuth2AuthorizationContext#getAttributes() + * authorization context} */ - public void setContextAttributesMapper(Function> contextAttributesMapper) { + public void setContextAttributesMapper( + Function> contextAttributesMapper) { Assert.notNull(contextAttributesMapper, "contextAttributesMapper cannot be null"); this.contextAttributesMapper = contextAttributesMapper; } /** - * Sets the {@link OAuth2AuthorizationSuccessHandler} that handles successful authorizations. + * Sets the {@link OAuth2AuthorizationSuccessHandler} that handles successful + * authorizations. * *

        - * The default saves {@link OAuth2AuthorizedClient}s in the {@link OAuth2AuthorizedClientService}. - * - * @param authorizationSuccessHandler the {@link OAuth2AuthorizationSuccessHandler} that handles successful authorizations + * The default saves {@link OAuth2AuthorizedClient}s in the + * {@link OAuth2AuthorizedClientService}. + * @param authorizationSuccessHandler the {@link OAuth2AuthorizationSuccessHandler} + * that handles successful authorizations * @since 5.3 */ public void setAuthorizationSuccessHandler(OAuth2AuthorizationSuccessHandler authorizationSuccessHandler) { @@ -194,12 +211,14 @@ public final class AuthorizedClientServiceOAuth2AuthorizedClientManager implemen } /** - * Sets the {@link OAuth2AuthorizationFailureHandler} that handles authorization failures. + * Sets the {@link OAuth2AuthorizationFailureHandler} that handles authorization + * failures. * *

        - * A {@link RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} is used by default. - * - * @param authorizationFailureHandler the {@link OAuth2AuthorizationFailureHandler} that handles authorization failures + * A {@link RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} is used by + * default. + * @param authorizationFailureHandler the {@link OAuth2AuthorizationFailureHandler} + * that handles authorization failures * @see RemoveAuthorizedClientOAuth2AuthorizationFailureHandler * @since 5.3 */ @@ -209,9 +228,11 @@ public final class AuthorizedClientServiceOAuth2AuthorizedClientManager implemen } /** - * The default implementation of the {@link #setContextAttributesMapper(Function) contextAttributesMapper}. + * The default implementation of the {@link #setContextAttributesMapper(Function) + * contextAttributesMapper}. */ - public static class DefaultContextAttributesMapper implements Function> { + public static class DefaultContextAttributesMapper + implements Function> { @Override public Map apply(OAuth2AuthorizeRequest authorizeRequest) { @@ -224,5 +245,7 @@ public final class AuthorizedClientServiceOAuth2AuthorizedClientManager implemen } return contextAttributes; } + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager.java index 3a446ec2da..0439c6bc1a 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager.java @@ -28,34 +28,45 @@ import java.util.Map; import java.util.function.Function; /** - * An implementation of a {@link ReactiveOAuth2AuthorizedClientManager} - * that is capable of operating outside of the context of a {@link ServerWebExchange}, - * e.g. in a scheduled/background thread and/or in the service-tier. + * An implementation of a {@link ReactiveOAuth2AuthorizedClientManager} that is capable of + * operating outside of the context of a {@link ServerWebExchange}, e.g. in a + * scheduled/background thread and/or in the service-tier. * - *

        (When operating within the context of a {@link ServerWebExchange}, - * use {@link DefaultReactiveOAuth2AuthorizedClientManager} instead.)

        + *

        + * (When operating within the context of a {@link ServerWebExchange}, use + * {@link DefaultReactiveOAuth2AuthorizedClientManager} instead.) + *

        * - *

        This is a reactive equivalent of {@link org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager}.

        + *

        + * This is a reactive equivalent of + * {@link org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager}. + *

        * *

        Authorized Client Persistence

        * - *

        This client manager utilizes a {@link ReactiveOAuth2AuthorizedClientService} - * to persist {@link OAuth2AuthorizedClient}s.

        + *

        + * This client manager utilizes a {@link ReactiveOAuth2AuthorizedClientService} to persist + * {@link OAuth2AuthorizedClient}s. + *

        * - *

        By default, when an authorization attempt succeeds, the {@link OAuth2AuthorizedClient} - * will be saved in the authorized client service. - * This functionality can be changed by configuring a custom {@link ReactiveOAuth2AuthorizationSuccessHandler} - * via {@link #setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler)}.

        + *

        + * By default, when an authorization attempt succeeds, the {@link OAuth2AuthorizedClient} + * will be saved in the authorized client service. This functionality can be changed by + * configuring a custom {@link ReactiveOAuth2AuthorizationSuccessHandler} via + * {@link #setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler)}. + *

        * - *

        By default, when an authorization attempt fails due to an + *

        + * By default, when an authorization attempt fails due to an * {@value org.springframework.security.oauth2.core.OAuth2ErrorCodes#INVALID_GRANT} error, - * the previously saved {@link OAuth2AuthorizedClient} - * will be removed from the authorized client service. - * (The {@value org.springframework.security.oauth2.core.OAuth2ErrorCodes#INVALID_GRANT} - * error generally occurs when a refresh token that is no longer valid - * is used to retrieve a new access token.) - * This functionality can be changed by configuring a custom {@link ReactiveOAuth2AuthorizationFailureHandler} - * via {@link #setAuthorizationFailureHandler(ReactiveOAuth2AuthorizationFailureHandler)}.

        + * the previously saved {@link OAuth2AuthorizedClient} will be removed from the authorized + * client service. (The + * {@value org.springframework.security.oauth2.core.OAuth2ErrorCodes#INVALID_GRANT} error + * generally occurs when a refresh token that is no longer valid is used to retrieve a new + * access token.) This functionality can be changed by configuring a custom + * {@link ReactiveOAuth2AuthorizationFailureHandler} via + * {@link #setAuthorizationFailureHandler(ReactiveOAuth2AuthorizationFailureHandler)}. + *

        * * @author Ankur Pathak * @author Phil Clay @@ -69,22 +80,26 @@ import java.util.function.Function; public final class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager implements ReactiveOAuth2AuthorizedClientManager { - private static final ReactiveOAuth2AuthorizedClientProvider DEFAULT_AUTHORIZED_CLIENT_PROVIDER = - ReactiveOAuth2AuthorizedClientProviderBuilder.builder() - .clientCredentials() - .build(); + private static final ReactiveOAuth2AuthorizedClientProvider DEFAULT_AUTHORIZED_CLIENT_PROVIDER = ReactiveOAuth2AuthorizedClientProviderBuilder + .builder().clientCredentials().build(); + private final ReactiveClientRegistrationRepository clientRegistrationRepository; + private final ReactiveOAuth2AuthorizedClientService authorizedClientService; + private ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = DEFAULT_AUTHORIZED_CLIENT_PROVIDER; + private Function>> contextAttributesMapper = new DefaultContextAttributesMapper(); + private ReactiveOAuth2AuthorizationSuccessHandler authorizationSuccessHandler; + private ReactiveOAuth2AuthorizationFailureHandler authorizationFailureHandler; /** - * Constructs an {@code AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager} using the provided parameters. - * + * Constructs an {@code AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager} + * using the provided parameters. * @param clientRegistrationRepository the repository of client registrations - * @param authorizedClientService the authorized client service + * @param authorizedClientService the authorized client service */ public AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager( ReactiveClientRegistrationRepository clientRegistrationRepository, @@ -93,11 +108,11 @@ public final class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager Assert.notNull(authorizedClientService, "authorizedClientService cannot be null"); this.clientRegistrationRepository = clientRegistrationRepository; this.authorizedClientService = authorizedClientService; - this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> - authorizedClientService.saveAuthorizedClient(authorizedClient, principal); + this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> authorizedClientService + .saveAuthorizedClient(authorizedClient, principal); this.authorizationFailureHandler = new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler( - (clientRegistrationId, principal, attributes) -> - this.authorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName())); + (clientRegistrationId, principal, attributes) -> this.authorizedClientService + .removeAuthorizedClient(clientRegistrationId, principal.getName())); } @Override @@ -113,14 +128,17 @@ public final class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager Authentication principal = authorizeRequest.getPrincipal(); return Mono.justOrEmpty(authorizeRequest.getAuthorizedClient()) .map(OAuth2AuthorizationContext::withAuthorizedClient) - .switchIfEmpty(Mono.defer(() -> this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId) - .flatMap(clientRegistration -> this.authorizedClientService.loadAuthorizedClient(clientRegistrationId, principal.getName()) + .switchIfEmpty(Mono.defer(() -> this.clientRegistrationRepository + .findByRegistrationId(clientRegistrationId) + .flatMap(clientRegistration -> this.authorizedClientService + .loadAuthorizedClient(clientRegistrationId, principal.getName()) .map(OAuth2AuthorizationContext::withAuthorizedClient) - .switchIfEmpty(Mono.fromSupplier(() -> OAuth2AuthorizationContext.withClientRegistration(clientRegistration)))) - .switchIfEmpty(Mono.error(() -> new IllegalArgumentException("Could not find ClientRegistration with id '" + clientRegistrationId + "'"))))) + .switchIfEmpty(Mono.fromSupplier( + () -> OAuth2AuthorizationContext.withClientRegistration(clientRegistration)))) + .switchIfEmpty(Mono.error(() -> new IllegalArgumentException( + "Could not find ClientRegistration with id '" + clientRegistrationId + "'"))))) .flatMap(contextBuilder -> this.contextAttributesMapper.apply(authorizeRequest) - .defaultIfEmpty(Collections.emptyMap()) - .map(contextAttributes -> { + .defaultIfEmpty(Collections.emptyMap()).map(contextAttributes -> { OAuth2AuthorizationContext.Builder builder = contextBuilder.principal(principal); if (!contextAttributes.isEmpty()) { builder = builder.attributes(attributes -> attributes.putAll(contextAttributes)); @@ -130,39 +148,37 @@ public final class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager } /** - * Performs authorization and then delegates to either the {@link #authorizationSuccessHandler} - * or {@link #authorizationFailureHandler}, depending on the authorization result. - * + * Performs authorization and then delegates to either the + * {@link #authorizationSuccessHandler} or {@link #authorizationFailureHandler}, + * depending on the authorization result. * @param authorizationContext the context to authorize * @param principal the principle to authorize - * @return a {@link Mono} that emits the authorized client after the authorization attempt succeeds - * and the {@link #authorizationSuccessHandler} has completed, - * or completes with an exception after the authorization attempt fails - * and the {@link #authorizationFailureHandler} has completed + * @return a {@link Mono} that emits the authorized client after the authorization + * attempt succeeds and the {@link #authorizationSuccessHandler} has completed, or + * completes with an exception after the authorization attempt fails and the + * {@link #authorizationFailureHandler} has completed */ - private Mono authorize( - OAuth2AuthorizationContext authorizationContext, + private Mono authorize(OAuth2AuthorizationContext authorizationContext, Authentication principal) { return this.authorizedClientProvider.authorize(authorizationContext) - // Delegate to the authorizationSuccessHandler of the successful authorization - .flatMap(authorizedClient -> this.authorizationSuccessHandler.onAuthorizationSuccess( - authorizedClient, - principal, - Collections.emptyMap()) + // Delegate to the authorizationSuccessHandler of the successful + // authorization + .flatMap(authorizedClient -> this.authorizationSuccessHandler + .onAuthorizationSuccess(authorizedClient, principal, Collections.emptyMap()) .thenReturn(authorizedClient)) // Delegate to the authorizationFailureHandler of the failed authorization - .onErrorResume(OAuth2AuthorizationException.class, authorizationException -> this.authorizationFailureHandler.onAuthorizationFailure( - authorizationException, - principal, - Collections.emptyMap()) - .then(Mono.error(authorizationException))) + .onErrorResume(OAuth2AuthorizationException.class, + authorizationException -> this.authorizationFailureHandler + .onAuthorizationFailure(authorizationException, principal, Collections.emptyMap()) + .then(Mono.error(authorizationException))) .switchIfEmpty(Mono.defer(() -> Mono.justOrEmpty(authorizationContext.getAuthorizedClient()))); } /** - * Sets the {@link ReactiveOAuth2AuthorizedClientProvider} used for authorizing (or re-authorizing) an OAuth 2.0 Client. - * - * @param authorizedClientProvider the {@link ReactiveOAuth2AuthorizedClientProvider} used for authorizing (or re-authorizing) an OAuth 2.0 Client + * Sets the {@link ReactiveOAuth2AuthorizedClientProvider} used for authorizing (or + * re-authorizing) an OAuth 2.0 Client. + * @param authorizedClientProvider the {@link ReactiveOAuth2AuthorizedClientProvider} + * used for authorizing (or re-authorizing) an OAuth 2.0 Client */ public void setAuthorizedClientProvider(ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider) { Assert.notNull(authorizedClientProvider, "authorizedClientProvider cannot be null"); @@ -170,13 +186,15 @@ public final class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager } /** - * Sets the {@code Function} used for mapping attribute(s) from the {@link OAuth2AuthorizeRequest} to a {@code Map} of attributes - * to be associated to the {@link OAuth2AuthorizationContext#getAttributes() authorization context}. - * - * @param contextAttributesMapper the {@code Function} used for supplying the {@code Map} of attributes - * to the {@link OAuth2AuthorizationContext#getAttributes() authorization context} + * Sets the {@code Function} used for mapping attribute(s) from the + * {@link OAuth2AuthorizeRequest} to a {@code Map} of attributes to be associated to + * the {@link OAuth2AuthorizationContext#getAttributes() authorization context}. + * @param contextAttributesMapper the {@code Function} used for supplying the + * {@code Map} of attributes to the {@link OAuth2AuthorizationContext#getAttributes() + * authorization context} */ - public void setContextAttributesMapper(Function>> contextAttributesMapper) { + public void setContextAttributesMapper( + Function>> contextAttributesMapper) { Assert.notNull(contextAttributesMapper, "contextAttributesMapper cannot be null"); this.contextAttributesMapper = contextAttributesMapper; } @@ -184,9 +202,10 @@ public final class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager /** * Sets the handler that handles successful authorizations. * - * The default saves {@link OAuth2AuthorizedClient}s in the {@link ReactiveOAuth2AuthorizedClientService}. - * - * @param authorizationSuccessHandler the handler that handles successful authorizations. + * The default saves {@link OAuth2AuthorizedClient}s in the + * {@link ReactiveOAuth2AuthorizedClientService}. + * @param authorizationSuccessHandler the handler that handles successful + * authorizations. * @since 5.3 */ public void setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler authorizationSuccessHandler) { @@ -197,9 +216,10 @@ public final class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager /** * Sets the handler that handles authorization failures. * - *

        A {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} - * is used by default.

        - * + *

        + * A {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} is used + * by default. + *

        * @param authorizationFailureHandler the handler that handles authorization failures. * @see RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler * @since 5.3 @@ -210,16 +230,19 @@ public final class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager } /** - * The default implementation of the {@link #setContextAttributesMapper(Function) contextAttributesMapper}. + * The default implementation of the {@link #setContextAttributesMapper(Function) + * contextAttributesMapper}. */ - public static class DefaultContextAttributesMapper implements Function>> { + public static class DefaultContextAttributesMapper + implements Function>> { - private final AuthorizedClientServiceOAuth2AuthorizedClientManager.DefaultContextAttributesMapper mapper = - new AuthorizedClientServiceOAuth2AuthorizedClientManager.DefaultContextAttributesMapper(); + private final AuthorizedClientServiceOAuth2AuthorizedClientManager.DefaultContextAttributesMapper mapper = new AuthorizedClientServiceOAuth2AuthorizedClientManager.DefaultContextAttributesMapper(); @Override public Mono> apply(OAuth2AuthorizeRequest authorizeRequest) { return Mono.fromCallable(() -> mapper.apply(authorizeRequest)); } + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientAuthorizationException.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientAuthorizationException.java index 0cbd6ee2c8..c6010c504f 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientAuthorizationException.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientAuthorizationException.java @@ -20,8 +20,8 @@ import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.util.Assert; /** - * This exception is thrown on the client side when an attempt to authenticate - * or authorize an OAuth 2.0 client fails. + * This exception is thrown on the client side when an attempt to authenticate or + * authorize an OAuth 2.0 client fails. * * @author Phil Clay * @since 5.3 @@ -33,16 +33,15 @@ public class ClientAuthorizationException extends OAuth2AuthorizationException { /** * Constructs a {@code ClientAuthorizationException} using the provided parameters. - * * @param error the {@link OAuth2Error OAuth 2.0 Error} * @param clientRegistrationId the identifier for the client's registration */ public ClientAuthorizationException(OAuth2Error error, String clientRegistrationId) { this(error, clientRegistrationId, error.toString()); } + /** * Constructs a {@code ClientAuthorizationException} using the provided parameters. - * * @param error the {@link OAuth2Error OAuth 2.0 Error} * @param clientRegistrationId the identifier for the client's registration * @param message the exception message @@ -55,7 +54,6 @@ public class ClientAuthorizationException extends OAuth2AuthorizationException { /** * Constructs a {@code ClientAuthorizationException} using the provided parameters. - * * @param error the {@link OAuth2Error OAuth 2.0 Error} * @param clientRegistrationId the identifier for the client's registration * @param cause the root cause @@ -66,13 +64,13 @@ public class ClientAuthorizationException extends OAuth2AuthorizationException { /** * Constructs a {@code ClientAuthorizationException} using the provided parameters. - * * @param error the {@link OAuth2Error OAuth 2.0 Error} * @param clientRegistrationId the identifier for the client's registration * @param message the exception message * @param cause the root cause */ - public ClientAuthorizationException(OAuth2Error error, String clientRegistrationId, String message, Throwable cause) { + public ClientAuthorizationException(OAuth2Error error, String clientRegistrationId, String message, + Throwable cause) { super(error, message, cause); Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty"); this.clientRegistrationId = clientRegistrationId; @@ -80,10 +78,10 @@ public class ClientAuthorizationException extends OAuth2AuthorizationException { /** * Returns the identifier for the client's registration. - * * @return the identifier for the client's registration */ public String getClientRegistrationId() { return this.clientRegistrationId; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientAuthorizationRequiredException.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientAuthorizationRequiredException.java index d9b9e7a6a7..d951c99bc0 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientAuthorizationRequiredException.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientAuthorizationRequiredException.java @@ -18,19 +18,20 @@ package org.springframework.security.oauth2.client; import org.springframework.security.oauth2.core.OAuth2Error; /** - * This exception is thrown when an OAuth 2.0 Client is required - * to obtain authorization from the Resource Owner. + * This exception is thrown when an OAuth 2.0 Client is required to obtain authorization + * from the Resource Owner. * * @author Joe Grandja * @since 5.1 * @see OAuth2AuthorizedClient */ public class ClientAuthorizationRequiredException extends ClientAuthorizationException { + private static final String CLIENT_AUTHORIZATION_REQUIRED_ERROR_CODE = "client_authorization_required"; /** - * Constructs a {@code ClientAuthorizationRequiredException} using the provided parameters. - * + * Constructs a {@code ClientAuthorizationRequiredException} using the provided + * parameters. * @param clientRegistrationId the identifier for the client's registration */ public ClientAuthorizationRequiredException(String clientRegistrationId) { @@ -38,4 +39,5 @@ public class ClientAuthorizationRequiredException extends ClientAuthorizationExc "Authorization required for Client Registration Id: " + clientRegistrationId, null), clientRegistrationId); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientCredentialsOAuth2AuthorizedClientProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientCredentialsOAuth2AuthorizedClientProvider.java index ae5975d27f..20f5b318e1 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientCredentialsOAuth2AuthorizedClientProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientCredentialsOAuth2AuthorizedClientProvider.java @@ -31,8 +31,8 @@ import java.time.Duration; import java.time.Instant; /** - * An implementation of an {@link OAuth2AuthorizedClientProvider} - * for the {@link AuthorizationGrantType#CLIENT_CREDENTIALS client_credentials} grant. + * An implementation of an {@link OAuth2AuthorizedClientProvider} for the + * {@link AuthorizationGrantType#CLIENT_CREDENTIALS client_credentials} grant. * * @author Joe Grandja * @since 5.2 @@ -40,20 +40,24 @@ import java.time.Instant; * @see DefaultClientCredentialsTokenResponseClient */ public final class ClientCredentialsOAuth2AuthorizedClientProvider implements OAuth2AuthorizedClientProvider { - private OAuth2AccessTokenResponseClient accessTokenResponseClient = - new DefaultClientCredentialsTokenResponseClient(); + + private OAuth2AccessTokenResponseClient accessTokenResponseClient = new DefaultClientCredentialsTokenResponseClient(); + private Duration clockSkew = Duration.ofSeconds(60); + private Clock clock = Clock.systemUTC(); /** - * Attempt to authorize (or re-authorize) the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}. - * Returns {@code null} if authorization (or re-authorization) is not supported, - * e.g. the client's {@link ClientRegistration#getAuthorizationGrantType() authorization grant type} - * is not {@link AuthorizationGrantType#CLIENT_CREDENTIALS client_credentials} OR - * the {@link OAuth2AuthorizedClient#getAccessToken() access token} is not expired. - * + * Attempt to authorize (or re-authorize) the + * {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided + * {@code context}. Returns {@code null} if authorization (or re-authorization) is not + * supported, e.g. the client's {@link ClientRegistration#getAuthorizationGrantType() + * authorization grant type} is not {@link AuthorizationGrantType#CLIENT_CREDENTIALS + * client_credentials} OR the {@link OAuth2AuthorizedClient#getAccessToken() access + * token} is not expired. * @param context the context that holds authorization-specific state for the client - * @return the {@link OAuth2AuthorizedClient} or {@code null} if authorization (or re-authorization) is not supported + * @return the {@link OAuth2AuthorizedClient} or {@code null} if authorization (or + * re-authorization) is not supported */ @Override @Nullable @@ -67,7 +71,8 @@ public final class ClientCredentialsOAuth2AuthorizedClientProvider implements OA OAuth2AuthorizedClient authorizedClient = context.getAuthorizedClient(); if (authorizedClient != null && !hasTokenExpired(authorizedClient.getAccessToken())) { - // If client is already authorized but access token is NOT expired than no need for re-authorization + // If client is already authorized but access token is NOT expired than no + // need for re-authorization return null; } @@ -78,17 +83,19 @@ public final class ClientCredentialsOAuth2AuthorizedClientProvider implements OA // Therefore, renewing an expired access token (re-authorization) // is the same as acquiring a new access token (authorization). - OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = - new OAuth2ClientCredentialsGrantRequest(clientRegistration); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + clientRegistration); OAuth2AccessTokenResponse tokenResponse; try { tokenResponse = this.accessTokenResponseClient.getTokenResponse(clientCredentialsGrantRequest); - } catch (OAuth2AuthorizationException ex) { + } + catch (OAuth2AuthorizationException ex) { throw new ClientAuthorizationException(ex.getError(), clientRegistration.getRegistrationId(), ex); } - return new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), tokenResponse.getAccessToken()); + return new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), + tokenResponse.getAccessToken()); } private boolean hasTokenExpired(AbstractOAuth2Token token) { @@ -96,23 +103,26 @@ public final class ClientCredentialsOAuth2AuthorizedClientProvider implements OA } /** - * Sets the client used when requesting an access token credential at the Token Endpoint for the {@code client_credentials} grant. - * - * @param accessTokenResponseClient the client used when requesting an access token credential at the Token Endpoint for the {@code client_credentials} grant + * Sets the client used when requesting an access token credential at the Token + * Endpoint for the {@code client_credentials} grant. + * @param accessTokenResponseClient the client used when requesting an access token + * credential at the Token Endpoint for the {@code client_credentials} grant */ - public void setAccessTokenResponseClient(OAuth2AccessTokenResponseClient accessTokenResponseClient) { + public void setAccessTokenResponseClient( + OAuth2AccessTokenResponseClient accessTokenResponseClient) { Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null"); this.accessTokenResponseClient = accessTokenResponseClient; } /** * Sets the maximum acceptable clock skew, which is used when checking the - * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is 60 seconds. + * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is + * 60 seconds. * *

        - * An access token is considered expired if {@code OAuth2AccessToken#getExpiresAt() - clockSkew} - * is before the current time {@code clock#instant()}. - * + * An access token is considered expired if + * {@code OAuth2AccessToken#getExpiresAt() - clockSkew} is before the current time + * {@code clock#instant()}. * @param clockSkew the maximum acceptable clock skew */ public void setClockSkew(Duration clockSkew) { @@ -122,12 +132,13 @@ public final class ClientCredentialsOAuth2AuthorizedClientProvider implements OA } /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry. - * + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access + * token expiry. * @param clock the clock */ public void setClock(Clock clock) { Assert.notNull(clock, "clock cannot be null"); this.clock = clock; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientCredentialsReactiveOAuth2AuthorizedClientProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientCredentialsReactiveOAuth2AuthorizedClientProvider.java index 71835832cb..3b9cfc78c3 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientCredentialsReactiveOAuth2AuthorizedClientProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ClientCredentialsReactiveOAuth2AuthorizedClientProvider.java @@ -30,29 +30,34 @@ import java.time.Duration; import java.time.Instant; /** - * An implementation of a {@link ReactiveOAuth2AuthorizedClientProvider} - * for the {@link AuthorizationGrantType#CLIENT_CREDENTIALS client_credentials} grant. + * An implementation of a {@link ReactiveOAuth2AuthorizedClientProvider} for the + * {@link AuthorizationGrantType#CLIENT_CREDENTIALS client_credentials} grant. * * @author Joe Grandja * @since 5.2 * @see ReactiveOAuth2AuthorizedClientProvider * @see WebClientReactiveClientCredentialsTokenResponseClient */ -public final class ClientCredentialsReactiveOAuth2AuthorizedClientProvider implements ReactiveOAuth2AuthorizedClientProvider { - private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient = - new WebClientReactiveClientCredentialsTokenResponseClient(); +public final class ClientCredentialsReactiveOAuth2AuthorizedClientProvider + implements ReactiveOAuth2AuthorizedClientProvider { + + private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient = new WebClientReactiveClientCredentialsTokenResponseClient(); + private Duration clockSkew = Duration.ofSeconds(60); + private Clock clock = Clock.systemUTC(); /** - * Attempt to authorize (or re-authorize) the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}. - * Returns an empty {@code Mono} if authorization (or re-authorization) is not supported, - * e.g. the client's {@link ClientRegistration#getAuthorizationGrantType() authorization grant type} - * is not {@link AuthorizationGrantType#CLIENT_CREDENTIALS client_credentials} OR - * the {@link OAuth2AuthorizedClient#getAccessToken() access token} is not expired. - * + * Attempt to authorize (or re-authorize) the + * {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided + * {@code context}. Returns an empty {@code Mono} if authorization (or + * re-authorization) is not supported, e.g. the client's + * {@link ClientRegistration#getAuthorizationGrantType() authorization grant type} is + * not {@link AuthorizationGrantType#CLIENT_CREDENTIALS client_credentials} OR the + * {@link OAuth2AuthorizedClient#getAccessToken() access token} is not expired. * @param context the context that holds authorization-specific state for the client - * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if authorization (or re-authorization) is not supported + * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if + * authorization (or re-authorization) is not supported */ @Override public Mono authorize(OAuth2AuthorizationContext context) { @@ -65,7 +70,8 @@ public final class ClientCredentialsReactiveOAuth2AuthorizedClientProvider imple OAuth2AuthorizedClient authorizedClient = context.getAuthorizedClient(); if (authorizedClient != null && !hasTokenExpired(authorizedClient.getAccessToken())) { - // If client is already authorized but access token is NOT expired than no need for re-authorization + // If client is already authorized but access token is NOT expired than no + // need for re-authorization return Mono.empty(); } @@ -80,8 +86,8 @@ public final class ClientCredentialsReactiveOAuth2AuthorizedClientProvider imple .flatMap(this.accessTokenResponseClient::getTokenResponse) .onErrorMap(OAuth2AuthorizationException.class, e -> new ClientAuthorizationException(e.getError(), clientRegistration.getRegistrationId(), e)) - .map(tokenResponse -> new OAuth2AuthorizedClient( - clientRegistration, context.getPrincipal().getName(), tokenResponse.getAccessToken())); + .map(tokenResponse -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), + tokenResponse.getAccessToken())); } private boolean hasTokenExpired(AbstractOAuth2Token token) { @@ -89,23 +95,26 @@ public final class ClientCredentialsReactiveOAuth2AuthorizedClientProvider imple } /** - * Sets the client used when requesting an access token credential at the Token Endpoint for the {@code client_credentials} grant. - * - * @param accessTokenResponseClient the client used when requesting an access token credential at the Token Endpoint for the {@code client_credentials} grant + * Sets the client used when requesting an access token credential at the Token + * Endpoint for the {@code client_credentials} grant. + * @param accessTokenResponseClient the client used when requesting an access token + * credential at the Token Endpoint for the {@code client_credentials} grant */ - public void setAccessTokenResponseClient(ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient) { + public void setAccessTokenResponseClient( + ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient) { Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null"); this.accessTokenResponseClient = accessTokenResponseClient; } /** * Sets the maximum acceptable clock skew, which is used when checking the - * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is 60 seconds. + * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is + * 60 seconds. * *

        - * An access token is considered expired if {@code OAuth2AccessToken#getExpiresAt() - clockSkew} - * is before the current time {@code clock#instant()}. - * + * An access token is considered expired if + * {@code OAuth2AccessToken#getExpiresAt() - clockSkew} is before the current time + * {@code clock#instant()}. * @param clockSkew the maximum acceptable clock skew */ public void setClockSkew(Duration clockSkew) { @@ -115,12 +124,13 @@ public final class ClientCredentialsReactiveOAuth2AuthorizedClientProvider imple } /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry. - * + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access + * token expiry. * @param clock the clock */ public void setClock(Clock clock) { Assert.notNull(clock, "clock cannot be null"); this.clock = clock; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/DelegatingOAuth2AuthorizedClientProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/DelegatingOAuth2AuthorizedClientProvider.java index d57bcf8153..cd7148e25a 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/DelegatingOAuth2AuthorizedClientProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/DelegatingOAuth2AuthorizedClientProvider.java @@ -24,25 +24,27 @@ import java.util.Collections; import java.util.List; /** - * An implementation of an {@link OAuth2AuthorizedClientProvider} that simply delegates - * to it's internal {@code List} of {@link OAuth2AuthorizedClientProvider}(s). + * An implementation of an {@link OAuth2AuthorizedClientProvider} that simply delegates to + * it's internal {@code List} of {@link OAuth2AuthorizedClientProvider}(s). *

        * Each provider is given a chance to * {@link OAuth2AuthorizedClientProvider#authorize(OAuth2AuthorizationContext) authorize} - * the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided context - * with the first {@code non-null} {@link OAuth2AuthorizedClient} being returned. + * the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided + * context with the first {@code non-null} {@link OAuth2AuthorizedClient} being returned. * * @author Joe Grandja * @since 5.2 * @see OAuth2AuthorizedClientProvider */ public final class DelegatingOAuth2AuthorizedClientProvider implements OAuth2AuthorizedClientProvider { + private final List authorizedClientProviders; /** - * Constructs a {@code DelegatingOAuth2AuthorizedClientProvider} using the provided parameters. - * - * @param authorizedClientProviders a list of {@link OAuth2AuthorizedClientProvider}(s) + * Constructs a {@code DelegatingOAuth2AuthorizedClientProvider} using the provided + * parameters. + * @param authorizedClientProviders a list of + * {@link OAuth2AuthorizedClientProvider}(s) */ public DelegatingOAuth2AuthorizedClientProvider(OAuth2AuthorizedClientProvider... authorizedClientProviders) { Assert.notEmpty(authorizedClientProviders, "authorizedClientProviders cannot be empty"); @@ -50,9 +52,10 @@ public final class DelegatingOAuth2AuthorizedClientProvider implements OAuth2Aut } /** - * Constructs a {@code DelegatingOAuth2AuthorizedClientProvider} using the provided parameters. - * - * @param authorizedClientProviders a {@code List} of {@link OAuth2AuthorizedClientProvider}(s) + * Constructs a {@code DelegatingOAuth2AuthorizedClientProvider} using the provided + * parameters. + * @param authorizedClientProviders a {@code List} of + * {@link OAuth2AuthorizedClientProvider}(s) */ public DelegatingOAuth2AuthorizedClientProvider(List authorizedClientProviders) { Assert.notEmpty(authorizedClientProviders, "authorizedClientProviders cannot be empty"); @@ -71,4 +74,5 @@ public final class DelegatingOAuth2AuthorizedClientProvider implements OAuth2Aut } return null; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/DelegatingReactiveOAuth2AuthorizedClientProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/DelegatingReactiveOAuth2AuthorizedClientProvider.java index 1264d792c5..1d3c49e888 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/DelegatingReactiveOAuth2AuthorizedClientProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/DelegatingReactiveOAuth2AuthorizedClientProvider.java @@ -25,37 +25,44 @@ import java.util.Collections; import java.util.List; /** - * An implementation of a {@link ReactiveOAuth2AuthorizedClientProvider} that simply delegates - * to it's internal {@code List} of {@link ReactiveOAuth2AuthorizedClientProvider}(s). + * An implementation of a {@link ReactiveOAuth2AuthorizedClientProvider} that simply + * delegates to it's internal {@code List} of + * {@link ReactiveOAuth2AuthorizedClientProvider}(s). *

        * Each provider is given a chance to - * {@link ReactiveOAuth2AuthorizedClientProvider#authorize(OAuth2AuthorizationContext) authorize} - * the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided context - * with the first available {@link OAuth2AuthorizedClient} being returned. + * {@link ReactiveOAuth2AuthorizedClientProvider#authorize(OAuth2AuthorizationContext) + * authorize} the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the + * provided context with the first available {@link OAuth2AuthorizedClient} being + * returned. * * @author Joe Grandja * @since 5.2 * @see ReactiveOAuth2AuthorizedClientProvider */ public final class DelegatingReactiveOAuth2AuthorizedClientProvider implements ReactiveOAuth2AuthorizedClientProvider { + private final List authorizedClientProviders; /** - * Constructs a {@code DelegatingReactiveOAuth2AuthorizedClientProvider} using the provided parameters. - * - * @param authorizedClientProviders a list of {@link ReactiveOAuth2AuthorizedClientProvider}(s) + * Constructs a {@code DelegatingReactiveOAuth2AuthorizedClientProvider} using the + * provided parameters. + * @param authorizedClientProviders a list of + * {@link ReactiveOAuth2AuthorizedClientProvider}(s) */ - public DelegatingReactiveOAuth2AuthorizedClientProvider(ReactiveOAuth2AuthorizedClientProvider... authorizedClientProviders) { + public DelegatingReactiveOAuth2AuthorizedClientProvider( + ReactiveOAuth2AuthorizedClientProvider... authorizedClientProviders) { Assert.notEmpty(authorizedClientProviders, "authorizedClientProviders cannot be empty"); this.authorizedClientProviders = Collections.unmodifiableList(Arrays.asList(authorizedClientProviders)); } /** - * Constructs a {@code DelegatingReactiveOAuth2AuthorizedClientProvider} using the provided parameters. - * - * @param authorizedClientProviders a {@code List} of {@link OAuth2AuthorizedClientProvider}(s) + * Constructs a {@code DelegatingReactiveOAuth2AuthorizedClientProvider} using the + * provided parameters. + * @param authorizedClientProviders a {@code List} of + * {@link OAuth2AuthorizedClientProvider}(s) */ - public DelegatingReactiveOAuth2AuthorizedClientProvider(List authorizedClientProviders) { + public DelegatingReactiveOAuth2AuthorizedClientProvider( + List authorizedClientProviders) { Assert.notEmpty(authorizedClientProviders, "authorizedClientProviders cannot be empty"); this.authorizedClientProviders = Collections.unmodifiableList(new ArrayList<>(authorizedClientProviders)); } @@ -64,7 +71,7 @@ public final class DelegatingReactiveOAuth2AuthorizedClientProvider implements R public Mono authorize(OAuth2AuthorizationContext context) { Assert.notNull(context, "context cannot be null"); return Flux.fromIterable(this.authorizedClientProviders) - .concatMap(authorizedClientProvider -> authorizedClientProvider.authorize(context)) - .next(); + .concatMap(authorizedClientProvider -> authorizedClientProvider.authorize(context)).next(); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/InMemoryOAuth2AuthorizedClientService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/InMemoryOAuth2AuthorizedClientService.java index 2164b4ba1d..480a659dfe 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/InMemoryOAuth2AuthorizedClientService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/InMemoryOAuth2AuthorizedClientService.java @@ -24,8 +24,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** - * An {@link OAuth2AuthorizedClientService} that stores - * {@link OAuth2AuthorizedClient Authorized Client(s)} in-memory. + * An {@link OAuth2AuthorizedClientService} that stores {@link OAuth2AuthorizedClient + * Authorized Client(s)} in-memory. * * @author Joe Grandja * @author Vedran Pavic @@ -37,12 +37,14 @@ import java.util.concurrent.ConcurrentHashMap; * @see Authentication */ public final class InMemoryOAuth2AuthorizedClientService implements OAuth2AuthorizedClientService { + private final Map authorizedClients; + private final ClientRegistrationRepository clientRegistrationRepository; /** - * Constructs an {@code InMemoryOAuth2AuthorizedClientService} using the provided parameters. - * + * Constructs an {@code InMemoryOAuth2AuthorizedClientService} using the provided + * parameters. * @param clientRegistrationRepository the repository of client registrations */ public InMemoryOAuth2AuthorizedClientService(ClientRegistrationRepository clientRegistrationRepository) { @@ -52,14 +54,16 @@ public final class InMemoryOAuth2AuthorizedClientService implements OAuth2Author } /** - * Constructs an {@code InMemoryOAuth2AuthorizedClientService} using the provided parameters. + * Constructs an {@code InMemoryOAuth2AuthorizedClientService} using the provided + * parameters. * * @since 5.2 * @param clientRegistrationRepository the repository of client registrations - * @param authorizedClients the initial {@code Map} of authorized client(s) keyed by {@link OAuth2AuthorizedClientId} + * @param authorizedClients the initial {@code Map} of authorized client(s) keyed by + * {@link OAuth2AuthorizedClientId} */ public InMemoryOAuth2AuthorizedClientService(ClientRegistrationRepository clientRegistrationRepository, - Map authorizedClients) { + Map authorizedClients) { Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null"); Assert.notEmpty(authorizedClients, "authorizedClients cannot be empty"); this.clientRegistrationRepository = clientRegistrationRepository; @@ -68,7 +72,8 @@ public final class InMemoryOAuth2AuthorizedClientService implements OAuth2Author @Override @SuppressWarnings("unchecked") - public T loadAuthorizedClient(String clientRegistrationId, String principalName) { + public T loadAuthorizedClient(String clientRegistrationId, + String principalName) { Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty"); Assert.hasText(principalName, "principalName cannot be empty"); ClientRegistration registration = this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId); @@ -82,8 +87,8 @@ public final class InMemoryOAuth2AuthorizedClientService implements OAuth2Author public void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal) { Assert.notNull(authorizedClient, "authorizedClient cannot be null"); Assert.notNull(principal, "principal cannot be null"); - this.authorizedClients.put(new OAuth2AuthorizedClientId(authorizedClient.getClientRegistration().getRegistrationId(), - principal.getName()), authorizedClient); + this.authorizedClients.put(new OAuth2AuthorizedClientId( + authorizedClient.getClientRegistration().getRegistrationId(), principal.getName()), authorizedClient); } @Override @@ -95,4 +100,5 @@ public final class InMemoryOAuth2AuthorizedClientService implements OAuth2Author this.authorizedClients.remove(new OAuth2AuthorizedClientId(clientRegistrationId, principalName)); } } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/InMemoryReactiveOAuth2AuthorizedClientService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/InMemoryReactiveOAuth2AuthorizedClientService.java index 66091f8c90..4f58699305 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/InMemoryReactiveOAuth2AuthorizedClientService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/InMemoryReactiveOAuth2AuthorizedClientService.java @@ -25,8 +25,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** - * An {@link OAuth2AuthorizedClientService} that stores - * {@link OAuth2AuthorizedClient Authorized Client(s)} in-memory. + * An {@link OAuth2AuthorizedClientService} that stores {@link OAuth2AuthorizedClient + * Authorized Client(s)} in-memory. * * @author Rob Winch * @author Vedran Pavic @@ -37,22 +37,26 @@ import java.util.concurrent.ConcurrentHashMap; * @see Authentication */ public final class InMemoryReactiveOAuth2AuthorizedClientService implements ReactiveOAuth2AuthorizedClientService { + private final Map authorizedClients = new ConcurrentHashMap<>(); + private final ReactiveClientRegistrationRepository clientRegistrationRepository; /** - * Constructs an {@code InMemoryReactiveOAuth2AuthorizedClientService} using the provided parameters. - * + * Constructs an {@code InMemoryReactiveOAuth2AuthorizedClientService} using the + * provided parameters. * @param clientRegistrationRepository the repository of client registrations */ - public InMemoryReactiveOAuth2AuthorizedClientService(ReactiveClientRegistrationRepository clientRegistrationRepository) { + public InMemoryReactiveOAuth2AuthorizedClientService( + ReactiveClientRegistrationRepository clientRegistrationRepository) { Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null"); this.clientRegistrationRepository = clientRegistrationRepository; } @Override @SuppressWarnings("unchecked") - public Mono loadAuthorizedClient(String clientRegistrationId, String principalName) { + public Mono loadAuthorizedClient(String clientRegistrationId, + String principalName) { Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty"); Assert.hasText(principalName, "principalName cannot be empty"); return (Mono) this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId) @@ -77,7 +81,7 @@ public final class InMemoryReactiveOAuth2AuthorizedClientService implements Reac Assert.hasText(principalName, "principalName cannot be empty"); return this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId) .map(clientRegistration -> new OAuth2AuthorizedClientId(clientRegistrationId, principalName)) - .doOnNext(this.authorizedClients::remove) - .then(Mono.empty()); + .doOnNext(this.authorizedClients::remove).then(Mono.empty()); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/JdbcOAuth2AuthorizedClientService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/JdbcOAuth2AuthorizedClientService.java index cd3da393ac..05bc2405d9 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/JdbcOAuth2AuthorizedClientService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/JdbcOAuth2AuthorizedClientService.java @@ -44,13 +44,14 @@ import java.util.Set; import java.util.function.Function; /** - * A JDBC implementation of an {@link OAuth2AuthorizedClientService} - * that uses a {@link JdbcOperations} for {@link OAuth2AuthorizedClient} persistence. + * A JDBC implementation of an {@link OAuth2AuthorizedClientService} that uses a + * {@link JdbcOperations} for {@link OAuth2AuthorizedClient} persistence. * *

        * NOTE: This {@code OAuth2AuthorizedClientService} depends on the table definition - * described in "classpath:org/springframework/security/oauth2/client/oauth2-client-schema.sql" - * and therefore MUST be defined in the database schema. + * described in + * "classpath:org/springframework/security/oauth2/client/oauth2-client-schema.sql" and + * therefore MUST be defined in the database schema. * * @author Joe Grandja * @author Stav Shamir @@ -61,41 +62,42 @@ import java.util.function.Function; * @see RowMapper */ public class JdbcOAuth2AuthorizedClientService implements OAuth2AuthorizedClientService { - private static final String COLUMN_NAMES = - "client_registration_id, " + - "principal_name, " + - "access_token_type, " + - "access_token_value, " + - "access_token_issued_at, " + - "access_token_expires_at, " + - "access_token_scopes, " + - "refresh_token_value, " + - "refresh_token_issued_at"; + + private static final String COLUMN_NAMES = "client_registration_id, " + "principal_name, " + "access_token_type, " + + "access_token_value, " + "access_token_issued_at, " + "access_token_expires_at, " + + "access_token_scopes, " + "refresh_token_value, " + "refresh_token_issued_at"; + private static final String TABLE_NAME = "oauth2_authorized_client"; + private static final String PK_FILTER = "client_registration_id = ? AND principal_name = ?"; - private static final String LOAD_AUTHORIZED_CLIENT_SQL = "SELECT " + COLUMN_NAMES + - " FROM " + TABLE_NAME + " WHERE " + PK_FILTER; - private static final String SAVE_AUTHORIZED_CLIENT_SQL = "INSERT INTO " + TABLE_NAME + - " (" + COLUMN_NAMES + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; - private static final String REMOVE_AUTHORIZED_CLIENT_SQL = "DELETE FROM " + TABLE_NAME + - " WHERE " + PK_FILTER; - private static final String UPDATE_AUTHORIZED_CLIENT_SQL = "UPDATE " + TABLE_NAME + - " SET access_token_type = ?, access_token_value = ?, access_token_issued_at = ?," + - " access_token_expires_at = ?, access_token_scopes = ?," + - " refresh_token_value = ?, refresh_token_issued_at = ?" + - " WHERE " + PK_FILTER; + + private static final String LOAD_AUTHORIZED_CLIENT_SQL = "SELECT " + COLUMN_NAMES + " FROM " + TABLE_NAME + + " WHERE " + PK_FILTER; + + private static final String SAVE_AUTHORIZED_CLIENT_SQL = "INSERT INTO " + TABLE_NAME + " (" + COLUMN_NAMES + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + private static final String REMOVE_AUTHORIZED_CLIENT_SQL = "DELETE FROM " + TABLE_NAME + " WHERE " + PK_FILTER; + + private static final String UPDATE_AUTHORIZED_CLIENT_SQL = "UPDATE " + TABLE_NAME + + " SET access_token_type = ?, access_token_value = ?, access_token_issued_at = ?," + + " access_token_expires_at = ?, access_token_scopes = ?," + + " refresh_token_value = ?, refresh_token_issued_at = ?" + " WHERE " + PK_FILTER; + protected final JdbcOperations jdbcOperations; + protected RowMapper authorizedClientRowMapper; + protected Function> authorizedClientParametersMapper; /** - * Constructs a {@code JdbcOAuth2AuthorizedClientService} using the provided parameters. - * + * Constructs a {@code JdbcOAuth2AuthorizedClientService} using the provided + * parameters. * @param jdbcOperations the JDBC operations * @param clientRegistrationRepository the repository of client registrations */ - public JdbcOAuth2AuthorizedClientService( - JdbcOperations jdbcOperations, ClientRegistrationRepository clientRegistrationRepository) { + public JdbcOAuth2AuthorizedClientService(JdbcOperations jdbcOperations, + ClientRegistrationRepository clientRegistrationRepository) { Assert.notNull(jdbcOperations, "jdbcOperations cannot be null"); Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null"); @@ -106,18 +108,18 @@ public class JdbcOAuth2AuthorizedClientService implements OAuth2AuthorizedClient @Override @SuppressWarnings("unchecked") - public T loadAuthorizedClient(String clientRegistrationId, String principalName) { + public T loadAuthorizedClient(String clientRegistrationId, + String principalName) { Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty"); Assert.hasText(principalName, "principalName cannot be empty"); SqlParameterValue[] parameters = new SqlParameterValue[] { new SqlParameterValue(Types.VARCHAR, clientRegistrationId), - new SqlParameterValue(Types.VARCHAR, principalName) - }; + new SqlParameterValue(Types.VARCHAR, principalName) }; PreparedStatementSetter pss = new ArgumentPreparedStatementSetter(parameters); - List result = this.jdbcOperations.query( - LOAD_AUTHORIZED_CLIENT_SQL, pss, this.authorizedClientRowMapper); + List result = this.jdbcOperations.query(LOAD_AUTHORIZED_CLIENT_SQL, pss, + this.authorizedClientRowMapper); return !result.isEmpty() ? (T) result.get(0) : null; } @@ -132,18 +134,20 @@ public class JdbcOAuth2AuthorizedClientService implements OAuth2AuthorizedClient if (existsAuthorizedClient) { updateAuthorizedClient(authorizedClient, principal); - } else { + } + else { try { insertAuthorizedClient(authorizedClient, principal); - } catch (DuplicateKeyException e) { + } + catch (DuplicateKeyException e) { updateAuthorizedClient(authorizedClient, principal); } } } private void updateAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal) { - List parameters = this.authorizedClientParametersMapper.apply( - new OAuth2AuthorizedClientHolder(authorizedClient, principal)); + List parameters = this.authorizedClientParametersMapper + .apply(new OAuth2AuthorizedClientHolder(authorizedClient, principal)); SqlParameterValue clientRegistrationIdParameter = parameters.remove(0); SqlParameterValue principalNameParameter = parameters.remove(0); @@ -156,8 +160,8 @@ public class JdbcOAuth2AuthorizedClientService implements OAuth2AuthorizedClient } private void insertAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal) { - List parameters = this.authorizedClientParametersMapper.apply( - new OAuth2AuthorizedClientHolder(authorizedClient, principal)); + List parameters = this.authorizedClientParametersMapper + .apply(new OAuth2AuthorizedClientHolder(authorizedClient, principal)); PreparedStatementSetter pss = new ArgumentPreparedStatementSetter(parameters.toArray()); this.jdbcOperations.update(SAVE_AUTHORIZED_CLIENT_SQL, pss); @@ -170,18 +174,18 @@ public class JdbcOAuth2AuthorizedClientService implements OAuth2AuthorizedClient SqlParameterValue[] parameters = new SqlParameterValue[] { new SqlParameterValue(Types.VARCHAR, clientRegistrationId), - new SqlParameterValue(Types.VARCHAR, principalName) - }; + new SqlParameterValue(Types.VARCHAR, principalName) }; PreparedStatementSetter pss = new ArgumentPreparedStatementSetter(parameters); this.jdbcOperations.update(REMOVE_AUTHORIZED_CLIENT_SQL, pss); } /** - * Sets the {@link RowMapper} used for mapping the current row in {@code java.sql.ResultSet} to {@link OAuth2AuthorizedClient}. - * The default is {@link OAuth2AuthorizedClientRowMapper}. - * - * @param authorizedClientRowMapper the {@link RowMapper} used for mapping the current row in {@code java.sql.ResultSet} to {@link OAuth2AuthorizedClient} + * Sets the {@link RowMapper} used for mapping the current row in + * {@code java.sql.ResultSet} to {@link OAuth2AuthorizedClient}. The default is + * {@link OAuth2AuthorizedClientRowMapper}. + * @param authorizedClientRowMapper the {@link RowMapper} used for mapping the current + * row in {@code java.sql.ResultSet} to {@link OAuth2AuthorizedClient} */ public final void setAuthorizedClientRowMapper(RowMapper authorizedClientRowMapper) { Assert.notNull(authorizedClientRowMapper, "authorizedClientRowMapper cannot be null"); @@ -189,21 +193,24 @@ public class JdbcOAuth2AuthorizedClientService implements OAuth2AuthorizedClient } /** - * Sets the {@code Function} used for mapping {@link OAuth2AuthorizedClientHolder} to a {@code List} of {@link SqlParameterValue}. - * The default is {@link OAuth2AuthorizedClientParametersMapper}. - * - * @param authorizedClientParametersMapper the {@code Function} used for mapping {@link OAuth2AuthorizedClientHolder} to a {@code List} of {@link SqlParameterValue} + * Sets the {@code Function} used for mapping {@link OAuth2AuthorizedClientHolder} to + * a {@code List} of {@link SqlParameterValue}. The default is + * {@link OAuth2AuthorizedClientParametersMapper}. + * @param authorizedClientParametersMapper the {@code Function} used for mapping + * {@link OAuth2AuthorizedClientHolder} to a {@code List} of {@link SqlParameterValue} */ - public final void setAuthorizedClientParametersMapper(Function> authorizedClientParametersMapper) { + public final void setAuthorizedClientParametersMapper( + Function> authorizedClientParametersMapper) { Assert.notNull(authorizedClientParametersMapper, "authorizedClientParametersMapper cannot be null"); this.authorizedClientParametersMapper = authorizedClientParametersMapper; } /** - * The default {@link RowMapper} that maps the current row - * in {@code java.sql.ResultSet} to {@link OAuth2AuthorizedClient}. + * The default {@link RowMapper} that maps the current row in + * {@code java.sql.ResultSet} to {@link OAuth2AuthorizedClient}. */ public static class OAuth2AuthorizedClientRowMapper implements RowMapper { + protected final ClientRegistrationRepository clientRegistrationRepository; public OAuth2AuthorizedClientRowMapper(ClientRegistrationRepository clientRegistrationRepository) { @@ -214,17 +221,16 @@ public class JdbcOAuth2AuthorizedClientService implements OAuth2AuthorizedClient @Override public OAuth2AuthorizedClient mapRow(ResultSet rs, int rowNum) throws SQLException { String clientRegistrationId = rs.getString("client_registration_id"); - ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId( - clientRegistrationId); + ClientRegistration clientRegistration = this.clientRegistrationRepository + .findByRegistrationId(clientRegistrationId); if (clientRegistration == null) { - throw new DataRetrievalFailureException("The ClientRegistration with id '" + - clientRegistrationId + "' exists in the data source, " + - "however, it was not found in the ClientRegistrationRepository."); + throw new DataRetrievalFailureException( + "The ClientRegistration with id '" + clientRegistrationId + "' exists in the data source, " + + "however, it was not found in the ClientRegistrationRepository."); } OAuth2AccessToken.TokenType tokenType = null; - if (OAuth2AccessToken.TokenType.BEARER.getValue().equalsIgnoreCase( - rs.getString("access_token_type"))) { + if (OAuth2AccessToken.TokenType.BEARER.getValue().equalsIgnoreCase(rs.getString("access_token_type"))) { tokenType = OAuth2AccessToken.TokenType.BEARER; } String tokenValue = new String(rs.getBytes("access_token_value"), StandardCharsets.UTF_8); @@ -235,8 +241,7 @@ public class JdbcOAuth2AuthorizedClientService implements OAuth2AuthorizedClient if (accessTokenScopes != null) { scopes = StringUtils.commaDelimitedListToSet(accessTokenScopes); } - OAuth2AccessToken accessToken = new OAuth2AccessToken( - tokenType, tokenValue, issuedAt, expiresAt, scopes); + OAuth2AccessToken accessToken = new OAuth2AccessToken(tokenType, tokenValue, issuedAt, expiresAt, scopes); OAuth2RefreshToken refreshToken = null; byte[] refreshTokenValue = rs.getBytes("refresh_token_value"); @@ -252,16 +257,17 @@ public class JdbcOAuth2AuthorizedClientService implements OAuth2AuthorizedClient String principalName = rs.getString("principal_name"); - return new OAuth2AuthorizedClient( - clientRegistration, principalName, accessToken, refreshToken); + return new OAuth2AuthorizedClient(clientRegistration, principalName, accessToken, refreshToken); } + } /** - * The default {@code Function} that maps {@link OAuth2AuthorizedClientHolder} - * to a {@code List} of {@link SqlParameterValue}. + * The default {@code Function} that maps {@link OAuth2AuthorizedClientHolder} to a + * {@code List} of {@link SqlParameterValue}. */ - public static class OAuth2AuthorizedClientParametersMapper implements Function> { + public static class OAuth2AuthorizedClientParametersMapper + implements Function> { @Override public List apply(OAuth2AuthorizedClientHolder authorizedClientHolder) { @@ -272,24 +278,18 @@ public class JdbcOAuth2AuthorizedClientService implements OAuth2AuthorizedClient OAuth2RefreshToken refreshToken = authorizedClient.getRefreshToken(); List parameters = new ArrayList<>(); - parameters.add(new SqlParameterValue( - Types.VARCHAR, clientRegistration.getRegistrationId())); - parameters.add(new SqlParameterValue( - Types.VARCHAR, principal.getName())); - parameters.add(new SqlParameterValue( - Types.VARCHAR, accessToken.getTokenType().getValue())); - parameters.add(new SqlParameterValue( - Types.BLOB, accessToken.getTokenValue().getBytes(StandardCharsets.UTF_8))); - parameters.add(new SqlParameterValue( - Types.TIMESTAMP, Timestamp.from(accessToken.getIssuedAt()))); - parameters.add(new SqlParameterValue( - Types.TIMESTAMP, Timestamp.from(accessToken.getExpiresAt()))); + parameters.add(new SqlParameterValue(Types.VARCHAR, clientRegistration.getRegistrationId())); + parameters.add(new SqlParameterValue(Types.VARCHAR, principal.getName())); + parameters.add(new SqlParameterValue(Types.VARCHAR, accessToken.getTokenType().getValue())); + parameters.add( + new SqlParameterValue(Types.BLOB, accessToken.getTokenValue().getBytes(StandardCharsets.UTF_8))); + parameters.add(new SqlParameterValue(Types.TIMESTAMP, Timestamp.from(accessToken.getIssuedAt()))); + parameters.add(new SqlParameterValue(Types.TIMESTAMP, Timestamp.from(accessToken.getExpiresAt()))); String accessTokenScopes = null; if (!CollectionUtils.isEmpty(accessToken.getScopes())) { accessTokenScopes = StringUtils.collectionToDelimitedString(accessToken.getScopes(), ","); } - parameters.add(new SqlParameterValue( - Types.VARCHAR, accessTokenScopes)); + parameters.add(new SqlParameterValue(Types.VARCHAR, accessTokenScopes)); byte[] refreshTokenValue = null; Timestamp refreshTokenIssuedAt = null; if (refreshToken != null) { @@ -298,25 +298,27 @@ public class JdbcOAuth2AuthorizedClientService implements OAuth2AuthorizedClient refreshTokenIssuedAt = Timestamp.from(refreshToken.getIssuedAt()); } } - parameters.add(new SqlParameterValue( - Types.BLOB, refreshTokenValue)); - parameters.add(new SqlParameterValue( - Types.TIMESTAMP, refreshTokenIssuedAt)); + parameters.add(new SqlParameterValue(Types.BLOB, refreshTokenValue)); + parameters.add(new SqlParameterValue(Types.TIMESTAMP, refreshTokenIssuedAt)); return parameters; } + } /** - * A holder for an {@link OAuth2AuthorizedClient} and End-User {@link Authentication} (Resource Owner). + * A holder for an {@link OAuth2AuthorizedClient} and End-User {@link Authentication} + * (Resource Owner). */ public static final class OAuth2AuthorizedClientHolder { + private final OAuth2AuthorizedClient authorizedClient; + private final Authentication principal; /** - * Constructs an {@code OAuth2AuthorizedClientHolder} using the provided parameters. - * + * Constructs an {@code OAuth2AuthorizedClientHolder} using the provided + * parameters. * @param authorizedClient the authorized client * @param principal the End-User {@link Authentication} (Resource Owner) */ @@ -329,7 +331,6 @@ public class JdbcOAuth2AuthorizedClientService implements OAuth2AuthorizedClient /** * Returns the {@link OAuth2AuthorizedClient}. - * * @return the {@link OAuth2AuthorizedClient} */ public OAuth2AuthorizedClient getAuthorizedClient() { @@ -338,11 +339,12 @@ public class JdbcOAuth2AuthorizedClientService implements OAuth2AuthorizedClient /** * Returns the End-User {@link Authentication} (Resource Owner). - * * @return the End-User {@link Authentication} (Resource Owner) */ public Authentication getPrincipal() { return this.principal; } + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizationContext.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizationContext.java index 8bac099ae7..29fbf35c9c 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizationContext.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizationContext.java @@ -28,33 +28,43 @@ import java.util.Map; import java.util.function.Consumer; /** - * A context that holds authorization-specific state and is used by an {@link OAuth2AuthorizedClientProvider} - * when attempting to authorize (or re-authorize) an OAuth 2.0 Client. + * A context that holds authorization-specific state and is used by an + * {@link OAuth2AuthorizedClientProvider} when attempting to authorize (or re-authorize) + * an OAuth 2.0 Client. * * @author Joe Grandja * @since 5.2 * @see OAuth2AuthorizedClientProvider */ public final class OAuth2AuthorizationContext { - /** - * The name of the {@link #getAttribute(String) attribute} in the context associated to the value for the "request scope(s)". - * The value of the attribute is a {@code String[]} of scope(s) to be requested by the {@link #getClientRegistration() client}. - */ - public static final String REQUEST_SCOPE_ATTRIBUTE_NAME = OAuth2AuthorizationContext.class.getName().concat(".REQUEST_SCOPE"); /** - * The name of the {@link #getAttribute(String) attribute} in the context associated to the value for the resource owner's username. + * The name of the {@link #getAttribute(String) attribute} in the context associated + * to the value for the "request scope(s)". The value of the attribute is a + * {@code String[]} of scope(s) to be requested by the {@link #getClientRegistration() + * client}. + */ + public static final String REQUEST_SCOPE_ATTRIBUTE_NAME = OAuth2AuthorizationContext.class.getName() + .concat(".REQUEST_SCOPE"); + + /** + * The name of the {@link #getAttribute(String) attribute} in the context associated + * to the value for the resource owner's username. */ public static final String USERNAME_ATTRIBUTE_NAME = OAuth2AuthorizationContext.class.getName().concat(".USERNAME"); /** - * The name of the {@link #getAttribute(String) attribute} in the context associated to the value for the resource owner's password. + * The name of the {@link #getAttribute(String) attribute} in the context associated + * to the value for the resource owner's password. */ public static final String PASSWORD_ATTRIBUTE_NAME = OAuth2AuthorizationContext.class.getName().concat(".PASSWORD"); private ClientRegistration clientRegistration; + private OAuth2AuthorizedClient authorizedClient; + private Authentication principal; + private Map attributes; private OAuth2AuthorizationContext() { @@ -62,7 +72,6 @@ public final class OAuth2AuthorizationContext { /** * Returns the {@link ClientRegistration client registration}. - * * @return the {@link ClientRegistration} */ public ClientRegistration getClientRegistration() { @@ -70,10 +79,11 @@ public final class OAuth2AuthorizationContext { } /** - * Returns the {@link OAuth2AuthorizedClient authorized client} or {@code null} - * if the {@link #withClientRegistration(ClientRegistration) client registration} was supplied. - * - * @return the {@link OAuth2AuthorizedClient} or {@code null} if the client registration was supplied + * Returns the {@link OAuth2AuthorizedClient authorized client} or {@code null} if the + * {@link #withClientRegistration(ClientRegistration) client registration} was + * supplied. + * @return the {@link OAuth2AuthorizedClient} or {@code null} if the client + * registration was supplied */ @Nullable public OAuth2AuthorizedClient getAuthorizedClient() { @@ -82,7 +92,6 @@ public final class OAuth2AuthorizationContext { /** * Returns the {@code Principal} (to be) associated to the authorized client. - * * @return the {@code Principal} (to be) associated to the authorized client */ public Authentication getPrincipal() { @@ -91,7 +100,6 @@ public final class OAuth2AuthorizationContext { /** * Returns the attributes associated to the context. - * * @return a {@code Map} of the attributes associated to the context */ public Map getAttributes() { @@ -99,8 +107,8 @@ public final class OAuth2AuthorizationContext { } /** - * Returns the value of an attribute associated to the context or {@code null} if not available. - * + * Returns the value of an attribute associated to the context or {@code null} if not + * available. * @param name the name of the attribute * @param the type of the attribute * @return the value of the attribute associated to the context @@ -113,7 +121,6 @@ public final class OAuth2AuthorizationContext { /** * Returns a new {@link Builder} initialized with the {@link ClientRegistration}. - * * @param clientRegistration the {@link ClientRegistration client registration} * @return the {@link Builder} */ @@ -123,7 +130,6 @@ public final class OAuth2AuthorizationContext { /** * Returns a new {@link Builder} initialized with the {@link OAuth2AuthorizedClient}. - * * @param authorizedClient the {@link OAuth2AuthorizedClient authorized client} * @return the {@link Builder} */ @@ -135,9 +141,13 @@ public final class OAuth2AuthorizationContext { * A builder for {@link OAuth2AuthorizationContext}. */ public static class Builder { + private ClientRegistration clientRegistration; + private OAuth2AuthorizedClient authorizedClient; + private Authentication principal; + private Map attributes; private Builder(ClientRegistration clientRegistration) { @@ -152,8 +162,8 @@ public final class OAuth2AuthorizationContext { /** * Sets the {@code Principal} (to be) associated to the authorized client. - * - * @param principal the {@code Principal} (to be) associated to the authorized client + * @param principal the {@code Principal} (to be) associated to the authorized + * client * @return the {@link Builder} */ public Builder principal(Authentication principal) { @@ -163,8 +173,8 @@ public final class OAuth2AuthorizationContext { /** * Provides a {@link Consumer} access to the attributes associated to the context. - * - * @param attributesConsumer a {@link Consumer} of the attributes associated to the context + * @param attributesConsumer a {@link Consumer} of the attributes associated to + * the context * @return the {@link OAuth2AuthorizeRequest.Builder} */ public Builder attributes(Consumer> attributesConsumer) { @@ -177,7 +187,6 @@ public final class OAuth2AuthorizationContext { /** * Sets an attribute associated to the context. - * * @param name the name of the attribute * @param value the value of the attribute * @return the {@link Builder} @@ -192,7 +201,6 @@ public final class OAuth2AuthorizationContext { /** * Builds a new {@link OAuth2AuthorizationContext}. - * * @return a {@link OAuth2AuthorizationContext} */ public OAuth2AuthorizationContext build() { @@ -201,14 +209,16 @@ public final class OAuth2AuthorizationContext { if (this.authorizedClient != null) { context.clientRegistration = this.authorizedClient.getClientRegistration(); context.authorizedClient = this.authorizedClient; - } else { + } + else { context.clientRegistration = this.clientRegistration; } context.principal = this.principal; - context.attributes = Collections.unmodifiableMap( - CollectionUtils.isEmpty(this.attributes) ? - Collections.emptyMap() : new LinkedHashMap<>(this.attributes)); + context.attributes = Collections.unmodifiableMap(CollectionUtils.isEmpty(this.attributes) + ? Collections.emptyMap() : new LinkedHashMap<>(this.attributes)); return context; } + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizationFailureHandler.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizationFailureHandler.java index c24141d8b4..7ddbecf503 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizationFailureHandler.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizationFailureHandler.java @@ -21,8 +21,8 @@ import org.springframework.security.oauth2.core.OAuth2AuthorizationException; import java.util.Map; /** - * Handles when an OAuth 2.0 Client fails to authorize (or re-authorize) - * via the Authorization Server or Resource Server. + * Handles when an OAuth 2.0 Client fails to authorize (or re-authorize) via the + * Authorization Server or Resource Server. * * @author Joe Grandja * @since 5.3 @@ -33,16 +33,17 @@ import java.util.Map; public interface OAuth2AuthorizationFailureHandler { /** - * Called when an OAuth 2.0 Client fails to authorize (or re-authorize) - * via the Authorization Server or Resource Server. - * + * Called when an OAuth 2.0 Client fails to authorize (or re-authorize) via the + * Authorization Server or Resource Server. * @param authorizationException the exception that contains details about what failed * @param principal the {@code Principal} associated with the attempted authorization - * @param attributes an immutable {@code Map} of (optional) attributes present under certain conditions. - * For example, this might contain a {@code javax.servlet.http.HttpServletRequest} - * and {@code javax.servlet.http.HttpServletResponse} if the authorization was performed - * within the context of a {@code javax.servlet.ServletContext}. + * @param attributes an immutable {@code Map} of (optional) attributes present under + * certain conditions. For example, this might contain a + * {@code javax.servlet.http.HttpServletRequest} and + * {@code javax.servlet.http.HttpServletResponse} if the authorization was performed + * within the context of a {@code javax.servlet.ServletContext}. */ - void onAuthorizationFailure(OAuth2AuthorizationException authorizationException, - Authentication principal, Map attributes); + void onAuthorizationFailure(OAuth2AuthorizationException authorizationException, Authentication principal, + Map attributes); + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizationSuccessHandler.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizationSuccessHandler.java index b350924ab5..c49129e26a 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizationSuccessHandler.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizationSuccessHandler.java @@ -20,8 +20,8 @@ import org.springframework.security.core.Authentication; import java.util.Map; /** - * Handles when an OAuth 2.0 Client has been successfully - * authorized (or re-authorized) via the Authorization Server. + * Handles when an OAuth 2.0 Client has been successfully authorized (or re-authorized) + * via the Authorization Server. * * @author Joe Grandja * @since 5.3 @@ -32,16 +32,18 @@ import java.util.Map; public interface OAuth2AuthorizationSuccessHandler { /** - * Called when an OAuth 2.0 Client has been successfully - * authorized (or re-authorized) via the Authorization Server. - * - * @param authorizedClient the client that was successfully authorized (or re-authorized) + * Called when an OAuth 2.0 Client has been successfully authorized (or re-authorized) + * via the Authorization Server. + * @param authorizedClient the client that was successfully authorized (or + * re-authorized) * @param principal the {@code Principal} associated with the authorized client - * @param attributes an immutable {@code Map} of (optional) attributes present under certain conditions. - * For example, this might contain a {@code javax.servlet.http.HttpServletRequest} - * and {@code javax.servlet.http.HttpServletResponse} if the authorization was performed - * within the context of a {@code javax.servlet.ServletContext}. + * @param attributes an immutable {@code Map} of (optional) attributes present under + * certain conditions. For example, this might contain a + * {@code javax.servlet.http.HttpServletRequest} and + * {@code javax.servlet.http.HttpServletResponse} if the authorization was performed + * within the context of a {@code javax.servlet.ServletContext}. */ - void onAuthorizationSuccess(OAuth2AuthorizedClient authorizedClient, - Authentication principal, Map attributes); + void onAuthorizationSuccess(OAuth2AuthorizedClient authorizedClient, Authentication principal, + Map attributes); + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizeRequest.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizeRequest.java index a8aa973e2a..4520b2628e 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizeRequest.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizeRequest.java @@ -30,17 +30,22 @@ import java.util.function.Consumer; /** * Represents a request the {@link OAuth2AuthorizedClientManager} uses to - * {@link OAuth2AuthorizedClientManager#authorize(OAuth2AuthorizeRequest) authorize} (or re-authorize) - * the {@link ClientRegistration client} identified by the provided {@link #getClientRegistrationId() clientRegistrationId}. + * {@link OAuth2AuthorizedClientManager#authorize(OAuth2AuthorizeRequest) authorize} (or + * re-authorize) the {@link ClientRegistration client} identified by the provided + * {@link #getClientRegistrationId() clientRegistrationId}. * * @author Joe Grandja * @since 5.2 * @see OAuth2AuthorizedClientManager */ public final class OAuth2AuthorizeRequest { + private String clientRegistrationId; + private OAuth2AuthorizedClient authorizedClient; + private Authentication principal; + private Map attributes; private OAuth2AuthorizeRequest() { @@ -48,7 +53,6 @@ public final class OAuth2AuthorizeRequest { /** * Returns the identifier for the {@link ClientRegistration client registration}. - * * @return the identifier for the client registration */ public String getClientRegistrationId() { @@ -56,8 +60,8 @@ public final class OAuth2AuthorizeRequest { } /** - * Returns the {@link OAuth2AuthorizedClient authorized client} or {@code null} if it was not provided. - * + * Returns the {@link OAuth2AuthorizedClient authorized client} or {@code null} if it + * was not provided. * @return the {@link OAuth2AuthorizedClient} or {@code null} if it was not provided */ @Nullable @@ -67,7 +71,6 @@ public final class OAuth2AuthorizeRequest { /** * Returns the {@code Principal} (to be) associated to the authorized client. - * * @return the {@code Principal} (to be) associated to the authorized client */ public Authentication getPrincipal() { @@ -76,7 +79,6 @@ public final class OAuth2AuthorizeRequest { /** * Returns the attributes associated to the request. - * * @return a {@code Map} of the attributes associated to the request */ public Map getAttributes() { @@ -84,8 +86,8 @@ public final class OAuth2AuthorizeRequest { } /** - * Returns the value of an attribute associated to the request or {@code null} if not available. - * + * Returns the value of an attribute associated to the request or {@code null} if not + * available. * @param name the name of the attribute * @param the type of the attribute * @return the value of the attribute associated to the request @@ -97,9 +99,10 @@ public final class OAuth2AuthorizeRequest { } /** - * Returns a new {@link Builder} initialized with the identifier for the {@link ClientRegistration client registration}. - * - * @param clientRegistrationId the identifier for the {@link ClientRegistration client registration} + * Returns a new {@link Builder} initialized with the identifier for the + * {@link ClientRegistration client registration}. + * @param clientRegistrationId the identifier for the {@link ClientRegistration client + * registration} * @return the {@link Builder} */ public static Builder withClientRegistrationId(String clientRegistrationId) { @@ -107,8 +110,8 @@ public final class OAuth2AuthorizeRequest { } /** - * Returns a new {@link Builder} initialized with the {@link OAuth2AuthorizedClient authorized client}. - * + * Returns a new {@link Builder} initialized with the {@link OAuth2AuthorizedClient + * authorized client}. * @param authorizedClient the {@link OAuth2AuthorizedClient authorized client} * @return the {@link Builder} */ @@ -120,9 +123,13 @@ public final class OAuth2AuthorizeRequest { * A builder for {@link OAuth2AuthorizeRequest}. */ public static class Builder { + private String clientRegistrationId; + private OAuth2AuthorizedClient authorizedClient; + private Authentication principal; + private Map attributes; private Builder(String clientRegistrationId) { @@ -136,10 +143,12 @@ public final class OAuth2AuthorizeRequest { } /** - * Sets the name of the {@code Principal} (to be) associated to the authorized client. + * Sets the name of the {@code Principal} (to be) associated to the authorized + * client. * * @since 5.3 - * @param principalName the name of the {@code Principal} (to be) associated to the authorized client + * @param principalName the name of the {@code Principal} (to be) associated to + * the authorized client * @return the {@link Builder} */ public Builder principal(String principalName) { @@ -164,8 +173,8 @@ public final class OAuth2AuthorizeRequest { /** * Sets the {@code Principal} (to be) associated to the authorized client. - * - * @param principal the {@code Principal} (to be) associated to the authorized client + * @param principal the {@code Principal} (to be) associated to the authorized + * client * @return the {@link Builder} */ public Builder principal(Authentication principal) { @@ -175,8 +184,8 @@ public final class OAuth2AuthorizeRequest { /** * Provides a {@link Consumer} access to the attributes associated to the request. - * - * @param attributesConsumer a {@link Consumer} of the attributes associated to the request + * @param attributesConsumer a {@link Consumer} of the attributes associated to + * the request * @return the {@link Builder} */ public Builder attributes(Consumer> attributesConsumer) { @@ -189,7 +198,6 @@ public final class OAuth2AuthorizeRequest { /** * Sets an attribute associated to the request. - * * @param name the name of the attribute * @param value the value of the attribute * @return the {@link Builder} @@ -204,23 +212,25 @@ public final class OAuth2AuthorizeRequest { /** * Builds a new {@link OAuth2AuthorizeRequest}. - * * @return a {@link OAuth2AuthorizeRequest} */ public OAuth2AuthorizeRequest build() { Assert.notNull(this.principal, "principal cannot be null"); OAuth2AuthorizeRequest authorizeRequest = new OAuth2AuthorizeRequest(); if (this.authorizedClient != null) { - authorizeRequest.clientRegistrationId = this.authorizedClient.getClientRegistration().getRegistrationId(); + authorizeRequest.clientRegistrationId = this.authorizedClient.getClientRegistration() + .getRegistrationId(); authorizeRequest.authorizedClient = this.authorizedClient; - } else { + } + else { authorizeRequest.clientRegistrationId = this.clientRegistrationId; } authorizeRequest.principal = this.principal; - authorizeRequest.attributes = Collections.unmodifiableMap( - CollectionUtils.isEmpty(this.attributes) ? - Collections.emptyMap() : new LinkedHashMap<>(this.attributes)); + authorizeRequest.attributes = Collections.unmodifiableMap(CollectionUtils.isEmpty(this.attributes) + ? Collections.emptyMap() : new LinkedHashMap<>(this.attributes)); return authorizeRequest; } + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClient.java index e45fd060e6..04fa5b8cd1 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClient.java @@ -27,12 +27,12 @@ import java.io.Serializable; /** * A representation of an OAuth 2.0 "Authorized Client". *

        - * A client is considered "authorized" when the End-User (Resource Owner) - * has granted authorization to the client to access it's protected resources. + * A client is considered "authorized" when the End-User (Resource Owner) has + * granted authorization to the client to access it's protected resources. *

        - * This class associates the {@link #getClientRegistration() Client} - * to the {@link #getAccessToken() Access Token} - * granted/authorized by the {@link #getPrincipalName() Resource Owner}. + * This class associates the {@link #getClientRegistration() Client} to the + * {@link #getAccessToken() Access Token} granted/authorized by the + * {@link #getPrincipalName() Resource Owner}. * * @author Joe Grandja * @since 5.0 @@ -41,33 +41,37 @@ import java.io.Serializable; * @see OAuth2RefreshToken */ public class OAuth2AuthorizedClient implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private final ClientRegistration clientRegistration; + private final String principalName; + private final OAuth2AccessToken accessToken; + private final OAuth2RefreshToken refreshToken; /** * Constructs an {@code OAuth2AuthorizedClient} using the provided parameters. - * * @param clientRegistration the authorized client's registration * @param principalName the name of the End-User {@code Principal} (Resource Owner) * @param accessToken the access token credential granted */ - public OAuth2AuthorizedClient(ClientRegistration clientRegistration, String principalName, OAuth2AccessToken accessToken) { + public OAuth2AuthorizedClient(ClientRegistration clientRegistration, String principalName, + OAuth2AccessToken accessToken) { this(clientRegistration, principalName, accessToken, null); } /** * Constructs an {@code OAuth2AuthorizedClient} using the provided parameters. - * * @param clientRegistration the authorized client's registration * @param principalName the name of the End-User {@code Principal} (Resource Owner) * @param accessToken the access token credential granted * @param refreshToken the refresh token credential granted */ public OAuth2AuthorizedClient(ClientRegistration clientRegistration, String principalName, - OAuth2AccessToken accessToken, @Nullable OAuth2RefreshToken refreshToken) { + OAuth2AccessToken accessToken, @Nullable OAuth2RefreshToken refreshToken) { Assert.notNull(clientRegistration, "clientRegistration cannot be null"); Assert.hasText(principalName, "principalName cannot be empty"); Assert.notNull(accessToken, "accessToken cannot be null"); @@ -79,7 +83,6 @@ public class OAuth2AuthorizedClient implements Serializable { /** * Returns the authorized client's {@link ClientRegistration registration}. - * * @return the {@link ClientRegistration} */ public ClientRegistration getClientRegistration() { @@ -88,7 +91,6 @@ public class OAuth2AuthorizedClient implements Serializable { /** * Returns the End-User's {@code Principal} name. - * * @return the End-User's {@code Principal} name */ public String getPrincipalName() { @@ -97,7 +99,6 @@ public class OAuth2AuthorizedClient implements Serializable { /** * Returns the {@link OAuth2AccessToken access token} credential granted. - * * @return the {@link OAuth2AccessToken} */ public OAuth2AccessToken getAccessToken() { @@ -113,4 +114,5 @@ public class OAuth2AuthorizedClient implements Serializable { public @Nullable OAuth2RefreshToken getRefreshToken() { return this.refreshToken; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientId.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientId.java index 3c0cb7d40d..e36da1fa5e 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientId.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientId.java @@ -30,13 +30,15 @@ import java.util.Objects; * @see OAuth2AuthorizedClientService */ public final class OAuth2AuthorizedClientId implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private final String clientRegistrationId; + private final String principalName; /** * Constructs an {@code OAuth2AuthorizedClientId} using the provided parameters. - * * @param clientRegistrationId the identifier for the client's registration * @param principalName the name of the End-User {@code Principal} (Resource Owner) */ @@ -64,4 +66,5 @@ public final class OAuth2AuthorizedClientId implements Serializable { public int hashCode() { return Objects.hash(this.clientRegistrationId, this.principalName); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientManager.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientManager.java index d8c0f1d3a1..4133fe8f6e 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientManager.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientManager.java @@ -20,16 +20,16 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; /** - * Implementations of this interface are responsible for the overall management - * of {@link OAuth2AuthorizedClient Authorized Client(s)}. + * Implementations of this interface are responsible for the overall management of + * {@link OAuth2AuthorizedClient Authorized Client(s)}. * *

        * The primary responsibilities include: *

          - *
        1. Authorizing (or re-authorizing) an OAuth 2.0 Client - * by leveraging an {@link OAuth2AuthorizedClientProvider}(s).
        2. - *
        3. Delegating the persistence of an {@link OAuth2AuthorizedClient}, - * typically using an {@link OAuth2AuthorizedClientService} OR {@link OAuth2AuthorizedClientRepository}.
        4. + *
        5. Authorizing (or re-authorizing) an OAuth 2.0 Client by leveraging an + * {@link OAuth2AuthorizedClientProvider}(s).
        6. + *
        7. Delegating the persistence of an {@link OAuth2AuthorizedClient}, typically using an + * {@link OAuth2AuthorizedClientService} OR {@link OAuth2AuthorizedClientRepository}.
        8. *
        * * @author Joe Grandja @@ -43,20 +43,23 @@ import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepo public interface OAuth2AuthorizedClientManager { /** - * Attempt to authorize or re-authorize (if required) the {@link ClientRegistration client} - * identified by the provided {@link OAuth2AuthorizeRequest#getClientRegistrationId() clientRegistrationId}. - * Implementations must return {@code null} if authorization is not supported for the specified client, - * e.g. the associated {@link OAuth2AuthorizedClientProvider}(s) does not support - * the {@link ClientRegistration#getAuthorizationGrantType() authorization grant} type configured for the client. + * Attempt to authorize or re-authorize (if required) the {@link ClientRegistration + * client} identified by the provided + * {@link OAuth2AuthorizeRequest#getClientRegistrationId() clientRegistrationId}. + * Implementations must return {@code null} if authorization is not supported for the + * specified client, e.g. the associated {@link OAuth2AuthorizedClientProvider}(s) + * does not support the {@link ClientRegistration#getAuthorizationGrantType() + * authorization grant} type configured for the client. * *

        - * In the case of re-authorization, implementations must return the provided {@link OAuth2AuthorizeRequest#getAuthorizedClient() authorized client} - * if re-authorization is not supported for the client OR is not required, - * e.g. a {@link OAuth2AuthorizedClient#getRefreshToken() refresh token} is not available OR + * In the case of re-authorization, implementations must return the provided + * {@link OAuth2AuthorizeRequest#getAuthorizedClient() authorized client} if + * re-authorization is not supported for the client OR is not required, e.g. a + * {@link OAuth2AuthorizedClient#getRefreshToken() refresh token} is not available OR * the {@link OAuth2AuthorizedClient#getAccessToken() access token} is not expired. - * * @param authorizeRequest the authorize request - * @return the {@link OAuth2AuthorizedClient} or {@code null} if authorization is not supported for the specified client + * @return the {@link OAuth2AuthorizedClient} or {@code null} if authorization is not + * supported for the specified client */ @Nullable OAuth2AuthorizedClient authorize(OAuth2AuthorizeRequest authorizeRequest); diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProvider.java index ad96f4a985..d6f055c777 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProvider.java @@ -20,25 +20,30 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio import org.springframework.security.oauth2.core.AuthorizationGrantType; /** - * A strategy for authorizing (or re-authorizing) an OAuth 2.0 Client. - * Implementations will typically implement a specific {@link AuthorizationGrantType authorization grant} type. + * A strategy for authorizing (or re-authorizing) an OAuth 2.0 Client. Implementations + * will typically implement a specific {@link AuthorizationGrantType authorization grant} + * type. * * @author Joe Grandja * @since 5.2 * @see OAuth2AuthorizedClient * @see OAuth2AuthorizationContext - * @see Section 1.3 Authorization Grant + * @see Section + * 1.3 Authorization Grant */ @FunctionalInterface public interface OAuth2AuthorizedClientProvider { /** - * Attempt to authorize (or re-authorize) the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided context. - * Implementations must return {@code null} if authorization is not supported for the specified client, - * e.g. the provider doesn't support the {@link ClientRegistration#getAuthorizationGrantType() authorization grant} type configured for the client. - * + * Attempt to authorize (or re-authorize) the + * {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided + * context. Implementations must return {@code null} if authorization is not supported + * for the specified client, e.g. the provider doesn't support the + * {@link ClientRegistration#getAuthorizationGrantType() authorization grant} type + * configured for the client. * @param context the context that holds authorization-specific state for the client - * @return the {@link OAuth2AuthorizedClient} or {@code null} if authorization is not supported for the specified client + * @return the {@link OAuth2AuthorizedClient} or {@code null} if authorization is not + * supported for the specified client */ @Nullable OAuth2AuthorizedClient authorize(OAuth2AuthorizationContext context); diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProviderBuilder.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProviderBuilder.java index 7d02a4efcc..375eacffb3 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProviderBuilder.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProviderBuilder.java @@ -32,11 +32,11 @@ import java.util.function.Consumer; /** * A builder that builds a {@link DelegatingOAuth2AuthorizedClientProvider} composed of - * one or more {@link OAuth2AuthorizedClientProvider}(s) that implement specific authorization grants. - * The supported authorization grants are {@link #authorizationCode() authorization_code}, - * {@link #refreshToken() refresh_token}, {@link #clientCredentials() client_credentials} - * and {@link #password() password}. - * In addition to the standard authorization grants, an implementation of an extension grant + * one or more {@link OAuth2AuthorizedClientProvider}(s) that implement specific + * authorization grants. The supported authorization grants are + * {@link #authorizationCode() authorization_code}, {@link #refreshToken() refresh_token}, + * {@link #clientCredentials() client_credentials} and {@link #password() password}. In + * addition to the standard authorization grants, an implementation of an extension grant * may be supplied via {@link #provider(OAuth2AuthorizedClientProvider)}. * * @author Joe Grandja @@ -49,14 +49,15 @@ import java.util.function.Consumer; * @see DelegatingOAuth2AuthorizedClientProvider */ public final class OAuth2AuthorizedClientProviderBuilder { + private final Map, Builder> builders = new LinkedHashMap<>(); private OAuth2AuthorizedClientProviderBuilder() { } /** - * Returns a new {@link OAuth2AuthorizedClientProviderBuilder} for configuring the supported authorization grant(s). - * + * Returns a new {@link OAuth2AuthorizedClientProviderBuilder} for configuring the + * supported authorization grant(s). * @return the {@link OAuth2AuthorizedClientProviderBuilder} */ public static OAuth2AuthorizedClientProviderBuilder builder() { @@ -64,9 +65,9 @@ public final class OAuth2AuthorizedClientProviderBuilder { } /** - * Configures an {@link OAuth2AuthorizedClientProvider} to be composed with the {@link DelegatingOAuth2AuthorizedClientProvider}. - * This may be used for implementations of extension authorization grants. - * + * Configures an {@link OAuth2AuthorizedClientProvider} to be composed with the + * {@link DelegatingOAuth2AuthorizedClientProvider}. This may be used for + * implementations of extension authorization grants. * @return the {@link OAuth2AuthorizedClientProviderBuilder} */ public OAuth2AuthorizedClientProviderBuilder provider(OAuth2AuthorizedClientProvider provider) { @@ -77,11 +78,11 @@ public final class OAuth2AuthorizedClientProviderBuilder { /** * Configures support for the {@code authorization_code} grant. - * * @return the {@link OAuth2AuthorizedClientProviderBuilder} */ public OAuth2AuthorizedClientProviderBuilder authorizationCode() { - this.builders.computeIfAbsent(AuthorizationCodeOAuth2AuthorizedClientProvider.class, k -> new AuthorizationCodeGrantBuilder()); + this.builders.computeIfAbsent(AuthorizationCodeOAuth2AuthorizedClientProvider.class, + k -> new AuthorizationCodeGrantBuilder()); return OAuth2AuthorizedClientProviderBuilder.this; } @@ -95,34 +96,34 @@ public final class OAuth2AuthorizedClientProviderBuilder { /** * Builds an instance of {@link AuthorizationCodeOAuth2AuthorizedClientProvider}. - * * @return the {@link AuthorizationCodeOAuth2AuthorizedClientProvider} */ @Override public OAuth2AuthorizedClientProvider build() { return new AuthorizationCodeOAuth2AuthorizedClientProvider(); } + } /** * Configures support for the {@code refresh_token} grant. - * * @return the {@link OAuth2AuthorizedClientProviderBuilder} */ public OAuth2AuthorizedClientProviderBuilder refreshToken() { - this.builders.computeIfAbsent(RefreshTokenOAuth2AuthorizedClientProvider.class, k -> new RefreshTokenGrantBuilder()); + this.builders.computeIfAbsent(RefreshTokenOAuth2AuthorizedClientProvider.class, + k -> new RefreshTokenGrantBuilder()); return OAuth2AuthorizedClientProviderBuilder.this; } /** * Configures support for the {@code refresh_token} grant. - * - * @param builderConsumer a {@code Consumer} of {@link RefreshTokenGrantBuilder} used for further configuration + * @param builderConsumer a {@code Consumer} of {@link RefreshTokenGrantBuilder} used + * for further configuration * @return the {@link OAuth2AuthorizedClientProviderBuilder} */ public OAuth2AuthorizedClientProviderBuilder refreshToken(Consumer builderConsumer) { - RefreshTokenGrantBuilder builder = (RefreshTokenGrantBuilder) this.builders.computeIfAbsent( - RefreshTokenOAuth2AuthorizedClientProvider.class, k -> new RefreshTokenGrantBuilder()); + RefreshTokenGrantBuilder builder = (RefreshTokenGrantBuilder) this.builders + .computeIfAbsent(RefreshTokenOAuth2AuthorizedClientProvider.class, k -> new RefreshTokenGrantBuilder()); builderConsumer.accept(builder); return OAuth2AuthorizedClientProviderBuilder.this; } @@ -131,28 +132,33 @@ public final class OAuth2AuthorizedClientProviderBuilder { * A builder for the {@code refresh_token} grant. */ public class RefreshTokenGrantBuilder implements Builder { + private OAuth2AccessTokenResponseClient accessTokenResponseClient; + private Duration clockSkew; + private Clock clock; private RefreshTokenGrantBuilder() { } /** - * Sets the client used when requesting an access token credential at the Token Endpoint. - * - * @param accessTokenResponseClient the client used when requesting an access token credential at the Token Endpoint + * Sets the client used when requesting an access token credential at the Token + * Endpoint. + * @param accessTokenResponseClient the client used when requesting an access + * token credential at the Token Endpoint * @return the {@link RefreshTokenGrantBuilder} */ - public RefreshTokenGrantBuilder accessTokenResponseClient(OAuth2AccessTokenResponseClient accessTokenResponseClient) { + public RefreshTokenGrantBuilder accessTokenResponseClient( + OAuth2AccessTokenResponseClient accessTokenResponseClient) { this.accessTokenResponseClient = accessTokenResponseClient; return this; } /** - * Sets the maximum acceptable clock skew, which is used when checking the access token expiry. - * An access token is considered expired if it's before {@code Instant.now(this.clock) - clockSkew}. - * + * Sets the maximum acceptable clock skew, which is used when checking the access + * token expiry. An access token is considered expired if it's before + * {@code Instant.now(this.clock) - clockSkew}. * @param clockSkew the maximum acceptable clock skew * @return the {@link RefreshTokenGrantBuilder} */ @@ -162,8 +168,8 @@ public final class OAuth2AuthorizedClientProviderBuilder { } /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry. - * + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the + * access token expiry. * @param clock the clock * @return the {@link RefreshTokenGrantBuilder} */ @@ -174,7 +180,6 @@ public final class OAuth2AuthorizedClientProviderBuilder { /** * Builds an instance of {@link RefreshTokenOAuth2AuthorizedClientProvider}. - * * @return the {@link RefreshTokenOAuth2AuthorizedClientProvider} */ @Override @@ -191,25 +196,27 @@ public final class OAuth2AuthorizedClientProviderBuilder { } return authorizedClientProvider; } + } /** * Configures support for the {@code client_credentials} grant. - * * @return the {@link OAuth2AuthorizedClientProviderBuilder} */ public OAuth2AuthorizedClientProviderBuilder clientCredentials() { - this.builders.computeIfAbsent(ClientCredentialsOAuth2AuthorizedClientProvider.class, k -> new ClientCredentialsGrantBuilder()); + this.builders.computeIfAbsent(ClientCredentialsOAuth2AuthorizedClientProvider.class, + k -> new ClientCredentialsGrantBuilder()); return OAuth2AuthorizedClientProviderBuilder.this; } /** * Configures support for the {@code client_credentials} grant. - * - * @param builderConsumer a {@code Consumer} of {@link ClientCredentialsGrantBuilder} used for further configuration + * @param builderConsumer a {@code Consumer} of {@link ClientCredentialsGrantBuilder} + * used for further configuration * @return the {@link OAuth2AuthorizedClientProviderBuilder} */ - public OAuth2AuthorizedClientProviderBuilder clientCredentials(Consumer builderConsumer) { + public OAuth2AuthorizedClientProviderBuilder clientCredentials( + Consumer builderConsumer) { ClientCredentialsGrantBuilder builder = (ClientCredentialsGrantBuilder) this.builders.computeIfAbsent( ClientCredentialsOAuth2AuthorizedClientProvider.class, k -> new ClientCredentialsGrantBuilder()); builderConsumer.accept(builder); @@ -220,28 +227,33 @@ public final class OAuth2AuthorizedClientProviderBuilder { * A builder for the {@code client_credentials} grant. */ public class ClientCredentialsGrantBuilder implements Builder { + private OAuth2AccessTokenResponseClient accessTokenResponseClient; + private Duration clockSkew; + private Clock clock; private ClientCredentialsGrantBuilder() { } /** - * Sets the client used when requesting an access token credential at the Token Endpoint. - * - * @param accessTokenResponseClient the client used when requesting an access token credential at the Token Endpoint + * Sets the client used when requesting an access token credential at the Token + * Endpoint. + * @param accessTokenResponseClient the client used when requesting an access + * token credential at the Token Endpoint * @return the {@link ClientCredentialsGrantBuilder} */ - public ClientCredentialsGrantBuilder accessTokenResponseClient(OAuth2AccessTokenResponseClient accessTokenResponseClient) { + public ClientCredentialsGrantBuilder accessTokenResponseClient( + OAuth2AccessTokenResponseClient accessTokenResponseClient) { this.accessTokenResponseClient = accessTokenResponseClient; return this; } /** - * Sets the maximum acceptable clock skew, which is used when checking the access token expiry. - * An access token is considered expired if it's before {@code Instant.now(this.clock) - clockSkew}. - * + * Sets the maximum acceptable clock skew, which is used when checking the access + * token expiry. An access token is considered expired if it's before + * {@code Instant.now(this.clock) - clockSkew}. * @param clockSkew the maximum acceptable clock skew * @return the {@link ClientCredentialsGrantBuilder} */ @@ -251,8 +263,8 @@ public final class OAuth2AuthorizedClientProviderBuilder { } /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry. - * + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the + * access token expiry. * @param clock the clock * @return the {@link ClientCredentialsGrantBuilder} */ @@ -263,7 +275,6 @@ public final class OAuth2AuthorizedClientProviderBuilder { /** * Builds an instance of {@link ClientCredentialsOAuth2AuthorizedClientProvider}. - * * @return the {@link ClientCredentialsOAuth2AuthorizedClientProvider} */ @Override @@ -280,11 +291,11 @@ public final class OAuth2AuthorizedClientProviderBuilder { } return authorizedClientProvider; } + } /** * Configures support for the {@code password} grant. - * * @return the {@link OAuth2AuthorizedClientProviderBuilder} */ public OAuth2AuthorizedClientProviderBuilder password() { @@ -294,13 +305,13 @@ public final class OAuth2AuthorizedClientProviderBuilder { /** * Configures support for the {@code password} grant. - * - * @param builderConsumer a {@code Consumer} of {@link PasswordGrantBuilder} used for further configuration + * @param builderConsumer a {@code Consumer} of {@link PasswordGrantBuilder} used for + * further configuration * @return the {@link OAuth2AuthorizedClientProviderBuilder} */ public OAuth2AuthorizedClientProviderBuilder password(Consumer builderConsumer) { - PasswordGrantBuilder builder = (PasswordGrantBuilder) this.builders.computeIfAbsent( - PasswordOAuth2AuthorizedClientProvider.class, k -> new PasswordGrantBuilder()); + PasswordGrantBuilder builder = (PasswordGrantBuilder) this.builders + .computeIfAbsent(PasswordOAuth2AuthorizedClientProvider.class, k -> new PasswordGrantBuilder()); builderConsumer.accept(builder); return OAuth2AuthorizedClientProviderBuilder.this; } @@ -309,28 +320,33 @@ public final class OAuth2AuthorizedClientProviderBuilder { * A builder for the {@code password} grant. */ public class PasswordGrantBuilder implements Builder { + private OAuth2AccessTokenResponseClient accessTokenResponseClient; + private Duration clockSkew; + private Clock clock; private PasswordGrantBuilder() { } /** - * Sets the client used when requesting an access token credential at the Token Endpoint. - * - * @param accessTokenResponseClient the client used when requesting an access token credential at the Token Endpoint + * Sets the client used when requesting an access token credential at the Token + * Endpoint. + * @param accessTokenResponseClient the client used when requesting an access + * token credential at the Token Endpoint * @return the {@link PasswordGrantBuilder} */ - public PasswordGrantBuilder accessTokenResponseClient(OAuth2AccessTokenResponseClient accessTokenResponseClient) { + public PasswordGrantBuilder accessTokenResponseClient( + OAuth2AccessTokenResponseClient accessTokenResponseClient) { this.accessTokenResponseClient = accessTokenResponseClient; return this; } /** - * Sets the maximum acceptable clock skew, which is used when checking the access token expiry. - * An access token is considered expired if it's before {@code Instant.now(this.clock) - clockSkew}. - * + * Sets the maximum acceptable clock skew, which is used when checking the access + * token expiry. An access token is considered expired if it's before + * {@code Instant.now(this.clock) - clockSkew}. * @param clockSkew the maximum acceptable clock skew * @return the {@link PasswordGrantBuilder} */ @@ -340,8 +356,8 @@ public final class OAuth2AuthorizedClientProviderBuilder { } /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry. - * + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the + * access token expiry. * @param clock the clock * @return the {@link PasswordGrantBuilder} */ @@ -352,7 +368,6 @@ public final class OAuth2AuthorizedClientProviderBuilder { /** * Builds an instance of {@link PasswordOAuth2AuthorizedClientProvider}. - * * @return the {@link PasswordOAuth2AuthorizedClientProvider} */ @Override @@ -369,12 +384,12 @@ public final class OAuth2AuthorizedClientProviderBuilder { } return authorizedClientProvider; } + } /** - * Builds an instance of {@link DelegatingOAuth2AuthorizedClientProvider} - * composed of one or more {@link OAuth2AuthorizedClientProvider}(s). - * + * Builds an instance of {@link DelegatingOAuth2AuthorizedClientProvider} composed of + * one or more {@link OAuth2AuthorizedClientProvider}(s). * @return the {@link DelegatingOAuth2AuthorizedClientProvider} */ public OAuth2AuthorizedClientProvider build() { @@ -386,6 +401,9 @@ public final class OAuth2AuthorizedClientProviderBuilder { } interface Builder { + OAuth2AuthorizedClientProvider build(); + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientService.java index 4a275287dd..47786cde16 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientService.java @@ -20,12 +20,12 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio import org.springframework.security.oauth2.core.OAuth2AccessToken; /** - * Implementations of this interface are responsible for the management - * of {@link OAuth2AuthorizedClient Authorized Client(s)}, which provide the purpose - * of associating an {@link OAuth2AuthorizedClient#getAccessToken() Access Token} credential + * Implementations of this interface are responsible for the management of + * {@link OAuth2AuthorizedClient Authorized Client(s)}, which provide the purpose of + * associating an {@link OAuth2AuthorizedClient#getAccessToken() Access Token} credential * to a {@link OAuth2AuthorizedClient#getClientRegistration() Client} and Resource Owner, - * who is the {@link OAuth2AuthorizedClient#getPrincipalName() Principal} - * that originally granted the authorization. + * who is the {@link OAuth2AuthorizedClient#getPrincipalName() Principal} that originally + * granted the authorization. * * @author Joe Grandja * @since 5.0 @@ -37,10 +37,9 @@ import org.springframework.security.oauth2.core.OAuth2AccessToken; public interface OAuth2AuthorizedClientService { /** - * Returns the {@link OAuth2AuthorizedClient} associated to the - * provided client registration identifier and End-User's {@code Principal} name - * or {@code null} if not available. - * + * Returns the {@link OAuth2AuthorizedClient} associated to the provided client + * registration identifier and End-User's {@code Principal} name or {@code null} if + * not available. * @param clientRegistrationId the identifier for the client's registration * @param principalName the name of the End-User {@code Principal} (Resource Owner) * @param a type of OAuth2AuthorizedClient @@ -49,18 +48,16 @@ public interface OAuth2AuthorizedClientService { T loadAuthorizedClient(String clientRegistrationId, String principalName); /** - * Saves the {@link OAuth2AuthorizedClient} associating it to - * the provided End-User {@link Authentication} (Resource Owner). - * + * Saves the {@link OAuth2AuthorizedClient} associating it to the provided End-User + * {@link Authentication} (Resource Owner). * @param authorizedClient the authorized client * @param principal the End-User {@link Authentication} (Resource Owner) */ void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal); /** - * Removes the {@link OAuth2AuthorizedClient} associated to the - * provided client registration identifier and End-User's {@code Principal} name. - * + * Removes the {@link OAuth2AuthorizedClient} associated to the provided client + * registration identifier and End-User's {@code Principal} name. * @param clientRegistrationId the identifier for the client's registration * @param principalName the name of the End-User {@code Principal} (Resource Owner) */ diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/PasswordOAuth2AuthorizedClientProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/PasswordOAuth2AuthorizedClientProvider.java index e40522a7e5..921f588031 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/PasswordOAuth2AuthorizedClientProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/PasswordOAuth2AuthorizedClientProvider.java @@ -32,8 +32,8 @@ import java.time.Duration; import java.time.Instant; /** - * An implementation of an {@link OAuth2AuthorizedClientProvider} - * for the {@link AuthorizationGrantType#PASSWORD password} grant. + * An implementation of an {@link OAuth2AuthorizedClientProvider} for the + * {@link AuthorizationGrantType#PASSWORD password} grant. * * @author Joe Grandja * @since 5.2 @@ -41,30 +41,36 @@ import java.time.Instant; * @see DefaultPasswordTokenResponseClient */ public final class PasswordOAuth2AuthorizedClientProvider implements OAuth2AuthorizedClientProvider { - private OAuth2AccessTokenResponseClient accessTokenResponseClient = - new DefaultPasswordTokenResponseClient(); + + private OAuth2AccessTokenResponseClient accessTokenResponseClient = new DefaultPasswordTokenResponseClient(); + private Duration clockSkew = Duration.ofSeconds(60); + private Clock clock = Clock.systemUTC(); /** - * Attempt to authorize (or re-authorize) the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}. - * Returns {@code null} if authorization (or re-authorization) is not supported, - * e.g. the client's {@link ClientRegistration#getAuthorizationGrantType() authorization grant type} - * is not {@link AuthorizationGrantType#PASSWORD password} OR - * the {@link OAuth2AuthorizationContext#USERNAME_ATTRIBUTE_NAME username} and/or - * {@link OAuth2AuthorizationContext#PASSWORD_ATTRIBUTE_NAME password} attributes - * are not available in the provided {@code context} OR - * the {@link OAuth2AuthorizedClient#getAccessToken() access token} is not expired. + * Attempt to authorize (or re-authorize) the + * {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided + * {@code context}. Returns {@code null} if authorization (or re-authorization) is not + * supported, e.g. the client's {@link ClientRegistration#getAuthorizationGrantType() + * authorization grant type} is not {@link AuthorizationGrantType#PASSWORD password} + * OR the {@link OAuth2AuthorizationContext#USERNAME_ATTRIBUTE_NAME username} and/or + * {@link OAuth2AuthorizationContext#PASSWORD_ATTRIBUTE_NAME password} attributes are + * not available in the provided {@code context} OR the + * {@link OAuth2AuthorizedClient#getAccessToken() access token} is not expired. * *

        - * The following {@link OAuth2AuthorizationContext#getAttributes() context attributes} are supported: + * The following {@link OAuth2AuthorizationContext#getAttributes() context attributes} + * are supported: *

          - *
        1. {@link OAuth2AuthorizationContext#USERNAME_ATTRIBUTE_NAME} (required) - a {@code String} value for the resource owner's username
        2. - *
        3. {@link OAuth2AuthorizationContext#PASSWORD_ATTRIBUTE_NAME} (required) - a {@code String} value for the resource owner's password
        4. + *
        5. {@link OAuth2AuthorizationContext#USERNAME_ATTRIBUTE_NAME} (required) - a + * {@code String} value for the resource owner's username
        6. + *
        7. {@link OAuth2AuthorizationContext#PASSWORD_ATTRIBUTE_NAME} (required) - a + * {@code String} value for the resource owner's password
        8. *
        - * * @param context the context that holds authorization-specific state for the client - * @return the {@link OAuth2AuthorizedClient} or {@code null} if authorization (or re-authorization) is not supported + * @return the {@link OAuth2AuthorizedClient} or {@code null} if authorization (or + * re-authorization) is not supported */ @Override @Nullable @@ -85,23 +91,28 @@ public final class PasswordOAuth2AuthorizedClientProvider implements OAuth2Autho } if (authorizedClient != null && !hasTokenExpired(authorizedClient.getAccessToken())) { - // If client is already authorized and access token is NOT expired than no need for re-authorization + // If client is already authorized and access token is NOT expired than no + // need for re-authorization return null; } - if (authorizedClient != null && hasTokenExpired(authorizedClient.getAccessToken()) && authorizedClient.getRefreshToken() != null) { - // If client is already authorized and access token is expired and a refresh token is available, - // than return and allow RefreshTokenOAuth2AuthorizedClientProvider to handle the refresh + if (authorizedClient != null && hasTokenExpired(authorizedClient.getAccessToken()) + && authorizedClient.getRefreshToken() != null) { + // If client is already authorized and access token is expired and a refresh + // token is available, + // than return and allow RefreshTokenOAuth2AuthorizedClientProvider to handle + // the refresh return null; } - OAuth2PasswordGrantRequest passwordGrantRequest = - new OAuth2PasswordGrantRequest(clientRegistration, username, password); + OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest(clientRegistration, username, + password); OAuth2AccessTokenResponse tokenResponse; try { tokenResponse = this.accessTokenResponseClient.getTokenResponse(passwordGrantRequest); - } catch (OAuth2AuthorizationException ex) { + } + catch (OAuth2AuthorizationException ex) { throw new ClientAuthorizationException(ex.getError(), clientRegistration.getRegistrationId(), ex); } @@ -114,23 +125,26 @@ public final class PasswordOAuth2AuthorizedClientProvider implements OAuth2Autho } /** - * Sets the client used when requesting an access token credential at the Token Endpoint for the {@code password} grant. - * - * @param accessTokenResponseClient the client used when requesting an access token credential at the Token Endpoint for the {@code password} grant + * Sets the client used when requesting an access token credential at the Token + * Endpoint for the {@code password} grant. + * @param accessTokenResponseClient the client used when requesting an access token + * credential at the Token Endpoint for the {@code password} grant */ - public void setAccessTokenResponseClient(OAuth2AccessTokenResponseClient accessTokenResponseClient) { + public void setAccessTokenResponseClient( + OAuth2AccessTokenResponseClient accessTokenResponseClient) { Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null"); this.accessTokenResponseClient = accessTokenResponseClient; } /** * Sets the maximum acceptable clock skew, which is used when checking the - * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is 60 seconds. + * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is + * 60 seconds. * *

        - * An access token is considered expired if {@code OAuth2AccessToken#getExpiresAt() - clockSkew} - * is before the current time {@code clock#instant()}. - * + * An access token is considered expired if + * {@code OAuth2AccessToken#getExpiresAt() - clockSkew} is before the current time + * {@code clock#instant()}. * @param clockSkew the maximum acceptable clock skew */ public void setClockSkew(Duration clockSkew) { @@ -140,12 +154,13 @@ public final class PasswordOAuth2AuthorizedClientProvider implements OAuth2Autho } /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry. - * + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access + * token expiry. * @param clock the clock */ public void setClock(Clock clock) { Assert.notNull(clock, "clock cannot be null"); this.clock = clock; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/PasswordReactiveOAuth2AuthorizedClientProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/PasswordReactiveOAuth2AuthorizedClientProvider.java index 971170aef6..b4ad2e52a8 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/PasswordReactiveOAuth2AuthorizedClientProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/PasswordReactiveOAuth2AuthorizedClientProvider.java @@ -31,8 +31,8 @@ import java.time.Duration; import java.time.Instant; /** - * An implementation of a {@link ReactiveOAuth2AuthorizedClientProvider} - * for the {@link AuthorizationGrantType#PASSWORD password} grant. + * An implementation of a {@link ReactiveOAuth2AuthorizedClientProvider} for the + * {@link AuthorizationGrantType#PASSWORD password} grant. * * @author Joe Grandja * @since 5.2 @@ -40,30 +40,37 @@ import java.time.Instant; * @see WebClientReactivePasswordTokenResponseClient */ public final class PasswordReactiveOAuth2AuthorizedClientProvider implements ReactiveOAuth2AuthorizedClientProvider { - private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient = - new WebClientReactivePasswordTokenResponseClient(); + + private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient = new WebClientReactivePasswordTokenResponseClient(); + private Duration clockSkew = Duration.ofSeconds(60); + private Clock clock = Clock.systemUTC(); /** - * Attempt to authorize (or re-authorize) the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}. - * Returns an empty {@code Mono} if authorization (or re-authorization) is not supported, - * e.g. the client's {@link ClientRegistration#getAuthorizationGrantType() authorization grant type} - * is not {@link AuthorizationGrantType#PASSWORD password} OR - * the {@link OAuth2AuthorizationContext#USERNAME_ATTRIBUTE_NAME username} and/or - * {@link OAuth2AuthorizationContext#PASSWORD_ATTRIBUTE_NAME password} attributes - * are not available in the provided {@code context} OR - * the {@link OAuth2AuthorizedClient#getAccessToken() access token} is not expired. + * Attempt to authorize (or re-authorize) the + * {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided + * {@code context}. Returns an empty {@code Mono} if authorization (or + * re-authorization) is not supported, e.g. the client's + * {@link ClientRegistration#getAuthorizationGrantType() authorization grant type} is + * not {@link AuthorizationGrantType#PASSWORD password} OR the + * {@link OAuth2AuthorizationContext#USERNAME_ATTRIBUTE_NAME username} and/or + * {@link OAuth2AuthorizationContext#PASSWORD_ATTRIBUTE_NAME password} attributes are + * not available in the provided {@code context} OR the + * {@link OAuth2AuthorizedClient#getAccessToken() access token} is not expired. * *

        - * The following {@link OAuth2AuthorizationContext#getAttributes() context attributes} are supported: + * The following {@link OAuth2AuthorizationContext#getAttributes() context attributes} + * are supported: *

          - *
        1. {@link OAuth2AuthorizationContext#USERNAME_ATTRIBUTE_NAME} (required) - a {@code String} value for the resource owner's username
        2. - *
        3. {@link OAuth2AuthorizationContext#PASSWORD_ATTRIBUTE_NAME} (required) - a {@code String} value for the resource owner's password
        4. + *
        5. {@link OAuth2AuthorizationContext#USERNAME_ATTRIBUTE_NAME} (required) - a + * {@code String} value for the resource owner's username
        6. + *
        7. {@link OAuth2AuthorizationContext#PASSWORD_ATTRIBUTE_NAME} (required) - a + * {@code String} value for the resource owner's password
        8. *
        - * * @param context the context that holds authorization-specific state for the client - * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if authorization (or re-authorization) is not supported + * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if + * authorization (or re-authorization) is not supported */ @Override public Mono authorize(OAuth2AuthorizationContext context) { @@ -83,21 +90,24 @@ public final class PasswordReactiveOAuth2AuthorizedClientProvider implements Rea } if (authorizedClient != null && !hasTokenExpired(authorizedClient.getAccessToken())) { - // If client is already authorized and access token is NOT expired than no need for re-authorization + // If client is already authorized and access token is NOT expired than no + // need for re-authorization return Mono.empty(); } - if (authorizedClient != null && hasTokenExpired(authorizedClient.getAccessToken()) && authorizedClient.getRefreshToken() != null) { - // If client is already authorized and access token is expired and a refresh token is available, - // than return and allow RefreshTokenReactiveOAuth2AuthorizedClientProvider to handle the refresh + if (authorizedClient != null && hasTokenExpired(authorizedClient.getAccessToken()) + && authorizedClient.getRefreshToken() != null) { + // If client is already authorized and access token is expired and a refresh + // token is available, + // than return and allow RefreshTokenReactiveOAuth2AuthorizedClientProvider to + // handle the refresh return Mono.empty(); } - OAuth2PasswordGrantRequest passwordGrantRequest = - new OAuth2PasswordGrantRequest(clientRegistration, username, password); + OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest(clientRegistration, username, + password); - return Mono.just(passwordGrantRequest) - .flatMap(this.accessTokenResponseClient::getTokenResponse) + return Mono.just(passwordGrantRequest).flatMap(this.accessTokenResponseClient::getTokenResponse) .onErrorMap(OAuth2AuthorizationException.class, e -> new ClientAuthorizationException(e.getError(), clientRegistration.getRegistrationId(), e)) .map(tokenResponse -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), @@ -109,23 +119,26 @@ public final class PasswordReactiveOAuth2AuthorizedClientProvider implements Rea } /** - * Sets the client used when requesting an access token credential at the Token Endpoint for the {@code password} grant. - * - * @param accessTokenResponseClient the client used when requesting an access token credential at the Token Endpoint for the {@code password} grant + * Sets the client used when requesting an access token credential at the Token + * Endpoint for the {@code password} grant. + * @param accessTokenResponseClient the client used when requesting an access token + * credential at the Token Endpoint for the {@code password} grant */ - public void setAccessTokenResponseClient(ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient) { + public void setAccessTokenResponseClient( + ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient) { Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null"); this.accessTokenResponseClient = accessTokenResponseClient; } /** * Sets the maximum acceptable clock skew, which is used when checking the - * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is 60 seconds. + * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is + * 60 seconds. * *

        - * An access token is considered expired if {@code OAuth2AccessToken#getExpiresAt() - clockSkew} - * is before the current time {@code clock#instant()}. - * + * An access token is considered expired if + * {@code OAuth2AccessToken#getExpiresAt() - clockSkew} is before the current time + * {@code clock#instant()}. * @param clockSkew the maximum acceptable clock skew */ public void setClockSkew(Duration clockSkew) { @@ -135,12 +148,13 @@ public final class PasswordReactiveOAuth2AuthorizedClientProvider implements Rea } /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry. - * + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access + * token expiry. * @param clock the clock */ public void setClock(Clock clock) { Assert.notNull(clock, "clock cannot be null"); this.clock = clock; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizationFailureHandler.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizationFailureHandler.java index ed93e6cbf4..7a92cae654 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizationFailureHandler.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizationFailureHandler.java @@ -22,9 +22,8 @@ import reactor.core.publisher.Mono; import java.util.Map; /** - * Handles when an OAuth 2.0 Client - * fails to authorize (or re-authorize) - * via the authorization server or resource server. + * Handles when an OAuth 2.0 Client fails to authorize (or re-authorize) via the + * authorization server or resource server. * * @author Phil Clay * @since 5.3 @@ -33,19 +32,18 @@ import java.util.Map; public interface ReactiveOAuth2AuthorizationFailureHandler { /** - * Called when an OAuth 2.0 Client - * fails to authorize (or re-authorize) - * via the authorization server or resource server. - * + * Called when an OAuth 2.0 Client fails to authorize (or re-authorize) via the + * authorization server or resource server. * @param authorizationException the exception that contains details about what failed * @param principal the {@code Principal} that was attempted to be authorized - * @param attributes an immutable {@code Map} of extra optional attributes present under certain conditions. - * For example, this might contain a {@link org.springframework.web.server.ServerWebExchange ServerWebExchange} - * if the authorization was performed within the context of a {@code ServerWebExchange}. - * @return an empty {@link Mono} that completes after this handler has finished handling the event. + * @param attributes an immutable {@code Map} of extra optional attributes present + * under certain conditions. For example, this might contain a + * {@link org.springframework.web.server.ServerWebExchange ServerWebExchange} if the + * authorization was performed within the context of a {@code ServerWebExchange}. + * @return an empty {@link Mono} that completes after this handler has finished + * handling the event. */ - Mono onAuthorizationFailure( - OAuth2AuthorizationException authorizationException, - Authentication principal, + Mono onAuthorizationFailure(OAuth2AuthorizationException authorizationException, Authentication principal, Map attributes); + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizationSuccessHandler.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizationSuccessHandler.java index 1df3258f63..48ded751b9 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizationSuccessHandler.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizationSuccessHandler.java @@ -21,8 +21,7 @@ import reactor.core.publisher.Mono; import java.util.Map; /** - * Handles when an OAuth 2.0 Client - * has been successfully authorized (or re-authorized) + * Handles when an OAuth 2.0 Client has been successfully authorized (or re-authorized) * via the authorization server. * * @author Phil Clay @@ -32,20 +31,18 @@ import java.util.Map; public interface ReactiveOAuth2AuthorizationSuccessHandler { /** - * Called when an OAuth 2.0 Client - * has been successfully authorized (or re-authorized) + * Called when an OAuth 2.0 Client has been successfully authorized (or re-authorized) * via the authorization server. - * * @param authorizedClient the client that was successfully authorized * @param principal the {@code Principal} associated with the authorized client - * @param attributes an immutable {@code Map} of extra optional attributes present under certain conditions. - * For example, this might contain a {@link org.springframework.web.server.ServerWebExchange ServerWebExchange} - * if the authorization was performed within the context of a {@code ServerWebExchange}. - * @return an empty {@link Mono} that completes after this handler has finished handling the event. + * @param attributes an immutable {@code Map} of extra optional attributes present + * under certain conditions. For example, this might contain a + * {@link org.springframework.web.server.ServerWebExchange ServerWebExchange} if the + * authorization was performed within the context of a {@code ServerWebExchange}. + * @return an empty {@link Mono} that completes after this handler has finished + * handling the event. */ - Mono onAuthorizationSuccess( - OAuth2AuthorizedClient authorizedClient, - Authentication principal, + Mono onAuthorizationSuccess(OAuth2AuthorizedClient authorizedClient, Authentication principal, Map attributes); } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientManager.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientManager.java index 8730aaefb9..fb489614c9 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientManager.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientManager.java @@ -20,16 +20,17 @@ import org.springframework.security.oauth2.client.web.server.ServerOAuth2Authori import reactor.core.publisher.Mono; /** - * Implementations of this interface are responsible for the overall management - * of {@link OAuth2AuthorizedClient Authorized Client(s)}. + * Implementations of this interface are responsible for the overall management of + * {@link OAuth2AuthorizedClient Authorized Client(s)}. * *

        * The primary responsibilities include: *

          - *
        1. Authorizing (or re-authorizing) an OAuth 2.0 Client - * by leveraging a {@link ReactiveOAuth2AuthorizedClientProvider}(s).
        2. - *
        3. Delegating the persistence of an {@link OAuth2AuthorizedClient}, - * typically using a {@link ReactiveOAuth2AuthorizedClientService} OR {@link ServerOAuth2AuthorizedClientRepository}.
        4. + *
        5. Authorizing (or re-authorizing) an OAuth 2.0 Client by leveraging a + * {@link ReactiveOAuth2AuthorizedClientProvider}(s).
        6. + *
        7. Delegating the persistence of an {@link OAuth2AuthorizedClient}, typically using a + * {@link ReactiveOAuth2AuthorizedClientService} OR + * {@link ServerOAuth2AuthorizedClientRepository}.
        8. *
        * * @author Joe Grandja @@ -43,20 +44,24 @@ import reactor.core.publisher.Mono; public interface ReactiveOAuth2AuthorizedClientManager { /** - * Attempt to authorize or re-authorize (if required) the {@link ClientRegistration client} - * identified by the provided {@link OAuth2AuthorizeRequest#getClientRegistrationId() clientRegistrationId}. - * Implementations must return an empty {@code Mono} if authorization is not supported for the specified client, - * e.g. the associated {@link ReactiveOAuth2AuthorizedClientProvider}(s) does not support - * the {@link ClientRegistration#getAuthorizationGrantType() authorization grant} type configured for the client. + * Attempt to authorize or re-authorize (if required) the {@link ClientRegistration + * client} identified by the provided + * {@link OAuth2AuthorizeRequest#getClientRegistrationId() clientRegistrationId}. + * Implementations must return an empty {@code Mono} if authorization is not supported + * for the specified client, e.g. the associated + * {@link ReactiveOAuth2AuthorizedClientProvider}(s) does not support the + * {@link ClientRegistration#getAuthorizationGrantType() authorization grant} type + * configured for the client. * *

        - * In the case of re-authorization, implementations must return the provided {@link OAuth2AuthorizeRequest#getAuthorizedClient() authorized client} - * if re-authorization is not supported for the client OR is not required, - * e.g. a {@link OAuth2AuthorizedClient#getRefreshToken() refresh token} is not available OR + * In the case of re-authorization, implementations must return the provided + * {@link OAuth2AuthorizeRequest#getAuthorizedClient() authorized client} if + * re-authorization is not supported for the client OR is not required, e.g. a + * {@link OAuth2AuthorizedClient#getRefreshToken() refresh token} is not available OR * the {@link OAuth2AuthorizedClient#getAccessToken() access token} is not expired. - * * @param authorizeRequest the authorize request - * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if authorization is not supported for the specified client + * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if + * authorization is not supported for the specified client */ Mono authorize(OAuth2AuthorizeRequest authorizeRequest); diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProvider.java index f5b775410c..e47a26305f 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProvider.java @@ -20,25 +20,30 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType; import reactor.core.publisher.Mono; /** - * A strategy for authorizing (or re-authorizing) an OAuth 2.0 Client. - * Implementations will typically implement a specific {@link AuthorizationGrantType authorization grant} type. + * A strategy for authorizing (or re-authorizing) an OAuth 2.0 Client. Implementations + * will typically implement a specific {@link AuthorizationGrantType authorization grant} + * type. * * @author Joe Grandja * @since 5.2 * @see OAuth2AuthorizedClient * @see OAuth2AuthorizationContext - * @see Section 1.3 Authorization Grant + * @see Section + * 1.3 Authorization Grant */ @FunctionalInterface public interface ReactiveOAuth2AuthorizedClientProvider { /** - * Attempt to authorize (or re-authorize) the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided context. - * Implementations must return an empty {@code Mono} if authorization is not supported for the specified client, - * e.g. the provider doesn't support the {@link ClientRegistration#getAuthorizationGrantType() authorization grant} type configured for the client. - * + * Attempt to authorize (or re-authorize) the + * {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided + * context. Implementations must return an empty {@code Mono} if authorization is not + * supported for the specified client, e.g. the provider doesn't support the + * {@link ClientRegistration#getAuthorizationGrantType() authorization grant} type + * configured for the client. * @param context the context that holds authorization-specific state for the client - * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if authorization is not supported for the specified client + * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if + * authorization is not supported for the specified client */ Mono authorize(OAuth2AuthorizationContext context); diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProviderBuilder.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProviderBuilder.java index 482b5962ec..9cdf6d9ff4 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProviderBuilder.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProviderBuilder.java @@ -31,12 +31,12 @@ import java.util.function.Consumer; import java.util.stream.Collectors; /** - * A builder that builds a {@link DelegatingReactiveOAuth2AuthorizedClientProvider} composed of - * one or more {@link ReactiveOAuth2AuthorizedClientProvider}(s) that implement specific authorization grants. - * The supported authorization grants are {@link #authorizationCode() authorization_code}, - * {@link #refreshToken() refresh_token}, {@link #clientCredentials() client_credentials} - * and {@link #password() password}. - * In addition to the standard authorization grants, an implementation of an extension grant + * A builder that builds a {@link DelegatingReactiveOAuth2AuthorizedClientProvider} + * composed of one or more {@link ReactiveOAuth2AuthorizedClientProvider}(s) that + * implement specific authorization grants. The supported authorization grants are + * {@link #authorizationCode() authorization_code}, {@link #refreshToken() refresh_token}, + * {@link #clientCredentials() client_credentials} and {@link #password() password}. In + * addition to the standard authorization grants, an implementation of an extension grant * may be supplied via {@link #provider(ReactiveOAuth2AuthorizedClientProvider)}. * * @author Joe Grandja @@ -49,14 +49,15 @@ import java.util.stream.Collectors; * @see DelegatingReactiveOAuth2AuthorizedClientProvider */ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { + private final Map, Builder> builders = new LinkedHashMap<>(); private ReactiveOAuth2AuthorizedClientProviderBuilder() { } /** - * Returns a new {@link ReactiveOAuth2AuthorizedClientProviderBuilder} for configuring the supported authorization grant(s). - * + * Returns a new {@link ReactiveOAuth2AuthorizedClientProviderBuilder} for configuring + * the supported authorization grant(s). * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} */ public static ReactiveOAuth2AuthorizedClientProviderBuilder builder() { @@ -64,9 +65,9 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { } /** - * Configures a {@link ReactiveOAuth2AuthorizedClientProvider} to be composed with the {@link DelegatingReactiveOAuth2AuthorizedClientProvider}. - * This may be used for implementations of extension authorization grants. - * + * Configures a {@link ReactiveOAuth2AuthorizedClientProvider} to be composed with the + * {@link DelegatingReactiveOAuth2AuthorizedClientProvider}. This may be used for + * implementations of extension authorization grants. * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} */ public ReactiveOAuth2AuthorizedClientProviderBuilder provider(ReactiveOAuth2AuthorizedClientProvider provider) { @@ -77,11 +78,11 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { /** * Configures support for the {@code authorization_code} grant. - * * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} */ public ReactiveOAuth2AuthorizedClientProviderBuilder authorizationCode() { - this.builders.computeIfAbsent(AuthorizationCodeReactiveOAuth2AuthorizedClientProvider.class, k -> new AuthorizationCodeGrantBuilder()); + this.builders.computeIfAbsent(AuthorizationCodeReactiveOAuth2AuthorizedClientProvider.class, + k -> new AuthorizationCodeGrantBuilder()); return ReactiveOAuth2AuthorizedClientProviderBuilder.this; } @@ -94,33 +95,35 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { } /** - * Builds an instance of {@link AuthorizationCodeReactiveOAuth2AuthorizedClientProvider}. - * + * Builds an instance of + * {@link AuthorizationCodeReactiveOAuth2AuthorizedClientProvider}. * @return the {@link AuthorizationCodeReactiveOAuth2AuthorizedClientProvider} */ @Override public ReactiveOAuth2AuthorizedClientProvider build() { return new AuthorizationCodeReactiveOAuth2AuthorizedClientProvider(); } + } /** * Configures support for the {@code refresh_token} grant. - * * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} */ public ReactiveOAuth2AuthorizedClientProviderBuilder refreshToken() { - this.builders.computeIfAbsent(RefreshTokenReactiveOAuth2AuthorizedClientProvider.class, k -> new RefreshTokenGrantBuilder()); + this.builders.computeIfAbsent(RefreshTokenReactiveOAuth2AuthorizedClientProvider.class, + k -> new RefreshTokenGrantBuilder()); return ReactiveOAuth2AuthorizedClientProviderBuilder.this; } /** * Configures support for the {@code refresh_token} grant. - * - * @param builderConsumer a {@code Consumer} of {@link RefreshTokenGrantBuilder} used for further configuration + * @param builderConsumer a {@code Consumer} of {@link RefreshTokenGrantBuilder} used + * for further configuration * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} */ - public ReactiveOAuth2AuthorizedClientProviderBuilder refreshToken(Consumer builderConsumer) { + public ReactiveOAuth2AuthorizedClientProviderBuilder refreshToken( + Consumer builderConsumer) { RefreshTokenGrantBuilder builder = (RefreshTokenGrantBuilder) this.builders.computeIfAbsent( RefreshTokenReactiveOAuth2AuthorizedClientProvider.class, k -> new RefreshTokenGrantBuilder()); builderConsumer.accept(builder); @@ -131,28 +134,33 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { * A builder for the {@code refresh_token} grant. */ public class RefreshTokenGrantBuilder implements Builder { + private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient; + private Duration clockSkew; + private Clock clock; private RefreshTokenGrantBuilder() { } /** - * Sets the client used when requesting an access token credential at the Token Endpoint. - * - * @param accessTokenResponseClient the client used when requesting an access token credential at the Token Endpoint + * Sets the client used when requesting an access token credential at the Token + * Endpoint. + * @param accessTokenResponseClient the client used when requesting an access + * token credential at the Token Endpoint * @return the {@link RefreshTokenGrantBuilder} */ - public RefreshTokenGrantBuilder accessTokenResponseClient(ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient) { + public RefreshTokenGrantBuilder accessTokenResponseClient( + ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient) { this.accessTokenResponseClient = accessTokenResponseClient; return this; } /** - * Sets the maximum acceptable clock skew, which is used when checking the access token expiry. - * An access token is considered expired if it's before {@code Instant.now(this.clock) - clockSkew}. - * + * Sets the maximum acceptable clock skew, which is used when checking the access + * token expiry. An access token is considered expired if it's before + * {@code Instant.now(this.clock) - clockSkew}. * @param clockSkew the maximum acceptable clock skew * @return the {@link RefreshTokenGrantBuilder} */ @@ -162,8 +170,8 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { } /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry. - * + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the + * access token expiry. * @param clock the clock * @return the {@link RefreshTokenGrantBuilder} */ @@ -173,8 +181,8 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { } /** - * Builds an instance of {@link RefreshTokenReactiveOAuth2AuthorizedClientProvider}. - * + * Builds an instance of + * {@link RefreshTokenReactiveOAuth2AuthorizedClientProvider}. * @return the {@link RefreshTokenReactiveOAuth2AuthorizedClientProvider} */ @Override @@ -191,27 +199,30 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { } return authorizedClientProvider; } + } /** * Configures support for the {@code client_credentials} grant. - * * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} */ public ReactiveOAuth2AuthorizedClientProviderBuilder clientCredentials() { - this.builders.computeIfAbsent(ClientCredentialsReactiveOAuth2AuthorizedClientProvider.class, k -> new ClientCredentialsGrantBuilder()); + this.builders.computeIfAbsent(ClientCredentialsReactiveOAuth2AuthorizedClientProvider.class, + k -> new ClientCredentialsGrantBuilder()); return ReactiveOAuth2AuthorizedClientProviderBuilder.this; } /** * Configures support for the {@code client_credentials} grant. - * - * @param builderConsumer a {@code Consumer} of {@link ClientCredentialsGrantBuilder} used for further configuration + * @param builderConsumer a {@code Consumer} of {@link ClientCredentialsGrantBuilder} + * used for further configuration * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} */ - public ReactiveOAuth2AuthorizedClientProviderBuilder clientCredentials(Consumer builderConsumer) { + public ReactiveOAuth2AuthorizedClientProviderBuilder clientCredentials( + Consumer builderConsumer) { ClientCredentialsGrantBuilder builder = (ClientCredentialsGrantBuilder) this.builders.computeIfAbsent( - ClientCredentialsReactiveOAuth2AuthorizedClientProvider.class, k -> new ClientCredentialsGrantBuilder()); + ClientCredentialsReactiveOAuth2AuthorizedClientProvider.class, + k -> new ClientCredentialsGrantBuilder()); builderConsumer.accept(builder); return ReactiveOAuth2AuthorizedClientProviderBuilder.this; } @@ -220,28 +231,33 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { * A builder for the {@code client_credentials} grant. */ public class ClientCredentialsGrantBuilder implements Builder { + private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient; + private Duration clockSkew; + private Clock clock; private ClientCredentialsGrantBuilder() { } /** - * Sets the client used when requesting an access token credential at the Token Endpoint. - * - * @param accessTokenResponseClient the client used when requesting an access token credential at the Token Endpoint + * Sets the client used when requesting an access token credential at the Token + * Endpoint. + * @param accessTokenResponseClient the client used when requesting an access + * token credential at the Token Endpoint * @return the {@link ClientCredentialsGrantBuilder} */ - public ClientCredentialsGrantBuilder accessTokenResponseClient(ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient) { + public ClientCredentialsGrantBuilder accessTokenResponseClient( + ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient) { this.accessTokenResponseClient = accessTokenResponseClient; return this; } /** - * Sets the maximum acceptable clock skew, which is used when checking the access token expiry. - * An access token is considered expired if it's before {@code Instant.now(this.clock) - clockSkew}. - * + * Sets the maximum acceptable clock skew, which is used when checking the access + * token expiry. An access token is considered expired if it's before + * {@code Instant.now(this.clock) - clockSkew}. * @param clockSkew the maximum acceptable clock skew * @return the {@link ClientCredentialsGrantBuilder} */ @@ -251,8 +267,8 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { } /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry. - * + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the + * access token expiry. * @param clock the clock * @return the {@link ClientCredentialsGrantBuilder} */ @@ -262,8 +278,8 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { } /** - * Builds an instance of {@link ClientCredentialsReactiveOAuth2AuthorizedClientProvider}. - * + * Builds an instance of + * {@link ClientCredentialsReactiveOAuth2AuthorizedClientProvider}. * @return the {@link ClientCredentialsReactiveOAuth2AuthorizedClientProvider} */ @Override @@ -280,27 +296,28 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { } return authorizedClientProvider; } + } /** * Configures support for the {@code password} grant. - * * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} */ public ReactiveOAuth2AuthorizedClientProviderBuilder password() { - this.builders.computeIfAbsent(PasswordReactiveOAuth2AuthorizedClientProvider.class, k -> new PasswordGrantBuilder()); + this.builders.computeIfAbsent(PasswordReactiveOAuth2AuthorizedClientProvider.class, + k -> new PasswordGrantBuilder()); return ReactiveOAuth2AuthorizedClientProviderBuilder.this; } /** * Configures support for the {@code password} grant. - * - * @param builderConsumer a {@code Consumer} of {@link PasswordGrantBuilder} used for further configuration + * @param builderConsumer a {@code Consumer} of {@link PasswordGrantBuilder} used for + * further configuration * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} */ public ReactiveOAuth2AuthorizedClientProviderBuilder password(Consumer builderConsumer) { - PasswordGrantBuilder builder = (PasswordGrantBuilder) this.builders.computeIfAbsent( - PasswordReactiveOAuth2AuthorizedClientProvider.class, k -> new PasswordGrantBuilder()); + PasswordGrantBuilder builder = (PasswordGrantBuilder) this.builders + .computeIfAbsent(PasswordReactiveOAuth2AuthorizedClientProvider.class, k -> new PasswordGrantBuilder()); builderConsumer.accept(builder); return ReactiveOAuth2AuthorizedClientProviderBuilder.this; } @@ -309,28 +326,33 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { * A builder for the {@code password} grant. */ public class PasswordGrantBuilder implements Builder { + private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient; + private Duration clockSkew; + private Clock clock; private PasswordGrantBuilder() { } /** - * Sets the client used when requesting an access token credential at the Token Endpoint. - * - * @param accessTokenResponseClient the client used when requesting an access token credential at the Token Endpoint + * Sets the client used when requesting an access token credential at the Token + * Endpoint. + * @param accessTokenResponseClient the client used when requesting an access + * token credential at the Token Endpoint * @return the {@link PasswordGrantBuilder} */ - public PasswordGrantBuilder accessTokenResponseClient(ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient) { + public PasswordGrantBuilder accessTokenResponseClient( + ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient) { this.accessTokenResponseClient = accessTokenResponseClient; return this; } /** - * Sets the maximum acceptable clock skew, which is used when checking the access token expiry. - * An access token is considered expired if it's before {@code Instant.now(this.clock) - clockSkew}. - * + * Sets the maximum acceptable clock skew, which is used when checking the access + * token expiry. An access token is considered expired if it's before + * {@code Instant.now(this.clock) - clockSkew}. * @param clockSkew the maximum acceptable clock skew * @return the {@link PasswordGrantBuilder} */ @@ -340,8 +362,8 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { } /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry. - * + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the + * access token expiry. * @param clock the clock * @return the {@link PasswordGrantBuilder} */ @@ -352,7 +374,6 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { /** * Builds an instance of {@link PasswordReactiveOAuth2AuthorizedClientProvider}. - * * @return the {@link PasswordReactiveOAuth2AuthorizedClientProvider} */ @Override @@ -369,23 +390,24 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { } return authorizedClientProvider; } + } /** * Builds an instance of {@link DelegatingReactiveOAuth2AuthorizedClientProvider} * composed of one or more {@link ReactiveOAuth2AuthorizedClientProvider}(s). - * * @return the {@link DelegatingReactiveOAuth2AuthorizedClientProvider} */ public ReactiveOAuth2AuthorizedClientProvider build() { - List authorizedClientProviders = - this.builders.values().stream() - .map(Builder::build) - .collect(Collectors.toList()); + List authorizedClientProviders = this.builders.values().stream() + .map(Builder::build).collect(Collectors.toList()); return new DelegatingReactiveOAuth2AuthorizedClientProvider(authorizedClientProviders); } interface Builder { + ReactiveOAuth2AuthorizedClientProvider build(); + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientService.java index 3e189f8b11..ac78d89aa0 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientService.java @@ -22,12 +22,12 @@ import org.springframework.security.oauth2.core.OAuth2AccessToken; import reactor.core.publisher.Mono; /** - * Implementations of this interface are responsible for the management - * of {@link OAuth2AuthorizedClient Authorized Client(s)}, which provide the purpose - * of associating an {@link OAuth2AuthorizedClient#getAccessToken() Access Token} credential + * Implementations of this interface are responsible for the management of + * {@link OAuth2AuthorizedClient Authorized Client(s)}, which provide the purpose of + * associating an {@link OAuth2AuthorizedClient#getAccessToken() Access Token} credential * to a {@link OAuth2AuthorizedClient#getClientRegistration() Client} and Resource Owner, - * who is the {@link OAuth2AuthorizedClient#getPrincipalName() Principal} - * that originally granted the authorization. + * who is the {@link OAuth2AuthorizedClient#getPrincipalName() Principal} that originally + * granted the authorization. * * @author Rob Winch * @since 5.1 @@ -39,32 +39,27 @@ import reactor.core.publisher.Mono; public interface ReactiveOAuth2AuthorizedClientService { /** - * Returns the {@link OAuth2AuthorizedClient} associated to the - * provided client registration identifier and End-User's {@code Principal} name - * or {@code null} if not available. - * + * Returns the {@link OAuth2AuthorizedClient} associated to the provided client + * registration identifier and End-User's {@code Principal} name or {@code null} if + * not available. * @param clientRegistrationId the identifier for the client's registration * @param principalName the name of the End-User {@code Principal} (Resource Owner) * @param a type of OAuth2AuthorizedClient * @return the {@link OAuth2AuthorizedClient} or {@code null} if not available */ - Mono loadAuthorizedClient(String clientRegistrationId, - String principalName); + Mono loadAuthorizedClient(String clientRegistrationId, String principalName); /** - * Saves the {@link OAuth2AuthorizedClient} associating it to - * the provided End-User {@link Authentication} (Resource Owner). - * + * Saves the {@link OAuth2AuthorizedClient} associating it to the provided End-User + * {@link Authentication} (Resource Owner). * @param authorizedClient the authorized client * @param principal the End-User {@link Authentication} (Resource Owner) */ - Mono saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, - Authentication principal); + Mono saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal); /** - * Removes the {@link OAuth2AuthorizedClient} associated to the - * provided client registration identifier and End-User's {@code Principal} name. - * + * Removes the {@link OAuth2AuthorizedClient} associated to the provided client + * registration identifier and End-User's {@code Principal} name. * @param clientRegistrationId the identifier for the client's registration * @param principalName the name of the End-User {@code Principal} (Resource Owner) */ diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RefreshTokenOAuth2AuthorizedClientProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RefreshTokenOAuth2AuthorizedClientProvider.java index f77a44809b..2f19d5ec6d 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RefreshTokenOAuth2AuthorizedClientProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RefreshTokenOAuth2AuthorizedClientProvider.java @@ -34,8 +34,8 @@ import java.util.HashSet; import java.util.Set; /** - * An implementation of an {@link OAuth2AuthorizedClientProvider} - * for the {@link AuthorizationGrantType#REFRESH_TOKEN refresh_token} grant. + * An implementation of an {@link OAuth2AuthorizedClientProvider} for the + * {@link AuthorizationGrantType#REFRESH_TOKEN refresh_token} grant. * * @author Joe Grandja * @since 5.2 @@ -43,26 +43,32 @@ import java.util.Set; * @see DefaultRefreshTokenTokenResponseClient */ public final class RefreshTokenOAuth2AuthorizedClientProvider implements OAuth2AuthorizedClientProvider { - private OAuth2AccessTokenResponseClient accessTokenResponseClient = - new DefaultRefreshTokenTokenResponseClient(); + + private OAuth2AccessTokenResponseClient accessTokenResponseClient = new DefaultRefreshTokenTokenResponseClient(); + private Duration clockSkew = Duration.ofSeconds(60); + private Clock clock = Clock.systemUTC(); /** - * Attempt to re-authorize the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}. - * Returns {@code null} if re-authorization is not supported, - * e.g. the client is not authorized OR the {@link OAuth2AuthorizedClient#getRefreshToken() refresh token} - * is not available for the authorized client OR the {@link OAuth2AuthorizedClient#getAccessToken() access token} is not expired. + * Attempt to re-authorize the + * {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided + * {@code context}. Returns {@code null} if re-authorization is not supported, e.g. + * the client is not authorized OR the {@link OAuth2AuthorizedClient#getRefreshToken() + * refresh token} is not available for the authorized client OR the + * {@link OAuth2AuthorizedClient#getAccessToken() access token} is not expired. * *

        - * The following {@link OAuth2AuthorizationContext#getAttributes() context attributes} are supported: + * The following {@link OAuth2AuthorizationContext#getAttributes() context attributes} + * are supported: *

          - *
        1. {@link OAuth2AuthorizationContext#REQUEST_SCOPE_ATTRIBUTE_NAME} (optional) - a {@code String[]} of scope(s) - * to be requested by the {@link OAuth2AuthorizationContext#getClientRegistration() client}
        2. + *
        3. {@link OAuth2AuthorizationContext#REQUEST_SCOPE_ATTRIBUTE_NAME} (optional) - a + * {@code String[]} of scope(s) to be requested by the + * {@link OAuth2AuthorizationContext#getClientRegistration() client}
        4. *
        - * * @param context the context that holds authorization-specific state for the client - * @return the {@link OAuth2AuthorizedClient} or {@code null} if re-authorization is not supported + * @return the {@link OAuth2AuthorizedClient} or {@code null} if re-authorization is + * not supported */ @Override @Nullable @@ -70,17 +76,16 @@ public final class RefreshTokenOAuth2AuthorizedClientProvider implements OAuth2A Assert.notNull(context, "context cannot be null"); OAuth2AuthorizedClient authorizedClient = context.getAuthorizedClient(); - if (authorizedClient == null || - authorizedClient.getRefreshToken() == null || - !hasTokenExpired(authorizedClient.getAccessToken())) { + if (authorizedClient == null || authorizedClient.getRefreshToken() == null + || !hasTokenExpired(authorizedClient.getAccessToken())) { return null; } Object requestScope = context.getAttribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME); Set scopes = Collections.emptySet(); if (requestScope != null) { - Assert.isInstanceOf(String[].class, requestScope, - "The context attribute must be of type String[] '" + OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME + "'"); + Assert.isInstanceOf(String[].class, requestScope, "The context attribute must be of type String[] '" + + OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME + "'"); scopes = new HashSet<>(Arrays.asList((String[]) requestScope)); } @@ -91,8 +96,10 @@ public final class RefreshTokenOAuth2AuthorizedClientProvider implements OAuth2A OAuth2AccessTokenResponse tokenResponse; try { tokenResponse = this.accessTokenResponseClient.getTokenResponse(refreshTokenGrantRequest); - } catch (OAuth2AuthorizationException ex) { - throw new ClientAuthorizationException(ex.getError(), authorizedClient.getClientRegistration().getRegistrationId(), ex); + } + catch (OAuth2AuthorizationException ex) { + throw new ClientAuthorizationException(ex.getError(), + authorizedClient.getClientRegistration().getRegistrationId(), ex); } return new OAuth2AuthorizedClient(context.getAuthorizedClient().getClientRegistration(), @@ -104,23 +111,26 @@ public final class RefreshTokenOAuth2AuthorizedClientProvider implements OAuth2A } /** - * Sets the client used when requesting an access token credential at the Token Endpoint for the {@code refresh_token} grant. - * - * @param accessTokenResponseClient the client used when requesting an access token credential at the Token Endpoint for the {@code refresh_token} grant + * Sets the client used when requesting an access token credential at the Token + * Endpoint for the {@code refresh_token} grant. + * @param accessTokenResponseClient the client used when requesting an access token + * credential at the Token Endpoint for the {@code refresh_token} grant */ - public void setAccessTokenResponseClient(OAuth2AccessTokenResponseClient accessTokenResponseClient) { + public void setAccessTokenResponseClient( + OAuth2AccessTokenResponseClient accessTokenResponseClient) { Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null"); this.accessTokenResponseClient = accessTokenResponseClient; } /** * Sets the maximum acceptable clock skew, which is used when checking the - * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is 60 seconds. + * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is + * 60 seconds. * *

        - * An access token is considered expired if {@code OAuth2AccessToken#getExpiresAt() - clockSkew} - * is before the current time {@code clock#instant()}. - * + * An access token is considered expired if + * {@code OAuth2AccessToken#getExpiresAt() - clockSkew} is before the current time + * {@code clock#instant()}. * @param clockSkew the maximum acceptable clock skew */ public void setClockSkew(Duration clockSkew) { @@ -130,12 +140,13 @@ public final class RefreshTokenOAuth2AuthorizedClientProvider implements OAuth2A } /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry. - * + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access + * token expiry. * @param clock the clock */ public void setClock(Clock clock) { Assert.notNull(clock, "clock cannot be null"); this.clock = clock; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RefreshTokenReactiveOAuth2AuthorizedClientProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RefreshTokenReactiveOAuth2AuthorizedClientProvider.java index f2526ed225..d96984b59a 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RefreshTokenReactiveOAuth2AuthorizedClientProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RefreshTokenReactiveOAuth2AuthorizedClientProvider.java @@ -34,61 +34,67 @@ import java.util.HashSet; import java.util.Set; /** - * An implementation of a {@link ReactiveOAuth2AuthorizedClientProvider} - * for the {@link AuthorizationGrantType#REFRESH_TOKEN refresh_token} grant. + * An implementation of a {@link ReactiveOAuth2AuthorizedClientProvider} for the + * {@link AuthorizationGrantType#REFRESH_TOKEN refresh_token} grant. * * @author Joe Grandja * @since 5.2 * @see ReactiveOAuth2AuthorizedClientProvider * @see WebClientReactiveRefreshTokenTokenResponseClient */ -public final class RefreshTokenReactiveOAuth2AuthorizedClientProvider implements ReactiveOAuth2AuthorizedClientProvider { - private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient = - new WebClientReactiveRefreshTokenTokenResponseClient(); +public final class RefreshTokenReactiveOAuth2AuthorizedClientProvider + implements ReactiveOAuth2AuthorizedClientProvider { + + private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient = new WebClientReactiveRefreshTokenTokenResponseClient(); + private Duration clockSkew = Duration.ofSeconds(60); + private Clock clock = Clock.systemUTC(); /** - * Attempt to re-authorize the {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided {@code context}. - * Returns an empty {@code Mono} if re-authorization is not supported, - * e.g. the client is not authorized OR the {@link OAuth2AuthorizedClient#getRefreshToken() refresh token} - * is not available for the authorized client OR the {@link OAuth2AuthorizedClient#getAccessToken() access token} is not expired. + * Attempt to re-authorize the + * {@link OAuth2AuthorizationContext#getClientRegistration() client} in the provided + * {@code context}. Returns an empty {@code Mono} if re-authorization is not + * supported, e.g. the client is not authorized OR the + * {@link OAuth2AuthorizedClient#getRefreshToken() refresh token} is not available for + * the authorized client OR the {@link OAuth2AuthorizedClient#getAccessToken() access + * token} is not expired. * *

        - * The following {@link OAuth2AuthorizationContext#getAttributes() context attributes} are supported: + * The following {@link OAuth2AuthorizationContext#getAttributes() context attributes} + * are supported: *

          - *
        1. {@code "org.springframework.security.oauth2.client.REQUEST_SCOPE"} (optional) - a {@code String[]} of scope(s) - * to be requested by the {@link OAuth2AuthorizationContext#getClientRegistration() client}
        2. + *
        3. {@code "org.springframework.security.oauth2.client.REQUEST_SCOPE"} (optional) - + * a {@code String[]} of scope(s) to be requested by the + * {@link OAuth2AuthorizationContext#getClientRegistration() client}
        4. *
        - * * @param context the context that holds authorization-specific state for the client - * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if re-authorization is not supported + * @return the {@link OAuth2AuthorizedClient} or an empty {@code Mono} if + * re-authorization is not supported */ @Override public Mono authorize(OAuth2AuthorizationContext context) { Assert.notNull(context, "context cannot be null"); OAuth2AuthorizedClient authorizedClient = context.getAuthorizedClient(); - if (authorizedClient == null || - authorizedClient.getRefreshToken() == null || - !hasTokenExpired(authorizedClient.getAccessToken())) { + if (authorizedClient == null || authorizedClient.getRefreshToken() == null + || !hasTokenExpired(authorizedClient.getAccessToken())) { return Mono.empty(); } Object requestScope = context.getAttribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME); Set scopes = Collections.emptySet(); if (requestScope != null) { - Assert.isInstanceOf(String[].class, requestScope, - "The context attribute must be of type String[] '" + OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME + "'"); + Assert.isInstanceOf(String[].class, requestScope, "The context attribute must be of type String[] '" + + OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME + "'"); scopes = new HashSet<>(Arrays.asList((String[]) requestScope)); } ClientRegistration clientRegistration = context.getClientRegistration(); - OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest( - clientRegistration, authorizedClient.getAccessToken(), authorizedClient.getRefreshToken(), scopes); + OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest(clientRegistration, + authorizedClient.getAccessToken(), authorizedClient.getRefreshToken(), scopes); - return Mono.just(refreshTokenGrantRequest) - .flatMap(this.accessTokenResponseClient::getTokenResponse) + return Mono.just(refreshTokenGrantRequest).flatMap(this.accessTokenResponseClient::getTokenResponse) .onErrorMap(OAuth2AuthorizationException.class, e -> new ClientAuthorizationException(e.getError(), clientRegistration.getRegistrationId(), e)) .map(tokenResponse -> new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(), @@ -100,23 +106,26 @@ public final class RefreshTokenReactiveOAuth2AuthorizedClientProvider implements } /** - * Sets the client used when requesting an access token credential at the Token Endpoint for the {@code refresh_token} grant. - * - * @param accessTokenResponseClient the client used when requesting an access token credential at the Token Endpoint for the {@code refresh_token} grant + * Sets the client used when requesting an access token credential at the Token + * Endpoint for the {@code refresh_token} grant. + * @param accessTokenResponseClient the client used when requesting an access token + * credential at the Token Endpoint for the {@code refresh_token} grant */ - public void setAccessTokenResponseClient(ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient) { + public void setAccessTokenResponseClient( + ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient) { Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null"); this.accessTokenResponseClient = accessTokenResponseClient; } /** * Sets the maximum acceptable clock skew, which is used when checking the - * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is 60 seconds. + * {@link OAuth2AuthorizedClient#getAccessToken() access token} expiry. The default is + * 60 seconds. * *

        - * An access token is considered expired if {@code OAuth2AccessToken#getExpiresAt() - clockSkew} - * is before the current time {@code clock#instant()}. - * + * An access token is considered expired if + * {@code OAuth2AccessToken#getExpiresAt() - clockSkew} is before the current time + * {@code clock#instant()}. * @param clockSkew the maximum acceptable clock skew */ public void setClockSkew(Duration clockSkew) { @@ -126,12 +135,13 @@ public final class RefreshTokenReactiveOAuth2AuthorizedClientProvider implements } /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access token expiry. - * + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the access + * token expiry. * @param clock the clock */ public void setClock(Clock clock) { Assert.notNull(clock, "clock cannot be null"); this.clock = clock; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientOAuth2AuthorizationFailureHandler.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientOAuth2AuthorizationFailureHandler.java index 1afe7f43d1..cb10fdb195 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientOAuth2AuthorizationFailureHandler.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientOAuth2AuthorizationFailureHandler.java @@ -29,9 +29,9 @@ import java.util.Map; import java.util.Set; /** - * An {@link OAuth2AuthorizationFailureHandler} that removes an {@link OAuth2AuthorizedClient} - * when the {@link OAuth2Error#getErrorCode()} matches - * one of the configured {@link OAuth2ErrorCodes OAuth 2.0 error codes}. + * An {@link OAuth2AuthorizationFailureHandler} that removes an + * {@link OAuth2AuthorizedClient} when the {@link OAuth2Error#getErrorCode()} matches one + * of the configured {@link OAuth2ErrorCodes OAuth 2.0 error codes}. * * @author Joe Grandja * @since 5.3 @@ -42,29 +42,34 @@ import java.util.Set; public class RemoveAuthorizedClientOAuth2AuthorizationFailureHandler implements OAuth2AuthorizationFailureHandler { /** - * The default OAuth 2.0 error codes that will trigger removal of an {@link OAuth2AuthorizedClient}. + * The default OAuth 2.0 error codes that will trigger removal of an + * {@link OAuth2AuthorizedClient}. * @see OAuth2ErrorCodes */ - public static final Set DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList( - /* - * Returned from Resource Servers when an access token provided is expired, revoked, - * malformed, or invalid for other reasons. - * - * Note that this is needed because ServletOAuth2AuthorizedClientExchangeFilterFunction - * delegates this type of failure received from a Resource Server - * to this failure handler. - */ - OAuth2ErrorCodes.INVALID_TOKEN, + public static final Set DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES = Collections + .unmodifiableSet(new HashSet<>(Arrays.asList( + /* + * Returned from Resource Servers when an access token provided is + * expired, revoked, malformed, or invalid for other reasons. + * + * Note that this is needed because + * ServletOAuth2AuthorizedClientExchangeFilterFunction delegates this + * type of failure received from a Resource Server to this failure + * handler. + */ + OAuth2ErrorCodes.INVALID_TOKEN, - /* - * Returned from Authorization Servers when the authorization grant or refresh token is invalid, expired, revoked, - * does not match the redirection URI used in the authorization request, or was issued to another client. - */ - OAuth2ErrorCodes.INVALID_GRANT - ))); + /* + * Returned from Authorization Servers when the authorization grant or + * refresh token is invalid, expired, revoked, does not match the + * redirection URI used in the authorization request, or was issued to + * another client. + */ + OAuth2ErrorCodes.INVALID_GRANT))); /** - * The OAuth 2.0 error codes which will trigger removal of an {@link OAuth2AuthorizedClient}. + * The OAuth 2.0 error codes which will trigger removal of an + * {@link OAuth2AuthorizedClient}. * @see OAuth2ErrorCodes */ private final Set removeAuthorizedClientErrorCodes; @@ -84,68 +89,74 @@ public class RemoveAuthorizedClientOAuth2AuthorizationFailureHandler implements public interface OAuth2AuthorizedClientRemover { /** - * Removes the {@link OAuth2AuthorizedClient} associated to the - * provided client registration identifier and End-User {@link Authentication} (Resource Owner). - * + * Removes the {@link OAuth2AuthorizedClient} associated to the provided client + * registration identifier and End-User {@link Authentication} (Resource Owner). * @param clientRegistrationId the identifier for the client's registration * @param principal the End-User {@link Authentication} (Resource Owner) - * @param attributes an immutable {@code Map} of (optional) attributes present under certain conditions. - * For example, this might contain a {@code javax.servlet.http.HttpServletRequest} - * and {@code javax.servlet.http.HttpServletResponse} if the authorization was performed - * within the context of a {@code javax.servlet.ServletContext}. + * @param attributes an immutable {@code Map} of (optional) attributes present + * under certain conditions. For example, this might contain a + * {@code javax.servlet.http.HttpServletRequest} and + * {@code javax.servlet.http.HttpServletResponse} if the authorization was + * performed within the context of a {@code javax.servlet.ServletContext}. */ - void removeAuthorizedClient(String clientRegistrationId, Authentication principal, Map attributes); + void removeAuthorizedClient(String clientRegistrationId, Authentication principal, + Map attributes); + } /** - * Constructs a {@code RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} using the provided parameters. - * - * @param authorizedClientRemover the {@link OAuth2AuthorizedClientRemover} used for removing an {@link OAuth2AuthorizedClient} - * if the error code is one of the {@link #DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES}. + * Constructs a {@code RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} using + * the provided parameters. + * @param authorizedClientRemover the {@link OAuth2AuthorizedClientRemover} used for + * removing an {@link OAuth2AuthorizedClient} if the error code is one of the + * {@link #DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES}. */ - public RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(OAuth2AuthorizedClientRemover authorizedClientRemover) { + public RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( + OAuth2AuthorizedClientRemover authorizedClientRemover) { this(authorizedClientRemover, DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES); } /** - * Constructs a {@code RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} using the provided parameters. - * - * @param authorizedClientRemover the {@link OAuth2AuthorizedClientRemover} used for removing an {@link OAuth2AuthorizedClient} - * if the error code is one of the {@link #removeAuthorizedClientErrorCodes}. - * @param removeAuthorizedClientErrorCodes the OAuth 2.0 error codes which will trigger removal of an authorized client. + * Constructs a {@code RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} using + * the provided parameters. + * @param authorizedClientRemover the {@link OAuth2AuthorizedClientRemover} used for + * removing an {@link OAuth2AuthorizedClient} if the error code is one of the + * {@link #removeAuthorizedClientErrorCodes}. + * @param removeAuthorizedClientErrorCodes the OAuth 2.0 error codes which will + * trigger removal of an authorized client. * @see OAuth2ErrorCodes */ public RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( - OAuth2AuthorizedClientRemover authorizedClientRemover, - Set removeAuthorizedClientErrorCodes) { + OAuth2AuthorizedClientRemover authorizedClientRemover, Set removeAuthorizedClientErrorCodes) { Assert.notNull(authorizedClientRemover, "authorizedClientRemover cannot be null"); Assert.notNull(removeAuthorizedClientErrorCodes, "removeAuthorizedClientErrorCodes cannot be null"); - this.removeAuthorizedClientErrorCodes = Collections.unmodifiableSet(new HashSet<>(removeAuthorizedClientErrorCodes)); + this.removeAuthorizedClientErrorCodes = Collections + .unmodifiableSet(new HashSet<>(removeAuthorizedClientErrorCodes)); this.delegate = authorizedClientRemover; } @Override - public void onAuthorizationFailure(OAuth2AuthorizationException authorizationException, - Authentication principal, Map attributes) { + public void onAuthorizationFailure(OAuth2AuthorizationException authorizationException, Authentication principal, + Map attributes) { - if (authorizationException instanceof ClientAuthorizationException && - hasRemovalErrorCode(authorizationException)) { + if (authorizationException instanceof ClientAuthorizationException + && hasRemovalErrorCode(authorizationException)) { ClientAuthorizationException clientAuthorizationException = (ClientAuthorizationException) authorizationException; - this.delegate.removeAuthorizedClient( - clientAuthorizationException.getClientRegistrationId(), principal, attributes); + this.delegate.removeAuthorizedClient(clientAuthorizationException.getClientRegistrationId(), principal, + attributes); } } /** - * Returns true if the given exception has an error code that - * indicates that the authorized client should be removed. - * + * Returns true if the given exception has an error code that indicates that the + * authorized client should be removed. * @param authorizationException the exception that caused the authorization failure - * @return true if the given exception has an error code that - * indicates that the authorized client should be removed. + * @return true if the given exception has an error code that indicates that the + * authorized client should be removed. */ private boolean hasRemovalErrorCode(OAuth2AuthorizationException authorizationException) { return this.removeAuthorizedClientErrorCodes.contains(authorizationException.getError().getErrorCode()); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler.java index a0106ab40f..2d1e3225a8 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler.java @@ -30,39 +30,45 @@ import java.util.Map; import java.util.Set; /** - * A {@link ReactiveOAuth2AuthorizationFailureHandler} that removes an {@link OAuth2AuthorizedClient} - * when the {@link OAuth2Error#getErrorCode()} matches - * one of the configured {@link OAuth2ErrorCodes OAuth 2.0 error codes}. + * A {@link ReactiveOAuth2AuthorizationFailureHandler} that removes an + * {@link OAuth2AuthorizedClient} when the {@link OAuth2Error#getErrorCode()} matches one + * of the configured {@link OAuth2ErrorCodes OAuth 2.0 error codes}. * * @author Phil Clay * @since 5.3 */ -public class RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler implements ReactiveOAuth2AuthorizationFailureHandler { +public class RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler + implements ReactiveOAuth2AuthorizationFailureHandler { /** - * The default OAuth 2.0 error codes that will trigger removal of the authorized client. + * The default OAuth 2.0 error codes that will trigger removal of the authorized + * client. * @see OAuth2ErrorCodes */ - public static final Set DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList( - /* - * Returned from resource servers when an access token provided is expired, revoked, - * malformed, or invalid for other reasons. - * - * Note that this is needed because the ServerOAuth2AuthorizedClientExchangeFilterFunction - * delegates this type of failure received from a resource server - * to this failure handler. - */ - OAuth2ErrorCodes.INVALID_TOKEN, - /* - * Returned from authorization servers when a refresh token is invalid, expired, revoked, - * does not match the redirection URI used in the authorization request, or was issued to another client. - */ - OAuth2ErrorCodes.INVALID_GRANT))); + public static final Set DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES = Collections + .unmodifiableSet(new HashSet<>(Arrays.asList( + /* + * Returned from resource servers when an access token provided is + * expired, revoked, malformed, or invalid for other reasons. + * + * Note that this is needed because the + * ServerOAuth2AuthorizedClientExchangeFilterFunction delegates this + * type of failure received from a resource server to this failure + * handler. + */ + OAuth2ErrorCodes.INVALID_TOKEN, + /* + * Returned from authorization servers when a refresh token is + * invalid, expired, revoked, does not match the redirection URI used + * in the authorization request, or was issued to another client. + */ + OAuth2ErrorCodes.INVALID_GRANT))); /** * A delegate that removes an {@link OAuth2AuthorizedClient} from a - * {@link ServerOAuth2AuthorizedClientRepository} or {@link ReactiveOAuth2AuthorizedClientService} - * if the error code is one of the {@link #removeAuthorizedClientErrorCodes}. + * {@link ServerOAuth2AuthorizedClientRepository} or + * {@link ReactiveOAuth2AuthorizedClientService} if the error code is one of the + * {@link #removeAuthorizedClientErrorCodes}. */ private final OAuth2AuthorizedClientRemover delegate; @@ -74,49 +80,60 @@ public class RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler imp /** * Removes an {@link OAuth2AuthorizedClient} from a - * {@link ServerOAuth2AuthorizedClientRepository} or {@link ReactiveOAuth2AuthorizedClientService}. + * {@link ServerOAuth2AuthorizedClientRepository} or + * {@link ReactiveOAuth2AuthorizedClientService}. */ @FunctionalInterface public interface OAuth2AuthorizedClientRemover { /** - * Removes the {@link OAuth2AuthorizedClient} associated to the - * provided client registration identifier and End-User {@link Authentication} (Resource Owner). - * + * Removes the {@link OAuth2AuthorizedClient} associated to the provided client + * registration identifier and End-User {@link Authentication} (Resource Owner). * @param clientRegistrationId the identifier for the client's registration * @param principal the End-User {@link Authentication} (Resource Owner) - * @param attributes an immutable {@code Map} of extra optional attributes present under certain conditions. - * For example, this might contain a {@link org.springframework.web.server.ServerWebExchange ServerWebExchange} - * if the authorization was performed within the context of a {@code ServerWebExchange}. - * @return an empty {@link Mono} that completes after this handler has finished handling the event. + * @param attributes an immutable {@code Map} of extra optional attributes present + * under certain conditions. For example, this might contain a + * {@link org.springframework.web.server.ServerWebExchange ServerWebExchange} if + * the authorization was performed within the context of a + * {@code ServerWebExchange}. + * @return an empty {@link Mono} that completes after this handler has finished + * handling the event. */ - Mono removeAuthorizedClient(String clientRegistrationId, Authentication principal, Map attributes); + Mono removeAuthorizedClient(String clientRegistrationId, Authentication principal, + Map attributes); + } /** - * Constructs a {@code RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} using the provided parameters. - * - * @param authorizedClientRemover the {@link OAuth2AuthorizedClientRemover} used for removing an {@link OAuth2AuthorizedClient} - * if the error code is one of the {@link #DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES}. + * Constructs a + * {@code RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} using the + * provided parameters. + * @param authorizedClientRemover the {@link OAuth2AuthorizedClientRemover} used for + * removing an {@link OAuth2AuthorizedClient} if the error code is one of the + * {@link #DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES}. */ - public RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler(OAuth2AuthorizedClientRemover authorizedClientRemover) { + public RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler( + OAuth2AuthorizedClientRemover authorizedClientRemover) { this(authorizedClientRemover, DEFAULT_REMOVE_AUTHORIZED_CLIENT_ERROR_CODES); } /** - * Constructs a {@code RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} using the provided parameters. - * - * @param authorizedClientRemover the {@link OAuth2AuthorizedClientRemover} used for removing an {@link OAuth2AuthorizedClient} - * if the error code is one of the {@link #removeAuthorizedClientErrorCodes}. - * @param removeAuthorizedClientErrorCodes the OAuth 2.0 error codes which will trigger removal of an authorized client. + * Constructs a + * {@code RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} using the + * provided parameters. + * @param authorizedClientRemover the {@link OAuth2AuthorizedClientRemover} used for + * removing an {@link OAuth2AuthorizedClient} if the error code is one of the + * {@link #removeAuthorizedClientErrorCodes}. + * @param removeAuthorizedClientErrorCodes the OAuth 2.0 error codes which will + * trigger removal of an authorized client. * @see OAuth2ErrorCodes */ public RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler( - OAuth2AuthorizedClientRemover authorizedClientRemover, - Set removeAuthorizedClientErrorCodes) { + OAuth2AuthorizedClientRemover authorizedClientRemover, Set removeAuthorizedClientErrorCodes) { Assert.notNull(authorizedClientRemover, "authorizedClientRemover cannot be null"); Assert.notNull(removeAuthorizedClientErrorCodes, "removeAuthorizedClientErrorCodes cannot be null"); - this.removeAuthorizedClientErrorCodes = Collections.unmodifiableSet(new HashSet<>(removeAuthorizedClientErrorCodes)); + this.removeAuthorizedClientErrorCodes = Collections + .unmodifiableSet(new HashSet<>(removeAuthorizedClientErrorCodes)); this.delegate = authorizedClientRemover; } @@ -128,22 +145,23 @@ public class RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler imp && hasRemovalErrorCode(authorizationException)) { ClientAuthorizationException clientAuthorizationException = (ClientAuthorizationException) authorizationException; - return this.delegate.removeAuthorizedClient( - clientAuthorizationException.getClientRegistrationId(), principal, attributes); - } else { + return this.delegate.removeAuthorizedClient(clientAuthorizationException.getClientRegistrationId(), + principal, attributes); + } + else { return Mono.empty(); } } /** - * Returns true if the given exception has an error code that - * indicates that the authorized client should be removed. - * + * Returns true if the given exception has an error code that indicates that the + * authorized client should be removed. * @param authorizationException the exception that caused the authorization failure - * @return true if the given exception has an error code that - * indicates that the authorized client should be removed. + * @return true if the given exception has an error code that indicates that the + * authorized client should be removed. */ private boolean hasRemovalErrorCode(OAuth2AuthorizationException authorizationException) { return this.removeAuthorizedClientErrorCodes.contains(authorizationException.getError().getErrorCode()); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/annotation/RegisteredOAuth2AuthorizedClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/annotation/RegisteredOAuth2AuthorizedClient.java index 4bad4aff8e..86925cc002 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/annotation/RegisteredOAuth2AuthorizedClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/annotation/RegisteredOAuth2AuthorizedClient.java @@ -26,12 +26,11 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * This annotation may be used to resolve a method parameter - * to an argument value of type {@link OAuth2AuthorizedClient}. + * This annotation may be used to resolve a method parameter to an argument value of type + * {@link OAuth2AuthorizedClient}. * *

        - * For example: - *

        + * For example: 
          * @Controller
          * public class MyController {
          *     @GetMapping("/authorized-client")
        @@ -52,18 +51,16 @@ public @interface RegisteredOAuth2AuthorizedClient {
         
         	/**
         	 * Sets the client registration identifier.
        -	 *
         	 * @return the client registration identifier
         	 */
         	@AliasFor("value")
         	String registrationId() default "";
         
         	/**
        -	 * The default attribute for this annotation.
        -	 * This is an alias for {@link #registrationId()}.
        -	 * For example, {@code @RegisteredOAuth2AuthorizedClient("login-client")} is equivalent to
        +	 * The default attribute for this annotation. This is an alias for
        +	 * {@link #registrationId()}. For example,
        +	 * {@code @RegisteredOAuth2AuthorizedClient("login-client")} is equivalent to
         	 * {@code @RegisteredOAuth2AuthorizedClient(registrationId="login-client")}.
        -	 *
         	 * @return the client registration identifier
         	 */
         	@AliasFor("registrationId")
        diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthenticationToken.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthenticationToken.java
        index 73fd7d5b19..e63c363ad2 100644
        --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthenticationToken.java
        +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthenticationToken.java
        @@ -26,13 +26,13 @@ import org.springframework.util.Assert;
         import java.util.Collection;
         
         /**
        - * An implementation of an {@link AbstractAuthenticationToken}
        - * that represents an OAuth 2.0 {@link Authentication}.
        + * An implementation of an {@link AbstractAuthenticationToken} that represents an OAuth
        + * 2.0 {@link Authentication}.
          * 

        - * The {@link Authentication} associates an {@link OAuth2User} {@code Principal} - * to the identifier of the {@link #getAuthorizedClientRegistrationId() Authorized Client}, - * which the End-User ({@code Principal}) granted authorization to - * so that it can access it's protected resources at the UserInfo Endpoint. + * The {@link Authentication} associates an {@link OAuth2User} {@code Principal} to the + * identifier of the {@link #getAuthorizedClientRegistrationId() Authorized Client}, which + * the End-User ({@code Principal}) granted authorization to so that it can access it's + * protected resources at the UserInfo Endpoint. * * @author Joe Grandja * @since 5.0 @@ -41,20 +41,22 @@ import java.util.Collection; * @see OAuth2AuthorizedClient */ public class OAuth2AuthenticationToken extends AbstractAuthenticationToken { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private final OAuth2User principal; + private final String authorizedClientRegistrationId; /** * Constructs an {@code OAuth2AuthenticationToken} using the provided parameters. - * * @param principal the user {@code Principal} registered with the OAuth 2.0 Provider * @param authorities the authorities granted to the user - * @param authorizedClientRegistrationId the registration identifier of the {@link OAuth2AuthorizedClient Authorized Client} + * @param authorizedClientRegistrationId the registration identifier of the + * {@link OAuth2AuthorizedClient Authorized Client} */ - public OAuth2AuthenticationToken(OAuth2User principal, - Collection authorities, - String authorizedClientRegistrationId) { + public OAuth2AuthenticationToken(OAuth2User principal, Collection authorities, + String authorizedClientRegistrationId) { super(authorities); Assert.notNull(principal, "principal cannot be null"); Assert.hasText(authorizedClientRegistrationId, "authorizedClientRegistrationId cannot be empty"); @@ -75,11 +77,12 @@ public class OAuth2AuthenticationToken extends AbstractAuthenticationToken { } /** - * Returns the registration identifier of the {@link OAuth2AuthorizedClient Authorized Client}. - * + * Returns the registration identifier of the {@link OAuth2AuthorizedClient Authorized + * Client}. * @return the registration identifier of the Authorized Client. */ public String getAuthorizedClientRegistrationId() { return this.authorizedClientRegistrationId; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java index 4ad62b09ce..a2b3b900a9 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java @@ -28,32 +28,41 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResp import org.springframework.util.Assert; /** - * An implementation of an {@link AuthenticationProvider} for the OAuth 2.0 Authorization Code Grant. + * An implementation of an {@link AuthenticationProvider} for the OAuth 2.0 Authorization + * Code Grant. * *

        - * This {@link AuthenticationProvider} is responsible for authenticating - * an Authorization Code credential with the Authorization Server's Token Endpoint - * and if valid, exchanging it for an Access Token credential. + * This {@link AuthenticationProvider} is responsible for authenticating an Authorization + * Code credential with the Authorization Server's Token Endpoint and if valid, exchanging + * it for an Access Token credential. * * @author Joe Grandja * @since 5.1 * @see OAuth2AuthorizationCodeAuthenticationToken * @see OAuth2AccessTokenResponseClient - * @see Section 4.1 Authorization Code Grant Flow - * @see Section 4.1.3 Access Token Request - * @see Section 4.1.4 Access Token Response + * @see Section + * 4.1 Authorization Code Grant Flow + * @see Section 4.1.3 Access Token + * Request + * @see Section 4.1.4 Access Token + * Response */ public class OAuth2AuthorizationCodeAuthenticationProvider implements AuthenticationProvider { + private static final String INVALID_STATE_PARAMETER_ERROR_CODE = "invalid_state_parameter"; + private final OAuth2AccessTokenResponseClient accessTokenResponseClient; /** - * Constructs an {@code OAuth2AuthorizationCodeAuthenticationProvider} using the provided parameters. - * - * @param accessTokenResponseClient the client used for requesting the access token credential from the Token Endpoint + * Constructs an {@code OAuth2AuthorizationCodeAuthenticationProvider} using the + * provided parameters. + * @param accessTokenResponseClient the client used for requesting the access token + * credential from the Token Endpoint */ public OAuth2AuthorizationCodeAuthenticationProvider( - OAuth2AccessTokenResponseClient accessTokenResponseClient) { + OAuth2AccessTokenResponseClient accessTokenResponseClient) { Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null"); this.accessTokenResponseClient = accessTokenResponseClient; @@ -61,35 +70,29 @@ public class OAuth2AuthorizationCodeAuthenticationProvider implements Authentica @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { - OAuth2AuthorizationCodeAuthenticationToken authorizationCodeAuthentication = - (OAuth2AuthorizationCodeAuthenticationToken) authentication; + OAuth2AuthorizationCodeAuthenticationToken authorizationCodeAuthentication = (OAuth2AuthorizationCodeAuthenticationToken) authentication; - OAuth2AuthorizationResponse authorizationResponse = authorizationCodeAuthentication - .getAuthorizationExchange().getAuthorizationResponse(); + OAuth2AuthorizationResponse authorizationResponse = authorizationCodeAuthentication.getAuthorizationExchange() + .getAuthorizationResponse(); if (authorizationResponse.statusError()) { throw new OAuth2AuthorizationException(authorizationResponse.getError()); } - OAuth2AuthorizationRequest authorizationRequest = authorizationCodeAuthentication - .getAuthorizationExchange().getAuthorizationRequest(); + OAuth2AuthorizationRequest authorizationRequest = authorizationCodeAuthentication.getAuthorizationExchange() + .getAuthorizationRequest(); if (!authorizationResponse.getState().equals(authorizationRequest.getState())) { OAuth2Error oauth2Error = new OAuth2Error(INVALID_STATE_PARAMETER_ERROR_CODE); throw new OAuth2AuthorizationException(oauth2Error); } - OAuth2AccessTokenResponse accessTokenResponse = - this.accessTokenResponseClient.getTokenResponse( - new OAuth2AuthorizationCodeGrantRequest( - authorizationCodeAuthentication.getClientRegistration(), - authorizationCodeAuthentication.getAuthorizationExchange())); + OAuth2AccessTokenResponse accessTokenResponse = this.accessTokenResponseClient.getTokenResponse( + new OAuth2AuthorizationCodeGrantRequest(authorizationCodeAuthentication.getClientRegistration(), + authorizationCodeAuthentication.getAuthorizationExchange())); - OAuth2AuthorizationCodeAuthenticationToken authenticationResult = - new OAuth2AuthorizationCodeAuthenticationToken( + OAuth2AuthorizationCodeAuthenticationToken authenticationResult = new OAuth2AuthorizationCodeAuthenticationToken( authorizationCodeAuthentication.getClientRegistration(), - authorizationCodeAuthentication.getAuthorizationExchange(), - accessTokenResponse.getAccessToken(), - accessTokenResponse.getRefreshToken(), - accessTokenResponse.getAdditionalParameters()); + authorizationCodeAuthentication.getAuthorizationExchange(), accessTokenResponse.getAccessToken(), + accessTokenResponse.getRefreshToken(), accessTokenResponse.getAdditionalParameters()); authenticationResult.setDetails(authorizationCodeAuthentication.getDetails()); return authenticationResult; @@ -99,4 +102,5 @@ public class OAuth2AuthorizationCodeAuthenticationProvider implements Authentica public boolean supports(Class authentication) { return OAuth2AuthorizationCodeAuthenticationToken.class.isAssignableFrom(authentication); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationToken.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationToken.java index 3c45b3e1d7..09f642289d 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationToken.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationToken.java @@ -37,24 +37,31 @@ import java.util.Map; * @see ClientRegistration * @see OAuth2AuthorizationExchange * @see OAuth2AccessToken - * @see Section 4.1 Authorization Code Grant Flow + * @see Section + * 4.1 Authorization Code Grant Flow */ public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenticationToken { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private Map additionalParameters = new HashMap<>(); + private ClientRegistration clientRegistration; + private OAuth2AuthorizationExchange authorizationExchange; + private OAuth2AccessToken accessToken; + private OAuth2RefreshToken refreshToken; /** - * This constructor should be used when the Authorization Request/Response is complete. - * + * This constructor should be used when the Authorization Request/Response is + * complete. * @param clientRegistration the client registration * @param authorizationExchange the authorization exchange */ public OAuth2AuthorizationCodeAuthenticationToken(ClientRegistration clientRegistration, - OAuth2AuthorizationExchange authorizationExchange) { + OAuth2AuthorizationExchange authorizationExchange) { super(Collections.emptyList()); Assert.notNull(clientRegistration, "clientRegistration cannot be null"); Assert.notNull(authorizationExchange, "authorizationExchange cannot be null"); @@ -65,35 +72,32 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenti /** * This constructor should be used when the Access Token Request/Response is complete, * which indicates that the Authorization Code Grant flow has fully completed. - * * @param clientRegistration the client registration * @param authorizationExchange the authorization exchange * @param accessToken the access token credential */ public OAuth2AuthorizationCodeAuthenticationToken(ClientRegistration clientRegistration, - OAuth2AuthorizationExchange authorizationExchange, - OAuth2AccessToken accessToken) { + OAuth2AuthorizationExchange authorizationExchange, OAuth2AccessToken accessToken) { this(clientRegistration, authorizationExchange, accessToken, null); } /** * This constructor should be used when the Access Token Request/Response is complete, * which indicates that the Authorization Code Grant flow has fully completed. - * * @param clientRegistration the client registration * @param authorizationExchange the authorization exchange * @param accessToken the access token credential * @param refreshToken the refresh token credential */ public OAuth2AuthorizationCodeAuthenticationToken(ClientRegistration clientRegistration, - OAuth2AuthorizationExchange authorizationExchange, - OAuth2AccessToken accessToken, - @Nullable OAuth2RefreshToken refreshToken) { + OAuth2AuthorizationExchange authorizationExchange, OAuth2AccessToken accessToken, + @Nullable OAuth2RefreshToken refreshToken) { this(clientRegistration, authorizationExchange, accessToken, refreshToken, Collections.emptyMap()); } - public OAuth2AuthorizationCodeAuthenticationToken(ClientRegistration clientRegistration, OAuth2AuthorizationExchange authorizationExchange, OAuth2AccessToken accessToken, OAuth2RefreshToken refreshToken, - Map additionalParameters) { + public OAuth2AuthorizationCodeAuthenticationToken(ClientRegistration clientRegistration, + OAuth2AuthorizationExchange authorizationExchange, OAuth2AccessToken accessToken, + OAuth2RefreshToken refreshToken, Map additionalParameters) { this(clientRegistration, authorizationExchange); Assert.notNull(accessToken, "accessToken cannot be null"); this.accessToken = accessToken; @@ -109,14 +113,12 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenti @Override public Object getCredentials() { - return this.accessToken != null ? - this.accessToken.getTokenValue() : - this.authorizationExchange.getAuthorizationResponse().getCode(); + return this.accessToken != null ? this.accessToken.getTokenValue() + : this.authorizationExchange.getAuthorizationResponse().getCode(); } /** * Returns the {@link ClientRegistration client registration}. - * * @return the {@link ClientRegistration} */ public ClientRegistration getClientRegistration() { @@ -125,7 +127,6 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenti /** * Returns the {@link OAuth2AuthorizationExchange authorization exchange}. - * * @return the {@link OAuth2AuthorizationExchange} */ public OAuth2AuthorizationExchange getAuthorizationExchange() { @@ -134,7 +135,6 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenti /** * Returns the {@link OAuth2AccessToken access token}. - * * @return the {@link OAuth2AccessToken} */ public OAuth2AccessToken getAccessToken() { @@ -143,7 +143,6 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenti /** * Returns the {@link OAuth2RefreshToken refresh token}. - * * @return the {@link OAuth2RefreshToken} */ public @Nullable OAuth2RefreshToken getRefreshToken() { @@ -152,10 +151,10 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenti /** * Returns the additional parameters - * * @return the additional parameters */ public Map getAdditionalParameters() { return this.additionalParameters; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeReactiveAuthenticationManager.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeReactiveAuthenticationManager.java index 28e4d7bdfe..0e4d36bab5 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeReactiveAuthenticationManager.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeReactiveAuthenticationManager.java @@ -36,18 +36,20 @@ import reactor.core.publisher.Mono; import java.util.function.Function; /** - * An implementation of an {@link org.springframework.security.authentication.AuthenticationProvider} for OAuth 2.0 Login, - * which leverages the OAuth 2.0 Authorization Code Grant Flow. + * An implementation of an + * {@link org.springframework.security.authentication.AuthenticationProvider} for OAuth + * 2.0 Login, which leverages the OAuth 2.0 Authorization Code Grant Flow. * - * This {@link org.springframework.security.authentication.AuthenticationProvider} is responsible for authenticating - * an Authorization Code credential with the Authorization Server's Token Endpoint - * and if valid, exchanging it for an Access Token credential. + * This {@link org.springframework.security.authentication.AuthenticationProvider} is + * responsible for authenticating an Authorization Code credential with the Authorization + * Server's Token Endpoint and if valid, exchanging it for an Access Token credential. *

        - * It will also obtain the user attributes of the End-User (Resource Owner) - * from the UserInfo Endpoint using an {@link org.springframework.security.oauth2.client.userinfo.OAuth2UserService}, - * which will create a {@code Principal} in the form of an {@link OAuth2User}. - * The {@code OAuth2User} is then associated to the {@link OAuth2LoginAuthenticationToken} - * to complete the authentication. + * It will also obtain the user attributes of the End-User (Resource Owner) from the + * UserInfo Endpoint using an + * {@link org.springframework.security.oauth2.client.userinfo.OAuth2UserService}, which + * will create a {@code Principal} in the form of an {@link OAuth2User}. The + * {@code OAuth2User} is then associated to the {@link OAuth2LoginAuthenticationToken} to + * complete the authentication. * * @author Rob Winch * @since 5.1 @@ -55,12 +57,19 @@ import java.util.function.Function; * @see ReactiveOAuth2AccessTokenResponseClient * @see ReactiveOAuth2UserService * @see OAuth2User - * @see Section 4.1 Authorization Code Grant Flow - * @see Section 4.1.3 Access Token Request - * @see Section 4.1.4 Access Token Response + * @see Section + * 4.1 Authorization Code Grant Flow + * @see Section 4.1.3 Access Token + * Request + * @see Section 4.1.4 Access Token + * Response */ public class OAuth2AuthorizationCodeReactiveAuthenticationManager implements ReactiveAuthenticationManager { + private static final String INVALID_STATE_PARAMETER_ERROR_CODE = "invalid_state_parameter"; + private final ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient; public OAuth2AuthorizationCodeReactiveAuthenticationManager( @@ -74,33 +83,36 @@ public class OAuth2AuthorizationCodeReactiveAuthenticationManager implements Rea return Mono.defer(() -> { OAuth2AuthorizationCodeAuthenticationToken token = (OAuth2AuthorizationCodeAuthenticationToken) authentication; - OAuth2AuthorizationResponse authorizationResponse = token.getAuthorizationExchange().getAuthorizationResponse(); + OAuth2AuthorizationResponse authorizationResponse = token.getAuthorizationExchange() + .getAuthorizationResponse(); if (authorizationResponse.statusError()) { return Mono.error(new OAuth2AuthorizationException(authorizationResponse.getError())); } - OAuth2AuthorizationRequest authorizationRequest = token.getAuthorizationExchange().getAuthorizationRequest(); + OAuth2AuthorizationRequest authorizationRequest = token.getAuthorizationExchange() + .getAuthorizationRequest(); if (!authorizationResponse.getState().equals(authorizationRequest.getState())) { OAuth2Error oauth2Error = new OAuth2Error(INVALID_STATE_PARAMETER_ERROR_CODE); return Mono.error(new OAuth2AuthorizationException(oauth2Error)); } OAuth2AuthorizationCodeGrantRequest authzRequest = new OAuth2AuthorizationCodeGrantRequest( - token.getClientRegistration(), - token.getAuthorizationExchange()); + token.getClientRegistration(), token.getAuthorizationExchange()); - return this.accessTokenResponseClient.getTokenResponse(authzRequest) - .map(onSuccess(token)); + return this.accessTokenResponseClient.getTokenResponse(authzRequest).map(onSuccess(token)); }); } - private Function onSuccess(OAuth2AuthorizationCodeAuthenticationToken token) { + private Function onSuccess( + OAuth2AuthorizationCodeAuthenticationToken token) { return accessTokenResponse -> { ClientRegistration registration = token.getClientRegistration(); OAuth2AuthorizationExchange exchange = token.getAuthorizationExchange(); OAuth2AccessToken accessToken = accessTokenResponse.getAccessToken(); OAuth2RefreshToken refreshToken = accessTokenResponse.getRefreshToken(); - return new OAuth2AuthorizationCodeAuthenticationToken(registration, exchange, accessToken, refreshToken, accessTokenResponse.getAdditionalParameters()); + return new OAuth2AuthorizationCodeAuthenticationToken(registration, exchange, accessToken, refreshToken, + accessTokenResponse.getAdditionalParameters()); }; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationProvider.java index 8d3b70234d..d27e0fe7c2 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationProvider.java @@ -35,18 +35,18 @@ import java.util.Collection; import java.util.Map; /** - * An implementation of an {@link AuthenticationProvider} for OAuth 2.0 Login, - * which leverages the OAuth 2.0 Authorization Code Grant Flow. + * An implementation of an {@link AuthenticationProvider} for OAuth 2.0 Login, which + * leverages the OAuth 2.0 Authorization Code Grant Flow. * - * This {@link AuthenticationProvider} is responsible for authenticating - * an Authorization Code credential with the Authorization Server's Token Endpoint - * and if valid, exchanging it for an Access Token credential. + * This {@link AuthenticationProvider} is responsible for authenticating an Authorization + * Code credential with the Authorization Server's Token Endpoint and if valid, exchanging + * it for an Access Token credential. *

        - * It will also obtain the user attributes of the End-User (Resource Owner) - * from the UserInfo Endpoint using an {@link OAuth2UserService}, - * which will create a {@code Principal} in the form of an {@link OAuth2User}. - * The {@code OAuth2User} is then associated to the {@link OAuth2LoginAuthenticationToken} - * to complete the authentication. + * It will also obtain the user attributes of the End-User (Resource Owner) from the + * UserInfo Endpoint using an {@link OAuth2UserService}, which will create a + * {@code Principal} in the form of an {@link OAuth2User}. The {@code OAuth2User} is then + * associated to the {@link OAuth2LoginAuthenticationToken} to complete the + * authentication. * * @author Joe Grandja * @since 5.0 @@ -54,40 +54,51 @@ import java.util.Map; * @see OAuth2AccessTokenResponseClient * @see OAuth2UserService * @see OAuth2User - * @see Section 4.1 Authorization Code Grant Flow - * @see Section 4.1.3 Access Token Request - * @see Section 4.1.4 Access Token Response + * @see Section + * 4.1 Authorization Code Grant Flow + * @see Section 4.1.3 Access Token + * Request + * @see Section 4.1.4 Access Token + * Response */ public class OAuth2LoginAuthenticationProvider implements AuthenticationProvider { + private final OAuth2AuthorizationCodeAuthenticationProvider authorizationCodeAuthenticationProvider; + private final OAuth2UserService userService; + private GrantedAuthoritiesMapper authoritiesMapper = (authorities -> authorities); /** - * Constructs an {@code OAuth2LoginAuthenticationProvider} using the provided parameters. - * - * @param accessTokenResponseClient the client used for requesting the access token credential from the Token Endpoint - * @param userService the service used for obtaining the user attributes of the End-User from the UserInfo Endpoint + * Constructs an {@code OAuth2LoginAuthenticationProvider} using the provided + * parameters. + * @param accessTokenResponseClient the client used for requesting the access token + * credential from the Token Endpoint + * @param userService the service used for obtaining the user attributes of the + * End-User from the UserInfo Endpoint */ public OAuth2LoginAuthenticationProvider( - OAuth2AccessTokenResponseClient accessTokenResponseClient, - OAuth2UserService userService) { + OAuth2AccessTokenResponseClient accessTokenResponseClient, + OAuth2UserService userService) { Assert.notNull(userService, "userService cannot be null"); - this.authorizationCodeAuthenticationProvider = new OAuth2AuthorizationCodeAuthenticationProvider(accessTokenResponseClient); + this.authorizationCodeAuthenticationProvider = new OAuth2AuthorizationCodeAuthenticationProvider( + accessTokenResponseClient); this.userService = userService; } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { - OAuth2LoginAuthenticationToken loginAuthenticationToken = - (OAuth2LoginAuthenticationToken) authentication; + OAuth2LoginAuthenticationToken loginAuthenticationToken = (OAuth2LoginAuthenticationToken) authentication; - // Section 3.1.2.1 Authentication Request - https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest + // Section 3.1.2.1 Authentication Request - + // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest // scope - // REQUIRED. OpenID Connect requests MUST contain the "openid" scope value. - if (loginAuthenticationToken.getAuthorizationExchange() - .getAuthorizationRequest().getScopes().contains("openid")) { + // REQUIRED. OpenID Connect requests MUST contain the "openid" scope value. + if (loginAuthenticationToken.getAuthorizationExchange().getAuthorizationRequest().getScopes() + .contains("openid")) { // This is an OpenID Connect Authentication Request so return null // and let OidcAuthorizationCodeAuthenticationProvider handle it instead return null; @@ -99,7 +110,8 @@ public class OAuth2LoginAuthenticationProvider implements AuthenticationProvider .authenticate(new OAuth2AuthorizationCodeAuthenticationToken( loginAuthenticationToken.getClientRegistration(), loginAuthenticationToken.getAuthorizationExchange())); - } catch (OAuth2AuthorizationException ex) { + } + catch (OAuth2AuthorizationException ex) { OAuth2Error oauth2Error = ex.getError(); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } @@ -110,26 +122,23 @@ public class OAuth2LoginAuthenticationProvider implements AuthenticationProvider OAuth2User oauth2User = this.userService.loadUser(new OAuth2UserRequest( loginAuthenticationToken.getClientRegistration(), accessToken, additionalParameters)); - Collection mappedAuthorities = - this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities()); + Collection mappedAuthorities = this.authoritiesMapper + .mapAuthorities(oauth2User.getAuthorities()); OAuth2LoginAuthenticationToken authenticationResult = new OAuth2LoginAuthenticationToken( - loginAuthenticationToken.getClientRegistration(), - loginAuthenticationToken.getAuthorizationExchange(), - oauth2User, - mappedAuthorities, - accessToken, - authorizationCodeAuthenticationToken.getRefreshToken()); + loginAuthenticationToken.getClientRegistration(), loginAuthenticationToken.getAuthorizationExchange(), + oauth2User, mappedAuthorities, accessToken, authorizationCodeAuthenticationToken.getRefreshToken()); authenticationResult.setDetails(loginAuthenticationToken.getDetails()); return authenticationResult; } /** - * Sets the {@link GrantedAuthoritiesMapper} used for mapping {@link OAuth2User#getAuthorities()} - * to a new set of authorities which will be associated to the {@link OAuth2LoginAuthenticationToken}. - * - * @param authoritiesMapper the {@link GrantedAuthoritiesMapper} used for mapping the user's authorities + * Sets the {@link GrantedAuthoritiesMapper} used for mapping + * {@link OAuth2User#getAuthorities()} to a new set of authorities which will be + * associated to the {@link OAuth2LoginAuthenticationToken}. + * @param authoritiesMapper the {@link GrantedAuthoritiesMapper} used for mapping the + * user's authorities */ public final void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) { Assert.notNull(authoritiesMapper, "authoritiesMapper cannot be null"); @@ -140,4 +149,5 @@ public class OAuth2LoginAuthenticationProvider implements AuthenticationProvider public boolean supports(Class authentication) { return OAuth2LoginAuthenticationToken.class.isAssignableFrom(authentication); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationToken.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationToken.java index a8fc5fd128..e0976bbe98 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationToken.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationToken.java @@ -30,8 +30,8 @@ import java.util.Collection; import java.util.Collections; /** - * An {@link AbstractAuthenticationToken} for OAuth 2.0 Login, - * which leverages the OAuth 2.0 Authorization Code Grant Flow. + * An {@link AbstractAuthenticationToken} for OAuth 2.0 Login, which leverages the OAuth + * 2.0 Authorization Code Grant Flow. * * @author Joe Grandja * @since 5.0 @@ -40,24 +40,31 @@ import java.util.Collections; * @see ClientRegistration * @see OAuth2AuthorizationExchange * @see OAuth2AccessToken - * @see Section 4.1 Authorization Code Grant Flow + * @see Section + * 4.1 Authorization Code Grant Flow */ public class OAuth2LoginAuthenticationToken extends AbstractAuthenticationToken { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private OAuth2User principal; + private ClientRegistration clientRegistration; + private OAuth2AuthorizationExchange authorizationExchange; + private OAuth2AccessToken accessToken; + private OAuth2RefreshToken refreshToken; /** - * This constructor should be used when the Authorization Request/Response is complete. - * + * This constructor should be used when the Authorization Request/Response is + * complete. * @param clientRegistration the client registration * @param authorizationExchange the authorization exchange */ public OAuth2LoginAuthenticationToken(ClientRegistration clientRegistration, - OAuth2AuthorizationExchange authorizationExchange) { + OAuth2AuthorizationExchange authorizationExchange) { super(Collections.emptyList()); Assert.notNull(clientRegistration, "clientRegistration cannot be null"); @@ -69,9 +76,8 @@ public class OAuth2LoginAuthenticationToken extends AbstractAuthenticationToken /** * This constructor should be used when the Access Token Request/Response is complete, - * which indicates that the Authorization Code Grant flow has fully completed - * and OAuth 2.0 Login has been achieved. - * + * which indicates that the Authorization Code Grant flow has fully completed and + * OAuth 2.0 Login has been achieved. * @param clientRegistration the client registration * @param authorizationExchange the authorization exchange * @param principal the user {@code Principal} registered with the OAuth 2.0 Provider @@ -79,18 +85,15 @@ public class OAuth2LoginAuthenticationToken extends AbstractAuthenticationToken * @param accessToken the access token credential */ public OAuth2LoginAuthenticationToken(ClientRegistration clientRegistration, - OAuth2AuthorizationExchange authorizationExchange, - OAuth2User principal, - Collection authorities, - OAuth2AccessToken accessToken) { + OAuth2AuthorizationExchange authorizationExchange, OAuth2User principal, + Collection authorities, OAuth2AccessToken accessToken) { this(clientRegistration, authorizationExchange, principal, authorities, accessToken, null); } /** * This constructor should be used when the Access Token Request/Response is complete, - * which indicates that the Authorization Code Grant flow has fully completed - * and OAuth 2.0 Login has been achieved. - * + * which indicates that the Authorization Code Grant flow has fully completed and + * OAuth 2.0 Login has been achieved. * @param clientRegistration the client registration * @param authorizationExchange the authorization exchange * @param principal the user {@code Principal} registered with the OAuth 2.0 Provider @@ -99,11 +102,9 @@ public class OAuth2LoginAuthenticationToken extends AbstractAuthenticationToken * @param refreshToken the refresh token credential */ public OAuth2LoginAuthenticationToken(ClientRegistration clientRegistration, - OAuth2AuthorizationExchange authorizationExchange, - OAuth2User principal, - Collection authorities, - OAuth2AccessToken accessToken, - @Nullable OAuth2RefreshToken refreshToken) { + OAuth2AuthorizationExchange authorizationExchange, OAuth2User principal, + Collection authorities, OAuth2AccessToken accessToken, + @Nullable OAuth2RefreshToken refreshToken) { super(authorities); Assert.notNull(clientRegistration, "clientRegistration cannot be null"); Assert.notNull(authorizationExchange, "authorizationExchange cannot be null"); @@ -129,7 +130,6 @@ public class OAuth2LoginAuthenticationToken extends AbstractAuthenticationToken /** * Returns the {@link ClientRegistration client registration}. - * * @return the {@link ClientRegistration} */ public ClientRegistration getClientRegistration() { @@ -138,7 +138,6 @@ public class OAuth2LoginAuthenticationToken extends AbstractAuthenticationToken /** * Returns the {@link OAuth2AuthorizationExchange authorization exchange}. - * * @return the {@link OAuth2AuthorizationExchange} */ public OAuth2AuthorizationExchange getAuthorizationExchange() { @@ -147,7 +146,6 @@ public class OAuth2LoginAuthenticationToken extends AbstractAuthenticationToken /** * Returns the {@link OAuth2AccessToken access token}. - * * @return the {@link OAuth2AccessToken} */ public OAuth2AccessToken getAccessToken() { @@ -163,4 +161,5 @@ public class OAuth2LoginAuthenticationToken extends AbstractAuthenticationToken public @Nullable OAuth2RefreshToken getRefreshToken() { return this.refreshToken; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginReactiveAuthenticationManager.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginReactiveAuthenticationManager.java index 9fb1820ff5..e157b3ae40 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginReactiveAuthenticationManager.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginReactiveAuthenticationManager.java @@ -34,18 +34,20 @@ import java.util.Collection; import java.util.Map; /** - * An implementation of an {@link org.springframework.security.authentication.AuthenticationProvider} for OAuth 2.0 Login, - * which leverages the OAuth 2.0 Authorization Code Grant Flow. + * An implementation of an + * {@link org.springframework.security.authentication.AuthenticationProvider} for OAuth + * 2.0 Login, which leverages the OAuth 2.0 Authorization Code Grant Flow. * - * This {@link org.springframework.security.authentication.AuthenticationProvider} is responsible for authenticating - * an Authorization Code credential with the Authorization Server's Token Endpoint - * and if valid, exchanging it for an Access Token credential. + * This {@link org.springframework.security.authentication.AuthenticationProvider} is + * responsible for authenticating an Authorization Code credential with the Authorization + * Server's Token Endpoint and if valid, exchanging it for an Access Token credential. *

        - * It will also obtain the user attributes of the End-User (Resource Owner) - * from the UserInfo Endpoint using an {@link org.springframework.security.oauth2.client.userinfo.OAuth2UserService}, - * which will create a {@code Principal} in the form of an {@link OAuth2User}. - * The {@code OAuth2User} is then associated to the {@link OAuth2LoginAuthenticationToken} - * to complete the authentication. + * It will also obtain the user attributes of the End-User (Resource Owner) from the + * UserInfo Endpoint using an + * {@link org.springframework.security.oauth2.client.userinfo.OAuth2UserService}, which + * will create a {@code Principal} in the form of an {@link OAuth2User}. The + * {@code OAuth2User} is then associated to the {@link OAuth2LoginAuthenticationToken} to + * complete the authentication. * * @author Rob Winch * @since 5.1 @@ -53,12 +55,17 @@ import java.util.Map; * @see org.springframework.security.oauth2.client.endpoint.ReactiveOAuth2AccessTokenResponseClient * @see org.springframework.security.oauth2.client.userinfo.ReactiveOAuth2UserService * @see OAuth2User - * @see Section 4.1 Authorization Code Grant Flow - * @see Section 4.1.3 Access Token Request - * @see Section 4.1.4 Access Token Response + * @see Section + * 4.1 Authorization Code Grant Flow + * @see Section 4.1.3 Access Token + * Request + * @see Section 4.1.4 Access Token + * Response */ -public class OAuth2LoginReactiveAuthenticationManager implements - ReactiveAuthenticationManager { +public class OAuth2LoginReactiveAuthenticationManager implements ReactiveAuthenticationManager { + private final ReactiveAuthenticationManager authorizationCodeManager; private final ReactiveOAuth2UserService userService; @@ -70,7 +77,8 @@ public class OAuth2LoginReactiveAuthenticationManager implements ReactiveOAuth2UserService userService) { Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null"); Assert.notNull(userService, "userService cannot be null"); - this.authorizationCodeManager = new OAuth2AuthorizationCodeReactiveAuthenticationManager(accessTokenResponseClient); + this.authorizationCodeManager = new OAuth2AuthorizationCodeReactiveAuthenticationManager( + accessTokenResponseClient); this.userService = userService; } @@ -79,28 +87,32 @@ public class OAuth2LoginReactiveAuthenticationManager implements return Mono.defer(() -> { OAuth2AuthorizationCodeAuthenticationToken token = (OAuth2AuthorizationCodeAuthenticationToken) authentication; - // Section 3.1.2.1 Authentication Request - https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest - // scope REQUIRED. OpenID Connect requests MUST contain the "openid" scope value. - if (token.getAuthorizationExchange() - .getAuthorizationRequest().getScopes().contains("openid")) { + // Section 3.1.2.1 Authentication Request - + // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest + // scope REQUIRED. OpenID Connect requests MUST contain the "openid" scope + // value. + if (token.getAuthorizationExchange().getAuthorizationRequest().getScopes().contains("openid")) { // This is an OpenID Connect Authentication Request so return null - // and let OidcAuthorizationCodeReactiveAuthenticationManager handle it instead once one is created + // and let OidcAuthorizationCodeReactiveAuthenticationManager handle it + // instead once one is created return Mono.empty(); } return this.authorizationCodeManager.authenticate(token) - .onErrorMap(OAuth2AuthorizationException.class, e -> new OAuth2AuthenticationException(e.getError(), e.getError().toString())) - .cast(OAuth2AuthorizationCodeAuthenticationToken.class) - .flatMap(this::onSuccess); + .onErrorMap(OAuth2AuthorizationException.class, + e -> new OAuth2AuthenticationException(e.getError(), e.getError().toString())) + .cast(OAuth2AuthorizationCodeAuthenticationToken.class).flatMap(this::onSuccess); }); } /** - * Sets the {@link GrantedAuthoritiesMapper} used for mapping {@link OAuth2User#getAuthorities()} - * to a new set of authorities which will be associated to the {@link OAuth2LoginAuthenticationToken}. + * Sets the {@link GrantedAuthoritiesMapper} used for mapping + * {@link OAuth2User#getAuthorities()} to a new set of authorities which will be + * associated to the {@link OAuth2LoginAuthenticationToken}. * * @since 5.4 - * @param authoritiesMapper the {@link GrantedAuthoritiesMapper} used for mapping the user's authorities + * @param authoritiesMapper the {@link GrantedAuthoritiesMapper} used for mapping the + * user's authorities */ public final void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) { Assert.notNull(authoritiesMapper, "authoritiesMapper cannot be null"); @@ -110,20 +122,17 @@ public class OAuth2LoginReactiveAuthenticationManager implements private Mono onSuccess(OAuth2AuthorizationCodeAuthenticationToken authentication) { OAuth2AccessToken accessToken = authentication.getAccessToken(); Map additionalParameters = authentication.getAdditionalParameters(); - OAuth2UserRequest userRequest = new OAuth2UserRequest(authentication.getClientRegistration(), accessToken, additionalParameters); - return this.userService.loadUser(userRequest) - .map(oauth2User -> { - Collection mappedAuthorities = - this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities()); + OAuth2UserRequest userRequest = new OAuth2UserRequest(authentication.getClientRegistration(), accessToken, + additionalParameters); + return this.userService.loadUser(userRequest).map(oauth2User -> { + Collection mappedAuthorities = this.authoritiesMapper + .mapAuthorities(oauth2User.getAuthorities()); - OAuth2LoginAuthenticationToken authenticationResult = new OAuth2LoginAuthenticationToken( - authentication.getClientRegistration(), - authentication.getAuthorizationExchange(), - oauth2User, - mappedAuthorities, - accessToken, - authentication.getRefreshToken()); - return authenticationResult; - }); + OAuth2LoginAuthenticationToken authenticationResult = new OAuth2LoginAuthenticationToken( + authentication.getClientRegistration(), authentication.getAuthorizationExchange(), oauth2User, + mappedAuthorities, accessToken, authentication.getRefreshToken()); + return authenticationResult; + }); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/package-info.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/package-info.java index 1fe301ac98..8ca0e3b135 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/package-info.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/authentication/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Support classes and interfaces for authenticating and authorizing a client - * with an OAuth 2.0 Authorization Server using a specific authorization grant flow. + * Support classes and interfaces for authenticating and authorizing a client with an + * OAuth 2.0 Authorization Server using a specific authorization grant flow. */ package org.springframework.security.oauth2.client.authentication; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractOAuth2AuthorizationGrantRequest.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractOAuth2AuthorizationGrantRequest.java index d1c7f26aa4..900f2c828b 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractOAuth2AuthorizationGrantRequest.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractOAuth2AuthorizationGrantRequest.java @@ -19,21 +19,22 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.util.Assert; /** - * Base implementation of an OAuth 2.0 Authorization Grant request - * that holds an authorization grant credential and is used when - * initiating a request to the Authorization Server's Token Endpoint. + * Base implementation of an OAuth 2.0 Authorization Grant request that holds an + * authorization grant credential and is used when initiating a request to the + * Authorization Server's Token Endpoint. * * @author Joe Grandja * @since 5.0 * @see AuthorizationGrantType - * @see Section 1.3 Authorization Grant + * @see Section + * 1.3 Authorization Grant */ public abstract class AbstractOAuth2AuthorizationGrantRequest { + private final AuthorizationGrantType authorizationGrantType; /** * Sub-class constructor. - * * @param authorizationGrantType the authorization grant type */ protected AbstractOAuth2AuthorizationGrantRequest(AuthorizationGrantType authorizationGrantType) { @@ -43,10 +44,10 @@ public abstract class AbstractOAuth2AuthorizationGrantRequest { /** * Returns the authorization grant type. - * * @return the authorization grant type */ public AuthorizationGrantType getGrantType() { return this.authorizationGrantType; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java index 2991b855a8..a9397e8c2a 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java @@ -35,17 +35,22 @@ import java.util.Set; import static org.springframework.security.oauth2.core.web.reactive.function.OAuth2BodyExtractors.oauth2AccessTokenResponse; /** - * Abstract base class for all of the {@code WebClientReactive*TokenResponseClient}s - * that communicate to the Authorization Server's Token Endpoint. + * Abstract base class for all of the {@code WebClientReactive*TokenResponseClient}s that + * communicate to the Authorization Server's Token Endpoint. * - *

        Submits a form request body specific to the type of grant request.

        + *

        + * Submits a form request body specific to the type of grant request. + *

        * - *

        Accepts a JSON response body containing an OAuth 2.0 Access token or error.

        + *

        + * Accepts a JSON response body containing an OAuth 2.0 Access token or error. + *

        * * @author Phil Clay * @since 5.3 * @param type of grant request - * @see RFC-6749 Token Endpoint + * @see RFC-6749 Token + * Endpoint * @see WebClientReactiveAuthorizationCodeTokenResponseClient * @see WebClientReactiveClientCredentialsTokenResponseClient * @see WebClientReactivePasswordTokenResponseClient @@ -59,17 +64,15 @@ abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient getTokenResponse(T grantRequest) { Assert.notNull(grantRequest, "grantRequest cannot be null"); - return Mono.defer(() -> this.webClient.post() - .uri(clientRegistration(grantRequest).getProviderDetails().getTokenUri()) - .headers(headers -> populateTokenRequestHeaders(grantRequest, headers)) - .body(createTokenRequestBody(grantRequest)) - .exchange() - .flatMap(response -> readTokenResponse(grantRequest, response))); + return Mono.defer( + () -> this.webClient.post().uri(clientRegistration(grantRequest).getProviderDetails().getTokenUri()) + .headers(headers -> populateTokenRequestHeaders(grantRequest, headers)) + .body(createTokenRequestBody(grantRequest)).exchange() + .flatMap(response -> readTokenResponse(grantRequest, response))); } /** * Returns the {@link ClientRegistration} for the given {@code grantRequest}. - * * @param grantRequest the grant request * @return the {@link ClientRegistration} for the given {@code grantRequest}. */ @@ -77,7 +80,6 @@ abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClientThis method pre-populates the body with some standard properties, - * and then delegates to {@link #populateTokenRequestBody(AbstractOAuth2AuthorizationGrantRequest, BodyInserters.FormInserter)} - * for subclasses to further populate the body before returning.

        - * + *

        + * This method pre-populates the body with some standard properties, and then + * delegates to + * {@link #populateTokenRequestBody(AbstractOAuth2AuthorizationGrantRequest, BodyInserters.FormInserter)} + * for subclasses to further populate the body before returning. + *

        * @param grantRequest the grant request * @return the body for the token request. */ private BodyInserters.FormInserter createTokenRequestBody(T grantRequest) { - BodyInserters.FormInserter body = BodyInserters - .fromFormData(OAuth2ParameterNames.GRANT_TYPE, grantRequest.getGrantType().getValue()); + BodyInserters.FormInserter body = BodyInserters.fromFormData(OAuth2ParameterNames.GRANT_TYPE, + grantRequest.getGrantType().getValue()); return populateTokenRequestBody(grantRequest, body); } /** * Populates the body of the token request. * - *

        By default, populates properties that are common to all grant types. - * Subclasses can extend this method to populate grant type specific properties.

        - * + *

        + * By default, populates properties that are common to all grant types. Subclasses can + * extend this method to populate grant type specific properties. + *

        * @param grantRequest the grant request * @param body the body to populate * @return the populated body */ - BodyInserters.FormInserter populateTokenRequestBody(T grantRequest, BodyInserters.FormInserter body) { + BodyInserters.FormInserter populateTokenRequestBody(T grantRequest, + BodyInserters.FormInserter body) { ClientRegistration clientRegistration = clientRegistration(grantRequest); if (!ClientAuthenticationMethod.BASIC.equals(clientRegistration.getClientAuthenticationMethod())) { body.with(OAuth2ParameterNames.CLIENT_ID, clientRegistration.getClientId()); @@ -126,31 +132,30 @@ abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient scopes = scopes(grantRequest); if (!CollectionUtils.isEmpty(scopes)) { - body.with(OAuth2ParameterNames.SCOPE, - StringUtils.collectionToDelimitedString(scopes, " ")); + body.with(OAuth2ParameterNames.SCOPE, StringUtils.collectionToDelimitedString(scopes, " ")); } return body; } /** * Returns the scopes to include as a property in the token request. - * * @param grantRequest the grant request * @return the scopes to include as a property in the token request. */ abstract Set scopes(T grantRequest); /** - * Returns the scopes to include in the response if the authorization - * server returned no scopes in the response. - * - *

        As per RFC-6749 Section 5.1 Successful Access Token Response, - * if AccessTokenResponse.scope is empty, then default to the scope - * originally requested by the client in the Token Request.

        + * Returns the scopes to include in the response if the authorization server returned + * no scopes in the response. * + *

        + * As per RFC-6749 Section + * 5.1 Successful Access Token Response, if AccessTokenResponse.scope is empty, + * then default to the scope originally requested by the client in the Token Request. + *

        * @param grantRequest the grant request - * @return the scopes to include in the response if the authorization - * server returned no scopes. + * @return the scopes to include in the response if the authorization server returned + * no scopes. */ Set defaultScopes(T grantRequest) { return scopes(grantRequest); @@ -158,7 +163,6 @@ abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient defaultScopes = defaultScopes(grantRequest); - tokenResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse) - .scopes(defaultScopes) - .build(); + tokenResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse).scopes(defaultScopes).build(); } return tokenResponse; } /** - * Sets the {@link WebClient} used when requesting the OAuth 2.0 Access Token Response. - * - * @param webClient the {@link WebClient} used when requesting the Access Token Response + * Sets the {@link WebClient} used when requesting the OAuth 2.0 Access Token + * Response. + * @param webClient the {@link WebClient} used when requesting the Access Token + * Response */ public void setWebClient(WebClient webClient) { Assert.notNull(webClient, "webClient cannot be null"); this.webClient = webClient; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClient.java index 174dc75e43..656d55c195 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClient.java @@ -36,36 +36,42 @@ import org.springframework.web.client.RestTemplate; import java.util.Arrays; /** - * The default implementation of an {@link OAuth2AccessTokenResponseClient} - * for the {@link AuthorizationGrantType#AUTHORIZATION_CODE authorization_code} grant. - * This implementation uses a {@link RestOperations} when requesting - * an access token credential at the Authorization Server's Token Endpoint. + * The default implementation of an {@link OAuth2AccessTokenResponseClient} for the + * {@link AuthorizationGrantType#AUTHORIZATION_CODE authorization_code} grant. This + * implementation uses a {@link RestOperations} when requesting an access token credential + * at the Authorization Server's Token Endpoint. * * @author Joe Grandja * @since 5.1 * @see OAuth2AccessTokenResponseClient * @see OAuth2AuthorizationCodeGrantRequest * @see OAuth2AccessTokenResponse - * @see Section 4.1.3 Access Token Request (Authorization Code Grant) - * @see Section 4.1.4 Access Token Response (Authorization Code Grant) + * @see Section 4.1.3 Access Token Request + * (Authorization Code Grant) + * @see Section 4.1.4 Access Token Response + * (Authorization Code Grant) */ -public final class DefaultAuthorizationCodeTokenResponseClient implements OAuth2AccessTokenResponseClient { +public final class DefaultAuthorizationCodeTokenResponseClient + implements OAuth2AccessTokenResponseClient { + private static final String INVALID_TOKEN_RESPONSE_ERROR_CODE = "invalid_token_response"; - private Converter> requestEntityConverter = - new OAuth2AuthorizationCodeGrantRequestEntityConverter(); + private Converter> requestEntityConverter = new OAuth2AuthorizationCodeGrantRequestEntityConverter(); private RestOperations restOperations; public DefaultAuthorizationCodeTokenResponseClient() { - RestTemplate restTemplate = new RestTemplate(Arrays.asList( - new FormHttpMessageConverter(), new OAuth2AccessTokenResponseHttpMessageConverter())); + RestTemplate restTemplate = new RestTemplate( + Arrays.asList(new FormHttpMessageConverter(), new OAuth2AccessTokenResponseHttpMessageConverter())); restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler()); this.restOperations = restTemplate; } @Override - public OAuth2AccessTokenResponse getTokenResponse(OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) { + public OAuth2AccessTokenResponse getTokenResponse( + OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) { Assert.notNull(authorizationCodeGrantRequest, "authorizationCodeGrantRequest cannot be null"); RequestEntity request = this.requestEntityConverter.convert(authorizationCodeGrantRequest); @@ -73,9 +79,12 @@ public final class DefaultAuthorizationCodeTokenResponseClient implements OAuth2 ResponseEntity response; try { response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class); - } catch (RestClientException ex) { + } + catch (RestClientException ex) { OAuth2Error oauth2Error = new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE, - "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), null); + "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + + ex.getMessage(), + null); throw new OAuth2AuthorizationException(oauth2Error, ex); } @@ -87,38 +96,43 @@ public final class DefaultAuthorizationCodeTokenResponseClient implements OAuth2 // If AccessTokenResponse.scope is empty, then default to the scope // originally requested by the client in the Token Request tokenResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse) - .scopes(authorizationCodeGrantRequest.getClientRegistration().getScopes()) - .build(); + .scopes(authorizationCodeGrantRequest.getClientRegistration().getScopes()).build(); } return tokenResponse; } /** - * Sets the {@link Converter} used for converting the {@link OAuth2AuthorizationCodeGrantRequest} - * to a {@link RequestEntity} representation of the OAuth 2.0 Access Token Request. - * - * @param requestEntityConverter the {@link Converter} used for converting to a {@link RequestEntity} representation of the Access Token Request + * Sets the {@link Converter} used for converting the + * {@link OAuth2AuthorizationCodeGrantRequest} to a {@link RequestEntity} + * representation of the OAuth 2.0 Access Token Request. + * @param requestEntityConverter the {@link Converter} used for converting to a + * {@link RequestEntity} representation of the Access Token Request */ - public void setRequestEntityConverter(Converter> requestEntityConverter) { + public void setRequestEntityConverter( + Converter> requestEntityConverter) { Assert.notNull(requestEntityConverter, "requestEntityConverter cannot be null"); this.requestEntityConverter = requestEntityConverter; } /** - * Sets the {@link RestOperations} used when requesting the OAuth 2.0 Access Token Response. + * Sets the {@link RestOperations} used when requesting the OAuth 2.0 Access Token + * Response. * *

        - * NOTE: At a minimum, the supplied {@code restOperations} must be configured with the following: + * NOTE: At a minimum, the supplied {@code restOperations} must be configured + * with the following: *

          - *
        1. {@link HttpMessageConverter}'s - {@link FormHttpMessageConverter} and {@link OAuth2AccessTokenResponseHttpMessageConverter}
        2. - *
        3. {@link ResponseErrorHandler} - {@link OAuth2ErrorResponseErrorHandler}
        4. + *
        5. {@link HttpMessageConverter}'s - {@link FormHttpMessageConverter} and + * {@link OAuth2AccessTokenResponseHttpMessageConverter}
        6. + *
        7. {@link ResponseErrorHandler} - {@link OAuth2ErrorResponseErrorHandler}
        8. *
        - * - * @param restOperations the {@link RestOperations} used when requesting the Access Token Response + * @param restOperations the {@link RestOperations} used when requesting the Access + * Token Response */ public void setRestOperations(RestOperations restOperations) { Assert.notNull(restOperations, "restOperations cannot be null"); this.restOperations = restOperations; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClient.java index fdd5eb1e75..155d1f8d22 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClient.java @@ -36,36 +36,42 @@ import org.springframework.web.client.RestTemplate; import java.util.Arrays; /** - * The default implementation of an {@link OAuth2AccessTokenResponseClient} - * for the {@link AuthorizationGrantType#CLIENT_CREDENTIALS client_credentials} grant. - * This implementation uses a {@link RestOperations} when requesting - * an access token credential at the Authorization Server's Token Endpoint. + * The default implementation of an {@link OAuth2AccessTokenResponseClient} for the + * {@link AuthorizationGrantType#CLIENT_CREDENTIALS client_credentials} grant. This + * implementation uses a {@link RestOperations} when requesting an access token credential + * at the Authorization Server's Token Endpoint. * * @author Joe Grandja * @since 5.1 * @see OAuth2AccessTokenResponseClient * @see OAuth2ClientCredentialsGrantRequest * @see OAuth2AccessTokenResponse - * @see Section 4.4.2 Access Token Request (Client Credentials Grant) - * @see Section 4.4.3 Access Token Response (Client Credentials Grant) + * @see Section 4.4.2 Access Token Request + * (Client Credentials Grant) + * @see Section 4.4.3 Access Token Response + * (Client Credentials Grant) */ -public final class DefaultClientCredentialsTokenResponseClient implements OAuth2AccessTokenResponseClient { +public final class DefaultClientCredentialsTokenResponseClient + implements OAuth2AccessTokenResponseClient { + private static final String INVALID_TOKEN_RESPONSE_ERROR_CODE = "invalid_token_response"; - private Converter> requestEntityConverter = - new OAuth2ClientCredentialsGrantRequestEntityConverter(); + private Converter> requestEntityConverter = new OAuth2ClientCredentialsGrantRequestEntityConverter(); private RestOperations restOperations; public DefaultClientCredentialsTokenResponseClient() { - RestTemplate restTemplate = new RestTemplate(Arrays.asList( - new FormHttpMessageConverter(), new OAuth2AccessTokenResponseHttpMessageConverter())); + RestTemplate restTemplate = new RestTemplate( + Arrays.asList(new FormHttpMessageConverter(), new OAuth2AccessTokenResponseHttpMessageConverter())); restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler()); this.restOperations = restTemplate; } @Override - public OAuth2AccessTokenResponse getTokenResponse(OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest) { + public OAuth2AccessTokenResponse getTokenResponse( + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest) { Assert.notNull(clientCredentialsGrantRequest, "clientCredentialsGrantRequest cannot be null"); RequestEntity request = this.requestEntityConverter.convert(clientCredentialsGrantRequest); @@ -73,9 +79,12 @@ public final class DefaultClientCredentialsTokenResponseClient implements OAuth2 ResponseEntity response; try { response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class); - } catch (RestClientException ex) { + } + catch (RestClientException ex) { OAuth2Error oauth2Error = new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE, - "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), null); + "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + + ex.getMessage(), + null); throw new OAuth2AuthorizationException(oauth2Error, ex); } @@ -87,38 +96,43 @@ public final class DefaultClientCredentialsTokenResponseClient implements OAuth2 // If AccessTokenResponse.scope is empty, then default to the scope // originally requested by the client in the Token Request tokenResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse) - .scopes(clientCredentialsGrantRequest.getClientRegistration().getScopes()) - .build(); + .scopes(clientCredentialsGrantRequest.getClientRegistration().getScopes()).build(); } return tokenResponse; } /** - * Sets the {@link Converter} used for converting the {@link OAuth2ClientCredentialsGrantRequest} - * to a {@link RequestEntity} representation of the OAuth 2.0 Access Token Request. - * - * @param requestEntityConverter the {@link Converter} used for converting to a {@link RequestEntity} representation of the Access Token Request + * Sets the {@link Converter} used for converting the + * {@link OAuth2ClientCredentialsGrantRequest} to a {@link RequestEntity} + * representation of the OAuth 2.0 Access Token Request. + * @param requestEntityConverter the {@link Converter} used for converting to a + * {@link RequestEntity} representation of the Access Token Request */ - public void setRequestEntityConverter(Converter> requestEntityConverter) { + public void setRequestEntityConverter( + Converter> requestEntityConverter) { Assert.notNull(requestEntityConverter, "requestEntityConverter cannot be null"); this.requestEntityConverter = requestEntityConverter; } /** - * Sets the {@link RestOperations} used when requesting the OAuth 2.0 Access Token Response. + * Sets the {@link RestOperations} used when requesting the OAuth 2.0 Access Token + * Response. * *

        - * NOTE: At a minimum, the supplied {@code restOperations} must be configured with the following: + * NOTE: At a minimum, the supplied {@code restOperations} must be configured + * with the following: *

          - *
        1. {@link HttpMessageConverter}'s - {@link FormHttpMessageConverter} and {@link OAuth2AccessTokenResponseHttpMessageConverter}
        2. - *
        3. {@link ResponseErrorHandler} - {@link OAuth2ErrorResponseErrorHandler}
        4. + *
        5. {@link HttpMessageConverter}'s - {@link FormHttpMessageConverter} and + * {@link OAuth2AccessTokenResponseHttpMessageConverter}
        6. + *
        7. {@link ResponseErrorHandler} - {@link OAuth2ErrorResponseErrorHandler}
        8. *
        - * - * @param restOperations the {@link RestOperations} used when requesting the Access Token Response + * @param restOperations the {@link RestOperations} used when requesting the Access + * Token Response */ public void setRestOperations(RestOperations restOperations) { Assert.notNull(restOperations, "restOperations cannot be null"); this.restOperations = restOperations; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultPasswordTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultPasswordTokenResponseClient.java index e2f7180d2e..05e71120c4 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultPasswordTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultPasswordTokenResponseClient.java @@ -36,30 +36,35 @@ import org.springframework.web.client.RestTemplate; import java.util.Arrays; /** - * The default implementation of an {@link OAuth2AccessTokenResponseClient} - * for the {@link AuthorizationGrantType#PASSWORD password} grant. - * This implementation uses a {@link RestOperations} when requesting - * an access token credential at the Authorization Server's Token Endpoint. + * The default implementation of an {@link OAuth2AccessTokenResponseClient} for the + * {@link AuthorizationGrantType#PASSWORD password} grant. This implementation uses a + * {@link RestOperations} when requesting an access token credential at the Authorization + * Server's Token Endpoint. * * @author Joe Grandja * @since 5.2 * @see OAuth2AccessTokenResponseClient * @see OAuth2PasswordGrantRequest * @see OAuth2AccessTokenResponse - * @see Section 4.3.2 Access Token Request (Resource Owner Password Credentials Grant) - * @see Section 4.3.3 Access Token Response (Resource Owner Password Credentials Grant) + * @see Section 4.3.2 Access Token Request + * (Resource Owner Password Credentials Grant) + * @see Section 4.3.3 Access Token Response + * (Resource Owner Password Credentials Grant) */ -public final class DefaultPasswordTokenResponseClient implements OAuth2AccessTokenResponseClient { +public final class DefaultPasswordTokenResponseClient + implements OAuth2AccessTokenResponseClient { + private static final String INVALID_TOKEN_RESPONSE_ERROR_CODE = "invalid_token_response"; - private Converter> requestEntityConverter = - new OAuth2PasswordGrantRequestEntityConverter(); + private Converter> requestEntityConverter = new OAuth2PasswordGrantRequestEntityConverter(); private RestOperations restOperations; public DefaultPasswordTokenResponseClient() { - RestTemplate restTemplate = new RestTemplate(Arrays.asList( - new FormHttpMessageConverter(), new OAuth2AccessTokenResponseHttpMessageConverter())); + RestTemplate restTemplate = new RestTemplate( + Arrays.asList(new FormHttpMessageConverter(), new OAuth2AccessTokenResponseHttpMessageConverter())); restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler()); this.restOperations = restTemplate; } @@ -73,9 +78,12 @@ public final class DefaultPasswordTokenResponseClient implements OAuth2AccessTok ResponseEntity response; try { response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class); - } catch (RestClientException ex) { + } + catch (RestClientException ex) { OAuth2Error oauth2Error = new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE, - "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), null); + "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + + ex.getMessage(), + null); throw new OAuth2AuthorizationException(oauth2Error, ex); } @@ -87,38 +95,43 @@ public final class DefaultPasswordTokenResponseClient implements OAuth2AccessTok // If AccessTokenResponse.scope is empty, then default to the scope // originally requested by the client in the Token Request tokenResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse) - .scopes(passwordGrantRequest.getClientRegistration().getScopes()) - .build(); + .scopes(passwordGrantRequest.getClientRegistration().getScopes()).build(); } return tokenResponse; } /** - * Sets the {@link Converter} used for converting the {@link OAuth2PasswordGrantRequest} - * to a {@link RequestEntity} representation of the OAuth 2.0 Access Token Request. - * - * @param requestEntityConverter the {@link Converter} used for converting to a {@link RequestEntity} representation of the Access Token Request + * Sets the {@link Converter} used for converting the + * {@link OAuth2PasswordGrantRequest} to a {@link RequestEntity} representation of the + * OAuth 2.0 Access Token Request. + * @param requestEntityConverter the {@link Converter} used for converting to a + * {@link RequestEntity} representation of the Access Token Request */ - public void setRequestEntityConverter(Converter> requestEntityConverter) { + public void setRequestEntityConverter( + Converter> requestEntityConverter) { Assert.notNull(requestEntityConverter, "requestEntityConverter cannot be null"); this.requestEntityConverter = requestEntityConverter; } /** - * Sets the {@link RestOperations} used when requesting the OAuth 2.0 Access Token Response. + * Sets the {@link RestOperations} used when requesting the OAuth 2.0 Access Token + * Response. * *

        - * NOTE: At a minimum, the supplied {@code restOperations} must be configured with the following: + * NOTE: At a minimum, the supplied {@code restOperations} must be configured + * with the following: *

          - *
        1. {@link HttpMessageConverter}'s - {@link FormHttpMessageConverter} and {@link OAuth2AccessTokenResponseHttpMessageConverter}
        2. - *
        3. {@link ResponseErrorHandler} - {@link OAuth2ErrorResponseErrorHandler}
        4. + *
        5. {@link HttpMessageConverter}'s - {@link FormHttpMessageConverter} and + * {@link OAuth2AccessTokenResponseHttpMessageConverter}
        6. + *
        7. {@link ResponseErrorHandler} - {@link OAuth2ErrorResponseErrorHandler}
        8. *
        - * - * @param restOperations the {@link RestOperations} used when requesting the Access Token Response + * @param restOperations the {@link RestOperations} used when requesting the Access + * Token Response */ public void setRestOperations(RestOperations restOperations) { Assert.notNull(restOperations, "restOperations cannot be null"); this.restOperations = restOperations; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClient.java index 0efd37d8eb..4cd267db54 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClient.java @@ -36,29 +36,31 @@ import org.springframework.web.client.RestTemplate; import java.util.Arrays; /** - * The default implementation of an {@link OAuth2AccessTokenResponseClient} - * for the {@link AuthorizationGrantType#REFRESH_TOKEN refresh_token} grant. - * This implementation uses a {@link RestOperations} when requesting - * an access token credential at the Authorization Server's Token Endpoint. + * The default implementation of an {@link OAuth2AccessTokenResponseClient} for the + * {@link AuthorizationGrantType#REFRESH_TOKEN refresh_token} grant. This implementation + * uses a {@link RestOperations} when requesting an access token credential at the + * Authorization Server's Token Endpoint. * * @author Joe Grandja * @since 5.2 * @see OAuth2AccessTokenResponseClient * @see OAuth2RefreshTokenGrantRequest * @see OAuth2AccessTokenResponse - * @see Section 6 Refreshing an Access Token + * @see Section 6 + * Refreshing an Access Token */ -public final class DefaultRefreshTokenTokenResponseClient implements OAuth2AccessTokenResponseClient { +public final class DefaultRefreshTokenTokenResponseClient + implements OAuth2AccessTokenResponseClient { + private static final String INVALID_TOKEN_RESPONSE_ERROR_CODE = "invalid_token_response"; - private Converter> requestEntityConverter = - new OAuth2RefreshTokenGrantRequestEntityConverter(); + private Converter> requestEntityConverter = new OAuth2RefreshTokenGrantRequestEntityConverter(); private RestOperations restOperations; public DefaultRefreshTokenTokenResponseClient() { - RestTemplate restTemplate = new RestTemplate(Arrays.asList( - new FormHttpMessageConverter(), new OAuth2AccessTokenResponseHttpMessageConverter())); + RestTemplate restTemplate = new RestTemplate( + Arrays.asList(new FormHttpMessageConverter(), new OAuth2AccessTokenResponseHttpMessageConverter())); restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler()); this.restOperations = restTemplate; } @@ -72,17 +74,21 @@ public final class DefaultRefreshTokenTokenResponseClient implements OAuth2Acces ResponseEntity response; try { response = this.restOperations.exchange(request, OAuth2AccessTokenResponse.class); - } catch (RestClientException ex) { + } + catch (RestClientException ex) { OAuth2Error oauth2Error = new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE, - "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), null); + "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + + ex.getMessage(), + null); throw new OAuth2AuthorizationException(oauth2Error, ex); } OAuth2AccessTokenResponse tokenResponse = response.getBody(); - if (CollectionUtils.isEmpty(tokenResponse.getAccessToken().getScopes()) || - tokenResponse.getRefreshToken() == null) { - OAuth2AccessTokenResponse.Builder tokenResponseBuilder = OAuth2AccessTokenResponse.withResponse(tokenResponse); + if (CollectionUtils.isEmpty(tokenResponse.getAccessToken().getScopes()) + || tokenResponse.getRefreshToken() == null) { + OAuth2AccessTokenResponse.Builder tokenResponseBuilder = OAuth2AccessTokenResponse + .withResponse(tokenResponse); if (CollectionUtils.isEmpty(tokenResponse.getAccessToken().getScopes())) { // As per spec, in Section 5.1 Successful Access Token Response @@ -104,30 +110,36 @@ public final class DefaultRefreshTokenTokenResponseClient implements OAuth2Acces } /** - * Sets the {@link Converter} used for converting the {@link OAuth2RefreshTokenGrantRequest} - * to a {@link RequestEntity} representation of the OAuth 2.0 Access Token Request. - * - * @param requestEntityConverter the {@link Converter} used for converting to a {@link RequestEntity} representation of the Access Token Request + * Sets the {@link Converter} used for converting the + * {@link OAuth2RefreshTokenGrantRequest} to a {@link RequestEntity} representation of + * the OAuth 2.0 Access Token Request. + * @param requestEntityConverter the {@link Converter} used for converting to a + * {@link RequestEntity} representation of the Access Token Request */ - public void setRequestEntityConverter(Converter> requestEntityConverter) { + public void setRequestEntityConverter( + Converter> requestEntityConverter) { Assert.notNull(requestEntityConverter, "requestEntityConverter cannot be null"); this.requestEntityConverter = requestEntityConverter; } /** - * Sets the {@link RestOperations} used when requesting the OAuth 2.0 Access Token Response. + * Sets the {@link RestOperations} used when requesting the OAuth 2.0 Access Token + * Response. * *

        - * NOTE: At a minimum, the supplied {@code restOperations} must be configured with the following: + * NOTE: At a minimum, the supplied {@code restOperations} must be configured + * with the following: *

          - *
        1. {@link HttpMessageConverter}'s - {@link FormHttpMessageConverter} and {@link OAuth2AccessTokenResponseHttpMessageConverter}
        2. - *
        3. {@link ResponseErrorHandler} - {@link OAuth2ErrorResponseErrorHandler}
        4. + *
        5. {@link HttpMessageConverter}'s - {@link FormHttpMessageConverter} and + * {@link OAuth2AccessTokenResponseHttpMessageConverter}
        6. + *
        7. {@link ResponseErrorHandler} - {@link OAuth2ErrorResponseErrorHandler}
        8. *
        - * - * @param restOperations the {@link RestOperations} used when requesting the Access Token Response + * @param restOperations the {@link RestOperations} used when requesting the Access + * Token Response */ public void setRestOperations(RestOperations restOperations) { Assert.notNull(restOperations, "restOperations cannot be null"); this.restOperations = restOperations; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/NimbusAuthorizationCodeTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/NimbusAuthorizationCodeTokenResponseClient.java index cac276aa67..ea3e1ffbd8 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/NimbusAuthorizationCodeTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/NimbusAuthorizationCodeTokenResponseClient.java @@ -15,7 +15,6 @@ */ package org.springframework.security.oauth2.client.endpoint; - import com.nimbusds.oauth2.sdk.AccessTokenResponse; import com.nimbusds.oauth2.sdk.AuthorizationCode; import com.nimbusds.oauth2.sdk.AuthorizationCodeGrant; @@ -48,8 +47,8 @@ import java.util.Map; import java.util.Set; /** - * An implementation of an {@link OAuth2AccessTokenResponseClient} that "exchanges" - * an authorization code credential for an access token credential + * An implementation of an {@link OAuth2AccessTokenResponseClient} that + * "exchanges" an authorization code credential for an access token credential * at the Authorization Server's Token Endpoint. * *

        @@ -61,12 +60,20 @@ import java.util.Set; * @see OAuth2AccessTokenResponseClient * @see OAuth2AuthorizationCodeGrantRequest * @see OAuth2AccessTokenResponse - * @see Nimbus OAuth 2.0 SDK - * @see Section 4.1.3 Access Token Request (Authorization Code Grant) - * @see Section 4.1.4 Access Token Response (Authorization Code Grant) + * @see Nimbus OAuth 2.0 + * SDK + * @see Section 4.1.3 Access Token Request + * (Authorization Code Grant) + * @see Section 4.1.4 Access Token Response + * (Authorization Code Grant) */ @Deprecated -public class NimbusAuthorizationCodeTokenResponseClient implements OAuth2AccessTokenResponseClient { +public class NimbusAuthorizationCodeTokenResponseClient + implements OAuth2AccessTokenResponseClient { + private static final String INVALID_TOKEN_RESPONSE_ERROR_CODE = "invalid_token_response"; @Override @@ -75,8 +82,9 @@ public class NimbusAuthorizationCodeTokenResponseClient implements OAuth2AccessT // Build the authorization code grant request for the token endpoint AuthorizationCode authorizationCode = new AuthorizationCode( - authorizationGrantRequest.getAuthorizationExchange().getAuthorizationResponse().getCode()); - URI redirectUri = toURI(authorizationGrantRequest.getAuthorizationExchange().getAuthorizationRequest().getRedirectUri()); + authorizationGrantRequest.getAuthorizationExchange().getAuthorizationResponse().getCode()); + URI redirectUri = toURI( + authorizationGrantRequest.getAuthorizationExchange().getAuthorizationRequest().getRedirectUri()); AuthorizationGrant authorizationCodeGrant = new AuthorizationCodeGrant(authorizationCode, redirectUri); URI tokenUri = toURI(clientRegistration.getProviderDetails().getTokenUri()); @@ -86,7 +94,8 @@ public class NimbusAuthorizationCodeTokenResponseClient implements OAuth2AccessT ClientAuthentication clientAuthentication; if (ClientAuthenticationMethod.POST.equals(clientRegistration.getClientAuthenticationMethod())) { clientAuthentication = new ClientSecretPost(clientId, clientSecret); - } else { + } + else { clientAuthentication = new ClientSecretBasic(clientId, clientSecret); } @@ -99,9 +108,12 @@ public class NimbusAuthorizationCodeTokenResponseClient implements OAuth2AccessT httpRequest.setConnectTimeout(30000); httpRequest.setReadTimeout(30000); tokenResponse = com.nimbusds.oauth2.sdk.TokenResponse.parse(httpRequest.send()); - } catch (ParseException | IOException ex) { + } + catch (ParseException | IOException ex) { OAuth2Error oauth2Error = new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE, - "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + ex.getMessage(), null); + "An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: " + + ex.getMessage(), + null); throw new OAuth2AuthorizationException(oauth2Error, ex); } @@ -111,7 +123,8 @@ public class NimbusAuthorizationCodeTokenResponseClient implements OAuth2AccessT OAuth2Error oauth2Error; if (errorObject == null) { oauth2Error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR); - } else { + } + else { oauth2Error = new OAuth2Error( errorObject.getCode() != null ? errorObject.getCode() : OAuth2ErrorCodes.SERVER_ERROR, errorObject.getDescription(), @@ -124,7 +137,8 @@ public class NimbusAuthorizationCodeTokenResponseClient implements OAuth2AccessT String accessToken = accessTokenResponse.getTokens().getAccessToken().getValue(); OAuth2AccessToken.TokenType accessTokenType = null; - if (OAuth2AccessToken.TokenType.BEARER.getValue().equalsIgnoreCase(accessTokenResponse.getTokens().getAccessToken().getType().getValue())) { + if (OAuth2AccessToken.TokenType.BEARER.getValue() + .equalsIgnoreCase(accessTokenResponse.getTokens().getAccessToken().getType().getValue())) { accessTokenType = OAuth2AccessToken.TokenType.BEARER; } long expiresIn = accessTokenResponse.getTokens().getAccessToken().getLifetime(); @@ -136,10 +150,10 @@ public class NimbusAuthorizationCodeTokenResponseClient implements OAuth2AccessT Set scopes; if (CollectionUtils.isEmpty(accessTokenResponse.getTokens().getAccessToken().getScope())) { scopes = new LinkedHashSet<>( - authorizationGrantRequest.getAuthorizationExchange().getAuthorizationRequest().getScopes()); - } else { - scopes = new LinkedHashSet<>( - accessTokenResponse.getTokens().getAccessToken().getScope().toStringList()); + authorizationGrantRequest.getAuthorizationExchange().getAuthorizationRequest().getScopes()); + } + else { + scopes = new LinkedHashSet<>(accessTokenResponse.getTokens().getAccessToken().getScope().toStringList()); } String refreshToken = null; @@ -149,20 +163,17 @@ public class NimbusAuthorizationCodeTokenResponseClient implements OAuth2AccessT Map additionalParameters = new LinkedHashMap<>(accessTokenResponse.getCustomParameters()); - return OAuth2AccessTokenResponse.withToken(accessToken) - .tokenType(accessTokenType) - .expiresIn(expiresIn) - .scopes(scopes) - .refreshToken(refreshToken) - .additionalParameters(additionalParameters) - .build(); + return OAuth2AccessTokenResponse.withToken(accessToken).tokenType(accessTokenType).expiresIn(expiresIn) + .scopes(scopes).refreshToken(refreshToken).additionalParameters(additionalParameters).build(); } private static URI toURI(String uriStr) { try { return new URI(uriStr); - } catch (Exception ex) { + } + catch (Exception ex) { throw new IllegalArgumentException("An error occurred parsing URI: " + uriStr, ex); } } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AccessTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AccessTokenResponseClient.java index cf86174324..7afbde5e98 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AccessTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AccessTokenResponseClient.java @@ -15,35 +15,42 @@ */ package org.springframework.security.oauth2.client.endpoint; - import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.security.oauth2.core.OAuth2AuthorizationException; import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; /** - * A strategy for "exchanging" an authorization grant credential - * (e.g. an Authorization Code) for an access token credential - * at the Authorization Server's Token Endpoint. + * A strategy for "exchanging" an authorization grant credential (e.g. an + * Authorization Code) for an access token credential at the Authorization Server's Token + * Endpoint. * * @author Joe Grandja * @since 5.0 * @see AbstractOAuth2AuthorizationGrantRequest * @see OAuth2AccessTokenResponse * @see AuthorizationGrantType - * @see Section 1.3 Authorization Grant - * @see Section 4.1.3 Access Token Request (Authorization Code Grant) - * @see Section 4.1.4 Access Token Response (Authorization Code Grant) + * @see Section + * 1.3 Authorization Grant + * @see Section 4.1.3 Access Token Request + * (Authorization Code Grant) + * @see Section 4.1.4 Access Token Response + * (Authorization Code Grant) */ @FunctionalInterface -public interface OAuth2AccessTokenResponseClient { +public interface OAuth2AccessTokenResponseClient { /** - * Exchanges the authorization grant credential, provided in the authorization grant request, - * for an access token credential at the Authorization Server's Token Endpoint. - * - * @param authorizationGrantRequest the authorization grant request that contains the authorization grant credential - * @return an {@link OAuth2AccessTokenResponse} that contains the {@link OAuth2AccessTokenResponse#getAccessToken() access token} credential - * @throws OAuth2AuthorizationException if an error occurs while attempting to exchange for the access token credential + * Exchanges the authorization grant credential, provided in the authorization grant + * request, for an access token credential at the Authorization Server's Token + * Endpoint. + * @param authorizationGrantRequest the authorization grant request that contains the + * authorization grant credential + * @return an {@link OAuth2AccessTokenResponse} that contains the + * {@link OAuth2AccessTokenResponse#getAccessToken() access token} credential + * @throws OAuth2AuthorizationException if an error occurs while attempting to + * exchange for the access token credential */ OAuth2AccessTokenResponse getTokenResponse(T authorizationGrantRequest); diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequest.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequest.java index 3b4c36c670..7fff7206d1 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequest.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequest.java @@ -21,28 +21,33 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExch import org.springframework.util.Assert; /** - * An OAuth 2.0 Authorization Code Grant request that holds an Authorization Code credential, - * which was granted by the Resource Owner to the {@link #getClientRegistration() Client}. + * An OAuth 2.0 Authorization Code Grant request that holds an Authorization Code + * credential, which was granted by the Resource Owner to the + * {@link #getClientRegistration() Client}. * * @author Joe Grandja * @since 5.0 * @see AbstractOAuth2AuthorizationGrantRequest * @see ClientRegistration * @see OAuth2AuthorizationExchange - * @see Section 1.3.1 Authorization Code Grant + * @see Section 1.3.1 Authorization Code + * Grant */ public class OAuth2AuthorizationCodeGrantRequest extends AbstractOAuth2AuthorizationGrantRequest { + private final ClientRegistration clientRegistration; + private final OAuth2AuthorizationExchange authorizationExchange; /** - * Constructs an {@code OAuth2AuthorizationCodeGrantRequest} using the provided parameters. - * + * Constructs an {@code OAuth2AuthorizationCodeGrantRequest} using the provided + * parameters. * @param clientRegistration the client registration * @param authorizationExchange the authorization exchange */ public OAuth2AuthorizationCodeGrantRequest(ClientRegistration clientRegistration, - OAuth2AuthorizationExchange authorizationExchange) { + OAuth2AuthorizationExchange authorizationExchange) { super(AuthorizationGrantType.AUTHORIZATION_CODE); Assert.notNull(clientRegistration, "clientRegistration cannot be null"); Assert.notNull(authorizationExchange, "authorizationExchange cannot be null"); @@ -52,7 +57,6 @@ public class OAuth2AuthorizationCodeGrantRequest extends AbstractOAuth2Authoriza /** * Returns the {@link ClientRegistration client registration}. - * * @return the {@link ClientRegistration} */ public ClientRegistration getClientRegistration() { @@ -61,10 +65,10 @@ public class OAuth2AuthorizationCodeGrantRequest extends AbstractOAuth2Authoriza /** * Returns the {@link OAuth2AuthorizationExchange authorization exchange}. - * * @return the {@link OAuth2AuthorizationExchange} */ public OAuth2AuthorizationExchange getAuthorizationExchange() { return this.authorizationExchange; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequestEntityConverter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequestEntityConverter.java index a8a088a77a..146e3f4ab8 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequestEntityConverter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequestEntityConverter.java @@ -31,9 +31,9 @@ import org.springframework.web.util.UriComponentsBuilder; import java.net.URI; /** - * A {@link Converter} that converts the provided {@link OAuth2AuthorizationCodeGrantRequest} - * to a {@link RequestEntity} representation of an OAuth 2.0 Access Token Request - * for the Authorization Code Grant. + * A {@link Converter} that converts the provided + * {@link OAuth2AuthorizationCodeGrantRequest} to a {@link RequestEntity} representation + * of an OAuth 2.0 Access Token Request for the Authorization Code Grant. * * @author Joe Grandja * @since 5.1 @@ -41,11 +41,11 @@ import java.net.URI; * @see OAuth2AuthorizationCodeGrantRequest * @see RequestEntity */ -public class OAuth2AuthorizationCodeGrantRequestEntityConverter implements Converter> { +public class OAuth2AuthorizationCodeGrantRequestEntityConverter + implements Converter> { /** * Returns the {@link RequestEntity} used for the Access Token Request. - * * @param authorizationCodeGrantRequest the authorization code grant request * @return the {@link RequestEntity} used for the Access Token Request */ @@ -55,20 +55,21 @@ public class OAuth2AuthorizationCodeGrantRequestEntityConverter implements Conve HttpHeaders headers = OAuth2AuthorizationGrantRequestEntityUtils.getTokenRequestHeaders(clientRegistration); MultiValueMap formParameters = this.buildFormParameters(authorizationCodeGrantRequest); - URI uri = UriComponentsBuilder.fromUriString(clientRegistration.getProviderDetails().getTokenUri()) - .build() + URI uri = UriComponentsBuilder.fromUriString(clientRegistration.getProviderDetails().getTokenUri()).build() .toUri(); return new RequestEntity<>(formParameters, headers, HttpMethod.POST, uri); } /** - * Returns a {@link MultiValueMap} of the form parameters used for the Access Token Request body. - * + * Returns a {@link MultiValueMap} of the form parameters used for the Access Token + * Request body. * @param authorizationCodeGrantRequest the authorization code grant request - * @return a {@link MultiValueMap} of the form parameters used for the Access Token Request body + * @return a {@link MultiValueMap} of the form parameters used for the Access Token + * Request body */ - private MultiValueMap buildFormParameters(OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) { + private MultiValueMap buildFormParameters( + OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) { ClientRegistration clientRegistration = authorizationCodeGrantRequest.getClientRegistration(); OAuth2AuthorizationExchange authorizationExchange = authorizationCodeGrantRequest.getAuthorizationExchange(); @@ -76,7 +77,8 @@ public class OAuth2AuthorizationCodeGrantRequestEntityConverter implements Conve formParameters.add(OAuth2ParameterNames.GRANT_TYPE, authorizationCodeGrantRequest.getGrantType().getValue()); formParameters.add(OAuth2ParameterNames.CODE, authorizationExchange.getAuthorizationResponse().getCode()); String redirectUri = authorizationExchange.getAuthorizationRequest().getRedirectUri(); - String codeVerifier = authorizationExchange.getAuthorizationRequest().getAttribute(PkceParameterNames.CODE_VERIFIER); + String codeVerifier = authorizationExchange.getAuthorizationRequest() + .getAttribute(PkceParameterNames.CODE_VERIFIER); if (redirectUri != null) { formParameters.add(OAuth2ParameterNames.REDIRECT_URI, redirectUri); } @@ -92,4 +94,5 @@ public class OAuth2AuthorizationCodeGrantRequestEntityConverter implements Conve return formParameters; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationGrantRequestEntityUtils.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationGrantRequestEntityUtils.java index a1ed924307..2fe790d956 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationGrantRequestEntityUtils.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationGrantRequestEntityUtils.java @@ -27,10 +27,10 @@ import java.util.Collections; import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE; /** - * Utility methods used by the {@link Converter}'s that convert - * from an implementation of an {@link AbstractOAuth2AuthorizationGrantRequest} - * to a {@link RequestEntity} representation of an OAuth 2.0 Access Token Request - * for the specific Authorization Grant. + * Utility methods used by the {@link Converter}'s that convert from an implementation of + * an {@link AbstractOAuth2AuthorizationGrantRequest} to a {@link RequestEntity} + * representation of an OAuth 2.0 Access Token Request for the specific Authorization + * Grant. * * @author Joe Grandja * @since 5.1 @@ -38,6 +38,7 @@ import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VAL * @see OAuth2ClientCredentialsGrantRequestEntityConverter */ final class OAuth2AuthorizationGrantRequestEntityUtils { + private static HttpHeaders DEFAULT_TOKEN_REQUEST_HEADERS = getDefaultTokenRequestHeaders(); static HttpHeaders getTokenRequestHeaders(ClientRegistration clientRegistration) { @@ -56,4 +57,5 @@ final class OAuth2AuthorizationGrantRequestEntityUtils { headers.setContentType(contentType); return headers; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequest.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequest.java index 8764d2068b..4b4c6574fc 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequest.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequest.java @@ -20,21 +20,24 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.util.Assert; /** - * An OAuth 2.0 Client Credentials Grant request that holds - * the client's credentials in {@link #getClientRegistration()}. + * An OAuth 2.0 Client Credentials Grant request that holds the client's credentials in + * {@link #getClientRegistration()}. * * @author Joe Grandja * @since 5.1 * @see AbstractOAuth2AuthorizationGrantRequest * @see ClientRegistration - * @see Section 1.3.4 Client Credentials Grant + * @see Section 1.3.4 Client Credentials + * Grant */ public class OAuth2ClientCredentialsGrantRequest extends AbstractOAuth2AuthorizationGrantRequest { + private final ClientRegistration clientRegistration; /** - * Constructs an {@code OAuth2ClientCredentialsGrantRequest} using the provided parameters. - * + * Constructs an {@code OAuth2ClientCredentialsGrantRequest} using the provided + * parameters. * @param clientRegistration the client registration */ public OAuth2ClientCredentialsGrantRequest(ClientRegistration clientRegistration) { @@ -47,10 +50,10 @@ public class OAuth2ClientCredentialsGrantRequest extends AbstractOAuth2Authoriza /** * Returns the {@link ClientRegistration client registration}. - * * @return the {@link ClientRegistration} */ public ClientRegistration getClientRegistration() { return this.clientRegistration; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequestEntityConverter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequestEntityConverter.java index 75c0398cc7..bfbd63f12b 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequestEntityConverter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequestEntityConverter.java @@ -31,9 +31,9 @@ import org.springframework.web.util.UriComponentsBuilder; import java.net.URI; /** - * A {@link Converter} that converts the provided {@link OAuth2ClientCredentialsGrantRequest} - * to a {@link RequestEntity} representation of an OAuth 2.0 Access Token Request - * for the Client Credentials Grant. + * A {@link Converter} that converts the provided + * {@link OAuth2ClientCredentialsGrantRequest} to a {@link RequestEntity} representation + * of an OAuth 2.0 Access Token Request for the Client Credentials Grant. * * @author Joe Grandja * @since 5.1 @@ -41,11 +41,11 @@ import java.net.URI; * @see OAuth2ClientCredentialsGrantRequest * @see RequestEntity */ -public class OAuth2ClientCredentialsGrantRequestEntityConverter implements Converter> { +public class OAuth2ClientCredentialsGrantRequestEntityConverter + implements Converter> { /** * Returns the {@link RequestEntity} used for the Access Token Request. - * * @param clientCredentialsGrantRequest the client credentials grant request * @return the {@link RequestEntity} used for the Access Token Request */ @@ -55,20 +55,21 @@ public class OAuth2ClientCredentialsGrantRequestEntityConverter implements Conve HttpHeaders headers = OAuth2AuthorizationGrantRequestEntityUtils.getTokenRequestHeaders(clientRegistration); MultiValueMap formParameters = this.buildFormParameters(clientCredentialsGrantRequest); - URI uri = UriComponentsBuilder.fromUriString(clientRegistration.getProviderDetails().getTokenUri()) - .build() + URI uri = UriComponentsBuilder.fromUriString(clientRegistration.getProviderDetails().getTokenUri()).build() .toUri(); return new RequestEntity<>(formParameters, headers, HttpMethod.POST, uri); } /** - * Returns a {@link MultiValueMap} of the form parameters used for the Access Token Request body. - * + * Returns a {@link MultiValueMap} of the form parameters used for the Access Token + * Request body. * @param clientCredentialsGrantRequest the client credentials grant request - * @return a {@link MultiValueMap} of the form parameters used for the Access Token Request body + * @return a {@link MultiValueMap} of the form parameters used for the Access Token + * Request body */ - private MultiValueMap buildFormParameters(OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest) { + private MultiValueMap buildFormParameters( + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest) { ClientRegistration clientRegistration = clientCredentialsGrantRequest.getClientRegistration(); MultiValueMap formParameters = new LinkedMultiValueMap<>(); @@ -84,4 +85,5 @@ public class OAuth2ClientCredentialsGrantRequestEntityConverter implements Conve return formParameters; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequest.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequest.java index 0898fc32a0..69901df2e7 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequest.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequest.java @@ -20,22 +20,26 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.util.Assert; /** - * An OAuth 2.0 Resource Owner Password Credentials Grant request - * that holds the resource owner's credentials. + * An OAuth 2.0 Resource Owner Password Credentials Grant request that holds the resource + * owner's credentials. * * @author Joe Grandja * @since 5.2 * @see AbstractOAuth2AuthorizationGrantRequest - * @see Section 1.3.3 Resource Owner Password Credentials + * @see Section 1.3.3 Resource Owner + * Password Credentials */ public class OAuth2PasswordGrantRequest extends AbstractOAuth2AuthorizationGrantRequest { + private final ClientRegistration clientRegistration; + private final String username; + private final String password; /** * Constructs an {@code OAuth2PasswordGrantRequest} using the provided parameters. - * * @param clientRegistration the client registration * @param username the resource owner's username * @param password the resource owner's password @@ -54,7 +58,6 @@ public class OAuth2PasswordGrantRequest extends AbstractOAuth2AuthorizationGrant /** * Returns the {@link ClientRegistration client registration}. - * * @return the {@link ClientRegistration} */ public ClientRegistration getClientRegistration() { @@ -63,7 +66,6 @@ public class OAuth2PasswordGrantRequest extends AbstractOAuth2AuthorizationGrant /** * Returns the resource owner's username. - * * @return the resource owner's username */ public String getUsername() { @@ -72,10 +74,10 @@ public class OAuth2PasswordGrantRequest extends AbstractOAuth2AuthorizationGrant /** * Returns the resource owner's password. - * * @return the resource owner's password */ public String getPassword() { return this.password; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequestEntityConverter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequestEntityConverter.java index f2ba2b40a0..465b27071c 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequestEntityConverter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequestEntityConverter.java @@ -31,9 +31,9 @@ import org.springframework.web.util.UriComponentsBuilder; import java.net.URI; /** - * A {@link Converter} that converts the provided {@link OAuth2PasswordGrantRequest} - * to a {@link RequestEntity} representation of an OAuth 2.0 Access Token Request - * for the Resource Owner Password Credentials Grant. + * A {@link Converter} that converts the provided {@link OAuth2PasswordGrantRequest} to a + * {@link RequestEntity} representation of an OAuth 2.0 Access Token Request for the + * Resource Owner Password Credentials Grant. * * @author Joe Grandja * @since 5.2 @@ -41,11 +41,11 @@ import java.net.URI; * @see OAuth2PasswordGrantRequest * @see RequestEntity */ -public class OAuth2PasswordGrantRequestEntityConverter implements Converter> { +public class OAuth2PasswordGrantRequestEntityConverter + implements Converter> { /** * Returns the {@link RequestEntity} used for the Access Token Request. - * * @param passwordGrantRequest the password grant request * @return the {@link RequestEntity} used for the Access Token Request */ @@ -55,18 +55,18 @@ public class OAuth2PasswordGrantRequestEntityConverter implements Converter formParameters = buildFormParameters(passwordGrantRequest); - URI uri = UriComponentsBuilder.fromUriString(clientRegistration.getProviderDetails().getTokenUri()) - .build() + URI uri = UriComponentsBuilder.fromUriString(clientRegistration.getProviderDetails().getTokenUri()).build() .toUri(); return new RequestEntity<>(formParameters, headers, HttpMethod.POST, uri); } /** - * Returns a {@link MultiValueMap} of the form parameters used for the Access Token Request body. - * + * Returns a {@link MultiValueMap} of the form parameters used for the Access Token + * Request body. * @param passwordGrantRequest the password grant request - * @return a {@link MultiValueMap} of the form parameters used for the Access Token Request body + * @return a {@link MultiValueMap} of the form parameters used for the Access Token + * Request body */ private MultiValueMap buildFormParameters(OAuth2PasswordGrantRequest passwordGrantRequest) { ClientRegistration clientRegistration = passwordGrantRequest.getClientRegistration(); @@ -86,4 +86,5 @@ public class OAuth2PasswordGrantRequestEntityConverter implements ConverterSection 6 Refreshing an Access Token + * @see Section 6 + * Refreshing an Access Token */ public class OAuth2RefreshTokenGrantRequest extends AbstractOAuth2AuthorizationGrantRequest { + private final ClientRegistration clientRegistration; + private final OAuth2AccessToken accessToken; + private final OAuth2RefreshToken refreshToken; + private final Set scopes; /** * Constructs an {@code OAuth2RefreshTokenGrantRequest} using the provided parameters. - * * @param clientRegistration the authorized client's registration * @param accessToken the access token credential granted * @param refreshToken the refresh token credential granted */ public OAuth2RefreshTokenGrantRequest(ClientRegistration clientRegistration, OAuth2AccessToken accessToken, - OAuth2RefreshToken refreshToken) { + OAuth2RefreshToken refreshToken) { this(clientRegistration, accessToken, refreshToken, Collections.emptySet()); } /** * Constructs an {@code OAuth2RefreshTokenGrantRequest} using the provided parameters. - * * @param clientRegistration the authorized client's registration * @param accessToken the access token credential granted * @param refreshToken the refresh token credential granted * @param scopes the scopes to request */ public OAuth2RefreshTokenGrantRequest(ClientRegistration clientRegistration, OAuth2AccessToken accessToken, - OAuth2RefreshToken refreshToken, Set scopes) { + OAuth2RefreshToken refreshToken, Set scopes) { super(AuthorizationGrantType.REFRESH_TOKEN); Assert.notNull(clientRegistration, "clientRegistration cannot be null"); Assert.notNull(accessToken, "accessToken cannot be null"); @@ -70,13 +73,12 @@ public class OAuth2RefreshTokenGrantRequest extends AbstractOAuth2AuthorizationG this.clientRegistration = clientRegistration; this.accessToken = accessToken; this.refreshToken = refreshToken; - this.scopes = Collections.unmodifiableSet(scopes != null ? - new LinkedHashSet<>(scopes) : Collections.emptySet()); + this.scopes = Collections + .unmodifiableSet(scopes != null ? new LinkedHashSet<>(scopes) : Collections.emptySet()); } /** * Returns the authorized client's {@link ClientRegistration registration}. - * * @return the {@link ClientRegistration} */ public ClientRegistration getClientRegistration() { @@ -85,7 +87,6 @@ public class OAuth2RefreshTokenGrantRequest extends AbstractOAuth2AuthorizationG /** * Returns the {@link OAuth2AccessToken access token} credential granted. - * * @return the {@link OAuth2AccessToken} */ public OAuth2AccessToken getAccessToken() { @@ -94,7 +95,6 @@ public class OAuth2RefreshTokenGrantRequest extends AbstractOAuth2AuthorizationG /** * Returns the {@link OAuth2RefreshToken refresh token} credential granted. - * * @return the {@link OAuth2RefreshToken} */ public OAuth2RefreshToken getRefreshToken() { @@ -103,10 +103,10 @@ public class OAuth2RefreshTokenGrantRequest extends AbstractOAuth2AuthorizationG /** * Returns the scope(s) to request. - * * @return the scope(s) to request */ public Set getScopes() { return this.scopes; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2RefreshTokenGrantRequestEntityConverter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2RefreshTokenGrantRequestEntityConverter.java index 00cac8beed..8bf4cfd3b3 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2RefreshTokenGrantRequestEntityConverter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/OAuth2RefreshTokenGrantRequestEntityConverter.java @@ -32,8 +32,8 @@ import java.net.URI; /** * A {@link Converter} that converts the provided {@link OAuth2RefreshTokenGrantRequest} - * to a {@link RequestEntity} representation of an OAuth 2.0 Access Token Request - * for the Refresh Token Grant. + * to a {@link RequestEntity} representation of an OAuth 2.0 Access Token Request for the + * Refresh Token Grant. * * @author Joe Grandja * @since 5.2 @@ -41,11 +41,11 @@ import java.net.URI; * @see OAuth2RefreshTokenGrantRequest * @see RequestEntity */ -public class OAuth2RefreshTokenGrantRequestEntityConverter implements Converter> { +public class OAuth2RefreshTokenGrantRequestEntityConverter + implements Converter> { /** * Returns the {@link RequestEntity} used for the Access Token Request. - * * @param refreshTokenGrantRequest the refresh token grant request * @return the {@link RequestEntity} used for the Access Token Request */ @@ -55,18 +55,18 @@ public class OAuth2RefreshTokenGrantRequestEntityConverter implements Converter< HttpHeaders headers = OAuth2AuthorizationGrantRequestEntityUtils.getTokenRequestHeaders(clientRegistration); MultiValueMap formParameters = buildFormParameters(refreshTokenGrantRequest); - URI uri = UriComponentsBuilder.fromUriString(clientRegistration.getProviderDetails().getTokenUri()) - .build() + URI uri = UriComponentsBuilder.fromUriString(clientRegistration.getProviderDetails().getTokenUri()).build() .toUri(); return new RequestEntity<>(formParameters, headers, HttpMethod.POST, uri); } /** - * Returns a {@link MultiValueMap} of the form parameters used for the Access Token Request body. - * + * Returns a {@link MultiValueMap} of the form parameters used for the Access Token + * Request body. * @param refreshTokenGrantRequest the refresh token grant request - * @return a {@link MultiValueMap} of the form parameters used for the Access Token Request body + * @return a {@link MultiValueMap} of the form parameters used for the Access Token + * Request body */ private MultiValueMap buildFormParameters(OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest) { ClientRegistration clientRegistration = refreshTokenGrantRequest.getClientRegistration(); @@ -86,4 +86,5 @@ public class OAuth2RefreshTokenGrantRequestEntityConverter implements Converter< return formParameters; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/ReactiveOAuth2AccessTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/ReactiveOAuth2AccessTokenResponseClient.java index f0196bdcc3..fa09352341 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/ReactiveOAuth2AccessTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/ReactiveOAuth2AccessTokenResponseClient.java @@ -21,29 +21,37 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenRespon import reactor.core.publisher.Mono; /** - * A reactive strategy for "exchanging" an authorization grant credential - * (e.g. an Authorization Code) for an access token credential - * at the Authorization Server's Token Endpoint. + * A reactive strategy for "exchanging" an authorization grant credential (e.g. + * an Authorization Code) for an access token credential at the Authorization Server's + * Token Endpoint. * * @author Rob Winch * @since 5.1 * @see AbstractOAuth2AuthorizationGrantRequest * @see OAuth2AccessTokenResponse * @see AuthorizationGrantType - * @see Section 1.3 Authorization Grant - * @see Section 4.1.3 Access Token Request (Authorization Code Grant) - * @see Section 4.1.4 Access Token Response (Authorization Code Grant) + * @see Section + * 1.3 Authorization Grant + * @see Section 4.1.3 Access Token Request + * (Authorization Code Grant) + * @see Section 4.1.4 Access Token Response + * (Authorization Code Grant) */ @FunctionalInterface -public interface ReactiveOAuth2AccessTokenResponseClient { +public interface ReactiveOAuth2AccessTokenResponseClient { /** - * Exchanges the authorization grant credential, provided in the authorization grant request, - * for an access token credential at the Authorization Server's Token Endpoint. - * - * @param authorizationGrantRequest the authorization grant request that contains the authorization grant credential - * @return an {@link OAuth2AccessTokenResponse} that contains the {@link OAuth2AccessTokenResponse#getAccessToken() access token} credential - * @throws OAuth2AuthorizationException if an error occurs while attempting to exchange for the access token credential + * Exchanges the authorization grant credential, provided in the authorization grant + * request, for an access token credential at the Authorization Server's Token + * Endpoint. + * @param authorizationGrantRequest the authorization grant request that contains the + * authorization grant credential + * @return an {@link OAuth2AccessTokenResponse} that contains the + * {@link OAuth2AccessTokenResponse#getAccessToken() access token} credential + * @throws OAuth2AuthorizationException if an error occurs while attempting to + * exchange for the access token credential */ Mono getTokenResponse(T authorizationGrantRequest); diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClient.java index 80cbe4cafd..8ada808580 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClient.java @@ -27,8 +27,8 @@ import java.util.Collections; import java.util.Set; /** - * An implementation of a {@link ReactiveOAuth2AccessTokenResponseClient} that "exchanges" - * an authorization code credential for an access token credential + * An implementation of a {@link ReactiveOAuth2AccessTokenResponseClient} that + * "exchanges" an authorization code credential for an access token credential * at the Authorization Server's Token Endpoint. * *

        @@ -39,13 +39,20 @@ import java.util.Set; * @see ReactiveOAuth2AccessTokenResponseClient * @see OAuth2AuthorizationCodeGrantRequest * @see OAuth2AccessTokenResponse - * @see Nimbus OAuth 2.0 SDK - * @see Section 4.1.3 Access Token Request (Authorization Code Grant) - * @see Section 4.1.4 Access Token Response (Authorization Code Grant) - * @see Section 4.2 Client Creates the Code Challenge + * @see Nimbus OAuth 2.0 + * SDK + * @see Section 4.1.3 Access Token Request + * (Authorization Code Grant) + * @see Section 4.1.4 Access Token Response + * (Authorization Code Grant) + * @see Section + * 4.2 Client Creates the Code Challenge */ -public class WebClientReactiveAuthorizationCodeTokenResponseClient extends - AbstractWebClientReactiveOAuth2AccessTokenResponseClient { +public class WebClientReactiveAuthorizationCodeTokenResponseClient + extends AbstractWebClientReactiveOAuth2AccessTokenResponseClient { @Override ClientRegistration clientRegistration(OAuth2AuthorizationCodeGrantRequest grantRequest) { @@ -63,8 +70,7 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClient extends } @Override - BodyInserters.FormInserter populateTokenRequestBody( - OAuth2AuthorizationCodeGrantRequest grantRequest, + BodyInserters.FormInserter populateTokenRequestBody(OAuth2AuthorizationCodeGrantRequest grantRequest, BodyInserters.FormInserter body) { super.populateTokenRequestBody(grantRequest, body); OAuth2AuthorizationExchange authorizationExchange = grantRequest.getAuthorizationExchange(); @@ -74,10 +80,12 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClient extends if (redirectUri != null) { body.with(OAuth2ParameterNames.REDIRECT_URI, redirectUri); } - String codeVerifier = authorizationExchange.getAuthorizationRequest().getAttribute(PkceParameterNames.CODE_VERIFIER); + String codeVerifier = authorizationExchange.getAuthorizationRequest() + .getAttribute(PkceParameterNames.CODE_VERIFIER); if (codeVerifier != null) { body.with(PkceParameterNames.CODE_VERIFIER, codeVerifier); } return body; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClient.java index b5f4142ef6..95c01b2672 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClient.java @@ -21,21 +21,27 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenRespon import java.util.Set; /** - * An implementation of a {@link ReactiveOAuth2AccessTokenResponseClient} that "exchanges" - * a client credential for an access token credential - * at the Authorization Server's Token Endpoint. + * An implementation of a {@link ReactiveOAuth2AccessTokenResponseClient} that + * "exchanges" a client credential for an access token credential at the + * Authorization Server's Token Endpoint. * * @author Rob Winch * @since 5.1 * @see ReactiveOAuth2AccessTokenResponseClient * @see OAuth2AuthorizationCodeGrantRequest * @see OAuth2AccessTokenResponse - * @see Nimbus OAuth 2.0 SDK - * @see Section 4.1.3 Access Token Request (Authorization Code Grant) - * @see Section 4.1.4 Access Token Response (Authorization Code Grant) + * @see Nimbus OAuth 2.0 + * SDK + * @see Section 4.1.3 Access Token Request + * (Authorization Code Grant) + * @see Section 4.1.4 Access Token Response + * (Authorization Code Grant) */ -public class WebClientReactiveClientCredentialsTokenResponseClient extends - AbstractWebClientReactiveOAuth2AccessTokenResponseClient { +public class WebClientReactiveClientCredentialsTokenResponseClient + extends AbstractWebClientReactiveOAuth2AccessTokenResponseClient { @Override ClientRegistration clientRegistration(OAuth2ClientCredentialsGrantRequest grantRequest) { diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactivePasswordTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactivePasswordTokenResponseClient.java index 442e2543fc..354b2b3368 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactivePasswordTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactivePasswordTokenResponseClient.java @@ -25,21 +25,25 @@ import org.springframework.web.reactive.function.client.WebClient; import java.util.Set; /** - * An implementation of a {@link ReactiveOAuth2AccessTokenResponseClient} - * for the {@link AuthorizationGrantType#PASSWORD password} grant. - * This implementation uses {@link WebClient} when requesting - * an access token credential at the Authorization Server's Token Endpoint. + * An implementation of a {@link ReactiveOAuth2AccessTokenResponseClient} for the + * {@link AuthorizationGrantType#PASSWORD password} grant. This implementation uses + * {@link WebClient} when requesting an access token credential at the Authorization + * Server's Token Endpoint. * * @author Joe Grandja * @since 5.2 * @see ReactiveOAuth2AccessTokenResponseClient * @see OAuth2PasswordGrantRequest * @see OAuth2AccessTokenResponse - * @see Section 4.3.2 Access Token Request (Resource Owner Password Credentials Grant) - * @see Section 4.3.3 Access Token Response (Resource Owner Password Credentials Grant) + * @see Section 4.3.2 Access Token Request + * (Resource Owner Password Credentials Grant) + * @see Section 4.3.3 Access Token Response + * (Resource Owner Password Credentials Grant) */ -public final class WebClientReactivePasswordTokenResponseClient extends - AbstractWebClientReactiveOAuth2AccessTokenResponseClient { +public final class WebClientReactivePasswordTokenResponseClient + extends AbstractWebClientReactiveOAuth2AccessTokenResponseClient { @Override ClientRegistration clientRegistration(OAuth2PasswordGrantRequest grantRequest) { @@ -52,12 +56,11 @@ public final class WebClientReactivePasswordTokenResponseClient extends } @Override - BodyInserters.FormInserter populateTokenRequestBody( - OAuth2PasswordGrantRequest grantRequest, + BodyInserters.FormInserter populateTokenRequestBody(OAuth2PasswordGrantRequest grantRequest, BodyInserters.FormInserter body) { return super.populateTokenRequestBody(grantRequest, body) - .with(OAuth2ParameterNames.USERNAME, grantRequest.getUsername()) - .with(OAuth2ParameterNames.PASSWORD, grantRequest.getPassword()); + .with(OAuth2ParameterNames.USERNAME, grantRequest.getUsername()) + .with(OAuth2ParameterNames.PASSWORD, grantRequest.getPassword()); } } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClient.java index 9ad787af7f..e0d4924e1e 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClient.java @@ -26,20 +26,21 @@ import org.springframework.web.reactive.function.client.WebClient; import java.util.Set; /** - * An implementation of a {@link ReactiveOAuth2AccessTokenResponseClient} - * for the {@link AuthorizationGrantType#REFRESH_TOKEN refresh_token} grant. - * This implementation uses {@link WebClient} when requesting - * an access token credential at the Authorization Server's Token Endpoint. + * An implementation of a {@link ReactiveOAuth2AccessTokenResponseClient} for the + * {@link AuthorizationGrantType#REFRESH_TOKEN refresh_token} grant. This implementation + * uses {@link WebClient} when requesting an access token credential at the Authorization + * Server's Token Endpoint. * * @author Joe Grandja * @since 5.2 * @see ReactiveOAuth2AccessTokenResponseClient * @see OAuth2RefreshTokenGrantRequest * @see OAuth2AccessTokenResponse - * @see Section 6 Refreshing an Access Token + * @see Section 6 + * Refreshing an Access Token */ -public final class WebClientReactiveRefreshTokenTokenResponseClient extends - AbstractWebClientReactiveOAuth2AccessTokenResponseClient { +public final class WebClientReactiveRefreshTokenTokenResponseClient + extends AbstractWebClientReactiveOAuth2AccessTokenResponseClient { @Override ClientRegistration clientRegistration(OAuth2RefreshTokenGrantRequest grantRequest) { @@ -57,24 +58,23 @@ public final class WebClientReactiveRefreshTokenTokenResponseClient extends } @Override - BodyInserters.FormInserter populateTokenRequestBody( - OAuth2RefreshTokenGrantRequest grantRequest, + BodyInserters.FormInserter populateTokenRequestBody(OAuth2RefreshTokenGrantRequest grantRequest, BodyInserters.FormInserter body) { - return super.populateTokenRequestBody(grantRequest, body) - .with(OAuth2ParameterNames.REFRESH_TOKEN, grantRequest.getRefreshToken().getTokenValue()); + return super.populateTokenRequestBody(grantRequest, body).with(OAuth2ParameterNames.REFRESH_TOKEN, + grantRequest.getRefreshToken().getTokenValue()); } @Override - OAuth2AccessTokenResponse populateTokenResponse( - OAuth2RefreshTokenGrantRequest grantRequest, + OAuth2AccessTokenResponse populateTokenResponse(OAuth2RefreshTokenGrantRequest grantRequest, OAuth2AccessTokenResponse accessTokenResponse) { - if (!CollectionUtils.isEmpty(accessTokenResponse.getAccessToken().getScopes()) && - accessTokenResponse.getRefreshToken() != null) { + if (!CollectionUtils.isEmpty(accessTokenResponse.getAccessToken().getScopes()) + && accessTokenResponse.getRefreshToken() != null) { return accessTokenResponse; } - OAuth2AccessTokenResponse.Builder tokenResponseBuilder = OAuth2AccessTokenResponse.withResponse(accessTokenResponse); + OAuth2AccessTokenResponse.Builder tokenResponseBuilder = OAuth2AccessTokenResponse + .withResponse(accessTokenResponse); if (CollectionUtils.isEmpty(accessTokenResponse.getAccessToken().getScopes())) { tokenResponseBuilder.scopes(defaultScopes(grantRequest)); } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/package-info.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/package-info.java index a443ff76b9..fa3b2f41ba 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/package-info.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Classes and interfaces providing support to the client - * for initiating requests to the Authorization Server's Protocol Endpoints. + * Classes and interfaces providing support to the client for initiating requests to the + * Authorization Server's Protocol Endpoints. */ package org.springframework.security.oauth2.client.endpoint; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorResponseErrorHandler.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorResponseErrorHandler.java index 3f865a5897..2aad49caa6 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorResponseErrorHandler.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/http/OAuth2ErrorResponseErrorHandler.java @@ -38,7 +38,9 @@ import java.io.IOException; * @since 5.1 */ public class OAuth2ErrorResponseErrorHandler implements ResponseErrorHandler { + private final OAuth2ErrorHttpMessageConverter oauth2ErrorConverter = new OAuth2ErrorHttpMessageConverter(); + private final ResponseErrorHandler defaultErrorHandler = new DefaultResponseErrorHandler(); @Override @@ -71,16 +73,17 @@ public class OAuth2ErrorResponseErrorHandler implements ResponseErrorHandler { BearerTokenError bearerTokenError; try { bearerTokenError = BearerTokenError.parse(wwwAuthenticateHeader); - } catch (Exception ex) { + } + catch (Exception ex) { return null; } - String errorCode = bearerTokenError.getCode() != null ? - bearerTokenError.getCode() : OAuth2ErrorCodes.SERVER_ERROR; + String errorCode = bearerTokenError.getCode() != null ? bearerTokenError.getCode() + : OAuth2ErrorCodes.SERVER_ERROR; String errorDescription = bearerTokenError.getDescription(); - String errorUri = bearerTokenError.getURI() != null ? - bearerTokenError.getURI().toString() : null; + String errorUri = bearerTokenError.getURI() != null ? bearerTokenError.getURI().toString() : null; return new OAuth2Error(errorCode, errorDescription, errorUri); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/ClientRegistrationDeserializer.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/ClientRegistrationDeserializer.java index 9e12424f74..84c17c15fd 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/ClientRegistrationDeserializer.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/ClientRegistrationDeserializer.java @@ -43,12 +43,12 @@ import static org.springframework.security.oauth2.client.jackson2.JsonNodeUtils. * @see ClientRegistrationMixin */ final class ClientRegistrationDeserializer extends JsonDeserializer { - private static final StdConverter CLIENT_AUTHENTICATION_METHOD_CONVERTER = - new StdConverters.ClientAuthenticationMethodConverter(); - private static final StdConverter AUTHORIZATION_GRANT_TYPE_CONVERTER = - new StdConverters.AuthorizationGrantTypeConverter(); - private static final StdConverter AUTHENTICATION_METHOD_CONVERTER = - new StdConverters.AuthenticationMethodConverter(); + + private static final StdConverter CLIENT_AUTHENTICATION_METHOD_CONVERTER = new StdConverters.ClientAuthenticationMethodConverter(); + + private static final StdConverter AUTHORIZATION_GRANT_TYPE_CONVERTER = new StdConverters.AuthorizationGrantTypeConverter(); + + private static final StdConverter AUTHENTICATION_METHOD_CONVERTER = new StdConverters.AuthenticationMethodConverter(); @Override public ClientRegistration deserialize(JsonParser parser, DeserializationContext context) throws IOException { @@ -57,29 +57,26 @@ final class ClientRegistrationDeserializer extends JsonDeserializer authorities, + DefaultOAuth2UserMixin(@JsonProperty("authorities") Collection authorities, @JsonProperty("attributes") Map attributes, @JsonProperty("nameAttributeKey") String nameAttributeKey) { } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/DefaultOidcUserMixin.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/DefaultOidcUserMixin.java index 003b6e707e..dcbee5ef45 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/DefaultOidcUserMixin.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/DefaultOidcUserMixin.java @@ -38,14 +38,13 @@ import java.util.Collection; @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE) -@JsonIgnoreProperties(value = {"attributes"}, ignoreUnknown = true) +@JsonIgnoreProperties(value = { "attributes" }, ignoreUnknown = true) abstract class DefaultOidcUserMixin { @JsonCreator - DefaultOidcUserMixin( - @JsonProperty("authorities") Collection authorities, - @JsonProperty("idToken") OidcIdToken idToken, - @JsonProperty("userInfo") OidcUserInfo userInfo, + DefaultOidcUserMixin(@JsonProperty("authorities") Collection authorities, + @JsonProperty("idToken") OidcIdToken idToken, @JsonProperty("userInfo") OidcUserInfo userInfo, @JsonProperty("nameAttributeKey") String nameAttributeKey) { } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/JsonNodeUtils.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/JsonNodeUtils.java index d9320227b7..6e9afbb2ed 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/JsonNodeUtils.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/JsonNodeUtils.java @@ -29,9 +29,11 @@ import java.util.Set; * @since 5.3 */ abstract class JsonNodeUtils { - static final TypeReference> SET_TYPE_REFERENCE = new TypeReference>() {}; - static final TypeReference> MAP_TYPE_REFERENCE = new TypeReference>() {}; + static final TypeReference> SET_TYPE_REFERENCE = new TypeReference>() { + }; + static final TypeReference> MAP_TYPE_REFERENCE = new TypeReference>() { + }; static String findStringValue(JsonNode jsonNode, String fieldName) { if (jsonNode == null) { @@ -44,7 +46,8 @@ abstract class JsonNodeUtils { return null; } - static T findValue(JsonNode jsonNode, String fieldName, TypeReference valueTypeReference, ObjectMapper mapper) { + static T findValue(JsonNode jsonNode, String fieldName, TypeReference valueTypeReference, + ObjectMapper mapper) { if (jsonNode == null) { return null; } @@ -65,4 +68,5 @@ abstract class JsonNodeUtils { } return null; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AccessTokenMixin.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AccessTokenMixin.java index f94eb87178..a6ca1d18ff 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AccessTokenMixin.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AccessTokenMixin.java @@ -42,10 +42,10 @@ abstract class OAuth2AccessTokenMixin { @JsonCreator OAuth2AccessTokenMixin( - @JsonProperty("tokenType") @JsonDeserialize(converter = StdConverters.AccessTokenTypeConverter.class) OAuth2AccessToken.TokenType tokenType, - @JsonProperty("tokenValue") String tokenValue, - @JsonProperty("issuedAt") Instant issuedAt, - @JsonProperty("expiresAt") Instant expiresAt, - @JsonProperty("scopes") Set scopes) { + @JsonProperty("tokenType") @JsonDeserialize( + converter = StdConverters.AccessTokenTypeConverter.class) OAuth2AccessToken.TokenType tokenType, + @JsonProperty("tokenValue") String tokenValue, @JsonProperty("issuedAt") Instant issuedAt, + @JsonProperty("expiresAt") Instant expiresAt, @JsonProperty("scopes") Set scopes) { } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationExceptionMixin.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationExceptionMixin.java index 187eb16d8e..9175b10e9e 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationExceptionMixin.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationExceptionMixin.java @@ -34,13 +34,13 @@ import org.springframework.security.oauth2.core.OAuth2Error; */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, - isGetterVisibility = JsonAutoDetect.Visibility.NONE) -@JsonIgnoreProperties(ignoreUnknown = true, value = {"cause", "stackTrace", "suppressedExceptions"}) + isGetterVisibility = JsonAutoDetect.Visibility.NONE) +@JsonIgnoreProperties(ignoreUnknown = true, value = { "cause", "stackTrace", "suppressedExceptions" }) abstract class OAuth2AuthenticationExceptionMixin { @JsonCreator - OAuth2AuthenticationExceptionMixin( - @JsonProperty("error") OAuth2Error error, + OAuth2AuthenticationExceptionMixin(@JsonProperty("error") OAuth2Error error, @JsonProperty("detailMessage") String message) { } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationTokenMixin.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationTokenMixin.java index ebd3c1b77c..cbfec890c2 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationTokenMixin.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationTokenMixin.java @@ -37,13 +37,13 @@ import java.util.Collection; @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE) -@JsonIgnoreProperties(value = {"authenticated"}, ignoreUnknown = true) +@JsonIgnoreProperties(value = { "authenticated" }, ignoreUnknown = true) abstract class OAuth2AuthenticationTokenMixin { @JsonCreator - OAuth2AuthenticationTokenMixin( - @JsonProperty("principal") OAuth2User principal, + OAuth2AuthenticationTokenMixin(@JsonProperty("principal") OAuth2User principal, @JsonProperty("authorities") Collection authorities, @JsonProperty("authorizedClientRegistrationId") String authorizedClientRegistrationId) { } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizationRequestDeserializer.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizationRequestDeserializer.java index ae3d64ae38..6c2e4a1753 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizationRequestDeserializer.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizationRequestDeserializer.java @@ -42,35 +42,38 @@ import static org.springframework.security.oauth2.client.jackson2.JsonNodeUtils. * @see OAuth2AuthorizationRequestMixin */ final class OAuth2AuthorizationRequestDeserializer extends JsonDeserializer { - private static final StdConverter AUTHORIZATION_GRANT_TYPE_CONVERTER = - new StdConverters.AuthorizationGrantTypeConverter(); + + private static final StdConverter AUTHORIZATION_GRANT_TYPE_CONVERTER = new StdConverters.AuthorizationGrantTypeConverter(); @Override - public OAuth2AuthorizationRequest deserialize(JsonParser parser, DeserializationContext context) throws IOException { + public OAuth2AuthorizationRequest deserialize(JsonParser parser, DeserializationContext context) + throws IOException { ObjectMapper mapper = (ObjectMapper) parser.getCodec(); JsonNode authorizationRequestNode = mapper.readTree(parser); - AuthorizationGrantType authorizationGrantType = AUTHORIZATION_GRANT_TYPE_CONVERTER.convert( - findObjectNode(authorizationRequestNode, "authorizationGrantType")); + AuthorizationGrantType authorizationGrantType = AUTHORIZATION_GRANT_TYPE_CONVERTER + .convert(findObjectNode(authorizationRequestNode, "authorizationGrantType")); OAuth2AuthorizationRequest.Builder builder; if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(authorizationGrantType)) { builder = OAuth2AuthorizationRequest.authorizationCode(); - } else if (AuthorizationGrantType.IMPLICIT.equals(authorizationGrantType)) { + } + else if (AuthorizationGrantType.IMPLICIT.equals(authorizationGrantType)) { builder = OAuth2AuthorizationRequest.implicit(); - } else { + } + else { throw new JsonParseException(parser, "Invalid authorizationGrantType"); } - return builder - .authorizationUri(findStringValue(authorizationRequestNode, "authorizationUri")) + return builder.authorizationUri(findStringValue(authorizationRequestNode, "authorizationUri")) .clientId(findStringValue(authorizationRequestNode, "clientId")) .redirectUri(findStringValue(authorizationRequestNode, "redirectUri")) .scopes(findValue(authorizationRequestNode, "scopes", SET_TYPE_REFERENCE, mapper)) .state(findStringValue(authorizationRequestNode, "state")) - .additionalParameters(findValue(authorizationRequestNode, "additionalParameters", MAP_TYPE_REFERENCE, mapper)) + .additionalParameters( + findValue(authorizationRequestNode, "additionalParameters", MAP_TYPE_REFERENCE, mapper)) .authorizationRequestUri(findStringValue(authorizationRequestNode, "authorizationRequestUri")) - .attributes(findValue(authorizationRequestNode, "attributes", MAP_TYPE_REFERENCE, mapper)) - .build(); + .attributes(findValue(authorizationRequestNode, "attributes", MAP_TYPE_REFERENCE, mapper)).build(); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizationRequestMixin.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizationRequestMixin.java index 4e85728a1f..760b536780 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizationRequestMixin.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizationRequestMixin.java @@ -37,4 +37,5 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequ isGetterVisibility = JsonAutoDetect.Visibility.NONE) @JsonIgnoreProperties(ignoreUnknown = true) abstract class OAuth2AuthorizationRequestMixin { + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizedClientMixin.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizedClientMixin.java index 3ca81104eb..f56c4d1ca1 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizedClientMixin.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizedClientMixin.java @@ -40,10 +40,10 @@ import org.springframework.security.oauth2.core.OAuth2RefreshToken; abstract class OAuth2AuthorizedClientMixin { @JsonCreator - OAuth2AuthorizedClientMixin( - @JsonProperty("clientRegistration") ClientRegistration clientRegistration, + OAuth2AuthorizedClientMixin(@JsonProperty("clientRegistration") ClientRegistration clientRegistration, @JsonProperty("principalName") String principalName, @JsonProperty("accessToken") OAuth2AccessToken accessToken, @JsonProperty("refreshToken") OAuth2RefreshToken refreshToken) { } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2ClientJackson2Module.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2ClientJackson2Module.java index 4aa70fc847..5ed27cf913 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2ClientJackson2Module.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2ClientJackson2Module.java @@ -36,36 +36,37 @@ import org.springframework.security.oauth2.core.user.OAuth2UserAuthority; import java.util.Collections; /** - * Jackson {@code Module} for {@code spring-security-oauth2-client}, - * that registers the following mix-in annotations: + * Jackson {@code Module} for {@code spring-security-oauth2-client}, that registers the + * following mix-in annotations: * *

          - *
        • {@link OAuth2AuthorizationRequestMixin}
        • - *
        • {@link ClientRegistrationMixin}
        • - *
        • {@link OAuth2AccessTokenMixin}
        • - *
        • {@link OAuth2RefreshTokenMixin}
        • - *
        • {@link OAuth2AuthorizedClientMixin}
        • - *
        • {@link OAuth2UserAuthorityMixin}
        • - *
        • {@link DefaultOAuth2UserMixin}
        • - *
        • {@link OidcIdTokenMixin}
        • - *
        • {@link OidcUserInfoMixin}
        • - *
        • {@link OidcUserAuthorityMixin}
        • - *
        • {@link DefaultOidcUserMixin}
        • - *
        • {@link OAuth2AuthenticationTokenMixin}
        • - *
        • {@link OAuth2AuthenticationExceptionMixin}
        • - *
        • {@link OAuth2ErrorMixin}
        • + *
        • {@link OAuth2AuthorizationRequestMixin}
        • + *
        • {@link ClientRegistrationMixin}
        • + *
        • {@link OAuth2AccessTokenMixin}
        • + *
        • {@link OAuth2RefreshTokenMixin}
        • + *
        • {@link OAuth2AuthorizedClientMixin}
        • + *
        • {@link OAuth2UserAuthorityMixin}
        • + *
        • {@link DefaultOAuth2UserMixin}
        • + *
        • {@link OidcIdTokenMixin}
        • + *
        • {@link OidcUserInfoMixin}
        • + *
        • {@link OidcUserAuthorityMixin}
        • + *
        • {@link DefaultOidcUserMixin}
        • + *
        • {@link OAuth2AuthenticationTokenMixin}
        • + *
        • {@link OAuth2AuthenticationExceptionMixin}
        • + *
        • {@link OAuth2ErrorMixin}
        • *
        * - * If not already enabled, default typing will be automatically enabled - * as type info is required to properly serialize/deserialize objects. - * In order to use this module just add it to your {@code ObjectMapper} configuration. + * If not already enabled, default typing will be automatically enabled as type info is + * required to properly serialize/deserialize objects. In order to use this module just + * add it to your {@code ObjectMapper} configuration. * *
          *     ObjectMapper mapper = new ObjectMapper();
          *     mapper.registerModule(new OAuth2ClientJackson2Module());
          * 
        * - * NOTE: Use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get a list of all security modules. + * NOTE: Use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get a list + * of all security modules. * * @author Joe Grandja * @since 5.3 @@ -94,7 +95,8 @@ public class OAuth2ClientJackson2Module extends SimpleModule { @Override public void setupModule(SetupContext context) { SecurityJackson2Modules.enableDefaultTyping(context.getOwner()); - context.setMixInAnnotations(Collections.unmodifiableMap(Collections.emptyMap()).getClass(), UnmodifiableMapMixin.class); + context.setMixInAnnotations(Collections.unmodifiableMap(Collections.emptyMap()).getClass(), + UnmodifiableMapMixin.class); context.setMixInAnnotations(OAuth2AuthorizationRequest.class, OAuth2AuthorizationRequestMixin.class); context.setMixInAnnotations(ClientRegistration.class, ClientRegistrationMixin.class); context.setMixInAnnotations(OAuth2AccessToken.class, OAuth2AccessTokenMixin.class); @@ -110,4 +112,5 @@ public class OAuth2ClientJackson2Module extends SimpleModule { context.setMixInAnnotations(OAuth2AuthenticationException.class, OAuth2AuthenticationExceptionMixin.class); context.setMixInAnnotations(OAuth2Error.class, OAuth2ErrorMixin.class); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2ErrorMixin.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2ErrorMixin.java index aba0c5b61f..3d59400d42 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2ErrorMixin.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2ErrorMixin.java @@ -34,14 +34,13 @@ import org.springframework.security.oauth2.core.OAuth2Error; */ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, - isGetterVisibility = JsonAutoDetect.Visibility.NONE) + isGetterVisibility = JsonAutoDetect.Visibility.NONE) @JsonIgnoreProperties(ignoreUnknown = true) abstract class OAuth2ErrorMixin { @JsonCreator - OAuth2ErrorMixin( - @JsonProperty("errorCode") String errorCode, - @JsonProperty("description") String description, + OAuth2ErrorMixin(@JsonProperty("errorCode") String errorCode, @JsonProperty("description") String description, @JsonProperty("uri") String uri) { } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2RefreshTokenMixin.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2RefreshTokenMixin.java index 191fb3e2d1..71c54c45c4 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2RefreshTokenMixin.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2RefreshTokenMixin.java @@ -39,8 +39,7 @@ import java.time.Instant; abstract class OAuth2RefreshTokenMixin { @JsonCreator - OAuth2RefreshTokenMixin( - @JsonProperty("tokenValue") String tokenValue, - @JsonProperty("issuedAt") Instant issuedAt) { + OAuth2RefreshTokenMixin(@JsonProperty("tokenValue") String tokenValue, @JsonProperty("issuedAt") Instant issuedAt) { } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2UserAuthorityMixin.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2UserAuthorityMixin.java index 02509a3575..481a64e18c 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2UserAuthorityMixin.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OAuth2UserAuthorityMixin.java @@ -39,8 +39,8 @@ import java.util.Map; abstract class OAuth2UserAuthorityMixin { @JsonCreator - OAuth2UserAuthorityMixin( - @JsonProperty("authority") String authority, + OAuth2UserAuthorityMixin(@JsonProperty("authority") String authority, @JsonProperty("attributes") Map attributes) { } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OidcIdTokenMixin.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OidcIdTokenMixin.java index d795e157b7..2f687460b7 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OidcIdTokenMixin.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OidcIdTokenMixin.java @@ -40,10 +40,8 @@ import java.util.Map; abstract class OidcIdTokenMixin { @JsonCreator - OidcIdTokenMixin( - @JsonProperty("tokenValue") String tokenValue, - @JsonProperty("issuedAt") Instant issuedAt, - @JsonProperty("expiresAt") Instant expiresAt, - @JsonProperty("claims") Map claims) { + OidcIdTokenMixin(@JsonProperty("tokenValue") String tokenValue, @JsonProperty("issuedAt") Instant issuedAt, + @JsonProperty("expiresAt") Instant expiresAt, @JsonProperty("claims") Map claims) { } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OidcUserAuthorityMixin.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OidcUserAuthorityMixin.java index 1ab4de1ac2..324b69160b 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OidcUserAuthorityMixin.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OidcUserAuthorityMixin.java @@ -35,13 +35,12 @@ import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority; @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE) -@JsonIgnoreProperties(value = {"attributes"}, ignoreUnknown = true) +@JsonIgnoreProperties(value = { "attributes" }, ignoreUnknown = true) abstract class OidcUserAuthorityMixin { @JsonCreator - OidcUserAuthorityMixin( - @JsonProperty("authority") String authority, - @JsonProperty("idToken") OidcIdToken idToken, + OidcUserAuthorityMixin(@JsonProperty("authority") String authority, @JsonProperty("idToken") OidcIdToken idToken, @JsonProperty("userInfo") OidcUserInfo userInfo) { } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OidcUserInfoMixin.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OidcUserInfoMixin.java index 89b131fbdb..83d624e467 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OidcUserInfoMixin.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/OidcUserInfoMixin.java @@ -41,4 +41,5 @@ abstract class OidcUserInfoMixin { @JsonCreator OidcUserInfoMixin(@JsonProperty("claims") Map claims) { } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/StdConverters.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/StdConverters.java index 10510e5baf..ec6ecde107 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/StdConverters.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/StdConverters.java @@ -33,6 +33,7 @@ import static org.springframework.security.oauth2.client.jackson2.JsonNodeUtils. abstract class StdConverters { static final class AccessTokenTypeConverter extends StdConverter { + @Override public OAuth2AccessToken.TokenType convert(JsonNode jsonNode) { String value = findStringValue(jsonNode, "value"); @@ -41,52 +42,67 @@ abstract class StdConverters { } return null; } + } static final class ClientAuthenticationMethodConverter extends StdConverter { + @Override public ClientAuthenticationMethod convert(JsonNode jsonNode) { String value = findStringValue(jsonNode, "value"); if (ClientAuthenticationMethod.BASIC.getValue().equalsIgnoreCase(value)) { return ClientAuthenticationMethod.BASIC; - } else if (ClientAuthenticationMethod.POST.getValue().equalsIgnoreCase(value)) { + } + else if (ClientAuthenticationMethod.POST.getValue().equalsIgnoreCase(value)) { return ClientAuthenticationMethod.POST; - } else if (ClientAuthenticationMethod.NONE.getValue().equalsIgnoreCase(value)) { + } + else if (ClientAuthenticationMethod.NONE.getValue().equalsIgnoreCase(value)) { return ClientAuthenticationMethod.NONE; } return null; } + } static final class AuthorizationGrantTypeConverter extends StdConverter { + @Override public AuthorizationGrantType convert(JsonNode jsonNode) { String value = findStringValue(jsonNode, "value"); if (AuthorizationGrantType.AUTHORIZATION_CODE.getValue().equalsIgnoreCase(value)) { return AuthorizationGrantType.AUTHORIZATION_CODE; - } else if (AuthorizationGrantType.IMPLICIT.getValue().equalsIgnoreCase(value)) { + } + else if (AuthorizationGrantType.IMPLICIT.getValue().equalsIgnoreCase(value)) { return AuthorizationGrantType.IMPLICIT; - } else if (AuthorizationGrantType.CLIENT_CREDENTIALS.getValue().equalsIgnoreCase(value)) { + } + else if (AuthorizationGrantType.CLIENT_CREDENTIALS.getValue().equalsIgnoreCase(value)) { return AuthorizationGrantType.CLIENT_CREDENTIALS; - } else if (AuthorizationGrantType.PASSWORD.getValue().equalsIgnoreCase(value)) { + } + else if (AuthorizationGrantType.PASSWORD.getValue().equalsIgnoreCase(value)) { return AuthorizationGrantType.PASSWORD; } return null; } + } static final class AuthenticationMethodConverter extends StdConverter { + @Override public AuthenticationMethod convert(JsonNode jsonNode) { String value = findStringValue(jsonNode, "value"); if (AuthenticationMethod.HEADER.getValue().equalsIgnoreCase(value)) { return AuthenticationMethod.HEADER; - } else if (AuthenticationMethod.FORM.getValue().equalsIgnoreCase(value)) { + } + else if (AuthenticationMethod.FORM.getValue().equalsIgnoreCase(value)) { return AuthenticationMethod.FORM; - } else if (AuthenticationMethod.QUERY.getValue().equalsIgnoreCase(value)) { + } + else if (AuthenticationMethod.QUERY.getValue().equalsIgnoreCase(value)) { return AuthenticationMethod.QUERY; } return null; } + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/UnmodifiableMapDeserializer.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/UnmodifiableMapDeserializer.java index e7f97a1b87..03070f3be8 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/UnmodifiableMapDeserializer.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/UnmodifiableMapDeserializer.java @@ -49,4 +49,5 @@ final class UnmodifiableMapDeserializer extends JsonDeserializer> { } return Collections.unmodifiableMap(result); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/UnmodifiableMapMixin.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/UnmodifiableMapMixin.java index 18753d4154..577c3e3064 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/UnmodifiableMapMixin.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/jackson2/UnmodifiableMapMixin.java @@ -23,8 +23,9 @@ import java.util.Collections; import java.util.Map; /** - * This mixin class is used to serialize/deserialize {@link Collections#unmodifiableMap(Map)}. - * It also registers a custom deserializer {@link UnmodifiableMapDeserializer}. + * This mixin class is used to serialize/deserialize + * {@link Collections#unmodifiableMap(Map)}. It also registers a custom deserializer + * {@link UnmodifiableMapDeserializer}. * * @author Joe Grandja * @since 5.3 @@ -39,4 +40,5 @@ abstract class UnmodifiableMapMixin { @JsonCreator UnmodifiableMapMixin(Map map) { } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/DefaultOidcIdTokenValidatorFactory.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/DefaultOidcIdTokenValidatorFactory.java index 70c5a6749c..3e7d066e63 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/DefaultOidcIdTokenValidatorFactory.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/DefaultOidcIdTokenValidatorFactory.java @@ -24,7 +24,6 @@ import org.springframework.security.oauth2.jwt.JwtTimestampValidator; import java.util.function.Function; /** - * * @author Joe Grandja * @since 5.2 */ @@ -32,7 +31,8 @@ class DefaultOidcIdTokenValidatorFactory implements Function apply(ClientRegistration clientRegistration) { - return new DelegatingOAuth2TokenValidator<>( - new JwtTimestampValidator(), new OidcIdTokenValidator(clientRegistration)); + return new DelegatingOAuth2TokenValidator<>(new JwtTimestampValidator(), + new OidcIdTokenValidator(clientRegistration)); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java index 9246502d74..afe63b2b23 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java @@ -51,18 +51,18 @@ import java.util.Collection; import java.util.Map; /** - * An implementation of an {@link AuthenticationProvider} - * for the OpenID Connect Core 1.0 Authorization Code Grant Flow. + * An implementation of an {@link AuthenticationProvider} for the OpenID Connect Core 1.0 + * Authorization Code Grant Flow. *

        - * This {@link AuthenticationProvider} is responsible for authenticating - * an Authorization Code credential with the Authorization Server's Token Endpoint - * and if valid, exchanging it for an Access Token credential. + * This {@link AuthenticationProvider} is responsible for authenticating an Authorization + * Code credential with the Authorization Server's Token Endpoint and if valid, exchanging + * it for an Access Token credential. *

        - * It will also obtain the user attributes of the End-User (Resource Owner) - * from the UserInfo Endpoint using an {@link OAuth2UserService}, - * which will create a {@code Principal} in the form of an {@link OidcUser}. - * The {@code OidcUser} is then associated to the {@link OAuth2LoginAuthenticationToken} - * to complete the authentication. + * It will also obtain the user attributes of the End-User (Resource Owner) from the + * UserInfo Endpoint using an {@link OAuth2UserService}, which will create a + * {@code Principal} in the form of an {@link OidcUser}. The {@code OidcUser} is then + * associated to the {@link OAuth2LoginAuthenticationToken} to complete the + * authentication. * * @author Joe Grandja * @author Mark Heckler @@ -72,28 +72,43 @@ import java.util.Map; * @see OidcUserService * @see OidcUser * @see OidcIdTokenDecoderFactory - * @see Section 3.1 Authorization Code Grant Flow - * @see Section 3.1.3.1 Token Request - * @see Section 3.1.3.3 Token Response + * @see Section 3.1 + * Authorization Code Grant Flow + * @see Section 3.1.3.1 + * Token Request + * @see Section 3.1.3.3 + * Token Response */ public class OidcAuthorizationCodeAuthenticationProvider implements AuthenticationProvider { + private static final String INVALID_STATE_PARAMETER_ERROR_CODE = "invalid_state_parameter"; + private static final String INVALID_ID_TOKEN_ERROR_CODE = "invalid_id_token"; + private static final String INVALID_NONCE_ERROR_CODE = "invalid_nonce"; + private final OAuth2AccessTokenResponseClient accessTokenResponseClient; + private final OAuth2UserService userService; + private JwtDecoderFactory jwtDecoderFactory = new OidcIdTokenDecoderFactory(); + private GrantedAuthoritiesMapper authoritiesMapper = (authorities -> authorities); /** - * Constructs an {@code OidcAuthorizationCodeAuthenticationProvider} using the provided parameters. - * - * @param accessTokenResponseClient the client used for requesting the access token credential from the Token Endpoint - * @param userService the service used for obtaining the user attributes of the End-User from the UserInfo Endpoint + * Constructs an {@code OidcAuthorizationCodeAuthenticationProvider} using the + * provided parameters. + * @param accessTokenResponseClient the client used for requesting the access token + * credential from the Token Endpoint + * @param userService the service used for obtaining the user attributes of the + * End-User from the UserInfo Endpoint */ public OidcAuthorizationCodeAuthenticationProvider( - OAuth2AccessTokenResponseClient accessTokenResponseClient, - OAuth2UserService userService) { + OAuth2AccessTokenResponseClient accessTokenResponseClient, + OAuth2UserService userService) { Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null"); Assert.notNull(userService, "userService cannot be null"); @@ -103,27 +118,27 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { - OAuth2LoginAuthenticationToken authorizationCodeAuthentication = - (OAuth2LoginAuthenticationToken) authentication; + OAuth2LoginAuthenticationToken authorizationCodeAuthentication = (OAuth2LoginAuthenticationToken) authentication; - // Section 3.1.2.1 Authentication Request - https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest + // Section 3.1.2.1 Authentication Request - + // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest // scope - // REQUIRED. OpenID Connect requests MUST contain the "openid" scope value. - if (!authorizationCodeAuthentication.getAuthorizationExchange() - .getAuthorizationRequest().getScopes().contains(OidcScopes.OPENID)) { + // REQUIRED. OpenID Connect requests MUST contain the "openid" scope value. + if (!authorizationCodeAuthentication.getAuthorizationExchange().getAuthorizationRequest().getScopes() + .contains(OidcScopes.OPENID)) { // This is NOT an OpenID Connect Authentication Request so return null // and let OAuth2LoginAuthenticationProvider handle it instead return null; } - OAuth2AuthorizationRequest authorizationRequest = authorizationCodeAuthentication - .getAuthorizationExchange().getAuthorizationRequest(); - OAuth2AuthorizationResponse authorizationResponse = authorizationCodeAuthentication - .getAuthorizationExchange().getAuthorizationResponse(); + OAuth2AuthorizationRequest authorizationRequest = authorizationCodeAuthentication.getAuthorizationExchange() + .getAuthorizationRequest(); + OAuth2AuthorizationResponse authorizationResponse = authorizationCodeAuthentication.getAuthorizationExchange() + .getAuthorizationResponse(); if (authorizationResponse.statusError()) { - throw new OAuth2AuthenticationException( - authorizationResponse.getError(), authorizationResponse.getError().toString()); + throw new OAuth2AuthenticationException(authorizationResponse.getError(), + authorizationResponse.getError().toString()); } if (!authorizationResponse.getState().equals(authorizationRequest.getState())) { @@ -134,10 +149,10 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati OAuth2AccessTokenResponse accessTokenResponse; try { accessTokenResponse = this.accessTokenResponseClient.getTokenResponse( - new OAuth2AuthorizationCodeGrantRequest( - authorizationCodeAuthentication.getClientRegistration(), + new OAuth2AuthorizationCodeGrantRequest(authorizationCodeAuthentication.getClientRegistration(), authorizationCodeAuthentication.getAuthorizationExchange())); - } catch (OAuth2AuthorizationException ex) { + } + catch (OAuth2AuthorizationException ex) { OAuth2Error oauth2Error = ex.getError(); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } @@ -146,10 +161,10 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati Map additionalParameters = accessTokenResponse.getAdditionalParameters(); if (!additionalParameters.containsKey(OidcParameterNames.ID_TOKEN)) { - OAuth2Error invalidIdTokenError = new OAuth2Error( - INVALID_ID_TOKEN_ERROR_CODE, - "Missing (required) ID Token in Token Response for Client Registration: " + clientRegistration.getRegistrationId(), - null); + OAuth2Error invalidIdTokenError = new OAuth2Error(INVALID_ID_TOKEN_ERROR_CODE, + "Missing (required) ID Token in Token Response for Client Registration: " + + clientRegistration.getRegistrationId(), + null); throw new OAuth2AuthenticationException(invalidIdTokenError, invalidIdTokenError.toString()); } OidcIdToken idToken = createOidcToken(clientRegistration, accessTokenResponse); @@ -160,7 +175,8 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati String nonceHash; try { nonceHash = createHash(requestNonce); - } catch (NoSuchAlgorithmException e) { + } + catch (NoSuchAlgorithmException e) { OAuth2Error oauth2Error = new OAuth2Error(INVALID_NONCE_ERROR_CODE); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } @@ -171,29 +187,28 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati } } - OidcUser oidcUser = this.userService.loadUser(new OidcUserRequest( - clientRegistration, accessTokenResponse.getAccessToken(), idToken, additionalParameters)); - Collection mappedAuthorities = - this.authoritiesMapper.mapAuthorities(oidcUser.getAuthorities()); + OidcUser oidcUser = this.userService.loadUser(new OidcUserRequest(clientRegistration, + accessTokenResponse.getAccessToken(), idToken, additionalParameters)); + Collection mappedAuthorities = this.authoritiesMapper + .mapAuthorities(oidcUser.getAuthorities()); OAuth2LoginAuthenticationToken authenticationResult = new OAuth2LoginAuthenticationToken( - authorizationCodeAuthentication.getClientRegistration(), - authorizationCodeAuthentication.getAuthorizationExchange(), - oidcUser, - mappedAuthorities, - accessTokenResponse.getAccessToken(), - accessTokenResponse.getRefreshToken()); + authorizationCodeAuthentication.getClientRegistration(), + authorizationCodeAuthentication.getAuthorizationExchange(), oidcUser, mappedAuthorities, + accessTokenResponse.getAccessToken(), accessTokenResponse.getRefreshToken()); authenticationResult.setDetails(authorizationCodeAuthentication.getDetails()); return authenticationResult; } /** - * Sets the {@link JwtDecoderFactory} used for {@link OidcIdToken} signature verification. - * The factory returns a {@link JwtDecoder} associated to the provided {@link ClientRegistration}. + * Sets the {@link JwtDecoderFactory} used for {@link OidcIdToken} signature + * verification. The factory returns a {@link JwtDecoder} associated to the provided + * {@link ClientRegistration}. * * @since 5.2 - * @param jwtDecoderFactory the {@link JwtDecoderFactory} used for {@link OidcIdToken} signature verification + * @param jwtDecoderFactory the {@link JwtDecoderFactory} used for {@link OidcIdToken} + * signature verification */ public final void setJwtDecoderFactory(JwtDecoderFactory jwtDecoderFactory) { Assert.notNull(jwtDecoderFactory, "jwtDecoderFactory cannot be null"); @@ -201,10 +216,11 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati } /** - * Sets the {@link GrantedAuthoritiesMapper} used for mapping {@link OidcUser#getAuthorities()}} - * to a new set of authorities which will be associated to the {@link OAuth2LoginAuthenticationToken}. - * - * @param authoritiesMapper the {@link GrantedAuthoritiesMapper} used for mapping the user's authorities + * Sets the {@link GrantedAuthoritiesMapper} used for mapping + * {@link OidcUser#getAuthorities()}} to a new set of authorities which will be + * associated to the {@link OAuth2LoginAuthenticationToken}. + * @param authoritiesMapper the {@link GrantedAuthoritiesMapper} used for mapping the + * user's authorities */ public final void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) { Assert.notNull(authoritiesMapper, "authoritiesMapper cannot be null"); @@ -216,16 +232,20 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati return OAuth2LoginAuthenticationToken.class.isAssignableFrom(authentication); } - private OidcIdToken createOidcToken(ClientRegistration clientRegistration, OAuth2AccessTokenResponse accessTokenResponse) { + private OidcIdToken createOidcToken(ClientRegistration clientRegistration, + OAuth2AccessTokenResponse accessTokenResponse) { JwtDecoder jwtDecoder = this.jwtDecoderFactory.createDecoder(clientRegistration); Jwt jwt; try { - jwt = jwtDecoder.decode((String) accessTokenResponse.getAdditionalParameters().get(OidcParameterNames.ID_TOKEN)); - } catch (JwtException ex) { + jwt = jwtDecoder + .decode((String) accessTokenResponse.getAdditionalParameters().get(OidcParameterNames.ID_TOKEN)); + } + catch (JwtException ex) { OAuth2Error invalidIdTokenError = new OAuth2Error(INVALID_ID_TOKEN_ERROR_CODE, ex.getMessage(), null); throw new OAuth2AuthenticationException(invalidIdTokenError, invalidIdTokenError.toString(), ex); } - OidcIdToken idToken = new OidcIdToken(jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), jwt.getClaims()); + OidcIdToken idToken = new OidcIdToken(jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), + jwt.getClaims()); return idToken; } @@ -234,4 +254,5 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati byte[] digest = md.digest(nonce.getBytes(StandardCharsets.US_ASCII)); return Base64.getUrlEncoder().withoutPadding().encodeToString(digest); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeReactiveAuthenticationManager.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeReactiveAuthenticationManager.java index a413dca145..f1b8ef5b19 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeReactiveAuthenticationManager.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeReactiveAuthenticationManager.java @@ -51,18 +51,20 @@ import java.util.Collection; import java.util.Map; /** - * An implementation of an {@link org.springframework.security.authentication.AuthenticationProvider} for OAuth 2.0 Login, - * which leverages the OAuth 2.0 Authorization Code Grant Flow. + * An implementation of an + * {@link org.springframework.security.authentication.AuthenticationProvider} for OAuth + * 2.0 Login, which leverages the OAuth 2.0 Authorization Code Grant Flow. *

        - * This {@link org.springframework.security.authentication.AuthenticationProvider} is responsible for authenticating - * an Authorization Code credential with the Authorization Server's Token Endpoint - * and if valid, exchanging it for an Access Token credential. + * This {@link org.springframework.security.authentication.AuthenticationProvider} is + * responsible for authenticating an Authorization Code credential with the Authorization + * Server's Token Endpoint and if valid, exchanging it for an Access Token credential. *

        - * It will also obtain the user attributes of the End-User (Resource Owner) - * from the UserInfo Endpoint using an {@link org.springframework.security.oauth2.client.userinfo.OAuth2UserService}, - * which will create a {@code Principal} in the form of an {@link OAuth2User}. - * The {@code OAuth2User} is then associated to the {@link OAuth2LoginAuthenticationToken} - * to complete the authentication. + * It will also obtain the user attributes of the End-User (Resource Owner) from the + * UserInfo Endpoint using an + * {@link org.springframework.security.oauth2.client.userinfo.OAuth2UserService}, which + * will create a {@code Principal} in the form of an {@link OAuth2User}. The + * {@code OAuth2User} is then associated to the {@link OAuth2LoginAuthenticationToken} to + * complete the authentication. * * @author Rob Winch * @author Mark Heckler @@ -72,15 +74,21 @@ import java.util.Map; * @see ReactiveOAuth2UserService * @see OAuth2User * @see ReactiveOidcIdTokenDecoderFactory - * @see Section 4.1 Authorization Code Grant Flow - * @see Section 4.1.3 Access Token Request - * @see Section 4.1.4 Access Token Response + * @see Section + * 4.1 Authorization Code Grant Flow + * @see Section 4.1.3 Access Token + * Request + * @see Section 4.1.4 Access Token + * Response */ -public class OidcAuthorizationCodeReactiveAuthenticationManager implements - ReactiveAuthenticationManager { +public class OidcAuthorizationCodeReactiveAuthenticationManager implements ReactiveAuthenticationManager { private static final String INVALID_STATE_PARAMETER_ERROR_CODE = "invalid_state_parameter"; + private static final String INVALID_ID_TOKEN_ERROR_CODE = "invalid_id_token"; + private static final String INVALID_NONCE_ERROR_CODE = "invalid_nonce"; private final ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient; @@ -105,52 +113,57 @@ public class OidcAuthorizationCodeReactiveAuthenticationManager implements return Mono.defer(() -> { OAuth2AuthorizationCodeAuthenticationToken authorizationCodeAuthentication = (OAuth2AuthorizationCodeAuthenticationToken) authentication; - // Section 3.1.2.1 Authentication Request - https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest - // scope REQUIRED. OpenID Connect requests MUST contain the "openid" scope value. - if (!authorizationCodeAuthentication.getAuthorizationExchange() - .getAuthorizationRequest().getScopes().contains("openid")) { + // Section 3.1.2.1 Authentication Request - + // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest + // scope REQUIRED. OpenID Connect requests MUST contain the "openid" scope + // value. + if (!authorizationCodeAuthentication.getAuthorizationExchange().getAuthorizationRequest().getScopes() + .contains("openid")) { // This is an OpenID Connect Authentication Request so return empty // and let OAuth2LoginReactiveAuthenticationManager handle it instead return Mono.empty(); } - - OAuth2AuthorizationRequest authorizationRequest = authorizationCodeAuthentication - .getAuthorizationExchange().getAuthorizationRequest(); + OAuth2AuthorizationRequest authorizationRequest = authorizationCodeAuthentication.getAuthorizationExchange() + .getAuthorizationRequest(); OAuth2AuthorizationResponse authorizationResponse = authorizationCodeAuthentication .getAuthorizationExchange().getAuthorizationResponse(); if (authorizationResponse.statusError()) { - return Mono.error(new OAuth2AuthenticationException( - authorizationResponse.getError(), authorizationResponse.getError().toString())); + return Mono.error(new OAuth2AuthenticationException(authorizationResponse.getError(), + authorizationResponse.getError().toString())); } if (!authorizationResponse.getState().equals(authorizationRequest.getState())) { OAuth2Error oauth2Error = new OAuth2Error(INVALID_STATE_PARAMETER_ERROR_CODE); - return Mono.error(new OAuth2AuthenticationException( - oauth2Error, oauth2Error.toString())); + return Mono.error(new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString())); } OAuth2AuthorizationCodeGrantRequest authzRequest = new OAuth2AuthorizationCodeGrantRequest( authorizationCodeAuthentication.getClientRegistration(), authorizationCodeAuthentication.getAuthorizationExchange()); - return this.accessTokenResponseClient.getTokenResponse(authzRequest) - .flatMap(accessTokenResponse -> authenticationResult(authorizationCodeAuthentication, accessTokenResponse)) - .onErrorMap(OAuth2AuthorizationException.class, e -> new OAuth2AuthenticationException(e.getError(), e.getError().toString())) + return this.accessTokenResponseClient.getTokenResponse(authzRequest).flatMap( + accessTokenResponse -> authenticationResult(authorizationCodeAuthentication, accessTokenResponse)) + .onErrorMap(OAuth2AuthorizationException.class, + e -> new OAuth2AuthenticationException(e.getError(), e.getError().toString())) .onErrorMap(JwtException.class, e -> { - OAuth2Error invalidIdTokenError = new OAuth2Error(INVALID_ID_TOKEN_ERROR_CODE, e.getMessage(), null); - return new OAuth2AuthenticationException(invalidIdTokenError, invalidIdTokenError.toString(), e); + OAuth2Error invalidIdTokenError = new OAuth2Error(INVALID_ID_TOKEN_ERROR_CODE, e.getMessage(), + null); + return new OAuth2AuthenticationException(invalidIdTokenError, invalidIdTokenError.toString(), + e); }); }); } /** - * Sets the {@link ReactiveJwtDecoderFactory} used for {@link OidcIdToken} signature verification. - * The factory returns a {@link ReactiveJwtDecoder} associated to the provided {@link ClientRegistration}. + * Sets the {@link ReactiveJwtDecoderFactory} used for {@link OidcIdToken} signature + * verification. The factory returns a {@link ReactiveJwtDecoder} associated to the + * provided {@link ClientRegistration}. * * @since 5.2 - * @param jwtDecoderFactory the {@link ReactiveJwtDecoderFactory} used for {@link OidcIdToken} signature verification + * @param jwtDecoderFactory the {@link ReactiveJwtDecoderFactory} used for + * {@link OidcIdToken} signature verification */ public final void setJwtDecoderFactory(ReactiveJwtDecoderFactory jwtDecoderFactory) { Assert.notNull(jwtDecoderFactory, "jwtDecoderFactory cannot be null"); @@ -158,26 +171,30 @@ public class OidcAuthorizationCodeReactiveAuthenticationManager implements } /** - * Sets the {@link GrantedAuthoritiesMapper} used for mapping {@link OidcUser#getAuthorities()} - * to a new set of authorities which will be associated to the {@link OAuth2LoginAuthenticationToken}. + * Sets the {@link GrantedAuthoritiesMapper} used for mapping + * {@link OidcUser#getAuthorities()} to a new set of authorities which will be + * associated to the {@link OAuth2LoginAuthenticationToken}. * * @since 5.4 - * @param authoritiesMapper the {@link GrantedAuthoritiesMapper} used for mapping the user's authorities + * @param authoritiesMapper the {@link GrantedAuthoritiesMapper} used for mapping the + * user's authorities */ public final void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) { Assert.notNull(authoritiesMapper, "authoritiesMapper cannot be null"); this.authoritiesMapper = authoritiesMapper; } - private Mono authenticationResult(OAuth2AuthorizationCodeAuthenticationToken authorizationCodeAuthentication, OAuth2AccessTokenResponse accessTokenResponse) { + private Mono authenticationResult( + OAuth2AuthorizationCodeAuthenticationToken authorizationCodeAuthentication, + OAuth2AccessTokenResponse accessTokenResponse) { OAuth2AccessToken accessToken = accessTokenResponse.getAccessToken(); ClientRegistration clientRegistration = authorizationCodeAuthentication.getClientRegistration(); Map additionalParameters = accessTokenResponse.getAdditionalParameters(); if (!additionalParameters.containsKey(OidcParameterNames.ID_TOKEN)) { - OAuth2Error invalidIdTokenError = new OAuth2Error( - INVALID_ID_TOKEN_ERROR_CODE, - "Missing (required) ID Token in Token Response for Client Registration: " + clientRegistration.getRegistrationId(), + OAuth2Error invalidIdTokenError = new OAuth2Error(INVALID_ID_TOKEN_ERROR_CODE, + "Missing (required) ID Token in Token Response for Client Registration: " + + clientRegistration.getRegistrationId(), null); return Mono.error(new OAuth2AuthenticationException(invalidIdTokenError, invalidIdTokenError.toString())); } @@ -185,36 +202,34 @@ public class OidcAuthorizationCodeReactiveAuthenticationManager implements return createOidcToken(clientRegistration, accessTokenResponse) .doOnNext(idToken -> validateNonce(authorizationCodeAuthentication, idToken)) .map(idToken -> new OidcUserRequest(clientRegistration, accessToken, idToken, additionalParameters)) - .flatMap(this.userService::loadUser) - .map(oauth2User -> { - Collection mappedAuthorities = - this.authoritiesMapper.mapAuthorities(oauth2User.getAuthorities()); + .flatMap(this.userService::loadUser).map(oauth2User -> { + Collection mappedAuthorities = this.authoritiesMapper + .mapAuthorities(oauth2User.getAuthorities()); - return new OAuth2LoginAuthenticationToken( - authorizationCodeAuthentication.getClientRegistration(), - authorizationCodeAuthentication.getAuthorizationExchange(), - oauth2User, - mappedAuthorities, - accessToken, - accessTokenResponse.getRefreshToken()); + return new OAuth2LoginAuthenticationToken(authorizationCodeAuthentication.getClientRegistration(), + authorizationCodeAuthentication.getAuthorizationExchange(), oauth2User, mappedAuthorities, + accessToken, accessTokenResponse.getRefreshToken()); }); } - private Mono createOidcToken(ClientRegistration clientRegistration, OAuth2AccessTokenResponse accessTokenResponse) { + private Mono createOidcToken(ClientRegistration clientRegistration, + OAuth2AccessTokenResponse accessTokenResponse) { ReactiveJwtDecoder jwtDecoder = this.jwtDecoderFactory.createDecoder(clientRegistration); String rawIdToken = (String) accessTokenResponse.getAdditionalParameters().get(OidcParameterNames.ID_TOKEN); - return jwtDecoder.decode(rawIdToken) - .map(jwt -> new OidcIdToken(jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), jwt.getClaims())); + return jwtDecoder.decode(rawIdToken).map( + jwt -> new OidcIdToken(jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), jwt.getClaims())); } - private static Mono validateNonce(OAuth2AuthorizationCodeAuthenticationToken authorizationCodeAuthentication, OidcIdToken idToken) { - String requestNonce = authorizationCodeAuthentication.getAuthorizationExchange() - .getAuthorizationRequest().getAttribute(OidcParameterNames.NONCE); + private static Mono validateNonce( + OAuth2AuthorizationCodeAuthenticationToken authorizationCodeAuthentication, OidcIdToken idToken) { + String requestNonce = authorizationCodeAuthentication.getAuthorizationExchange().getAuthorizationRequest() + .getAttribute(OidcParameterNames.NONCE); if (requestNonce != null) { String nonceHash; try { nonceHash = createHash(requestNonce); - } catch (NoSuchAlgorithmException e) { + } + catch (NoSuchAlgorithmException e) { OAuth2Error oauth2Error = new OAuth2Error(INVALID_NONCE_ERROR_CODE); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } @@ -233,4 +248,5 @@ public class OidcAuthorizationCodeReactiveAuthenticationManager implements byte[] digest = md.digest(nonce.getBytes(StandardCharsets.US_ASCII)); return Base64.getUrlEncoder().withoutPadding().encodeToString(digest); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenDecoderFactory.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenDecoderFactory.java index da51f71d62..10d48ea8e4 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenDecoderFactory.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenDecoderFactory.java @@ -51,9 +51,9 @@ import static org.springframework.security.oauth2.jwt.NimbusJwtDecoder.withJwkSe import static org.springframework.security.oauth2.jwt.NimbusJwtDecoder.withSecretKey; /** - * A {@link JwtDecoderFactory factory} that provides a {@link JwtDecoder} - * used for {@link OidcIdToken} signature verification. - * The provided {@link JwtDecoder} is associated to a specific {@link ClientRegistration}. + * A {@link JwtDecoderFactory factory} that provides a {@link JwtDecoder} used for + * {@link OidcIdToken} signature verification. The provided {@link JwtDecoder} is + * associated to a specific {@link ClientRegistration}. * * @author Joe Grandja * @author Rafael Dominguez @@ -64,7 +64,9 @@ import static org.springframework.security.oauth2.jwt.NimbusJwtDecoder.withSecre * @see OidcIdToken */ public final class OidcIdTokenDecoderFactory implements JwtDecoderFactory { + private static final String MISSING_SIGNATURE_VERIFIER_ERROR_CODE = "missing_signature_verifier"; + private static Map jcaAlgorithmMappings = new HashMap() { { put(MacAlgorithm.HS256, "HmacSHA256"); @@ -72,18 +74,23 @@ public final class OidcIdTokenDecoderFactory implements JwtDecoderFactory, Map> DEFAULT_CLAIM_TYPE_CONVERTER = - new ClaimTypeConverter(createDefaultClaimTypeConverters()); + + private static final Converter, Map> DEFAULT_CLAIM_TYPE_CONVERTER = new ClaimTypeConverter( + createDefaultClaimTypeConverters()); + private final Map jwtDecoders = new ConcurrentHashMap<>(); + private Function> jwtValidatorFactory = new DefaultOidcIdTokenValidatorFactory(); + private Function jwsAlgorithmResolver = clientRegistration -> SignatureAlgorithm.RS256; - private Function, Map>> claimTypeConverterFactory = - clientRegistration -> DEFAULT_CLAIM_TYPE_CONVERTER; + + private Function, Map>> claimTypeConverterFactory = clientRegistration -> DEFAULT_CLAIM_TYPE_CONVERTER; /** - * Returns the default {@link Converter}'s used for type conversion of claim values for an {@link OidcIdToken}. - * - * @return a {@link Map} of {@link Converter}'s keyed by {@link IdTokenClaimNames claim name} + * Returns the default {@link Converter}'s used for type conversion of claim values + * for an {@link OidcIdToken}. + * @return a {@link Map} of {@link Converter}'s keyed by {@link IdTokenClaimNames + * claim name} */ public static Map> createDefaultClaimTypeConverters() { Converter booleanConverter = getConverter(TypeDescriptor.valueOf(Boolean.class)); @@ -118,8 +125,8 @@ public final class OidcIdTokenDecoderFactory implements JwtDecoderFactory { NimbusJwtDecoder jwtDecoder = buildDecoder(clientRegistration); jwtDecoder.setJwtValidator(this.jwtValidatorFactory.apply(clientRegistration)); - Converter, Map> claimTypeConverter = - this.claimTypeConverterFactory.apply(clientRegistration); + Converter, Map> claimTypeConverter = this.claimTypeConverterFactory + .apply(clientRegistration); if (claimTypeConverter != null) { jwtDecoder.setClaimSetConverter(claimTypeConverter); } @@ -134,68 +141,68 @@ public final class OidcIdTokenDecoderFactory implements JwtDecoderFactory> jwtValidatorFactory) { Assert.notNull(jwtValidatorFactory, "jwtValidatorFactory cannot be null"); @@ -204,11 +211,11 @@ public final class OidcIdTokenDecoderFactory implements JwtDecoderFactory jwsAlgorithmResolver) { Assert.notNull(jwsAlgorithmResolver, "jwsAlgorithmResolver cannot be null"); @@ -216,14 +223,17 @@ public final class OidcIdTokenDecoderFactory implements JwtDecoderFactory, Map>> claimTypeConverterFactory) { + public void setClaimTypeConverterFactory( + Function, Map>> claimTypeConverterFactory) { Assert.notNull(claimTypeConverterFactory, "claimTypeConverterFactory cannot be null"); this.claimTypeConverterFactory = claimTypeConverterFactory; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenValidator.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenValidator.java index 03ae739a7b..21a80d8b14 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenValidator.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenValidator.java @@ -36,20 +36,26 @@ import java.util.Map; import java.util.Objects; /** - * An {@link OAuth2TokenValidator} responsible for - * validating the claims in an {@link OidcIdToken ID Token}. + * An {@link OAuth2TokenValidator} responsible for validating the claims in an + * {@link OidcIdToken ID Token}. * * @author Rob Winch * @author Joe Grandja * @since 5.1 * @see OAuth2TokenValidator * @see Jwt - * @see ID Token Validation + * @see ID Token + * Validation */ public final class OidcIdTokenValidator implements OAuth2TokenValidator { + private static final Duration DEFAULT_CLOCK_SKEW = Duration.ofSeconds(60); + private final ClientRegistration clientRegistration; + private Duration clockSkew = DEFAULT_CLOCK_SKEW; + private Clock clock = Clock.systemUTC(); public OidcIdTokenValidator(ClientRegistration clientRegistration) { @@ -59,7 +65,7 @@ public final class OidcIdTokenValidator implements OAuth2TokenValidator { @Override public OAuth2TokenValidatorResult validate(Jwt idToken) { - // 3.1.3.7 ID Token Validation + // 3.1.3.7 ID Token Validation // https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation Map invalidClaims = validateRequiredClaims(idToken); @@ -67,7 +73,8 @@ public final class OidcIdTokenValidator implements OAuth2TokenValidator { return OAuth2TokenValidatorResult.failure(invalidIdToken(invalidClaims)); } - // 2. The Issuer Identifier for the OpenID Provider (which is typically obtained during Discovery) + // 2. The Issuer Identifier for the OpenID Provider (which is typically obtained + // during Discovery) // MUST exactly match the value of the iss (issuer) Claim. String metadataIssuer = this.clientRegistration.getProviderDetails().getIssuerUri(); @@ -75,10 +82,12 @@ public final class OidcIdTokenValidator implements OAuth2TokenValidator { invalidClaims.put(IdTokenClaimNames.ISS, idToken.getIssuer()); } - // 3. The Client MUST validate that the aud (audience) Claim contains its client_id value + // 3. The Client MUST validate that the aud (audience) Claim contains its + // client_id value // registered at the Issuer identified by the iss (issuer) Claim as an audience. // The aud (audience) Claim MAY contain an array with more than one element. - // The ID Token MUST be rejected if the ID Token does not list the Client as a valid audience, + // The ID Token MUST be rejected if the ID Token does not list the Client as a + // valid audience, // or if it contains additional audiences not trusted by the Client. if (!idToken.getAudience().contains(this.clientRegistration.getClientId())) { invalidClaims.put(IdTokenClaimNames.AUD, idToken.getAudience()); @@ -97,7 +106,8 @@ public final class OidcIdTokenValidator implements OAuth2TokenValidator { invalidClaims.put(IdTokenClaimNames.AZP, authorizedParty); } - // 7. The alg value SHOULD be the default of RS256 or the algorithm sent by the Client + // 7. The alg value SHOULD be the default of RS256 or the algorithm sent by the + // Client // in the id_token_signed_response_alg parameter during Registration. // TODO Depends on gh-4413 @@ -107,7 +117,8 @@ public final class OidcIdTokenValidator implements OAuth2TokenValidator { invalidClaims.put(IdTokenClaimNames.EXP, idToken.getExpiresAt()); } - // 10. The iat Claim can be used to reject tokens that were issued too far away from the current time, + // 10. The iat Claim can be used to reject tokens that were issued too far away + // from the current time, // limiting the amount of time that nonces need to be stored to prevent attacks. // The acceptable range is Client specific. if (now.plus(this.clockSkew).isBefore(idToken.getIssuedAt())) { @@ -122,9 +133,9 @@ public final class OidcIdTokenValidator implements OAuth2TokenValidator { } /** - * Sets the maximum acceptable clock skew. The default is 60 seconds. - * The clock skew is used when validating the {@link JwtClaimNames#EXP exp} - * and {@link JwtClaimNames#IAT iat} claims. + * Sets the maximum acceptable clock skew. The default is 60 seconds. The clock skew + * is used when validating the {@link JwtClaimNames#EXP exp} and + * {@link JwtClaimNames#IAT iat} claims. * * @since 5.2 * @param clockSkew the maximum acceptable clock skew @@ -136,9 +147,8 @@ public final class OidcIdTokenValidator implements OAuth2TokenValidator { } /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} - * when validating the {@link JwtClaimNames#EXP exp} - * and {@link JwtClaimNames#IAT iat} claims. + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when validating the + * {@link JwtClaimNames#EXP exp} and {@link JwtClaimNames#IAT iat} claims. * * @since 5.3 * @param clock the clock @@ -149,8 +159,7 @@ public final class OidcIdTokenValidator implements OAuth2TokenValidator { } private static OAuth2Error invalidIdToken(Map invalidClaims) { - return new OAuth2Error("invalid_id_token", - "The ID Token contains invalid claims: " + invalidClaims, + return new OAuth2Error("invalid_id_token", "The ID Token contains invalid claims: " + invalidClaims, "https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation"); } @@ -180,4 +189,5 @@ public final class OidcIdTokenValidator implements OAuth2TokenValidator { return requiredClaims; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/ReactiveOidcIdTokenDecoderFactory.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/ReactiveOidcIdTokenDecoderFactory.java index 6661efb7ed..c4421c1fbf 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/ReactiveOidcIdTokenDecoderFactory.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/ReactiveOidcIdTokenDecoderFactory.java @@ -52,8 +52,8 @@ import static org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder.w /** * A {@link ReactiveJwtDecoderFactory factory} that provides a {@link ReactiveJwtDecoder} - * used for {@link OidcIdToken} signature verification. - * The provided {@link ReactiveJwtDecoder} is associated to a specific {@link ClientRegistration}. + * used for {@link OidcIdToken} signature verification. The provided + * {@link ReactiveJwtDecoder} is associated to a specific {@link ClientRegistration}. * * @author Joe Grandja * @author Rafael Dominguez @@ -64,7 +64,9 @@ import static org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder.w * @see OidcIdToken */ public final class ReactiveOidcIdTokenDecoderFactory implements ReactiveJwtDecoderFactory { + private static final String MISSING_SIGNATURE_VERIFIER_ERROR_CODE = "missing_signature_verifier"; + private static Map jcaAlgorithmMappings = new HashMap() { { put(MacAlgorithm.HS256, "HmacSHA256"); @@ -72,18 +74,23 @@ public final class ReactiveOidcIdTokenDecoderFactory implements ReactiveJwtDecod put(MacAlgorithm.HS512, "HmacSHA512"); } }; - private static final Converter, Map> DEFAULT_CLAIM_TYPE_CONVERTER = - new ClaimTypeConverter(createDefaultClaimTypeConverters()); + + private static final Converter, Map> DEFAULT_CLAIM_TYPE_CONVERTER = new ClaimTypeConverter( + createDefaultClaimTypeConverters()); + private final Map jwtDecoders = new ConcurrentHashMap<>(); + private Function> jwtValidatorFactory = new DefaultOidcIdTokenValidatorFactory(); + private Function jwsAlgorithmResolver = clientRegistration -> SignatureAlgorithm.RS256; - private Function, Map>> claimTypeConverterFactory = - clientRegistration -> DEFAULT_CLAIM_TYPE_CONVERTER; + + private Function, Map>> claimTypeConverterFactory = clientRegistration -> DEFAULT_CLAIM_TYPE_CONVERTER; /** - * Returns the default {@link Converter}'s used for type conversion of claim values for an {@link OidcIdToken}. - * - * @return a {@link Map} of {@link Converter}'s keyed by {@link IdTokenClaimNames claim name} + * Returns the default {@link Converter}'s used for type conversion of claim values + * for an {@link OidcIdToken}. + * @return a {@link Map} of {@link Converter}'s keyed by {@link IdTokenClaimNames + * claim name} */ public static Map> createDefaultClaimTypeConverters() { Converter booleanConverter = getConverter(TypeDescriptor.valueOf(Boolean.class)); @@ -118,8 +125,8 @@ public final class ReactiveOidcIdTokenDecoderFactory implements ReactiveJwtDecod return this.jwtDecoders.computeIfAbsent(clientRegistration.getRegistrationId(), key -> { NimbusReactiveJwtDecoder jwtDecoder = buildDecoder(clientRegistration); jwtDecoder.setJwtValidator(this.jwtValidatorFactory.apply(clientRegistration)); - Converter, Map> claimTypeConverter = - this.claimTypeConverterFactory.apply(clientRegistration); + Converter, Map> claimTypeConverter = this.claimTypeConverterFactory + .apply(clientRegistration); if (claimTypeConverter != null) { jwtDecoder.setClaimSetConverter(claimTypeConverter); } @@ -134,68 +141,68 @@ public final class ReactiveOidcIdTokenDecoderFactory implements ReactiveJwtDecod // // 6. If the ID Token is received via direct communication between the Client // and the Token Endpoint (which it is in this flow), - // the TLS server validation MAY be used to validate the issuer in place of checking the token signature. - // The Client MUST validate the signature of all other ID Tokens according to JWS [JWS] + // the TLS server validation MAY be used to validate the issuer in place of + // checking the token signature. + // The Client MUST validate the signature of all other ID Tokens according to + // JWS [JWS] // using the algorithm specified in the JWT alg Header Parameter. // The Client MUST use the keys provided by the Issuer. // - // 7. The alg value SHOULD be the default of RS256 or the algorithm sent by the Client + // 7. The alg value SHOULD be the default of RS256 or the algorithm sent by + // the Client // in the id_token_signed_response_alg parameter during Registration. String jwkSetUri = clientRegistration.getProviderDetails().getJwkSetUri(); if (!StringUtils.hasText(jwkSetUri)) { - OAuth2Error oauth2Error = new OAuth2Error( - MISSING_SIGNATURE_VERIFIER_ERROR_CODE, - "Failed to find a Signature Verifier for Client Registration: '" + - clientRegistration.getRegistrationId() + - "'. Check to ensure you have configured the JwkSet URI.", - null - ); + OAuth2Error oauth2Error = new OAuth2Error(MISSING_SIGNATURE_VERIFIER_ERROR_CODE, + "Failed to find a Signature Verifier for Client Registration: '" + + clientRegistration.getRegistrationId() + + "'. Check to ensure you have configured the JwkSet URI.", + null); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } return withJwkSetUri(jwkSetUri).jwsAlgorithm((SignatureAlgorithm) jwsAlgorithm).build(); - } else if (jwsAlgorithm != null && MacAlgorithm.class.isAssignableFrom(jwsAlgorithm.getClass())) { + } + else if (jwsAlgorithm != null && MacAlgorithm.class.isAssignableFrom(jwsAlgorithm.getClass())) { // https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation // - // 8. If the JWT alg Header Parameter uses a MAC based algorithm such as HS256, HS384, or HS512, + // 8. If the JWT alg Header Parameter uses a MAC based algorithm such as + // HS256, HS384, or HS512, // the octets of the UTF-8 representation of the client_secret // corresponding to the client_id contained in the aud (audience) Claim // are used as the key to validate the signature. - // For MAC based algorithms, the behavior is unspecified if the aud is multi-valued or + // For MAC based algorithms, the behavior is unspecified if the aud is + // multi-valued or // if an azp value is present that is different than the aud value. String clientSecret = clientRegistration.getClientSecret(); if (!StringUtils.hasText(clientSecret)) { - OAuth2Error oauth2Error = new OAuth2Error( - MISSING_SIGNATURE_VERIFIER_ERROR_CODE, - "Failed to find a Signature Verifier for Client Registration: '" + - clientRegistration.getRegistrationId() + - "'. Check to ensure you have configured the client secret.", - null - ); + OAuth2Error oauth2Error = new OAuth2Error(MISSING_SIGNATURE_VERIFIER_ERROR_CODE, + "Failed to find a Signature Verifier for Client Registration: '" + + clientRegistration.getRegistrationId() + + "'. Check to ensure you have configured the client secret.", + null); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } - SecretKeySpec secretKeySpec = new SecretKeySpec( - clientSecret.getBytes(StandardCharsets.UTF_8), jcaAlgorithmMappings.get(jwsAlgorithm)); + SecretKeySpec secretKeySpec = new SecretKeySpec(clientSecret.getBytes(StandardCharsets.UTF_8), + jcaAlgorithmMappings.get(jwsAlgorithm)); return withSecretKey(secretKeySpec).macAlgorithm((MacAlgorithm) jwsAlgorithm).build(); } - OAuth2Error oauth2Error = new OAuth2Error( - MISSING_SIGNATURE_VERIFIER_ERROR_CODE, - "Failed to find a Signature Verifier for Client Registration: '" + - clientRegistration.getRegistrationId() + - "'. Check to ensure you have configured a valid JWS Algorithm: '" + - jwsAlgorithm + "'", - null - ); + OAuth2Error oauth2Error = new OAuth2Error(MISSING_SIGNATURE_VERIFIER_ERROR_CODE, + "Failed to find a Signature Verifier for Client Registration: '" + + clientRegistration.getRegistrationId() + + "'. Check to ensure you have configured a valid JWS Algorithm: '" + jwsAlgorithm + "'", + null); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } /** - * Sets the factory that provides an {@link OAuth2TokenValidator}, which is used by the {@link ReactiveJwtDecoder}. - * The default composes {@link JwtTimestampValidator} and {@link OidcIdTokenValidator}. - * - * @param jwtValidatorFactory the factory that provides an {@link OAuth2TokenValidator} + * Sets the factory that provides an {@link OAuth2TokenValidator}, which is used by + * the {@link ReactiveJwtDecoder}. The default composes {@link JwtTimestampValidator} + * and {@link OidcIdTokenValidator}. + * @param jwtValidatorFactory the factory that provides an + * {@link OAuth2TokenValidator} */ public void setJwtValidatorFactory(Function> jwtValidatorFactory) { Assert.notNull(jwtValidatorFactory, "jwtValidatorFactory cannot be null"); @@ -204,11 +211,11 @@ public final class ReactiveOidcIdTokenDecoderFactory implements ReactiveJwtDecod /** * Sets the resolver that provides the expected {@link JwsAlgorithm JWS algorithm} - * used for the signature or MAC on the {@link OidcIdToken ID Token}. - * The default resolves to {@link SignatureAlgorithm#RS256 RS256} for all {@link ClientRegistration clients}. - * - * @param jwsAlgorithmResolver the resolver that provides the expected {@link JwsAlgorithm JWS algorithm} - * for a specific {@link ClientRegistration client} + * used for the signature or MAC on the {@link OidcIdToken ID Token}. The default + * resolves to {@link SignatureAlgorithm#RS256 RS256} for all + * {@link ClientRegistration clients}. + * @param jwsAlgorithmResolver the resolver that provides the expected + * {@link JwsAlgorithm JWS algorithm} for a specific {@link ClientRegistration client} */ public void setJwsAlgorithmResolver(Function jwsAlgorithmResolver) { Assert.notNull(jwsAlgorithmResolver, "jwsAlgorithmResolver cannot be null"); @@ -216,14 +223,17 @@ public final class ReactiveOidcIdTokenDecoderFactory implements ReactiveJwtDecod } /** - * Sets the factory that provides a {@link Converter} used for type conversion of claim values for an {@link OidcIdToken}. - * The default is {@link ClaimTypeConverter} for all {@link ClientRegistration clients}. - * - * @param claimTypeConverterFactory the factory that provides a {@link Converter} used for type conversion - * of claim values for a specific {@link ClientRegistration client} + * Sets the factory that provides a {@link Converter} used for type conversion of + * claim values for an {@link OidcIdToken}. The default is {@link ClaimTypeConverter} + * for all {@link ClientRegistration clients}. + * @param claimTypeConverterFactory the factory that provides a {@link Converter} used + * for type conversion of claim values for a specific {@link ClientRegistration + * client} */ - public void setClaimTypeConverterFactory(Function, Map>> claimTypeConverterFactory) { + public void setClaimTypeConverterFactory( + Function, Map>> claimTypeConverterFactory) { Assert.notNull(claimTypeConverterFactory, "claimTypeConverterFactory cannot be null"); this.claimTypeConverterFactory = claimTypeConverterFactory; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/package-info.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/package-info.java index 6e60be59e7..04db3acbee 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/package-info.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Support classes and interfaces for authenticating and authorizing a client - * with an OpenID Connect 1.0 Provider using a specific authorization grant flow. + * Support classes and interfaces for authenticating and authorizing a client with an + * OpenID Connect 1.0 Provider using a specific authorization grant flow. */ package org.springframework.security.oauth2.client.oidc.authentication; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcReactiveOAuth2UserService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcReactiveOAuth2UserService.java index 5893d799d8..713c696f3d 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcReactiveOAuth2UserService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcReactiveOAuth2UserService.java @@ -46,7 +46,8 @@ import java.util.Set; import java.util.function.Function; /** - * An implementation of an {@link ReactiveOAuth2UserService} that supports OpenID Connect 1.0 Provider's. + * An implementation of an {@link ReactiveOAuth2UserService} that supports OpenID Connect + * 1.0 Provider's. * * @author Rob Winch * @since 5.1 @@ -56,24 +57,24 @@ import java.util.function.Function; * @see DefaultOidcUser * @see OidcUserInfo */ -public class OidcReactiveOAuth2UserService implements - ReactiveOAuth2UserService { +public class OidcReactiveOAuth2UserService implements ReactiveOAuth2UserService { private static final String INVALID_USER_INFO_RESPONSE_ERROR_CODE = "invalid_user_info_response"; - private static final Converter, Map> DEFAULT_CLAIM_TYPE_CONVERTER = - new ClaimTypeConverter(createDefaultClaimTypeConverters()); + private static final Converter, Map> DEFAULT_CLAIM_TYPE_CONVERTER = new ClaimTypeConverter( + createDefaultClaimTypeConverters()); private ReactiveOAuth2UserService oauth2UserService = new DefaultReactiveOAuth2UserService(); - private Function, Map>> claimTypeConverterFactory = - clientRegistration -> DEFAULT_CLAIM_TYPE_CONVERTER; + private Function, Map>> claimTypeConverterFactory = clientRegistration -> DEFAULT_CLAIM_TYPE_CONVERTER; /** - * Returns the default {@link Converter}'s used for type conversion of claim values for an {@link OidcUserInfo}. - + * Returns the default {@link Converter}'s used for type conversion of claim values + * for an {@link OidcUserInfo}. + * * @since 5.2 - * @return a {@link Map} of {@link Converter}'s keyed by {@link StandardClaimNames claim name} + * @return a {@link Map} of {@link Converter}'s keyed by {@link StandardClaimNames + * claim name} */ public static Map> createDefaultClaimTypeConverters() { Converter booleanConverter = getConverter(TypeDescriptor.valueOf(Boolean.class)); @@ -94,25 +95,25 @@ public class OidcReactiveOAuth2UserService implements @Override public Mono loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException { Assert.notNull(userRequest, "userRequest cannot be null"); - return getUserInfo(userRequest) - .map(userInfo -> new OidcUserAuthority(userRequest.getIdToken(), userInfo)) - .defaultIfEmpty(new OidcUserAuthority(userRequest.getIdToken(), null)) - .map(authority -> { - OidcUserInfo userInfo = authority.getUserInfo(); - Set authorities = new HashSet<>(); - authorities.add(authority); - OAuth2AccessToken token = userRequest.getAccessToken(); - for (String scope : token.getScopes()) { - authorities.add(new SimpleGrantedAuthority("SCOPE_" + scope)); - } - String userNameAttributeName = userRequest.getClientRegistration() - .getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName(); - if (StringUtils.hasText(userNameAttributeName)) { - return new DefaultOidcUser(authorities, userRequest.getIdToken(), userInfo, userNameAttributeName); - } else { - return new DefaultOidcUser(authorities, userRequest.getIdToken(), userInfo); - } - }); + return getUserInfo(userRequest).map(userInfo -> new OidcUserAuthority(userRequest.getIdToken(), userInfo)) + .defaultIfEmpty(new OidcUserAuthority(userRequest.getIdToken(), null)).map(authority -> { + OidcUserInfo userInfo = authority.getUserInfo(); + Set authorities = new HashSet<>(); + authorities.add(authority); + OAuth2AccessToken token = userRequest.getAccessToken(); + for (String scope : token.getScopes()) { + authorities.add(new SimpleGrantedAuthority("SCOPE_" + scope)); + } + String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails() + .getUserInfoEndpoint().getUserNameAttributeName(); + if (StringUtils.hasText(userNameAttributeName)) { + return new DefaultOidcUser(authorities, userRequest.getIdToken(), userInfo, + userNameAttributeName); + } + else { + return new DefaultOidcUser(authorities, userRequest.getIdToken(), userInfo); + } + }); } private Mono getUserInfo(OidcUserRequest userRequest) { @@ -120,25 +121,22 @@ public class OidcReactiveOAuth2UserService implements return Mono.empty(); } - return this.oauth2UserService.loadUser(userRequest) - .map(OAuth2User::getAttributes) - .map(claims -> convertClaims(claims, userRequest.getClientRegistration())) - .map(OidcUserInfo::new) - .doOnNext(userInfo -> { - String subject = userInfo.getSubject(); - if (subject == null || !subject.equals(userRequest.getIdToken().getSubject())) { - OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE); - throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); - } - }); + return this.oauth2UserService.loadUser(userRequest).map(OAuth2User::getAttributes) + .map(claims -> convertClaims(claims, userRequest.getClientRegistration())).map(OidcUserInfo::new) + .doOnNext(userInfo -> { + String subject = userInfo.getSubject(); + if (subject == null || !subject.equals(userRequest.getIdToken().getSubject())) { + OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE); + throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); + } + }); } private Map convertClaims(Map claims, ClientRegistration clientRegistration) { - Converter, Map> claimTypeConverter = - this.claimTypeConverterFactory.apply(clientRegistration); - return claimTypeConverter != null ? - claimTypeConverter.convert(claims) : - DEFAULT_CLAIM_TYPE_CONVERTER.convert(claims); + Converter, Map> claimTypeConverter = this.claimTypeConverterFactory + .apply(clientRegistration); + return claimTypeConverter != null ? claimTypeConverter.convert(claims) + : DEFAULT_CLAIM_TYPE_CONVERTER.convert(claims); } public void setOauth2UserService(ReactiveOAuth2UserService oauth2UserService) { @@ -147,15 +145,19 @@ public class OidcReactiveOAuth2UserService implements } /** - * Sets the factory that provides a {@link Converter} used for type conversion of claim values for an {@link OidcUserInfo}. - * The default is {@link ClaimTypeConverter} for all {@link ClientRegistration clients}. + * Sets the factory that provides a {@link Converter} used for type conversion of + * claim values for an {@link OidcUserInfo}. The default is {@link ClaimTypeConverter} + * for all {@link ClientRegistration clients}. * * @since 5.2 - * @param claimTypeConverterFactory the factory that provides a {@link Converter} used for type conversion - * of claim values for a specific {@link ClientRegistration client} + * @param claimTypeConverterFactory the factory that provides a {@link Converter} used + * for type conversion of claim values for a specific {@link ClientRegistration + * client} */ - public final void setClaimTypeConverterFactory(Function, Map>> claimTypeConverterFactory) { + public final void setClaimTypeConverterFactory( + Function, Map>> claimTypeConverterFactory) { Assert.notNull(claimTypeConverterFactory, "claimTypeConverterFactory cannot be null"); this.claimTypeConverterFactory = claimTypeConverterFactory; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequest.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequest.java index ce8c52d8c4..33f4c4a004 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequest.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequest.java @@ -25,8 +25,8 @@ import java.util.Collections; import java.util.Map; /** - * Represents a request the {@link OidcUserService} uses - * when initiating a request to the UserInfo Endpoint. + * Represents a request the {@link OidcUserService} uses when initiating a request to the + * UserInfo Endpoint. * * @author Joe Grandja * @since 5.0 @@ -36,17 +36,16 @@ import java.util.Map; * @see OidcUserService */ public class OidcUserRequest extends OAuth2UserRequest { + private final OidcIdToken idToken; /** * Constructs an {@code OidcUserRequest} using the provided parameters. - * * @param clientRegistration the client registration * @param accessToken the access token credential * @param idToken the ID Token */ - public OidcUserRequest(ClientRegistration clientRegistration, - OAuth2AccessToken accessToken, OidcIdToken idToken) { + public OidcUserRequest(ClientRegistration clientRegistration, OAuth2AccessToken accessToken, OidcIdToken idToken) { this(clientRegistration, accessToken, idToken, Collections.emptyMap()); } @@ -60,8 +59,8 @@ public class OidcUserRequest extends OAuth2UserRequest { * @param idToken the ID Token * @param additionalParameters the additional parameters, may be empty */ - public OidcUserRequest(ClientRegistration clientRegistration, OAuth2AccessToken accessToken, - OidcIdToken idToken, Map additionalParameters) { + public OidcUserRequest(ClientRegistration clientRegistration, OAuth2AccessToken accessToken, OidcIdToken idToken, + Map additionalParameters) { super(clientRegistration, accessToken, additionalParameters); Assert.notNull(idToken, "idToken cannot be null"); @@ -70,10 +69,10 @@ public class OidcUserRequest extends OAuth2UserRequest { /** * Returns the {@link OidcIdToken ID Token} containing claims about the user. - * * @return the {@link OidcIdToken} containing claims about the user. */ public OidcIdToken getIdToken() { return this.idToken; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequestUtils.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequestUtils.java index 5a7787d351..6045a44fa9 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequestUtils.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequestUtils.java @@ -30,13 +30,14 @@ import org.springframework.util.StringUtils; final class OidcUserRequestUtils { /** - * Determines if an {@link OidcUserRequest} should attempt to retrieve the user info endpoint. Will return true if - * all of the following are true: + * Determines if an {@link OidcUserRequest} should attempt to retrieve the user info + * endpoint. Will return true if all of the following are true: * *

          - *
        • The user info endpoint is defined on the ClientRegistration
        • - *
        • The Client Registration uses the {@link AuthorizationGrantType#AUTHORIZATION_CODE} and scopes in the - * access token are defined in the {@link ClientRegistration}
        • + *
        • The user info endpoint is defined on the ClientRegistration
        • + *
        • The Client Registration uses the + * {@link AuthorizationGrantType#AUTHORIZATION_CODE} and scopes in the access token + * are defined in the {@link ClientRegistration}
        • *
        * @param userRequest * @return @@ -44,27 +45,32 @@ final class OidcUserRequestUtils { static boolean shouldRetrieveUserInfo(OidcUserRequest userRequest) { // Auto-disabled if UserInfo Endpoint URI is not provided ClientRegistration clientRegistration = userRequest.getClientRegistration(); - if (StringUtils.isEmpty(clientRegistration.getProviderDetails() - .getUserInfoEndpoint().getUri())) { + if (StringUtils.isEmpty(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUri())) { return false; } // The Claims requested by the profile, email, address, and phone scope values // are returned from the UserInfo Endpoint (as described in Section 5.3.2), - // when a response_type value is used that results in an Access Token being issued. - // However, when no Access Token is issued, which is the case for the response_type=id_token, + // when a response_type value is used that results in an Access Token being + // issued. + // However, when no Access Token is issued, which is the case for the + // response_type=id_token, // the resulting Claims are returned in the ID Token. - // The Authorization Code Grant Flow, which is response_type=code, results in an Access Token being issued. + // The Authorization Code Grant Flow, which is response_type=code, results in an + // Access Token being issued. if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(clientRegistration.getAuthorizationGrantType())) { - // Return true if there is at least one match between the authorized scope(s) and UserInfo scope(s) - return CollectionUtils - .containsAny(userRequest.getAccessToken().getScopes(), userRequest.getClientRegistration().getScopes()); + // Return true if there is at least one match between the authorized scope(s) + // and UserInfo scope(s) + return CollectionUtils.containsAny(userRequest.getAccessToken().getScopes(), + userRequest.getClientRegistration().getScopes()); } return false; } - private OidcUserRequestUtils() {} + private OidcUserRequestUtils() { + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserService.java index 3fb35f5ada..7d30cee451 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserService.java @@ -50,7 +50,8 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; /** - * An implementation of an {@link OAuth2UserService} that supports OpenID Connect 1.0 Provider's. + * An implementation of an {@link OAuth2UserService} that supports OpenID Connect 1.0 + * Provider's. * * @author Joe Grandja * @since 5.0 @@ -61,20 +62,26 @@ import org.springframework.util.StringUtils; * @see OidcUserInfo */ public class OidcUserService implements OAuth2UserService { + private static final String INVALID_USER_INFO_RESPONSE_ERROR_CODE = "invalid_user_info_response"; - private static final Converter, Map> DEFAULT_CLAIM_TYPE_CONVERTER = - new ClaimTypeConverter(createDefaultClaimTypeConverters()); - private Set accessibleScopes = new HashSet<>(Arrays.asList( - OidcScopes.PROFILE, OidcScopes.EMAIL, OidcScopes.ADDRESS, OidcScopes.PHONE)); + + private static final Converter, Map> DEFAULT_CLAIM_TYPE_CONVERTER = new ClaimTypeConverter( + createDefaultClaimTypeConverters()); + + private Set accessibleScopes = new HashSet<>( + Arrays.asList(OidcScopes.PROFILE, OidcScopes.EMAIL, OidcScopes.ADDRESS, OidcScopes.PHONE)); + private OAuth2UserService oauth2UserService = new DefaultOAuth2UserService(); - private Function, Map>> claimTypeConverterFactory = - clientRegistration -> DEFAULT_CLAIM_TYPE_CONVERTER; + + private Function, Map>> claimTypeConverterFactory = clientRegistration -> DEFAULT_CLAIM_TYPE_CONVERTER; /** - * Returns the default {@link Converter}'s used for type conversion of claim values for an {@link OidcUserInfo}. - + * Returns the default {@link Converter}'s used for type conversion of claim values + * for an {@link OidcUserInfo}. + * * @since 5.2 - * @return a {@link Map} of {@link Converter}'s keyed by {@link StandardClaimNames claim name} + * @return a {@link Map} of {@link Converter}'s keyed by {@link StandardClaimNames + * claim name} */ public static Map> createDefaultClaimTypeConverters() { Converter booleanConverter = getConverter(TypeDescriptor.valueOf(Boolean.class)); @@ -100,11 +107,12 @@ public class OidcUserService implements OAuth2UserService claims; - Converter, Map> claimTypeConverter = - this.claimTypeConverterFactory.apply(userRequest.getClientRegistration()); + Converter, Map> claimTypeConverter = this.claimTypeConverterFactory + .apply(userRequest.getClientRegistration()); if (claimTypeConverter != null) { claims = claimTypeConverter.convert(oauth2User.getAttributes()); - } else { + } + else { claims = DEFAULT_CLAIM_TYPE_CONVERTER.convert(oauth2User.getAttributes()); } userInfo = new OidcUserInfo(claims); @@ -117,7 +125,8 @@ public class OidcUserService implements OAuth2UserService oauth2UserService) { Assert.notNull(oauth2UserService, "oauth2UserService cannot be null"); @@ -186,24 +201,29 @@ public class OidcUserService implements OAuth2UserService, Map>> claimTypeConverterFactory) { + public final void setClaimTypeConverterFactory( + Function, Map>> claimTypeConverterFactory) { Assert.notNull(claimTypeConverterFactory, "claimTypeConverterFactory cannot be null"); this.claimTypeConverterFactory = claimTypeConverterFactory; } /** - * Sets the scope(s) that allow access to the user info resource. - * The default is {@link OidcScopes#PROFILE profile}, {@link OidcScopes#EMAIL email}, {@link OidcScopes#ADDRESS address} and {@link OidcScopes#PHONE phone}. - * The scope(s) are checked against the "granted" scope(s) associated to the {@link OidcUserRequest#getAccessToken() access token} - * to determine if the user info resource is accessible or not. - * If there is at least one match, the user info resource will be requested, otherwise it will not. + * Sets the scope(s) that allow access to the user info resource. The default is + * {@link OidcScopes#PROFILE profile}, {@link OidcScopes#EMAIL email}, + * {@link OidcScopes#ADDRESS address} and {@link OidcScopes#PHONE phone}. The scope(s) + * are checked against the "granted" scope(s) associated to the + * {@link OidcUserRequest#getAccessToken() access token} to determine if the user info + * resource is accessible or not. If there is at least one match, the user info + * resource will be requested, otherwise it will not. * * @since 5.2 * @param accessibleScopes the scope(s) that allow access to the user info resource @@ -212,4 +232,5 @@ public class OidcUserService implements OAuth2UserServiceRP-Initiated Logout + * @see RP-Initiated + * Logout * @see org.springframework.security.web.authentication.logout.LogoutSuccessHandler */ public final class OidcClientInitiatedLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler { + private final ClientRegistrationRepository clientRegistrationRepository; private String postLogoutRedirectUri; @@ -52,8 +55,8 @@ public final class OidcClientInitiatedLogoutSuccessHandler extends SimpleUrlLogo } @Override - protected String determineTargetUrl(HttpServletRequest request, - HttpServletResponse response, Authentication authentication) { + protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) { String targetUrl = null; URI endSessionEndpoint; if (authentication instanceof OAuth2AuthenticationToken && authentication.getPrincipal() instanceof OidcUser) { @@ -96,16 +99,11 @@ public final class OidcClientInitiatedLogoutSuccessHandler extends SimpleUrlLogo return null; } UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(UrlUtils.buildFullRequestUrl(request)) - .replacePath(request.getContextPath()) - .replaceQuery(null) - .fragment(null) - .build(); + .replacePath(request.getContextPath()).replaceQuery(null).fragment(null).build(); return UriComponentsBuilder.fromUriString(this.postLogoutRedirectUri) - .buildAndExpand(Collections.singletonMap("baseUrl", uriComponents.toUriString())) - .toUri(); + .buildAndExpand(Collections.singletonMap("baseUrl", uriComponents.toUriString())).toUri(); } - private String endpointUri(URI endSessionEndpoint, String idToken, URI postLogoutRedirectUri) { UriComponentsBuilder builder = UriComponentsBuilder.fromUri(endSessionEndpoint); builder.queryParam("id_token_hint", idToken); @@ -117,8 +115,8 @@ public final class OidcClientInitiatedLogoutSuccessHandler extends SimpleUrlLogo /** * Set the post logout redirect uri to use - * - * @param postLogoutRedirectUri - A valid URL to which the OP should redirect after logging out the user + * @param postLogoutRedirectUri - A valid URL to which the OP should redirect after + * logging out the user * @deprecated {@link #setPostLogoutRedirectUri(String)} */ @Deprecated @@ -135,15 +133,15 @@ public final class OidcClientInitiatedLogoutSuccessHandler extends SimpleUrlLogo * handler.setPostLogoutRedirectUri("{baseUrl}"); *
        * - * will make so that {@code post_logout_redirect_uri} will be set to the base url for the client - * application. - * - * @param postLogoutRedirectUri - A template for creating the {@code post_logout_redirect_uri} - * query parameter + * will make so that {@code post_logout_redirect_uri} will be set to the base url for + * the client application. + * @param postLogoutRedirectUri - A template for creating the + * {@code post_logout_redirect_uri} query parameter * @since 5.3 */ public void setPostLogoutRedirectUri(String postLogoutRedirectUri) { Assert.notNull(postLogoutRedirectUri, "postLogoutRedirectUri cannot be null"); this.postLogoutRedirectUri = postLogoutRedirectUri; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandler.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandler.java index ce4a5dac77..c3eac99e96 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandler.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandler.java @@ -42,27 +42,30 @@ import org.springframework.web.util.UriComponentsBuilder; * * @author Josh Cummings * @since 5.2 - * @see RP-Initiated Logout + * @see RP-Initiated + * Logout * @see org.springframework.security.web.server.authentication.logout.ServerLogoutSuccessHandler */ -public class OidcClientInitiatedServerLogoutSuccessHandler - implements ServerLogoutSuccessHandler { +public class OidcClientInitiatedServerLogoutSuccessHandler implements ServerLogoutSuccessHandler { private final ServerRedirectStrategy redirectStrategy = new DefaultServerRedirectStrategy(); - private final RedirectServerLogoutSuccessHandler serverLogoutSuccessHandler - = new RedirectServerLogoutSuccessHandler(); + + private final RedirectServerLogoutSuccessHandler serverLogoutSuccessHandler = new RedirectServerLogoutSuccessHandler(); + private final ReactiveClientRegistrationRepository clientRegistrationRepository; private String postLogoutRedirectUri; /** - * Constructs an {@link OidcClientInitiatedServerLogoutSuccessHandler} with the provided parameters - * - * @param clientRegistrationRepository The {@link ReactiveClientRegistrationRepository} to use to derive - * the end_session_endpoint value + * Constructs an {@link OidcClientInitiatedServerLogoutSuccessHandler} with the + * provided parameters + * @param clientRegistrationRepository The + * {@link ReactiveClientRegistrationRepository} to use to derive the + * end_session_endpoint value */ - public OidcClientInitiatedServerLogoutSuccessHandler - (ReactiveClientRegistrationRepository clientRegistrationRepository) { + public OidcClientInitiatedServerLogoutSuccessHandler( + ReactiveClientRegistrationRepository clientRegistrationRepository) { Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null"); this.clientRegistrationRepository = clientRegistrationRepository; @@ -73,13 +76,11 @@ public class OidcClientInitiatedServerLogoutSuccessHandler */ @Override public Mono onLogoutSuccess(WebFilterExchange exchange, Authentication authentication) { - return Mono.just(authentication) - .filter(OAuth2AuthenticationToken.class::isInstance) + return Mono.just(authentication).filter(OAuth2AuthenticationToken.class::isInstance) .filter(token -> authentication.getPrincipal() instanceof OidcUser) .map(OAuth2AuthenticationToken.class::cast) .map(OAuth2AuthenticationToken::getAuthorizedClientRegistrationId) - .flatMap(this.clientRegistrationRepository::findByRegistrationId) - .flatMap(clientRegistration -> { + .flatMap(this.clientRegistrationRepository::findByRegistrationId).flatMap(clientRegistration -> { URI endSessionEndpoint = endSessionEndpoint(clientRegistration); if (endSessionEndpoint == null) { return Mono.empty(); @@ -88,8 +89,8 @@ public class OidcClientInitiatedServerLogoutSuccessHandler URI postLogoutRedirectUri = postLogoutRedirectUri(exchange.getExchange().getRequest()); return Mono.just(endpointUri(endSessionEndpoint, idToken, postLogoutRedirectUri)); }) - .switchIfEmpty(this.serverLogoutSuccessHandler - .onLogoutSuccess(exchange, authentication).then(Mono.empty())) + .switchIfEmpty( + this.serverLogoutSuccessHandler.onLogoutSuccess(exchange, authentication).then(Mono.empty())) .flatMap(endpointUri -> this.redirectStrategy.sendRedirect(exchange.getExchange(), endpointUri)); } @@ -124,19 +125,15 @@ public class OidcClientInitiatedServerLogoutSuccessHandler return null; } UriComponents uriComponents = UriComponentsBuilder.fromUri(request.getURI()) - .replacePath(request.getPath().contextPath().value()) - .replaceQuery(null) - .fragment(null) - .build(); + .replacePath(request.getPath().contextPath().value()).replaceQuery(null).fragment(null).build(); return UriComponentsBuilder.fromUriString(this.postLogoutRedirectUri) - .buildAndExpand(Collections.singletonMap("baseUrl", uriComponents.toUriString())) - .toUri(); + .buildAndExpand(Collections.singletonMap("baseUrl", uriComponents.toUriString())).toUri(); } /** * Set the post logout redirect uri to use - * - * @param postLogoutRedirectUri - A valid URL to which the OP should redirect after logging out the user + * @param postLogoutRedirectUri - A valid URL to which the OP should redirect after + * logging out the user * @deprecated {@link #setPostLogoutRedirectUri(String)} */ @Deprecated @@ -153,11 +150,10 @@ public class OidcClientInitiatedServerLogoutSuccessHandler * handler.setPostLogoutRedirectUri("{baseUrl}"); *
        * - * will make so that {@code post_logout_redirect_uri} will be set to the base url for the client - * application. - * - * @param postLogoutRedirectUri - A template for creating the {@code post_logout_redirect_uri} - * query parameter + * will make so that {@code post_logout_redirect_uri} will be set to the base url for + * the client application. + * @param postLogoutRedirectUri - A template for creating the + * {@code post_logout_redirect_uri} query parameter * @since 5.3 */ public void setPostLogoutRedirectUri(String postLogoutRedirectUri) { @@ -166,12 +162,13 @@ public class OidcClientInitiatedServerLogoutSuccessHandler } /** - * The URL to redirect to after successfully logging out when not originally an OIDC login - * + * The URL to redirect to after successfully logging out when not originally an OIDC + * login * @param logoutSuccessUrl the url to redirect to. Default is "/login?logout". */ public void setLogoutSuccessUrl(URI logoutSuccessUrl) { Assert.notNull(logoutSuccessUrl, "logoutSuccessUrl cannot be null"); this.serverLogoutSuccessHandler.setLogoutSuccessUrl(logoutSuccessUrl); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java index 939778b2ee..241fb22755 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java @@ -36,22 +36,34 @@ import org.springframework.util.StringUtils; import static java.util.Collections.EMPTY_MAP; /** - * A representation of a client registration with an OAuth 2.0 or OpenID Connect 1.0 Provider. + * A representation of a client registration with an OAuth 2.0 or OpenID Connect 1.0 + * Provider. * * @author Joe Grandja * @since 5.0 - * @see Section 2 Client Registration + * @see Section 2 + * Client Registration */ public final class ClientRegistration implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private String registrationId; + private String clientId; + private String clientSecret; + private ClientAuthenticationMethod clientAuthenticationMethod; + private AuthorizationGrantType authorizationGrantType; + private String redirectUri; + private Set scopes = Collections.emptySet(); + private ProviderDetails providerDetails = new ProviderDetails(); + private String clientName; private ClientRegistration() { @@ -59,7 +71,6 @@ public final class ClientRegistration implements Serializable { /** * Returns the identifier for the registration. - * * @return the identifier for the registration */ public String getRegistrationId() { @@ -68,7 +79,6 @@ public final class ClientRegistration implements Serializable { /** * Returns the client identifier. - * * @return the client identifier */ public String getClientId() { @@ -77,7 +87,6 @@ public final class ClientRegistration implements Serializable { /** * Returns the client secret. - * * @return the client secret */ public String getClientSecret() { @@ -85,9 +94,8 @@ public final class ClientRegistration implements Serializable { } /** - * Returns the {@link ClientAuthenticationMethod authentication method} used - * when authenticating the client with the authorization server. - * + * Returns the {@link ClientAuthenticationMethod authentication method} used when + * authenticating the client with the authorization server. * @return the {@link ClientAuthenticationMethod} */ public ClientAuthenticationMethod getClientAuthenticationMethod() { @@ -95,8 +103,8 @@ public final class ClientRegistration implements Serializable { } /** - * Returns the {@link AuthorizationGrantType authorization grant type} used for the client. - * + * Returns the {@link AuthorizationGrantType authorization grant type} used for the + * client. * @return the {@link AuthorizationGrantType} */ public AuthorizationGrantType getAuthorizationGrantType() { @@ -105,7 +113,6 @@ public final class ClientRegistration implements Serializable { /** * Returns the uri (or uri template) for the redirection endpoint. - * * @deprecated Use {@link #getRedirectUri()} instead * @return the uri (or uri template) for the redirection endpoint */ @@ -118,14 +125,17 @@ public final class ClientRegistration implements Serializable { * Returns the uri (or uri template) for the redirection endpoint. * *
        - * The supported uri template variables are: {baseScheme}, {baseHost}, {basePort}, {basePath} and {registrationId}. + * The supported uri template variables are: {baseScheme}, {baseHost}, {basePort}, + * {basePath} and {registrationId}. * *
        - * NOTE: {baseUrl} is also supported, which is the same as {baseScheme}://{baseHost}{basePort}{basePath}. + * NOTE: {baseUrl} is also supported, which is the same as + * {baseScheme}://{baseHost}{basePort}{basePath}. * *
        - * Configuring uri template variables is especially useful when the client is running behind a Proxy Server. - * This ensures that the X-Forwarded-* headers are used when expanding the redirect-uri. + * Configuring uri template variables is especially useful when the client is running + * behind a Proxy Server. This ensures that the X-Forwarded-* headers are used when + * expanding the redirect-uri. * * @since 5.4 * @return the uri (or uri template) for the redirection endpoint @@ -136,7 +146,6 @@ public final class ClientRegistration implements Serializable { /** * Returns the scope(s) used for the client. - * * @return the {@code Set} of scope(s) */ public Set getScopes() { @@ -145,7 +154,6 @@ public final class ClientRegistration implements Serializable { /** * Returns the details of the provider. - * * @return the {@link ProviderDetails} */ public ProviderDetails getProviderDetails() { @@ -154,7 +162,6 @@ public final class ClientRegistration implements Serializable { /** * Returns the logical name of the client or registration. - * * @return the client or registration name */ public String getClientName() { @@ -163,29 +170,30 @@ public final class ClientRegistration implements Serializable { @Override public String toString() { - return "ClientRegistration{" - + "registrationId='" + this.registrationId + '\'' - + ", clientId='" + this.clientId + '\'' - + ", clientSecret='" + this.clientSecret + '\'' - + ", clientAuthenticationMethod=" + this.clientAuthenticationMethod - + ", authorizationGrantType=" + this.authorizationGrantType - + ", redirectUri='" + this.redirectUri + '\'' - + ", scopes=" + this.scopes - + ", providerDetails=" + this.providerDetails - + ", clientName='" + this.clientName - + '\'' + '}'; + return "ClientRegistration{" + "registrationId='" + this.registrationId + '\'' + ", clientId='" + this.clientId + + '\'' + ", clientSecret='" + this.clientSecret + '\'' + ", clientAuthenticationMethod=" + + this.clientAuthenticationMethod + ", authorizationGrantType=" + this.authorizationGrantType + + ", redirectUri='" + this.redirectUri + '\'' + ", scopes=" + this.scopes + ", providerDetails=" + + this.providerDetails + ", clientName='" + this.clientName + '\'' + '}'; } /** * Details of the Provider. */ public class ProviderDetails implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private String authorizationUri; + private String tokenUri; + private UserInfoEndpoint userInfoEndpoint = new UserInfoEndpoint(); + private String jwkSetUri; + private String issuerUri; + private Map configurationMetadata = Collections.emptyMap(); private ProviderDetails() { @@ -193,7 +201,6 @@ public final class ClientRegistration implements Serializable { /** * Returns the uri for the authorization endpoint. - * * @return the uri for the authorization endpoint */ public String getAuthorizationUri() { @@ -202,7 +209,6 @@ public final class ClientRegistration implements Serializable { /** * Returns the uri for the token endpoint. - * * @return the uri for the token endpoint */ public String getTokenUri() { @@ -211,7 +217,6 @@ public final class ClientRegistration implements Serializable { /** * Returns the details of the {@link UserInfoEndpoint UserInfo Endpoint}. - * * @return the {@link UserInfoEndpoint} */ public UserInfoEndpoint getUserInfoEndpoint() { @@ -220,7 +225,6 @@ public final class ClientRegistration implements Serializable { /** * Returns the uri for the JSON Web Key (JWK) Set endpoint. - * * @return the uri for the JSON Web Key (JWK) Set endpoint */ public String getJwkSetUri() { @@ -228,11 +232,12 @@ public final class ClientRegistration implements Serializable { } /** - * Returns the issuer identifier uri for the OpenID Connect 1.0 provider - * or the OAuth 2.0 Authorization Server. + * Returns the issuer identifier uri for the OpenID Connect 1.0 provider or the + * OAuth 2.0 Authorization Server. * * @since 5.4 - * @return the issuer identifier uri for the OpenID Connect 1.0 provider or the OAuth 2.0 Authorization Server + * @return the issuer identifier uri for the OpenID Connect 1.0 provider or the + * OAuth 2.0 Authorization Server */ public String getIssuerUri() { return this.issuerUri; @@ -252,9 +257,13 @@ public final class ClientRegistration implements Serializable { * Details of the UserInfo Endpoint. */ public class UserInfoEndpoint implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private String uri; + private AuthenticationMethod authenticationMethod = AuthenticationMethod.HEADER; + private String userNameAttributeName; private UserInfoEndpoint() { @@ -262,7 +271,6 @@ public final class ClientRegistration implements Serializable { /** * Returns the uri for the user info endpoint. - * * @return the uri for the user info endpoint */ public String getUri() { @@ -280,19 +288,22 @@ public final class ClientRegistration implements Serializable { } /** - * Returns the attribute name used to access the user's name from the user info response. - * - * @return the attribute name used to access the user's name from the user info response + * Returns the attribute name used to access the user's name from the user + * info response. + * @return the attribute name used to access the user's name from the user + * info response */ public String getUserNameAttributeName() { return this.userNameAttributeName; } + } + } /** - * Returns a new {@link Builder}, initialized with the provided registration identifier. - * + * Returns a new {@link Builder}, initialized with the provided registration + * identifier. * @param registrationId the identifier for the registration * @return the {@link Builder} */ @@ -302,8 +313,8 @@ public final class ClientRegistration implements Serializable { } /** - * Returns a new {@link Builder}, initialized with the provided {@link ClientRegistration}. - * + * Returns a new {@link Builder}, initialized with the provided + * {@link ClientRegistration}. * @param clientRegistration the {@link ClientRegistration} to copy from * @return the {@link Builder} */ @@ -316,22 +327,39 @@ public final class ClientRegistration implements Serializable { * A builder for {@link ClientRegistration}. */ public static class Builder implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private String registrationId; + private String clientId; + private String clientSecret; + private ClientAuthenticationMethod clientAuthenticationMethod; + private AuthorizationGrantType authorizationGrantType; + private String redirectUri; + private Set scopes; + private String authorizationUri; + private String tokenUri; + private String userInfoUri; + private AuthenticationMethod userInfoAuthenticationMethod = AuthenticationMethod.HEADER; + private String userNameAttributeName; + private String jwkSetUri; + private String issuerUri; + private Map configurationMetadata = Collections.emptyMap(); + private String clientName; private Builder(String registrationId) { @@ -362,7 +390,6 @@ public final class ClientRegistration implements Serializable { /** * Sets the registration id. - * * @param registrationId the registration id * @return the {@link Builder} */ @@ -373,7 +400,6 @@ public final class ClientRegistration implements Serializable { /** * Sets the client identifier. - * * @param clientId the client identifier * @return the {@link Builder} */ @@ -384,7 +410,6 @@ public final class ClientRegistration implements Serializable { /** * Sets the client secret. - * * @param clientSecret the client secret * @return the {@link Builder} */ @@ -394,9 +419,8 @@ public final class ClientRegistration implements Serializable { } /** - * Sets the {@link ClientAuthenticationMethod authentication method} used - * when authenticating the client with the authorization server. - * + * Sets the {@link ClientAuthenticationMethod authentication method} used when + * authenticating the client with the authorization server. * @param clientAuthenticationMethod the authentication method used for the client * @return the {@link Builder} */ @@ -406,8 +430,8 @@ public final class ClientRegistration implements Serializable { } /** - * Sets the {@link AuthorizationGrantType authorization grant type} used for the client. - * + * Sets the {@link AuthorizationGrantType authorization grant type} used for the + * client. * @param authorizationGrantType the authorization grant type used for the client * @return the {@link Builder} */ @@ -418,9 +442,9 @@ public final class ClientRegistration implements Serializable { /** * Sets the uri (or uri template) for the redirection endpoint. - * * @deprecated Use {@link #redirectUri(String)} instead - * @param redirectUriTemplate the uri (or uri template) for the redirection endpoint + * @param redirectUriTemplate the uri (or uri template) for the redirection + * endpoint * @return the {@link Builder} */ @Deprecated @@ -432,14 +456,17 @@ public final class ClientRegistration implements Serializable { * Sets the uri (or uri template) for the redirection endpoint. * *
        - * The supported uri template variables are: {baseScheme}, {baseHost}, {basePort}, {basePath} and {registrationId}. + * The supported uri template variables are: {baseScheme}, {baseHost}, {basePort}, + * {basePath} and {registrationId}. * *
        - * NOTE: {baseUrl} is also supported, which is the same as {baseScheme}://{baseHost}{basePort}{basePath}. + * NOTE: {baseUrl} is also supported, which is the same as + * {baseScheme}://{baseHost}{basePort}{basePath}. * *
        - * Configuring uri template variables is especially useful when the client is running behind a Proxy Server. - * This ensures that the X-Forwarded-* headers are used when expanding the redirect-uri. + * Configuring uri template variables is especially useful when the client is + * running behind a Proxy Server. This ensures that the X-Forwarded-* headers are + * used when expanding the redirect-uri. * * @since 5.4 * @param redirectUri the uri (or uri template) for the redirection endpoint @@ -452,35 +479,30 @@ public final class ClientRegistration implements Serializable { /** * Sets the scope(s) used for the client. - * * @param scope the scope(s) used for the client * @return the {@link Builder} */ public Builder scope(String... scope) { if (scope != null && scope.length > 0) { - this.scopes = Collections.unmodifiableSet( - new LinkedHashSet<>(Arrays.asList(scope))); + this.scopes = Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(scope))); } return this; } /** * Sets the scope(s) used for the client. - * * @param scope the scope(s) used for the client * @return the {@link Builder} */ public Builder scope(Collection scope) { if (scope != null && !scope.isEmpty()) { - this.scopes = Collections.unmodifiableSet( - new LinkedHashSet<>(scope)); + this.scopes = Collections.unmodifiableSet(new LinkedHashSet<>(scope)); } return this; } /** * Sets the uri for the authorization endpoint. - * * @param authorizationUri the uri for the authorization endpoint * @return the {@link Builder} */ @@ -491,7 +513,6 @@ public final class ClientRegistration implements Serializable { /** * Sets the uri for the token endpoint. - * * @param tokenUri the uri for the token endpoint * @return the {@link Builder} */ @@ -502,7 +523,6 @@ public final class ClientRegistration implements Serializable { /** * Sets the uri for the user info endpoint. - * * @param userInfoUri the uri for the user info endpoint * @return the {@link Builder} */ @@ -515,7 +535,8 @@ public final class ClientRegistration implements Serializable { * Sets the authentication method for the user info endpoint. * * @since 5.1 - * @param userInfoAuthenticationMethod the authentication method for the user info endpoint + * @param userInfoAuthenticationMethod the authentication method for the user info + * endpoint * @return the {@link Builder} */ public Builder userInfoAuthenticationMethod(AuthenticationMethod userInfoAuthenticationMethod) { @@ -524,9 +545,10 @@ public final class ClientRegistration implements Serializable { } /** - * Sets the attribute name used to access the user's name from the user info response. - * - * @param userNameAttributeName the attribute name used to access the user's name from the user info response + * Sets the attribute name used to access the user's name from the user info + * response. + * @param userNameAttributeName the attribute name used to access the user's name + * from the user info response * @return the {@link Builder} */ public Builder userNameAttributeName(String userNameAttributeName) { @@ -536,7 +558,6 @@ public final class ClientRegistration implements Serializable { /** * Sets the uri for the JSON Web Key (JWK) Set endpoint. - * * @param jwkSetUri the uri for the JSON Web Key (JWK) Set endpoint * @return the {@link Builder} */ @@ -546,11 +567,12 @@ public final class ClientRegistration implements Serializable { } /** - * Sets the issuer identifier uri for the OpenID Connect 1.0 provider - * or the OAuth 2.0 Authorization Server. + * Sets the issuer identifier uri for the OpenID Connect 1.0 provider or the OAuth + * 2.0 Authorization Server. * * @since 5.4 - * @param issuerUri the issuer identifier uri for the OpenID Connect 1.0 provider or the OAuth 2.0 Authorization Server + * @param issuerUri the issuer identifier uri for the OpenID Connect 1.0 provider + * or the OAuth 2.0 Authorization Server * @return the {@link Builder} */ public Builder issuerUri(String issuerUri) { @@ -562,7 +584,8 @@ public final class ClientRegistration implements Serializable { * Sets the metadata describing the provider's configuration. * * @since 5.1 - * @param configurationMetadata the metadata describing the provider's configuration + * @param configurationMetadata the metadata describing the provider's + * configuration * @return the {@link Builder} */ public Builder providerConfigurationMetadata(Map configurationMetadata) { @@ -574,7 +597,6 @@ public final class ClientRegistration implements Serializable { /** * Sets the logical name of the client or registration. - * * @param clientName the client or registration name * @return the {@link Builder} */ @@ -585,18 +607,20 @@ public final class ClientRegistration implements Serializable { /** * Builds a new {@link ClientRegistration}. - * * @return a {@link ClientRegistration} */ public ClientRegistration build() { Assert.notNull(this.authorizationGrantType, "authorizationGrantType cannot be null"); if (AuthorizationGrantType.CLIENT_CREDENTIALS.equals(this.authorizationGrantType)) { this.validateClientCredentialsGrantType(); - } else if (AuthorizationGrantType.PASSWORD.equals(this.authorizationGrantType)) { + } + else if (AuthorizationGrantType.PASSWORD.equals(this.authorizationGrantType)) { this.validatePasswordGrantType(); - } else if (AuthorizationGrantType.IMPLICIT.equals(this.authorizationGrantType)) { + } + else if (AuthorizationGrantType.IMPLICIT.equals(this.authorizationGrantType)) { this.validateImplicitGrantType(); - } else if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(this.authorizationGrantType)) { + } + else if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(this.authorizationGrantType)) { this.validateAuthorizationCodeGrantType(); } this.validateScopes(); @@ -611,11 +635,13 @@ public final class ClientRegistration implements Serializable { clientRegistration.clientSecret = StringUtils.hasText(this.clientSecret) ? this.clientSecret : ""; if (this.clientAuthenticationMethod != null) { clientRegistration.clientAuthenticationMethod = this.clientAuthenticationMethod; - } else { - if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(this.authorizationGrantType) && - !StringUtils.hasText(this.clientSecret)) { + } + else { + if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(this.authorizationGrantType) + && !StringUtils.hasText(this.clientSecret)) { clientRegistration.clientAuthenticationMethod = ClientAuthenticationMethod.NONE; - } else { + } + else { clientRegistration.clientAuthenticationMethod = ClientAuthenticationMethod.BASIC; } } @@ -634,8 +660,8 @@ public final class ClientRegistration implements Serializable { providerDetails.configurationMetadata = Collections.unmodifiableMap(this.configurationMetadata); clientRegistration.providerDetails = providerDetails; - clientRegistration.clientName = StringUtils.hasText(this.clientName) ? - this.clientName : this.registrationId; + clientRegistration.clientName = StringUtils.hasText(this.clientName) ? this.clientName + : this.registrationId; return clientRegistration; } @@ -686,15 +712,14 @@ public final class ClientRegistration implements Serializable { } private static boolean validateScope(String scope) { - return scope == null || - scope.chars().allMatch(c -> - withinTheRangeOf(c, 0x21, 0x21) || - withinTheRangeOf(c, 0x23, 0x5B) || - withinTheRangeOf(c, 0x5D, 0x7E)); + return scope == null || scope.chars().allMatch(c -> withinTheRangeOf(c, 0x21, 0x21) + || withinTheRangeOf(c, 0x23, 0x5B) || withinTheRangeOf(c, 0x5D, 0x7E)); } private static boolean withinTheRangeOf(int c, int min, int max) { return c >= min && c <= max; } + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrationRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrationRepository.java index 10d27ec1ef..95df03b20c 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrationRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrationRepository.java @@ -19,11 +19,10 @@ package org.springframework.security.oauth2.client.registration; * A repository for OAuth 2.0 / OpenID Connect 1.0 {@link ClientRegistration}(s). * *

        - * NOTE: Client registration information is ultimately stored and owned - * by the associated Authorization Server. - * Therefore, this repository provides the capability to store a sub-set copy - * of the primary client registration information - * externally from the Authorization Server. + * NOTE: Client registration information is ultimately stored and owned by the + * associated Authorization Server. Therefore, this repository provides the capability to + * store a sub-set copy of the primary client registration information externally + * from the Authorization Server. * * @author Joe Grandja * @since 5.0 @@ -32,8 +31,8 @@ package org.springframework.security.oauth2.client.registration; public interface ClientRegistrationRepository { /** - * Returns the client registration identified by the provided {@code registrationId}, or {@code null} if not found. - * + * Returns the client registration identified by the provided {@code registrationId}, + * or {@code null} if not found. * @param registrationId the registration identifier * @return the {@link ClientRegistration} if found, otherwise {@code null} */ diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrations.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrations.java index b8be1d4d42..aa68f450c1 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrations.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrations.java @@ -42,10 +42,11 @@ import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; /** - * Allows creating a {@link ClientRegistration.Builder} from an - * OpenID Provider Configuration - * or Authorization Server Metadata based on - * provided issuer. + * Allows creating a {@link ClientRegistration.Builder} from an OpenID + * Provider Configuration or + * Authorization Server + * Metadata based on provided issuer. * * @author Rob Winch * @author Josh Cummings @@ -53,24 +54,31 @@ import org.springframework.web.util.UriComponentsBuilder; * @since 5.1 */ public final class ClientRegistrations { + private static final String OIDC_METADATA_PATH = "/.well-known/openid-configuration"; + private static final String OAUTH_METADATA_PATH = "/.well-known/oauth-authorization-server"; + private static final RestTemplate rest = new RestTemplate(); - private static final ParameterizedTypeReference> typeReference = - new ParameterizedTypeReference>() {}; + + private static final ParameterizedTypeReference> typeReference = new ParameterizedTypeReference>() { + }; /** - * Creates a {@link ClientRegistration.Builder} using the provided - * Issuer by making an - * OpenID Provider - * Configuration Request and using the values in the - * OpenID - * Provider Configuration Response to initialize the {@link ClientRegistration.Builder}. + * Creates a {@link ClientRegistration.Builder} using the provided Issuer + * by making an OpenID + * Provider Configuration Request and using the values in the OpenID + * Provider Configuration Response to initialize the + * {@link ClientRegistration.Builder}. * *

        - * For example, if the issuer provided is "https://example.com", then an "OpenID Provider Configuration Request" will - * be made to "https://example.com/.well-known/openid-configuration". The result is expected to be an "OpenID - * Provider Configuration Response". + * For example, if the issuer provided is "https://example.com", then an "OpenID + * Provider Configuration Request" will be made to + * "https://example.com/.well-known/openid-configuration". The result is expected to + * be an "OpenID Provider Configuration Response". *

        * *

        @@ -82,8 +90,10 @@ public final class ClientRegistrations { * .clientSecret("client-secret") * .build(); * - * @param issuer the Issuer - * @return a {@link ClientRegistration.Builder} that was initialized by the OpenID Provider Configuration. + * @param issuer the Issuer + * @return a {@link ClientRegistration.Builder} that was initialized by the OpenID + * Provider Configuration. */ public static ClientRegistration.Builder fromOidcIssuerLocation(String issuer) { Assert.hasText(issuer, "issuer cannot be empty"); @@ -91,29 +101,25 @@ public final class ClientRegistrations { } /** - * Creates a {@link ClientRegistration.Builder} using the provided - * Issuer by querying - * three different discovery endpoints serially, using the values in the first successful response to - * initialize. If an endpoint returns anything other than a 200 or a 4xx, the method will exit without - * attempting subsequent endpoints. + * Creates a {@link ClientRegistration.Builder} using the provided Issuer + * by querying three different discovery endpoints serially, using the values in the + * first successful response to initialize. If an endpoint returns anything other than + * a 200 or a 4xx, the method will exit without attempting subsequent endpoints. * - * The three endpoints are computed as follows, given that the {@code issuer} is composed of a {@code host} - * and a {@code path}: + * The three endpoints are computed as follows, given that the {@code issuer} is + * composed of a {@code host} and a {@code path}: * *

          - *
        1. - * {@code host/.well-known/openid-configuration/path}, as defined in - * RFC 8414's Compatibility Notes. - *
        2. - *
        3. - * {@code issuer/.well-known/openid-configuration}, as defined in - * - * OpenID Provider Configuration. - *
        4. - *
        5. - * {@code host/.well-known/oauth-authorization-server/path}, as defined in - * Authorization Server Metadata Request. - *
        6. + *
        7. {@code host/.well-known/openid-configuration/path}, as defined in + * RFC 8414's Compatibility + * Notes.
        8. + *
        9. {@code issuer/.well-known/openid-configuration}, as defined in + * OpenID Provider Configuration.
        10. + *
        11. {@code host/.well-known/oauth-authorization-server/path}, as defined in + * Authorization Server + * Metadata Request.
        12. *
        * * Note that the second endpoint is the equivalent of calling @@ -128,9 +134,9 @@ public final class ClientRegistrations { * .clientSecret("client-secret") * .build(); * - * * @param issuer - * @return a {@link ClientRegistration.Builder} that was initialized by one of the described endpoints + * @return a {@link ClientRegistration.Builder} that was initialized by one of the + * described endpoints */ public static ClientRegistration.Builder fromIssuerLocation(String issuer) { Assert.hasText(issuer, "issuer cannot be empty"); @@ -139,8 +145,8 @@ public final class ClientRegistrations { } private static Supplier oidc(URI issuer) { - URI uri = UriComponentsBuilder.fromUri(issuer) - .replacePath(issuer.getPath() + OIDC_METADATA_PATH).build(Collections.emptyMap()); + URI uri = UriComponentsBuilder.fromUri(issuer).replacePath(issuer.getPath() + OIDC_METADATA_PATH) + .build(Collections.emptyMap()); return () -> { RequestEntity request = RequestEntity.get(uri).build(); @@ -156,14 +162,14 @@ public final class ClientRegistrations { } private static Supplier oidcRfc8414(URI issuer) { - URI uri = UriComponentsBuilder.fromUri(issuer) - .replacePath(OIDC_METADATA_PATH + issuer.getPath()).build(Collections.emptyMap()); + URI uri = UriComponentsBuilder.fromUri(issuer).replacePath(OIDC_METADATA_PATH + issuer.getPath()) + .build(Collections.emptyMap()); return getRfc8414Builder(issuer, uri); } private static Supplier oauth(URI issuer) { - URI uri = UriComponentsBuilder.fromUri(issuer) - .replacePath(OAUTH_METADATA_PATH + issuer.getPath()).build(Collections.emptyMap()); + URI uri = UriComponentsBuilder.fromUri(issuer).replacePath(OAUTH_METADATA_PATH + issuer.getPath()) + .build(Collections.emptyMap()); return getRfc8414Builder(issuer, uri); } @@ -188,73 +194,79 @@ public final class ClientRegistrations { } @SafeVarargs - private static ClientRegistration.Builder getBuilder(String issuer, Supplier... suppliers) { + private static ClientRegistration.Builder getBuilder(String issuer, + Supplier... suppliers) { String errorMessage = "Unable to resolve Configuration with the provided Issuer of \"" + issuer + "\""; for (Supplier supplier : suppliers) { try { return supplier.get(); - } catch (HttpClientErrorException e) { + } + catch (HttpClientErrorException e) { if (!e.getStatusCode().is4xxClientError()) { throw e; } // else try another endpoint - } catch (IllegalArgumentException | IllegalStateException e) { + } + catch (IllegalArgumentException | IllegalStateException e) { throw e; - } catch (RuntimeException e) { + } + catch (RuntimeException e) { throw new IllegalArgumentException(errorMessage, e); } } throw new IllegalArgumentException(errorMessage); } - private static T parse(Map body, - ThrowingFunction parser) { + private static T parse(Map body, ThrowingFunction parser) { try { return parser.apply(new JSONObject(body)); - } catch (ParseException e) { + } + catch (ParseException e) { throw new RuntimeException(e); } } private interface ThrowingFunction { + T apply(S src) throws E; + } - private static ClientRegistration.Builder withProviderConfiguration(AuthorizationServerMetadata metadata, String issuer) { + private static ClientRegistration.Builder withProviderConfiguration(AuthorizationServerMetadata metadata, + String issuer) { String metadataIssuer = metadata.getIssuer().getValue(); if (!issuer.equals(metadataIssuer)) { - throw new IllegalStateException("The Issuer \"" + metadataIssuer + "\" provided in the configuration metadata did " - + "not match the requested issuer \"" + issuer + "\""); + throw new IllegalStateException( + "The Issuer \"" + metadataIssuer + "\" provided in the configuration metadata did " + + "not match the requested issuer \"" + issuer + "\""); } String name = URI.create(issuer).getHost(); - ClientAuthenticationMethod method = getClientAuthenticationMethod(issuer, metadata.getTokenEndpointAuthMethods()); + ClientAuthenticationMethod method = getClientAuthenticationMethod(issuer, + metadata.getTokenEndpointAuthMethods()); List grantTypes = metadata.getGrantTypes(); // If null, the default includes authorization_code if (grantTypes != null && !grantTypes.contains(GrantType.AUTHORIZATION_CODE)) { - throw new IllegalArgumentException("Only AuthorizationGrantType.AUTHORIZATION_CODE is supported. The issuer \"" + issuer + - "\" returned a configuration of " + grantTypes); + throw new IllegalArgumentException( + "Only AuthorizationGrantType.AUTHORIZATION_CODE is supported. The issuer \"" + issuer + + "\" returned a configuration of " + grantTypes); } List scopes = getScopes(metadata); Map configurationMetadata = new LinkedHashMap<>(metadata.toJSONObject()); - return ClientRegistration.withRegistrationId(name) - .userNameAttributeName(IdTokenClaimNames.SUB) - .scope(scopes) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .clientAuthenticationMethod(method) + return ClientRegistration.withRegistrationId(name).userNameAttributeName(IdTokenClaimNames.SUB).scope(scopes) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).clientAuthenticationMethod(method) .redirectUri("{baseUrl}/{action}/oauth2/code/{registrationId}") .authorizationUri(metadata.getAuthorizationEndpointURI().toASCIIString()) .providerConfigurationMetadata(configurationMetadata) - .tokenUri(metadata.getTokenEndpointURI().toASCIIString()) - .issuerUri(issuer) - .clientName(issuer); + .tokenUri(metadata.getTokenEndpointURI().toASCIIString()).issuerUri(issuer).clientName(issuer); } private static ClientAuthenticationMethod getClientAuthenticationMethod(String issuer, List metadataAuthMethods) { - if (metadataAuthMethods == null || metadataAuthMethods.contains(com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod.CLIENT_SECRET_BASIC)) { + if (metadataAuthMethods == null || metadataAuthMethods + .contains(com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod.CLIENT_SECRET_BASIC)) { // If null, the default includes client_secret_basic return ClientAuthenticationMethod.BASIC; } @@ -265,7 +277,8 @@ public final class ClientRegistrations { return ClientAuthenticationMethod.NONE; } throw new IllegalArgumentException("Only ClientAuthenticationMethod.BASIC, ClientAuthenticationMethod.POST and " - + "ClientAuthenticationMethod.NONE are supported. The issuer \"" + issuer + "\" returned a configuration of " + metadataAuthMethods); + + "ClientAuthenticationMethod.NONE are supported. The issuer \"" + issuer + + "\" returned a configuration of " + metadataAuthMethods); } private static List getScopes(AuthorizationServerMetadata metadata) { @@ -273,11 +286,13 @@ public final class ClientRegistrations { if (scope == null) { // If null, default to "openid" which must be supported return Collections.singletonList(OidcScopes.OPENID); - } else { + } + else { return scope.toStringList(); } } - private ClientRegistrations() {} + private ClientRegistrations() { + } } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/InMemoryClientRegistrationRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/InMemoryClientRegistrationRepository.java index 7378d5fe4f..ca81eeee9b 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/InMemoryClientRegistrationRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/InMemoryClientRegistrationRepository.java @@ -25,7 +25,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** - * A {@link ClientRegistrationRepository} that stores {@link ClientRegistration}(s) in-memory. + * A {@link ClientRegistrationRepository} that stores {@link ClientRegistration}(s) + * in-memory. * * @author Joe Grandja * @author Rob Winch @@ -34,12 +35,14 @@ import java.util.concurrent.ConcurrentHashMap; * @see ClientRegistrationRepository * @see ClientRegistration */ -public final class InMemoryClientRegistrationRepository implements ClientRegistrationRepository, Iterable { +public final class InMemoryClientRegistrationRepository + implements ClientRegistrationRepository, Iterable { + private final Map registrations; /** - * Constructs an {@code InMemoryClientRegistrationRepository} using the provided parameters. - * + * Constructs an {@code InMemoryClientRegistrationRepository} using the provided + * parameters. * @param registrations the client registration(s) */ public InMemoryClientRegistrationRepository(ClientRegistration... registrations) { @@ -47,8 +50,8 @@ public final class InMemoryClientRegistrationRepository implements ClientRegistr } /** - * Constructs an {@code InMemoryClientRegistrationRepository} using the provided parameters. - * + * Constructs an {@code InMemoryClientRegistrationRepository} using the provided + * parameters. * @param registrations the client registration(s) */ public InMemoryClientRegistrationRepository(List registrations) { @@ -64,8 +67,7 @@ public final class InMemoryClientRegistrationRepository implements ClientRegistr ConcurrentHashMap result = new ConcurrentHashMap<>(); for (ClientRegistration registration : registrations) { if (result.containsKey(registration.getRegistrationId())) { - throw new IllegalStateException(String.format("Duplicate key %s", - registration.getRegistrationId())); + throw new IllegalStateException(String.format("Duplicate key %s", registration.getRegistrationId())); } result.put(registration.getRegistrationId(), registration); } @@ -73,8 +75,9 @@ public final class InMemoryClientRegistrationRepository implements ClientRegistr } /** - * Constructs an {@code InMemoryClientRegistrationRepository} using the provided {@code Map} - * of {@link ClientRegistration#getRegistrationId() registration id} to {@link ClientRegistration}. + * Constructs an {@code InMemoryClientRegistrationRepository} using the provided + * {@code Map} of {@link ClientRegistration#getRegistrationId() registration id} to + * {@link ClientRegistration}. * * @since 5.2 * @param registrations the {@code Map} of client registration(s) @@ -92,11 +95,11 @@ public final class InMemoryClientRegistrationRepository implements ClientRegistr /** * Returns an {@code Iterator} of {@link ClientRegistration}. - * * @return an {@code Iterator} */ @Override public Iterator iterator() { return this.registrations.values().iterator(); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/InMemoryReactiveClientRegistrationRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/InMemoryReactiveClientRegistrationRepository.java index 98ba597c41..43a0d8c408 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/InMemoryReactiveClientRegistrationRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/InMemoryReactiveClientRegistrationRepository.java @@ -27,7 +27,8 @@ import reactor.core.publisher.Mono; import org.springframework.util.Assert; /** - * A Reactive {@link ClientRegistrationRepository} that stores {@link ClientRegistration}(s) in-memory. + * A Reactive {@link ClientRegistrationRepository} that stores + * {@link ClientRegistration}(s) in-memory. * * @author Rob Winch * @author Ebert Toribio @@ -41,8 +42,8 @@ public final class InMemoryReactiveClientRegistrationRepository private final Map clientIdToClientRegistration; /** - * Constructs an {@code InMemoryReactiveClientRegistrationRepository} using the provided parameters. - * + * Constructs an {@code InMemoryReactiveClientRegistrationRepository} using the + * provided parameters. * @param registrations the client registration(s) */ public InMemoryReactiveClientRegistrationRepository(ClientRegistration... registrations) { @@ -55,8 +56,8 @@ public final class InMemoryReactiveClientRegistrationRepository } /** - * Constructs an {@code InMemoryReactiveClientRegistrationRepository} using the provided parameters. - * + * Constructs an {@code InMemoryReactiveClientRegistrationRepository} using the + * provided parameters. * @param registrations the client registration(s) */ public InMemoryReactiveClientRegistrationRepository(List registrations) { @@ -70,7 +71,6 @@ public final class InMemoryReactiveClientRegistrationRepository /** * Returns an {@code Iterator} of {@link ClientRegistration}. - * * @return an {@code Iterator} */ @Override @@ -84,11 +84,11 @@ public final class InMemoryReactiveClientRegistrationRepository for (ClientRegistration registration : registrations) { Assert.notNull(registration, "no registration can be null"); if (result.containsKey(registration.getRegistrationId())) { - throw new IllegalStateException(String.format("Duplicate key %s", - registration.getRegistrationId())); + throw new IllegalStateException(String.format("Duplicate key %s", registration.getRegistrationId())); } result.put(registration.getRegistrationId(), registration); } return Collections.unmodifiableMap(result); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ReactiveClientRegistrationRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ReactiveClientRegistrationRepository.java index 731e414141..3d9c82aaf4 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ReactiveClientRegistrationRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ReactiveClientRegistrationRepository.java @@ -22,11 +22,10 @@ import reactor.core.publisher.Mono; * A reactive repository for OAuth 2.0 / OpenID Connect 1.0 {@link ClientRegistration}(s). * *

        - * NOTE: Client registration information is ultimately stored and owned - * by the associated Authorization Server. - * Therefore, this repository provides the capability to store a sub-set copy - * of the primary client registration information - * externally from the Authorization Server. + * NOTE: Client registration information is ultimately stored and owned by the + * associated Authorization Server. Therefore, this repository provides the capability to + * store a sub-set copy of the primary client registration information externally + * from the Authorization Server. * * @author Rob Winch * @since 5.1 @@ -35,8 +34,8 @@ import reactor.core.publisher.Mono; public interface ReactiveClientRegistrationRepository { /** - * Returns the client registration identified by the provided {@code registrationId}, or {@code null} if not found. - * + * Returns the client registration identified by the provided {@code registrationId}, + * or {@code null} if not found. * @param registrationId the registration identifier * @return the {@link ClientRegistration} if found, otherwise {@code null} */ diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/package-info.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/package-info.java index 9f133f1165..437fb51e69 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/package-info.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/package-info.java @@ -14,6 +14,7 @@ * limitations under the License. */ /** - * Classes and interfaces that provide support for {@link org.springframework.security.oauth2.client.registration.ClientRegistration}. + * Classes and interfaces that provide support for + * {@link org.springframework.security.oauth2.client.registration.ClientRegistration}. */ package org.springframework.security.oauth2.client.registration; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/CustomUserTypesOAuth2UserService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/CustomUserTypesOAuth2UserService.java index df77620f91..d50ea1e56c 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/CustomUserTypesOAuth2UserService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/CustomUserTypesOAuth2UserService.java @@ -34,16 +34,19 @@ import java.util.LinkedHashMap; import java.util.Map; /** - * An implementation of an {@link OAuth2UserService} that supports custom {@link OAuth2User} types. + * An implementation of an {@link OAuth2UserService} that supports custom + * {@link OAuth2User} types. *

        - * The custom user type(s) is supplied via the constructor, - * using a {@code Map} of {@link OAuth2User} type(s) keyed by {@code String}, - * which represents the {@link ClientRegistration#getRegistrationId() Registration Id} of the Client. - * - * @deprecated It is recommended to use a delegation-based strategy of an {@link OAuth2UserService} to support custom {@link OAuth2User} types, - * as it provides much greater flexibility compared to this implementation. - * See the reference manual for details on how to implement. + * The custom user type(s) is supplied via the constructor, using a {@code Map} of + * {@link OAuth2User} type(s) keyed by {@code String}, which represents the + * {@link ClientRegistration#getRegistrationId() Registration Id} of the Client. * + * @deprecated It is recommended to use a delegation-based strategy of an + * {@link OAuth2UserService} to support custom {@link OAuth2User} types, as it provides + * much greater flexibility compared to this implementation. See the + * reference + * manual for details on how to implement. * @author Joe Grandja * @since 5.0 * @see OAuth2UserService @@ -53,6 +56,7 @@ import java.util.Map; */ @Deprecated public class CustomUserTypesOAuth2UserService implements OAuth2UserService { + private static final String INVALID_USER_INFO_RESPONSE_ERROR_CODE = "invalid_user_info_response"; private final Map> customUserTypes; @@ -62,9 +66,10 @@ public class CustomUserTypesOAuth2UserService implements OAuth2UserService> customUserTypes) { Assert.notEmpty(customUserTypes, "customUserTypes cannot be empty"); @@ -88,7 +93,8 @@ public class CustomUserTypesOAuth2UserService implements OAuth2UserService response; try { response = this.restOperations.exchange(request, customUserType); - } catch (RestClientException ex) { + } + catch (RestClientException ex) { OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE, "An error occurred while attempting to retrieve the UserInfo Resource: " + ex.getMessage(), null); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), ex); @@ -100,11 +106,12 @@ public class CustomUserTypesOAuth2UserService implements OAuth2UserService> requestEntityConverter) { Assert.notNull(requestEntityConverter, "requestEntityConverter cannot be null"); @@ -115,16 +122,19 @@ public class CustomUserTypesOAuth2UserService implements OAuth2UserService - * NOTE: At a minimum, the supplied {@code restOperations} must be configured with the following: + * NOTE: At a minimum, the supplied {@code restOperations} must be configured + * with the following: *

          - *
        1. {@link ResponseErrorHandler} - {@link OAuth2ErrorResponseErrorHandler}
        2. + *
        3. {@link ResponseErrorHandler} - {@link OAuth2ErrorResponseErrorHandler}
        4. *
        * * @since 5.1 - * @param restOperations the {@link RestOperations} used when requesting the UserInfo resource + * @param restOperations the {@link RestOperations} used when requesting the UserInfo + * resource */ public final void setRestOperations(RestOperations restOperations) { Assert.notNull(restOperations, "restOperations cannot be null"); this.restOperations = restOperations; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserService.java index b3d00a077c..98bd846240 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserService.java @@ -43,14 +43,17 @@ import org.springframework.web.client.RestTemplate; import org.springframework.web.client.UnknownContentTypeException; /** - * An implementation of an {@link OAuth2UserService} that supports standard OAuth 2.0 Provider's. + * An implementation of an {@link OAuth2UserService} that supports standard OAuth 2.0 + * Provider's. *

        * For standard OAuth 2.0 Provider's, the attribute name used to access the user's name * from the UserInfo response is required and therefore must be available via - * {@link ClientRegistration.ProviderDetails.UserInfoEndpoint#getUserNameAttributeName() UserInfoEndpoint.getUserNameAttributeName()}. + * {@link ClientRegistration.ProviderDetails.UserInfoEndpoint#getUserNameAttributeName() + * UserInfoEndpoint.getUserNameAttributeName()}. *

        - * NOTE: Attribute names are not standardized between providers and therefore will vary. - * Please consult the provider's API documentation for the set of supported user attribute names. + * NOTE: Attribute names are not standardized between providers and + * therefore will vary. Please consult the provider's API documentation for the set of + * supported user attribute names. * * @author Joe Grandja * @since 5.0 @@ -60,14 +63,15 @@ import org.springframework.web.client.UnknownContentTypeException; * @see DefaultOAuth2User */ public class DefaultOAuth2UserService implements OAuth2UserService { + private static final String MISSING_USER_INFO_URI_ERROR_CODE = "missing_user_info_uri"; private static final String MISSING_USER_NAME_ATTRIBUTE_ERROR_CODE = "missing_user_name_attribute"; private static final String INVALID_USER_INFO_RESPONSE_ERROR_CODE = "invalid_user_info_response"; - private static final ParameterizedTypeReference> PARAMETERIZED_RESPONSE_TYPE = - new ParameterizedTypeReference>() {}; + private static final ParameterizedTypeReference> PARAMETERIZED_RESPONSE_TYPE = new ParameterizedTypeReference>() { + }; private Converter> requestEntityConverter = new OAuth2UserRequestEntityConverter(); @@ -83,24 +87,21 @@ public class DefaultOAuth2UserService implements OAuth2UserService> response; try { response = this.restOperations.exchange(request, PARAMETERIZED_RESPONSE_TYPE); - } catch (OAuth2AuthorizationException ex) { + } + catch (OAuth2AuthorizationException ex) { OAuth2Error oauth2Error = ex.getError(); StringBuilder errorDetails = new StringBuilder(); errorDetails.append("Error details: ["); - errorDetails.append("UserInfo Uri: ").append( - userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri()); + errorDetails.append("UserInfo Uri: ") + .append(userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri()); errorDetails.append(", Error Code: ").append(oauth2Error.getErrorCode()); if (oauth2Error.getDescription() != null) { errorDetails.append(", Error Description: ").append(oauth2Error.getDescription()); } errorDetails.append("]"); oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE, - "An error occurred while attempting to retrieve the UserInfo Resource: " + errorDetails.toString(), null); + "An error occurred while attempting to retrieve the UserInfo Resource: " + errorDetails.toString(), + null); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), ex); - } catch (UnknownContentTypeException ex) { - String errorMessage = "An error occurred while attempting to retrieve the UserInfo Resource from '" + - userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri() + - "': response contains invalid content type '" + ex.getContentType().toString() + "'. " + - "The UserInfo Response should return a JSON object (content type 'application/json') " + - "that contains a collection of name and value pairs of the claims about the authenticated End-User. " + - "Please ensure the UserInfo Uri in UserInfoEndpoint for Client Registration '" + - userRequest.getClientRegistration().getRegistrationId() + "' conforms to the UserInfo Endpoint, " + - "as defined in OpenID Connect 1.0: 'https://openid.net/specs/openid-connect-core-1_0.html#UserInfo'"; + } + catch (UnknownContentTypeException ex) { + String errorMessage = "An error occurred while attempting to retrieve the UserInfo Resource from '" + + userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri() + + "': response contains invalid content type '" + ex.getContentType().toString() + "'. " + + "The UserInfo Response should return a JSON object (content type 'application/json') " + + "that contains a collection of name and value pairs of the claims about the authenticated End-User. " + + "Please ensure the UserInfo Uri in UserInfoEndpoint for Client Registration '" + + userRequest.getClientRegistration().getRegistrationId() + "' conforms to the UserInfo Endpoint, " + + "as defined in OpenID Connect 1.0: 'https://openid.net/specs/openid-connect-core-1_0.html#UserInfo'"; OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE, errorMessage, null); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), ex); - } catch (RestClientException ex) { + } + catch (RestClientException ex) { OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE, "An error occurred while attempting to retrieve the UserInfo Resource: " + ex.getMessage(), null); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), ex); @@ -152,11 +157,12 @@ public class DefaultOAuth2UserService implements OAuth2UserService> requestEntityConverter) { Assert.notNull(requestEntityConverter, "requestEntityConverter cannot be null"); @@ -167,16 +173,19 @@ public class DefaultOAuth2UserService implements OAuth2UserService - * NOTE: At a minimum, the supplied {@code restOperations} must be configured with the following: + * NOTE: At a minimum, the supplied {@code restOperations} must be configured + * with the following: *

          - *
        1. {@link ResponseErrorHandler} - {@link OAuth2ErrorResponseErrorHandler}
        2. + *
        3. {@link ResponseErrorHandler} - {@link OAuth2ErrorResponseErrorHandler}
        4. *
        * * @since 5.1 - * @param restOperations the {@link RestOperations} used when requesting the UserInfo resource + * @param restOperations the {@link RestOperations} used when requesting the UserInfo + * resource */ public final void setRestOperations(RestOperations restOperations) { Assert.notNull(restOperations, "restOperations cannot be null"); this.restOperations = restOperations; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultReactiveOAuth2UserService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultReactiveOAuth2UserService.java index 8e547be7f9..e654eb571d 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultReactiveOAuth2UserService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultReactiveOAuth2UserService.java @@ -16,7 +16,6 @@ package org.springframework.security.oauth2.client.userinfo; - import java.io.IOException; import java.util.HashSet; import java.util.Map; @@ -49,14 +48,17 @@ import net.minidev.json.JSONObject; import reactor.core.publisher.Mono; /** - * An implementation of an {@link ReactiveOAuth2UserService} that supports standard OAuth 2.0 Provider's. + * An implementation of an {@link ReactiveOAuth2UserService} that supports standard OAuth + * 2.0 Provider's. *

        * For standard OAuth 2.0 Provider's, the attribute name used to access the user's name * from the UserInfo response is required and therefore must be available via - * {@link org.springframework.security.oauth2.client.registration.ClientRegistration.ProviderDetails.UserInfoEndpoint#getUserNameAttributeName() UserInfoEndpoint.getUserNameAttributeName()}. + * {@link org.springframework.security.oauth2.client.registration.ClientRegistration.ProviderDetails.UserInfoEndpoint#getUserNameAttributeName() + * UserInfoEndpoint.getUserNameAttributeName()}. *

        - * NOTE: Attribute names are not standardized between providers and therefore will vary. - * Please consult the provider's API documentation for the set of supported user attribute names. + * NOTE: Attribute names are not standardized between providers and + * therefore will vary. Please consult the provider's API documentation for the set of + * supported user attribute names. * * @author Rob Winch * @since 5.1 @@ -66,34 +68,33 @@ import reactor.core.publisher.Mono; * @see DefaultOAuth2User */ public class DefaultReactiveOAuth2UserService implements ReactiveOAuth2UserService { + private static final String INVALID_USER_INFO_RESPONSE_ERROR_CODE = "invalid_user_info_response"; + private static final String MISSING_USER_INFO_URI_ERROR_CODE = "missing_user_info_uri"; + private static final String MISSING_USER_NAME_ATTRIBUTE_ERROR_CODE = "missing_user_name_attribute"; private WebClient webClient = WebClient.create(); @Override - public Mono loadUser(OAuth2UserRequest userRequest) - throws OAuth2AuthenticationException { + public Mono loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { return Mono.defer(() -> { Assert.notNull(userRequest, "userRequest cannot be null"); - String userInfoUri = userRequest.getClientRegistration().getProviderDetails() - .getUserInfoEndpoint().getUri(); - if (!StringUtils.hasText( - userInfoUri)) { - OAuth2Error oauth2Error = new OAuth2Error( - MISSING_USER_INFO_URI_ERROR_CODE, + String userInfoUri = userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint() + .getUri(); + if (!StringUtils.hasText(userInfoUri)) { + OAuth2Error oauth2Error = new OAuth2Error(MISSING_USER_INFO_URI_ERROR_CODE, "Missing required UserInfo Uri in UserInfoEndpoint for Client Registration: " + userRequest.getClientRegistration().getRegistrationId(), null); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } - String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint() - .getUserNameAttributeName(); + String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails() + .getUserInfoEndpoint().getUserNameAttributeName(); if (!StringUtils.hasText(userNameAttributeName)) { - OAuth2Error oauth2Error = new OAuth2Error( - MISSING_USER_NAME_ATTRIBUTE_ERROR_CODE, + OAuth2Error oauth2Error = new OAuth2Error(MISSING_USER_NAME_ATTRIBUTE_ERROR_CODE, "Missing required \"user name\" attribute name in UserInfoEndpoint for Client Registration: " + userRequest.getClientRegistration().getRegistrationId(), null); @@ -107,28 +108,23 @@ public class DefaultReactiveOAuth2UserService implements ReactiveOAuth2UserServi .getUserInfoEndpoint().getAuthenticationMethod(); WebClient.RequestHeadersSpec requestHeadersSpec; if (AuthenticationMethod.FORM.equals(authenticationMethod)) { - requestHeadersSpec = this.webClient.post() - .uri(userInfoUri) + requestHeadersSpec = this.webClient.post().uri(userInfoUri) .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE) .syncBody("access_token=" + userRequest.getAccessToken().getTokenValue()); - } else { - requestHeadersSpec = this.webClient.get() - .uri(userInfoUri) + } + else { + requestHeadersSpec = this.webClient.get().uri(userInfoUri) .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .headers(headers -> headers.setBearerAuth(userRequest.getAccessToken().getTokenValue())); } - Mono> userAttributes = requestHeadersSpec - .retrieve() + Mono> userAttributes = requestHeadersSpec.retrieve() .onStatus(s -> s != HttpStatus.OK, response -> parse(response).map(userInfoErrorResponse -> { String description = userInfoErrorResponse.getErrorObject().getDescription(); - OAuth2Error oauth2Error = new OAuth2Error( - INVALID_USER_INFO_RESPONSE_ERROR_CODE, description, + OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE, description, null); - throw new OAuth2AuthenticationException(oauth2Error, - oauth2Error.toString()); - })) - .bodyToMono(typeReference); + throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); + })).bodyToMono(typeReference); return userAttributes.map(attrs -> { GrantedAuthority authority = new OAuth2UserAuthority(attrs); @@ -140,24 +136,27 @@ public class DefaultReactiveOAuth2UserService implements ReactiveOAuth2UserServi } return new DefaultOAuth2User(authorities, attrs, userNameAttributeName); - }) - .onErrorMap(IOException.class, e -> new AuthenticationServiceException("Unable to access the userInfoEndpoint " + userInfoUri, e)) - .onErrorMap(UnsupportedMediaTypeException.class, e -> { - String errorMessage = "An error occurred while attempting to retrieve the UserInfo Resource from '" + - userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri() + - "': response contains invalid content type '" + e.getContentType().toString() + "'. " + - "The UserInfo Response should return a JSON object (content type 'application/json') " + - "that contains a collection of name and value pairs of the claims about the authenticated End-User. " + - "Please ensure the UserInfo Uri in UserInfoEndpoint for Client Registration '" + - userRequest.getClientRegistration().getRegistrationId() + "' conforms to the UserInfo Endpoint, " + - "as defined in OpenID Connect 1.0: 'https://openid.net/specs/openid-connect-core-1_0.html#UserInfo'"; - OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE, errorMessage, null); - throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), e); - }) - .onErrorMap(t -> !(t instanceof AuthenticationServiceException), t -> { - OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE, "An error occurred reading the UserInfo Success response: " + t.getMessage(), null); - return new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), t); - }); + }).onErrorMap(IOException.class, + e -> new AuthenticationServiceException("Unable to access the userInfoEndpoint " + userInfoUri, e)) + .onErrorMap(UnsupportedMediaTypeException.class, e -> { + String errorMessage = "An error occurred while attempting to retrieve the UserInfo Resource from '" + + userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint() + .getUri() + + "': response contains invalid content type '" + e.getContentType().toString() + "'. " + + "The UserInfo Response should return a JSON object (content type 'application/json') " + + "that contains a collection of name and value pairs of the claims about the authenticated End-User. " + + "Please ensure the UserInfo Uri in UserInfoEndpoint for Client Registration '" + + userRequest.getClientRegistration().getRegistrationId() + + "' conforms to the UserInfo Endpoint, " + + "as defined in OpenID Connect 1.0: 'https://openid.net/specs/openid-connect-core-1_0.html#UserInfo'"; + OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE, errorMessage, + null); + throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), e); + }).onErrorMap(t -> !(t instanceof AuthenticationServiceException), t -> { + OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE, + "An error occurred reading the UserInfo Success response: " + t.getMessage(), null); + return new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), t); + }); }); } @@ -179,11 +178,11 @@ public class DefaultReactiveOAuth2UserService implements ReactiveOAuth2UserServi return Mono.fromCallable(() -> UserInfoErrorResponse.parse(wwwAuth)); } - ParameterizedTypeReference> typeReference = - new ParameterizedTypeReference>() {}; + ParameterizedTypeReference> typeReference = new ParameterizedTypeReference>() { + }; // Other error? - return httpResponse - .bodyToMono(typeReference) - .map(body -> new UserInfoErrorResponse(ErrorObject.parse(new JSONObject(body)))); + return httpResponse.bodyToMono(typeReference) + .map(body -> new UserInfoErrorResponse(ErrorObject.parse(new JSONObject(body)))); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DelegatingOAuth2UserService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DelegatingOAuth2UserService.java index a44058f2c2..3105049c01 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DelegatingOAuth2UserService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DelegatingOAuth2UserService.java @@ -25,28 +25,28 @@ import java.util.List; import java.util.Objects; /** - * An implementation of an {@link OAuth2UserService} that simply delegates - * to it's internal {@code List} of {@link OAuth2UserService}(s). + * An implementation of an {@link OAuth2UserService} that simply delegates to it's + * internal {@code List} of {@link OAuth2UserService}(s). *

        * Each {@link OAuth2UserService} is given a chance to - * {@link OAuth2UserService#loadUser(OAuth2UserRequest) load} an {@link OAuth2User} - * with the first {@code non-null} {@link OAuth2User} being returned. + * {@link OAuth2UserService#loadUser(OAuth2UserRequest) load} an {@link OAuth2User} with + * the first {@code non-null} {@link OAuth2User} being returned. * * @author Joe Grandja * @since 5.0 * @see OAuth2UserService * @see OAuth2UserRequest * @see OAuth2User - * * @param The type of OAuth 2.0 User Request * @param The type of OAuth 2.0 User */ -public class DelegatingOAuth2UserService implements OAuth2UserService { +public class DelegatingOAuth2UserService + implements OAuth2UserService { + private final List> userServices; /** * Constructs a {@code DelegatingOAuth2UserService} using the provided parameters. - * * @param userServices a {@code List} of {@link OAuth2UserService}(s) */ public DelegatingOAuth2UserService(List> userServices) { @@ -57,10 +57,8 @@ public class DelegatingOAuth2UserService userService.loadUser(userRequest)) - .filter(Objects::nonNull) - .findFirst() - .orElse(null); + return this.userServices.stream().map(userService -> userService.loadUser(userRequest)).filter(Objects::nonNull) + .findFirst().orElse(null); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequest.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequest.java index 34dc78f7b5..0b0490c9f5 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequest.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequest.java @@ -25,8 +25,8 @@ import java.util.LinkedHashMap; import java.util.Map; /** - * Represents a request the {@link OAuth2UserService} uses - * when initiating a request to the UserInfo Endpoint. + * Represents a request the {@link OAuth2UserService} uses when initiating a request to + * the UserInfo Endpoint. * * @author Joe Grandja * @since 5.0 @@ -35,13 +35,15 @@ import java.util.Map; * @see OAuth2UserService */ public class OAuth2UserRequest { + private final ClientRegistration clientRegistration; + private final OAuth2AccessToken accessToken; + private final Map additionalParameters; /** * Constructs an {@code OAuth2UserRequest} using the provided parameters. - * * @param clientRegistration the client registration * @param accessToken the access token */ @@ -58,19 +60,17 @@ public class OAuth2UserRequest { * @param additionalParameters the additional parameters, may be empty */ public OAuth2UserRequest(ClientRegistration clientRegistration, OAuth2AccessToken accessToken, - Map additionalParameters) { + Map additionalParameters) { Assert.notNull(clientRegistration, "clientRegistration cannot be null"); Assert.notNull(accessToken, "accessToken cannot be null"); this.clientRegistration = clientRegistration; this.accessToken = accessToken; - this.additionalParameters = Collections.unmodifiableMap( - CollectionUtils.isEmpty(additionalParameters) ? - Collections.emptyMap() : new LinkedHashMap<>(additionalParameters)); + this.additionalParameters = Collections.unmodifiableMap(CollectionUtils.isEmpty(additionalParameters) + ? Collections.emptyMap() : new LinkedHashMap<>(additionalParameters)); } /** * Returns the {@link ClientRegistration client registration}. - * * @return the {@link ClientRegistration} */ public ClientRegistration getClientRegistration() { @@ -79,7 +79,6 @@ public class OAuth2UserRequest { /** * Returns the {@link OAuth2AccessToken access token}. - * * @return the {@link OAuth2AccessToken} */ public OAuth2AccessToken getAccessToken() { @@ -95,4 +94,5 @@ public class OAuth2UserRequest { public Map getAdditionalParameters() { return this.additionalParameters; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequestEntityConverter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequestEntityConverter.java index f373a21012..09379adf3f 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequestEntityConverter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequestEntityConverter.java @@ -33,8 +33,8 @@ import java.util.Collections; import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE; /** - * A {@link Converter} that converts the provided {@link OAuth2UserRequest} - * to a {@link RequestEntity} representation of a request for the UserInfo Endpoint. + * A {@link Converter} that converts the provided {@link OAuth2UserRequest} to a + * {@link RequestEntity} representation of a request for the UserInfo Endpoint. * * @author Joe Grandja * @since 5.1 @@ -43,11 +43,12 @@ import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VAL * @see RequestEntity */ public class OAuth2UserRequestEntityConverter implements Converter> { - private static final MediaType DEFAULT_CONTENT_TYPE = MediaType.valueOf(APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"); + + private static final MediaType DEFAULT_CONTENT_TYPE = MediaType + .valueOf(APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"); /** * Returns the {@link RequestEntity} used for the UserInfo Request. - * * @param userRequest the user request * @return the {@link RequestEntity} used for the UserInfo Request */ @@ -56,14 +57,14 @@ public class OAuth2UserRequestEntityConverter implements Converter request; if (HttpMethod.POST.equals(httpMethod)) { @@ -71,11 +72,13 @@ public class OAuth2UserRequestEntityConverter implements Converter formParameters = new LinkedMultiValueMap<>(); formParameters.add(OAuth2ParameterNames.ACCESS_TOKEN, userRequest.getAccessToken().getTokenValue()); request = new RequestEntity<>(formParameters, headers, httpMethod, uri); - } else { + } + else { headers.setBearerAuth(userRequest.getAccessToken().getTokenValue()); request = new RequestEntity<>(headers, httpMethod, uri); } return request; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserService.java index 2aae74a0d9..1c61f31fc0 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserService.java @@ -20,18 +20,17 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.user.OAuth2User; /** - * Implementations of this interface are responsible for obtaining the user attributes - * of the End-User (Resource Owner) from the UserInfo Endpoint - * using the {@link OAuth2UserRequest#getAccessToken() Access Token} - * granted to the {@link OAuth2UserRequest#getClientRegistration() Client} - * and returning an {@link AuthenticatedPrincipal} in the form of an {@link OAuth2User}. + * Implementations of this interface are responsible for obtaining the user attributes of + * the End-User (Resource Owner) from the UserInfo Endpoint using the + * {@link OAuth2UserRequest#getAccessToken() Access Token} granted to the + * {@link OAuth2UserRequest#getClientRegistration() Client} and returning an + * {@link AuthenticatedPrincipal} in the form of an {@link OAuth2User}. * * @author Joe Grandja * @since 5.0 * @see OAuth2UserRequest * @see OAuth2User * @see AuthenticatedPrincipal - * * @param The type of OAuth 2.0 User Request * @param The type of OAuth 2.0 User */ @@ -39,11 +38,12 @@ import org.springframework.security.oauth2.core.user.OAuth2User; public interface OAuth2UserService { /** - * Returns an {@link OAuth2User} after obtaining the user attributes of the End-User from the UserInfo Endpoint. - * + * Returns an {@link OAuth2User} after obtaining the user attributes of the End-User + * from the UserInfo Endpoint. * @param userRequest the user request * @return an {@link OAuth2User} - * @throws OAuth2AuthenticationException if an error occurs while attempting to obtain the user attributes from the UserInfo Endpoint + * @throws OAuth2AuthenticationException if an error occurs while attempting to obtain + * the user attributes from the UserInfo Endpoint */ U loadUser(R userRequest) throws OAuth2AuthenticationException; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/ReactiveOAuth2UserService.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/ReactiveOAuth2UserService.java index f166c27326..be73af0f98 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/ReactiveOAuth2UserService.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/ReactiveOAuth2UserService.java @@ -21,18 +21,17 @@ import org.springframework.security.oauth2.core.user.OAuth2User; import reactor.core.publisher.Mono; /** - * Implementations of this interface are responsible for obtaining the user attributes - * of the End-User (Resource Owner) from the UserInfo Endpoint - * using the {@link OAuth2UserRequest#getAccessToken() Access Token} - * granted to the {@link OAuth2UserRequest#getClientRegistration() Client} - * and returning an {@link AuthenticatedPrincipal} in the form of an {@link OAuth2User}. + * Implementations of this interface are responsible for obtaining the user attributes of + * the End-User (Resource Owner) from the UserInfo Endpoint using the + * {@link OAuth2UserRequest#getAccessToken() Access Token} granted to the + * {@link OAuth2UserRequest#getClientRegistration() Client} and returning an + * {@link AuthenticatedPrincipal} in the form of an {@link OAuth2User}. * * @author Rob Winch * @since 5.1 * @see OAuth2UserRequest * @see OAuth2User * @see AuthenticatedPrincipal - * * @param The type of OAuth 2.0 User Request * @param The type of OAuth 2.0 User */ @@ -40,11 +39,12 @@ import reactor.core.publisher.Mono; public interface ReactiveOAuth2UserService { /** - * Returns an {@link OAuth2User} after obtaining the user attributes of the End-User from the UserInfo Endpoint. - * + * Returns an {@link OAuth2User} after obtaining the user attributes of the End-User + * from the UserInfo Endpoint. * @param userRequest the user request * @return an {@link OAuth2User} - * @throws OAuth2AuthenticationException if an error occurs while attempting to obtain the user attributes from the UserInfo Endpoint + * @throws OAuth2AuthenticationException if an error occurs while attempting to obtain + * the user attributes from the UserInfo Endpoint */ Mono loadUser(R userRequest) throws OAuth2AuthenticationException; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/package-info.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/package-info.java index 2d698369b9..c66ac1a8e7 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/package-info.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Classes and interfaces providing support to the client for initiating requests - * to the OAuth 2.0 Authorization Server's UserInfo Endpoint. + * Classes and interfaces providing support to the client for initiating requests to the + * OAuth 2.0 Authorization Server's UserInfo Endpoint. */ package org.springframework.security.oauth2.client.userinfo; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/AuthenticatedPrincipalOAuth2AuthorizedClientRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/AuthenticatedPrincipalOAuth2AuthorizedClientRepository.java index fef8ffac71..62527e9035 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/AuthenticatedPrincipalOAuth2AuthorizedClientRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/AuthenticatedPrincipalOAuth2AuthorizedClientRepository.java @@ -26,12 +26,12 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** - * An implementation of an {@link OAuth2AuthorizedClientRepository} that - * delegates to the provided {@link OAuth2AuthorizedClientService} if the current - * {@code Principal} is authenticated, otherwise, - * to the default (or provided) {@link OAuth2AuthorizedClientRepository} - * if the current request is unauthenticated (or anonymous). - * The default {@code OAuth2AuthorizedClientRepository} is {@link HttpSessionOAuth2AuthorizedClientRepository}. + * An implementation of an {@link OAuth2AuthorizedClientRepository} that delegates to the + * provided {@link OAuth2AuthorizedClientService} if the current {@code Principal} is + * authenticated, otherwise, to the default (or provided) + * {@link OAuth2AuthorizedClientRepository} if the current request is unauthenticated (or + * anonymous). The default {@code OAuth2AuthorizedClientRepository} is + * {@link HttpSessionOAuth2AuthorizedClientRepository}. * * @author Joe Grandja * @since 5.1 @@ -41,64 +41,76 @@ import javax.servlet.http.HttpServletResponse; * @see HttpSessionOAuth2AuthorizedClientRepository */ public final class AuthenticatedPrincipalOAuth2AuthorizedClientRepository implements OAuth2AuthorizedClientRepository { + private final AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl(); + private final OAuth2AuthorizedClientService authorizedClientService; + private OAuth2AuthorizedClientRepository anonymousAuthorizedClientRepository = new HttpSessionOAuth2AuthorizedClientRepository(); /** - * Constructs a {@code AuthenticatedPrincipalOAuth2AuthorizedClientRepository} using the provided parameters. - * + * Constructs a {@code AuthenticatedPrincipalOAuth2AuthorizedClientRepository} using + * the provided parameters. * @param authorizedClientService the authorized client service */ - public AuthenticatedPrincipalOAuth2AuthorizedClientRepository(OAuth2AuthorizedClientService authorizedClientService) { + public AuthenticatedPrincipalOAuth2AuthorizedClientRepository( + OAuth2AuthorizedClientService authorizedClientService) { Assert.notNull(authorizedClientService, "authorizedClientService cannot be null"); this.authorizedClientService = authorizedClientService; } /** - * Sets the {@link OAuth2AuthorizedClientRepository} used for requests that are unauthenticated (or anonymous). - * The default is {@link HttpSessionOAuth2AuthorizedClientRepository}. - * - * @param anonymousAuthorizedClientRepository the repository used for requests that are unauthenticated (or anonymous) + * Sets the {@link OAuth2AuthorizedClientRepository} used for requests that are + * unauthenticated (or anonymous). The default is + * {@link HttpSessionOAuth2AuthorizedClientRepository}. + * @param anonymousAuthorizedClientRepository the repository used for requests that + * are unauthenticated (or anonymous) */ - public void setAnonymousAuthorizedClientRepository(OAuth2AuthorizedClientRepository anonymousAuthorizedClientRepository) { + public void setAnonymousAuthorizedClientRepository( + OAuth2AuthorizedClientRepository anonymousAuthorizedClientRepository) { Assert.notNull(anonymousAuthorizedClientRepository, "anonymousAuthorizedClientRepository cannot be null"); this.anonymousAuthorizedClientRepository = anonymousAuthorizedClientRepository; } @Override - public T loadAuthorizedClient(String clientRegistrationId, Authentication principal, - HttpServletRequest request) { + public T loadAuthorizedClient(String clientRegistrationId, + Authentication principal, HttpServletRequest request) { if (this.isPrincipalAuthenticated(principal)) { return this.authorizedClientService.loadAuthorizedClient(clientRegistrationId, principal.getName()); - } else { - return this.anonymousAuthorizedClientRepository.loadAuthorizedClient(clientRegistrationId, principal, request); + } + else { + return this.anonymousAuthorizedClientRepository.loadAuthorizedClient(clientRegistrationId, principal, + request); } } @Override public void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal, - HttpServletRequest request, HttpServletResponse response) { + HttpServletRequest request, HttpServletResponse response) { if (this.isPrincipalAuthenticated(principal)) { this.authorizedClientService.saveAuthorizedClient(authorizedClient, principal); - } else { - this.anonymousAuthorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, request, response); + } + else { + this.anonymousAuthorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, request, + response); } } @Override public void removeAuthorizedClient(String clientRegistrationId, Authentication principal, - HttpServletRequest request, HttpServletResponse response) { + HttpServletRequest request, HttpServletResponse response) { if (this.isPrincipalAuthenticated(principal)) { this.authorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName()); - } else { - this.anonymousAuthorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, request, response); + } + else { + this.anonymousAuthorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, request, + response); } } private boolean isPrincipalAuthenticated(Authentication authentication) { - return authentication != null && - !this.authenticationTrustResolver.isAnonymous(authentication) && - authentication.isAuthenticated(); + return authentication != null && !this.authenticationTrustResolver.isAnonymous(authentication) + && authentication.isAuthenticated(); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/AuthorizationRequestRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/AuthorizationRequestRepository.java index c2114a0aa8..46a0d041e1 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/AuthorizationRequestRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/AuthorizationRequestRepository.java @@ -21,58 +21,57 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** - * Implementations of this interface are responsible for the persistence - * of {@link OAuth2AuthorizationRequest} between requests. + * Implementations of this interface are responsible for the persistence of + * {@link OAuth2AuthorizationRequest} between requests. * *

        - * Used by the {@link OAuth2AuthorizationRequestRedirectFilter} for persisting the Authorization Request - * before it initiates the authorization code grant flow. - * As well, used by the {@link OAuth2LoginAuthenticationFilter} for resolving - * the associated Authorization Request when handling the callback of the Authorization Response. + * Used by the {@link OAuth2AuthorizationRequestRedirectFilter} for persisting the + * Authorization Request before it initiates the authorization code grant flow. As well, + * used by the {@link OAuth2LoginAuthenticationFilter} for resolving the associated + * Authorization Request when handling the callback of the Authorization Response. * * @author Joe Grandja * @since 5.0 * @see OAuth2AuthorizationRequest * @see HttpSessionOAuth2AuthorizationRequestRepository - * * @param The type of OAuth 2.0 Authorization Request */ public interface AuthorizationRequestRepository { /** - * Returns the {@link OAuth2AuthorizationRequest} associated to the provided {@code HttpServletRequest} - * or {@code null} if not available. - * + * Returns the {@link OAuth2AuthorizationRequest} associated to the provided + * {@code HttpServletRequest} or {@code null} if not available. * @param request the {@code HttpServletRequest} * @return the {@link OAuth2AuthorizationRequest} or {@code null} if not available */ T loadAuthorizationRequest(HttpServletRequest request); /** - * Persists the {@link OAuth2AuthorizationRequest} associating it to - * the provided {@code HttpServletRequest} and/or {@code HttpServletResponse}. - * + * Persists the {@link OAuth2AuthorizationRequest} associating it to the provided + * {@code HttpServletRequest} and/or {@code HttpServletResponse}. * @param authorizationRequest the {@link OAuth2AuthorizationRequest} * @param request the {@code HttpServletRequest} * @param response the {@code HttpServletResponse} */ - void saveAuthorizationRequest(T authorizationRequest, HttpServletRequest request, - HttpServletResponse response); + void saveAuthorizationRequest(T authorizationRequest, HttpServletRequest request, HttpServletResponse response); /** * Removes and returns the {@link OAuth2AuthorizationRequest} associated to the * provided {@code HttpServletRequest} or if not available returns {@code null}. - * - * @deprecated Use {@link #removeAuthorizationRequest(HttpServletRequest, HttpServletResponse)} instead + * @deprecated Use + * {@link #removeAuthorizationRequest(HttpServletRequest, HttpServletResponse)} + * instead * @param request the {@code HttpServletRequest} - * @return the removed {@link OAuth2AuthorizationRequest} or {@code null} if not available + * @return the removed {@link OAuth2AuthorizationRequest} or {@code null} if not + * available */ @Deprecated T removeAuthorizationRequest(HttpServletRequest request); /** * Removes and returns the {@link OAuth2AuthorizationRequest} associated to the - * provided {@code HttpServletRequest} and {@code HttpServletResponse} or if not available returns {@code null}. + * provided {@code HttpServletRequest} and {@code HttpServletResponse} or if not + * available returns {@code null}. * * @since 5.1 * @param request the {@code HttpServletRequest} @@ -82,4 +81,5 @@ public interface AuthorizationRequestRepository - * NOTE: The default base {@code URI} {@code /oauth2/authorization} may be overridden - * via it's constructor {@link #DefaultOAuth2AuthorizationRequestResolver(ClientRegistrationRepository, String)}. + * NOTE: The default base {@code URI} {@code /oauth2/authorization} may be + * overridden via it's constructor + * {@link #DefaultOAuth2AuthorizationRequestResolver(ClientRegistrationRepository, String)}. * * @author Joe Grandja * @author Rob Winch @@ -61,22 +63,32 @@ import java.util.function.Consumer; * @see OAuth2AuthorizationRequestRedirectFilter */ public final class DefaultOAuth2AuthorizationRequestResolver implements OAuth2AuthorizationRequestResolver { + private static final String REGISTRATION_ID_URI_VARIABLE_NAME = "registrationId"; + private static final char PATH_DELIMITER = '/'; + private final ClientRegistrationRepository clientRegistrationRepository; + private final AntPathRequestMatcher authorizationRequestMatcher; + private final StringKeyGenerator stateGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder()); - private final StringKeyGenerator secureKeyGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96); - private Consumer authorizationRequestCustomizer = customizer -> {}; + + private final StringKeyGenerator secureKeyGenerator = new Base64StringKeyGenerator( + Base64.getUrlEncoder().withoutPadding(), 96); + + private Consumer authorizationRequestCustomizer = customizer -> { + }; /** - * Constructs a {@code DefaultOAuth2AuthorizationRequestResolver} using the provided parameters. - * + * Constructs a {@code DefaultOAuth2AuthorizationRequestResolver} using the provided + * parameters. * @param clientRegistrationRepository the repository of client registrations - * @param authorizationRequestBaseUri the base {@code URI} used for resolving authorization requests + * @param authorizationRequestBaseUri the base {@code URI} used for resolving + * authorization requests */ public DefaultOAuth2AuthorizationRequestResolver(ClientRegistrationRepository clientRegistrationRepository, - String authorizationRequestBaseUri) { + String authorizationRequestBaseUri) { Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null"); Assert.hasText(authorizationRequestBaseUri, "authorizationRequestBaseUri cannot be empty"); this.clientRegistrationRepository = clientRegistrationRepository; @@ -104,13 +116,15 @@ public final class DefaultOAuth2AuthorizationRequestResolver implements OAuth2Au } /** - * Sets the {@code Consumer} to be provided the {@link OAuth2AuthorizationRequest.Builder} - * allowing for further customizations. + * Sets the {@code Consumer} to be provided the + * {@link OAuth2AuthorizationRequest.Builder} allowing for further customizations. * * @since 5.3 - * @param authorizationRequestCustomizer the {@code Consumer} to be provided the {@link OAuth2AuthorizationRequest.Builder} + * @param authorizationRequestCustomizer the {@code Consumer} to be provided the + * {@link OAuth2AuthorizationRequest.Builder} */ - public void setAuthorizationRequestCustomizer(Consumer authorizationRequestCustomizer) { + public void setAuthorizationRequestCustomizer( + Consumer authorizationRequestCustomizer) { Assert.notNull(authorizationRequestCustomizer, "authorizationRequestCustomizer cannot be null"); this.authorizationRequestCustomizer = authorizationRequestCustomizer; } @@ -123,7 +137,8 @@ public final class DefaultOAuth2AuthorizationRequestResolver implements OAuth2Au return action; } - private OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId, String redirectUriAction) { + private OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId, + String redirectUriAction) { if (registrationId == null) { return null; } @@ -140,34 +155,35 @@ public final class DefaultOAuth2AuthorizationRequestResolver implements OAuth2Au if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(clientRegistration.getAuthorizationGrantType())) { builder = OAuth2AuthorizationRequest.authorizationCode(); Map additionalParameters = new HashMap<>(); - if (!CollectionUtils.isEmpty(clientRegistration.getScopes()) && - clientRegistration.getScopes().contains(OidcScopes.OPENID)) { - // Section 3.1.2.1 Authentication Request - https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest + if (!CollectionUtils.isEmpty(clientRegistration.getScopes()) + && clientRegistration.getScopes().contains(OidcScopes.OPENID)) { + // Section 3.1.2.1 Authentication Request - + // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest // scope - // REQUIRED. OpenID Connect requests MUST contain the "openid" scope value. + // REQUIRED. OpenID Connect requests MUST contain the "openid" scope + // value. addNonceParameters(attributes, additionalParameters); } if (ClientAuthenticationMethod.NONE.equals(clientRegistration.getClientAuthenticationMethod())) { addPkceParameters(attributes, additionalParameters); } builder.additionalParameters(additionalParameters); - } else if (AuthorizationGrantType.IMPLICIT.equals(clientRegistration.getAuthorizationGrantType())) { + } + else if (AuthorizationGrantType.IMPLICIT.equals(clientRegistration.getAuthorizationGrantType())) { builder = OAuth2AuthorizationRequest.implicit(); - } else { - throw new IllegalArgumentException("Invalid Authorization Grant Type (" + - clientRegistration.getAuthorizationGrantType().getValue() + - ") for Client Registration with Id: " + clientRegistration.getRegistrationId()); + } + else { + throw new IllegalArgumentException( + "Invalid Authorization Grant Type (" + clientRegistration.getAuthorizationGrantType().getValue() + + ") for Client Registration with Id: " + clientRegistration.getRegistrationId()); } String redirectUriStr = expandRedirectUri(request, clientRegistration, redirectUriAction); - builder - .clientId(clientRegistration.getClientId()) + builder.clientId(clientRegistration.getClientId()) .authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()) - .redirectUri(redirectUriStr) - .scopes(clientRegistration.getScopes()) - .state(this.stateGenerator.generateKey()) - .attributes(attributes); + .redirectUri(redirectUriStr).scopes(clientRegistration.getScopes()) + .state(this.stateGenerator.generateKey()).attributes(attributes); this.authorizationRequestCustomizer.accept(builder); @@ -176,14 +192,15 @@ public final class DefaultOAuth2AuthorizationRequestResolver implements OAuth2Au private String resolveRegistrationId(HttpServletRequest request) { if (this.authorizationRequestMatcher.matches(request)) { - return this.authorizationRequestMatcher - .matcher(request).getVariables().get(REGISTRATION_ID_URI_VARIABLE_NAME); + return this.authorizationRequestMatcher.matcher(request).getVariables() + .get(REGISTRATION_ID_URI_VARIABLE_NAME); } return null; } /** - * Expands the {@link ClientRegistration#getRedirectUri()} with following provided variables:
        + * Expands the {@link ClientRegistration#getRedirectUri()} with following provided + * variables:
        * - baseUrl (e.g. https://localhost/app)
        * - baseScheme (e.g. https)
        * - baseHost (e.g. localhost)
        @@ -194,19 +211,17 @@ public final class DefaultOAuth2AuthorizationRequestResolver implements OAuth2Au *

        * Null variables are provided as empty strings. *

        - * Default redirectUri is: {@code org.springframework.security.config.oauth2.client.CommonOAuth2Provider#DEFAULT_REDIRECT_URL} - * + * Default redirectUri is: + * {@code org.springframework.security.config.oauth2.client.CommonOAuth2Provider#DEFAULT_REDIRECT_URL} * @return expanded URI */ - private static String expandRedirectUri(HttpServletRequest request, ClientRegistration clientRegistration, String action) { + private static String expandRedirectUri(HttpServletRequest request, ClientRegistration clientRegistration, + String action) { Map uriVariables = new HashMap<>(); uriVariables.put("registrationId", clientRegistration.getRegistrationId()); UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(UrlUtils.buildFullRequestUrl(request)) - .replacePath(request.getContextPath()) - .replaceQuery(null) - .fragment(null) - .build(); + .replacePath(request.getContextPath()).replaceQuery(null).fragment(null).build(); String scheme = uriComponents.getScheme(); uriVariables.put("baseScheme", scheme == null ? "" : scheme); String host = uriComponents.getHost(); @@ -225,19 +240,21 @@ public final class DefaultOAuth2AuthorizationRequestResolver implements OAuth2Au uriVariables.put("action", action == null ? "" : action); - return UriComponentsBuilder.fromUriString(clientRegistration.getRedirectUri()) - .buildAndExpand(uriVariables) + return UriComponentsBuilder.fromUriString(clientRegistration.getRedirectUri()).buildAndExpand(uriVariables) .toUriString(); } /** * Creates nonce and its hash for use in OpenID Connect 1.0 Authentication Requests. - * - * @param attributes where the {@link OidcParameterNames#NONCE} is stored for the authentication request - * @param additionalParameters where the {@link OidcParameterNames#NONCE} hash is added for the authentication request + * @param attributes where the {@link OidcParameterNames#NONCE} is stored for the + * authentication request + * @param additionalParameters where the {@link OidcParameterNames#NONCE} hash is + * added for the authentication request * * @since 5.2 - * @see 3.1.2.1. Authentication Request + * @see 3.1.2.1. + * Authentication Request */ private void addNonceParameters(Map attributes, Map additionalParameters) { try { @@ -245,20 +262,27 @@ public final class DefaultOAuth2AuthorizationRequestResolver implements OAuth2Au String nonceHash = createHash(nonce); attributes.put(OidcParameterNames.NONCE, nonce); additionalParameters.put(OidcParameterNames.NONCE, nonceHash); - } catch (NoSuchAlgorithmException e) { } + } + catch (NoSuchAlgorithmException e) { + } } /** - * Creates and adds additional PKCE parameters for use in the OAuth 2.0 Authorization and Access Token Requests - * - * @param attributes where {@link PkceParameterNames#CODE_VERIFIER} is stored for the token request - * @param additionalParameters where {@link PkceParameterNames#CODE_CHALLENGE} and, usually, - * {@link PkceParameterNames#CODE_CHALLENGE_METHOD} are added to be used in the authorization request. + * Creates and adds additional PKCE parameters for use in the OAuth 2.0 Authorization + * and Access Token Requests + * @param attributes where {@link PkceParameterNames#CODE_VERIFIER} is stored for the + * token request + * @param additionalParameters where {@link PkceParameterNames#CODE_CHALLENGE} and, + * usually, {@link PkceParameterNames#CODE_CHALLENGE_METHOD} are added to be used in + * the authorization request. * * @since 5.2 - * @see 1.1. Protocol Flow - * @see 4.1. Client Creates a Code Verifier - * @see 4.2. Client Creates the Code Challenge + * @see 1.1. + * Protocol Flow + * @see 4.1. + * Client Creates a Code Verifier + * @see 4.2. + * Client Creates the Code Challenge */ private void addPkceParameters(Map attributes, Map additionalParameters) { String codeVerifier = this.secureKeyGenerator.generateKey(); @@ -267,7 +291,8 @@ public final class DefaultOAuth2AuthorizationRequestResolver implements OAuth2Au String codeChallenge = createHash(codeVerifier); additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, codeChallenge); additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256"); - } catch (NoSuchAlgorithmException e) { + } + catch (NoSuchAlgorithmException e) { additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, codeVerifier); } } @@ -277,4 +302,5 @@ public final class DefaultOAuth2AuthorizationRequestResolver implements OAuth2Au byte[] digest = md.digest(value.getBytes(StandardCharsets.US_ASCII)); return Base64.getUrlEncoder().withoutPadding().encodeToString(digest); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizedClientManager.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizedClientManager.java index 708db52020..78bc7af340 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizedClientManager.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizedClientManager.java @@ -47,34 +47,34 @@ import java.util.Map; import java.util.function.Function; /** - * The default implementation of an {@link OAuth2AuthorizedClientManager} - * for use within the context of a {@code HttpServletRequest}. + * The default implementation of an {@link OAuth2AuthorizedClientManager} for use within + * the context of a {@code HttpServletRequest}. * *

        - * (When operating outside of the context of a {@code HttpServletRequest}, - * use {@link AuthorizedClientServiceOAuth2AuthorizedClientManager} instead.) + * (When operating outside of the context of a {@code HttpServletRequest}, use + * {@link AuthorizedClientServiceOAuth2AuthorizedClientManager} instead.) * *

        Authorized Client Persistence

        * *

        - * This manager utilizes an {@link OAuth2AuthorizedClientRepository} - * to persist {@link OAuth2AuthorizedClient}s. + * This manager utilizes an {@link OAuth2AuthorizedClientRepository} to persist + * {@link OAuth2AuthorizedClient}s. * *

        * By default, when an authorization attempt succeeds, the {@link OAuth2AuthorizedClient} - * will be saved in the {@link OAuth2AuthorizedClientRepository}. - * This functionality can be changed by configuring a custom {@link OAuth2AuthorizationSuccessHandler} - * via {@link #setAuthorizationSuccessHandler(OAuth2AuthorizationSuccessHandler)}. + * will be saved in the {@link OAuth2AuthorizedClientRepository}. This functionality can + * be changed by configuring a custom {@link OAuth2AuthorizationSuccessHandler} via + * {@link #setAuthorizationSuccessHandler(OAuth2AuthorizationSuccessHandler)}. * *

        * By default, when an authorization attempt fails due to an - * {@value OAuth2ErrorCodes#INVALID_GRANT} error, - * the previously saved {@link OAuth2AuthorizedClient} - * will be removed from the {@link OAuth2AuthorizedClientRepository}. - * (The {@value OAuth2ErrorCodes#INVALID_GRANT} error can occur - * when a refresh token that is no longer valid is used to retrieve a new access token.) - * This functionality can be changed by configuring a custom {@link OAuth2AuthorizationFailureHandler} - * via {@link #setAuthorizationFailureHandler(OAuth2AuthorizationFailureHandler)}. + * {@value OAuth2ErrorCodes#INVALID_GRANT} error, the previously saved + * {@link OAuth2AuthorizedClient} will be removed from the + * {@link OAuth2AuthorizedClientRepository}. (The {@value OAuth2ErrorCodes#INVALID_GRANT} + * error can occur when a refresh token that is no longer valid is used to retrieve a new + * access token.) This functionality can be changed by configuring a custom + * {@link OAuth2AuthorizationFailureHandler} via + * {@link #setAuthorizationFailureHandler(OAuth2AuthorizationFailureHandler)}. * * @author Joe Grandja * @since 5.2 @@ -84,43 +84,45 @@ import java.util.function.Function; * @see OAuth2AuthorizationFailureHandler */ public final class DefaultOAuth2AuthorizedClientManager implements OAuth2AuthorizedClientManager { - private static final OAuth2AuthorizedClientProvider DEFAULT_AUTHORIZED_CLIENT_PROVIDER = - OAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .refreshToken() - .clientCredentials() - .password() - .build(); + + private static final OAuth2AuthorizedClientProvider DEFAULT_AUTHORIZED_CLIENT_PROVIDER = OAuth2AuthorizedClientProviderBuilder + .builder().authorizationCode().refreshToken().clientCredentials().password().build(); + private final ClientRegistrationRepository clientRegistrationRepository; + private final OAuth2AuthorizedClientRepository authorizedClientRepository; + private OAuth2AuthorizedClientProvider authorizedClientProvider; + private Function> contextAttributesMapper; + private OAuth2AuthorizationSuccessHandler authorizationSuccessHandler; + private OAuth2AuthorizationFailureHandler authorizationFailureHandler; /** - * Constructs a {@code DefaultOAuth2AuthorizedClientManager} using the provided parameters. - * + * Constructs a {@code DefaultOAuth2AuthorizedClientManager} using the provided + * parameters. * @param clientRegistrationRepository the repository of client registrations * @param authorizedClientRepository the repository of authorized clients */ public DefaultOAuth2AuthorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, - OAuth2AuthorizedClientRepository authorizedClientRepository) { + OAuth2AuthorizedClientRepository authorizedClientRepository) { Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null"); Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null"); this.clientRegistrationRepository = clientRegistrationRepository; this.authorizedClientRepository = authorizedClientRepository; this.authorizedClientProvider = DEFAULT_AUTHORIZED_CLIENT_PROVIDER; this.contextAttributesMapper = new DefaultContextAttributesMapper(); - this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> - authorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, + this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> authorizedClientRepository + .saveAuthorizedClient(authorizedClient, principal, (HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), (HttpServletResponse) attributes.get(HttpServletResponse.class.getName())); this.authorizationFailureHandler = new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( - (clientRegistrationId, principal, attributes) -> - authorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, - (HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), - (HttpServletResponse) attributes.get(HttpServletResponse.class.getName()))); + (clientRegistrationId, principal, attributes) -> authorizedClientRepository.removeAuthorizedClient( + clientRegistrationId, principal, + (HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), + (HttpServletResponse) attributes.get(HttpServletResponse.class.getName()))); } @Nullable @@ -140,41 +142,46 @@ public final class DefaultOAuth2AuthorizedClientManager implements OAuth2Authori OAuth2AuthorizationContext.Builder contextBuilder; if (authorizedClient != null) { contextBuilder = OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient); - } else { - authorizedClient = this.authorizedClientRepository.loadAuthorizedClient( - clientRegistrationId, principal, servletRequest); + } + else { + authorizedClient = this.authorizedClientRepository.loadAuthorizedClient(clientRegistrationId, principal, + servletRequest); if (authorizedClient != null) { contextBuilder = OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient); - } else { - ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId); - Assert.notNull(clientRegistration, "Could not find ClientRegistration with id '" + clientRegistrationId + "'"); + } + else { + ClientRegistration clientRegistration = this.clientRegistrationRepository + .findByRegistrationId(clientRegistrationId); + Assert.notNull(clientRegistration, + "Could not find ClientRegistration with id '" + clientRegistrationId + "'"); contextBuilder = OAuth2AuthorizationContext.withClientRegistration(clientRegistration); } } - OAuth2AuthorizationContext authorizationContext = contextBuilder - .principal(principal) - .attributes(attributes -> { - Map contextAttributes = this.contextAttributesMapper.apply(authorizeRequest); - if (!CollectionUtils.isEmpty(contextAttributes)) { - attributes.putAll(contextAttributes); - } - }) - .build(); + OAuth2AuthorizationContext authorizationContext = contextBuilder.principal(principal).attributes(attributes -> { + Map contextAttributes = this.contextAttributesMapper.apply(authorizeRequest); + if (!CollectionUtils.isEmpty(contextAttributes)) { + attributes.putAll(contextAttributes); + } + }).build(); try { authorizedClient = this.authorizedClientProvider.authorize(authorizationContext); - } catch (OAuth2AuthorizationException ex) { - this.authorizationFailureHandler.onAuthorizationFailure( - ex, principal, createAttributes(servletRequest, servletResponse)); + } + catch (OAuth2AuthorizationException ex) { + this.authorizationFailureHandler.onAuthorizationFailure(ex, principal, + createAttributes(servletRequest, servletResponse)); throw ex; } if (authorizedClient != null) { - this.authorizationSuccessHandler.onAuthorizationSuccess( - authorizedClient, principal, createAttributes(servletRequest, servletResponse)); - } else { - // In the case of re-authorization, the returned `authorizedClient` may be null if re-authorization is not supported. - // For these cases, return the provided `authorizationContext.authorizedClient`. + this.authorizationSuccessHandler.onAuthorizationSuccess(authorizedClient, principal, + createAttributes(servletRequest, servletResponse)); + } + else { + // In the case of re-authorization, the returned `authorizedClient` may be + // null if re-authorization is not supported. + // For these cases, return the provided + // `authorizationContext.authorizedClient`. if (authorizationContext.getAuthorizedClient() != null) { return authorizationContext.getAuthorizedClient(); } @@ -183,7 +190,8 @@ public final class DefaultOAuth2AuthorizedClientManager implements OAuth2Authori return authorizedClient; } - private static Map createAttributes(HttpServletRequest servletRequest, HttpServletResponse servletResponse) { + private static Map createAttributes(HttpServletRequest servletRequest, + HttpServletResponse servletResponse) { Map attributes = new HashMap<>(); attributes.put(HttpServletRequest.class.getName(), servletRequest); attributes.put(HttpServletResponse.class.getName(), servletResponse); @@ -206,16 +214,17 @@ public final class DefaultOAuth2AuthorizedClientManager implements OAuth2Authori if (servletResponse == null) { RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); if (requestAttributes instanceof ServletRequestAttributes) { - servletResponse = ((ServletRequestAttributes) requestAttributes).getResponse(); + servletResponse = ((ServletRequestAttributes) requestAttributes).getResponse(); } } return servletResponse; } /** - * Sets the {@link OAuth2AuthorizedClientProvider} used for authorizing (or re-authorizing) an OAuth 2.0 Client. - * - * @param authorizedClientProvider the {@link OAuth2AuthorizedClientProvider} used for authorizing (or re-authorizing) an OAuth 2.0 Client + * Sets the {@link OAuth2AuthorizedClientProvider} used for authorizing (or + * re-authorizing) an OAuth 2.0 Client. + * @param authorizedClientProvider the {@link OAuth2AuthorizedClientProvider} used for + * authorizing (or re-authorizing) an OAuth 2.0 Client */ public void setAuthorizedClientProvider(OAuth2AuthorizedClientProvider authorizedClientProvider) { Assert.notNull(authorizedClientProvider, "authorizedClientProvider cannot be null"); @@ -223,24 +232,28 @@ public final class DefaultOAuth2AuthorizedClientManager implements OAuth2Authori } /** - * Sets the {@code Function} used for mapping attribute(s) from the {@link OAuth2AuthorizeRequest} to a {@code Map} of attributes - * to be associated to the {@link OAuth2AuthorizationContext#getAttributes() authorization context}. - * - * @param contextAttributesMapper the {@code Function} used for supplying the {@code Map} of attributes - * to the {@link OAuth2AuthorizationContext#getAttributes() authorization context} + * Sets the {@code Function} used for mapping attribute(s) from the + * {@link OAuth2AuthorizeRequest} to a {@code Map} of attributes to be associated to + * the {@link OAuth2AuthorizationContext#getAttributes() authorization context}. + * @param contextAttributesMapper the {@code Function} used for supplying the + * {@code Map} of attributes to the {@link OAuth2AuthorizationContext#getAttributes() + * authorization context} */ - public void setContextAttributesMapper(Function> contextAttributesMapper) { + public void setContextAttributesMapper( + Function> contextAttributesMapper) { Assert.notNull(contextAttributesMapper, "contextAttributesMapper cannot be null"); this.contextAttributesMapper = contextAttributesMapper; } /** - * Sets the {@link OAuth2AuthorizationSuccessHandler} that handles successful authorizations. + * Sets the {@link OAuth2AuthorizationSuccessHandler} that handles successful + * authorizations. * *

        - * The default saves {@link OAuth2AuthorizedClient}s in the {@link OAuth2AuthorizedClientRepository}. - * - * @param authorizationSuccessHandler the {@link OAuth2AuthorizationSuccessHandler} that handles successful authorizations + * The default saves {@link OAuth2AuthorizedClient}s in the + * {@link OAuth2AuthorizedClientRepository}. + * @param authorizationSuccessHandler the {@link OAuth2AuthorizationSuccessHandler} + * that handles successful authorizations * @since 5.3 */ public void setAuthorizationSuccessHandler(OAuth2AuthorizationSuccessHandler authorizationSuccessHandler) { @@ -249,12 +262,14 @@ public final class DefaultOAuth2AuthorizedClientManager implements OAuth2Authori } /** - * Sets the {@link OAuth2AuthorizationFailureHandler} that handles authorization failures. + * Sets the {@link OAuth2AuthorizationFailureHandler} that handles authorization + * failures. * *

        - * A {@link RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} is used by default. - * - * @param authorizationFailureHandler the {@link OAuth2AuthorizationFailureHandler} that handles authorization failures + * A {@link RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} is used by + * default. + * @param authorizationFailureHandler the {@link OAuth2AuthorizationFailureHandler} + * that handles authorization failures * @see RemoveAuthorizedClientOAuth2AuthorizationFailureHandler * @since 5.3 */ @@ -264,9 +279,11 @@ public final class DefaultOAuth2AuthorizedClientManager implements OAuth2Authori } /** - * The default implementation of the {@link #setContextAttributesMapper(Function) contextAttributesMapper}. + * The default implementation of the {@link #setContextAttributesMapper(Function) + * contextAttributesMapper}. */ - public static class DefaultContextAttributesMapper implements Function> { + public static class DefaultContextAttributesMapper + implements Function> { @Override public Map apply(OAuth2AuthorizeRequest authorizeRequest) { @@ -280,5 +297,7 @@ public final class DefaultOAuth2AuthorizedClientManager implements OAuth2Authori } return contextAttributes; } + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultReactiveOAuth2AuthorizedClientManager.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultReactiveOAuth2AuthorizedClientManager.java index fbeef271d4..c7fac35606 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultReactiveOAuth2AuthorizedClientManager.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/DefaultReactiveOAuth2AuthorizedClientManager.java @@ -42,33 +42,44 @@ import java.util.Map; import java.util.function.Function; /** - * The default implementation of a {@link ReactiveOAuth2AuthorizedClientManager} - * for use within the context of a {@link ServerWebExchange}. + * The default implementation of a {@link ReactiveOAuth2AuthorizedClientManager} for use + * within the context of a {@link ServerWebExchange}. * - *

        (When operating outside of the context of a {@link ServerWebExchange}, - * use {@link org.springframework.security.oauth2.client.AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager} instead.)

        + *

        + * (When operating outside of the context of a {@link ServerWebExchange}, use + * {@link org.springframework.security.oauth2.client.AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager + * AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager} instead.) + *

        * - *

        This is a reactive equivalent of {@link DefaultOAuth2AuthorizedClientManager}.

        + *

        + * This is a reactive equivalent of {@link DefaultOAuth2AuthorizedClientManager}. + *

        * *

        Authorized Client Persistence

        * - *

        This client manager utilizes a {@link ServerOAuth2AuthorizedClientRepository} - * to persist {@link OAuth2AuthorizedClient}s.

        + *

        + * This client manager utilizes a {@link ServerOAuth2AuthorizedClientRepository} to + * persist {@link OAuth2AuthorizedClient}s. + *

        * - *

        By default, when an authorization attempt succeeds, the {@link OAuth2AuthorizedClient} - * will be saved in the authorized client repository. - * This functionality can be changed by configuring a custom {@link ReactiveOAuth2AuthorizationSuccessHandler} - * via {@link #setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler)}.

        + *

        + * By default, when an authorization attempt succeeds, the {@link OAuth2AuthorizedClient} + * will be saved in the authorized client repository. This functionality can be changed by + * configuring a custom {@link ReactiveOAuth2AuthorizationSuccessHandler} via + * {@link #setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler)}. + *

        * - *

        By default, when an authorization attempt fails due to an + *

        + * By default, when an authorization attempt fails due to an * {@value org.springframework.security.oauth2.core.OAuth2ErrorCodes#INVALID_GRANT} error, - * the previously saved {@link OAuth2AuthorizedClient} - * will be removed from the authorized client repository. - * (The {@value org.springframework.security.oauth2.core.OAuth2ErrorCodes#INVALID_GRANT} - * error generally occurs when a refresh token that is no longer valid - * is used to retrieve a new access token.) - * This functionality can be changed by configuring a custom {@link ReactiveOAuth2AuthorizationFailureHandler} - * via {@link #setAuthorizationFailureHandler(ReactiveOAuth2AuthorizationFailureHandler)}.

        + * the previously saved {@link OAuth2AuthorizedClient} will be removed from the authorized + * client repository. (The + * {@value org.springframework.security.oauth2.core.OAuth2ErrorCodes#INVALID_GRANT} error + * generally occurs when a refresh token that is no longer valid is used to retrieve a new + * access token.) This functionality can be changed by configuring a custom + * {@link ReactiveOAuth2AuthorizationFailureHandler} via + * {@link #setAuthorizationFailureHandler(ReactiveOAuth2AuthorizationFailureHandler)}. + *

        * * @author Joe Grandja * @author Phil Clay @@ -79,44 +90,45 @@ import java.util.function.Function; * @see ReactiveOAuth2AuthorizationFailureHandler */ public final class DefaultReactiveOAuth2AuthorizedClientManager implements ReactiveOAuth2AuthorizedClientManager { - private static final ReactiveOAuth2AuthorizedClientProvider DEFAULT_AUTHORIZED_CLIENT_PROVIDER = - ReactiveOAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .refreshToken() - .clientCredentials() - .password() - .build(); + + private static final ReactiveOAuth2AuthorizedClientProvider DEFAULT_AUTHORIZED_CLIENT_PROVIDER = ReactiveOAuth2AuthorizedClientProviderBuilder + .builder().authorizationCode().refreshToken().clientCredentials().password().build(); private static final Mono currentServerWebExchangeMono = Mono.subscriberContext() - .filter(c -> c.hasKey(ServerWebExchange.class)) - .map(c -> c.get(ServerWebExchange.class)); + .filter(c -> c.hasKey(ServerWebExchange.class)).map(c -> c.get(ServerWebExchange.class)); private final ReactiveClientRegistrationRepository clientRegistrationRepository; + private final ServerOAuth2AuthorizedClientRepository authorizedClientRepository; + private ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = DEFAULT_AUTHORIZED_CLIENT_PROVIDER; + private Function>> contextAttributesMapper = new DefaultContextAttributesMapper(); + private ReactiveOAuth2AuthorizationSuccessHandler authorizationSuccessHandler; + private ReactiveOAuth2AuthorizationFailureHandler authorizationFailureHandler; /** - * Constructs a {@code DefaultReactiveOAuth2AuthorizedClientManager} using the provided parameters. - * + * Constructs a {@code DefaultReactiveOAuth2AuthorizedClientManager} using the + * provided parameters. * @param clientRegistrationRepository the repository of client registrations * @param authorizedClientRepository the repository of authorized clients */ - public DefaultReactiveOAuth2AuthorizedClientManager(ReactiveClientRegistrationRepository clientRegistrationRepository, - ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { + public DefaultReactiveOAuth2AuthorizedClientManager( + ReactiveClientRegistrationRepository clientRegistrationRepository, + ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null"); Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null"); this.clientRegistrationRepository = clientRegistrationRepository; this.authorizedClientRepository = authorizedClientRepository; - this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> - authorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, + this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> authorizedClientRepository + .saveAuthorizedClient(authorizedClient, principal, (ServerWebExchange) attributes.get(ServerWebExchange.class.getName())); this.authorizationFailureHandler = new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler( - (clientRegistrationId, principal, attributes) -> - authorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, - (ServerWebExchange) attributes.get(ServerWebExchange.class.getName()))); + (clientRegistrationId, principal, attributes) -> authorizedClientRepository.removeAuthorizedClient( + clientRegistrationId, principal, + (ServerWebExchange) attributes.get(ServerWebExchange.class.getName()))); } @Override @@ -130,60 +142,60 @@ public final class DefaultReactiveOAuth2AuthorizedClientManager implements React .switchIfEmpty(currentServerWebExchangeMono) .switchIfEmpty(Mono.error(() -> new IllegalArgumentException("serverWebExchange cannot be null"))) .flatMap(serverWebExchange -> Mono.justOrEmpty(authorizeRequest.getAuthorizedClient()) - .switchIfEmpty(Mono.defer(() -> loadAuthorizedClient(clientRegistrationId, principal, serverWebExchange))) + .switchIfEmpty(Mono + .defer(() -> loadAuthorizedClient(clientRegistrationId, principal, serverWebExchange))) .flatMap(authorizedClient -> { // Re-authorize return authorizationContext(authorizeRequest, authorizedClient) - .flatMap(authorizationContext -> authorize(authorizationContext, principal, serverWebExchange)) - // Default to the existing authorizedClient if the client was not re-authorized - .defaultIfEmpty(authorizeRequest.getAuthorizedClient() != null ? - authorizeRequest.getAuthorizedClient() : authorizedClient); - }) - .switchIfEmpty(Mono.defer(() -> - // Authorize - this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId) - .switchIfEmpty(Mono.error(() -> new IllegalArgumentException( - "Could not find ClientRegistration with id '" + clientRegistrationId + "'"))) - .flatMap(clientRegistration -> authorizationContext(authorizeRequest, clientRegistration)) - .flatMap(authorizationContext -> authorize(authorizationContext, principal, serverWebExchange)) - ) - )); + .flatMap(authorizationContext -> authorize(authorizationContext, principal, + serverWebExchange)) + // Default to the existing authorizedClient if the + // client was not re-authorized + .defaultIfEmpty(authorizeRequest.getAuthorizedClient() != null + ? authorizeRequest.getAuthorizedClient() : authorizedClient); + }).switchIfEmpty(Mono.defer(() -> + // Authorize + this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId) + .switchIfEmpty(Mono.error(() -> new IllegalArgumentException( + "Could not find ClientRegistration with id '" + clientRegistrationId + "'"))) + .flatMap(clientRegistration -> authorizationContext(authorizeRequest, + clientRegistration)) + .flatMap(authorizationContext -> authorize(authorizationContext, principal, + serverWebExchange))))); } - private Mono loadAuthorizedClient(String clientRegistrationId, Authentication principal, ServerWebExchange serverWebExchange) { + private Mono loadAuthorizedClient(String clientRegistrationId, Authentication principal, + ServerWebExchange serverWebExchange) { return this.authorizedClientRepository.loadAuthorizedClient(clientRegistrationId, principal, serverWebExchange); } /** - * Performs authorization and then delegates to either the {@link #authorizationSuccessHandler} - * or {@link #authorizationFailureHandler}, depending on the authorization result. - * + * Performs authorization and then delegates to either the + * {@link #authorizationSuccessHandler} or {@link #authorizationFailureHandler}, + * depending on the authorization result. * @param authorizationContext the context to authorize * @param principal the principle to authorize * @param serverWebExchange the currently active exchange - * @return a {@link Mono} that emits the authorized client after the authorization attempt succeeds - * and the {@link #authorizationSuccessHandler} has completed, - * or completes with an exception after the authorization attempt fails - * and the {@link #authorizationFailureHandler} has completed + * @return a {@link Mono} that emits the authorized client after the authorization + * attempt succeeds and the {@link #authorizationSuccessHandler} has completed, or + * completes with an exception after the authorization attempt fails and the + * {@link #authorizationFailureHandler} has completed */ - private Mono authorize( - OAuth2AuthorizationContext authorizationContext, - Authentication principal, - ServerWebExchange serverWebExchange) { + private Mono authorize(OAuth2AuthorizationContext authorizationContext, + Authentication principal, ServerWebExchange serverWebExchange) { return this.authorizedClientProvider.authorize(authorizationContext) - // Delegate to the authorizationSuccessHandler of the successful authorization - .flatMap(authorizedClient -> this.authorizationSuccessHandler.onAuthorizationSuccess( - authorizedClient, - principal, - createAttributes(serverWebExchange)) + // Delegate to the authorizationSuccessHandler of the successful + // authorization + .flatMap(authorizedClient -> this.authorizationSuccessHandler + .onAuthorizationSuccess(authorizedClient, principal, createAttributes(serverWebExchange)) .thenReturn(authorizedClient)) // Delegate to the authorizationFailureHandler of the failed authorization - .onErrorResume(OAuth2AuthorizationException.class, authorizationException -> this.authorizationFailureHandler.onAuthorizationFailure( - authorizationException, - principal, - createAttributes(serverWebExchange)) - .then(Mono.error(authorizationException))); + .onErrorResume(OAuth2AuthorizationException.class, + authorizationException -> this.authorizationFailureHandler + .onAuthorizationFailure(authorizationException, principal, + createAttributes(serverWebExchange)) + .then(Mono.error(authorizationException))); } private Map createAttributes(ServerWebExchange serverWebExchange) { @@ -191,37 +203,32 @@ public final class DefaultReactiveOAuth2AuthorizedClientManager implements React } private Mono authorizationContext(OAuth2AuthorizeRequest authorizeRequest, - OAuth2AuthorizedClient authorizedClient) { - return Mono.just(authorizeRequest) - .flatMap(this.contextAttributesMapper) + OAuth2AuthorizedClient authorizedClient) { + return Mono.just(authorizeRequest).flatMap(this.contextAttributesMapper) .map(attrs -> OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(authorizeRequest.getPrincipal()) - .attributes(attributes -> { + .principal(authorizeRequest.getPrincipal()).attributes(attributes -> { if (!CollectionUtils.isEmpty(attrs)) { attributes.putAll(attrs); } - }) - .build()); + }).build()); } private Mono authorizationContext(OAuth2AuthorizeRequest authorizeRequest, - ClientRegistration clientRegistration) { - return Mono.just(authorizeRequest) - .flatMap(this.contextAttributesMapper) + ClientRegistration clientRegistration) { + return Mono.just(authorizeRequest).flatMap(this.contextAttributesMapper) .map(attrs -> OAuth2AuthorizationContext.withClientRegistration(clientRegistration) - .principal(authorizeRequest.getPrincipal()) - .attributes(attributes -> { + .principal(authorizeRequest.getPrincipal()).attributes(attributes -> { if (!CollectionUtils.isEmpty(attrs)) { attributes.putAll(attrs); } - }) - .build()); + }).build()); } /** - * Sets the {@link ReactiveOAuth2AuthorizedClientProvider} used for authorizing (or re-authorizing) an OAuth 2.0 Client. - * - * @param authorizedClientProvider the {@link ReactiveOAuth2AuthorizedClientProvider} used for authorizing (or re-authorizing) an OAuth 2.0 Client + * Sets the {@link ReactiveOAuth2AuthorizedClientProvider} used for authorizing (or + * re-authorizing) an OAuth 2.0 Client. + * @param authorizedClientProvider the {@link ReactiveOAuth2AuthorizedClientProvider} + * used for authorizing (or re-authorizing) an OAuth 2.0 Client */ public void setAuthorizedClientProvider(ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider) { Assert.notNull(authorizedClientProvider, "authorizedClientProvider cannot be null"); @@ -229,13 +236,15 @@ public final class DefaultReactiveOAuth2AuthorizedClientManager implements React } /** - * Sets the {@code Function} used for mapping attribute(s) from the {@link OAuth2AuthorizeRequest} to a {@code Map} of attributes - * to be associated to the {@link OAuth2AuthorizationContext#getAttributes() authorization context}. - * - * @param contextAttributesMapper the {@code Function} used for supplying the {@code Map} of attributes - * to the {@link OAuth2AuthorizationContext#getAttributes() authorization context} + * Sets the {@code Function} used for mapping attribute(s) from the + * {@link OAuth2AuthorizeRequest} to a {@code Map} of attributes to be associated to + * the {@link OAuth2AuthorizationContext#getAttributes() authorization context}. + * @param contextAttributesMapper the {@code Function} used for supplying the + * {@code Map} of attributes to the {@link OAuth2AuthorizationContext#getAttributes() + * authorization context} */ - public void setContextAttributesMapper(Function>> contextAttributesMapper) { + public void setContextAttributesMapper( + Function>> contextAttributesMapper) { Assert.notNull(contextAttributesMapper, "contextAttributesMapper cannot be null"); this.contextAttributesMapper = contextAttributesMapper; } @@ -243,9 +252,10 @@ public final class DefaultReactiveOAuth2AuthorizedClientManager implements React /** * Sets the handler that handles successful authorizations. * - * The default saves {@link OAuth2AuthorizedClient}s in the {@link ServerOAuth2AuthorizedClientRepository}. - * - * @param authorizationSuccessHandler the handler that handles successful authorizations. + * The default saves {@link OAuth2AuthorizedClient}s in the + * {@link ServerOAuth2AuthorizedClientRepository}. + * @param authorizationSuccessHandler the handler that handles successful + * authorizations. * @since 5.3 */ public void setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler authorizationSuccessHandler) { @@ -256,9 +266,10 @@ public final class DefaultReactiveOAuth2AuthorizedClientManager implements React /** * Sets the handler that handles authorization failures. * - *

        A {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} - * is used by default.

        - * + *

        + * A {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} is used + * by default. + *

        * @param authorizationFailureHandler the handler that handles authorization failures. * @see RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler * @since 5.3 @@ -269,26 +280,27 @@ public final class DefaultReactiveOAuth2AuthorizedClientManager implements React } /** - * The default implementation of the {@link #setContextAttributesMapper(Function) contextAttributesMapper}. + * The default implementation of the {@link #setContextAttributesMapper(Function) + * contextAttributesMapper}. */ - public static class DefaultContextAttributesMapper implements Function>> { + public static class DefaultContextAttributesMapper + implements Function>> { @Override public Mono> apply(OAuth2AuthorizeRequest authorizeRequest) { ServerWebExchange serverWebExchange = authorizeRequest.getAttribute(ServerWebExchange.class.getName()); - return Mono.justOrEmpty(serverWebExchange) - .switchIfEmpty(currentServerWebExchangeMono) - .flatMap(exchange -> { - Map contextAttributes = Collections.emptyMap(); - String scope = exchange.getRequest().getQueryParams().getFirst(OAuth2ParameterNames.SCOPE); - if (StringUtils.hasText(scope)) { - contextAttributes = new HashMap<>(); - contextAttributes.put(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME, - StringUtils.delimitedListToStringArray(scope, " ")); - } - return Mono.just(contextAttributes); - }) - .defaultIfEmpty(Collections.emptyMap()); + return Mono.justOrEmpty(serverWebExchange).switchIfEmpty(currentServerWebExchangeMono).flatMap(exchange -> { + Map contextAttributes = Collections.emptyMap(); + String scope = exchange.getRequest().getQueryParams().getFirst(OAuth2ParameterNames.SCOPE); + if (StringUtils.hasText(scope)) { + contextAttributes = new HashMap<>(); + contextAttributes.put(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME, + StringUtils.delimitedListToStringArray(scope, " ")); + } + return Mono.just(contextAttributes); + }).defaultIfEmpty(Collections.emptyMap()); } + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizationRequestRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizationRequestRepository.java index 58ea54f53e..9ff3664282 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizationRequestRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizationRequestRepository.java @@ -35,9 +35,11 @@ import java.util.Map; * @see AuthorizationRequestRepository * @see OAuth2AuthorizationRequest */ -public final class HttpSessionOAuth2AuthorizationRequestRepository implements AuthorizationRequestRepository { - private static final String DEFAULT_AUTHORIZATION_REQUEST_ATTR_NAME = - HttpSessionOAuth2AuthorizationRequestRepository.class.getName() + ".AUTHORIZATION_REQUEST"; +public final class HttpSessionOAuth2AuthorizationRequestRepository + implements AuthorizationRequestRepository { + + private static final String DEFAULT_AUTHORIZATION_REQUEST_ATTR_NAME = HttpSessionOAuth2AuthorizationRequestRepository.class + .getName() + ".AUTHORIZATION_REQUEST"; private final String sessionAttributeName = DEFAULT_AUTHORIZATION_REQUEST_ATTR_NAME; @@ -54,7 +56,7 @@ public final class HttpSessionOAuth2AuthorizationRequestRepository implements Au @Override public void saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest, HttpServletRequest request, - HttpServletResponse response) { + HttpServletResponse response) { Assert.notNull(request, "request cannot be null"); Assert.notNull(response, "response cannot be null"); if (authorizationRequest == null) { @@ -79,14 +81,16 @@ public final class HttpSessionOAuth2AuthorizationRequestRepository implements Au OAuth2AuthorizationRequest originalRequest = authorizationRequests.remove(stateParameter); if (!authorizationRequests.isEmpty()) { request.getSession().setAttribute(this.sessionAttributeName, authorizationRequests); - } else { + } + else { request.getSession().removeAttribute(this.sessionAttributeName); } return originalRequest; } @Override - public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request, HttpServletResponse response) { + public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request, + HttpServletResponse response) { Assert.notNull(response, "response cannot be null"); return this.removeAuthorizationRequest(request); } @@ -101,17 +105,20 @@ public final class HttpSessionOAuth2AuthorizationRequestRepository implements Au } /** - * Gets a non-null and mutable map of {@link OAuth2AuthorizationRequest#getState()} to an {@link OAuth2AuthorizationRequest} + * Gets a non-null and mutable map of {@link OAuth2AuthorizationRequest#getState()} to + * an {@link OAuth2AuthorizationRequest} * @param request - * @return a non-null and mutable map of {@link OAuth2AuthorizationRequest#getState()} to an {@link OAuth2AuthorizationRequest}. + * @return a non-null and mutable map of {@link OAuth2AuthorizationRequest#getState()} + * to an {@link OAuth2AuthorizationRequest}. */ private Map getAuthorizationRequests(HttpServletRequest request) { HttpSession session = request.getSession(false); - Map authorizationRequests = session == null ? null : - (Map) session.getAttribute(this.sessionAttributeName); + Map authorizationRequests = session == null ? null + : (Map) session.getAttribute(this.sessionAttributeName); if (authorizationRequests == null) { return new HashMap<>(); } return authorizationRequests; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizedClientRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizedClientRepository.java index 6d608cf066..ea3e519712 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizedClientRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizedClientRepository.java @@ -35,14 +35,16 @@ import java.util.Map; * @see OAuth2AuthorizedClient */ public final class HttpSessionOAuth2AuthorizedClientRepository implements OAuth2AuthorizedClientRepository { - private static final String DEFAULT_AUTHORIZED_CLIENTS_ATTR_NAME = - HttpSessionOAuth2AuthorizedClientRepository.class.getName() + ".AUTHORIZED_CLIENTS"; + + private static final String DEFAULT_AUTHORIZED_CLIENTS_ATTR_NAME = HttpSessionOAuth2AuthorizedClientRepository.class + .getName() + ".AUTHORIZED_CLIENTS"; + private final String sessionAttributeName = DEFAULT_AUTHORIZED_CLIENTS_ATTR_NAME; @SuppressWarnings("unchecked") @Override - public T loadAuthorizedClient(String clientRegistrationId, Authentication principal, - HttpServletRequest request) { + public T loadAuthorizedClient(String clientRegistrationId, + Authentication principal, HttpServletRequest request) { Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty"); Assert.notNull(request, "request cannot be null"); return (T) this.getAuthorizedClients(request).get(clientRegistrationId); @@ -50,7 +52,7 @@ public final class HttpSessionOAuth2AuthorizedClientRepository implements OAuth2 @Override public void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal, - HttpServletRequest request, HttpServletResponse response) { + HttpServletRequest request, HttpServletResponse response) { Assert.notNull(authorizedClient, "authorizedClient cannot be null"); Assert.notNull(request, "request cannot be null"); Assert.notNull(response, "response cannot be null"); @@ -61,7 +63,7 @@ public final class HttpSessionOAuth2AuthorizedClientRepository implements OAuth2 @Override public void removeAuthorizedClient(String clientRegistrationId, Authentication principal, - HttpServletRequest request, HttpServletResponse response) { + HttpServletRequest request, HttpServletResponse response) { Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty"); Assert.notNull(request, "request cannot be null"); Map authorizedClients = this.getAuthorizedClients(request); @@ -69,7 +71,8 @@ public final class HttpSessionOAuth2AuthorizedClientRepository implements OAuth2 if (authorizedClients.remove(clientRegistrationId) != null) { if (!authorizedClients.isEmpty()) { request.getSession().setAttribute(this.sessionAttributeName, authorizedClients); - } else { + } + else { request.getSession().removeAttribute(this.sessionAttributeName); } } @@ -79,11 +82,12 @@ public final class HttpSessionOAuth2AuthorizedClientRepository implements OAuth2 @SuppressWarnings("unchecked") private Map getAuthorizedClients(HttpServletRequest request) { HttpSession session = request.getSession(false); - Map authorizedClients = session == null ? null : - (Map) session.getAttribute(this.sessionAttributeName); + Map authorizedClients = session == null ? null + : (Map) session.getAttribute(this.sessionAttributeName); if (authorizedClients == null) { authorizedClients = new HashMap<>(); } return authorizedClients; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationCodeGrantFilter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationCodeGrantFilter.java index 8d2f157c45..96be281fba 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationCodeGrantFilter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationCodeGrantFilter.java @@ -56,30 +56,29 @@ import java.util.Objects; import java.util.Set; /** - * A {@code Filter} for the OAuth 2.0 Authorization Code Grant, - * which handles the processing of the OAuth 2.0 Authorization Response. + * A {@code Filter} for the OAuth 2.0 Authorization Code Grant, which handles the + * processing of the OAuth 2.0 Authorization Response. * *

        * The OAuth 2.0 Authorization Response is processed as follows: * *

          - *
        • - * Assuming the End-User (Resource Owner) has granted access to the Client, the Authorization Server will append the - * {@link OAuth2ParameterNames#CODE code} and {@link OAuth2ParameterNames#STATE state} parameters - * to the {@link OAuth2ParameterNames#REDIRECT_URI redirect_uri} (provided in the Authorization Request) - * and redirect the End-User's user-agent back to this {@code Filter} (the Client). - *
        • - *
        • - * This {@code Filter} will then create an {@link OAuth2AuthorizationCodeAuthenticationToken} with - * the {@link OAuth2ParameterNames#CODE code} received and - * delegate it to the {@link AuthenticationManager} to authenticate. - *
        • - *
        • - * Upon a successful authentication, an {@link OAuth2AuthorizedClient Authorized Client} is created by associating the - * {@link OAuth2AuthorizationCodeAuthenticationToken#getClientRegistration() client} to the - * {@link OAuth2AuthorizationCodeAuthenticationToken#getAccessToken() access token} and current {@code Principal} - * and saving it via the {@link OAuth2AuthorizedClientRepository}. - *
        • + *
        • Assuming the End-User (Resource Owner) has granted access to the Client, the + * Authorization Server will append the {@link OAuth2ParameterNames#CODE code} and + * {@link OAuth2ParameterNames#STATE state} parameters to the + * {@link OAuth2ParameterNames#REDIRECT_URI redirect_uri} (provided in the Authorization + * Request) and redirect the End-User's user-agent back to this {@code Filter} (the + * Client).
        • + *
        • This {@code Filter} will then create an + * {@link OAuth2AuthorizationCodeAuthenticationToken} with the + * {@link OAuth2ParameterNames#CODE code} received and delegate it to the + * {@link AuthenticationManager} to authenticate.
        • + *
        • Upon a successful authentication, an {@link OAuth2AuthorizedClient Authorized + * Client} is created by associating the + * {@link OAuth2AuthorizationCodeAuthenticationToken#getClientRegistration() client} to + * the {@link OAuth2AuthorizationCodeAuthenticationToken#getAccessToken() access token} + * and current {@code Principal} and saving it via the + * {@link OAuth2AuthorizedClientRepository}.
        • *
        * * @author Joe Grandja @@ -94,29 +93,37 @@ import java.util.Set; * @see ClientRegistrationRepository * @see OAuth2AuthorizedClient * @see OAuth2AuthorizedClientRepository - * @see Section 4.1 Authorization Code Grant - * @see Section 4.1.2 Authorization Response + * @see Section + * 4.1 Authorization Code Grant + * @see Section 4.1.2 Authorization + * Response */ public class OAuth2AuthorizationCodeGrantFilter extends OncePerRequestFilter { + private final ClientRegistrationRepository clientRegistrationRepository; + private final OAuth2AuthorizedClientRepository authorizedClientRepository; + private final AuthenticationManager authenticationManager; - private AuthorizationRequestRepository authorizationRequestRepository = - new HttpSessionOAuth2AuthorizationRequestRepository(); + + private AuthorizationRequestRepository authorizationRequestRepository = new HttpSessionOAuth2AuthorizationRequestRepository(); + private final AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); + private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); + private RequestCache requestCache = new HttpSessionRequestCache(); /** - * Constructs an {@code OAuth2AuthorizationCodeGrantFilter} using the provided parameters. - * + * Constructs an {@code OAuth2AuthorizationCodeGrantFilter} using the provided + * parameters. * @param clientRegistrationRepository the repository of client registrations * @param authorizedClientRepository the authorized client repository * @param authenticationManager the authentication manager */ public OAuth2AuthorizationCodeGrantFilter(ClientRegistrationRepository clientRegistrationRepository, - OAuth2AuthorizedClientRepository authorizedClientRepository, - AuthenticationManager authenticationManager) { + OAuth2AuthorizedClientRepository authorizedClientRepository, AuthenticationManager authenticationManager) { Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null"); Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null"); Assert.notNull(authenticationManager, "authenticationManager cannot be null"); @@ -127,20 +134,23 @@ public class OAuth2AuthorizationCodeGrantFilter extends OncePerRequestFilter { /** * Sets the repository for stored {@link OAuth2AuthorizationRequest}'s. - * - * @param authorizationRequestRepository the repository for stored {@link OAuth2AuthorizationRequest}'s + * @param authorizationRequestRepository the repository for stored + * {@link OAuth2AuthorizationRequest}'s */ - public final void setAuthorizationRequestRepository(AuthorizationRequestRepository authorizationRequestRepository) { + public final void setAuthorizationRequestRepository( + AuthorizationRequestRepository authorizationRequestRepository) { Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null"); this.authorizationRequestRepository = authorizationRequestRepository; } /** - * Sets the {@link RequestCache} used for loading a previously saved request (if available) - * and replaying it after completing the processing of the OAuth 2.0 Authorization Response. + * Sets the {@link RequestCache} used for loading a previously saved request (if + * available) and replaying it after completing the processing of the OAuth 2.0 + * Authorization Response. * * @since 5.4 - * @param requestCache the cache used for loading a previously saved request (if available) + * @param requestCache the cache used for loading a previously saved request (if + * available) */ public final void setRequestCache(RequestCache requestCache) { Assert.notNull(requestCache, "requestCache cannot be null"); @@ -149,7 +159,7 @@ public class OAuth2AuthorizationCodeGrantFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) - throws ServletException, IOException { + throws ServletException, IOException { if (matchesAuthorizationResponse(request)) { processAuthorizationResponse(request, response); @@ -164,7 +174,8 @@ public class OAuth2AuthorizationCodeGrantFilter extends OncePerRequestFilter { if (!OAuth2AuthorizationResponseUtils.isAuthorizationResponse(params)) { return false; } - OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestRepository.loadAuthorizationRequest(request); + OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestRepository + .loadAuthorizationRequest(request); if (authorizationRequest == null) { return false; } @@ -172,50 +183,55 @@ public class OAuth2AuthorizationCodeGrantFilter extends OncePerRequestFilter { // Compare redirect_uri UriComponents requestUri = UriComponentsBuilder.fromUriString(UrlUtils.buildFullRequestUrl(request)).build(); UriComponents redirectUri = UriComponentsBuilder.fromUriString(authorizationRequest.getRedirectUri()).build(); - Set>> requestUriParameters = new LinkedHashSet<>(requestUri.getQueryParams().entrySet()); - Set>> redirectUriParameters = new LinkedHashSet<>(redirectUri.getQueryParams().entrySet()); - // Remove the additional request parameters (if any) from the authorization response (request) - // before doing an exact comparison with the authorizationRequest.getRedirectUri() parameters (if any) + Set>> requestUriParameters = new LinkedHashSet<>( + requestUri.getQueryParams().entrySet()); + Set>> redirectUriParameters = new LinkedHashSet<>( + redirectUri.getQueryParams().entrySet()); + // Remove the additional request parameters (if any) from the authorization + // response (request) + // before doing an exact comparison with the authorizationRequest.getRedirectUri() + // parameters (if any) requestUriParameters.retainAll(redirectUriParameters); - if (Objects.equals(requestUri.getScheme(), redirectUri.getScheme()) && - Objects.equals(requestUri.getUserInfo(), redirectUri.getUserInfo()) && - Objects.equals(requestUri.getHost(), redirectUri.getHost()) && - Objects.equals(requestUri.getPort(), redirectUri.getPort()) && - Objects.equals(requestUri.getPath(), redirectUri.getPath()) && - Objects.equals(requestUriParameters.toString(), redirectUriParameters.toString())) { + if (Objects.equals(requestUri.getScheme(), redirectUri.getScheme()) + && Objects.equals(requestUri.getUserInfo(), redirectUri.getUserInfo()) + && Objects.equals(requestUri.getHost(), redirectUri.getHost()) + && Objects.equals(requestUri.getPort(), redirectUri.getPort()) + && Objects.equals(requestUri.getPath(), redirectUri.getPath()) + && Objects.equals(requestUriParameters.toString(), redirectUriParameters.toString())) { return true; } return false; } private void processAuthorizationResponse(HttpServletRequest request, HttpServletResponse response) - throws IOException { + throws IOException { - OAuth2AuthorizationRequest authorizationRequest = - this.authorizationRequestRepository.removeAuthorizationRequest(request, response); + OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestRepository + .removeAuthorizationRequest(request, response); String registrationId = authorizationRequest.getAttribute(OAuth2ParameterNames.REGISTRATION_ID); ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(registrationId); MultiValueMap params = OAuth2AuthorizationResponseUtils.toMultiMap(request.getParameterMap()); String redirectUri = UrlUtils.buildFullRequestUrl(request); - OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponseUtils.convert(params, redirectUri); + OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponseUtils.convert(params, + redirectUri); OAuth2AuthorizationCodeAuthenticationToken authenticationRequest = new OAuth2AuthorizationCodeAuthenticationToken( - clientRegistration, new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse)); + clientRegistration, new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse)); authenticationRequest.setDetails(this.authenticationDetailsSource.buildDetails(request)); OAuth2AuthorizationCodeAuthenticationToken authenticationResult; try { - authenticationResult = (OAuth2AuthorizationCodeAuthenticationToken) - this.authenticationManager.authenticate(authenticationRequest); - } catch (OAuth2AuthorizationException ex) { + authenticationResult = (OAuth2AuthorizationCodeAuthenticationToken) this.authenticationManager + .authenticate(authenticationRequest); + } + catch (OAuth2AuthorizationException ex) { OAuth2Error error = ex.getError(); - UriComponentsBuilder uriBuilder = UriComponentsBuilder - .fromUriString(authorizationRequest.getRedirectUri()) - .queryParam(OAuth2ParameterNames.ERROR, error.getErrorCode()); + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(authorizationRequest.getRedirectUri()) + .queryParam(OAuth2ParameterNames.ERROR, error.getErrorCode()); if (!StringUtils.isEmpty(error.getDescription())) { uriBuilder.queryParam(OAuth2ParameterNames.ERROR_DESCRIPTION, error.getDescription()); } @@ -230,12 +246,11 @@ public class OAuth2AuthorizationCodeGrantFilter extends OncePerRequestFilter { String principalName = currentAuthentication != null ? currentAuthentication.getName() : "anonymousUser"; OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - authenticationResult.getClientRegistration(), - principalName, - authenticationResult.getAccessToken(), - authenticationResult.getRefreshToken()); + authenticationResult.getClientRegistration(), principalName, authenticationResult.getAccessToken(), + authenticationResult.getRefreshToken()); - this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, currentAuthentication, request, response); + this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, currentAuthentication, request, + response); String redirectUrl = authorizationRequest.getRedirectUri(); SavedRequest savedRequest = this.requestCache.getRequest(request, response); @@ -246,4 +261,5 @@ public class OAuth2AuthorizationCodeGrantFilter extends OncePerRequestFilter { this.redirectStrategy.sendRedirect(request, response, redirectUrl); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilter.java index 0953200255..2544f57fa5 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilter.java @@ -36,31 +36,34 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** - * This {@code Filter} initiates the authorization code grant or implicit grant flow - * by redirecting the End-User's user-agent to the Authorization Server's Authorization Endpoint. + * This {@code Filter} initiates the authorization code grant or implicit grant flow by + * redirecting the End-User's user-agent to the Authorization Server's Authorization + * Endpoint. * *

        - * It builds the OAuth 2.0 Authorization Request, - * which is used as the redirect {@code URI} to the Authorization Endpoint. - * The redirect {@code URI} will include the client identifier, requested scope(s), state, - * response type, and a redirection URI which the authorization server will send the user-agent back to - * once access is granted (or denied) by the End-User (Resource Owner). + * It builds the OAuth 2.0 Authorization Request, which is used as the redirect + * {@code URI} to the Authorization Endpoint. The redirect {@code URI} will include the + * client identifier, requested scope(s), state, response type, and a redirection URI + * which the authorization server will send the user-agent back to once access is granted + * (or denied) by the End-User (Resource Owner). * *

        - * By default, this {@code Filter} responds to authorization requests - * at the {@code URI} {@code /oauth2/authorization/{registrationId}} - * using the default {@link OAuth2AuthorizationRequestResolver}. - * The {@code URI} template variable {@code {registrationId}} represents the - * {@link ClientRegistration#getRegistrationId() registration identifier} of the client - * that is used for initiating the OAuth 2.0 Authorization Request. + * By default, this {@code Filter} responds to authorization requests at the {@code URI} + * {@code /oauth2/authorization/{registrationId}} using the default + * {@link OAuth2AuthorizationRequestResolver}. The {@code URI} template variable + * {@code {registrationId}} represents the {@link ClientRegistration#getRegistrationId() + * registration identifier} of the client that is used for initiating the OAuth 2.0 + * Authorization Request. * *

        - * The default base {@code URI} {@code /oauth2/authorization} may be overridden - * via the constructor {@link #OAuth2AuthorizationRequestRedirectFilter(ClientRegistrationRepository, String)}, - * or alternatively, an {@code OAuth2AuthorizationRequestResolver} may be provided to the constructor + * The default base {@code URI} {@code /oauth2/authorization} may be overridden via the + * constructor + * {@link #OAuth2AuthorizationRequestRedirectFilter(ClientRegistrationRepository, String)}, + * or alternatively, an {@code OAuth2AuthorizationRequestResolver} may be provided to the + * constructor * {@link #OAuth2AuthorizationRequestRedirectFilter(OAuth2AuthorizationRequestResolver)} * to override the resolving of authorization requests. - + * * @author Joe Grandja * @author Rob Winch * @since 5.0 @@ -69,26 +72,37 @@ import java.io.IOException; * @see AuthorizationRequestRepository * @see ClientRegistration * @see ClientRegistrationRepository - * @see Section 4.1 Authorization Code Grant - * @see Section 4.1.1 Authorization Request (Authorization Code) - * @see Section 4.2 Implicit Grant - * @see Section 4.2.1 Authorization Request (Implicit) + * @see Section + * 4.1 Authorization Code Grant + * @see Section 4.1.1 Authorization Request + * (Authorization Code) + * @see Section + * 4.2 Implicit Grant + * @see Section 4.2.1 Authorization Request + * (Implicit) */ public class OAuth2AuthorizationRequestRedirectFilter extends OncePerRequestFilter { + /** * The default base {@code URI} used for authorization requests. */ public static final String DEFAULT_AUTHORIZATION_REQUEST_BASE_URI = "/oauth2/authorization"; + private final ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer(); + private final RedirectStrategy authorizationRedirectStrategy = new DefaultRedirectStrategy(); + private OAuth2AuthorizationRequestResolver authorizationRequestResolver; - private AuthorizationRequestRepository authorizationRequestRepository = - new HttpSessionOAuth2AuthorizationRequestRepository(); + + private AuthorizationRequestRepository authorizationRequestRepository = new HttpSessionOAuth2AuthorizationRequestRepository(); + private RequestCache requestCache = new HttpSessionRequestCache(); /** - * Constructs an {@code OAuth2AuthorizationRequestRedirectFilter} using the provided parameters. - * + * Constructs an {@code OAuth2AuthorizationRequestRedirectFilter} using the provided + * parameters. * @param clientRegistrationRepository the repository of client registrations */ public OAuth2AuthorizationRequestRedirectFilter(ClientRegistrationRepository clientRegistrationRepository) { @@ -96,24 +110,27 @@ public class OAuth2AuthorizationRequestRedirectFilter extends OncePerRequestFilt } /** - * Constructs an {@code OAuth2AuthorizationRequestRedirectFilter} using the provided parameters. - * + * Constructs an {@code OAuth2AuthorizationRequestRedirectFilter} using the provided + * parameters. * @param clientRegistrationRepository the repository of client registrations - * @param authorizationRequestBaseUri the base {@code URI} used for authorization requests + * @param authorizationRequestBaseUri the base {@code URI} used for authorization + * requests */ public OAuth2AuthorizationRequestRedirectFilter(ClientRegistrationRepository clientRegistrationRepository, - String authorizationRequestBaseUri) { + String authorizationRequestBaseUri) { Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null"); Assert.hasText(authorizationRequestBaseUri, "authorizationRequestBaseUri cannot be empty"); - this.authorizationRequestResolver = new DefaultOAuth2AuthorizationRequestResolver( - clientRegistrationRepository, authorizationRequestBaseUri); + this.authorizationRequestResolver = new DefaultOAuth2AuthorizationRequestResolver(clientRegistrationRepository, + authorizationRequestBaseUri); } /** - * Constructs an {@code OAuth2AuthorizationRequestRedirectFilter} using the provided parameters. + * Constructs an {@code OAuth2AuthorizationRequestRedirectFilter} using the provided + * parameters. * * @since 5.1 - * @param authorizationRequestResolver the resolver used for resolving authorization requests + * @param authorizationRequestResolver the resolver used for resolving authorization + * requests */ public OAuth2AuthorizationRequestRedirectFilter(OAuth2AuthorizationRequestResolver authorizationRequestResolver) { Assert.notNull(authorizationRequestResolver, "authorizationRequestResolver cannot be null"); @@ -122,18 +139,18 @@ public class OAuth2AuthorizationRequestRedirectFilter extends OncePerRequestFilt /** * Sets the repository used for storing {@link OAuth2AuthorizationRequest}'s. - * - * @param authorizationRequestRepository the repository used for storing {@link OAuth2AuthorizationRequest}'s + * @param authorizationRequestRepository the repository used for storing + * {@link OAuth2AuthorizationRequest}'s */ - public final void setAuthorizationRequestRepository(AuthorizationRequestRepository authorizationRequestRepository) { + public final void setAuthorizationRequestRepository( + AuthorizationRequestRepository authorizationRequestRepository) { Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null"); this.authorizationRequestRepository = authorizationRequestRepository; } /** - * Sets the {@link RequestCache} used for storing the current request - * before redirecting the OAuth 2.0 Authorization Request. - * + * Sets the {@link RequestCache} used for storing the current request before + * redirecting the OAuth 2.0 Authorization Request. * @param requestCache the cache used for storing the current request */ public final void setRequestCache(RequestCache requestCache) { @@ -151,29 +168,34 @@ public class OAuth2AuthorizationRequestRedirectFilter extends OncePerRequestFilt this.sendRedirectForAuthorization(request, response, authorizationRequest); return; } - } catch (Exception failed) { + } + catch (Exception failed) { this.unsuccessfulRedirectForAuthorization(request, response, failed); return; } try { filterChain.doFilter(request, response); - } catch (IOException ex) { + } + catch (IOException ex) { throw ex; - } catch (Exception ex) { + } + catch (Exception ex) { // Check to see if we need to handle ClientAuthorizationRequiredException Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(ex); ClientAuthorizationRequiredException authzEx = (ClientAuthorizationRequiredException) this.throwableAnalyzer - .getFirstThrowableOfType(ClientAuthorizationRequiredException.class, causeChain); + .getFirstThrowableOfType(ClientAuthorizationRequiredException.class, causeChain); if (authzEx != null) { try { - OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestResolver.resolve(request, authzEx.getClientRegistrationId()); + OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestResolver.resolve(request, + authzEx.getClientRegistrationId()); if (authorizationRequest == null) { throw authzEx; } this.sendRedirectForAuthorization(request, response, authorizationRequest); this.requestCache.saveRequest(request, response); - } catch (Exception failed) { + } + catch (Exception failed) { this.unsuccessfulRedirectForAuthorization(request, response, failed); } return; @@ -181,33 +203,38 @@ public class OAuth2AuthorizationRequestRedirectFilter extends OncePerRequestFilt if (ex instanceof ServletException) { throw (ServletException) ex; - } else if (ex instanceof RuntimeException) { + } + else if (ex instanceof RuntimeException) { throw (RuntimeException) ex; - } else { + } + else { throw new RuntimeException(ex); } } } private void sendRedirectForAuthorization(HttpServletRequest request, HttpServletResponse response, - OAuth2AuthorizationRequest authorizationRequest) throws IOException { + OAuth2AuthorizationRequest authorizationRequest) throws IOException { if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(authorizationRequest.getGrantType())) { this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, request, response); } - this.authorizationRedirectStrategy.sendRedirect(request, response, authorizationRequest.getAuthorizationRequestUri()); + this.authorizationRedirectStrategy.sendRedirect(request, response, + authorizationRequest.getAuthorizationRequestUri()); } private void unsuccessfulRedirectForAuthorization(HttpServletRequest request, HttpServletResponse response, - Exception failed) throws IOException { + Exception failed) throws IOException { if (logger.isErrorEnabled()) { logger.error("Authorization Request failed: " + failed.toString(), failed); } - response.sendError(HttpStatus.INTERNAL_SERVER_ERROR.value(), HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase()); + response.sendError(HttpStatus.INTERNAL_SERVER_ERROR.value(), + HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase()); } private static final class DefaultThrowableAnalyzer extends ThrowableAnalyzer { + protected void initExtractorMap() { super.initExtractorMap(); registerExtractor(ServletException.class, throwable -> { @@ -215,5 +242,7 @@ public class OAuth2AuthorizationRequestRedirectFilter extends OncePerRequestFilt return ((ServletException) throwable).getRootCause(); }); } + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestResolver.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestResolver.java index 10940c2373..372dfd290a 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestResolver.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestResolver.java @@ -20,9 +20,10 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequ import javax.servlet.http.HttpServletRequest; /** - * Implementations of this interface are capable of resolving - * an {@link OAuth2AuthorizationRequest} from the provided {@code HttpServletRequest}. - * Used by the {@link OAuth2AuthorizationRequestRedirectFilter} for resolving Authorization Requests. + * Implementations of this interface are capable of resolving an + * {@link OAuth2AuthorizationRequest} from the provided {@code HttpServletRequest}. Used + * by the {@link OAuth2AuthorizationRequestRedirectFilter} for resolving Authorization + * Requests. * * @author Joe Grandja * @author Rob Winch @@ -33,21 +34,21 @@ import javax.servlet.http.HttpServletRequest; public interface OAuth2AuthorizationRequestResolver { /** - * Returns the {@link OAuth2AuthorizationRequest} resolved from - * the provided {@code HttpServletRequest} or {@code null} if not available. - * + * Returns the {@link OAuth2AuthorizationRequest} resolved from the provided + * {@code HttpServletRequest} or {@code null} if not available. * @param request the {@code HttpServletRequest} - * @return the resolved {@link OAuth2AuthorizationRequest} or {@code null} if not available + * @return the resolved {@link OAuth2AuthorizationRequest} or {@code null} if not + * available */ OAuth2AuthorizationRequest resolve(HttpServletRequest request); /** - * Returns the {@link OAuth2AuthorizationRequest} resolved from - * the provided {@code HttpServletRequest} or {@code null} if not available. - * + * Returns the {@link OAuth2AuthorizationRequest} resolved from the provided + * {@code HttpServletRequest} or {@code null} if not available. * @param request the {@code HttpServletRequest} * @param clientRegistrationId the clientRegistrationId to use - * @return the resolved {@link OAuth2AuthorizationRequest} or {@code null} if not available + * @return the resolved {@link OAuth2AuthorizationRequest} or {@code null} if not + * available */ OAuth2AuthorizationRequest resolve(HttpServletRequest request, String clientRegistrationId); diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationResponseUtils.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationResponseUtils.java index 5443c895fb..23bcd88174 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationResponseUtils.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationResponseUtils.java @@ -52,13 +52,13 @@ final class OAuth2AuthorizationResponseUtils { } static boolean isAuthorizationResponseSuccess(MultiValueMap request) { - return StringUtils.hasText(request.getFirst(OAuth2ParameterNames.CODE)) && - StringUtils.hasText(request.getFirst(OAuth2ParameterNames.STATE)); + return StringUtils.hasText(request.getFirst(OAuth2ParameterNames.CODE)) + && StringUtils.hasText(request.getFirst(OAuth2ParameterNames.STATE)); } static boolean isAuthorizationResponseError(MultiValueMap request) { - return StringUtils.hasText(request.getFirst(OAuth2ParameterNames.ERROR)) && - StringUtils.hasText(request.getFirst(OAuth2ParameterNames.STATE)); + return StringUtils.hasText(request.getFirst(OAuth2ParameterNames.ERROR)) + && StringUtils.hasText(request.getFirst(OAuth2ParameterNames.STATE)); } static OAuth2AuthorizationResponse convert(MultiValueMap request, String redirectUri) { @@ -67,19 +67,14 @@ final class OAuth2AuthorizationResponseUtils { String state = request.getFirst(OAuth2ParameterNames.STATE); if (StringUtils.hasText(code)) { - return OAuth2AuthorizationResponse.success(code) - .redirectUri(redirectUri) - .state(state) - .build(); - } else { + return OAuth2AuthorizationResponse.success(code).redirectUri(redirectUri).state(state).build(); + } + else { String errorDescription = request.getFirst(OAuth2ParameterNames.ERROR_DESCRIPTION); String errorUri = request.getFirst(OAuth2ParameterNames.ERROR_URI); - return OAuth2AuthorizationResponse.error(errorCode) - .redirectUri(redirectUri) - .errorDescription(errorDescription) - .errorUri(errorUri) - .state(state) - .build(); + return OAuth2AuthorizationResponse.error(errorCode).redirectUri(redirectUri) + .errorDescription(errorDescription).errorUri(errorUri).state(state).build(); } } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizedClientRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizedClientRepository.java index b509f614dc..459c3f966e 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizedClientRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizedClientRepository.java @@ -24,15 +24,15 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** - * Implementations of this interface are responsible for the persistence - * of {@link OAuth2AuthorizedClient Authorized Client(s)} between requests. + * Implementations of this interface are responsible for the persistence of + * {@link OAuth2AuthorizedClient Authorized Client(s)} between requests. * *

        - * The primary purpose of an {@link OAuth2AuthorizedClient Authorized Client} - * is to associate an {@link OAuth2AuthorizedClient#getAccessToken() Access Token} credential - * to a {@link OAuth2AuthorizedClient#getClientRegistration() Client} and Resource Owner, - * who is the {@link OAuth2AuthorizedClient#getPrincipalName() Principal} - * that originally granted the authorization. + * The primary purpose of an {@link OAuth2AuthorizedClient Authorized Client} is to + * associate an {@link OAuth2AuthorizedClient#getAccessToken() Access Token} credential to + * a {@link OAuth2AuthorizedClient#getClientRegistration() Client} and Resource Owner, who + * is the {@link OAuth2AuthorizedClient#getPrincipalName() Principal} that originally + * granted the authorization. * * @author Joe Grandja * @since 5.1 @@ -44,10 +44,9 @@ import javax.servlet.http.HttpServletResponse; public interface OAuth2AuthorizedClientRepository { /** - * Returns the {@link OAuth2AuthorizedClient} associated to the - * provided client registration identifier and End-User {@link Authentication} (Resource Owner) - * or {@code null} if not available. - * + * Returns the {@link OAuth2AuthorizedClient} associated to the provided client + * registration identifier and End-User {@link Authentication} (Resource Owner) or + * {@code null} if not available. * @param clientRegistrationId the identifier for the client's registration * @param principal the End-User {@link Authentication} (Resource Owner) * @param request the {@code HttpServletRequest} @@ -55,30 +54,28 @@ public interface OAuth2AuthorizedClientRepository { * @return the {@link OAuth2AuthorizedClient} or {@code null} if not available */ T loadAuthorizedClient(String clientRegistrationId, Authentication principal, - HttpServletRequest request); + HttpServletRequest request); /** - * Saves the {@link OAuth2AuthorizedClient} associating it to - * the provided End-User {@link Authentication} (Resource Owner). - * + * Saves the {@link OAuth2AuthorizedClient} associating it to the provided End-User + * {@link Authentication} (Resource Owner). * @param authorizedClient the authorized client * @param principal the End-User {@link Authentication} (Resource Owner) * @param request the {@code HttpServletRequest} * @param response the {@code HttpServletResponse} */ void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal, - HttpServletRequest request, HttpServletResponse response); + HttpServletRequest request, HttpServletResponse response); /** - * Removes the {@link OAuth2AuthorizedClient} associated to the - * provided client registration identifier and End-User {@link Authentication} (Resource Owner). - * + * Removes the {@link OAuth2AuthorizedClient} associated to the provided client + * registration identifier and End-User {@link Authentication} (Resource Owner). * @param clientRegistrationId the identifier for the client's registration * @param principal the End-User {@link Authentication} (Resource Owner) * @param request the {@code HttpServletRequest} * @param response the {@code HttpServletResponse} */ - void removeAuthorizedClient(String clientRegistrationId, Authentication principal, - HttpServletRequest request, HttpServletResponse response); + void removeAuthorizedClient(String clientRegistrationId, Authentication principal, HttpServletRequest request, + HttpServletResponse response); } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilter.java index d98922fe3a..b622d9019e 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilter.java @@ -43,36 +43,34 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** - * An implementation of an {@link AbstractAuthenticationProcessingFilter} for OAuth 2.0 Login. + * An implementation of an {@link AbstractAuthenticationProcessingFilter} for OAuth 2.0 + * Login. * *

        - * This authentication {@code Filter} handles the processing of an OAuth 2.0 Authorization Response - * for the authorization code grant flow and delegates an {@link OAuth2LoginAuthenticationToken} - * to the {@link AuthenticationManager} to log in the End-User. + * This authentication {@code Filter} handles the processing of an OAuth 2.0 Authorization + * Response for the authorization code grant flow and delegates an + * {@link OAuth2LoginAuthenticationToken} to the {@link AuthenticationManager} to log in + * the End-User. * *

        * The OAuth 2.0 Authorization Response is processed as follows: * *

          - *
        • - * Assuming the End-User (Resource Owner) has granted access to the Client, the Authorization Server will append the - * {@link OAuth2ParameterNames#CODE code} and {@link OAuth2ParameterNames#STATE state} parameters - * to the {@link OAuth2ParameterNames#REDIRECT_URI redirect_uri} (provided in the Authorization Request) - * and redirect the End-User's user-agent back to this {@code Filter} (the Client). - *
        • - *
        • - * This {@code Filter} will then create an {@link OAuth2LoginAuthenticationToken} with - * the {@link OAuth2ParameterNames#CODE code} received and - * delegate it to the {@link AuthenticationManager} to authenticate. - *
        • - *
        • - * Upon a successful authentication, an {@link OAuth2AuthenticationToken} is created (representing the End-User {@code Principal}) - * and associated to the {@link OAuth2AuthorizedClient Authorized Client} using the {@link OAuth2AuthorizedClientRepository}. - *
        • - *
        • - * Finally, the {@link OAuth2AuthenticationToken} is returned and ultimately stored - * in the {@link SecurityContextRepository} to complete the authentication processing. - *
        • + *
        • Assuming the End-User (Resource Owner) has granted access to the Client, the + * Authorization Server will append the {@link OAuth2ParameterNames#CODE code} and + * {@link OAuth2ParameterNames#STATE state} parameters to the + * {@link OAuth2ParameterNames#REDIRECT_URI redirect_uri} (provided in the Authorization + * Request) and redirect the End-User's user-agent back to this {@code Filter} (the + * Client).
        • + *
        • This {@code Filter} will then create an {@link OAuth2LoginAuthenticationToken} with + * the {@link OAuth2ParameterNames#CODE code} received and delegate it to the + * {@link AuthenticationManager} to authenticate.
        • + *
        • Upon a successful authentication, an {@link OAuth2AuthenticationToken} is created + * (representing the End-User {@code Principal}) and associated to the + * {@link OAuth2AuthorizedClient Authorized Client} using the + * {@link OAuth2AuthorizedClientRepository}.
        • + *
        • Finally, the {@link OAuth2AuthenticationToken} is returned and ultimately stored in + * the {@link SecurityContextRepository} to complete the authentication processing.
        • *
        * * @author Joe Grandja @@ -88,57 +86,68 @@ import javax.servlet.http.HttpServletResponse; * @see ClientRegistrationRepository * @see OAuth2AuthorizedClient * @see OAuth2AuthorizedClientRepository - * @see Section 4.1 Authorization Code Grant - * @see Section 4.1.2 Authorization Response + * @see Section + * 4.1 Authorization Code Grant + * @see Section 4.1.2 Authorization + * Response */ public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProcessingFilter { - /** - * The default {@code URI} where this {@code Filter} processes authentication requests. - */ - public static final String DEFAULT_FILTER_PROCESSES_URI = "/login/oauth2/code/*"; - private static final String AUTHORIZATION_REQUEST_NOT_FOUND_ERROR_CODE = "authorization_request_not_found"; - private static final String CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE = "client_registration_not_found"; - private ClientRegistrationRepository clientRegistrationRepository; - private OAuth2AuthorizedClientRepository authorizedClientRepository; - private AuthorizationRequestRepository authorizationRequestRepository = - new HttpSessionOAuth2AuthorizationRequestRepository(); /** - * Constructs an {@code OAuth2LoginAuthenticationFilter} using the provided parameters. - * + * The default {@code URI} where this {@code Filter} processes authentication + * requests. + */ + public static final String DEFAULT_FILTER_PROCESSES_URI = "/login/oauth2/code/*"; + + private static final String AUTHORIZATION_REQUEST_NOT_FOUND_ERROR_CODE = "authorization_request_not_found"; + + private static final String CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE = "client_registration_not_found"; + + private ClientRegistrationRepository clientRegistrationRepository; + + private OAuth2AuthorizedClientRepository authorizedClientRepository; + + private AuthorizationRequestRepository authorizationRequestRepository = new HttpSessionOAuth2AuthorizationRequestRepository(); + + /** + * Constructs an {@code OAuth2LoginAuthenticationFilter} using the provided + * parameters. * @param clientRegistrationRepository the repository of client registrations * @param authorizedClientService the authorized client service */ public OAuth2LoginAuthenticationFilter(ClientRegistrationRepository clientRegistrationRepository, - OAuth2AuthorizedClientService authorizedClientService) { + OAuth2AuthorizedClientService authorizedClientService) { this(clientRegistrationRepository, authorizedClientService, DEFAULT_FILTER_PROCESSES_URI); } /** - * Constructs an {@code OAuth2LoginAuthenticationFilter} using the provided parameters. - * + * Constructs an {@code OAuth2LoginAuthenticationFilter} using the provided + * parameters. * @param clientRegistrationRepository the repository of client registrations * @param authorizedClientService the authorized client service - * @param filterProcessesUrl the {@code URI} where this {@code Filter} will process the authentication requests + * @param filterProcessesUrl the {@code URI} where this {@code Filter} will process + * the authentication requests */ public OAuth2LoginAuthenticationFilter(ClientRegistrationRepository clientRegistrationRepository, - OAuth2AuthorizedClientService authorizedClientService, - String filterProcessesUrl) { + OAuth2AuthorizedClientService authorizedClientService, String filterProcessesUrl) { this(clientRegistrationRepository, - new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService), filterProcessesUrl); + new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService), + filterProcessesUrl); } /** - * Constructs an {@code OAuth2LoginAuthenticationFilter} using the provided parameters. + * Constructs an {@code OAuth2LoginAuthenticationFilter} using the provided + * parameters. * * @since 5.1 * @param clientRegistrationRepository the repository of client registrations * @param authorizedClientRepository the authorized client repository - * @param filterProcessesUrl the {@code URI} where this {@code Filter} will process the authentication requests + * @param filterProcessesUrl the {@code URI} where this {@code Filter} will process + * the authentication requests */ public OAuth2LoginAuthenticationFilter(ClientRegistrationRepository clientRegistrationRepository, - OAuth2AuthorizedClientRepository authorizedClientRepository, - String filterProcessesUrl) { + OAuth2AuthorizedClientRepository authorizedClientRepository, String filterProcessesUrl) { super(filterProcessesUrl); Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null"); Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null"); @@ -156,8 +165,8 @@ public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProce throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } - OAuth2AuthorizationRequest authorizationRequest = - this.authorizationRequestRepository.removeAuthorizationRequest(request, response); + OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestRepository + .removeAuthorizationRequest(request, response); if (authorizationRequest == null) { OAuth2Error oauth2Error = new OAuth2Error(AUTHORIZATION_REQUEST_NOT_FOUND_ERROR_CODE); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); @@ -170,31 +179,27 @@ public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProce "Client Registration not found with Id: " + registrationId, null); throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString()); } - String redirectUri = UriComponentsBuilder.fromHttpUrl(UrlUtils.buildFullRequestUrl(request)) - .replaceQuery(null) - .build() - .toUriString(); - OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponseUtils.convert(params, redirectUri); + String redirectUri = UriComponentsBuilder.fromHttpUrl(UrlUtils.buildFullRequestUrl(request)).replaceQuery(null) + .build().toUriString(); + OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponseUtils.convert(params, + redirectUri); Object authenticationDetails = this.authenticationDetailsSource.buildDetails(request); - OAuth2LoginAuthenticationToken authenticationRequest = new OAuth2LoginAuthenticationToken( - clientRegistration, new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse)); + OAuth2LoginAuthenticationToken authenticationRequest = new OAuth2LoginAuthenticationToken(clientRegistration, + new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse)); authenticationRequest.setDetails(authenticationDetails); - OAuth2LoginAuthenticationToken authenticationResult = - (OAuth2LoginAuthenticationToken) this.getAuthenticationManager().authenticate(authenticationRequest); + OAuth2LoginAuthenticationToken authenticationResult = (OAuth2LoginAuthenticationToken) this + .getAuthenticationManager().authenticate(authenticationRequest); OAuth2AuthenticationToken oauth2Authentication = new OAuth2AuthenticationToken( - authenticationResult.getPrincipal(), - authenticationResult.getAuthorities(), - authenticationResult.getClientRegistration().getRegistrationId()); + authenticationResult.getPrincipal(), authenticationResult.getAuthorities(), + authenticationResult.getClientRegistration().getRegistrationId()); oauth2Authentication.setDetails(authenticationDetails); OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - authenticationResult.getClientRegistration(), - oauth2Authentication.getName(), - authenticationResult.getAccessToken(), - authenticationResult.getRefreshToken()); + authenticationResult.getClientRegistration(), oauth2Authentication.getName(), + authenticationResult.getAccessToken(), authenticationResult.getRefreshToken()); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, oauth2Authentication, request, response); @@ -203,11 +208,13 @@ public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProce /** * Sets the repository for stored {@link OAuth2AuthorizationRequest}'s. - * - * @param authorizationRequestRepository the repository for stored {@link OAuth2AuthorizationRequest}'s + * @param authorizationRequestRepository the repository for stored + * {@link OAuth2AuthorizationRequest}'s */ - public final void setAuthorizationRequestRepository(AuthorizationRequestRepository authorizationRequestRepository) { + public final void setAuthorizationRequestRepository( + AuthorizationRequestRepository authorizationRequestRepository) { Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null"); this.authorizationRequestRepository = authorizationRequestRepository; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/method/annotation/OAuth2AuthorizedClientArgumentResolver.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/method/annotation/OAuth2AuthorizedClientArgumentResolver.java index 8241f1bce1..c01e94da0c 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/method/annotation/OAuth2AuthorizedClientArgumentResolver.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/method/annotation/OAuth2AuthorizedClientArgumentResolver.java @@ -47,12 +47,12 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** - * An implementation of a {@link HandlerMethodArgumentResolver} that is capable - * of resolving a method parameter to an argument value of type {@link OAuth2AuthorizedClient}. + * An implementation of a {@link HandlerMethodArgumentResolver} that is capable of + * resolving a method parameter to an argument value of type + * {@link OAuth2AuthorizedClient}. * *

        - * For example: - *

        + * For example: 
          * @Controller
          * public class MyController {
          *     @GetMapping("/authorized-client")
        @@ -67,16 +67,21 @@ import javax.servlet.http.HttpServletResponse;
          * @see RegisteredOAuth2AuthorizedClient
          */
         public final class OAuth2AuthorizedClientArgumentResolver implements HandlerMethodArgumentResolver {
        -	private static final Authentication ANONYMOUS_AUTHENTICATION = new AnonymousAuthenticationToken(
        -			"anonymous", "anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
        +
        +	private static final Authentication ANONYMOUS_AUTHENTICATION = new AnonymousAuthenticationToken("anonymous",
        +			"anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
        +
         	private OAuth2AuthorizedClientManager authorizedClientManager;
        +
         	private boolean defaultAuthorizedClientManager;
         
         	/**
        -	 * Constructs an {@code OAuth2AuthorizedClientArgumentResolver} using the provided parameters.
        +	 * Constructs an {@code OAuth2AuthorizedClientArgumentResolver} using the provided
        +	 * parameters.
         	 *
         	 * @since 5.2
        -	 * @param authorizedClientManager the {@link OAuth2AuthorizedClientManager} which manages the authorized client(s)
        +	 * @param authorizedClientManager the {@link OAuth2AuthorizedClientManager} which
        +	 * manages the authorized client(s)
         	 */
         	public OAuth2AuthorizedClientArgumentResolver(OAuth2AuthorizedClientManager authorizedClientManager) {
         		Assert.notNull(authorizedClientManager, "authorizedClientManager cannot be null");
        @@ -84,40 +89,37 @@ public final class OAuth2AuthorizedClientArgumentResolver implements HandlerMeth
         	}
         
         	/**
        -	 * Constructs an {@code OAuth2AuthorizedClientArgumentResolver} using the provided parameters.
        -	 *
        +	 * Constructs an {@code OAuth2AuthorizedClientArgumentResolver} using the provided
        +	 * parameters.
         	 * @param clientRegistrationRepository the repository of client registrations
         	 * @param authorizedClientRepository the repository of authorized clients
         	 */
         	public OAuth2AuthorizedClientArgumentResolver(ClientRegistrationRepository clientRegistrationRepository,
        -													OAuth2AuthorizedClientRepository authorizedClientRepository) {
        +			OAuth2AuthorizedClientRepository authorizedClientRepository) {
         		Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
         		Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null");
        -		this.authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(
        -				clientRegistrationRepository, authorizedClientRepository);
        +		this.authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository,
        +				authorizedClientRepository);
         		this.defaultAuthorizedClientManager = true;
         	}
         
         	@Override
         	public boolean supportsParameter(MethodParameter parameter) {
         		Class parameterType = parameter.getParameterType();
        -		return (OAuth2AuthorizedClient.class.isAssignableFrom(parameterType) &&
        -				(AnnotatedElementUtils.findMergedAnnotation(
        -						parameter.getParameter(), RegisteredOAuth2AuthorizedClient.class) != null));
        +		return (OAuth2AuthorizedClient.class.isAssignableFrom(parameterType) && (AnnotatedElementUtils
        +				.findMergedAnnotation(parameter.getParameter(), RegisteredOAuth2AuthorizedClient.class) != null));
         	}
         
         	@NonNull
         	@Override
        -	public Object resolveArgument(MethodParameter parameter,
        -									@Nullable ModelAndViewContainer mavContainer,
        -									NativeWebRequest webRequest,
        -									@Nullable WebDataBinderFactory binderFactory) {
        +	public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
        +			NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) {
         
         		String clientRegistrationId = this.resolveClientRegistrationId(parameter);
         		if (StringUtils.isEmpty(clientRegistrationId)) {
        -			throw new IllegalArgumentException("Unable to resolve the Client Registration Identifier. " +
        -					"It must be provided via @RegisteredOAuth2AuthorizedClient(\"client1\") or " +
        -					"@RegisteredOAuth2AuthorizedClient(registrationId = \"client1\").");
        +			throw new IllegalArgumentException("Unable to resolve the Client Registration Identifier. "
        +					+ "It must be provided via @RegisteredOAuth2AuthorizedClient(\"client1\") or "
        +					+ "@RegisteredOAuth2AuthorizedClient(registrationId = \"client1\").");
         		}
         
         		Authentication principal = SecurityContextHolder.getContext().getAuthentication();
        @@ -128,26 +130,26 @@ public final class OAuth2AuthorizedClientArgumentResolver implements HandlerMeth
         		HttpServletResponse servletResponse = webRequest.getNativeResponse(HttpServletResponse.class);
         
         		OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(clientRegistrationId)
        -				.principal(principal)
        -				.attribute(HttpServletRequest.class.getName(), servletRequest)
        -				.attribute(HttpServletResponse.class.getName(), servletResponse)
        -				.build();
        +				.principal(principal).attribute(HttpServletRequest.class.getName(), servletRequest)
        +				.attribute(HttpServletResponse.class.getName(), servletResponse).build();
         
         		return this.authorizedClientManager.authorize(authorizeRequest);
         	}
         
         	private String resolveClientRegistrationId(MethodParameter parameter) {
        -		RegisteredOAuth2AuthorizedClient authorizedClientAnnotation = AnnotatedElementUtils.findMergedAnnotation(
        -				parameter.getParameter(), RegisteredOAuth2AuthorizedClient.class);
        +		RegisteredOAuth2AuthorizedClient authorizedClientAnnotation = AnnotatedElementUtils
        +				.findMergedAnnotation(parameter.getParameter(), RegisteredOAuth2AuthorizedClient.class);
         
         		Authentication principal = SecurityContextHolder.getContext().getAuthentication();
         
         		String clientRegistrationId = null;
         		if (!StringUtils.isEmpty(authorizedClientAnnotation.registrationId())) {
         			clientRegistrationId = authorizedClientAnnotation.registrationId();
        -		} else if (!StringUtils.isEmpty(authorizedClientAnnotation.value())) {
        +		}
        +		else if (!StringUtils.isEmpty(authorizedClientAnnotation.value())) {
         			clientRegistrationId = authorizedClientAnnotation.value();
        -		} else if (principal != null && OAuth2AuthenticationToken.class.isAssignableFrom(principal.getClass())) {
        +		}
        +		else if (principal != null && OAuth2AuthenticationToken.class.isAssignableFrom(principal.getClass())) {
         			clientRegistrationId = ((OAuth2AuthenticationToken) principal).getAuthorizedClientRegistrationId();
         		}
         
        @@ -155,34 +157,41 @@ public final class OAuth2AuthorizedClientArgumentResolver implements HandlerMeth
         	}
         
         	/**
        -	 * Sets the client used when requesting an access token credential at the Token Endpoint for the {@code client_credentials} grant.
        -	 *
        -	 * @deprecated Use {@link #OAuth2AuthorizedClientArgumentResolver(OAuth2AuthorizedClientManager)} instead.
        -	 * 				Create an instance of {@link ClientCredentialsOAuth2AuthorizedClientProvider} configured with a
        -	 * 				{@link ClientCredentialsOAuth2AuthorizedClientProvider#setAccessTokenResponseClient(OAuth2AccessTokenResponseClient) DefaultClientCredentialsTokenResponseClient}
        -	 * 				(or a custom one) and than supply it to {@link DefaultOAuth2AuthorizedClientManager#setAuthorizedClientProvider(OAuth2AuthorizedClientProvider) DefaultOAuth2AuthorizedClientManager}.
        -	 *
        -	 * @param clientCredentialsTokenResponseClient the client used when requesting an access token credential at the Token Endpoint for the {@code client_credentials} grant
        +	 * Sets the client used when requesting an access token credential at the Token
        +	 * Endpoint for the {@code client_credentials} grant.
        +	 * @deprecated Use
        +	 * {@link #OAuth2AuthorizedClientArgumentResolver(OAuth2AuthorizedClientManager)}
        +	 * instead. Create an instance of
        +	 * {@link ClientCredentialsOAuth2AuthorizedClientProvider} configured with a
        +	 * {@link ClientCredentialsOAuth2AuthorizedClientProvider#setAccessTokenResponseClient(OAuth2AccessTokenResponseClient)
        +	 * DefaultClientCredentialsTokenResponseClient} (or a custom one) and than supply it
        +	 * to
        +	 * {@link DefaultOAuth2AuthorizedClientManager#setAuthorizedClientProvider(OAuth2AuthorizedClientProvider)
        +	 * DefaultOAuth2AuthorizedClientManager}.
        +	 * @param clientCredentialsTokenResponseClient the client used when requesting an
        +	 * access token credential at the Token Endpoint for the {@code client_credentials}
        +	 * grant
         	 */
         	@Deprecated
         	public void setClientCredentialsTokenResponseClient(
         			OAuth2AccessTokenResponseClient clientCredentialsTokenResponseClient) {
         		Assert.notNull(clientCredentialsTokenResponseClient, "clientCredentialsTokenResponseClient cannot be null");
        -		Assert.state(this.defaultAuthorizedClientManager, "The client cannot be set when the constructor used is \"OAuth2AuthorizedClientArgumentResolver(OAuth2AuthorizedClientManager)\". " +
        -				"Instead, use the constructor \"OAuth2AuthorizedClientArgumentResolver(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\".");
        +		Assert.state(this.defaultAuthorizedClientManager,
        +				"The client cannot be set when the constructor used is \"OAuth2AuthorizedClientArgumentResolver(OAuth2AuthorizedClientManager)\". "
        +						+ "Instead, use the constructor \"OAuth2AuthorizedClientArgumentResolver(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\".");
         		updateDefaultAuthorizedClientManager(clientCredentialsTokenResponseClient);
         	}
         
         	private void updateDefaultAuthorizedClientManager(
         			OAuth2AccessTokenResponseClient clientCredentialsTokenResponseClient) {
         
        -		OAuth2AuthorizedClientProvider authorizedClientProvider =
        -				OAuth2AuthorizedClientProviderBuilder.builder()
        -						.authorizationCode()
        -						.refreshToken()
        -						.clientCredentials(configurer -> configurer.accessTokenResponseClient(clientCredentialsTokenResponseClient))
        -						.password()
        -						.build();
        -		((DefaultOAuth2AuthorizedClientManager) this.authorizedClientManager).setAuthorizedClientProvider(authorizedClientProvider);
        +		OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
        +				.authorizationCode().refreshToken()
        +				.clientCredentials(
        +						configurer -> configurer.accessTokenResponseClient(clientCredentialsTokenResponseClient))
        +				.password().build();
        +		((DefaultOAuth2AuthorizedClientManager) this.authorizedClientManager)
        +				.setAuthorizedClientProvider(authorizedClientProvider);
         	}
        +
         }
        diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunction.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunction.java
        index 8291e26704..945f6e68e7 100644
        --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunction.java
        +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunction.java
        @@ -67,26 +67,37 @@ import java.util.stream.Collectors;
         import java.util.stream.Stream;
         
         /**
        - * Provides an easy mechanism for using an {@link OAuth2AuthorizedClient} to make OAuth2 requests by including the
        - * token as a Bearer Token.
        + * Provides an easy mechanism for using an {@link OAuth2AuthorizedClient} to make OAuth2
        + * requests by including the token as a Bearer Token.
          *
          * 

        Authentication and Authorization Failures

        * - *

        Since 5.3, this filter function has the ability to forward authentication (HTTP 401 Unauthorized) - * and authorization (HTTP 403 Forbidden) failures from an OAuth 2.0 Resource Server to a - * {@link ReactiveOAuth2AuthorizationFailureHandler}. - * A {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} can be used - * to remove the cached {@link OAuth2AuthorizedClient}, so that future requests will result - * in a new token being retrieved from an Authorization Server, and sent to the Resource Server.

        + *

        + * Since 5.3, this filter function has the ability to forward authentication (HTTP 401 + * Unauthorized) and authorization (HTTP 403 Forbidden) failures from an OAuth 2.0 + * Resource Server to a {@link ReactiveOAuth2AuthorizationFailureHandler}. A + * {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} can be used to + * remove the cached {@link OAuth2AuthorizedClient}, so that future requests will result + * in a new token being retrieved from an Authorization Server, and sent to the Resource + * Server. + *

        * - *

        If the {@link #ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveClientRegistrationRepository, ServerOAuth2AuthorizedClientRepository)} - * constructor is used, a {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} - * will be configured automatically.

        + *

        + * If the + * {@link #ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveClientRegistrationRepository, ServerOAuth2AuthorizedClientRepository)} + * constructor is used, a + * {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} will be + * configured automatically. + *

        * - *

        If the {@link #ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)} - * constructor is used, a {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} - * will NOT be configured automatically. - * It is recommended that you configure one via {@link #setAuthorizationFailureHandler(ReactiveOAuth2AuthorizationFailureHandler)}.

        + *

        + * If the + * {@link #ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)} + * constructor is used, a + * {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} will + * NOT be configured automatically. It is recommended that you configure one via + * {@link #setAuthorizationFailureHandler(ReactiveOAuth2AuthorizationFailureHandler)}. + *

        * * @author Rob Winch * @author Joe Grandja @@ -94,36 +105,37 @@ import java.util.stream.Stream; * @since 5.1 */ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements ExchangeFilterFunction { + /** * The request attribute name used to locate the {@link OAuth2AuthorizedClient}. */ private static final String OAUTH2_AUTHORIZED_CLIENT_ATTR_NAME = OAuth2AuthorizedClient.class.getName(); /** - * The client request attribute name used to locate the {@link ClientRegistration#getRegistrationId()} + * The client request attribute name used to locate the + * {@link ClientRegistration#getRegistrationId()} */ - private static final String CLIENT_REGISTRATION_ID_ATTR_NAME = OAuth2AuthorizedClient.class.getName().concat(".CLIENT_REGISTRATION_ID"); + private static final String CLIENT_REGISTRATION_ID_ATTR_NAME = OAuth2AuthorizedClient.class.getName() + .concat(".CLIENT_REGISTRATION_ID"); /** - * The request attribute name used to locate the {@link org.springframework.web.server.ServerWebExchange}. + * The request attribute name used to locate the + * {@link org.springframework.web.server.ServerWebExchange}. */ private static final String SERVER_WEB_EXCHANGE_ATTR_NAME = ServerWebExchange.class.getName(); - private static final AnonymousAuthenticationToken ANONYMOUS_USER_TOKEN = new AnonymousAuthenticationToken("anonymous", "anonymousUser", - AuthorityUtils.createAuthorityList("ROLE_USER")); + private static final AnonymousAuthenticationToken ANONYMOUS_USER_TOKEN = new AnonymousAuthenticationToken( + "anonymous", "anonymousUser", AuthorityUtils.createAuthorityList("ROLE_USER")); private final Mono currentAuthenticationMono = ReactiveSecurityContextHolder.getContext() - .map(SecurityContext::getAuthentication) - .defaultIfEmpty(ANONYMOUS_USER_TOKEN); + .map(SecurityContext::getAuthentication).defaultIfEmpty(ANONYMOUS_USER_TOKEN); private final Mono clientRegistrationIdMono = currentAuthenticationMono .filter(t -> this.defaultOAuth2AuthorizedClient && t instanceof OAuth2AuthenticationToken) - .cast(OAuth2AuthenticationToken.class) - .map(OAuth2AuthenticationToken::getAuthorizedClientRegistrationId); + .cast(OAuth2AuthenticationToken.class).map(OAuth2AuthenticationToken::getAuthorizedClientRegistrationId); private final Mono currentServerWebExchangeMono = Mono.subscriberContext() - .filter(c -> c.hasKey(ServerWebExchange.class)) - .map(c -> c.get(ServerWebExchange.class)); + .filter(c -> c.hasKey(ServerWebExchange.class)).map(c -> c.get(ServerWebExchange.class)); private final ReactiveOAuth2AuthorizedClientManager authorizedClientManager; @@ -143,62 +155,72 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements @FunctionalInterface private interface ClientResponseHandler { + Mono handleResponse(ClientRequest request, Mono response); + } /** - * Constructs a {@code ServerOAuth2AuthorizedClientExchangeFilterFunction} using the provided parameters. + * Constructs a {@code ServerOAuth2AuthorizedClientExchangeFilterFunction} using the + * provided parameters. * - *

        When this constructor is used, authentication (HTTP 401) and authorization (HTTP 403) - * failures returned from a OAuth 2.0 Resource Server will NOT be forwarded to a - * {@link ReactiveOAuth2AuthorizationFailureHandler}. - * Therefore, future requests to the Resource Server will most likely use the same (most likely invalid) token, - * resulting in the same errors returned from the Resource Server. - * It is recommended to configure a {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} - * via {@link #setAuthorizationFailureHandler(ReactiveOAuth2AuthorizationFailureHandler)} + *

        + * When this constructor is used, authentication (HTTP 401) and authorization (HTTP + * 403) failures returned from a OAuth 2.0 Resource Server will NOT be + * forwarded to a {@link ReactiveOAuth2AuthorizationFailureHandler}. Therefore, future + * requests to the Resource Server will most likely use the same (most likely invalid) + * token, resulting in the same errors returned from the Resource Server. It is + * recommended to configure a + * {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} via + * {@link #setAuthorizationFailureHandler(ReactiveOAuth2AuthorizationFailureHandler)} * so that authentication and authorization failures returned from a Resource Server - * will result in removing the authorized client, so that a new token is retrieved for future requests.

        + * will result in removing the authorized client, so that a new token is retrieved for + * future requests. + *

        * * @since 5.2 - * @param authorizedClientManager the {@link ReactiveOAuth2AuthorizedClientManager} which manages the authorized client(s) + * @param authorizedClientManager the {@link ReactiveOAuth2AuthorizedClientManager} + * which manages the authorized client(s) */ - public ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) { + public ServerOAuth2AuthorizedClientExchangeFilterFunction( + ReactiveOAuth2AuthorizedClientManager authorizedClientManager) { Assert.notNull(authorizedClientManager, "authorizedClientManager cannot be null"); this.authorizedClientManager = authorizedClientManager; - this.clientResponseHandler = (request, responseMono) -> responseMono; + this.clientResponseHandler = (request, responseMono) -> responseMono; } /** - * Constructs a {@code ServerOAuth2AuthorizedClientExchangeFilterFunction} using the provided parameters. - * - *

        Since 5.3, when this constructor is used, authentication (HTTP 401) - * and authorization (HTTP 403) failures returned from an OAuth 2.0 Resource Server - * will be forwarded to a {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler}, - * which will potentially remove the {@link OAuth2AuthorizedClient} from the given - * {@link ServerOAuth2AuthorizedClientRepository}, depending on the OAuth 2.0 error code returned. - * Authentication failures returned from an OAuth 2.0 Resource Server typically indicate - * that the token is invalid, and should not be used in future requests. - * Removing the authorized client from the repository will ensure that the existing - * token will not be sent for future requests to the Resource Server, - * and a new token is retrieved from Authorization Server and used for - * future requests to the Resource Server.

        + * Constructs a {@code ServerOAuth2AuthorizedClientExchangeFilterFunction} using the + * provided parameters. * + *

        + * Since 5.3, when this constructor is used, authentication (HTTP 401) and + * authorization (HTTP 403) failures returned from an OAuth 2.0 Resource Server will + * be forwarded to a + * {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler}, which will + * potentially remove the {@link OAuth2AuthorizedClient} from the given + * {@link ServerOAuth2AuthorizedClientRepository}, depending on the OAuth 2.0 error + * code returned. Authentication failures returned from an OAuth 2.0 Resource Server + * typically indicate that the token is invalid, and should not be used in future + * requests. Removing the authorized client from the repository will ensure that the + * existing token will not be sent for future requests to the Resource Server, and a + * new token is retrieved from Authorization Server and used for future requests to + * the Resource Server. + *

        * @param clientRegistrationRepository the repository of client registrations * @param authorizedClientRepository the repository of authorized clients */ - public ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveClientRegistrationRepository clientRegistrationRepository, - ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { + public ServerOAuth2AuthorizedClientExchangeFilterFunction( + ReactiveClientRegistrationRepository clientRegistrationRepository, + ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { - ReactiveOAuth2AuthorizationFailureHandler authorizationFailureHandler = - new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler( - (clientRegistrationId, principal, attributes) -> - authorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, - (ServerWebExchange) attributes.get(ServerWebExchange.class.getName()))); + ReactiveOAuth2AuthorizationFailureHandler authorizationFailureHandler = new RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler( + (clientRegistrationId, principal, attributes) -> authorizedClientRepository.removeAuthorizedClient( + clientRegistrationId, principal, + (ServerWebExchange) attributes.get(ServerWebExchange.class.getName()))); - this.authorizedClientManager = createDefaultAuthorizedClientManager( - clientRegistrationRepository, - authorizedClientRepository, - authorizationFailureHandler); + this.authorizedClientManager = createDefaultAuthorizedClientManager(clientRegistrationRepository, + authorizedClientRepository, authorizationFailureHandler); this.clientResponseHandler = new AuthorizationFailureForwarder(authorizationFailureHandler); this.defaultAuthorizedClientManager = true; } @@ -210,32 +232,27 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements // gh-7544 if (authorizedClientRepository instanceof UnAuthenticatedServerOAuth2AuthorizedClientRepository) { - UnAuthenticatedReactiveOAuth2AuthorizedClientManager unauthenticatedAuthorizedClientManager = - new UnAuthenticatedReactiveOAuth2AuthorizedClientManager( - clientRegistrationRepository, - (UnAuthenticatedServerOAuth2AuthorizedClientRepository) authorizedClientRepository, - authorizationFailureHandler); - unauthenticatedAuthorizedClientManager.setAuthorizedClientProvider( - ReactiveOAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .refreshToken() - .clientCredentials() - .password() - .build()); + UnAuthenticatedReactiveOAuth2AuthorizedClientManager unauthenticatedAuthorizedClientManager = new UnAuthenticatedReactiveOAuth2AuthorizedClientManager( + clientRegistrationRepository, + (UnAuthenticatedServerOAuth2AuthorizedClientRepository) authorizedClientRepository, + authorizationFailureHandler); + unauthenticatedAuthorizedClientManager + .setAuthorizedClientProvider(ReactiveOAuth2AuthorizedClientProviderBuilder.builder() + .authorizationCode().refreshToken().clientCredentials().password().build()); return unauthenticatedAuthorizedClientManager; } - DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = - new DefaultReactiveOAuth2AuthorizedClientManager( - clientRegistrationRepository, authorizedClientRepository); + DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager( + clientRegistrationRepository, authorizedClientRepository); authorizedClientManager.setAuthorizationFailureHandler(authorizationFailureHandler); return authorizedClientManager; } /** - * Modifies the {@link ClientRequest#attributes()} to include the {@link OAuth2AuthorizedClient} to be used for - * providing the Bearer Token. Example usage: + * Modifies the {@link ClientRequest#attributes()} to include the + * {@link OAuth2AuthorizedClient} to be used for providing the Bearer Token. Example + * usage: * *
         	 * WebClient webClient = WebClient.builder()
        @@ -257,11 +274,10 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements
         	 * 
      4. A refresh token is present on the OAuth2AuthorizedClient
      5. *
      6. The access token will be expired in * {@link #setAccessTokenExpiresSkew(Duration)}
      7. - *
      8. The {@link ReactiveSecurityContextHolder} will be used to attempt to save - * the token. If it is empty, then the principal name on the OAuth2AuthorizedClient - * will be used to create an Authentication for saving.
      9. + *
      10. The {@link ReactiveSecurityContextHolder} will be used to attempt to save the + * token. If it is empty, then the principal name on the OAuth2AuthorizedClient will + * be used to create an Authentication for saving.
      11. * - * * @param authorizedClient the {@link OAuth2AuthorizedClient} to use. * @return the {@link Consumer} to populate the */ @@ -274,8 +290,8 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements } /** - * Modifies the {@link ClientRequest#attributes()} to include the {@link ServerWebExchange} to be used for - * providing the Bearer Token. Example usage: + * Modifies the {@link ClientRequest#attributes()} to include the + * {@link ServerWebExchange} to be used for providing the Bearer Token. Example usage: * *
         	 * WebClient webClient = WebClient.builder()
        @@ -301,9 +317,9 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements
         	}
         
         	/**
        -	 * Modifies the {@link ClientRequest#attributes()} to include the {@link ClientRegistration#getRegistrationId()} to
        -	 * be used to look up the {@link OAuth2AuthorizedClient}.
        -	 *
        +	 * Modifies the {@link ClientRequest#attributes()} to include the
        +	 * {@link ClientRegistration#getRegistrationId()} to be used to look up the
        +	 * {@link OAuth2AuthorizedClient}.
         	 * @param clientRegistrationId the {@link ClientRegistration#getRegistrationId()} to
         	 * be used to look up the {@link OAuth2AuthorizedClient}.
         	 * @return the {@link Consumer} to populate the attributes
        @@ -321,19 +337,21 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements
         	}
         
         	/**
        -	 * If true, a default {@link OAuth2AuthorizedClient} can be discovered from the current Authentication. It is
        -	 * recommended to be cautious with this feature since all HTTP requests will receive the access token if it can be
        -	 * resolved from the current Authentication.
        -	 * @param defaultOAuth2AuthorizedClient true if a default {@link OAuth2AuthorizedClient} should be used, else false.
        -	 *                                      Default is false.
        +	 * If true, a default {@link OAuth2AuthorizedClient} can be discovered from the
        +	 * current Authentication. It is recommended to be cautious with this feature since
        +	 * all HTTP requests will receive the access token if it can be resolved from the
        +	 * current Authentication.
        +	 * @param defaultOAuth2AuthorizedClient true if a default
        +	 * {@link OAuth2AuthorizedClient} should be used, else false. Default is false.
         	 */
         	public void setDefaultOAuth2AuthorizedClient(boolean defaultOAuth2AuthorizedClient) {
         		this.defaultOAuth2AuthorizedClient = defaultOAuth2AuthorizedClient;
         	}
         
         	/**
        -	 * If set, will be used as the default {@link ClientRegistration#getRegistrationId()}. It is
        -	 * recommended to be cautious with this feature since all HTTP requests will receive the access token.
        +	 * If set, will be used as the default {@link ClientRegistration#getRegistrationId()}.
        +	 * It is recommended to be cautious with this feature since all HTTP requests will
        +	 * receive the access token.
         	 * @param clientRegistrationId the id to use
         	 */
         	public void setDefaultClientRegistrationId(String clientRegistrationId) {
        @@ -341,41 +359,48 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements
         	}
         
         	/**
        -	 * Sets the {@link ReactiveOAuth2AccessTokenResponseClient} used for getting an {@link OAuth2AuthorizedClient} for the client_credentials grant.
        -	 *
        -	 * @deprecated Use {@link #ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)} instead.
        -	 * 				Create an instance of {@link ClientCredentialsReactiveOAuth2AuthorizedClientProvider} configured with a
        -	 * 				{@link ClientCredentialsReactiveOAuth2AuthorizedClientProvider#setAccessTokenResponseClient(ReactiveOAuth2AccessTokenResponseClient) WebClientReactiveClientCredentialsTokenResponseClient}
        -	 * 				(or a custom one) and than supply it to {@link DefaultReactiveOAuth2AuthorizedClientManager#setAuthorizedClientProvider(ReactiveOAuth2AuthorizedClientProvider) DefaultReactiveOAuth2AuthorizedClientManager}.
        -	 *
        +	 * Sets the {@link ReactiveOAuth2AccessTokenResponseClient} used for getting an
        +	 * {@link OAuth2AuthorizedClient} for the client_credentials grant.
        +	 * @deprecated Use
        +	 * {@link #ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)}
        +	 * instead. Create an instance of
        +	 * {@link ClientCredentialsReactiveOAuth2AuthorizedClientProvider} configured with a
        +	 * {@link ClientCredentialsReactiveOAuth2AuthorizedClientProvider#setAccessTokenResponseClient(ReactiveOAuth2AccessTokenResponseClient)
        +	 * WebClientReactiveClientCredentialsTokenResponseClient} (or a custom one) and than
        +	 * supply it to
        +	 * {@link DefaultReactiveOAuth2AuthorizedClientManager#setAuthorizedClientProvider(ReactiveOAuth2AuthorizedClientProvider)
        +	 * DefaultReactiveOAuth2AuthorizedClientManager}.
         	 * @param clientCredentialsTokenResponseClient the client to use
         	 */
         	@Deprecated
         	public void setClientCredentialsTokenResponseClient(
         			ReactiveOAuth2AccessTokenResponseClient clientCredentialsTokenResponseClient) {
         		Assert.notNull(clientCredentialsTokenResponseClient, "clientCredentialsTokenResponseClient cannot be null");
        -		Assert.state(this.defaultAuthorizedClientManager, "The client cannot be set when the constructor used is \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)\". " +
        -				"Instead, use the constructor \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\".");
        +		Assert.state(this.defaultAuthorizedClientManager,
        +				"The client cannot be set when the constructor used is \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)\". "
        +						+ "Instead, use the constructor \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\".");
         		this.clientCredentialsTokenResponseClient = clientCredentialsTokenResponseClient;
         		updateDefaultAuthorizedClientManager();
         	}
         
         	private void updateDefaultAuthorizedClientManager() {
        -		ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
        -				ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
        -						.authorizationCode()
        -						.refreshToken(configurer -> configurer.clockSkew(this.accessTokenExpiresSkew))
        -						.clientCredentials(this::updateClientCredentialsProvider)
        -						.password(configurer -> configurer.clockSkew(this.accessTokenExpiresSkew))
        -						.build();
        +		ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder
        +				.builder().authorizationCode()
        +				.refreshToken(configurer -> configurer.clockSkew(this.accessTokenExpiresSkew))
        +				.clientCredentials(this::updateClientCredentialsProvider)
        +				.password(configurer -> configurer.clockSkew(this.accessTokenExpiresSkew)).build();
         		if (this.authorizedClientManager instanceof UnAuthenticatedReactiveOAuth2AuthorizedClientManager) {
        -			((UnAuthenticatedReactiveOAuth2AuthorizedClientManager) this.authorizedClientManager).setAuthorizedClientProvider(authorizedClientProvider);
        -		} else {
        -			((DefaultReactiveOAuth2AuthorizedClientManager) this.authorizedClientManager).setAuthorizedClientProvider(authorizedClientProvider);
        +			((UnAuthenticatedReactiveOAuth2AuthorizedClientManager) this.authorizedClientManager)
        +					.setAuthorizedClientProvider(authorizedClientProvider);
        +		}
        +		else {
        +			((DefaultReactiveOAuth2AuthorizedClientManager) this.authorizedClientManager)
        +					.setAuthorizedClientProvider(authorizedClientProvider);
         		}
         	}
         
        -	private void updateClientCredentialsProvider(ReactiveOAuth2AuthorizedClientProviderBuilder.ClientCredentialsGrantBuilder builder) {
        +	private void updateClientCredentialsProvider(
        +			ReactiveOAuth2AuthorizedClientProviderBuilder.ClientCredentialsGrantBuilder builder) {
         		if (this.clientCredentialsTokenResponseClient != null) {
         			builder.accessTokenResponseClient(this.clientCredentialsTokenResponseClient);
         		}
        @@ -385,26 +410,27 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements
         	/**
         	 * An access token will be considered expired by comparing its expiration to now +
         	 * this skewed Duration. The default is 1 minute.
        -	 *
        -	 * @deprecated The {@code accessTokenExpiresSkew} should be configured with the specific {@link ReactiveOAuth2AuthorizedClientProvider} implementation,
        -	 * 				e.g. {@link ClientCredentialsReactiveOAuth2AuthorizedClientProvider#setClockSkew(Duration) ClientCredentialsReactiveOAuth2AuthorizedClientProvider} or
        -	 * 				{@link RefreshTokenReactiveOAuth2AuthorizedClientProvider#setClockSkew(Duration) RefreshTokenReactiveOAuth2AuthorizedClientProvider}.
        -	 *
        +	 * @deprecated The {@code accessTokenExpiresSkew} should be configured with the
        +	 * specific {@link ReactiveOAuth2AuthorizedClientProvider} implementation, e.g.
        +	 * {@link ClientCredentialsReactiveOAuth2AuthorizedClientProvider#setClockSkew(Duration)
        +	 * ClientCredentialsReactiveOAuth2AuthorizedClientProvider} or
        +	 * {@link RefreshTokenReactiveOAuth2AuthorizedClientProvider#setClockSkew(Duration)
        +	 * RefreshTokenReactiveOAuth2AuthorizedClientProvider}.
         	 * @param accessTokenExpiresSkew the Duration to use.
         	 */
         	@Deprecated
         	public void setAccessTokenExpiresSkew(Duration accessTokenExpiresSkew) {
         		Assert.notNull(accessTokenExpiresSkew, "accessTokenExpiresSkew cannot be null");
        -		Assert.state(this.defaultAuthorizedClientManager, "The accessTokenExpiresSkew cannot be set when the constructor used is \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)\". " +
        -				"Instead, use the constructor \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\".");
        +		Assert.state(this.defaultAuthorizedClientManager,
        +				"The accessTokenExpiresSkew cannot be set when the constructor used is \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)\". "
        +						+ "Instead, use the constructor \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\".");
         		this.accessTokenExpiresSkew = accessTokenExpiresSkew;
         		updateDefaultAuthorizedClientManager();
         	}
         
         	@Override
         	public Mono filter(ClientRequest request, ExchangeFunction next) {
        -		return authorizedClient(request)
        -				.map(authorizedClient -> bearer(request, authorizedClient))
        +		return authorizedClient(request).map(authorizedClient -> bearer(request, authorizedClient))
         				.flatMap(requestWithBearer -> exchangeAndHandleResponse(requestWithBearer, next))
         				.switchIfEmpty(Mono.defer(() -> exchangeAndHandleResponse(request, next)));
         	}
        @@ -417,10 +443,10 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements
         	private Mono authorizedClient(ClientRequest request) {
         		OAuth2AuthorizedClient authorizedClientFromAttrs = oauth2AuthorizedClient(request);
         		return Mono.justOrEmpty(authorizedClientFromAttrs)
        -				.switchIfEmpty(Mono.defer(() ->
        -						authorizeRequest(request).flatMap(this.authorizedClientManager::authorize)))
        -				.flatMap(authorizedClient ->
        -						reauthorizeRequest(request, authorizedClient).flatMap(this.authorizedClientManager::authorize));
        +				.switchIfEmpty(
        +						Mono.defer(() -> authorizeRequest(request).flatMap(this.authorizedClientManager::authorize)))
        +				.flatMap(authorizedClient -> reauthorizeRequest(request, authorizedClient)
        +						.flatMap(this.authorizedClientManager::authorize));
         	}
         
         	private Mono authorizeRequest(ClientRequest request) {
        @@ -428,21 +454,20 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements
         
         		Mono> serverWebExchange = effectiveServerWebExchange(request);
         
        -		return Mono.zip(clientRegistrationId, this.currentAuthenticationMono, serverWebExchange)
        -				.map(t3 -> {
        -					OAuth2AuthorizeRequest.Builder builder = OAuth2AuthorizeRequest.withClientRegistrationId(t3.getT1()).principal(t3.getT2());
        -					t3.getT3().ifPresent(exchange -> builder.attribute(ServerWebExchange.class.getName(), exchange));
        -					return builder.build();
        -				});
        +		return Mono.zip(clientRegistrationId, this.currentAuthenticationMono, serverWebExchange).map(t3 -> {
        +			OAuth2AuthorizeRequest.Builder builder = OAuth2AuthorizeRequest.withClientRegistrationId(t3.getT1())
        +					.principal(t3.getT2());
        +			t3.getT3().ifPresent(exchange -> builder.attribute(ServerWebExchange.class.getName(), exchange));
        +			return builder.build();
        +		});
         	}
         
         	/**
        -	 * Returns a {@link Mono} the emits the {@code clientRegistrationId}
        -	 * that is active for the given request.
        -	 *
        +	 * Returns a {@link Mono} the emits the {@code clientRegistrationId} that is active
        +	 * for the given request.
         	 * @param request the request for which to retrieve the {@code clientRegistrationId}
        -	 * @return a mono that emits the {@code clientRegistrationId}
        -	 * 	       that is active for the given request.
        +	 * @return a mono that emits the {@code clientRegistrationId} that is active for the
        +	 * given request.
         	 */
         	private Mono effectiveClientRegistrationId(ClientRequest request) {
         		return Mono.justOrEmpty(clientRegistrationId(request))
        @@ -451,53 +476,57 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements
         	}
         
         	/**
        -	 * Returns a {@link Mono} that emits an {@link Optional} for the {@link ServerWebExchange}
        -	 * that is active for the given request.
        -	 *
        -	 * 

        The returned {@link Mono} will never complete empty. - * Instead, it will emit an empty {@link Optional} if no exchange is active.

        + * Returns a {@link Mono} that emits an {@link Optional} for the + * {@link ServerWebExchange} that is active for the given request. * + *

        + * The returned {@link Mono} will never complete empty. Instead, it will emit an empty + * {@link Optional} if no exchange is active. + *

        * @param request the request for which to retrieve the exchange - * @return a {@link Mono} that emits an {@link Optional} for the {@link ServerWebExchange} - * that is active for the given request. + * @return a {@link Mono} that emits an {@link Optional} for the + * {@link ServerWebExchange} that is active for the given request. */ private Mono> effectiveServerWebExchange(ClientRequest request) { - return Mono.justOrEmpty(serverWebExchange(request)) - .switchIfEmpty(currentServerWebExchangeMono) - .map(Optional::of) - .defaultIfEmpty(Optional.empty()); + return Mono.justOrEmpty(serverWebExchange(request)).switchIfEmpty(currentServerWebExchangeMono) + .map(Optional::of).defaultIfEmpty(Optional.empty()); } - private Mono reauthorizeRequest(ClientRequest request, OAuth2AuthorizedClient authorizedClient) { + private Mono reauthorizeRequest(ClientRequest request, + OAuth2AuthorizedClient authorizedClient) { Mono> serverWebExchange = effectiveServerWebExchange(request); - return Mono.zip(this.currentAuthenticationMono, serverWebExchange) - .map(t2 -> { - OAuth2AuthorizeRequest.Builder builder = OAuth2AuthorizeRequest.withAuthorizedClient(authorizedClient).principal(t2.getT1()); - t2.getT2().ifPresent(exchange -> builder.attribute(ServerWebExchange.class.getName(), exchange)); - return builder.build(); - }); + return Mono.zip(this.currentAuthenticationMono, serverWebExchange).map(t2 -> { + OAuth2AuthorizeRequest.Builder builder = OAuth2AuthorizeRequest.withAuthorizedClient(authorizedClient) + .principal(t2.getT1()); + t2.getT2().ifPresent(exchange -> builder.attribute(ServerWebExchange.class.getName(), exchange)); + return builder.build(); + }); } private ClientRequest bearer(ClientRequest request, OAuth2AuthorizedClient authorizedClient) { return ClientRequest.from(request) - .headers(headers -> headers.setBearerAuth(authorizedClient.getAccessToken().getTokenValue())) - .build(); + .headers(headers -> headers.setBearerAuth(authorizedClient.getAccessToken().getTokenValue())).build(); } /** - * Sets the handler that handles authentication and authorization failures when communicating - * to the OAuth 2.0 Resource Server. + * Sets the handler that handles authentication and authorization failures when + * communicating to the OAuth 2.0 Resource Server. * - *

        For example, a {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} - * is typically used to remove the cached {@link OAuth2AuthorizedClient}, - * so that the same token is no longer used in future requests to the Resource Server.

        + *

        + * For example, a + * {@link RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} is + * typically used to remove the cached {@link OAuth2AuthorizedClient}, so that the + * same token is no longer used in future requests to the Resource Server. + *

        * - *

        The failure handler used by default depends on which constructor was used - * to construct this {@link ServerOAuth2AuthorizedClientExchangeFilterFunction}. - * See the constructors for more details.

        - * - * @param authorizationFailureHandler the handler that handles authentication and authorization failures. + *

        + * The failure handler used by default depends on which constructor was used to + * construct this {@link ServerOAuth2AuthorizedClientExchangeFilterFunction}. See the + * constructors for more details. + *

        + * @param authorizationFailureHandler the handler that handles authentication and + * authorization failures. * @since 5.3 */ public void setAuthorizationFailureHandler(ReactiveOAuth2AuthorizationFailureHandler authorizationFailureHandler) { @@ -505,11 +534,17 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements this.clientResponseHandler = new AuthorizationFailureForwarder(authorizationFailureHandler); } - private static class UnAuthenticatedReactiveOAuth2AuthorizedClientManager implements ReactiveOAuth2AuthorizedClientManager { + private static class UnAuthenticatedReactiveOAuth2AuthorizedClientManager + implements ReactiveOAuth2AuthorizedClientManager { + private final ReactiveClientRegistrationRepository clientRegistrationRepository; + private final UnAuthenticatedServerOAuth2AuthorizedClientRepository authorizedClientRepository; + private final ReactiveOAuth2AuthorizationSuccessHandler authorizationSuccessHandler; + private final ReactiveOAuth2AuthorizationFailureHandler authorizationFailureHandler; + private ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider; private UnAuthenticatedReactiveOAuth2AuthorizedClientManager( @@ -518,8 +553,8 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements ReactiveOAuth2AuthorizationFailureHandler authorizationFailureHandler) { this.clientRegistrationRepository = clientRegistrationRepository; this.authorizedClientRepository = authorizedClientRepository; - this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> - authorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, null); + this.authorizationSuccessHandler = (authorizedClient, principal, attributes) -> authorizedClientRepository + .saveAuthorizedClient(authorizedClient, principal, null); this.authorizationFailureHandler = authorizationFailureHandler; } @@ -530,60 +565,61 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements String clientRegistrationId = authorizeRequest.getClientRegistrationId(); Authentication principal = authorizeRequest.getPrincipal(); - return Mono.justOrEmpty(authorizeRequest.getAuthorizedClient()) - .switchIfEmpty(Mono.defer(() -> this.authorizedClientRepository.loadAuthorizedClient(clientRegistrationId, principal, null))) + return Mono.justOrEmpty(authorizeRequest.getAuthorizedClient()).switchIfEmpty(Mono.defer( + () -> this.authorizedClientRepository.loadAuthorizedClient(clientRegistrationId, principal, null))) .flatMap(authorizedClient -> { // Re-authorize - return Mono.just(OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient).principal(principal).build()) + return Mono + .just(OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) + .principal(principal).build()) .flatMap(authorizationContext -> authorize(authorizationContext, principal)) - // Default to the existing authorizedClient if the client was not re-authorized - .defaultIfEmpty(authorizeRequest.getAuthorizedClient() != null ? - authorizeRequest.getAuthorizedClient() : authorizedClient); - }) - .switchIfEmpty(Mono.defer(() -> - // Authorize - this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId) - .switchIfEmpty(Mono.error(() -> new IllegalArgumentException( - "Could not find ClientRegistration with id '" + clientRegistrationId + "'"))) - .flatMap(clientRegistration -> Mono.just(OAuth2AuthorizationContext.withClientRegistration(clientRegistration).principal(principal).build())) - .flatMap(authorizationContext -> authorize(authorizationContext, principal)) - )); + // Default to the existing authorizedClient if the client + // was not re-authorized + .defaultIfEmpty(authorizeRequest.getAuthorizedClient() != null + ? authorizeRequest.getAuthorizedClient() : authorizedClient); + }).switchIfEmpty(Mono.defer(() -> + // Authorize + this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId) + .switchIfEmpty(Mono.error(() -> new IllegalArgumentException( + "Could not find ClientRegistration with id '" + clientRegistrationId + "'"))) + .flatMap(clientRegistration -> Mono.just(OAuth2AuthorizationContext + .withClientRegistration(clientRegistration).principal(principal).build())) + .flatMap(authorizationContext -> authorize(authorizationContext, principal)))); } /** - * Performs authorization and then delegates to either the {@link #authorizationSuccessHandler} - * or {@link #authorizationFailureHandler}, depending on the authorization result. - * + * Performs authorization and then delegates to either the + * {@link #authorizationSuccessHandler} or {@link #authorizationFailureHandler}, + * depending on the authorization result. * @param authorizationContext the context to authorize * @param principal the principle to authorize - * @return a {@link Mono} that emits the authorized client after the authorization attempt succeeds - * and the {@link #authorizationSuccessHandler} has completed, - * or completes with an exception after the authorization attempt fails - * and the {@link #authorizationFailureHandler} has completed + * @return a {@link Mono} that emits the authorized client after the authorization + * attempt succeeds and the {@link #authorizationSuccessHandler} has completed, or + * completes with an exception after the authorization attempt fails and the + * {@link #authorizationFailureHandler} has completed */ - private Mono authorize( - OAuth2AuthorizationContext authorizationContext, + private Mono authorize(OAuth2AuthorizationContext authorizationContext, Authentication principal) { return this.authorizedClientProvider.authorize(authorizationContext) - // Delegates to the authorizationSuccessHandler of the successful authorization - .flatMap(authorizedClient -> this.authorizationSuccessHandler.onAuthorizationSuccess( - authorizedClient, - principal, - Collections.emptyMap()) + // Delegates to the authorizationSuccessHandler of the successful + // authorization + .flatMap(authorizedClient -> this.authorizationSuccessHandler + .onAuthorizationSuccess(authorizedClient, principal, Collections.emptyMap()) .thenReturn(authorizedClient)) - // Delegates to the authorizationFailureHandler of the failed authorization - .onErrorResume(OAuth2AuthorizationException.class, authorizationException -> this.authorizationFailureHandler.onAuthorizationFailure( - authorizationException, - principal, - Collections.emptyMap()) - .then(Mono.error(authorizationException))); + // Delegates to the authorizationFailureHandler of the failed + // authorization + .onErrorResume(OAuth2AuthorizationException.class, + authorizationException -> this.authorizationFailureHandler + .onAuthorizationFailure(authorizationException, principal, Collections.emptyMap()) + .then(Mono.error(authorizationException))); } private void setAuthorizedClientProvider(ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider) { Assert.notNull(authorizedClientProvider, "authorizedClientProvider cannot be null"); this.authorizedClientProvider = authorizedClientProvider; } + } /** @@ -595,15 +631,14 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements private class AuthorizationFailureForwarder implements ClientResponseHandler { /** - * A map of HTTP Status Code to OAuth 2.0 Error codes for - * HTTP status codes that should be interpreted as - * authentication or authorization failures. + * A map of HTTP Status Code to OAuth 2.0 Error codes for HTTP status codes that + * should be interpreted as authentication or authorization failures. */ private final Map httpStatusToOAuth2ErrorCodeMap; /** - * The {@link ReactiveOAuth2AuthorizationFailureHandler} to notify - * when an authentication/authorization failure occurs. + * The {@link ReactiveOAuth2AuthorizationFailureHandler} to notify when an + * authentication/authorization failure occurs. */ private final ReactiveOAuth2AuthorizationFailureHandler authorizationFailureHandler; @@ -619,30 +654,26 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements @Override public Mono handleResponse(ClientRequest request, Mono responseMono) { - return responseMono - .flatMap(response -> handleResponse(request, response) - .thenReturn(response)) - .onErrorResume(WebClientResponseException.class, e -> handleWebClientResponseException(request, e) - .then(Mono.error(e))) - .onErrorResume(OAuth2AuthorizationException.class, e -> handleAuthorizationException(request, e) - .then(Mono.error(e))); + return responseMono.flatMap(response -> handleResponse(request, response).thenReturn(response)) + .onErrorResume(WebClientResponseException.class, + e -> handleWebClientResponseException(request, e).then(Mono.error(e))) + .onErrorResume(OAuth2AuthorizationException.class, + e -> handleAuthorizationException(request, e).then(Mono.error(e))); } private Mono handleResponse(ClientRequest request, ClientResponse response) { - return Mono.justOrEmpty(resolveErrorIfPossible(response)) - .flatMap(oauth2Error -> { - Mono> serverWebExchange = effectiveServerWebExchange(request); + return Mono.justOrEmpty(resolveErrorIfPossible(response)).flatMap(oauth2Error -> { + Mono> serverWebExchange = effectiveServerWebExchange(request); - Mono clientRegistrationId = effectiveClientRegistrationId(request); + Mono clientRegistrationId = effectiveClientRegistrationId(request); - return Mono.zip(currentAuthenticationMono, serverWebExchange, clientRegistrationId) - .flatMap(tuple3 -> handleAuthorizationFailure( - tuple3.getT1(), // Authentication principal - tuple3.getT2().orElse(null), // ServerWebExchange exchange - new ClientAuthorizationException( - oauth2Error, - tuple3.getT3()))); // String clientRegistrationId - }); + return Mono.zip(currentAuthenticationMono, serverWebExchange, clientRegistrationId) + .flatMap(tuple3 -> handleAuthorizationFailure(tuple3.getT1(), // Authentication + // principal + tuple3.getT2().orElse(null), // ServerWebExchange exchange + new ClientAuthorizationException(oauth2Error, tuple3.getT3()))); // String + // clientRegistrationId + }); } private OAuth2Error resolveErrorIfPossible(ClientResponse response) { @@ -651,8 +682,7 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements String wwwAuthenticateHeader = response.headers().header(HttpHeaders.WWW_AUTHENTICATE).get(0); Map authParameters = parseAuthParameters(wwwAuthenticateHeader); if (authParameters.containsKey(OAuth2ParameterNames.ERROR)) { - return new OAuth2Error( - authParameters.get(OAuth2ParameterNames.ERROR), + return new OAuth2Error(authParameters.get(OAuth2ParameterNames.ERROR), authParameters.get(OAuth2ParameterNames.ERROR_DESCRIPTION), authParameters.get(OAuth2ParameterNames.ERROR_URI)); } @@ -662,89 +692,77 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements private OAuth2Error resolveErrorIfPossible(int statusCode) { if (this.httpStatusToOAuth2ErrorCodeMap.containsKey(statusCode)) { - return new OAuth2Error( - this.httpStatusToOAuth2ErrorCodeMap.get(statusCode), - null, + return new OAuth2Error(this.httpStatusToOAuth2ErrorCodeMap.get(statusCode), null, "https://tools.ietf.org/html/rfc6750#section-3.1"); } return null; } private Map parseAuthParameters(String wwwAuthenticateHeader) { - return Stream.of(wwwAuthenticateHeader) - .filter(header -> !StringUtils.isEmpty(header)) + return Stream.of(wwwAuthenticateHeader).filter(header -> !StringUtils.isEmpty(header)) .filter(header -> header.toLowerCase().startsWith("bearer")) - .map(header -> header.substring("bearer".length())) - .map(header -> header.split(",")) - .flatMap(Stream::of) - .map(parameter -> parameter.split("=")) - .filter(parameter -> parameter.length > 1) - .collect(Collectors.toMap( - parameters -> parameters[0].trim(), - parameters -> parameters[1].trim().replace("\"", ""))); + .map(header -> header.substring("bearer".length())).map(header -> header.split(",")) + .flatMap(Stream::of).map(parameter -> parameter.split("=")) + .filter(parameter -> parameter.length > 1).collect(Collectors.toMap( + parameters -> parameters[0].trim(), parameters -> parameters[1].trim().replace("\"", ""))); } /** - * Handles the given http status code returned from a resource server - * by notifying the authorization failure handler if the http status - * code is in the {@link #httpStatusToOAuth2ErrorCodeMap}. - * + * Handles the given http status code returned from a resource server by notifying + * the authorization failure handler if the http status code is in the + * {@link #httpStatusToOAuth2ErrorCodeMap}. * @param request the request being processed * @param exception The root cause exception for the failure - * @return a {@link Mono} that completes empty after the authorization failure handler completes. + * @return a {@link Mono} that completes empty after the authorization failure + * handler completes. */ - private Mono handleWebClientResponseException(ClientRequest request, WebClientResponseException exception) { - return Mono.justOrEmpty(resolveErrorIfPossible(exception.getRawStatusCode())) - .flatMap(oauth2Error -> { - Mono> serverWebExchange = effectiveServerWebExchange(request); + private Mono handleWebClientResponseException(ClientRequest request, + WebClientResponseException exception) { + return Mono.justOrEmpty(resolveErrorIfPossible(exception.getRawStatusCode())).flatMap(oauth2Error -> { + Mono> serverWebExchange = effectiveServerWebExchange(request); - Mono clientRegistrationId = effectiveClientRegistrationId(request); + Mono clientRegistrationId = effectiveClientRegistrationId(request); - return Mono.zip(currentAuthenticationMono, serverWebExchange, clientRegistrationId) - .flatMap(tuple3 -> handleAuthorizationFailure( - tuple3.getT1(), // Authentication principal - tuple3.getT2().orElse(null), // ServerWebExchange exchange - new ClientAuthorizationException( - oauth2Error, - tuple3.getT3(), // String clientRegistrationId - exception))); - }); + return Mono.zip(currentAuthenticationMono, serverWebExchange, clientRegistrationId) + .flatMap(tuple3 -> handleAuthorizationFailure(tuple3.getT1(), // Authentication + // principal + tuple3.getT2().orElse(null), // ServerWebExchange exchange + new ClientAuthorizationException(oauth2Error, tuple3.getT3(), // String + // clientRegistrationId + exception))); + }); } /** - * Handles the given OAuth2AuthorizationException that occurred downstream - * by notifying the authorization failure handler. - * + * Handles the given OAuth2AuthorizationException that occurred downstream by + * notifying the authorization failure handler. * @param request the request being processed * @param exception the authorization exception to include in the failure event. - * @return a {@link Mono} that completes empty after the authorization failure handler completes. + * @return a {@link Mono} that completes empty after the authorization failure + * handler completes. */ private Mono handleAuthorizationException(ClientRequest request, OAuth2AuthorizationException exception) { Mono> serverWebExchange = effectiveServerWebExchange(request); return Mono.zip(currentAuthenticationMono, serverWebExchange) - .flatMap(tuple2 -> handleAuthorizationFailure( - tuple2.getT1(), // Authentication principal + .flatMap(tuple2 -> handleAuthorizationFailure(tuple2.getT1(), // Authentication + // principal tuple2.getT2().orElse(null), // ServerWebExchange exchange exception)); } /** * Delegates to the authorization failure handler of the failed authorization. - * * @param principal the principal associated with the failed authorization attempt * @param exchange the currently active exchange * @param exception the authorization exception to include in the failure event. - * @return a {@link Mono} that completes empty after the authorization failure handler completes. + * @return a {@link Mono} that completes empty after the authorization failure + * handler completes. */ - private Mono handleAuthorizationFailure( - Authentication principal, - ServerWebExchange exchange, + private Mono handleAuthorizationFailure(Authentication principal, ServerWebExchange exchange, OAuth2AuthorizationException exception) { - return this.authorizationFailureHandler.onAuthorizationFailure( - exception, - principal, + return this.authorizationFailureHandler.onAuthorizationFailure(exception, principal, createAttributes(exchange)); } @@ -754,5 +772,7 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements } return Collections.singletonMap(ServerWebExchange.class.getName(), exchange); } + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunction.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunction.java index 8694121c8e..3acaede9b3 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunction.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunction.java @@ -69,8 +69,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; /** - * Provides an easy mechanism for using an {@link OAuth2AuthorizedClient} to make OAuth 2.0 requests - * by including the {@link OAuth2AuthorizedClient#getAccessToken() access token} as a bearer token. + * Provides an easy mechanism for using an {@link OAuth2AuthorizedClient} to make OAuth + * 2.0 requests by including the {@link OAuth2AuthorizedClient#getAccessToken() access + * token} as a bearer token. * *

        * NOTE:This class is intended to be used in a {@code Servlet} environment. @@ -95,23 +96,25 @@ import java.util.stream.Stream; *

        Authentication and Authorization Failures

        * *

        - * Since 5.3, this filter function has the ability to forward authentication (HTTP 401 Unauthorized) - * and authorization (HTTP 403 Forbidden) failures from an OAuth 2.0 Resource Server - * to a {@link OAuth2AuthorizationFailureHandler}. - * A {@link RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} can be used - * to remove the cached {@link OAuth2AuthorizedClient}, so that future requests will result - * in a new token being retrieved from an Authorization Server, and sent to the Resource Server. + * Since 5.3, this filter function has the ability to forward authentication (HTTP 401 + * Unauthorized) and authorization (HTTP 403 Forbidden) failures from an OAuth 2.0 + * Resource Server to a {@link OAuth2AuthorizationFailureHandler}. A + * {@link RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} can be used to remove + * the cached {@link OAuth2AuthorizedClient}, so that future requests will result in a new + * token being retrieved from an Authorization Server, and sent to the Resource Server. * *

        - * If the {@link #ServletOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)} + * If the + * {@link #ServletOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)} * constructor is used, a {@link RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} * will be configured automatically. * *

        - * If the {@link #ServletOAuth2AuthorizedClientExchangeFilterFunction(OAuth2AuthorizedClientManager)} + * If the + * {@link #ServletOAuth2AuthorizedClientExchangeFilterFunction(OAuth2AuthorizedClientManager)} * constructor is used, a {@link RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} - * will NOT be configured automatically. - * It is recommended that you configure one via {@link #setAuthorizationFailureHandler(OAuth2AuthorizationFailureHandler)}. + * will NOT be configured automatically. It is recommended that you configure one + * via {@link #setAuthorizationFailureHandler(OAuth2AuthorizationFailureHandler)}. * * @author Rob Winch * @author Joe Grandja @@ -124,7 +127,8 @@ import java.util.stream.Stream; */ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implements ExchangeFilterFunction { - // Same key as in SecurityReactorContextConfiguration.SecurityReactorContextSubscriber.SECURITY_CONTEXT_ATTRIBUTES + // Same key as in + // SecurityReactorContextConfiguration.SecurityReactorContextSubscriber.SECURITY_CONTEXT_ATTRIBUTES static final String SECURITY_REACTOR_CONTEXT_ATTRIBUTES_KEY = "org.springframework.security.SECURITY_CONTEXT_ATTRIBUTES"; /** @@ -132,13 +136,17 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement */ private static final String OAUTH2_AUTHORIZED_CLIENT_ATTR_NAME = OAuth2AuthorizedClient.class.getName(); - private static final String CLIENT_REGISTRATION_ID_ATTR_NAME = OAuth2AuthorizedClient.class.getName().concat(".CLIENT_REGISTRATION_ID"); + private static final String CLIENT_REGISTRATION_ID_ATTR_NAME = OAuth2AuthorizedClient.class.getName() + .concat(".CLIENT_REGISTRATION_ID"); + private static final String AUTHENTICATION_ATTR_NAME = Authentication.class.getName(); + private static final String HTTP_SERVLET_REQUEST_ATTR_NAME = HttpServletRequest.class.getName(); + private static final String HTTP_SERVLET_RESPONSE_ATTR_NAME = HttpServletResponse.class.getName(); - private static final Authentication ANONYMOUS_AUTHENTICATION = new AnonymousAuthenticationToken( - "anonymous", "anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); + private static final Authentication ANONYMOUS_AUTHENTICATION = new AnonymousAuthenticationToken("anonymous", + "anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); @Deprecated private Duration accessTokenExpiresSkew = Duration.ofMinutes(1); @@ -158,51 +166,57 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement @FunctionalInterface private interface ClientResponseHandler { + Mono handleResponse(ClientRequest request, Mono response); + } public ServletOAuth2AuthorizedClientExchangeFilterFunction() { } /** - * Constructs a {@code ServletOAuth2AuthorizedClientExchangeFilterFunction} using the provided parameters. + * Constructs a {@code ServletOAuth2AuthorizedClientExchangeFilterFunction} using the + * provided parameters. * *

        - * When this constructor is used, authentication (HTTP 401) and authorization (HTTP 403) - * failures returned from an OAuth 2.0 Resource Server will NOT be forwarded to an - * {@link OAuth2AuthorizationFailureHandler}. - * Therefore, future requests to the Resource Server will most likely use the same (likely invalid) token, - * resulting in the same errors returned from the Resource Server. - * It is recommended to configure a {@link RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} - * via {@link #setAuthorizationFailureHandler(OAuth2AuthorizationFailureHandler)} - * so that authentication and authorization failures returned from a Resource Server - * will result in removing the authorized client, so that a new token is retrieved for future requests. + * When this constructor is used, authentication (HTTP 401) and authorization (HTTP + * 403) failures returned from an OAuth 2.0 Resource Server will NOT be + * forwarded to an {@link OAuth2AuthorizationFailureHandler}. Therefore, future + * requests to the Resource Server will most likely use the same (likely invalid) + * token, resulting in the same errors returned from the Resource Server. It is + * recommended to configure a + * {@link RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} via + * {@link #setAuthorizationFailureHandler(OAuth2AuthorizationFailureHandler)} so that + * authentication and authorization failures returned from a Resource Server will + * result in removing the authorized client, so that a new token is retrieved for + * future requests. * * @since 5.2 - * @param authorizedClientManager the {@link OAuth2AuthorizedClientManager} which manages the authorized client(s) + * @param authorizedClientManager the {@link OAuth2AuthorizedClientManager} which + * manages the authorized client(s) */ public ServletOAuth2AuthorizedClientExchangeFilterFunction(OAuth2AuthorizedClientManager authorizedClientManager) { Assert.notNull(authorizedClientManager, "authorizedClientManager cannot be null"); this.authorizedClientManager = authorizedClientManager; - this.clientResponseHandler = (request, responseMono) -> responseMono; + this.clientResponseHandler = (request, responseMono) -> responseMono; } /** - * Constructs a {@code ServletOAuth2AuthorizedClientExchangeFilterFunction} using the provided parameters. + * Constructs a {@code ServletOAuth2AuthorizedClientExchangeFilterFunction} using the + * provided parameters. * *

        - * Since 5.3, when this constructor is used, authentication (HTTP 401) - * and authorization (HTTP 403) failures returned from an OAuth 2.0 Resource Server - * will be forwarded to a {@link RemoveAuthorizedClientOAuth2AuthorizationFailureHandler}, + * Since 5.3, when this constructor is used, authentication (HTTP 401) and + * authorization (HTTP 403) failures returned from an OAuth 2.0 Resource Server will + * be forwarded to a {@link RemoveAuthorizedClientOAuth2AuthorizationFailureHandler}, * which will potentially remove the {@link OAuth2AuthorizedClient} from the given - * {@link OAuth2AuthorizedClientRepository}, depending on the OAuth 2.0 error code returned. - * Authentication failures returned from an OAuth 2.0 Resource Server typically indicate - * that the token is invalid, and should not be used in future requests. - * Removing the authorized client from the repository will ensure that the existing - * token will not be sent for future requests to the Resource Server, - * and a new token is retrieved from the Authorization Server and used for - * future requests to the Resource Server. - * + * {@link OAuth2AuthorizedClientRepository}, depending on the OAuth 2.0 error code + * returned. Authentication failures returned from an OAuth 2.0 Resource Server + * typically indicate that the token is invalid, and should not be used in future + * requests. Removing the authorized client from the repository will ensure that the + * existing token will not be sent for future requests to the Resource Server, and a + * new token is retrieved from the Authorization Server and used for future requests + * to the Resource Server. * @param clientRegistrationRepository the repository of client registrations * @param authorizedClientRepository the repository of authorized clients */ @@ -210,15 +224,13 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository) { - OAuth2AuthorizationFailureHandler authorizationFailureHandler = - new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( - (clientRegistrationId, principal, attributes) -> - authorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, - (HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), - (HttpServletResponse) attributes.get(HttpServletResponse.class.getName()))); - DefaultOAuth2AuthorizedClientManager defaultAuthorizedClientManager = - new DefaultOAuth2AuthorizedClientManager( - clientRegistrationRepository, authorizedClientRepository); + OAuth2AuthorizationFailureHandler authorizationFailureHandler = new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( + (clientRegistrationId, principal, attributes) -> authorizedClientRepository.removeAuthorizedClient( + clientRegistrationId, principal, + (HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), + (HttpServletResponse) attributes.get(HttpServletResponse.class.getName()))); + DefaultOAuth2AuthorizedClientManager defaultAuthorizedClientManager = new DefaultOAuth2AuthorizedClientManager( + clientRegistrationRepository, authorizedClientRepository); defaultAuthorizedClientManager.setAuthorizationFailureHandler(authorizationFailureHandler); this.authorizedClientManager = defaultAuthorizedClientManager; this.defaultAuthorizedClientManager = true; @@ -226,37 +238,41 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement } /** - * Sets the {@link OAuth2AccessTokenResponseClient} used for getting an {@link OAuth2AuthorizedClient} for the client_credentials grant. - * - * @deprecated Use {@link #ServletOAuth2AuthorizedClientExchangeFilterFunction(OAuth2AuthorizedClientManager)} instead. - * Create an instance of {@link ClientCredentialsOAuth2AuthorizedClientProvider} configured with a - * {@link ClientCredentialsOAuth2AuthorizedClientProvider#setAccessTokenResponseClient(OAuth2AccessTokenResponseClient) DefaultClientCredentialsTokenResponseClient} - * (or a custom one) and than supply it to {@link DefaultOAuth2AuthorizedClientManager#setAuthorizedClientProvider(OAuth2AuthorizedClientProvider) DefaultOAuth2AuthorizedClientManager}. - * + * Sets the {@link OAuth2AccessTokenResponseClient} used for getting an + * {@link OAuth2AuthorizedClient} for the client_credentials grant. + * @deprecated Use + * {@link #ServletOAuth2AuthorizedClientExchangeFilterFunction(OAuth2AuthorizedClientManager)} + * instead. Create an instance of + * {@link ClientCredentialsOAuth2AuthorizedClientProvider} configured with a + * {@link ClientCredentialsOAuth2AuthorizedClientProvider#setAccessTokenResponseClient(OAuth2AccessTokenResponseClient) + * DefaultClientCredentialsTokenResponseClient} (or a custom one) and than supply it + * to + * {@link DefaultOAuth2AuthorizedClientManager#setAuthorizedClientProvider(OAuth2AuthorizedClientProvider) + * DefaultOAuth2AuthorizedClientManager}. * @param clientCredentialsTokenResponseClient the client to use */ @Deprecated public void setClientCredentialsTokenResponseClient( OAuth2AccessTokenResponseClient clientCredentialsTokenResponseClient) { Assert.notNull(clientCredentialsTokenResponseClient, "clientCredentialsTokenResponseClient cannot be null"); - Assert.state(this.defaultAuthorizedClientManager, "The client cannot be set when the constructor used is \"ServletOAuth2AuthorizedClientExchangeFilterFunction(OAuth2AuthorizedClientManager)\". " + - "Instead, use the constructor \"ServletOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\"."); + Assert.state(this.defaultAuthorizedClientManager, + "The client cannot be set when the constructor used is \"ServletOAuth2AuthorizedClientExchangeFilterFunction(OAuth2AuthorizedClientManager)\". " + + "Instead, use the constructor \"ServletOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\"."); this.clientCredentialsTokenResponseClient = clientCredentialsTokenResponseClient; updateDefaultAuthorizedClientManager(); } private void updateDefaultAuthorizedClientManager() { - OAuth2AuthorizedClientProvider authorizedClientProvider = - OAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .refreshToken(configurer -> configurer.clockSkew(this.accessTokenExpiresSkew)) - .clientCredentials(this::updateClientCredentialsProvider) - .password(configurer -> configurer.clockSkew(this.accessTokenExpiresSkew)) - .build(); - ((DefaultOAuth2AuthorizedClientManager) this.authorizedClientManager).setAuthorizedClientProvider(authorizedClientProvider); + OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() + .authorizationCode().refreshToken(configurer -> configurer.clockSkew(this.accessTokenExpiresSkew)) + .clientCredentials(this::updateClientCredentialsProvider) + .password(configurer -> configurer.clockSkew(this.accessTokenExpiresSkew)).build(); + ((DefaultOAuth2AuthorizedClientManager) this.authorizedClientManager) + .setAuthorizedClientProvider(authorizedClientProvider); } - private void updateClientCredentialsProvider(OAuth2AuthorizedClientProviderBuilder.ClientCredentialsGrantBuilder builder) { + private void updateClientCredentialsProvider( + OAuth2AuthorizedClientProviderBuilder.ClientCredentialsGrantBuilder builder) { if (this.clientCredentialsTokenResponseClient != null) { builder.accessTokenResponseClient(this.clientCredentialsTokenResponseClient); } @@ -264,19 +280,21 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement } /** - * If true, a default {@link OAuth2AuthorizedClient} can be discovered from the current Authentication. It is - * recommended to be cautious with this feature since all HTTP requests will receive the access token if it can be - * resolved from the current Authentication. - * @param defaultOAuth2AuthorizedClient true if a default {@link OAuth2AuthorizedClient} should be used, else false. - * Default is false. + * If true, a default {@link OAuth2AuthorizedClient} can be discovered from the + * current Authentication. It is recommended to be cautious with this feature since + * all HTTP requests will receive the access token if it can be resolved from the + * current Authentication. + * @param defaultOAuth2AuthorizedClient true if a default + * {@link OAuth2AuthorizedClient} should be used, else false. Default is false. */ public void setDefaultOAuth2AuthorizedClient(boolean defaultOAuth2AuthorizedClient) { this.defaultOAuth2AuthorizedClient = defaultOAuth2AuthorizedClient; } /** - * If set, will be used as the default {@link ClientRegistration#getRegistrationId()}. It is - * recommended to be cautious with this feature since all HTTP requests will receive the access token. + * If set, will be used as the default {@link ClientRegistration#getRegistrationId()}. + * It is recommended to be cautious with this feature since all HTTP requests will + * receive the access token. * @param clientRegistrationId the id to use */ public void setDefaultClientRegistrationId(String clientRegistrationId) { @@ -284,7 +302,8 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement } /** - * Configures the builder with {@link #defaultRequest()} and adds this as a {@link ExchangeFilterFunction} + * Configures the builder with {@link #defaultRequest()} and adds this as a + * {@link ExchangeFilterFunction} * @return the {@link Consumer} to configure the builder */ public Consumer oauth2Configuration() { @@ -292,10 +311,12 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement } /** - * Provides defaults for the {@link HttpServletRequest} and the {@link HttpServletResponse} using - * {@link RequestContextHolder}. It also provides defaults for the {@link Authentication} using - * {@link SecurityContextHolder}. It also can default the {@link OAuth2AuthorizedClient} using the - * {@link #clientRegistrationId(String)} or the {@link #authentication(Authentication)}. + * Provides defaults for the {@link HttpServletRequest} and the + * {@link HttpServletResponse} using {@link RequestContextHolder}. It also provides + * defaults for the {@link Authentication} using {@link SecurityContextHolder}. It + * also can default the {@link OAuth2AuthorizedClient} using the + * {@link #clientRegistrationId(String)} or the + * {@link #authentication(Authentication)}. * @return the {@link Consumer} to populate the attributes */ public Consumer> defaultRequest() { @@ -306,9 +327,8 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement } /** - * Modifies the {@link ClientRequest#attributes()} to include the {@link OAuth2AuthorizedClient} to be used for - * providing the Bearer Token. - * + * Modifies the {@link ClientRequest#attributes()} to include the + * {@link OAuth2AuthorizedClient} to be used for providing the Bearer Token. * @param authorizedClient the {@link OAuth2AuthorizedClient} to use. * @return the {@link Consumer} to populate the attributes */ @@ -316,16 +336,17 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement return attributes -> { if (authorizedClient == null) { attributes.remove(OAUTH2_AUTHORIZED_CLIENT_ATTR_NAME); - } else { + } + else { attributes.put(OAUTH2_AUTHORIZED_CLIENT_ATTR_NAME, authorizedClient); } }; } /** - * Modifies the {@link ClientRequest#attributes()} to include the {@link ClientRegistration#getRegistrationId()} to - * be used to look up the {@link OAuth2AuthorizedClient}. - * + * Modifies the {@link ClientRequest#attributes()} to include the + * {@link ClientRegistration#getRegistrationId()} to be used to look up the + * {@link OAuth2AuthorizedClient}. * @param clientRegistrationId the {@link ClientRegistration#getRegistrationId()} to * be used to look up the {@link OAuth2AuthorizedClient}. * @return the {@link Consumer} to populate the attributes @@ -335,10 +356,10 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement } /** - * Modifies the {@link ClientRequest#attributes()} to include the {@link Authentication} used to - * look up and save the {@link OAuth2AuthorizedClient}. The value is defaulted in + * Modifies the {@link ClientRequest#attributes()} to include the + * {@link Authentication} used to look up and save the {@link OAuth2AuthorizedClient}. + * The value is defaulted in * {@link ServletOAuth2AuthorizedClientExchangeFilterFunction#defaultRequest()} - * * @param authentication the {@link Authentication} to use. * @return the {@link Consumer} to populate the attributes */ @@ -347,10 +368,10 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement } /** - * Modifies the {@link ClientRequest#attributes()} to include the {@link HttpServletRequest} used to - * look up and save the {@link OAuth2AuthorizedClient}. The value is defaulted in + * Modifies the {@link ClientRequest#attributes()} to include the + * {@link HttpServletRequest} used to look up and save the + * {@link OAuth2AuthorizedClient}. The value is defaulted in * {@link ServletOAuth2AuthorizedClientExchangeFilterFunction#defaultRequest()} - * * @param request the {@link HttpServletRequest} to use. * @return the {@link Consumer} to populate the attributes */ @@ -359,10 +380,10 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement } /** - * Modifies the {@link ClientRequest#attributes()} to include the {@link HttpServletResponse} used to - * save the {@link OAuth2AuthorizedClient}. The value is defaulted in + * Modifies the {@link ClientRequest#attributes()} to include the + * {@link HttpServletResponse} used to save the {@link OAuth2AuthorizedClient}. The + * value is defaulted in * {@link ServletOAuth2AuthorizedClientExchangeFilterFunction#defaultRequest()} - * * @param response the {@link HttpServletResponse} to use. * @return the {@link Consumer} to populate the attributes */ @@ -373,38 +394,39 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement /** * An access token will be considered expired by comparing its expiration to now + * this skewed Duration. The default is 1 minute. - * - * @deprecated The {@code accessTokenExpiresSkew} should be configured with the specific {@link OAuth2AuthorizedClientProvider} implementation, - * e.g. {@link ClientCredentialsOAuth2AuthorizedClientProvider#setClockSkew(Duration) ClientCredentialsOAuth2AuthorizedClientProvider} or - * {@link RefreshTokenOAuth2AuthorizedClientProvider#setClockSkew(Duration) RefreshTokenOAuth2AuthorizedClientProvider}. - * + * @deprecated The {@code accessTokenExpiresSkew} should be configured with the + * specific {@link OAuth2AuthorizedClientProvider} implementation, e.g. + * {@link ClientCredentialsOAuth2AuthorizedClientProvider#setClockSkew(Duration) + * ClientCredentialsOAuth2AuthorizedClientProvider} or + * {@link RefreshTokenOAuth2AuthorizedClientProvider#setClockSkew(Duration) + * RefreshTokenOAuth2AuthorizedClientProvider}. * @param accessTokenExpiresSkew the Duration to use. */ @Deprecated public void setAccessTokenExpiresSkew(Duration accessTokenExpiresSkew) { Assert.notNull(accessTokenExpiresSkew, "accessTokenExpiresSkew cannot be null"); - Assert.state(this.defaultAuthorizedClientManager, "The accessTokenExpiresSkew cannot be set when the constructor used is \"ServletOAuth2AuthorizedClientExchangeFilterFunction(OAuth2AuthorizedClientManager)\". " + - "Instead, use the constructor \"ServletOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\"."); + Assert.state(this.defaultAuthorizedClientManager, + "The accessTokenExpiresSkew cannot be set when the constructor used is \"ServletOAuth2AuthorizedClientExchangeFilterFunction(OAuth2AuthorizedClientManager)\". " + + "Instead, use the constructor \"ServletOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\"."); this.accessTokenExpiresSkew = accessTokenExpiresSkew; updateDefaultAuthorizedClientManager(); } /** - * Sets the {@link OAuth2AuthorizationFailureHandler} that handles - * authentication and authorization failures when communicating - * to the OAuth 2.0 Resource Server. + * Sets the {@link OAuth2AuthorizationFailureHandler} that handles authentication and + * authorization failures when communicating to the OAuth 2.0 Resource Server. * *

        - * For example, a {@link RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} - * is typically used to remove the cached {@link OAuth2AuthorizedClient}, - * so that the same token is no longer used in future requests to the Resource Server. + * For example, a {@link RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} is + * typically used to remove the cached {@link OAuth2AuthorizedClient}, so that the + * same token is no longer used in future requests to the Resource Server. * *

        - * The failure handler used by default depends on which constructor was used - * to construct this {@link ServletOAuth2AuthorizedClientExchangeFilterFunction}. - * See the constructors for more details. - * - * @param authorizationFailureHandler the {@link OAuth2AuthorizationFailureHandler} that handles authentication and authorization failures + * The failure handler used by default depends on which constructor was used to + * construct this {@link ServletOAuth2AuthorizedClientExchangeFilterFunction}. See the + * constructors for more details. + * @param authorizationFailureHandler the {@link OAuth2AuthorizationFailureHandler} + * that handles authentication and authorization failures * @since 5.3 */ public void setAuthorizationFailureHandler(OAuth2AuthorizationFailureHandler authorizationFailureHandler) { @@ -417,11 +439,9 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement return mergeRequestAttributesIfNecessary(request) .filter(req -> req.attribute(OAUTH2_AUTHORIZED_CLIENT_ATTR_NAME).isPresent()) .flatMap(req -> reauthorizeClient(getOAuth2AuthorizedClient(req.attributes()), req)) - .switchIfEmpty(Mono.defer(() -> - mergeRequestAttributesIfNecessary(request) - .filter(req -> resolveClientRegistrationId(req) != null) - .flatMap(req -> authorizeClient(resolveClientRegistrationId(req), req)) - )) + .switchIfEmpty(Mono.defer(() -> mergeRequestAttributesIfNecessary(request) + .filter(req -> resolveClientRegistrationId(req) != null) + .flatMap(req -> authorizeClient(resolveClientRegistrationId(req), req)))) .map(authorizedClient -> bearer(request, authorizedClient)) .flatMap(requestWithBearer -> exchangeAndHandleResponse(requestWithBearer, next)) .switchIfEmpty(Mono.defer(() -> exchangeAndHandleResponse(request, next))); @@ -433,24 +453,25 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement } private Mono mergeRequestAttributesIfNecessary(ClientRequest request) { - if (!request.attribute(HTTP_SERVLET_REQUEST_ATTR_NAME).isPresent() || - !request.attribute(HTTP_SERVLET_RESPONSE_ATTR_NAME).isPresent() || - !request.attribute(AUTHENTICATION_ATTR_NAME).isPresent()) { + if (!request.attribute(HTTP_SERVLET_REQUEST_ATTR_NAME).isPresent() + || !request.attribute(HTTP_SERVLET_RESPONSE_ATTR_NAME).isPresent() + || !request.attribute(AUTHENTICATION_ATTR_NAME).isPresent()) { return mergeRequestAttributesFromContext(request); - } else { + } + else { return Mono.just(request); } } private Mono mergeRequestAttributesFromContext(ClientRequest request) { ClientRequest.Builder builder = ClientRequest.from(request); - return Mono.subscriberContext() - .map(ctx -> builder.attributes(attrs -> populateRequestAttributes(attrs, ctx))) + return Mono.subscriberContext().map(ctx -> builder.attributes(attrs -> populateRequestAttributes(attrs, ctx))) .map(ClientRequest.Builder::build); } private void populateRequestAttributes(Map attrs, Context ctx) { - // NOTE: SecurityReactorContextConfiguration.SecurityReactorContextSubscriber adds this key + // NOTE: SecurityReactorContextConfiguration.SecurityReactorContextSubscriber adds + // this key if (!ctx.hasKey(SECURITY_REACTOR_CONTEXT_ATTRIBUTES_KEY)) { return; } @@ -470,13 +491,12 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement } private void populateDefaultRequestResponse(Map attrs) { - if (attrs.containsKey(HTTP_SERVLET_REQUEST_ATTR_NAME) && - attrs.containsKey(HTTP_SERVLET_RESPONSE_ATTR_NAME)) { + if (attrs.containsKey(HTTP_SERVLET_REQUEST_ATTR_NAME) && attrs.containsKey(HTTP_SERVLET_RESPONSE_ATTR_NAME)) { return; } RequestAttributes context = RequestContextHolder.getRequestAttributes(); if (context instanceof ServletRequestAttributes) { - attrs.putIfAbsent(HTTP_SERVLET_REQUEST_ATTR_NAME, ((ServletRequestAttributes) context).getRequest()); + attrs.putIfAbsent(HTTP_SERVLET_REQUEST_ATTR_NAME, ((ServletRequestAttributes) context).getRequest()); attrs.putIfAbsent(HTTP_SERVLET_RESPONSE_ATTR_NAME, ((ServletRequestAttributes) context).getResponse()); } } @@ -496,8 +516,7 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement clientRegistrationId = this.defaultClientRegistrationId; } Authentication authentication = getAuthentication(attrs); - if (clientRegistrationId == null - && this.defaultOAuth2AuthorizedClient + if (clientRegistrationId == null && this.defaultOAuth2AuthorizedClient && authentication instanceof OAuth2AuthenticationToken) { clientRegistrationId = ((OAuth2AuthenticationToken) authentication).getAuthorizedClientRegistrationId(); } @@ -516,7 +535,8 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement HttpServletRequest servletRequest = getRequest(attrs); HttpServletResponse servletResponse = getResponse(attrs); - OAuth2AuthorizeRequest.Builder builder = OAuth2AuthorizeRequest.withClientRegistrationId(clientRegistrationId).principal(authentication); + OAuth2AuthorizeRequest.Builder builder = OAuth2AuthorizeRequest.withClientRegistrationId(clientRegistrationId) + .principal(authentication); builder.attributes(attributes -> { if (servletRequest != null) { attributes.put(HttpServletRequest.class.getName(), servletRequest); @@ -531,10 +551,12 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement // 'authorizedClientManager.authorize()' needs to be executed // on a dedicated thread via subscribeOn(Schedulers.boundedElastic()) // since it performs a blocking I/O operation using RestTemplate internally - return Mono.fromSupplier(() -> this.authorizedClientManager.authorize(authorizeRequest)).subscribeOn(Schedulers.boundedElastic()); + return Mono.fromSupplier(() -> this.authorizedClientManager.authorize(authorizeRequest)) + .subscribeOn(Schedulers.boundedElastic()); } - private Mono reauthorizeClient(OAuth2AuthorizedClient authorizedClient, ClientRequest request) { + private Mono reauthorizeClient(OAuth2AuthorizedClient authorizedClient, + ClientRequest request) { if (this.authorizedClientManager == null) { return Mono.just(authorizedClient); } @@ -546,7 +568,8 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement HttpServletRequest servletRequest = getRequest(attrs); HttpServletResponse servletResponse = getResponse(attrs); - OAuth2AuthorizeRequest.Builder builder = OAuth2AuthorizeRequest.withAuthorizedClient(authorizedClient).principal(authentication); + OAuth2AuthorizeRequest.Builder builder = OAuth2AuthorizeRequest.withAuthorizedClient(authorizedClient) + .principal(authentication); builder.attributes(attributes -> { if (servletRequest != null) { attributes.put(HttpServletRequest.class.getName(), servletRequest); @@ -561,14 +584,14 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement // 'authorizedClientManager.authorize()' needs to be executed // on a dedicated thread via subscribeOn(Schedulers.boundedElastic()) // since it performs a blocking I/O operation using RestTemplate internally - return Mono.fromSupplier(() -> this.authorizedClientManager.authorize(reauthorizeRequest)).subscribeOn(Schedulers.boundedElastic()); + return Mono.fromSupplier(() -> this.authorizedClientManager.authorize(reauthorizeRequest)) + .subscribeOn(Schedulers.boundedElastic()); } private ClientRequest bearer(ClientRequest request, OAuth2AuthorizedClient authorizedClient) { return ClientRequest.from(request) - .headers(headers -> headers.setBearerAuth(authorizedClient.getAccessToken().getTokenValue())) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .headers(headers -> headers.setBearerAuth(authorizedClient.getAccessToken().getTokenValue())) + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); } static OAuth2AuthorizedClient getOAuth2AuthorizedClient(Map attrs) { @@ -616,15 +639,14 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement private static class AuthorizationFailureForwarder implements ClientResponseHandler { /** - * A map of HTTP status code to OAuth 2.0 error code for - * HTTP status codes that should be interpreted as - * authentication or authorization failures. + * A map of HTTP status code to OAuth 2.0 error code for HTTP status codes that + * should be interpreted as authentication or authorization failures. */ private final Map httpStatusToOAuth2ErrorCodeMap; /** - * The {@link OAuth2AuthorizationFailureHandler} to notify - * when an authentication/authorization failure occurs. + * The {@link OAuth2AuthorizationFailureHandler} to notify when an + * authentication/authorization failure occurs. */ private final OAuth2AuthorizationFailureHandler authorizationFailureHandler; @@ -640,33 +662,30 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement @Override public Mono handleResponse(ClientRequest request, Mono responseMono) { - return responseMono - .flatMap(response -> handleResponse(request, response) - .thenReturn(response)) - .onErrorResume(WebClientResponseException.class, e -> handleWebClientResponseException(request, e) - .then(Mono.error(e))) - .onErrorResume(OAuth2AuthorizationException.class, e -> handleAuthorizationException(request, e) - .then(Mono.error(e))); + return responseMono.flatMap(response -> handleResponse(request, response).thenReturn(response)) + .onErrorResume(WebClientResponseException.class, + e -> handleWebClientResponseException(request, e).then(Mono.error(e))) + .onErrorResume(OAuth2AuthorizationException.class, + e -> handleAuthorizationException(request, e).then(Mono.error(e))); } private Mono handleResponse(ClientRequest request, ClientResponse response) { - return Mono.justOrEmpty(resolveErrorIfPossible(response)) - .flatMap(oauth2Error -> { - Map attrs = request.attributes(); - OAuth2AuthorizedClient authorizedClient = getOAuth2AuthorizedClient(attrs); - if (authorizedClient == null) { - return Mono.empty(); - } + return Mono.justOrEmpty(resolveErrorIfPossible(response)).flatMap(oauth2Error -> { + Map attrs = request.attributes(); + OAuth2AuthorizedClient authorizedClient = getOAuth2AuthorizedClient(attrs); + if (authorizedClient == null) { + return Mono.empty(); + } - ClientAuthorizationException authorizationException = new ClientAuthorizationException( - oauth2Error, authorizedClient.getClientRegistration().getRegistrationId()); + ClientAuthorizationException authorizationException = new ClientAuthorizationException(oauth2Error, + authorizedClient.getClientRegistration().getRegistrationId()); - Authentication principal = createAuthentication(authorizedClient.getPrincipalName()); - HttpServletRequest servletRequest = getRequest(attrs); - HttpServletResponse servletResponse = getResponse(attrs); + Authentication principal = createAuthentication(authorizedClient.getPrincipalName()); + HttpServletRequest servletRequest = getRequest(attrs); + HttpServletResponse servletResponse = getResponse(attrs); - return handleAuthorizationFailure(authorizationException, principal, servletRequest, servletResponse); - }); + return handleAuthorizationFailure(authorizationException, principal, servletRequest, servletResponse); + }); } private OAuth2Error resolveErrorIfPossible(ClientResponse response) { @@ -675,8 +694,7 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement String wwwAuthenticateHeader = response.headers().header(HttpHeaders.WWW_AUTHENTICATE).get(0); Map authParameters = parseAuthParameters(wwwAuthenticateHeader); if (authParameters.containsKey(OAuth2ParameterNames.ERROR)) { - return new OAuth2Error( - authParameters.get(OAuth2ParameterNames.ERROR), + return new OAuth2Error(authParameters.get(OAuth2ParameterNames.ERROR), authParameters.get(OAuth2ParameterNames.ERROR_DESCRIPTION), authParameters.get(OAuth2ParameterNames.ERROR_URI)); } @@ -686,103 +704,102 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement private OAuth2Error resolveErrorIfPossible(int statusCode) { if (this.httpStatusToOAuth2ErrorCodeMap.containsKey(statusCode)) { - return new OAuth2Error( - this.httpStatusToOAuth2ErrorCodeMap.get(statusCode), - null, + return new OAuth2Error(this.httpStatusToOAuth2ErrorCodeMap.get(statusCode), null, "https://tools.ietf.org/html/rfc6750#section-3.1"); } return null; } private Map parseAuthParameters(String wwwAuthenticateHeader) { - return Stream.of(wwwAuthenticateHeader) - .filter(header -> !StringUtils.isEmpty(header)) + return Stream.of(wwwAuthenticateHeader).filter(header -> !StringUtils.isEmpty(header)) .filter(header -> header.toLowerCase().startsWith("bearer")) - .map(header -> header.substring("bearer".length())) - .map(header -> header.split(",")) - .flatMap(Stream::of) - .map(parameter -> parameter.split("=")) - .filter(parameter -> parameter.length > 1) - .collect(Collectors.toMap( - parameters -> parameters[0].trim(), - parameters -> parameters[1].trim().replace("\"", ""))); + .map(header -> header.substring("bearer".length())).map(header -> header.split(",")) + .flatMap(Stream::of).map(parameter -> parameter.split("=")) + .filter(parameter -> parameter.length > 1).collect(Collectors.toMap( + parameters -> parameters[0].trim(), parameters -> parameters[1].trim().replace("\"", ""))); } /** - * Handles the given http status code returned from a resource server - * by notifying the authorization failure handler if the http status - * code is in the {@link #httpStatusToOAuth2ErrorCodeMap}. - * + * Handles the given http status code returned from a resource server by notifying + * the authorization failure handler if the http status code is in the + * {@link #httpStatusToOAuth2ErrorCodeMap}. * @param request the request being processed * @param exception The root cause exception for the failure - * @return a {@link Mono} that completes empty after the authorization failure handler completes + * @return a {@link Mono} that completes empty after the authorization failure + * handler completes */ - private Mono handleWebClientResponseException(ClientRequest request, WebClientResponseException exception) { - return Mono.justOrEmpty(resolveErrorIfPossible(exception.getRawStatusCode())) - .flatMap(oauth2Error -> { - Map attrs = request.attributes(); - OAuth2AuthorizedClient authorizedClient = getOAuth2AuthorizedClient(attrs); - if (authorizedClient == null) { - return Mono.empty(); - } + private Mono handleWebClientResponseException(ClientRequest request, + WebClientResponseException exception) { + return Mono.justOrEmpty(resolveErrorIfPossible(exception.getRawStatusCode())).flatMap(oauth2Error -> { + Map attrs = request.attributes(); + OAuth2AuthorizedClient authorizedClient = getOAuth2AuthorizedClient(attrs); + if (authorizedClient == null) { + return Mono.empty(); + } - ClientAuthorizationException authorizationException = new ClientAuthorizationException( - oauth2Error, authorizedClient.getClientRegistration().getRegistrationId(), exception); + ClientAuthorizationException authorizationException = new ClientAuthorizationException(oauth2Error, + authorizedClient.getClientRegistration().getRegistrationId(), exception); - Authentication principal = createAuthentication(authorizedClient.getPrincipalName()); - HttpServletRequest servletRequest = getRequest(attrs); - HttpServletResponse servletResponse = getResponse(attrs); + Authentication principal = createAuthentication(authorizedClient.getPrincipalName()); + HttpServletRequest servletRequest = getRequest(attrs); + HttpServletResponse servletResponse = getResponse(attrs); - return handleAuthorizationFailure(authorizationException, principal, servletRequest, servletResponse); - }); + return handleAuthorizationFailure(authorizationException, principal, servletRequest, servletResponse); + }); } /** * Handles the given {@link OAuth2AuthorizationException} that occurred downstream * by notifying the authorization failure handler. - * * @param request the request being processed - * @param authorizationException the authorization exception to include in the failure event - * @return a {@link Mono} that completes empty after the authorization failure handler completes + * @param authorizationException the authorization exception to include in the + * failure event + * @return a {@link Mono} that completes empty after the authorization failure + * handler completes */ - private Mono handleAuthorizationException(ClientRequest request, OAuth2AuthorizationException authorizationException) { - return Mono.justOrEmpty(request) - .flatMap(req -> { - Map attrs = req.attributes(); - OAuth2AuthorizedClient authorizedClient = getOAuth2AuthorizedClient(attrs); - if (authorizedClient == null) { - return Mono.empty(); - } + private Mono handleAuthorizationException(ClientRequest request, + OAuth2AuthorizationException authorizationException) { + return Mono.justOrEmpty(request).flatMap(req -> { + Map attrs = req.attributes(); + OAuth2AuthorizedClient authorizedClient = getOAuth2AuthorizedClient(attrs); + if (authorizedClient == null) { + return Mono.empty(); + } - Authentication principal = createAuthentication(authorizedClient.getPrincipalName()); - HttpServletRequest servletRequest = getRequest(attrs); - HttpServletResponse servletResponse = getResponse(attrs); + Authentication principal = createAuthentication(authorizedClient.getPrincipalName()); + HttpServletRequest servletRequest = getRequest(attrs); + HttpServletResponse servletResponse = getResponse(attrs); - return handleAuthorizationFailure(authorizationException, principal, servletRequest, servletResponse); - }); + return handleAuthorizationFailure(authorizationException, principal, servletRequest, servletResponse); + }); } /** - * Delegates the failed authorization to the {@link OAuth2AuthorizationFailureHandler}. - * - * @param exception the {@link OAuth2AuthorizationException} to include in the failure event + * Delegates the failed authorization to the + * {@link OAuth2AuthorizationFailureHandler}. + * @param exception the {@link OAuth2AuthorizationException} to include in the + * failure event * @param principal the principal associated with the failed authorization attempt * @param servletRequest the currently active {@code HttpServletRequest} * @param servletResponse the currently active {@code HttpServletResponse} - * @return a {@link Mono} that completes empty after the {@link OAuth2AuthorizationFailureHandler} completes + * @return a {@link Mono} that completes empty after the + * {@link OAuth2AuthorizationFailureHandler} completes */ - private Mono handleAuthorizationFailure(OAuth2AuthorizationException exception, - Authentication principal, HttpServletRequest servletRequest, HttpServletResponse servletResponse) { - Runnable runnable = () -> this.authorizationFailureHandler.onAuthorizationFailure( - exception, principal, createAttributes(servletRequest, servletResponse)); + private Mono handleAuthorizationFailure(OAuth2AuthorizationException exception, Authentication principal, + HttpServletRequest servletRequest, HttpServletResponse servletResponse) { + Runnable runnable = () -> this.authorizationFailureHandler.onAuthorizationFailure(exception, principal, + createAttributes(servletRequest, servletResponse)); return Mono.fromRunnable(runnable).subscribeOn(Schedulers.boundedElastic()).then(); } - private static Map createAttributes(HttpServletRequest servletRequest, HttpServletResponse servletResponse) { + private static Map createAttributes(HttpServletRequest servletRequest, + HttpServletResponse servletResponse) { Map attributes = new HashMap<>(); attributes.put(HttpServletRequest.class.getName(), servletRequest); attributes.put(HttpServletResponse.class.getName(), servletResponse); return attributes; } + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/result/method/annotation/OAuth2AuthorizedClientArgumentResolver.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/result/method/annotation/OAuth2AuthorizedClientArgumentResolver.java index 798fafc30c..b79bce181f 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/result/method/annotation/OAuth2AuthorizedClientArgumentResolver.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/result/method/annotation/OAuth2AuthorizedClientArgumentResolver.java @@ -39,12 +39,12 @@ import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /** - * An implementation of a {@link HandlerMethodArgumentResolver} that is capable - * of resolving a method parameter to an argument value of type {@link OAuth2AuthorizedClient}. + * An implementation of a {@link HandlerMethodArgumentResolver} that is capable of + * resolving a method parameter to an argument value of type + * {@link OAuth2AuthorizedClient}. * *

        - * For example: - *

        + * For example: 
          * @Controller
          * public class MyController {
          *     @GetMapping("/authorized-client")
        @@ -60,15 +60,19 @@ import reactor.core.publisher.Mono;
          * @see RegisteredOAuth2AuthorizedClient
          */
         public final class OAuth2AuthorizedClientArgumentResolver implements HandlerMethodArgumentResolver {
        +
         	private static final AnonymousAuthenticationToken ANONYMOUS_USER_TOKEN = new AnonymousAuthenticationToken(
         			"anonymous", "anonymousUser", AuthorityUtils.createAuthorityList("ROLE_USER"));
        +
         	private ReactiveOAuth2AuthorizedClientManager authorizedClientManager;
         
         	/**
        -	 * Constructs an {@code OAuth2AuthorizedClientArgumentResolver} using the provided parameters.
        +	 * Constructs an {@code OAuth2AuthorizedClientArgumentResolver} using the provided
        +	 * parameters.
         	 *
         	 * @since 5.2
        -	 * @param authorizedClientManager the {@link ReactiveOAuth2AuthorizedClientManager} which manages the authorized client(s)
        +	 * @param authorizedClientManager the {@link ReactiveOAuth2AuthorizedClientManager}
        +	 * which manages the authorized client(s)
         	 */
         	public OAuth2AuthorizedClientArgumentResolver(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
         		Assert.notNull(authorizedClientManager, "authorizedClientManager cannot be null");
        @@ -76,35 +80,36 @@ public final class OAuth2AuthorizedClientArgumentResolver implements HandlerMeth
         	}
         
         	/**
        -	 * Constructs an {@code OAuth2AuthorizedClientArgumentResolver} using the provided parameters.
        -	 *
        +	 * Constructs an {@code OAuth2AuthorizedClientArgumentResolver} using the provided
        +	 * parameters.
         	 * @param clientRegistrationRepository the repository of client registrations
         	 * @param authorizedClientRepository the repository of authorized clients
         	 */
         	public OAuth2AuthorizedClientArgumentResolver(ReactiveClientRegistrationRepository clientRegistrationRepository,
        -													ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
        +			ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
         		Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
         		Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null");
        -		this.authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager(
        -				clientRegistrationRepository, authorizedClientRepository);
        +		this.authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager(clientRegistrationRepository,
        +				authorizedClientRepository);
         	}
         
         	@Override
         	public boolean supportsParameter(MethodParameter parameter) {
        -		return AnnotatedElementUtils.findMergedAnnotation(parameter.getParameter(), RegisteredOAuth2AuthorizedClient.class) != null;
        +		return AnnotatedElementUtils.findMergedAnnotation(parameter.getParameter(),
        +				RegisteredOAuth2AuthorizedClient.class) != null;
         	}
         
         	@Override
        -	public Mono resolveArgument(MethodParameter parameter, BindingContext bindingContext, ServerWebExchange exchange) {
        +	public Mono resolveArgument(MethodParameter parameter, BindingContext bindingContext,
        +			ServerWebExchange exchange) {
         		return Mono.defer(() -> {
         			RegisteredOAuth2AuthorizedClient authorizedClientAnnotation = AnnotatedElementUtils
         					.findMergedAnnotation(parameter.getParameter(), RegisteredOAuth2AuthorizedClient.class);
         
        -			String clientRegistrationId = StringUtils.hasLength(authorizedClientAnnotation.registrationId()) ?
        -					authorizedClientAnnotation.registrationId() : null;
        +			String clientRegistrationId = StringUtils.hasLength(authorizedClientAnnotation.registrationId())
        +					? authorizedClientAnnotation.registrationId() : null;
         
        -			return authorizeRequest(clientRegistrationId, exchange)
        -					.flatMap(this.authorizedClientManager::authorize);
        +			return authorizeRequest(clientRegistrationId, exchange).flatMap(this.authorizedClientManager::authorize);
         		});
         	}
         
        @@ -113,35 +118,30 @@ public final class OAuth2AuthorizedClientArgumentResolver implements HandlerMeth
         
         		Mono defaultedRegistrationId = Mono.justOrEmpty(registrationId)
         				.switchIfEmpty(clientRegistrationId(defaultedAuthentication))
        -				.switchIfEmpty(Mono.error(() -> new IllegalArgumentException("The clientRegistrationId could not be resolved. Please provide one")));
        +				.switchIfEmpty(Mono.error(() -> new IllegalArgumentException(
        +						"The clientRegistrationId could not be resolved. Please provide one")));
         
         		Mono defaultedExchange = Mono.justOrEmpty(exchange)
         				.switchIfEmpty(currentServerWebExchange());
         
         		return Mono.zip(defaultedRegistrationId, defaultedAuthentication, defaultedExchange)
        -				.map(t3 -> OAuth2AuthorizeRequest.withClientRegistrationId(t3.getT1())
        -						.principal(t3.getT2())
        -						.attribute(ServerWebExchange.class.getName(), t3.getT3())
        -						.build()
        -				);
        +				.map(t3 -> OAuth2AuthorizeRequest.withClientRegistrationId(t3.getT1()).principal(t3.getT2())
        +						.attribute(ServerWebExchange.class.getName(), t3.getT3()).build());
         	}
         
         	private Mono currentAuthentication() {
        -		return ReactiveSecurityContextHolder.getContext()
        -				.map(SecurityContext::getAuthentication)
        +		return ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication)
         				.defaultIfEmpty(ANONYMOUS_USER_TOKEN);
         	}
         
         	private Mono clientRegistrationId(Mono authentication) {
        -		return authentication
        -				.filter(t -> t instanceof OAuth2AuthenticationToken)
        -				.cast(OAuth2AuthenticationToken.class)
        +		return authentication.filter(t -> t instanceof OAuth2AuthenticationToken).cast(OAuth2AuthenticationToken.class)
         				.map(OAuth2AuthenticationToken::getAuthorizedClientRegistrationId);
         	}
         
         	private Mono currentServerWebExchange() {
        -		return Mono.subscriberContext()
        -				.filter(c -> c.hasKey(ServerWebExchange.class))
        +		return Mono.subscriberContext().filter(c -> c.hasKey(ServerWebExchange.class))
         				.map(c -> c.get(ServerWebExchange.class));
         	}
        +
         }
        diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository.java
        index 6357dc38c9..79746fe621 100644
        --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository.java
        +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository.java
        @@ -28,12 +28,12 @@ import org.springframework.web.server.ServerWebExchange;
         import reactor.core.publisher.Mono;
         
         /**
        - * An implementation of an {@link ServerOAuth2AuthorizedClientRepository} that
        - * delegates to the provided {@link ServerOAuth2AuthorizedClientRepository} if the current
        - * {@code Principal} is authenticated, otherwise,
        - * to the default (or provided) {@link ServerOAuth2AuthorizedClientRepository}
        - * if the current request is unauthenticated (or anonymous).
        - * The default {@code ReactiveOAuth2AuthorizedClientRepository} is
        + * An implementation of an {@link ServerOAuth2AuthorizedClientRepository} that delegates
        + * to the provided {@link ServerOAuth2AuthorizedClientRepository} if the current
        + * {@code Principal} is authenticated, otherwise, to the default (or provided)
        + * {@link ServerOAuth2AuthorizedClientRepository} if the current request is
        + * unauthenticated (or anonymous). The default
        + * {@code ReactiveOAuth2AuthorizedClientRepository} is
          * {@link WebSessionServerOAuth2AuthorizedClientRepository}.
          *
          * @author Rob Winch
        @@ -45,25 +45,29 @@ import reactor.core.publisher.Mono;
          */
         public final class AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository
         		implements ServerOAuth2AuthorizedClientRepository {
        +
         	private final AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
        +
         	private final ReactiveOAuth2AuthorizedClientService authorizedClientService;
        +
         	private ServerOAuth2AuthorizedClientRepository anonymousAuthorizedClientRepository = new WebSessionServerOAuth2AuthorizedClientRepository();
         
         	/**
         	 * Creates an instance
        -	 *
         	 * @param authorizedClientService the authorized client service
         	 */
        -	public AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(ReactiveOAuth2AuthorizedClientService authorizedClientService) {
        +	public AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(
        +			ReactiveOAuth2AuthorizedClientService authorizedClientService) {
         		Assert.notNull(authorizedClientService, "authorizedClientService cannot be null");
         		this.authorizedClientService = authorizedClientService;
         	}
         
         	/**
        -	 * Sets the {@link ServerOAuth2AuthorizedClientRepository} used for requests that are unauthenticated (or anonymous).
        -	 * The default is {@link WebSessionServerOAuth2AuthorizedClientRepository}.
        -	 *
        -	 * @param anonymousAuthorizedClientRepository the repository used for requests that are unauthenticated (or anonymous)
        +	 * Sets the {@link ServerOAuth2AuthorizedClientRepository} used for requests that are
        +	 * unauthenticated (or anonymous). The default is
        +	 * {@link WebSessionServerOAuth2AuthorizedClientRepository}.
        +	 * @param anonymousAuthorizedClientRepository the repository used for requests that
        +	 * are unauthenticated (or anonymous)
         	 */
         	public void setAnonymousAuthorizedClientRepository(
         			ServerOAuth2AuthorizedClientRepository anonymousAuthorizedClientRepository) {
        @@ -72,12 +76,14 @@ public final class AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository
         	}
         
         	@Override
        -	public  Mono loadAuthorizedClient(String clientRegistrationId, Authentication principal,
        -																		ServerWebExchange exchange) {
        +	public  Mono loadAuthorizedClient(String clientRegistrationId,
        +			Authentication principal, ServerWebExchange exchange) {
         		if (this.isPrincipalAuthenticated(principal)) {
         			return this.authorizedClientService.loadAuthorizedClient(clientRegistrationId, principal.getName());
        -		} else {
        -			return this.anonymousAuthorizedClientRepository.loadAuthorizedClient(clientRegistrationId, principal, exchange);
        +		}
        +		else {
        +			return this.anonymousAuthorizedClientRepository.loadAuthorizedClient(clientRegistrationId, principal,
        +					exchange);
         		}
         	}
         
        @@ -86,7 +92,8 @@ public final class AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository
         			ServerWebExchange exchange) {
         		if (this.isPrincipalAuthenticated(principal)) {
         			return this.authorizedClientService.saveAuthorizedClient(authorizedClient, principal);
        -		} else {
        +		}
        +		else {
         			return this.anonymousAuthorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, exchange);
         		}
         	}
        @@ -96,14 +103,16 @@ public final class AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository
         			ServerWebExchange exchange) {
         		if (this.isPrincipalAuthenticated(principal)) {
         			return this.authorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName());
        -		} else {
        -			return this.anonymousAuthorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, exchange);
        +		}
        +		else {
        +			return this.anonymousAuthorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal,
        +					exchange);
         		}
         	}
         
         	private boolean isPrincipalAuthenticated(Authentication authentication) {
        -		return authentication != null &&
        -				!this.authenticationTrustResolver.isAnonymous(authentication) &&
        -				authentication.isAuthenticated();
        +		return authentication != null && !this.authenticationTrustResolver.isAnonymous(authentication)
        +				&& authentication.isAuthenticated();
         	}
        +
         }
        diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/DefaultServerOAuth2AuthorizationRequestResolver.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/DefaultServerOAuth2AuthorizationRequestResolver.java
        index 3aee38b289..ca751132f3 100644
        --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/DefaultServerOAuth2AuthorizationRequestResolver.java
        +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/DefaultServerOAuth2AuthorizationRequestResolver.java
        @@ -51,26 +51,29 @@ import java.util.function.Consumer;
         /**
          * The default implementation of {@link ServerOAuth2AuthorizationRequestResolver}.
          *
        - * The {@link ClientRegistration#getRegistrationId()} is extracted from the request using the
        - * {@link #DEFAULT_AUTHORIZATION_REQUEST_PATTERN}. The injected {@link ReactiveClientRegistrationRepository} is then
        - * used to resolve the {@link ClientRegistration} and create the {@link OAuth2AuthorizationRequest}.
        + * The {@link ClientRegistration#getRegistrationId()} is extracted from the request using
        + * the {@link #DEFAULT_AUTHORIZATION_REQUEST_PATTERN}. The injected
        + * {@link ReactiveClientRegistrationRepository} is then used to resolve the
        + * {@link ClientRegistration} and create the {@link OAuth2AuthorizationRequest}.
          *
          * @author Rob Winch
          * @author Mark Heckler
          * @since 5.1
          */
        -public class DefaultServerOAuth2AuthorizationRequestResolver
        -		implements ServerOAuth2AuthorizationRequestResolver {
        +public class DefaultServerOAuth2AuthorizationRequestResolver implements ServerOAuth2AuthorizationRequestResolver {
         
         	/**
        -	 * The name of the path variable that contains the {@link ClientRegistration#getRegistrationId()}
        +	 * The name of the path variable that contains the
        +	 * {@link ClientRegistration#getRegistrationId()}
         	 */
         	public static final String DEFAULT_REGISTRATION_ID_URI_VARIABLE_NAME = "registrationId";
         
         	/**
        -	 * The default pattern used to resolve the {@link ClientRegistration#getRegistrationId()}
        +	 * The default pattern used to resolve the
        +	 * {@link ClientRegistration#getRegistrationId()}
         	 */
        -	public static final String DEFAULT_AUTHORIZATION_REQUEST_PATTERN = "/oauth2/authorization/{" + DEFAULT_REGISTRATION_ID_URI_VARIABLE_NAME + "}";
        +	public static final String DEFAULT_AUTHORIZATION_REQUEST_PATTERN = "/oauth2/authorization/{"
        +			+ DEFAULT_REGISTRATION_ID_URI_VARIABLE_NAME + "}";
         
         	private static final char PATH_DELIMITER = '/';
         
        @@ -80,26 +83,33 @@ public class DefaultServerOAuth2AuthorizationRequestResolver
         
         	private final StringKeyGenerator stateGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder());
         
        -	private final StringKeyGenerator secureKeyGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96);
        +	private final StringKeyGenerator secureKeyGenerator = new Base64StringKeyGenerator(
        +			Base64.getUrlEncoder().withoutPadding(), 96);
         
        -	private Consumer authorizationRequestCustomizer = customizer -> {};
        +	private Consumer authorizationRequestCustomizer = customizer -> {
        +	};
         
         	/**
         	 * Creates a new instance
        -	 * @param clientRegistrationRepository the repository to resolve the {@link ClientRegistration}
        +	 * @param clientRegistrationRepository the repository to resolve the
        +	 * {@link ClientRegistration}
         	 */
        -	public DefaultServerOAuth2AuthorizationRequestResolver(ReactiveClientRegistrationRepository clientRegistrationRepository) {
        -		this(clientRegistrationRepository, new PathPatternParserServerWebExchangeMatcher(
        -				DEFAULT_AUTHORIZATION_REQUEST_PATTERN));
        +	public DefaultServerOAuth2AuthorizationRequestResolver(
        +			ReactiveClientRegistrationRepository clientRegistrationRepository) {
        +		this(clientRegistrationRepository,
        +				new PathPatternParserServerWebExchangeMatcher(DEFAULT_AUTHORIZATION_REQUEST_PATTERN));
         	}
         
         	/**
         	 * Creates a new instance
        -	 * @param clientRegistrationRepository the repository to resolve the {@link ClientRegistration}
        -	 * @param authorizationRequestMatcher the matcher that determines if the request is a match and extracts the
        -	 * {@link #DEFAULT_REGISTRATION_ID_URI_VARIABLE_NAME} from the path variables.
        +	 * @param clientRegistrationRepository the repository to resolve the
        +	 * {@link ClientRegistration}
        +	 * @param authorizationRequestMatcher the matcher that determines if the request is a
        +	 * match and extracts the {@link #DEFAULT_REGISTRATION_ID_URI_VARIABLE_NAME} from the
        +	 * path variables.
         	 */
        -	public DefaultServerOAuth2AuthorizationRequestResolver(ReactiveClientRegistrationRepository clientRegistrationRepository,
        +	public DefaultServerOAuth2AuthorizationRequestResolver(
        +			ReactiveClientRegistrationRepository clientRegistrationRepository,
         			ServerWebExchangeMatcher authorizationRequestMatcher) {
         		Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
         		Assert.notNull(authorizationRequestMatcher, "authorizationRequestMatcher cannot be null");
        @@ -109,36 +119,35 @@ public class DefaultServerOAuth2AuthorizationRequestResolver
         
         	@Override
         	public Mono resolve(ServerWebExchange exchange) {
        -		return this.authorizationRequestMatcher.matches(exchange)
        -				.filter(matchResult -> matchResult.isMatch())
        +		return this.authorizationRequestMatcher.matches(exchange).filter(matchResult -> matchResult.isMatch())
         				.map(ServerWebExchangeMatcher.MatchResult::getVariables)
        -				.map(variables -> variables.get(DEFAULT_REGISTRATION_ID_URI_VARIABLE_NAME))
        -				.cast(String.class)
        +				.map(variables -> variables.get(DEFAULT_REGISTRATION_ID_URI_VARIABLE_NAME)).cast(String.class)
         				.flatMap(clientRegistrationId -> resolve(exchange, clientRegistrationId));
         	}
         
         	@Override
        -	public Mono resolve(ServerWebExchange exchange,
        -			String clientRegistrationId) {
        +	public Mono resolve(ServerWebExchange exchange, String clientRegistrationId) {
         		return this.findByRegistrationId(exchange, clientRegistrationId)
        -			.map(clientRegistration -> authorizationRequest(exchange, clientRegistration));
        +				.map(clientRegistration -> authorizationRequest(exchange, clientRegistration));
         	}
         
         	/**
        -	 * Sets the {@code Consumer} to be provided the {@link OAuth2AuthorizationRequest.Builder}
        -	 * allowing for further customizations.
        +	 * Sets the {@code Consumer} to be provided the
        +	 * {@link OAuth2AuthorizationRequest.Builder} allowing for further customizations.
         	 *
         	 * @since 5.3
        -	 * @param authorizationRequestCustomizer the {@code Consumer} to be provided the {@link OAuth2AuthorizationRequest.Builder}
        +	 * @param authorizationRequestCustomizer the {@code Consumer} to be provided the
        +	 * {@link OAuth2AuthorizationRequest.Builder}
         	 */
        -	public final void setAuthorizationRequestCustomizer(Consumer authorizationRequestCustomizer) {
        +	public final void setAuthorizationRequestCustomizer(
        +			Consumer authorizationRequestCustomizer) {
         		Assert.notNull(authorizationRequestCustomizer, "authorizationRequestCustomizer cannot be null");
         		this.authorizationRequestCustomizer = authorizationRequestCustomizer;
         	}
         
         	private Mono findByRegistrationId(ServerWebExchange exchange, String clientRegistration) {
        -		return this.clientRegistrationRepository.findByRegistrationId(clientRegistration)
        -				.switchIfEmpty(Mono.error(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid client registration id")));
        +		return this.clientRegistrationRepository.findByRegistrationId(clientRegistration).switchIfEmpty(Mono
        +				.error(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid client registration id")));
         	}
         
         	private OAuth2AuthorizationRequest authorizationRequest(ServerWebExchange exchange,
        @@ -152,31 +161,32 @@ public class DefaultServerOAuth2AuthorizationRequestResolver
         		if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(clientRegistration.getAuthorizationGrantType())) {
         			builder = OAuth2AuthorizationRequest.authorizationCode();
         			Map additionalParameters = new HashMap<>();
        -			if (!CollectionUtils.isEmpty(clientRegistration.getScopes()) &&
        -					clientRegistration.getScopes().contains(OidcScopes.OPENID)) {
        -				// Section 3.1.2.1 Authentication Request - https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
        +			if (!CollectionUtils.isEmpty(clientRegistration.getScopes())
        +					&& clientRegistration.getScopes().contains(OidcScopes.OPENID)) {
        +				// Section 3.1.2.1 Authentication Request -
        +				// https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
         				// scope
        -				// 		REQUIRED. OpenID Connect requests MUST contain the "openid" scope value.
        +				// REQUIRED. OpenID Connect requests MUST contain the "openid" scope
        +				// value.
         				addNonceParameters(attributes, additionalParameters);
         			}
         			if (ClientAuthenticationMethod.NONE.equals(clientRegistration.getClientAuthenticationMethod())) {
         				addPkceParameters(attributes, additionalParameters);
         			}
         			builder.additionalParameters(additionalParameters);
        -		} else if (AuthorizationGrantType.IMPLICIT.equals(clientRegistration.getAuthorizationGrantType())) {
        +		}
        +		else if (AuthorizationGrantType.IMPLICIT.equals(clientRegistration.getAuthorizationGrantType())) {
         			builder = OAuth2AuthorizationRequest.implicit();
        -		} else {
        +		}
        +		else {
         			throw new IllegalArgumentException(
         					"Invalid Authorization Grant Type (" + clientRegistration.getAuthorizationGrantType().getValue()
         							+ ") for Client Registration with Id: " + clientRegistration.getRegistrationId());
         		}
        -		builder
        -				.clientId(clientRegistration.getClientId())
        +		builder.clientId(clientRegistration.getClientId())
         				.authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri())
        -				.redirectUri(redirectUriStr)
        -				.scopes(clientRegistration.getScopes())
        -				.state(this.stateGenerator.generateKey())
        -				.attributes(attributes);
        +				.redirectUri(redirectUriStr).scopes(clientRegistration.getScopes())
        +				.state(this.stateGenerator.generateKey()).attributes(attributes);
         
         		this.authorizationRequestCustomizer.accept(builder);
         
        @@ -184,7 +194,8 @@ public class DefaultServerOAuth2AuthorizationRequestResolver
         	}
         
         	/**
        -	 * Expands the {@link ClientRegistration#getRedirectUri()} with following provided variables:
        + * Expands the {@link ClientRegistration#getRedirectUri()} with following provided + * variables:
        * - baseUrl (e.g. https://localhost/app)
        * - baseScheme (e.g. https)
        * - baseHost (e.g. localhost)
        @@ -195,8 +206,8 @@ public class DefaultServerOAuth2AuthorizationRequestResolver *

        * Null variables are provided as empty strings. *

        - * Default redirectUri is: {@code org.springframework.security.config.oauth2.client.CommonOAuth2Provider#DEFAULT_REDIRECT_URL} - * + * Default redirectUri is: + * {@code org.springframework.security.config.oauth2.client.CommonOAuth2Provider#DEFAULT_REDIRECT_URL} * @return expanded URI */ private static String expandRedirectUri(ServerHttpRequest request, ClientRegistration clientRegistration) { @@ -204,10 +215,7 @@ public class DefaultServerOAuth2AuthorizationRequestResolver uriVariables.put("registrationId", clientRegistration.getRegistrationId()); UriComponents uriComponents = UriComponentsBuilder.fromUri(request.getURI()) - .replacePath(request.getPath().contextPath().value()) - .replaceQuery(null) - .fragment(null) - .build(); + .replacePath(request.getPath().contextPath().value()).replaceQuery(null).fragment(null).build(); String scheme = uriComponents.getScheme(); uriVariables.put("baseScheme", scheme == null ? "" : scheme); String host = uriComponents.getHost(); @@ -230,19 +238,21 @@ public class DefaultServerOAuth2AuthorizationRequestResolver } uriVariables.put("action", action); - return UriComponentsBuilder.fromUriString(clientRegistration.getRedirectUri()) - .buildAndExpand(uriVariables) + return UriComponentsBuilder.fromUriString(clientRegistration.getRedirectUri()).buildAndExpand(uriVariables) .toUriString(); } /** * Creates nonce and its hash for use in OpenID Connect 1.0 Authentication Requests. - * - * @param attributes where the {@link OidcParameterNames#NONCE} is stored for the authentication request - * @param additionalParameters where the {@link OidcParameterNames#NONCE} hash is added for the authentication request + * @param attributes where the {@link OidcParameterNames#NONCE} is stored for the + * authentication request + * @param additionalParameters where the {@link OidcParameterNames#NONCE} hash is + * added for the authentication request * * @since 5.2 - * @see 3.1.2.1. Authentication Request + * @see 3.1.2.1. + * Authentication Request */ private void addNonceParameters(Map attributes, Map additionalParameters) { try { @@ -250,20 +260,27 @@ public class DefaultServerOAuth2AuthorizationRequestResolver String nonceHash = createHash(nonce); attributes.put(OidcParameterNames.NONCE, nonce); additionalParameters.put(OidcParameterNames.NONCE, nonceHash); - } catch (NoSuchAlgorithmException e) { } + } + catch (NoSuchAlgorithmException e) { + } } /** - * Creates and adds additional PKCE parameters for use in the OAuth 2.0 Authorization and Access Token Requests - * - * @param attributes where {@link PkceParameterNames#CODE_VERIFIER} is stored for the token request - * @param additionalParameters where {@link PkceParameterNames#CODE_CHALLENGE} and, usually, - * {@link PkceParameterNames#CODE_CHALLENGE_METHOD} are added to be used in the authorization request. + * Creates and adds additional PKCE parameters for use in the OAuth 2.0 Authorization + * and Access Token Requests + * @param attributes where {@link PkceParameterNames#CODE_VERIFIER} is stored for the + * token request + * @param additionalParameters where {@link PkceParameterNames#CODE_CHALLENGE} and, + * usually, {@link PkceParameterNames#CODE_CHALLENGE_METHOD} are added to be used in + * the authorization request. * * @since 5.2 - * @see 1.1. Protocol Flow - * @see 4.1. Client Creates a Code Verifier - * @see 4.2. Client Creates the Code Challenge + * @see 1.1. + * Protocol Flow + * @see 4.1. + * Client Creates a Code Verifier + * @see 4.2. + * Client Creates the Code Challenge */ private void addPkceParameters(Map attributes, Map additionalParameters) { String codeVerifier = this.secureKeyGenerator.generateKey(); @@ -272,7 +289,8 @@ public class DefaultServerOAuth2AuthorizationRequestResolver String codeChallenge = createHash(codeVerifier); additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, codeChallenge); additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256"); - } catch (NoSuchAlgorithmException e) { + } + catch (NoSuchAlgorithmException e) { additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, codeVerifier); } } @@ -282,4 +300,5 @@ public class DefaultServerOAuth2AuthorizationRequestResolver byte[] digest = md.digest(value.getBytes(StandardCharsets.US_ASCII)); return Base64.getUrlEncoder().withoutPadding().encodeToString(digest); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationCodeGrantWebFilter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationCodeGrantWebFilter.java index a8d10bff0e..30d860bff7 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationCodeGrantWebFilter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationCodeGrantWebFilter.java @@ -56,30 +56,29 @@ import java.util.Objects; import java.util.Set; /** - * A {@code Filter} for the OAuth 2.0 Authorization Code Grant, - * which handles the processing of the OAuth 2.0 Authorization Response. + * A {@code Filter} for the OAuth 2.0 Authorization Code Grant, which handles the + * processing of the OAuth 2.0 Authorization Response. * *

        * The OAuth 2.0 Authorization Response is processed as follows: * *

          - *
        • - * Assuming the End-User (Resource Owner) has granted access to the Client, the Authorization Server will append the - * {@link OAuth2ParameterNames#CODE code} and {@link OAuth2ParameterNames#STATE state} parameters - * to the {@link OAuth2ParameterNames#REDIRECT_URI redirect_uri} (provided in the Authorization Request) - * and redirect the End-User's user-agent back to this {@code Filter} (the Client). - *
        • - *
        • - * This {@code Filter} will then create an {@link OAuth2AuthorizationCodeAuthenticationToken} with - * the {@link OAuth2ParameterNames#CODE code} received and - * delegate it to the {@link ReactiveAuthenticationManager} to authenticate. - *
        • - *
        • - * Upon a successful authentication, an {@link OAuth2AuthorizedClient Authorized Client} is created by associating the - * {@link OAuth2AuthorizationCodeAuthenticationToken#getClientRegistration() client} to the - * {@link OAuth2AuthorizationCodeAuthenticationToken#getAccessToken() access token} and current {@code Principal} - * and saving it via the {@link ServerOAuth2AuthorizedClientRepository}. - *
        • + *
        • Assuming the End-User (Resource Owner) has granted access to the Client, the + * Authorization Server will append the {@link OAuth2ParameterNames#CODE code} and + * {@link OAuth2ParameterNames#STATE state} parameters to the + * {@link OAuth2ParameterNames#REDIRECT_URI redirect_uri} (provided in the Authorization + * Request) and redirect the End-User's user-agent back to this {@code Filter} (the + * Client).
        • + *
        • This {@code Filter} will then create an + * {@link OAuth2AuthorizationCodeAuthenticationToken} with the + * {@link OAuth2ParameterNames#CODE code} received and delegate it to the + * {@link ReactiveAuthenticationManager} to authenticate.
        • + *
        • Upon a successful authentication, an {@link OAuth2AuthorizedClient Authorized + * Client} is created by associating the + * {@link OAuth2AuthorizationCodeAuthenticationToken#getClientRegistration() client} to + * the {@link OAuth2AuthorizationCodeAuthenticationToken#getAccessToken() access token} + * and current {@code Principal} and saving it via the + * {@link ServerOAuth2AuthorizedClientRepository}.
        • *
        * * @author Rob Winch @@ -95,16 +94,19 @@ import java.util.Set; * @see ReactiveClientRegistrationRepository * @see OAuth2AuthorizedClient * @see ServerOAuth2AuthorizedClientRepository - * @see Section 4.1 Authorization Code Grant - * @see Section 4.1.2 Authorization Response + * @see Section + * 4.1 Authorization Code Grant + * @see Section 4.1.2 Authorization + * Response */ public class OAuth2AuthorizationCodeGrantWebFilter implements WebFilter { + private final ReactiveAuthenticationManager authenticationManager; private final ServerOAuth2AuthorizedClientRepository authorizedClientRepository; - private ServerAuthorizationRequestRepository authorizationRequestRepository = - new WebSessionOAuth2ServerAuthorizationRequestRepository(); + private ServerAuthorizationRequestRepository authorizationRequestRepository = new WebSessionOAuth2ServerAuthorizationRequestRepository(); private ServerAuthenticationSuccessHandler authenticationSuccessHandler; @@ -119,10 +121,9 @@ public class OAuth2AuthorizationCodeGrantWebFilter implements WebFilter { private ServerRequestCache requestCache = new WebSessionServerRequestCache(); private AnonymousAuthenticationToken anonymousToken = new AnonymousAuthenticationToken("key", "anonymous", - AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); + AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); - public OAuth2AuthorizationCodeGrantWebFilter( - ReactiveAuthenticationManager authenticationManager, + public OAuth2AuthorizationCodeGrantWebFilter(ReactiveAuthenticationManager authenticationManager, ReactiveClientRegistrationRepository clientRegistrationRepository, ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { Assert.notNull(authenticationManager, "authenticationManager cannot be null"); @@ -131,20 +132,18 @@ public class OAuth2AuthorizationCodeGrantWebFilter implements WebFilter { this.authenticationManager = authenticationManager; this.authorizedClientRepository = authorizedClientRepository; this.requiresAuthenticationMatcher = this::matchesAuthorizationResponse; - ServerOAuth2AuthorizationCodeAuthenticationTokenConverter authenticationConverter = - new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter(clientRegistrationRepository); + ServerOAuth2AuthorizationCodeAuthenticationTokenConverter authenticationConverter = new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter( + clientRegistrationRepository); authenticationConverter.setAuthorizationRequestRepository(this.authorizationRequestRepository); this.authenticationConverter = authenticationConverter; this.defaultAuthenticationConverter = true; - RedirectServerAuthenticationSuccessHandler authenticationSuccessHandler = - new RedirectServerAuthenticationSuccessHandler(); + RedirectServerAuthenticationSuccessHandler authenticationSuccessHandler = new RedirectServerAuthenticationSuccessHandler(); authenticationSuccessHandler.setRequestCache(this.requestCache); this.authenticationSuccessHandler = authenticationSuccessHandler; this.authenticationFailureHandler = (webFilterExchange, exception) -> Mono.error(exception); } - public OAuth2AuthorizationCodeGrantWebFilter( - ReactiveAuthenticationManager authenticationManager, + public OAuth2AuthorizationCodeGrantWebFilter(ReactiveAuthenticationManager authenticationManager, ServerAuthenticationConverter authenticationConverter, ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { Assert.notNull(authenticationManager, "authenticationManager cannot be null"); @@ -154,19 +153,19 @@ public class OAuth2AuthorizationCodeGrantWebFilter implements WebFilter { this.authorizedClientRepository = authorizedClientRepository; this.requiresAuthenticationMatcher = this::matchesAuthorizationResponse; this.authenticationConverter = authenticationConverter; - RedirectServerAuthenticationSuccessHandler authenticationSuccessHandler = - new RedirectServerAuthenticationSuccessHandler(); + RedirectServerAuthenticationSuccessHandler authenticationSuccessHandler = new RedirectServerAuthenticationSuccessHandler(); authenticationSuccessHandler.setRequestCache(this.requestCache); this.authenticationSuccessHandler = authenticationSuccessHandler; this.authenticationFailureHandler = (webFilterExchange, exception) -> Mono.error(exception); } /** - * Sets the repository used for storing {@link OAuth2AuthorizationRequest}'s. - * The default is {@link WebSessionOAuth2ServerAuthorizationRequestRepository}. + * Sets the repository used for storing {@link OAuth2AuthorizationRequest}'s. The + * default is {@link WebSessionOAuth2ServerAuthorizationRequestRepository}. * * @since 5.2 - * @param authorizationRequestRepository the repository used for storing {@link OAuth2AuthorizationRequest}'s + * @param authorizationRequestRepository the repository used for storing + * {@link OAuth2AuthorizationRequest}'s */ public final void setAuthorizationRequestRepository( ServerAuthorizationRequestRepository authorizationRequestRepository) { @@ -183,11 +182,13 @@ public class OAuth2AuthorizationCodeGrantWebFilter implements WebFilter { } /** - * Sets the {@link ServerRequestCache} used for loading a previously saved request (if available) - * and replaying it after completing the processing of the OAuth 2.0 Authorization Response. + * Sets the {@link ServerRequestCache} used for loading a previously saved request (if + * available) and replaying it after completing the processing of the OAuth 2.0 + * Authorization Response. * * @since 5.4 - * @param requestCache the cache used for loading a previously saved request (if available) + * @param requestCache the cache used for loading a previously saved request (if + * available) */ public final void setRequestCache(ServerRequestCache requestCache) { Assert.notNull(requestCache, "requestCache cannot be null"); @@ -196,17 +197,17 @@ public class OAuth2AuthorizationCodeGrantWebFilter implements WebFilter { } private void updateDefaultAuthenticationSuccessHandler() { - ((RedirectServerAuthenticationSuccessHandler) this.authenticationSuccessHandler).setRequestCache(this.requestCache); + ((RedirectServerAuthenticationSuccessHandler) this.authenticationSuccessHandler) + .setRequestCache(this.requestCache); } @Override public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { return this.requiresAuthenticationMatcher.matches(exchange) .filter(ServerWebExchangeMatcher.MatchResult::isMatch) - .flatMap(matchResult -> - this.authenticationConverter.convert(exchange) - .onErrorMap(OAuth2AuthorizationException.class, e -> new OAuth2AuthenticationException( - e.getError(), e.getError().toString()))) + .flatMap(matchResult -> this.authenticationConverter.convert(exchange).onErrorMap( + OAuth2AuthorizationException.class, + e -> new OAuth2AuthenticationException(e.getError(), e.getError().toString()))) .switchIfEmpty(chain.filter(exchange).then(Mono.empty())) .flatMap(token -> authenticate(exchange, chain, token)) .onErrorResume(AuthenticationException.class, e -> this.authenticationFailureHandler @@ -216,59 +217,58 @@ public class OAuth2AuthorizationCodeGrantWebFilter implements WebFilter { private Mono authenticate(ServerWebExchange exchange, WebFilterChain chain, Authentication token) { WebFilterExchange webFilterExchange = new WebFilterExchange(exchange, chain); return this.authenticationManager.authenticate(token) - .onErrorMap(OAuth2AuthorizationException.class, e -> new OAuth2AuthenticationException( - e.getError(), e.getError().toString())) - .switchIfEmpty(Mono.defer(() -> Mono.error(new IllegalStateException("No provider found for " + token.getClass())))) + .onErrorMap(OAuth2AuthorizationException.class, + e -> new OAuth2AuthenticationException(e.getError(), e.getError().toString())) + .switchIfEmpty(Mono.defer( + () -> Mono.error(new IllegalStateException("No provider found for " + token.getClass())))) .flatMap(authentication -> onAuthenticationSuccess(authentication, webFilterExchange)) - .onErrorResume(AuthenticationException.class, e -> this.authenticationFailureHandler - .onAuthenticationFailure(webFilterExchange, e)); + .onErrorResume(AuthenticationException.class, + e -> this.authenticationFailureHandler.onAuthenticationFailure(webFilterExchange, e)); } private Mono onAuthenticationSuccess(Authentication authentication, WebFilterExchange webFilterExchange) { OAuth2AuthorizationCodeAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeAuthenticationToken) authentication; OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - authenticationResult.getClientRegistration(), - authenticationResult.getName(), - authenticationResult.getAccessToken(), - authenticationResult.getRefreshToken()); - return this.authenticationSuccessHandler - .onAuthenticationSuccess(webFilterExchange, authentication) - .then(ReactiveSecurityContextHolder.getContext() - .map(SecurityContext::getAuthentication) - .defaultIfEmpty(this.anonymousToken) - .flatMap(principal -> this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, webFilterExchange.getExchange())) - ); + authenticationResult.getClientRegistration(), authenticationResult.getName(), + authenticationResult.getAccessToken(), authenticationResult.getRefreshToken()); + return this.authenticationSuccessHandler.onAuthenticationSuccess(webFilterExchange, authentication) + .then(ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication) + .defaultIfEmpty(this.anonymousToken).flatMap(principal -> this.authorizedClientRepository + .saveAuthorizedClient(authorizedClient, principal, webFilterExchange.getExchange()))); } private Mono matchesAuthorizationResponse(ServerWebExchange exchange) { - return Mono.just(exchange) - .filter(exch -> OAuth2AuthorizationResponseUtils.isAuthorizationResponse(exch.getRequest().getQueryParams())) + return Mono.just(exchange).filter( + exch -> OAuth2AuthorizationResponseUtils.isAuthorizationResponse(exch.getRequest().getQueryParams())) .flatMap(exch -> this.authorizationRequestRepository.loadAuthorizationRequest(exchange) - .flatMap(authorizationRequest -> - matchesRedirectUri(exch.getRequest().getURI(), authorizationRequest.getRedirectUri()))) + .flatMap(authorizationRequest -> matchesRedirectUri(exch.getRequest().getURI(), + authorizationRequest.getRedirectUri()))) .switchIfEmpty(ServerWebExchangeMatcher.MatchResult.notMatch()); } - private static Mono matchesRedirectUri( - URI authorizationResponseUri, String authorizationRequestRedirectUri) { + private static Mono matchesRedirectUri(URI authorizationResponseUri, + String authorizationRequestRedirectUri) { UriComponents requestUri = UriComponentsBuilder.fromUri(authorizationResponseUri).build(); UriComponents redirectUri = UriComponentsBuilder.fromUriString(authorizationRequestRedirectUri).build(); - Set>> requestUriParameters = - new LinkedHashSet<>(requestUri.getQueryParams().entrySet()); - Set>> redirectUriParameters = - new LinkedHashSet<>(redirectUri.getQueryParams().entrySet()); - // Remove the additional request parameters (if any) from the authorization response (request) - // before doing an exact comparison with the authorizationRequest.getRedirectUri() parameters (if any) + Set>> requestUriParameters = new LinkedHashSet<>( + requestUri.getQueryParams().entrySet()); + Set>> redirectUriParameters = new LinkedHashSet<>( + redirectUri.getQueryParams().entrySet()); + // Remove the additional request parameters (if any) from the authorization + // response (request) + // before doing an exact comparison with the authorizationRequest.getRedirectUri() + // parameters (if any) requestUriParameters.retainAll(redirectUriParameters); - if (Objects.equals(requestUri.getScheme(), redirectUri.getScheme()) && - Objects.equals(requestUri.getUserInfo(), redirectUri.getUserInfo()) && - Objects.equals(requestUri.getHost(), redirectUri.getHost()) && - Objects.equals(requestUri.getPort(), redirectUri.getPort()) && - Objects.equals(requestUri.getPath(), redirectUri.getPath()) && - Objects.equals(requestUriParameters.toString(), redirectUriParameters.toString())) { + if (Objects.equals(requestUri.getScheme(), redirectUri.getScheme()) + && Objects.equals(requestUri.getUserInfo(), redirectUri.getUserInfo()) + && Objects.equals(requestUri.getHost(), redirectUri.getHost()) + && Objects.equals(requestUri.getPort(), redirectUri.getPort()) + && Objects.equals(requestUri.getPath(), redirectUri.getPath()) + && Objects.equals(requestUriParameters.toString(), redirectUriParameters.toString())) { return ServerWebExchangeMatcher.MatchResult.match(); } return ServerWebExchangeMatcher.MatchResult.notMatch(); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilter.java index 907ebdfffb..0c2cfd56ed 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilter.java @@ -36,22 +36,23 @@ import reactor.core.publisher.Mono; import java.net.URI; /** - * This {@code WebFilter} initiates the authorization code grant or implicit grant flow - * by redirecting the End-User's user-agent to the Authorization Server's Authorization Endpoint. + * This {@code WebFilter} initiates the authorization code grant or implicit grant flow by + * redirecting the End-User's user-agent to the Authorization Server's Authorization + * Endpoint. * *

        - * It builds the OAuth 2.0 Authorization Request, - * which is used as the redirect {@code URI} to the Authorization Endpoint. - * The redirect {@code URI} will include the client identifier, requested scope(s), state, - * response type, and a redirection URI which the authorization server will send the user-agent back to - * once access is granted (or denied) by the End-User (Resource Owner). + * It builds the OAuth 2.0 Authorization Request, which is used as the redirect + * {@code URI} to the Authorization Endpoint. The redirect {@code URI} will include the + * client identifier, requested scope(s), state, response type, and a redirection URI + * which the authorization server will send the user-agent back to once access is granted + * (or denied) by the End-User (Resource Owner). * *

        - * By default, this {@code Filter} responds to authorization requests - * at the {@code URI} {@code /oauth2/authorization/{registrationId}}. - * The {@code URI} template variable {@code {registrationId}} represents the - * {@link ClientRegistration#getRegistrationId() registration identifier} of the client - * that is used for initiating the OAuth 2.0 Authorization Request. + * By default, this {@code Filter} responds to authorization requests at the {@code URI} + * {@code /oauth2/authorization/{registrationId}}. The {@code URI} template variable + * {@code {registrationId}} represents the {@link ClientRegistration#getRegistrationId() + * registration identifier} of the client that is used for initiating the OAuth 2.0 + * Authorization Request. * * @author Rob Winch * @since 5.1 @@ -59,41 +60,53 @@ import java.net.URI; * @see AuthorizationRequestRepository * @see ClientRegistration * @see ClientRegistrationRepository - * @see Section 4.1 Authorization Code Grant - * @see Section 4.1.1 Authorization Request (Authorization Code) - * @see Section 4.2 Implicit Grant - * @see Section 4.2.1 Authorization Request (Implicit) + * @see Section + * 4.1 Authorization Code Grant + * @see Section 4.1.1 Authorization Request + * (Authorization Code) + * @see Section + * 4.2 Implicit Grant + * @see Section 4.2.1 Authorization Request + * (Implicit) */ public class OAuth2AuthorizationRequestRedirectWebFilter implements WebFilter { + private final ServerRedirectStrategy authorizationRedirectStrategy = new DefaultServerRedirectStrategy(); + private final ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver; - private ServerAuthorizationRequestRepository authorizationRequestRepository = - new WebSessionOAuth2ServerAuthorizationRequestRepository(); + + private ServerAuthorizationRequestRepository authorizationRequestRepository = new WebSessionOAuth2ServerAuthorizationRequestRepository(); + private ServerRequestCache requestCache = new WebSessionServerRequestCache(); /** - * Constructs an {@code OAuth2AuthorizationRequestRedirectFilter} using the provided parameters. - * + * Constructs an {@code OAuth2AuthorizationRequestRedirectFilter} using the provided + * parameters. * @param clientRegistrationRepository the repository of client registrations */ - public OAuth2AuthorizationRequestRedirectWebFilter(ReactiveClientRegistrationRepository clientRegistrationRepository) { - this.authorizationRequestResolver = new DefaultServerOAuth2AuthorizationRequestResolver(clientRegistrationRepository); + public OAuth2AuthorizationRequestRedirectWebFilter( + ReactiveClientRegistrationRepository clientRegistrationRepository) { + this.authorizationRequestResolver = new DefaultServerOAuth2AuthorizationRequestResolver( + clientRegistrationRepository); } /** - * Constructs an {@code OAuth2AuthorizationRequestRedirectFilter} using the provided parameters. - * + * Constructs an {@code OAuth2AuthorizationRequestRedirectFilter} using the provided + * parameters. * @param authorizationRequestResolver the resolver to use */ - public OAuth2AuthorizationRequestRedirectWebFilter(ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver) { + public OAuth2AuthorizationRequestRedirectWebFilter( + ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver) { Assert.notNull(authorizationRequestResolver, "authorizationRequestResolver cannot be null"); this.authorizationRequestResolver = authorizationRequestResolver; } /** * Sets the repository used for storing {@link OAuth2AuthorizationRequest}'s. - * - * @param authorizationRequestRepository the repository used for storing {@link OAuth2AuthorizationRequest}'s + * @param authorizationRequestRepository the repository used for storing + * {@link OAuth2AuthorizationRequest}'s */ public final void setAuthorizationRequestRepository( ServerAuthorizationRequestRepository authorizationRequestRepository) { @@ -113,10 +126,11 @@ public class OAuth2AuthorizationRequestRedirectWebFilter implements WebFilter { @Override public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { return this.authorizationRequestResolver.resolve(exchange) - .switchIfEmpty(chain.filter(exchange).then(Mono.empty())) - .onErrorResume(ClientAuthorizationRequiredException.class, e -> this.requestCache.saveRequest(exchange) - .then(this.authorizationRequestResolver.resolve(exchange, e.getClientRegistrationId()))) - .flatMap(clientRegistration -> sendRedirectForAuthorization(exchange, clientRegistration)); + .switchIfEmpty(chain.filter(exchange).then(Mono.empty())) + .onErrorResume(ClientAuthorizationRequiredException.class, + e -> this.requestCache.saveRequest(exchange) + .then(this.authorizationRequestResolver.resolve(exchange, e.getClientRegistrationId()))) + .flatMap(clientRegistration -> sendRedirectForAuthorization(exchange, clientRegistration)); } private Mono sendRedirectForAuthorization(ServerWebExchange exchange, @@ -128,11 +142,11 @@ public class OAuth2AuthorizationRequestRedirectWebFilter implements WebFilter { .saveAuthorizationRequest(authorizationRequest, exchange); } - URI redirectUri = UriComponentsBuilder - .fromUriString(authorizationRequest.getAuthorizationRequestUri()) + URI redirectUri = UriComponentsBuilder.fromUriString(authorizationRequest.getAuthorizationRequestUri()) .build(true).toUri(); return saveAuthorizationRequest .then(this.authorizationRedirectStrategy.sendRedirect(exchange, redirectUri)); }); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationResponseUtils.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationResponseUtils.java index 423c785302..f14e0898f5 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationResponseUtils.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationResponseUtils.java @@ -52,13 +52,13 @@ final class OAuth2AuthorizationResponseUtils { } static boolean isAuthorizationResponseSuccess(MultiValueMap request) { - return StringUtils.hasText(request.getFirst(OAuth2ParameterNames.CODE)) && - StringUtils.hasText(request.getFirst(OAuth2ParameterNames.STATE)); + return StringUtils.hasText(request.getFirst(OAuth2ParameterNames.CODE)) + && StringUtils.hasText(request.getFirst(OAuth2ParameterNames.STATE)); } static boolean isAuthorizationResponseError(MultiValueMap request) { - return StringUtils.hasText(request.getFirst(OAuth2ParameterNames.ERROR)) && - StringUtils.hasText(request.getFirst(OAuth2ParameterNames.STATE)); + return StringUtils.hasText(request.getFirst(OAuth2ParameterNames.ERROR)) + && StringUtils.hasText(request.getFirst(OAuth2ParameterNames.STATE)); } static OAuth2AuthorizationResponse convert(MultiValueMap request, String redirectUri) { @@ -67,19 +67,14 @@ final class OAuth2AuthorizationResponseUtils { String state = request.getFirst(OAuth2ParameterNames.STATE); if (StringUtils.hasText(code)) { - return OAuth2AuthorizationResponse.success(code) - .redirectUri(redirectUri) - .state(state) - .build(); - } else { + return OAuth2AuthorizationResponse.success(code).redirectUri(redirectUri).state(state).build(); + } + else { String errorDescription = request.getFirst(OAuth2ParameterNames.ERROR_DESCRIPTION); String errorUri = request.getFirst(OAuth2ParameterNames.ERROR_URI); - return OAuth2AuthorizationResponse.error(errorCode) - .redirectUri(redirectUri) - .errorDescription(errorDescription) - .errorUri(errorUri) - .state(state) - .build(); + return OAuth2AuthorizationResponse.error(errorCode).redirectUri(redirectUri) + .errorDescription(errorDescription).errorUri(errorUri).state(state).build(); } } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerAuthorizationRequestRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerAuthorizationRequestRepository.java index ee180a8faf..b102117a97 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerAuthorizationRequestRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerAuthorizationRequestRepository.java @@ -25,48 +25,46 @@ import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /** - * Implementations of this interface are responsible for the persistence - * of {@link OAuth2AuthorizationRequest} between requests. + * Implementations of this interface are responsible for the persistence of + * {@link OAuth2AuthorizationRequest} between requests. * *

        - * Used by the {@link OAuth2AuthorizationRequestRedirectFilter} for persisting the Authorization Request - * before it initiates the authorization code grant flow. - * As well, used by the {@link OAuth2LoginAuthenticationFilter} for resolving - * the associated Authorization Request when handling the callback of the Authorization Response. + * Used by the {@link OAuth2AuthorizationRequestRedirectFilter} for persisting the + * Authorization Request before it initiates the authorization code grant flow. As well, + * used by the {@link OAuth2LoginAuthenticationFilter} for resolving the associated + * Authorization Request when handling the callback of the Authorization Response. * * @author Rob Winch * @since 5.1 * @see OAuth2AuthorizationRequest * @see HttpSessionOAuth2AuthorizationRequestRepository - * * @param The type of OAuth 2.0 Authorization Request */ public interface ServerAuthorizationRequestRepository { /** - * Returns the {@link OAuth2AuthorizationRequest} associated to the provided {@code HttpServletRequest} - * or {@code null} if not available. - * + * Returns the {@link OAuth2AuthorizationRequest} associated to the provided + * {@code HttpServletRequest} or {@code null} if not available. * @param exchange the {@code ServerWebExchange} * @return the {@link OAuth2AuthorizationRequest} or {@code null} if not available */ Mono loadAuthorizationRequest(ServerWebExchange exchange); /** - * Persists the {@link OAuth2AuthorizationRequest} associating it to - * the provided {@code HttpServletRequest} and/or {@code HttpServletResponse}. - * + * Persists the {@link OAuth2AuthorizationRequest} associating it to the provided + * {@code HttpServletRequest} and/or {@code HttpServletResponse}. * @param authorizationRequest the {@link OAuth2AuthorizationRequest} - * @param exchange the {@code ServerWebExchange} + * @param exchange the {@code ServerWebExchange} */ Mono saveAuthorizationRequest(T authorizationRequest, ServerWebExchange exchange); /** * Removes and returns the {@link OAuth2AuthorizationRequest} associated to the * provided {@code HttpServletRequest} or if not available returns {@code null}. - * * @param exchange the {@code ServerWebExchange} - * @return the removed {@link OAuth2AuthorizationRequest} or {@code null} if not available + * @return the removed {@link OAuth2AuthorizationRequest} or {@code null} if not + * available */ Mono removeAuthorizationRequest(ServerWebExchange exchange); + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationCodeAuthenticationTokenConverter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationCodeAuthenticationTokenConverter.java index 6ff9d34fd1..36da4d9696 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationCodeAuthenticationTokenConverter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationCodeAuthenticationTokenConverter.java @@ -32,21 +32,21 @@ import org.springframework.web.util.UriComponentsBuilder; import reactor.core.publisher.Mono; /** - * Converts from a {@link ServerWebExchange} to an {@link OAuth2AuthorizationCodeAuthenticationToken} that can be authenticated. The + * Converts from a {@link ServerWebExchange} to an + * {@link OAuth2AuthorizationCodeAuthenticationToken} that can be authenticated. The * converter does not validate any errors it only performs a conversion. + * * @author Rob Winch * @since 5.1 * @see org.springframework.security.web.server.authentication.AuthenticationWebFilter#setServerAuthenticationConverter(ServerAuthenticationConverter) */ -public class ServerOAuth2AuthorizationCodeAuthenticationTokenConverter - implements ServerAuthenticationConverter { +public class ServerOAuth2AuthorizationCodeAuthenticationTokenConverter implements ServerAuthenticationConverter { static final String AUTHORIZATION_REQUEST_NOT_FOUND_ERROR_CODE = "authorization_request_not_found"; static final String CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE = "client_registration_not_found"; - private ServerAuthorizationRequestRepository authorizationRequestRepository = - new WebSessionOAuth2ServerAuthorizationRequestRepository(); + private ServerAuthorizationRequestRepository authorizationRequestRepository = new WebSessionOAuth2ServerAuthorizationRequestRepository(); private final ReactiveClientRegistrationRepository clientRegistrationRepository; @@ -70,8 +70,8 @@ public class ServerOAuth2AuthorizationCodeAuthenticationTokenConverter @Override public Mono convert(ServerWebExchange serverWebExchange) { return this.authorizationRequestRepository.removeAuthorizationRequest(serverWebExchange) - .switchIfEmpty(oauth2AuthorizationException(AUTHORIZATION_REQUEST_NOT_FOUND_ERROR_CODE)) - .flatMap(authorizationRequest -> authenticationRequest(serverWebExchange, authorizationRequest)); + .switchIfEmpty(oauth2AuthorizationException(AUTHORIZATION_REQUEST_NOT_FOUND_ERROR_CODE)) + .flatMap(authorizationRequest -> authenticationRequest(serverWebExchange, authorizationRequest)); } private Mono oauth2AuthorizationException(String errorCode) { @@ -81,30 +81,27 @@ public class ServerOAuth2AuthorizationCodeAuthenticationTokenConverter }); } - private Mono authenticationRequest(ServerWebExchange exchange, OAuth2AuthorizationRequest authorizationRequest) { - return Mono.just(authorizationRequest) - .map(OAuth2AuthorizationRequest::getAttributes) - .flatMap(attributes -> { - String id = (String) attributes.get(OAuth2ParameterNames.REGISTRATION_ID); - if (id == null) { - return oauth2AuthorizationException(CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE); - } - return this.clientRegistrationRepository.findByRegistrationId(id); - }) - .switchIfEmpty(oauth2AuthorizationException(CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE)) + private Mono authenticationRequest(ServerWebExchange exchange, + OAuth2AuthorizationRequest authorizationRequest) { + return Mono.just(authorizationRequest).map(OAuth2AuthorizationRequest::getAttributes).flatMap(attributes -> { + String id = (String) attributes.get(OAuth2ParameterNames.REGISTRATION_ID); + if (id == null) { + return oauth2AuthorizationException(CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE); + } + return this.clientRegistrationRepository.findByRegistrationId(id); + }).switchIfEmpty(oauth2AuthorizationException(CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE)) .map(clientRegistration -> { OAuth2AuthorizationResponse authorizationResponse = convertResponse(exchange); OAuth2AuthorizationCodeAuthenticationToken authenticationRequest = new OAuth2AuthorizationCodeAuthenticationToken( - clientRegistration, new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse)); + clientRegistration, + new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse)); return authenticationRequest; }); } private static OAuth2AuthorizationResponse convertResponse(ServerWebExchange exchange) { - String redirectUri = UriComponentsBuilder.fromUri(exchange.getRequest().getURI()) - .build() - .toUriString(); - return OAuth2AuthorizationResponseUtils - .convert(exchange.getRequest().getQueryParams(), redirectUri); + String redirectUri = UriComponentsBuilder.fromUri(exchange.getRequest().getURI()).build().toUriString(); + return OAuth2AuthorizationResponseUtils.convert(exchange.getRequest().getQueryParams(), redirectUri); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationRequestResolver.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationRequestResolver.java index e33d419b6e..b750bba16c 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationRequestResolver.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationRequestResolver.java @@ -20,9 +20,10 @@ import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /** - * Implementations of this interface are capable of resolving - * an {@link OAuth2AuthorizationRequest} from the provided {@code ServerWebExchange}. - * Used by the {@link OAuth2AuthorizationRequestRedirectWebFilter} for resolving Authorization Requests. + * Implementations of this interface are capable of resolving an + * {@link OAuth2AuthorizationRequest} from the provided {@code ServerWebExchange}. Used by + * the {@link OAuth2AuthorizationRequestRedirectWebFilter} for resolving Authorization + * Requests. * * @author Rob Winch * @since 5.1 @@ -32,21 +33,21 @@ import reactor.core.publisher.Mono; public interface ServerOAuth2AuthorizationRequestResolver { /** - * Returns the {@link OAuth2AuthorizationRequest} resolved from - * the provided {@code HttpServletRequest} or {@code null} if not available. - * + * Returns the {@link OAuth2AuthorizationRequest} resolved from the provided + * {@code HttpServletRequest} or {@code null} if not available. * @param exchange the {@code ServerWebExchange} - * @return the resolved {@link OAuth2AuthorizationRequest} or {@code null} if not available + * @return the resolved {@link OAuth2AuthorizationRequest} or {@code null} if not + * available */ Mono resolve(ServerWebExchange exchange); /** - * Returns the {@link OAuth2AuthorizationRequest} resolved from - * the provided {@code HttpServletRequest} or {@code null} if not available. - * + * Returns the {@link OAuth2AuthorizationRequest} resolved from the provided + * {@code HttpServletRequest} or {@code null} if not available. * @param exchange the {@code ServerWebExchange} * @param clientRegistrationId the client registration id - * @return the resolved {@link OAuth2AuthorizationRequest} or {@code null} if not available + * @return the resolved {@link OAuth2AuthorizationRequest} or {@code null} if not + * available */ Mono resolve(ServerWebExchange exchange, String clientRegistrationId); diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizedClientRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizedClientRepository.java index 9491f71361..8c86b30bf5 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizedClientRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizedClientRepository.java @@ -23,15 +23,15 @@ import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /** - * Implementations of this interface are responsible for the persistence - * of {@link OAuth2AuthorizedClient Authorized Client(s)} between requests. + * Implementations of this interface are responsible for the persistence of + * {@link OAuth2AuthorizedClient Authorized Client(s)} between requests. * *

        - * The primary purpose of an {@link OAuth2AuthorizedClient Authorized Client} - * is to associate an {@link OAuth2AuthorizedClient#getAccessToken() Access Token} credential - * to a {@link OAuth2AuthorizedClient#getClientRegistration() Client} and Resource Owner, - * who is the {@link OAuth2AuthorizedClient#getPrincipalName() Principal} - * that originally granted the authorization. + * The primary purpose of an {@link OAuth2AuthorizedClient Authorized Client} is to + * associate an {@link OAuth2AuthorizedClient#getAccessToken() Access Token} credential to + * a {@link OAuth2AuthorizedClient#getClientRegistration() Client} and Resource Owner, who + * is the {@link OAuth2AuthorizedClient#getPrincipalName() Principal} that originally + * granted the authorization. * * @author Rob Winch * @since 5.1 @@ -43,10 +43,9 @@ import reactor.core.publisher.Mono; public interface ServerOAuth2AuthorizedClientRepository { /** - * Returns the {@link OAuth2AuthorizedClient} associated to the - * provided client registration identifier and End-User {@link Authentication} (Resource Owner) - * or {@code null} if not available. - * + * Returns the {@link OAuth2AuthorizedClient} associated to the provided client + * registration identifier and End-User {@link Authentication} (Resource Owner) or + * {@code null} if not available. * @param clientRegistrationId the identifier for the client's registration * @param principal the End-User {@link Authentication} (Resource Owner) * @param exchange the {@code ServerWebExchange} @@ -57,20 +56,18 @@ public interface ServerOAuth2AuthorizedClientRepository { Authentication principal, ServerWebExchange exchange); /** - * Saves the {@link OAuth2AuthorizedClient} associating it to - * the provided End-User {@link Authentication} (Resource Owner). - * + * Saves the {@link OAuth2AuthorizedClient} associating it to the provided End-User + * {@link Authentication} (Resource Owner). * @param authorizedClient the authorized client * @param principal the End-User {@link Authentication} (Resource Owner) * @param exchange the {@code ServerWebExchange} */ - Mono saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, - Authentication principal, ServerWebExchange exchange); + Mono saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal, + ServerWebExchange exchange); /** - * Removes the {@link OAuth2AuthorizedClient} associated to the - * provided client registration identifier and End-User {@link Authentication} (Resource Owner). - * + * Removes the {@link OAuth2AuthorizedClient} associated to the provided client + * registration identifier and End-User {@link Authentication} (Resource Owner). * @param clientRegistrationId the identifier for the client's registration * @param principal the End-User {@link Authentication} (Resource Owner) * @param exchange the {@code ServerWebExchange} diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/UnAuthenticatedServerOAuth2AuthorizedClientRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/UnAuthenticatedServerOAuth2AuthorizedClientRepository.java index 05356df521..e77a10b9b8 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/UnAuthenticatedServerOAuth2AuthorizedClientRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/UnAuthenticatedServerOAuth2AuthorizedClientRepository.java @@ -29,17 +29,19 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** - * Provides support for an unauthenticated user. This is useful when running as a process with no - * user associated to it. The implementation ensures that {@link ServerWebExchange} is null and that the - * {@link Authentication} is either null or anonymous to prevent using it incorrectly. - * - * @deprecated Use {@link AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager} instead + * Provides support for an unauthenticated user. This is useful when running as a process + * with no user associated to it. The implementation ensures that + * {@link ServerWebExchange} is null and that the {@link Authentication} is either null or + * anonymous to prevent using it incorrectly. * + * @deprecated Use {@link AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager} + * instead * @author Rob Winch * @since 5.1 */ @Deprecated public class UnAuthenticatedServerOAuth2AuthorizedClientRepository implements ServerOAuth2AuthorizedClientRepository { + private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); private final Map clientRegistrationIdToAuthorizedClient = new ConcurrentHashMap<>(); @@ -55,9 +57,8 @@ public class UnAuthenticatedServerOAuth2AuthorizedClientRepository implements Se } @Override - public Mono saveAuthorizedClient( - OAuth2AuthorizedClient authorizedClient, - Authentication authentication, ServerWebExchange serverWebExchange) { + public Mono saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication authentication, + ServerWebExchange serverWebExchange) { Assert.notNull(authorizedClient, "authorizedClient cannot be null"); Assert.isNull(serverWebExchange, "serverWebExchange must be null"); Assert.isTrue(isUnauthenticated(authentication), "The user " + authentication + " should not be authenticated"); @@ -79,4 +80,5 @@ public class UnAuthenticatedServerOAuth2AuthorizedClientRepository implements Se private boolean isUnauthenticated(Authentication authentication) { return authentication == null || this.trustResolver.isAnonymous(authentication); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/WebSessionOAuth2ServerAuthorizationRequestRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/WebSessionOAuth2ServerAuthorizationRequestRepository.java index 2ad3026ca4..2422c80aaf 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/WebSessionOAuth2ServerAuthorizationRequestRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/WebSessionOAuth2ServerAuthorizationRequestRepository.java @@ -41,14 +41,13 @@ import reactor.core.publisher.Mono; public final class WebSessionOAuth2ServerAuthorizationRequestRepository implements ServerAuthorizationRequestRepository { - private static final String DEFAULT_AUTHORIZATION_REQUEST_ATTR_NAME = - WebSessionOAuth2ServerAuthorizationRequestRepository.class.getName() + ".AUTHORIZATION_REQUEST"; + private static final String DEFAULT_AUTHORIZATION_REQUEST_ATTR_NAME = WebSessionOAuth2ServerAuthorizationRequestRepository.class + .getName() + ".AUTHORIZATION_REQUEST"; private final String sessionAttributeName = DEFAULT_AUTHORIZATION_REQUEST_ATTR_NAME; @Override - public Mono loadAuthorizationRequest( - ServerWebExchange exchange) { + public Mono loadAuthorizationRequest(ServerWebExchange exchange) { String state = getStateParameter(exchange); if (state == null) { return Mono.empty(); @@ -59,42 +58,44 @@ public final class WebSessionOAuth2ServerAuthorizationRequestRepository } @Override - public Mono saveAuthorizationRequest( - OAuth2AuthorizationRequest authorizationRequest, ServerWebExchange exchange) { + public Mono saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest, + ServerWebExchange exchange) { Assert.notNull(authorizationRequest, "authorizationRequest cannot be null"); return saveStateToAuthorizationRequest(exchange) - .doOnNext(stateToAuthorizationRequest -> stateToAuthorizationRequest.put(authorizationRequest.getState(), authorizationRequest)) + .doOnNext(stateToAuthorizationRequest -> stateToAuthorizationRequest + .put(authorizationRequest.getState(), authorizationRequest)) .then(); } @Override - public Mono removeAuthorizationRequest( - ServerWebExchange exchange) { + public Mono removeAuthorizationRequest(ServerWebExchange exchange) { String state = getStateParameter(exchange); if (state == null) { return Mono.empty(); } - return exchange.getSession() - .map(WebSession::getAttributes) - .handle((sessionAttrs, sink) -> { - Map stateToAuthzRequest = sessionAttrsMapStateToAuthorizationRequest(sessionAttrs); - if (stateToAuthzRequest == null) { - sink.complete(); - return; - } - OAuth2AuthorizationRequest removedValue = stateToAuthzRequest.remove(state); - if (stateToAuthzRequest.isEmpty()) { - sessionAttrs.remove(this.sessionAttributeName); - } else if (removedValue != null) { - // gh-7327 Overwrite the existing Map to ensure the state is saved for distributed sessions - sessionAttrs.put(this.sessionAttributeName, stateToAuthzRequest); - } - if (removedValue == null) { - sink.complete(); - } else { - sink.next(removedValue); - } - }); + return exchange.getSession().map(WebSession::getAttributes).handle((sessionAttrs, sink) -> { + Map stateToAuthzRequest = sessionAttrsMapStateToAuthorizationRequest( + sessionAttrs); + if (stateToAuthzRequest == null) { + sink.complete(); + return; + } + OAuth2AuthorizationRequest removedValue = stateToAuthzRequest.remove(state); + if (stateToAuthzRequest.isEmpty()) { + sessionAttrs.remove(this.sessionAttributeName); + } + else if (removedValue != null) { + // gh-7327 Overwrite the existing Map to ensure the state is saved for + // distributed sessions + sessionAttrs.put(this.sessionAttributeName, stateToAuthzRequest); + } + if (removedValue == null) { + sink.complete(); + } + else { + sink.next(removedValue); + } + }); } /** @@ -114,28 +115,30 @@ public final class WebSessionOAuth2ServerAuthorizationRequestRepository private Mono> getStateToAuthorizationRequest(ServerWebExchange exchange) { Assert.notNull(exchange, "exchange cannot be null"); - return getSessionAttributes(exchange) - .flatMap(sessionAttrs -> Mono.justOrEmpty(this.sessionAttrsMapStateToAuthorizationRequest(sessionAttrs))); + return getSessionAttributes(exchange).flatMap( + sessionAttrs -> Mono.justOrEmpty(this.sessionAttrsMapStateToAuthorizationRequest(sessionAttrs))); } private Mono> saveStateToAuthorizationRequest(ServerWebExchange exchange) { Assert.notNull(exchange, "exchange cannot be null"); - return getSessionAttributes(exchange) - .doOnNext(sessionAttrs -> { - Object stateToAuthzRequest = sessionAttrs.get(this.sessionAttributeName); + return getSessionAttributes(exchange).doOnNext(sessionAttrs -> { + Object stateToAuthzRequest = sessionAttrs.get(this.sessionAttributeName); - if (stateToAuthzRequest == null) { - stateToAuthzRequest = new HashMap(); - } + if (stateToAuthzRequest == null) { + stateToAuthzRequest = new HashMap(); + } - // No matter stateToAuthzRequest was in session or not, we should always put it into session again - // in case of redis or hazelcast session. #6215 - sessionAttrs.put(this.sessionAttributeName, stateToAuthzRequest); - }).flatMap(sessionAttrs -> Mono.justOrEmpty(this.sessionAttrsMapStateToAuthorizationRequest(sessionAttrs))); + // No matter stateToAuthzRequest was in session or not, we should always put + // it into session again + // in case of redis or hazelcast session. #6215 + sessionAttrs.put(this.sessionAttributeName, stateToAuthzRequest); + }).flatMap(sessionAttrs -> Mono.justOrEmpty(this.sessionAttrsMapStateToAuthorizationRequest(sessionAttrs))); } - private Map sessionAttrsMapStateToAuthorizationRequest(Map sessionAttrs) { + private Map sessionAttrsMapStateToAuthorizationRequest( + Map sessionAttrs) { return (Map) sessionAttrs.get(this.sessionAttributeName); } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/WebSessionServerOAuth2AuthorizedClientRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/WebSessionServerOAuth2AuthorizedClientRepository.java index 2c3538e852..a066fb5399 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/WebSessionServerOAuth2AuthorizedClientRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/WebSessionServerOAuth2AuthorizedClientRepository.java @@ -35,21 +35,21 @@ import java.util.Map; * @see OAuth2AuthorizedClientRepository * @see OAuth2AuthorizedClient */ -public final class WebSessionServerOAuth2AuthorizedClientRepository - implements ServerOAuth2AuthorizedClientRepository { - private static final String DEFAULT_AUTHORIZED_CLIENTS_ATTR_NAME = - WebSessionServerOAuth2AuthorizedClientRepository.class.getName() + ".AUTHORIZED_CLIENTS"; +public final class WebSessionServerOAuth2AuthorizedClientRepository implements ServerOAuth2AuthorizedClientRepository { + + private static final String DEFAULT_AUTHORIZED_CLIENTS_ATTR_NAME = WebSessionServerOAuth2AuthorizedClientRepository.class + .getName() + ".AUTHORIZED_CLIENTS"; + private final String sessionAttributeName = DEFAULT_AUTHORIZED_CLIENTS_ATTR_NAME; @Override @SuppressWarnings("unchecked") - public Mono loadAuthorizedClient(String clientRegistrationId, Authentication principal, - ServerWebExchange exchange) { + public Mono loadAuthorizedClient(String clientRegistrationId, + Authentication principal, ServerWebExchange exchange) { Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty"); Assert.notNull(exchange, "exchange cannot be null"); - return exchange.getSession() - .map(this::getAuthorizedClients) - .flatMap(clients -> Mono.justOrEmpty((T) clients.get(clientRegistrationId))); + return exchange.getSession().map(this::getAuthorizedClients) + .flatMap(clients -> Mono.justOrEmpty((T) clients.get(clientRegistrationId))); } @Override @@ -57,13 +57,11 @@ public final class WebSessionServerOAuth2AuthorizedClientRepository ServerWebExchange exchange) { Assert.notNull(authorizedClient, "authorizedClient cannot be null"); Assert.notNull(exchange, "exchange cannot be null"); - return exchange.getSession() - .doOnSuccess(session -> { - Map authorizedClients = getAuthorizedClients(session); - authorizedClients.put(authorizedClient.getClientRegistration().getRegistrationId(), authorizedClient); - session.getAttributes().put(this.sessionAttributeName, authorizedClients); - }) - .then(Mono.empty()); + return exchange.getSession().doOnSuccess(session -> { + Map authorizedClients = getAuthorizedClients(session); + authorizedClients.put(authorizedClient.getClientRegistration().getRegistrationId(), authorizedClient); + session.getAttributes().put(this.sessionAttributeName, authorizedClients); + }).then(Mono.empty()); } @Override @@ -71,26 +69,26 @@ public final class WebSessionServerOAuth2AuthorizedClientRepository ServerWebExchange exchange) { Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty"); Assert.notNull(exchange, "exchange cannot be null"); - return exchange.getSession() - .doOnSuccess(session -> { - Map authorizedClients = getAuthorizedClients(session); - authorizedClients.remove(clientRegistrationId); - if (authorizedClients.isEmpty()) { - session.getAttributes().remove(this.sessionAttributeName); - } else { - session.getAttributes().put(this.sessionAttributeName, authorizedClients); - } - }) - .then(Mono.empty()); + return exchange.getSession().doOnSuccess(session -> { + Map authorizedClients = getAuthorizedClients(session); + authorizedClients.remove(clientRegistrationId); + if (authorizedClients.isEmpty()) { + session.getAttributes().remove(this.sessionAttributeName); + } + else { + session.getAttributes().put(this.sessionAttributeName, authorizedClients); + } + }).then(Mono.empty()); } @SuppressWarnings("unchecked") private Map getAuthorizedClients(WebSession session) { - Map authorizedClients = session == null ? null : - (Map) session.getAttribute(this.sessionAttributeName); + Map authorizedClients = session == null ? null + : (Map) session.getAttribute(this.sessionAttributeName); if (authorizedClients == null) { authorizedClients = new HashMap<>(); } return authorizedClients; } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/authentication/OAuth2LoginAuthenticationWebFilter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/authentication/OAuth2LoginAuthenticationWebFilter.java index 9c3a2ba8f5..0c3fdc5a78 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/authentication/OAuth2LoginAuthenticationWebFilter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/authentication/OAuth2LoginAuthenticationWebFilter.java @@ -27,8 +27,9 @@ import org.springframework.util.Assert; import reactor.core.publisher.Mono; /** - * A specialized {@link AuthenticationWebFilter} that converts from an {@link OAuth2LoginAuthenticationToken} to an - * {@link OAuth2AuthenticationToken} and saves the {@link OAuth2AuthorizedClient} + * A specialized {@link AuthenticationWebFilter} that converts from an + * {@link OAuth2LoginAuthenticationToken} to an {@link OAuth2AuthenticationToken} and + * saves the {@link OAuth2AuthorizedClient} * * @author Rob Winch * @since 5.1 @@ -39,12 +40,10 @@ public class OAuth2LoginAuthenticationWebFilter extends AuthenticationWebFilter /** * Creates an instance - * * @param authenticationManager the authentication manager to use * @param authorizedClientRepository */ - public OAuth2LoginAuthenticationWebFilter( - ReactiveAuthenticationManager authenticationManager, + public OAuth2LoginAuthenticationWebFilter(ReactiveAuthenticationManager authenticationManager, ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { super(authenticationManager); Assert.notNull(authorizedClientRepository, "authorizedClientService cannot be null"); @@ -52,19 +51,17 @@ public class OAuth2LoginAuthenticationWebFilter extends AuthenticationWebFilter } @Override - protected Mono onAuthenticationSuccess(Authentication authentication, - WebFilterExchange webFilterExchange) { + protected Mono onAuthenticationSuccess(Authentication authentication, WebFilterExchange webFilterExchange) { OAuth2LoginAuthenticationToken authenticationResult = (OAuth2LoginAuthenticationToken) authentication; OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - authenticationResult.getClientRegistration(), - authenticationResult.getName(), - authenticationResult.getAccessToken(), - authenticationResult.getRefreshToken()); - OAuth2AuthenticationToken result = new OAuth2AuthenticationToken( - authenticationResult.getPrincipal(), + authenticationResult.getClientRegistration(), authenticationResult.getName(), + authenticationResult.getAccessToken(), authenticationResult.getRefreshToken()); + OAuth2AuthenticationToken result = new OAuth2AuthenticationToken(authenticationResult.getPrincipal(), authenticationResult.getAuthorities(), authenticationResult.getClientRegistration().getRegistrationId()); - return this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, authenticationResult, webFilterExchange.getExchange()) + return this.authorizedClientRepository + .saveAuthorizedClient(authorizedClient, authenticationResult, webFilterExchange.getExchange()) .then(super.onAuthenticationSuccess(result, webFilterExchange)); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizationCodeOAuth2AuthorizedClientProviderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizationCodeOAuth2AuthorizedClientProviderTests.java index c393b9f323..921d3d03a4 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizationCodeOAuth2AuthorizedClientProviderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizationCodeOAuth2AuthorizedClientProviderTests.java @@ -32,17 +32,21 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class AuthorizationCodeOAuth2AuthorizedClientProviderTests { + private AuthorizationCodeOAuth2AuthorizedClientProvider authorizedClientProvider; + private ClientRegistration clientRegistration; + private OAuth2AuthorizedClient authorizedClient; + private Authentication principal; @Before public void setup() { this.authorizedClientProvider = new AuthorizationCodeOAuth2AuthorizedClientProvider(); this.clientRegistration = TestClientRegistrations.clientRegistration().build(); - this.authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, "principal", TestOAuth2AccessTokens.scopes("read", "write")); + this.authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, "principal", + TestOAuth2AccessTokens.scopes("read", "write")); this.principal = new TestingAuthenticationToken("principal", "password"); } @@ -56,29 +60,24 @@ public class AuthorizationCodeOAuth2AuthorizedClientProviderTests { public void authorizeWhenNotAuthorizationCodeThenUnableToAuthorize() { ClientRegistration clientCredentialsClient = TestClientRegistrations.clientCredentials().build(); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(clientCredentialsClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(clientCredentialsClient).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext)).isNull(); } @Test public void authorizeWhenAuthorizationCodeAndAuthorizedThenNotAuthorize() { - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(this.authorizedClient).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext)).isNull(); } @Test public void authorizeWhenAuthorizationCodeAndNotAuthorizedThenAuthorize() { - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistration) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistration).principal(this.principal).build(); assertThatThrownBy(() -> this.authorizedClientProvider.authorize(authorizationContext)) .isInstanceOf(ClientAuthorizationRequiredException.class); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizationCodeReactiveOAuth2AuthorizedClientProviderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizationCodeReactiveOAuth2AuthorizedClientProviderTests.java index 97bf724011..2e6d4ce9c9 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizationCodeReactiveOAuth2AuthorizedClientProviderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizationCodeReactiveOAuth2AuthorizedClientProviderTests.java @@ -32,17 +32,21 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class AuthorizationCodeReactiveOAuth2AuthorizedClientProviderTests { + private AuthorizationCodeReactiveOAuth2AuthorizedClientProvider authorizedClientProvider; + private ClientRegistration clientRegistration; + private OAuth2AuthorizedClient authorizedClient; + private Authentication principal; @Before public void setup() { this.authorizedClientProvider = new AuthorizationCodeReactiveOAuth2AuthorizedClientProvider(); this.clientRegistration = TestClientRegistrations.clientRegistration().build(); - this.authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, "principal", TestOAuth2AccessTokens.scopes("read", "write")); + this.authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, "principal", + TestOAuth2AccessTokens.scopes("read", "write")); this.principal = new TestingAuthenticationToken("principal", "password"); } @@ -56,29 +60,24 @@ public class AuthorizationCodeReactiveOAuth2AuthorizedClientProviderTests { public void authorizeWhenNotAuthorizationCodeThenUnableToAuthorize() { ClientRegistration clientCredentialsClient = TestClientRegistrations.clientCredentials().build(); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(clientCredentialsClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(clientCredentialsClient).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext).block()).isNull(); } @Test public void authorizeWhenAuthorizationCodeAndAuthorizedThenNotAuthorize() { - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(this.authorizedClient).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext).block()).isNull(); } @Test public void authorizeWhenAuthorizationCodeAndNotAuthorizedThenAuthorize() { - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistration) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistration).principal(this.principal).build(); assertThatThrownBy(() -> this.authorizedClientProvider.authorize(authorizationContext).block()) .isInstanceOf(ClientAuthorizationRequiredException.class); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizedClientServiceOAuth2AuthorizedClientManagerTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizedClientServiceOAuth2AuthorizedClientManagerTests.java index 9ca0f88929..b176d88d9b 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizedClientServiceOAuth2AuthorizedClientManagerTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizedClientServiceOAuth2AuthorizedClientManagerTests.java @@ -50,16 +50,27 @@ import static org.mockito.Mockito.when; * @author Joe Grandja */ public class AuthorizedClientServiceOAuth2AuthorizedClientManagerTests { + private ClientRegistrationRepository clientRegistrationRepository; + private OAuth2AuthorizedClientService authorizedClientService; + private OAuth2AuthorizedClientProvider authorizedClientProvider; + private Function contextAttributesMapper; + private OAuth2AuthorizationSuccessHandler authorizationSuccessHandler; + private OAuth2AuthorizationFailureHandler authorizationFailureHandler; + private AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager; + private ClientRegistration clientRegistration; + private Authentication principal; + private OAuth2AuthorizedClient authorizedClient; + private ArgumentCaptor authorizationContextCaptor; @SuppressWarnings("unchecked") @@ -71,13 +82,14 @@ public class AuthorizedClientServiceOAuth2AuthorizedClientManagerTests { this.contextAttributesMapper = mock(Function.class); this.authorizationSuccessHandler = spy(new OAuth2AuthorizationSuccessHandler() { @Override - public void onAuthorizationSuccess(OAuth2AuthorizedClient authorizedClient, Authentication principal, Map attributes) { + public void onAuthorizationSuccess(OAuth2AuthorizedClient authorizedClient, Authentication principal, + Map attributes) { authorizedClientService.saveAuthorizedClient(authorizedClient, principal); } }); this.authorizationFailureHandler = spy(new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( - (clientRegistrationId, principal, attributes) -> - this.authorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName()))); + (clientRegistrationId, principal, attributes) -> this.authorizedClientService + .removeAuthorizedClient(clientRegistrationId, principal.getName()))); this.authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager( this.clientRegistrationRepository, this.authorizedClientService); this.authorizedClientManager.setAuthorizedClientProvider(this.authorizedClientProvider); @@ -93,58 +105,54 @@ public class AuthorizedClientServiceOAuth2AuthorizedClientManagerTests { @Test public void constructorWhenClientRegistrationRepositoryIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new AuthorizedClientServiceOAuth2AuthorizedClientManager(null, this.authorizedClientService)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clientRegistrationRepository cannot be null"); + assertThatThrownBy( + () -> new AuthorizedClientServiceOAuth2AuthorizedClientManager(null, this.authorizedClientService)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("clientRegistrationRepository cannot be null"); } @Test public void constructorWhenOAuth2AuthorizedClientServiceIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new AuthorizedClientServiceOAuth2AuthorizedClientManager(this.clientRegistrationRepository, null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizedClientService cannot be null"); + assertThatThrownBy( + () -> new AuthorizedClientServiceOAuth2AuthorizedClientManager(this.clientRegistrationRepository, null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("authorizedClientService cannot be null"); } @Test public void setAuthorizedClientProviderWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setAuthorizedClientProvider(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizedClientProvider cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizedClientProvider cannot be null"); } @Test public void setContextAttributesMapperWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setContextAttributesMapper(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("contextAttributesMapper cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("contextAttributesMapper cannot be null"); } @Test public void setAuthorizationSuccessHandlerWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setAuthorizationSuccessHandler(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizationSuccessHandler cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizationSuccessHandler cannot be null"); } @Test public void setAuthorizationFailureHandlerWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setAuthorizationFailureHandler(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizationFailureHandler cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizationFailureHandler cannot be null"); } @Test public void authorizeWhenRequestIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.authorize(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizeRequest cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizeRequest cannot be null"); } @Test public void authorizeWhenClientRegistrationNotFoundThenThrowIllegalArgumentException() { - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("invalid-registration-id") - .principal(this.principal) - .build(); + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId("invalid-registration-id").principal(this.principal).build(); assertThatThrownBy(() -> this.authorizedClientManager.authorize(authorizeRequest)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Could not find ClientRegistration with id 'invalid-registration-id'"); @@ -153,11 +161,11 @@ public class AuthorizedClientServiceOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void authorizeWhenNotAuthorizedAndUnsupportedProviderThenNotAuthorized() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(this.clientRegistration); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(this.clientRegistration); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest); @@ -177,13 +185,14 @@ public class AuthorizedClientServiceOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void authorizeWhenNotAuthorizedAndSupportedProviderThenAuthorized() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(this.clientRegistration); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(this.clientRegistration); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(this.authorizedClient); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(this.authorizedClient); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest); @@ -196,28 +205,27 @@ public class AuthorizedClientServiceOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); assertThat(authorizedClient).isSameAs(this.authorizedClient); - verify(this.authorizationSuccessHandler).onAuthorizationSuccess( - eq(this.authorizedClient), eq(this.principal), any()); - verify(this.authorizedClientService).saveAuthorizedClient( - eq(this.authorizedClient), eq(this.principal)); + verify(this.authorizationSuccessHandler).onAuthorizationSuccess(eq(this.authorizedClient), eq(this.principal), + any()); + verify(this.authorizedClientService).saveAuthorizedClient(eq(this.authorizedClient), eq(this.principal)); } @SuppressWarnings("unchecked") @Test public void authorizeWhenAuthorizedAndSupportedProviderThenReauthorized() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(this.clientRegistration); - when(this.authorizedClientService.loadAuthorizedClient( - eq(this.clientRegistration.getRegistrationId()), eq(this.principal.getName()))).thenReturn(this.authorizedClient); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(this.clientRegistration); + when(this.authorizedClientService.loadAuthorizedClient(eq(this.clientRegistration.getRegistrationId()), + eq(this.principal.getName()))).thenReturn(this.authorizedClient); - OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(reauthorizedClient); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(reauthorizedClient); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest); @@ -230,18 +238,16 @@ public class AuthorizedClientServiceOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); assertThat(authorizedClient).isSameAs(reauthorizedClient); - verify(this.authorizationSuccessHandler).onAuthorizationSuccess( - eq(reauthorizedClient), eq(this.principal), any()); - verify(this.authorizedClientService).saveAuthorizedClient( - eq(reauthorizedClient), eq(this.principal)); + verify(this.authorizationSuccessHandler).onAuthorizationSuccess(eq(reauthorizedClient), eq(this.principal), + any()); + verify(this.authorizedClientService).saveAuthorizedClient(eq(reauthorizedClient), eq(this.principal)); } @SuppressWarnings("unchecked") @Test public void reauthorizeWhenUnsupportedProviderThenNotReauthorized() { OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .build(); + .principal(this.principal).build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(reauthorizeRequest); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); @@ -260,15 +266,14 @@ public class AuthorizedClientServiceOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void reauthorizeWhenSupportedProviderThenReauthorized() { - OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(reauthorizedClient); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(reauthorizedClient); OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .build(); + .principal(this.principal).build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(reauthorizeRequest); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); @@ -280,29 +285,26 @@ public class AuthorizedClientServiceOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); assertThat(authorizedClient).isSameAs(reauthorizedClient); - verify(this.authorizationSuccessHandler).onAuthorizationSuccess( - eq(reauthorizedClient), eq(this.principal), any()); - verify(this.authorizedClientService).saveAuthorizedClient( - eq(reauthorizedClient), eq(this.principal)); + verify(this.authorizationSuccessHandler).onAuthorizationSuccess(eq(reauthorizedClient), eq(this.principal), + any()); + verify(this.authorizedClientService).saveAuthorizedClient(eq(reauthorizedClient), eq(this.principal)); } @SuppressWarnings("unchecked") @Test public void reauthorizeWhenRequestAttributeScopeThenMappedToContext() { - OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(reauthorizedClient); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(reauthorizedClient); // Override the mock with the default this.authorizedClientManager.setContextAttributesMapper( new AuthorizedClientServiceOAuth2AuthorizedClientManager.DefaultContextAttributesMapper()); OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .attribute(OAuth2ParameterNames.SCOPE, "read write") - .build(); + .principal(this.principal).attribute(OAuth2ParameterNames.SCOPE, "read write").build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(reauthorizeRequest); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); @@ -311,15 +313,16 @@ public class AuthorizedClientServiceOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getClientRegistration()).isEqualTo(this.clientRegistration); assertThat(authorizationContext.getAuthorizedClient()).isSameAs(this.authorizedClient); assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); - assertThat(authorizationContext.getAttributes()).containsKey(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME); - String[] requestScopeAttribute = authorizationContext.getAttribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME); + assertThat(authorizationContext.getAttributes()) + .containsKey(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME); + String[] requestScopeAttribute = authorizationContext + .getAttribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME); assertThat(requestScopeAttribute).contains("read", "write"); assertThat(authorizedClient).isSameAs(reauthorizedClient); - verify(this.authorizationSuccessHandler).onAuthorizationSuccess( - eq(reauthorizedClient), eq(this.principal), any()); - verify(this.authorizedClientService).saveAuthorizedClient( - eq(reauthorizedClient), eq(this.principal)); + verify(this.authorizationSuccessHandler).onAuthorizationSuccess(eq(reauthorizedClient), eq(this.principal), + any()); + verify(this.authorizedClientService).saveAuthorizedClient(eq(reauthorizedClient), eq(this.principal)); } @Test @@ -332,36 +335,34 @@ public class AuthorizedClientServiceOAuth2AuthorizedClientManagerTests { .thenThrow(authorizationException); OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .build(); + .principal(this.principal).build(); assertThatCode(() -> this.authorizedClientManager.authorize(reauthorizeRequest)) .isEqualTo(authorizationException); - verify(this.authorizationFailureHandler).onAuthorizationFailure( - eq(authorizationException), eq(this.principal), any()); - verify(this.authorizedClientService).removeAuthorizedClient( - eq(this.clientRegistration.getRegistrationId()), eq(this.principal.getName())); + verify(this.authorizationFailureHandler).onAuthorizationFailure(eq(authorizationException), eq(this.principal), + any()); + verify(this.authorizedClientService).removeAuthorizedClient(eq(this.clientRegistration.getRegistrationId()), + eq(this.principal.getName())); } @Test public void reauthorizeWhenErrorCodeDoesNotMatchThenDoNotRemoveAuthorizedClient() { ClientAuthorizationException authorizationException = new ClientAuthorizationException( - new OAuth2Error("non-matching-error-code", null, null), - this.clientRegistration.getRegistrationId()); + new OAuth2Error("non-matching-error-code", null, null), this.clientRegistration.getRegistrationId()); when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) .thenThrow(authorizationException); OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .build(); + .principal(this.principal).build(); assertThatCode(() -> this.authorizedClientManager.authorize(reauthorizeRequest)) .isEqualTo(authorizationException); - verify(this.authorizationFailureHandler).onAuthorizationFailure( - eq(authorizationException), eq(this.principal), any()); + verify(this.authorizationFailureHandler).onAuthorizationFailure(eq(authorizationException), eq(this.principal), + any()); verifyNoInteractions(this.authorizedClientService); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests.java index 01d38442d2..8bcd9e335d 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests.java @@ -53,16 +53,27 @@ import static org.mockito.Mockito.when; * @author Phil Clay */ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { + private ReactiveClientRegistrationRepository clientRegistrationRepository; + private ReactiveOAuth2AuthorizedClientService authorizedClientService; + private ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider; + private Function>> contextAttributesMapper; + private AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager; + private ClientRegistration clientRegistration; + private Authentication principal; + private OAuth2AuthorizedClient authorizedClient; + private ArgumentCaptor authorizationContextCaptor; + private PublisherProbe saveAuthorizedClientProbe; + private PublisherProbe removeAuthorizedClientProbe; @SuppressWarnings("unchecked") @@ -71,9 +82,11 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { this.clientRegistrationRepository = mock(ReactiveClientRegistrationRepository.class); this.authorizedClientService = mock(ReactiveOAuth2AuthorizedClientService.class); this.saveAuthorizedClientProbe = PublisherProbe.empty(); - when(this.authorizedClientService.saveAuthorizedClient(any(), any())).thenReturn(this.saveAuthorizedClientProbe.mono()); + when(this.authorizedClientService.saveAuthorizedClient(any(), any())) + .thenReturn(this.saveAuthorizedClientProbe.mono()); this.removeAuthorizedClientProbe = PublisherProbe.empty(); - when(this.authorizedClientService.removeAuthorizedClient(any(), any())).thenReturn(this.removeAuthorizedClientProbe.mono()); + when(this.authorizedClientService.removeAuthorizedClient(any(), any())) + .thenReturn(this.removeAuthorizedClientProbe.mono()); this.authorizedClientProvider = mock(ReactiveOAuth2AuthorizedClientProvider.class); this.contextAttributesMapper = mock(Function.class); when(this.contextAttributesMapper.apply(any())).thenReturn(Mono.empty()); @@ -90,59 +103,53 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { @Test public void constructorWhenClientRegistrationRepositoryIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(null, this.authorizedClientService)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clientRegistrationRepository cannot be null"); + assertThatThrownBy(() -> new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(null, + this.authorizedClientService)).isInstanceOf(IllegalArgumentException.class) + .hasMessage("clientRegistrationRepository cannot be null"); } @Test public void constructorWhenOAuth2AuthorizedClientServiceIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(this.clientRegistrationRepository, null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizedClientService cannot be null"); + assertThatThrownBy(() -> new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager( + this.clientRegistrationRepository, null)).isInstanceOf(IllegalArgumentException.class) + .hasMessage("authorizedClientService cannot be null"); } @Test public void setAuthorizedClientProviderWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setAuthorizedClientProvider(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizedClientProvider cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizedClientProvider cannot be null"); } @Test public void setContextAttributesMapperWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setContextAttributesMapper(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("contextAttributesMapper cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("contextAttributesMapper cannot be null"); } @Test public void setAuthorizationSuccessHandlerWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setAuthorizationSuccessHandler(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizationSuccessHandler cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizationSuccessHandler cannot be null"); } @Test public void setAuthorizationFailureHandlerWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setAuthorizationFailureHandler(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizationFailureHandler cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizationFailureHandler cannot be null"); } @Test public void authorizeWhenRequestIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.authorize(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizeRequest cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizeRequest cannot be null"); } @Test public void authorizeWhenClientRegistrationNotFoundThenThrowIllegalArgumentException() { String clientRegistrationId = "invalid-registration-id"; OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(clientRegistrationId) - .principal(this.principal) - .build(); + .principal(this.principal).build(); when(this.clientRegistrationRepository.findByRegistrationId(clientRegistrationId)).thenReturn(Mono.empty()); StepVerifier.create(this.authorizedClientManager.authorize(authorizeRequest)) .verifyError(IllegalArgumentException.class); @@ -152,14 +159,13 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void authorizeWhenNotAuthorizedAndUnsupportedProviderThenNotAuthorized() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); - when(this.authorizedClientService.loadAuthorizedClient( - any(), any())).thenReturn(Mono.empty()); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); + when(this.authorizedClientService.loadAuthorizedClient(any(), any())).thenReturn(Mono.empty()); when(authorizedClientProvider.authorize(any())).thenReturn(Mono.empty()); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); Mono authorizedClient = this.authorizedClientManager.authorize(authorizeRequest); @@ -173,29 +179,27 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getAuthorizedClient()).isNull(); assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); - verify(this.authorizedClientService, never()).saveAuthorizedClient( - any(OAuth2AuthorizedClient.class), eq(this.principal)); + verify(this.authorizedClientService, never()).saveAuthorizedClient(any(OAuth2AuthorizedClient.class), + eq(this.principal)); } @SuppressWarnings("unchecked") @Test public void authorizeWhenNotAuthorizedAndSupportedProviderThenAuthorized() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); - when(this.authorizedClientService.loadAuthorizedClient( - any(), any())).thenReturn(Mono.empty()); + when(this.authorizedClientService.loadAuthorizedClient(any(), any())).thenReturn(Mono.empty()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.just(this.authorizedClient)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.just(this.authorizedClient)); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); Mono authorizedClient = this.authorizedClientManager.authorize(authorizeRequest); - StepVerifier.create(authorizedClient) - .expectNext(this.authorizedClient) - .verifyComplete(); + StepVerifier.create(authorizedClient).expectNext(this.authorizedClient).verifyComplete(); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(authorizeRequest)); @@ -205,8 +209,7 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getAuthorizedClient()).isNull(); assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); - verify(this.authorizedClientService).saveAuthorizedClient( - eq(this.authorizedClient), eq(this.principal)); + verify(this.authorizedClientService).saveAuthorizedClient(eq(this.authorizedClient), eq(this.principal)); this.saveAuthorizedClientProbe.assertWasSubscribed(); verify(this.authorizedClientService, never()).removeAuthorizedClient(any(), any()); } @@ -214,25 +217,24 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void authorizeWhenNotAuthorizedAndSupportedProviderAndCustomSuccessHandlerThenInvokeCustomSuccessHandler() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); - when(this.authorizedClientService.loadAuthorizedClient( - any(), any())).thenReturn(Mono.empty()); + when(this.authorizedClientService.loadAuthorizedClient(any(), any())).thenReturn(Mono.empty()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.just(this.authorizedClient)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.just(this.authorizedClient)); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); PublisherProbe authorizationSuccessHandlerProbe = PublisherProbe.empty(); - this.authorizedClientManager.setAuthorizationSuccessHandler((client, principal, attributes) -> authorizationSuccessHandlerProbe.mono()); + this.authorizedClientManager.setAuthorizationSuccessHandler( + (client, principal, attributes) -> authorizationSuccessHandlerProbe.mono()); Mono authorizedClient = this.authorizedClientManager.authorize(authorizeRequest); - StepVerifier.create(authorizedClient) - .expectNext(this.authorizedClient) - .verifyComplete(); + StepVerifier.create(authorizedClient).expectNext(this.authorizedClient).verifyComplete(); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(authorizeRequest)); @@ -249,24 +251,23 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { @Test public void authorizeWhenInvalidTokenThenRemoveAuthorizedClient() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); - when(this.authorizedClientService.loadAuthorizedClient( - any(), any())).thenReturn(Mono.empty()); + when(this.authorizedClientService.loadAuthorizedClient(any(), any())).thenReturn(Mono.empty()); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); ClientAuthorizationException exception = new ClientAuthorizationException( new OAuth2Error(OAuth2ErrorCodes.INVALID_TOKEN, null, null), this.clientRegistration.getRegistrationId()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.error(exception)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.error(exception)); - assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest).block()) - .isEqualTo(exception); + assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest).block()).isEqualTo(exception); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(authorizeRequest)); @@ -276,32 +277,31 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getAuthorizedClient()).isNull(); assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); - verify(this.authorizedClientService).removeAuthorizedClient( - eq(this.clientRegistration.getRegistrationId()), eq(this.principal.getName())); + verify(this.authorizedClientService).removeAuthorizedClient(eq(this.clientRegistration.getRegistrationId()), + eq(this.principal.getName())); this.removeAuthorizedClientProbe.assertWasSubscribed(); verify(this.authorizedClientService, never()).saveAuthorizedClient(any(), any()); } @Test public void authorizeWhenInvalidGrantThenRemoveAuthorizedClient() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); - when(this.authorizedClientService.loadAuthorizedClient( - any(), any())).thenReturn(Mono.empty()); + when(this.authorizedClientService.loadAuthorizedClient(any(), any())).thenReturn(Mono.empty()); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); ClientAuthorizationException exception = new ClientAuthorizationException( new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT, null, null), this.clientRegistration.getRegistrationId()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.error(exception)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.error(exception)); - assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest).block()) - .isEqualTo(exception); + assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest).block()).isEqualTo(exception); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(authorizeRequest)); @@ -311,32 +311,31 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getAuthorizedClient()).isNull(); assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); - verify(this.authorizedClientService).removeAuthorizedClient( - eq(this.clientRegistration.getRegistrationId()), eq(this.principal.getName())); + verify(this.authorizedClientService).removeAuthorizedClient(eq(this.clientRegistration.getRegistrationId()), + eq(this.principal.getName())); this.removeAuthorizedClientProbe.assertWasSubscribed(); verify(this.authorizedClientService, never()).saveAuthorizedClient(any(), any()); } @Test public void authorizeWhenServerErrorThenDoNotRemoveAuthorizedClient() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); - when(this.authorizedClientService.loadAuthorizedClient( - any(), any())).thenReturn(Mono.empty()); + when(this.authorizedClientService.loadAuthorizedClient(any(), any())).thenReturn(Mono.empty()); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); ClientAuthorizationException exception = new ClientAuthorizationException( new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR, null, null), this.clientRegistration.getRegistrationId()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.error(exception)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.error(exception)); - assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest).block()) - .isEqualTo(exception); + assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest).block()).isEqualTo(exception); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(authorizeRequest)); @@ -352,23 +351,22 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { @Test public void authorizeWhenOAuth2AuthorizationExceptionThenDoNotRemoveAuthorizedClient() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); - when(this.authorizedClientService.loadAuthorizedClient( - any(), any())).thenReturn(Mono.empty()); + when(this.authorizedClientService.loadAuthorizedClient(any(), any())).thenReturn(Mono.empty()); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); OAuth2AuthorizationException exception = new OAuth2AuthorizationException( new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT, null, null)); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.error(exception)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.error(exception)); - assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest).block()) - .isEqualTo(exception); + assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest).block()).isEqualTo(exception); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(authorizeRequest)); @@ -384,26 +382,26 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { @Test public void authorizeWhenOAuth2AuthorizationExceptionAndCustomFailureHandlerThenInvokeCustomFailureHandler() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); - when(this.authorizedClientService.loadAuthorizedClient( - any(), any())).thenReturn(Mono.empty()); + when(this.authorizedClientService.loadAuthorizedClient(any(), any())).thenReturn(Mono.empty()); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); OAuth2AuthorizationException exception = new OAuth2AuthorizationException( new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT, null, null)); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.error(exception)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.error(exception)); PublisherProbe authorizationFailureHandlerProbe = PublisherProbe.empty(); - this.authorizedClientManager.setAuthorizationFailureHandler((client, principal, attributes) -> authorizationFailureHandlerProbe.mono()); + this.authorizedClientManager.setAuthorizationFailureHandler( + (client, principal, attributes) -> authorizationFailureHandlerProbe.mono()); - assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest).block()) - .isEqualTo(exception); + assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest).block()).isEqualTo(exception); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(authorizeRequest)); @@ -421,25 +419,23 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void authorizeWhenAuthorizedAndSupportedProviderThenReauthorized() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); - when(this.authorizedClientService.loadAuthorizedClient( - eq(this.clientRegistration.getRegistrationId()), eq(this.principal.getName()))).thenReturn(Mono.just(this.authorizedClient)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); + when(this.authorizedClientService.loadAuthorizedClient(eq(this.clientRegistration.getRegistrationId()), + eq(this.principal.getName()))).thenReturn(Mono.just(this.authorizedClient)); - OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.just(reauthorizedClient)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.just(reauthorizedClient)); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); Mono authorizedClient = this.authorizedClientManager.authorize(authorizeRequest); - StepVerifier.create(authorizedClient) - .expectNext(reauthorizedClient) - .verifyComplete(); + StepVerifier.create(authorizedClient).expectNext(reauthorizedClient).verifyComplete(); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(authorizeRequest)); @@ -448,8 +444,7 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getAuthorizedClient()).isSameAs(this.authorizedClient); assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); - verify(this.authorizedClientService).saveAuthorizedClient( - eq(reauthorizedClient), eq(this.principal)); + verify(this.authorizedClientService).saveAuthorizedClient(eq(reauthorizedClient), eq(this.principal)); this.saveAuthorizedClientProbe.assertWasSubscribed(); verify(this.authorizedClientService, never()).removeAuthorizedClient(any(), any()); } @@ -459,13 +454,10 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { public void reauthorizeWhenUnsupportedProviderThenNotReauthorized() { when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.empty()); OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .build(); + .principal(this.principal).build(); Mono authorizedClient = this.authorizedClientManager.authorize(reauthorizeRequest); - StepVerifier.create(authorizedClient) - .expectNext(this.authorizedClient) - .verifyComplete(); + StepVerifier.create(authorizedClient).expectNext(this.authorizedClient).verifyComplete(); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(reauthorizeRequest)); @@ -474,27 +466,24 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getAuthorizedClient()).isSameAs(this.authorizedClient); assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); - verify(this.authorizedClientService, never()).saveAuthorizedClient( - any(OAuth2AuthorizedClient.class), eq(this.principal)); + verify(this.authorizedClientService, never()).saveAuthorizedClient(any(OAuth2AuthorizedClient.class), + eq(this.principal)); } @SuppressWarnings("unchecked") @Test public void reauthorizeWhenSupportedProviderThenReauthorized() { - OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.just(reauthorizedClient)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.just(reauthorizedClient)); OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .build(); + .principal(this.principal).build(); Mono authorizedClient = this.authorizedClientManager.authorize(reauthorizeRequest); - StepVerifier.create(authorizedClient) - .expectNext(reauthorizedClient) - .verifyComplete(); + StepVerifier.create(authorizedClient).expectNext(reauthorizedClient).verifyComplete(); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(reauthorizeRequest)); @@ -504,8 +493,7 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getAuthorizedClient()).isSameAs(this.authorizedClient); assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); - verify(this.authorizedClientService).saveAuthorizedClient( - eq(reauthorizedClient), eq(this.principal)); + verify(this.authorizedClientService).saveAuthorizedClient(eq(reauthorizedClient), eq(this.principal)); this.saveAuthorizedClientProbe.assertWasSubscribed(); verify(this.authorizedClientService, never()).removeAuthorizedClient(any(), any()); } @@ -513,25 +501,21 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void reauthorizeWhenRequestAttributeScopeThenMappedToContext() { - OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.just(reauthorizedClient)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.just(reauthorizedClient)); OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .attribute(OAuth2ParameterNames.SCOPE, "read write") - .build(); + .principal(this.principal).attribute(OAuth2ParameterNames.SCOPE, "read write").build(); - this.authorizedClientManager.setContextAttributesMapper(new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager.DefaultContextAttributesMapper()); + this.authorizedClientManager.setContextAttributesMapper( + new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager.DefaultContextAttributesMapper()); Mono authorizedClient = this.authorizedClientManager.authorize(reauthorizeRequest); - StepVerifier.create(authorizedClient) - .expectNext(reauthorizedClient) - .verifyComplete(); - verify(this.authorizedClientService).saveAuthorizedClient( - eq(reauthorizedClient), eq(this.principal)); + StepVerifier.create(authorizedClient).expectNext(reauthorizedClient).verifyComplete(); + verify(this.authorizedClientService).saveAuthorizedClient(eq(reauthorizedClient), eq(this.principal)); this.saveAuthorizedClientProbe.assertWasSubscribed(); verify(this.authorizedClientService, never()).removeAuthorizedClient(any(), any()); @@ -541,9 +525,12 @@ public class AuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getClientRegistration()).isEqualTo(this.clientRegistration); assertThat(authorizationContext.getAuthorizedClient()).isSameAs(this.authorizedClient); assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); - assertThat(authorizationContext.getAttributes()).containsKey(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME); - String[] requestScopeAttribute = authorizationContext.getAttribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME); + assertThat(authorizationContext.getAttributes()) + .containsKey(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME); + String[] requestScopeAttribute = authorizationContext + .getAttribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME); assertThat(requestScopeAttribute).contains("read", "write"); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/ClientCredentialsOAuth2AuthorizedClientProviderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/ClientCredentialsOAuth2AuthorizedClientProviderTests.java index c2b85c7a30..9255fdfd6b 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/ClientCredentialsOAuth2AuthorizedClientProviderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/ClientCredentialsOAuth2AuthorizedClientProviderTests.java @@ -43,9 +43,13 @@ import static org.mockito.Mockito.when; * @author Joe Grandja */ public class ClientCredentialsOAuth2AuthorizedClientProviderTests { + private ClientCredentialsOAuth2AuthorizedClientProvider authorizedClientProvider; + private OAuth2AccessTokenResponseClient accessTokenResponseClient; + private ClientRegistration clientRegistration; + private Authentication principal; @Before @@ -60,46 +64,39 @@ public class ClientCredentialsOAuth2AuthorizedClientProviderTests { @Test public void setAccessTokenResponseClientWhenClientIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setAccessTokenResponseClient(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("accessTokenResponseClient cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("accessTokenResponseClient cannot be null"); } @Test public void setClockSkewWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClockSkew(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clockSkew cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clockSkew cannot be null"); } @Test public void setClockSkewWhenNegativeSecondsThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClockSkew(Duration.ofSeconds(-1))) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clockSkew must be >= 0"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clockSkew must be >= 0"); } @Test public void setClockWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClock(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clock cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clock cannot be null"); } @Test public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.authorize(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("context cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("context cannot be null"); } @Test public void authorizeWhenNotClientCredentialsThenUnableToAuthorize() { ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(clientRegistration) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(clientRegistration).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext)).isNull(); } @@ -108,10 +105,8 @@ public class ClientCredentialsOAuth2AuthorizedClientProviderTests { OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistration) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistration).principal(this.principal).build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientProvider.authorize(authorizationContext); assertThat(authorizedClient.getClientRegistration()).isSameAs(this.clientRegistration); @@ -123,18 +118,16 @@ public class ClientCredentialsOAuth2AuthorizedClientProviderTests { public void authorizeWhenClientCredentialsAndTokenExpiredThenReauthorize() { Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant expiresAt = issuedAt.plus(Duration.ofMinutes(60)); - OAuth2AccessToken accessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-1234", issuedAt, expiresAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), accessToken); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token-1234", + issuedAt, expiresAt); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), accessToken); OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); authorizedClient = this.authorizedClientProvider.authorize(authorizationContext); assertThat(authorizedClient.getClientRegistration()).isSameAs(this.clientRegistration); @@ -144,13 +137,11 @@ public class ClientCredentialsOAuth2AuthorizedClientProviderTests { @Test public void authorizeWhenClientCredentialsAndTokenNotExpiredThenNotReauthorize() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), TestOAuth2AccessTokens.noScopes()); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.noScopes()); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext)).isNull(); } @@ -160,21 +151,20 @@ public class ClientCredentialsOAuth2AuthorizedClientProviderTests { Instant now = Instant.now(); Instant issuedAt = now.minus(Duration.ofMinutes(60)); Instant expiresAt = now.minus(Duration.ofMinutes(1)); - OAuth2AccessToken expiresInOneMinAccessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-1234", issuedAt, expiresAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), expiresInOneMinAccessToken); + OAuth2AccessToken expiresInOneMinAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + "access-token-1234", issuedAt, expiresAt); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), expiresInOneMinAccessToken); - // Shorten the lifespan of the access token by 90 seconds, which will ultimately force it to expire on the client + // Shorten the lifespan of the access token by 90 seconds, which will ultimately + // force it to expire on the client this.authorizedClientProvider.setClockSkew(Duration.ofSeconds(90)); OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); OAuth2AuthorizedClient reauthorizedClient = this.authorizedClientProvider.authorize(authorizationContext); @@ -182,4 +172,5 @@ public class ClientCredentialsOAuth2AuthorizedClientProviderTests { assertThat(reauthorizedClient.getPrincipalName()).isEqualTo(this.principal.getName()); assertThat(reauthorizedClient.getAccessToken()).isEqualTo(accessTokenResponse.getAccessToken()); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/ClientCredentialsReactiveOAuth2AuthorizedClientProviderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/ClientCredentialsReactiveOAuth2AuthorizedClientProviderTests.java index af33a645ac..607b00036a 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/ClientCredentialsReactiveOAuth2AuthorizedClientProviderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/ClientCredentialsReactiveOAuth2AuthorizedClientProviderTests.java @@ -44,9 +44,13 @@ import static org.mockito.Mockito.when; * @author Joe Grandja */ public class ClientCredentialsReactiveOAuth2AuthorizedClientProviderTests { + private ClientCredentialsReactiveOAuth2AuthorizedClientProvider authorizedClientProvider; + private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient; + private ClientRegistration clientRegistration; + private Authentication principal; @Before @@ -61,46 +65,39 @@ public class ClientCredentialsReactiveOAuth2AuthorizedClientProviderTests { @Test public void setAccessTokenResponseClientWhenClientIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setAccessTokenResponseClient(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("accessTokenResponseClient cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("accessTokenResponseClient cannot be null"); } @Test public void setClockSkewWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClockSkew(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clockSkew cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clockSkew cannot be null"); } @Test public void setClockSkewWhenNegativeSecondsThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClockSkew(Duration.ofSeconds(-1))) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clockSkew must be >= 0"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clockSkew must be >= 0"); } @Test public void setClockWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClock(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clock cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clock cannot be null"); } @Test public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.authorize(null).block()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("context cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("context cannot be null"); } @Test public void authorizeWhenNotClientCredentialsThenUnableToAuthorize() { ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(clientRegistration) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(clientRegistration).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext).block()).isNull(); } @@ -109,10 +106,8 @@ public class ClientCredentialsReactiveOAuth2AuthorizedClientProviderTests { OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistration) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistration).principal(this.principal).build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientProvider.authorize(authorizationContext).block(); assertThat(authorizedClient.getClientRegistration()).isSameAs(this.clientRegistration); @@ -124,18 +119,16 @@ public class ClientCredentialsReactiveOAuth2AuthorizedClientProviderTests { public void authorizeWhenClientCredentialsAndTokenExpiredThenReauthorize() { Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant expiresAt = issuedAt.plus(Duration.ofMinutes(60)); - OAuth2AccessToken accessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-1234", issuedAt, expiresAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), accessToken); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token-1234", + issuedAt, expiresAt); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), accessToken); OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); authorizedClient = this.authorizedClientProvider.authorize(authorizationContext).block(); assertThat(authorizedClient.getClientRegistration()).isSameAs(this.clientRegistration); @@ -145,13 +138,11 @@ public class ClientCredentialsReactiveOAuth2AuthorizedClientProviderTests { @Test public void authorizeWhenClientCredentialsAndTokenNotExpiredThenNotReauthorize() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), TestOAuth2AccessTokens.noScopes()); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.noScopes()); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext).block()).isNull(); } @@ -161,26 +152,27 @@ public class ClientCredentialsReactiveOAuth2AuthorizedClientProviderTests { Instant now = Instant.now(); Instant issuedAt = now.minus(Duration.ofMinutes(60)); Instant expiresAt = now.minus(Duration.ofMinutes(1)); - OAuth2AccessToken expiresInOneMinAccessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-1234", issuedAt, expiresAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), expiresInOneMinAccessToken); + OAuth2AccessToken expiresInOneMinAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + "access-token-1234", issuedAt, expiresAt); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), expiresInOneMinAccessToken); - // Shorten the lifespan of the access token by 90 seconds, which will ultimately force it to expire on the client + // Shorten the lifespan of the access token by 90 seconds, which will ultimately + // force it to expire on the client this.authorizedClientProvider.setClockSkew(Duration.ofSeconds(90)); OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); - OAuth2AuthorizedClient reauthorizedClient = this.authorizedClientProvider.authorize(authorizationContext).block(); + OAuth2AuthorizedClient reauthorizedClient = this.authorizedClientProvider.authorize(authorizationContext) + .block(); assertThat(reauthorizedClient.getClientRegistration()).isSameAs(this.clientRegistration); assertThat(reauthorizedClient.getPrincipalName()).isEqualTo(this.principal.getName()); assertThat(reauthorizedClient.getAccessToken()).isEqualTo(accessTokenResponse.getAccessToken()); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/DelegatingOAuth2AuthorizedClientProviderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/DelegatingOAuth2AuthorizedClientProviderTests.java index f930233aa8..5ec89f06b7 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/DelegatingOAuth2AuthorizedClientProviderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/DelegatingOAuth2AuthorizedClientProviderTests.java @@ -49,8 +49,7 @@ public class DelegatingOAuth2AuthorizedClientProviderTests { public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() { DelegatingOAuth2AuthorizedClientProvider delegate = new DelegatingOAuth2AuthorizedClientProvider( mock(OAuth2AuthorizedClientProvider.class)); - assertThatThrownBy(() -> delegate.authorize(null)) - .isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> delegate.authorize(null)).isInstanceOf(IllegalArgumentException.class) .hasMessage("context cannot be null"); } @@ -58,17 +57,17 @@ public class DelegatingOAuth2AuthorizedClientProviderTests { public void authorizeWhenProviderCanAuthorizeThenReturnAuthorizedClient() { Authentication principal = new TestingAuthenticationToken("principal", "password"); ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - clientRegistration, principal.getName(), TestOAuth2AccessTokens.noScopes()); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(clientRegistration, principal.getName(), + TestOAuth2AccessTokens.noScopes()); OAuth2AuthorizedClientProvider authorizedClientProvider = mock(OAuth2AuthorizedClientProvider.class); when(authorizedClientProvider.authorize(any())).thenReturn(authorizedClient); DelegatingOAuth2AuthorizedClientProvider delegate = new DelegatingOAuth2AuthorizedClientProvider( - mock(OAuth2AuthorizedClientProvider.class), mock(OAuth2AuthorizedClientProvider.class), authorizedClientProvider); + mock(OAuth2AuthorizedClientProvider.class), mock(OAuth2AuthorizedClientProvider.class), + authorizedClientProvider); OAuth2AuthorizationContext context = OAuth2AuthorizationContext.withClientRegistration(clientRegistration) - .principal(principal) - .build(); + .principal(principal).build(); OAuth2AuthorizedClient reauthorizedClient = delegate.authorize(context); assertThat(reauthorizedClient).isSameAs(authorizedClient); } @@ -77,11 +76,11 @@ public class DelegatingOAuth2AuthorizedClientProviderTests { public void authorizeWhenProviderCantAuthorizeThenReturnNull() { ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); OAuth2AuthorizationContext context = OAuth2AuthorizationContext.withClientRegistration(clientRegistration) - .principal(new TestingAuthenticationToken("principal", "password")) - .build(); + .principal(new TestingAuthenticationToken("principal", "password")).build(); DelegatingOAuth2AuthorizedClientProvider delegate = new DelegatingOAuth2AuthorizedClientProvider( mock(OAuth2AuthorizedClientProvider.class), mock(OAuth2AuthorizedClientProvider.class)); assertThat(delegate.authorize(context)).isNull(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/DelegatingReactiveOAuth2AuthorizedClientProviderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/DelegatingReactiveOAuth2AuthorizedClientProviderTests.java index 45ddf6e528..c136b6232a 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/DelegatingReactiveOAuth2AuthorizedClientProviderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/DelegatingReactiveOAuth2AuthorizedClientProviderTests.java @@ -40,8 +40,8 @@ public class DelegatingReactiveOAuth2AuthorizedClientProviderTests { @Test public void constructorWhenProvidersIsEmptyThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new DelegatingReactiveOAuth2AuthorizedClientProvider(new ReactiveOAuth2AuthorizedClientProvider[0])) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> new DelegatingReactiveOAuth2AuthorizedClientProvider( + new ReactiveOAuth2AuthorizedClientProvider[0])).isInstanceOf(IllegalArgumentException.class); assertThatThrownBy(() -> new DelegatingReactiveOAuth2AuthorizedClientProvider(Collections.emptyList())) .isInstanceOf(IllegalArgumentException.class); } @@ -50,8 +50,7 @@ public class DelegatingReactiveOAuth2AuthorizedClientProviderTests { public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() { DelegatingReactiveOAuth2AuthorizedClientProvider delegate = new DelegatingReactiveOAuth2AuthorizedClientProvider( mock(ReactiveOAuth2AuthorizedClientProvider.class)); - assertThatThrownBy(() -> delegate.authorize(null).block()) - .isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> delegate.authorize(null).block()).isInstanceOf(IllegalArgumentException.class) .hasMessage("context cannot be null"); } @@ -59,21 +58,23 @@ public class DelegatingReactiveOAuth2AuthorizedClientProviderTests { public void authorizeWhenProviderCanAuthorizeThenReturnAuthorizedClient() { Authentication principal = new TestingAuthenticationToken("principal", "password"); ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - clientRegistration, principal.getName(), TestOAuth2AccessTokens.noScopes()); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(clientRegistration, principal.getName(), + TestOAuth2AccessTokens.noScopes()); - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider1 = mock(ReactiveOAuth2AuthorizedClientProvider.class); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider1 = mock( + ReactiveOAuth2AuthorizedClientProvider.class); when(authorizedClientProvider1.authorize(any())).thenReturn(Mono.empty()); - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider2 = mock(ReactiveOAuth2AuthorizedClientProvider.class); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider2 = mock( + ReactiveOAuth2AuthorizedClientProvider.class); when(authorizedClientProvider2.authorize(any())).thenReturn(Mono.empty()); - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider3 = mock(ReactiveOAuth2AuthorizedClientProvider.class); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider3 = mock( + ReactiveOAuth2AuthorizedClientProvider.class); when(authorizedClientProvider3.authorize(any())).thenReturn(Mono.just(authorizedClient)); DelegatingReactiveOAuth2AuthorizedClientProvider delegate = new DelegatingReactiveOAuth2AuthorizedClientProvider( authorizedClientProvider1, authorizedClientProvider2, authorizedClientProvider3); OAuth2AuthorizationContext context = OAuth2AuthorizationContext.withClientRegistration(clientRegistration) - .principal(principal) - .build(); + .principal(principal).build(); OAuth2AuthorizedClient reauthorizedClient = delegate.authorize(context).block(); assertThat(reauthorizedClient).isSameAs(authorizedClient); } @@ -82,16 +83,18 @@ public class DelegatingReactiveOAuth2AuthorizedClientProviderTests { public void authorizeWhenProviderCantAuthorizeThenReturnNull() { ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); OAuth2AuthorizationContext context = OAuth2AuthorizationContext.withClientRegistration(clientRegistration) - .principal(new TestingAuthenticationToken("principal", "password")) - .build(); + .principal(new TestingAuthenticationToken("principal", "password")).build(); - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider1 = mock(ReactiveOAuth2AuthorizedClientProvider.class); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider1 = mock( + ReactiveOAuth2AuthorizedClientProvider.class); when(authorizedClientProvider1.authorize(any())).thenReturn(Mono.empty()); - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider2 = mock(ReactiveOAuth2AuthorizedClientProvider.class); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider2 = mock( + ReactiveOAuth2AuthorizedClientProvider.class); when(authorizedClientProvider2.authorize(any())).thenReturn(Mono.empty()); DelegatingReactiveOAuth2AuthorizedClientProvider delegate = new DelegatingReactiveOAuth2AuthorizedClientProvider( authorizedClientProvider1, authorizedClientProvider2); assertThat(delegate.authorize(context).block()).isNull(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/InMemoryOAuth2AuthorizedClientServiceTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/InMemoryOAuth2AuthorizedClientServiceTests.java index dbb00dbfcc..6561adab35 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/InMemoryOAuth2AuthorizedClientServiceTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/InMemoryOAuth2AuthorizedClientServiceTests.java @@ -39,24 +39,23 @@ import static org.mockito.Mockito.when; * @author Vedran Pavic */ public class InMemoryOAuth2AuthorizedClientServiceTests { + private String principalName1 = "principal-1"; + private String principalName2 = "principal-2"; private ClientRegistration registration1 = TestClientRegistrations.clientRegistration().build(); private ClientRegistration registration2 = TestClientRegistrations.clientRegistration2().build(); - private ClientRegistration registration3 = TestClientRegistrations.clientRegistration() - .clientId("client-3") - .registrationId("registration-3") - .build(); + private ClientRegistration registration3 = TestClientRegistrations.clientRegistration().clientId("client-3") + .registrationId("registration-3").build(); - private ClientRegistrationRepository clientRegistrationRepository = - new InMemoryClientRegistrationRepository(this.registration1, this.registration2, this.registration3); - - private InMemoryOAuth2AuthorizedClientService authorizedClientService = - new InMemoryOAuth2AuthorizedClientService(this.clientRegistrationRepository); + private ClientRegistrationRepository clientRegistrationRepository = new InMemoryClientRegistrationRepository( + this.registration1, this.registration2, this.registration3); + private InMemoryOAuth2AuthorizedClientService authorizedClientService = new InMemoryOAuth2AuthorizedClientService( + this.clientRegistrationRepository); @Test(expected = IllegalArgumentException.class) public void constructorWhenClientRegistrationRepositoryIsNullThenThrowIllegalArgumentException() { @@ -66,8 +65,7 @@ public class InMemoryOAuth2AuthorizedClientServiceTests { @Test public void constructorWhenAuthorizedClientsIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new InMemoryOAuth2AuthorizedClientService(this.clientRegistrationRepository, null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizedClients cannot be empty"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizedClients cannot be empty"); } @Test @@ -82,8 +80,8 @@ public class InMemoryOAuth2AuthorizedClientServiceTests { InMemoryOAuth2AuthorizedClientService authorizedClientService = new InMemoryOAuth2AuthorizedClientService( clientRegistrationRepository, authorizedClients); - assertThat((OAuth2AuthorizedClient) authorizedClientService.loadAuthorizedClient( - registrationId, this.principalName1)).isNotNull(); + assertThat((OAuth2AuthorizedClient) authorizedClientService.loadAuthorizedClient(registrationId, + this.principalName1)).isNotNull(); } @Test(expected = IllegalArgumentException.class) @@ -98,15 +96,15 @@ public class InMemoryOAuth2AuthorizedClientServiceTests { @Test public void loadAuthorizedClientWhenClientRegistrationNotFoundThenReturnNull() { - OAuth2AuthorizedClient authorizedClient = this.authorizedClientService.loadAuthorizedClient( - "registration-not-found", this.principalName1); + OAuth2AuthorizedClient authorizedClient = this.authorizedClientService + .loadAuthorizedClient("registration-not-found", this.principalName1); assertThat(authorizedClient).isNull(); } @Test public void loadAuthorizedClientWhenClientRegistrationFoundButNotAssociatedToPrincipalThenReturnNull() { - OAuth2AuthorizedClient authorizedClient = this.authorizedClientService.loadAuthorizedClient( - this.registration1.getRegistrationId(), "principal-not-found"); + OAuth2AuthorizedClient authorizedClient = this.authorizedClientService + .loadAuthorizedClient(this.registration1.getRegistrationId(), "principal-not-found"); assertThat(authorizedClient).isNull(); } @@ -115,12 +113,12 @@ public class InMemoryOAuth2AuthorizedClientServiceTests { Authentication authentication = mock(Authentication.class); when(authentication.getName()).thenReturn(this.principalName1); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration1, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration1, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientService.saveAuthorizedClient(authorizedClient, authentication); - OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientService.loadAuthorizedClient( - this.registration1.getRegistrationId(), this.principalName1); + OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientService + .loadAuthorizedClient(this.registration1.getRegistrationId(), this.principalName1); assertThat(loadedAuthorizedClient).isEqualTo(authorizedClient); } @@ -139,12 +137,12 @@ public class InMemoryOAuth2AuthorizedClientServiceTests { Authentication authentication = mock(Authentication.class); when(authentication.getName()).thenReturn(this.principalName2); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration3, this.principalName2, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration3, this.principalName2, + mock(OAuth2AccessToken.class)); this.authorizedClientService.saveAuthorizedClient(authorizedClient, authentication); - OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientService.loadAuthorizedClient( - this.registration3.getRegistrationId(), this.principalName2); + OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientService + .loadAuthorizedClient(this.registration3.getRegistrationId(), this.principalName2); assertThat(loadedAuthorizedClient).isEqualTo(authorizedClient); } @@ -163,18 +161,20 @@ public class InMemoryOAuth2AuthorizedClientServiceTests { Authentication authentication = mock(Authentication.class); when(authentication.getName()).thenReturn(this.principalName2); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration2, this.principalName2, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration2, this.principalName2, + mock(OAuth2AccessToken.class)); this.authorizedClientService.saveAuthorizedClient(authorizedClient, authentication); - OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientService.loadAuthorizedClient( - this.registration2.getRegistrationId(), this.principalName2); + OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientService + .loadAuthorizedClient(this.registration2.getRegistrationId(), this.principalName2); assertThat(loadedAuthorizedClient).isNotNull(); - this.authorizedClientService.removeAuthorizedClient(this.registration2.getRegistrationId(), this.principalName2); + this.authorizedClientService.removeAuthorizedClient(this.registration2.getRegistrationId(), + this.principalName2); - loadedAuthorizedClient = this.authorizedClientService.loadAuthorizedClient( - this.registration2.getRegistrationId(), this.principalName2); + loadedAuthorizedClient = this.authorizedClientService + .loadAuthorizedClient(this.registration2.getRegistrationId(), this.principalName2); assertThat(loadedAuthorizedClient).isNull(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/InMemoryReactiveOAuth2AuthorizedClientServiceTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/InMemoryReactiveOAuth2AuthorizedClientServiceTests.java index 2d05534822..69aa766928 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/InMemoryReactiveOAuth2AuthorizedClientServiceTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/InMemoryReactiveOAuth2AuthorizedClientServiceTests.java @@ -43,6 +43,7 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class InMemoryReactiveOAuth2AuthorizedClientServiceTests { + @Mock private ReactiveClientRegistrationRepository clientRegistrationRepository; @@ -54,24 +55,16 @@ public class InMemoryReactiveOAuth2AuthorizedClientServiceTests { private Authentication principal = new TestingAuthenticationToken(this.principalName, "notused"); - OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "token", - Instant.now(), + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token", Instant.now(), Instant.now().plus(Duration.ofDays(1))); private ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(this.clientRegistrationId) .redirectUri("{baseUrl}/{action}/oauth2/code/{registrationId}") .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .scope("read:user") + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).scope("read:user") .authorizationUri("https://github.com/login/oauth/authorize") - .tokenUri("https://github.com/login/oauth/access_token") - .userInfoUri("https://api.github.com/user") - .userNameAttributeName("id") - .clientName("GitHub") - .clientId("clientId") - .clientSecret("clientSecret") - .build(); + .tokenUri("https://github.com/login/oauth/access_token").userInfoUri("https://api.github.com/user") + .userNameAttributeName("id").clientName("GitHub").clientId("clientId").clientSecret("clientSecret").build(); @Before public void setup() { @@ -89,58 +82,64 @@ public class InMemoryReactiveOAuth2AuthorizedClientServiceTests { @Test public void loadAuthorizedClientWhenClientRegistrationIdNullThenIllegalArgumentException() { this.clientRegistrationId = null; - assertThatThrownBy(() -> this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void loadAuthorizedClientWhenClientRegistrationIdEmptyThenIllegalArgumentException() { this.clientRegistrationId = ""; - assertThatThrownBy(() -> this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void loadAuthorizedClientWhenPrincipalNameNullThenIllegalArgumentException() { this.principalName = null; - assertThatThrownBy(() -> this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void loadAuthorizedClientWhenPrincipalNameEmptyThenIllegalArgumentException() { this.principalName = ""; - assertThatThrownBy(() -> this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void loadAuthorizedClientWhenClientRegistrationIdNotFoundThenEmpty() { when(this.clientRegistrationRepository.findByRegistrationId(this.clientRegistrationId)) .thenReturn(Mono.empty()); - StepVerifier - .create(this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) - .verifyComplete(); + StepVerifier.create( + this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) + .verifyComplete(); } @Test public void loadAuthorizedClientWhenClientRegistrationFoundAndNotAuthorizedClientThenEmpty() { - when(this.clientRegistrationRepository.findByRegistrationId(this.clientRegistrationId)).thenReturn(Mono.just(this.clientRegistration)); - StepVerifier - .create(this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) + when(this.clientRegistrationRepository.findByRegistrationId(this.clientRegistrationId)) + .thenReturn(Mono.just(this.clientRegistration)); + StepVerifier.create( + this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) .verifyComplete(); } @Test public void loadAuthorizedClientWhenClientRegistrationFoundThenFound() { - when(this.clientRegistrationRepository.findByRegistrationId(this.clientRegistrationId)).thenReturn(Mono.just(this.clientRegistration)); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, this.principalName, this.accessToken); - Mono saveAndLoad = this.authorizedClientService.saveAuthorizedClient(authorizedClient, this.principal) + when(this.clientRegistrationRepository.findByRegistrationId(this.clientRegistrationId)) + .thenReturn(Mono.just(this.clientRegistration)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principalName, this.accessToken); + Mono saveAndLoad = this.authorizedClientService + .saveAuthorizedClient(authorizedClient, this.principal) .then(this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)); - StepVerifier.create(saveAndLoad) - .expectNext(authorizedClient) - .verifyComplete(); + StepVerifier.create(saveAndLoad).expectNext(authorizedClient).verifyComplete(); } @Test @@ -152,7 +151,8 @@ public class InMemoryReactiveOAuth2AuthorizedClientServiceTests { @Test public void saveAuthorizedClientWhenPrincipalNullThenIllegalArgumentException() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, this.principalName, this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principalName, this.accessToken); this.principal = null; assertThatThrownBy(() -> this.authorizedClientService.saveAuthorizedClient(authorizedClient, this.principal)) .isInstanceOf(IllegalArgumentException.class); @@ -161,51 +161,59 @@ public class InMemoryReactiveOAuth2AuthorizedClientServiceTests { @Test public void removeAuthorizedClientWhenClientRegistrationIdNullThenIllegalArgumentException() { this.clientRegistrationId = null; - assertThatThrownBy(() -> this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void removeAuthorizedClientWhenClientRegistrationIdEmptyThenIllegalArgumentException() { this.clientRegistrationId = ""; - assertThatThrownBy(() -> this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void removeAuthorizedClientWhenPrincipalNameNullThenIllegalArgumentException() { this.principalName = null; - assertThatThrownBy(() -> this.authorizedClientService.removeAuthorizedClient(this.clientRegistrationId, this.principalName)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.authorizedClientService.removeAuthorizedClient(this.clientRegistrationId, + this.principalName)).isInstanceOf(IllegalArgumentException.class); } @Test public void removeAuthorizedClientWhenPrincipalNameEmptyThenIllegalArgumentException() { this.principalName = ""; - assertThatThrownBy(() -> this.authorizedClientService.removeAuthorizedClient(this.clientRegistrationId, this.principalName)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.authorizedClientService.removeAuthorizedClient(this.clientRegistrationId, + this.principalName)).isInstanceOf(IllegalArgumentException.class); } @Test public void removeAuthorizedClientWhenClientIdThenNoException() { - when(this.clientRegistrationRepository.findByRegistrationId(this.clientRegistrationId)).thenReturn(Mono.empty()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, this.principalName, this.accessToken); - Mono saveAndDeleteAndLoad = this.authorizedClientService.saveAuthorizedClient(authorizedClient, this.principal) - .then(this.authorizedClientService.removeAuthorizedClient(this.clientRegistrationId, this.principalName)); + when(this.clientRegistrationRepository.findByRegistrationId(this.clientRegistrationId)) + .thenReturn(Mono.empty()); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principalName, this.accessToken); + Mono saveAndDeleteAndLoad = this.authorizedClientService + .saveAuthorizedClient(authorizedClient, this.principal).then(this.authorizedClientService + .removeAuthorizedClient(this.clientRegistrationId, this.principalName)); - StepVerifier.create(saveAndDeleteAndLoad) - .verifyComplete(); + StepVerifier.create(saveAndDeleteAndLoad).verifyComplete(); } @Test public void removeAuthorizedClientWhenClientRegistrationFoundRemovedThenNotFound() { - when(this.clientRegistrationRepository.findByRegistrationId(this.clientRegistrationId)).thenReturn(Mono.just(this.clientRegistration)); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, this.principalName, this.accessToken); - Mono saveAndDeleteAndLoad = this.authorizedClientService.saveAuthorizedClient(authorizedClient, this.principal) - .then(this.authorizedClientService.removeAuthorizedClient(this.clientRegistrationId, this.principalName)) + when(this.clientRegistrationRepository.findByRegistrationId(this.clientRegistrationId)) + .thenReturn(Mono.just(this.clientRegistration)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principalName, this.accessToken); + Mono saveAndDeleteAndLoad = this.authorizedClientService + .saveAuthorizedClient(authorizedClient, this.principal) + .then(this.authorizedClientService.removeAuthorizedClient(this.clientRegistrationId, + this.principalName)) .then(this.authorizedClientService.loadAuthorizedClient(this.clientRegistrationId, this.principalName)); - StepVerifier.create(saveAndDeleteAndLoad) - .verifyComplete(); + StepVerifier.create(saveAndDeleteAndLoad).verifyComplete(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/JdbcOAuth2AuthorizedClientServiceTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/JdbcOAuth2AuthorizedClientServiceTests.java index 78fe9c30fb..978da44b57 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/JdbcOAuth2AuthorizedClientServiceTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/JdbcOAuth2AuthorizedClientServiceTests.java @@ -68,12 +68,19 @@ import static org.mockito.Mockito.when; * @author Stav Shamir */ public class JdbcOAuth2AuthorizedClientServiceTests { + private static final String OAUTH2_CLIENT_SCHEMA_SQL_RESOURCE = "org/springframework/security/oauth2/client/oauth2-client-schema.sql"; + private static int principalId = 1000; + private ClientRegistration clientRegistration; + private ClientRegistrationRepository clientRegistrationRepository; + private EmbeddedDatabase db; + private JdbcOperations jdbcOperations; + private JdbcOAuth2AuthorizedClientService authorizedClientService; @Before @@ -83,8 +90,8 @@ public class JdbcOAuth2AuthorizedClientServiceTests { when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(this.clientRegistration); this.db = createDb(); this.jdbcOperations = new JdbcTemplate(this.db); - this.authorizedClientService = new JdbcOAuth2AuthorizedClientService( - this.jdbcOperations, this.clientRegistrationRepository); + this.authorizedClientService = new JdbcOAuth2AuthorizedClientService(this.jdbcOperations, + this.clientRegistrationRepository); } @After @@ -95,22 +102,19 @@ public class JdbcOAuth2AuthorizedClientServiceTests { @Test public void constructorWhenJdbcOperationsIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new JdbcOAuth2AuthorizedClientService(null, this.clientRegistrationRepository)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("jdbcOperations cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("jdbcOperations cannot be null"); } @Test public void constructorWhenClientRegistrationRepositoryIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new JdbcOAuth2AuthorizedClientService(this.jdbcOperations, null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clientRegistrationRepository cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clientRegistrationRepository cannot be null"); } @Test public void setAuthorizedClientRowMapperWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientService.setAuthorizedClientRowMapper(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizedClientRowMapper cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizedClientRowMapper cannot be null"); } @Test @@ -123,21 +127,20 @@ public class JdbcOAuth2AuthorizedClientServiceTests { @Test public void loadAuthorizedClientWhenClientRegistrationIdIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientService.loadAuthorizedClient(null, "principalName")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clientRegistrationId cannot be empty"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clientRegistrationId cannot be empty"); } @Test public void loadAuthorizedClientWhenPrincipalNameIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.authorizedClientService.loadAuthorizedClient(this.clientRegistration.getRegistrationId(), null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("principalName cannot be empty"); + assertThatThrownBy(() -> this.authorizedClientService + .loadAuthorizedClient(this.clientRegistration.getRegistrationId(), null)) + .isInstanceOf(IllegalArgumentException.class).hasMessage("principalName cannot be empty"); } @Test public void loadAuthorizedClientWhenDoesNotExistThenReturnNull() { - OAuth2AuthorizedClient authorizedClient = this.authorizedClientService.loadAuthorizedClient( - "registration-not-found", "principalName"); + OAuth2AuthorizedClient authorizedClient = this.authorizedClientService + .loadAuthorizedClient("registration-not-found", "principalName"); assertThat(authorizedClient).isNull(); } @@ -148,19 +151,25 @@ public class JdbcOAuth2AuthorizedClientServiceTests { this.authorizedClientService.saveAuthorizedClient(expected, principal); - OAuth2AuthorizedClient authorizedClient = this.authorizedClientService.loadAuthorizedClient( - this.clientRegistration.getRegistrationId(), principal.getName()); + OAuth2AuthorizedClient authorizedClient = this.authorizedClientService + .loadAuthorizedClient(this.clientRegistration.getRegistrationId(), principal.getName()); assertThat(authorizedClient).isNotNull(); assertThat(authorizedClient.getClientRegistration()).isEqualTo(expected.getClientRegistration()); assertThat(authorizedClient.getPrincipalName()).isEqualTo(expected.getPrincipalName()); - assertThat(authorizedClient.getAccessToken().getTokenType()).isEqualTo(expected.getAccessToken().getTokenType()); - assertThat(authorizedClient.getAccessToken().getTokenValue()).isEqualTo(expected.getAccessToken().getTokenValue()); - assertThat(authorizedClient.getAccessToken().getIssuedAt()).isCloseTo(expected.getAccessToken().getIssuedAt(), within(1, ChronoUnit.MILLIS)); - assertThat(authorizedClient.getAccessToken().getExpiresAt()).isCloseTo(expected.getAccessToken().getExpiresAt(), within(1, ChronoUnit.MILLIS)); + assertThat(authorizedClient.getAccessToken().getTokenType()) + .isEqualTo(expected.getAccessToken().getTokenType()); + assertThat(authorizedClient.getAccessToken().getTokenValue()) + .isEqualTo(expected.getAccessToken().getTokenValue()); + assertThat(authorizedClient.getAccessToken().getIssuedAt()).isCloseTo(expected.getAccessToken().getIssuedAt(), + within(1, ChronoUnit.MILLIS)); + assertThat(authorizedClient.getAccessToken().getExpiresAt()).isCloseTo(expected.getAccessToken().getExpiresAt(), + within(1, ChronoUnit.MILLIS)); assertThat(authorizedClient.getAccessToken().getScopes()).isEqualTo(expected.getAccessToken().getScopes()); - assertThat(authorizedClient.getRefreshToken().getTokenValue()).isEqualTo(expected.getRefreshToken().getTokenValue()); - assertThat(authorizedClient.getRefreshToken().getIssuedAt()).isCloseTo(expected.getRefreshToken().getIssuedAt(), within(1, ChronoUnit.MILLIS)); + assertThat(authorizedClient.getRefreshToken().getTokenValue()) + .isEqualTo(expected.getRefreshToken().getTokenValue()); + assertThat(authorizedClient.getRefreshToken().getIssuedAt()).isCloseTo(expected.getRefreshToken().getIssuedAt(), + within(1, ChronoUnit.MILLIS)); } @Test @@ -171,10 +180,11 @@ public class JdbcOAuth2AuthorizedClientServiceTests { this.authorizedClientService.saveAuthorizedClient(expected, principal); - assertThatThrownBy(() -> this.authorizedClientService.loadAuthorizedClient(this.clientRegistration.getRegistrationId(), principal.getName())) - .isInstanceOf(DataRetrievalFailureException.class) - .hasMessage("The ClientRegistration with id '" + this.clientRegistration.getRegistrationId() + - "' exists in the data source, however, it was not found in the ClientRegistrationRepository."); + assertThatThrownBy(() -> this.authorizedClientService + .loadAuthorizedClient(this.clientRegistration.getRegistrationId(), principal.getName())) + .isInstanceOf(DataRetrievalFailureException.class) + .hasMessage("The ClientRegistration with id '" + this.clientRegistration.getRegistrationId() + + "' exists in the data source, however, it was not found in the ClientRegistrationRepository."); } @Test @@ -182,8 +192,7 @@ public class JdbcOAuth2AuthorizedClientServiceTests { Authentication principal = createPrincipal(); assertThatThrownBy(() -> this.authorizedClientService.saveAuthorizedClient(null, principal)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizedClient cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizedClient cannot be null"); } @Test @@ -192,8 +201,7 @@ public class JdbcOAuth2AuthorizedClientServiceTests { OAuth2AuthorizedClient authorizedClient = createAuthorizedClient(principal, this.clientRegistration); assertThatThrownBy(() -> this.authorizedClientService.saveAuthorizedClient(authorizedClient, null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("principal cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("principal cannot be null"); } @Test @@ -203,19 +211,25 @@ public class JdbcOAuth2AuthorizedClientServiceTests { this.authorizedClientService.saveAuthorizedClient(expected, principal); - OAuth2AuthorizedClient authorizedClient = this.authorizedClientService.loadAuthorizedClient( - this.clientRegistration.getRegistrationId(), principal.getName()); + OAuth2AuthorizedClient authorizedClient = this.authorizedClientService + .loadAuthorizedClient(this.clientRegistration.getRegistrationId(), principal.getName()); assertThat(authorizedClient).isNotNull(); assertThat(authorizedClient.getClientRegistration()).isEqualTo(expected.getClientRegistration()); assertThat(authorizedClient.getPrincipalName()).isEqualTo(expected.getPrincipalName()); - assertThat(authorizedClient.getAccessToken().getTokenType()).isEqualTo(expected.getAccessToken().getTokenType()); - assertThat(authorizedClient.getAccessToken().getTokenValue()).isEqualTo(expected.getAccessToken().getTokenValue()); - assertThat(authorizedClient.getAccessToken().getIssuedAt()).isCloseTo(expected.getAccessToken().getIssuedAt(), within(1, ChronoUnit.MILLIS)); - assertThat(authorizedClient.getAccessToken().getExpiresAt()).isCloseTo(expected.getAccessToken().getExpiresAt(), within(1, ChronoUnit.MILLIS)); + assertThat(authorizedClient.getAccessToken().getTokenType()) + .isEqualTo(expected.getAccessToken().getTokenType()); + assertThat(authorizedClient.getAccessToken().getTokenValue()) + .isEqualTo(expected.getAccessToken().getTokenValue()); + assertThat(authorizedClient.getAccessToken().getIssuedAt()).isCloseTo(expected.getAccessToken().getIssuedAt(), + within(1, ChronoUnit.MILLIS)); + assertThat(authorizedClient.getAccessToken().getExpiresAt()).isCloseTo(expected.getAccessToken().getExpiresAt(), + within(1, ChronoUnit.MILLIS)); assertThat(authorizedClient.getAccessToken().getScopes()).isEqualTo(expected.getAccessToken().getScopes()); - assertThat(authorizedClient.getRefreshToken().getTokenValue()).isEqualTo(expected.getRefreshToken().getTokenValue()); - assertThat(authorizedClient.getRefreshToken().getIssuedAt()).isCloseTo(expected.getRefreshToken().getIssuedAt(), within(1, ChronoUnit.MILLIS)); + assertThat(authorizedClient.getRefreshToken().getTokenValue()) + .isEqualTo(expected.getRefreshToken().getTokenValue()); + assertThat(authorizedClient.getRefreshToken().getIssuedAt()).isCloseTo(expected.getRefreshToken().getIssuedAt(), + within(1, ChronoUnit.MILLIS)); // Test save/load of NOT NULL attributes only principal = createPrincipal(); @@ -223,16 +237,20 @@ public class JdbcOAuth2AuthorizedClientServiceTests { this.authorizedClientService.saveAuthorizedClient(expected, principal); - authorizedClient = this.authorizedClientService.loadAuthorizedClient( - this.clientRegistration.getRegistrationId(), principal.getName()); + authorizedClient = this.authorizedClientService + .loadAuthorizedClient(this.clientRegistration.getRegistrationId(), principal.getName()); assertThat(authorizedClient).isNotNull(); assertThat(authorizedClient.getClientRegistration()).isEqualTo(expected.getClientRegistration()); assertThat(authorizedClient.getPrincipalName()).isEqualTo(expected.getPrincipalName()); - assertThat(authorizedClient.getAccessToken().getTokenType()).isEqualTo(expected.getAccessToken().getTokenType()); - assertThat(authorizedClient.getAccessToken().getTokenValue()).isEqualTo(expected.getAccessToken().getTokenValue()); - assertThat(authorizedClient.getAccessToken().getIssuedAt()).isCloseTo(expected.getAccessToken().getIssuedAt(), within(1, ChronoUnit.MILLIS)); - assertThat(authorizedClient.getAccessToken().getExpiresAt()).isCloseTo(expected.getAccessToken().getExpiresAt(), within(1, ChronoUnit.MILLIS)); + assertThat(authorizedClient.getAccessToken().getTokenType()) + .isEqualTo(expected.getAccessToken().getTokenType()); + assertThat(authorizedClient.getAccessToken().getTokenValue()) + .isEqualTo(expected.getAccessToken().getTokenValue()); + assertThat(authorizedClient.getAccessToken().getIssuedAt()).isCloseTo(expected.getAccessToken().getIssuedAt(), + within(1, ChronoUnit.MILLIS)); + assertThat(authorizedClient.getAccessToken().getExpiresAt()).isCloseTo(expected.getAccessToken().getExpiresAt(), + within(1, ChronoUnit.MILLIS)); assertThat(authorizedClient.getAccessToken().getScopes()).isEmpty(); assertThat(authorizedClient.getRefreshToken()).isNull(); } @@ -249,36 +267,43 @@ public class JdbcOAuth2AuthorizedClientServiceTests { this.authorizedClientService.saveAuthorizedClient(updatedClient, principal); // Then the saved client is updated - OAuth2AuthorizedClient savedClient = this.authorizedClientService.loadAuthorizedClient( - this.clientRegistration.getRegistrationId(), principal.getName()); + OAuth2AuthorizedClient savedClient = this.authorizedClientService + .loadAuthorizedClient(this.clientRegistration.getRegistrationId(), principal.getName()); assertThat(savedClient).isNotNull(); assertThat(savedClient.getClientRegistration()).isEqualTo(updatedClient.getClientRegistration()); assertThat(savedClient.getPrincipalName()).isEqualTo(updatedClient.getPrincipalName()); - assertThat(savedClient.getAccessToken().getTokenType()).isEqualTo(updatedClient.getAccessToken().getTokenType()); - assertThat(savedClient.getAccessToken().getTokenValue()).isEqualTo(updatedClient.getAccessToken().getTokenValue()); - assertThat(savedClient.getAccessToken().getIssuedAt()).isCloseTo(updatedClient.getAccessToken().getIssuedAt(), within(1, ChronoUnit.MILLIS)); - assertThat(savedClient.getAccessToken().getExpiresAt()).isCloseTo(updatedClient.getAccessToken().getExpiresAt(), within(1, ChronoUnit.MILLIS)); + assertThat(savedClient.getAccessToken().getTokenType()) + .isEqualTo(updatedClient.getAccessToken().getTokenType()); + assertThat(savedClient.getAccessToken().getTokenValue()) + .isEqualTo(updatedClient.getAccessToken().getTokenValue()); + assertThat(savedClient.getAccessToken().getIssuedAt()).isCloseTo(updatedClient.getAccessToken().getIssuedAt(), + within(1, ChronoUnit.MILLIS)); + assertThat(savedClient.getAccessToken().getExpiresAt()).isCloseTo(updatedClient.getAccessToken().getExpiresAt(), + within(1, ChronoUnit.MILLIS)); assertThat(savedClient.getAccessToken().getScopes()).isEqualTo(updatedClient.getAccessToken().getScopes()); - assertThat(savedClient.getRefreshToken().getTokenValue()).isEqualTo(updatedClient.getRefreshToken().getTokenValue()); - assertThat(savedClient.getRefreshToken().getIssuedAt()).isCloseTo(updatedClient.getRefreshToken().getIssuedAt(), within(1, ChronoUnit.MILLIS)); + assertThat(savedClient.getRefreshToken().getTokenValue()) + .isEqualTo(updatedClient.getRefreshToken().getTokenValue()); + assertThat(savedClient.getRefreshToken().getIssuedAt()).isCloseTo(updatedClient.getRefreshToken().getIssuedAt(), + within(1, ChronoUnit.MILLIS)); } @Test public void saveLoadAuthorizedClientWhenCustomStrategiesSetThenCalled() throws Exception { - JdbcOAuth2AuthorizedClientService.OAuth2AuthorizedClientRowMapper authorizedClientRowMapper = - spy(new JdbcOAuth2AuthorizedClientService.OAuth2AuthorizedClientRowMapper(this.clientRegistrationRepository)); + JdbcOAuth2AuthorizedClientService.OAuth2AuthorizedClientRowMapper authorizedClientRowMapper = spy( + new JdbcOAuth2AuthorizedClientService.OAuth2AuthorizedClientRowMapper( + this.clientRegistrationRepository)); this.authorizedClientService.setAuthorizedClientRowMapper(authorizedClientRowMapper); - JdbcOAuth2AuthorizedClientService.OAuth2AuthorizedClientParametersMapper authorizedClientParametersMapper = - spy(new JdbcOAuth2AuthorizedClientService.OAuth2AuthorizedClientParametersMapper()); + JdbcOAuth2AuthorizedClientService.OAuth2AuthorizedClientParametersMapper authorizedClientParametersMapper = spy( + new JdbcOAuth2AuthorizedClientService.OAuth2AuthorizedClientParametersMapper()); this.authorizedClientService.setAuthorizedClientParametersMapper(authorizedClientParametersMapper); Authentication principal = createPrincipal(); OAuth2AuthorizedClient authorizedClient = createAuthorizedClient(principal, this.clientRegistration); this.authorizedClientService.saveAuthorizedClient(authorizedClient, principal); - this.authorizedClientService.loadAuthorizedClient( - this.clientRegistration.getRegistrationId(), principal.getName()); + this.authorizedClientService.loadAuthorizedClient(this.clientRegistration.getRegistrationId(), + principal.getName()); verify(authorizedClientRowMapper).mapRow(any(), anyInt()); verify(authorizedClientParametersMapper).apply(any()); @@ -287,15 +312,14 @@ public class JdbcOAuth2AuthorizedClientServiceTests { @Test public void removeAuthorizedClientWhenClientRegistrationIdIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientService.removeAuthorizedClient(null, "principalName")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clientRegistrationId cannot be empty"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clientRegistrationId cannot be empty"); } @Test public void removeAuthorizedClientWhenPrincipalNameIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.authorizedClientService.removeAuthorizedClient(this.clientRegistration.getRegistrationId(), null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("principalName cannot be empty"); + assertThatThrownBy(() -> this.authorizedClientService + .removeAuthorizedClient(this.clientRegistration.getRegistrationId(), null)) + .isInstanceOf(IllegalArgumentException.class).hasMessage("principalName cannot be empty"); } @Test @@ -305,39 +329,37 @@ public class JdbcOAuth2AuthorizedClientServiceTests { this.authorizedClientService.saveAuthorizedClient(authorizedClient, principal); - authorizedClient = this.authorizedClientService.loadAuthorizedClient( - this.clientRegistration.getRegistrationId(), principal.getName()); + authorizedClient = this.authorizedClientService + .loadAuthorizedClient(this.clientRegistration.getRegistrationId(), principal.getName()); assertThat(authorizedClient).isNotNull(); - this.authorizedClientService.removeAuthorizedClient( - this.clientRegistration.getRegistrationId(), principal.getName()); + this.authorizedClientService.removeAuthorizedClient(this.clientRegistration.getRegistrationId(), + principal.getName()); - authorizedClient = this.authorizedClientService.loadAuthorizedClient( - this.clientRegistration.getRegistrationId(), principal.getName()); + authorizedClient = this.authorizedClientService + .loadAuthorizedClient(this.clientRegistration.getRegistrationId(), principal.getName()); assertThat(authorizedClient).isNull(); } @Test public void tableDefinitionWhenCustomThenAbleToOverride() { - CustomTableDefinitionJdbcOAuth2AuthorizedClientService customAuthorizedClientService = - new CustomTableDefinitionJdbcOAuth2AuthorizedClientService( - new JdbcTemplate(createDb("custom-oauth2-client-schema.sql")), - this.clientRegistrationRepository); + CustomTableDefinitionJdbcOAuth2AuthorizedClientService customAuthorizedClientService = new CustomTableDefinitionJdbcOAuth2AuthorizedClientService( + new JdbcTemplate(createDb("custom-oauth2-client-schema.sql")), this.clientRegistrationRepository); Authentication principal = createPrincipal(); OAuth2AuthorizedClient authorizedClient = createAuthorizedClient(principal, this.clientRegistration); customAuthorizedClientService.saveAuthorizedClient(authorizedClient, principal); - authorizedClient = customAuthorizedClientService.loadAuthorizedClient( - this.clientRegistration.getRegistrationId(), principal.getName()); + authorizedClient = customAuthorizedClientService + .loadAuthorizedClient(this.clientRegistration.getRegistrationId(), principal.getName()); assertThat(authorizedClient).isNotNull(); - customAuthorizedClientService.removeAuthorizedClient( - this.clientRegistration.getRegistrationId(), principal.getName()); + customAuthorizedClientService.removeAuthorizedClient(this.clientRegistration.getRegistrationId(), + principal.getName()); - authorizedClient = customAuthorizedClientService.loadAuthorizedClient( - this.clientRegistration.getRegistrationId(), principal.getName()); + authorizedClient = customAuthorizedClientService + .loadAuthorizedClient(this.clientRegistration.getRegistrationId(), principal.getName()); assertThat(authorizedClient).isNull(); } @@ -346,19 +368,16 @@ public class JdbcOAuth2AuthorizedClientServiceTests { } private static EmbeddedDatabase createDb(String schema) { - return new EmbeddedDatabaseBuilder() - .generateUniqueName(true) - .setType(EmbeddedDatabaseType.HSQL) - .setScriptEncoding("UTF-8") - .addScript(schema) - .build(); + return new EmbeddedDatabaseBuilder().generateUniqueName(true).setType(EmbeddedDatabaseType.HSQL) + .setScriptEncoding("UTF-8").addScript(schema).build(); } private static Authentication createPrincipal() { return new TestingAuthenticationToken("principal-" + principalId++, "password"); } - private static OAuth2AuthorizedClient createAuthorizedClient(Authentication principal, ClientRegistration clientRegistration) { + private static OAuth2AuthorizedClient createAuthorizedClient(Authentication principal, + ClientRegistration clientRegistration) { return createAuthorizedClient(principal, clientRegistration, false); } @@ -367,60 +386,59 @@ public class JdbcOAuth2AuthorizedClientServiceTests { OAuth2AccessToken accessToken; if (!requiredAttributesOnly) { accessToken = TestOAuth2AccessTokens.scopes("read", "write"); - } else { + } + else { accessToken = TestOAuth2AccessTokens.noScopes(); } OAuth2RefreshToken refreshToken = null; if (!requiredAttributesOnly) { refreshToken = TestOAuth2RefreshTokens.refreshToken(); } - return new OAuth2AuthorizedClient( - clientRegistration, principal.getName(), accessToken, refreshToken); + return new OAuth2AuthorizedClient(clientRegistration, principal.getName(), accessToken, refreshToken); } - private static class CustomTableDefinitionJdbcOAuth2AuthorizedClientService extends JdbcOAuth2AuthorizedClientService { - private static final String COLUMN_NAMES = - "clientRegistrationId, " + - "principalName, " + - "accessTokenType, " + - "accessTokenValue, " + - "accessTokenIssuedAt, " + - "accessTokenExpiresAt, " + - "accessTokenScopes, " + - "refreshTokenValue, " + - "refreshTokenIssuedAt"; - private static final String TABLE_NAME = "oauth2AuthorizedClient"; - private static final String PK_FILTER = "clientRegistrationId = ? AND principalName = ?"; - private static final String LOAD_AUTHORIZED_CLIENT_SQL = "SELECT " + COLUMN_NAMES + - " FROM " + TABLE_NAME + " WHERE " + PK_FILTER; - private static final String SAVE_AUTHORIZED_CLIENT_SQL = "INSERT INTO " + TABLE_NAME + - " (" + COLUMN_NAMES + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; - private static final String REMOVE_AUTHORIZED_CLIENT_SQL = "DELETE FROM " + TABLE_NAME + - " WHERE " + PK_FILTER; + private static class CustomTableDefinitionJdbcOAuth2AuthorizedClientService + extends JdbcOAuth2AuthorizedClientService { - private CustomTableDefinitionJdbcOAuth2AuthorizedClientService( - JdbcOperations jdbcOperations, ClientRegistrationRepository clientRegistrationRepository) { + private static final String COLUMN_NAMES = "clientRegistrationId, " + "principalName, " + "accessTokenType, " + + "accessTokenValue, " + "accessTokenIssuedAt, " + "accessTokenExpiresAt, " + "accessTokenScopes, " + + "refreshTokenValue, " + "refreshTokenIssuedAt"; + + private static final String TABLE_NAME = "oauth2AuthorizedClient"; + + private static final String PK_FILTER = "clientRegistrationId = ? AND principalName = ?"; + + private static final String LOAD_AUTHORIZED_CLIENT_SQL = "SELECT " + COLUMN_NAMES + " FROM " + TABLE_NAME + + " WHERE " + PK_FILTER; + + private static final String SAVE_AUTHORIZED_CLIENT_SQL = "INSERT INTO " + TABLE_NAME + " (" + COLUMN_NAMES + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + private static final String REMOVE_AUTHORIZED_CLIENT_SQL = "DELETE FROM " + TABLE_NAME + " WHERE " + PK_FILTER; + + private CustomTableDefinitionJdbcOAuth2AuthorizedClientService(JdbcOperations jdbcOperations, + ClientRegistrationRepository clientRegistrationRepository) { super(jdbcOperations, clientRegistrationRepository); setAuthorizedClientRowMapper(new OAuth2AuthorizedClientRowMapper(clientRegistrationRepository)); } @Override @SuppressWarnings("unchecked") - public T loadAuthorizedClient(String clientRegistrationId, String principalName) { + public T loadAuthorizedClient(String clientRegistrationId, + String principalName) { SqlParameterValue[] parameters = new SqlParameterValue[] { new SqlParameterValue(Types.VARCHAR, clientRegistrationId), - new SqlParameterValue(Types.VARCHAR, principalName) - }; + new SqlParameterValue(Types.VARCHAR, principalName) }; PreparedStatementSetter pss = new ArgumentPreparedStatementSetter(parameters); - List result = this.jdbcOperations.query( - LOAD_AUTHORIZED_CLIENT_SQL, pss, this.authorizedClientRowMapper); + List result = this.jdbcOperations.query(LOAD_AUTHORIZED_CLIENT_SQL, pss, + this.authorizedClientRowMapper); return !result.isEmpty() ? (T) result.get(0) : null; } @Override public void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal) { - List parameters = this.authorizedClientParametersMapper.apply( - new OAuth2AuthorizedClientHolder(authorizedClient, principal)); + List parameters = this.authorizedClientParametersMapper + .apply(new OAuth2AuthorizedClientHolder(authorizedClient, principal)); PreparedStatementSetter pss = new ArgumentPreparedStatementSetter(parameters.toArray()); this.jdbcOperations.update(SAVE_AUTHORIZED_CLIENT_SQL, pss); } @@ -429,13 +447,13 @@ public class JdbcOAuth2AuthorizedClientServiceTests { public void removeAuthorizedClient(String clientRegistrationId, String principalName) { SqlParameterValue[] parameters = new SqlParameterValue[] { new SqlParameterValue(Types.VARCHAR, clientRegistrationId), - new SqlParameterValue(Types.VARCHAR, principalName) - }; + new SqlParameterValue(Types.VARCHAR, principalName) }; PreparedStatementSetter pss = new ArgumentPreparedStatementSetter(parameters); this.jdbcOperations.update(REMOVE_AUTHORIZED_CLIENT_SQL, pss); } private static class OAuth2AuthorizedClientRowMapper implements RowMapper { + private final ClientRegistrationRepository clientRegistrationRepository; private OAuth2AuthorizedClientRowMapper(ClientRegistrationRepository clientRegistrationRepository) { @@ -446,17 +464,16 @@ public class JdbcOAuth2AuthorizedClientServiceTests { @Override public OAuth2AuthorizedClient mapRow(ResultSet rs, int rowNum) throws SQLException { String clientRegistrationId = rs.getString("clientRegistrationId"); - ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId( - clientRegistrationId); + ClientRegistration clientRegistration = this.clientRegistrationRepository + .findByRegistrationId(clientRegistrationId); if (clientRegistration == null) { - throw new DataRetrievalFailureException("The ClientRegistration with id '" + - clientRegistrationId + "' exists in the data source, " + - "however, it was not found in the ClientRegistrationRepository."); + throw new DataRetrievalFailureException( + "The ClientRegistration with id '" + clientRegistrationId + "' exists in the data source, " + + "however, it was not found in the ClientRegistrationRepository."); } OAuth2AccessToken.TokenType tokenType = null; - if (OAuth2AccessToken.TokenType.BEARER.getValue().equalsIgnoreCase( - rs.getString("accessTokenType"))) { + if (OAuth2AccessToken.TokenType.BEARER.getValue().equalsIgnoreCase(rs.getString("accessTokenType"))) { tokenType = OAuth2AccessToken.TokenType.BEARER; } String tokenValue = new String(rs.getBytes("accessTokenValue"), StandardCharsets.UTF_8); @@ -467,8 +484,8 @@ public class JdbcOAuth2AuthorizedClientServiceTests { if (accessTokenScopes != null) { scopes = StringUtils.commaDelimitedListToSet(accessTokenScopes); } - OAuth2AccessToken accessToken = new OAuth2AccessToken( - tokenType, tokenValue, issuedAt, expiresAt, scopes); + OAuth2AccessToken accessToken = new OAuth2AccessToken(tokenType, tokenValue, issuedAt, expiresAt, + scopes); OAuth2RefreshToken refreshToken = null; byte[] refreshTokenValue = rs.getBytes("refreshTokenValue"); @@ -484,9 +501,11 @@ public class JdbcOAuth2AuthorizedClientServiceTests { String principalName = rs.getString("principalName"); - return new OAuth2AuthorizedClient( - clientRegistration, principalName, accessToken, refreshToken); + return new OAuth2AuthorizedClient(clientRegistration, principalName, accessToken, refreshToken); } + } + } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizationContextTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizationContextTests.java index 9749b6ded7..5c4a86c8d4 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizationContextTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizationContextTests.java @@ -31,52 +31,51 @@ import static org.assertj.core.api.Assertions.*; * @author Joe Grandja */ public class OAuth2AuthorizationContextTests { + private ClientRegistration clientRegistration; + private OAuth2AuthorizedClient authorizedClient; + private Authentication principal; @Before public void setup() { this.clientRegistration = TestClientRegistrations.clientRegistration().build(); - this.authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, "principal", TestOAuth2AccessTokens.scopes("read", "write")); + this.authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, "principal", + TestOAuth2AccessTokens.scopes("read", "write")); this.principal = new TestingAuthenticationToken("principal", "password"); } @Test public void withClientRegistrationWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> OAuth2AuthorizationContext.withClientRegistration(null).build()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clientRegistration cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clientRegistration cannot be null"); } @Test public void withAuthorizedClientWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> OAuth2AuthorizationContext.withAuthorizedClient(null).build()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizedClient cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizedClient cannot be null"); } @Test public void withClientRegistrationWhenPrincipalIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> OAuth2AuthorizationContext.withClientRegistration(this.clientRegistration).build()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("principal cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("principal cannot be null"); } @Test public void withAuthorizedClientWhenAllValuesProvidedThenAllValuesAreSet() { - OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .attributes(attributes -> { + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(this.authorizedClient).principal(this.principal).attributes(attributes -> { attributes.put("attribute1", "value1"); attributes.put("attribute2", "value2"); - }) - .build(); + }).build(); assertThat(authorizationContext.getClientRegistration()).isSameAs(this.clientRegistration); assertThat(authorizationContext.getAuthorizedClient()).isSameAs(this.authorizedClient); assertThat(authorizationContext.getPrincipal()).isSameAs(this.principal); - assertThat(authorizationContext.getAttributes()).contains( - entry("attribute1", "value1"), entry("attribute2", "value2")); + assertThat(authorizationContext.getAttributes()).contains(entry("attribute1", "value1"), + entry("attribute2", "value2")); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizeRequestTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizeRequestTests.java index 37c7e89eef..b52a3b99d5 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizeRequestTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizeRequestTests.java @@ -33,49 +33,49 @@ import static org.assertj.core.api.Assertions.entry; * @author Joe Grandja */ public class OAuth2AuthorizeRequestTests { + private ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); + private Authentication principal = new TestingAuthenticationToken("principal", "password"); - private OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - TestOAuth2AccessTokens.scopes("read", "write"), TestOAuth2RefreshTokens.refreshToken()); + + private OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.scopes("read", "write"), + TestOAuth2RefreshTokens.refreshToken()); @Test public void withClientRegistrationIdWhenClientRegistrationIdIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> OAuth2AuthorizeRequest.withClientRegistrationId(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clientRegistrationId cannot be empty"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clientRegistrationId cannot be empty"); } @Test public void withAuthorizedClientWhenAuthorizedClientIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> OAuth2AuthorizeRequest.withAuthorizedClient(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizedClient cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizedClient cannot be null"); } @Test public void withClientRegistrationIdWhenPrincipalIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()).build()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("principal cannot be null"); + assertThatThrownBy(() -> OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).build()) + .isInstanceOf(IllegalArgumentException.class).hasMessage("principal cannot be null"); } @Test public void withClientRegistrationIdWhenPrincipalNameIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal((String) null).build()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("principalName cannot be empty"); + assertThatThrownBy(() -> OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal((String) null).build()) + .isInstanceOf(IllegalArgumentException.class).hasMessage("principalName cannot be empty"); } @Test public void withClientRegistrationIdWhenAllValuesProvidedThenAllValuesAreSet() { - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .attributes(attrs -> { attrs.put("name1", "value1"); attrs.put("name2", "value2"); - }) - .build(); + }).build(); assertThat(authorizeRequest.getClientRegistrationId()).isEqualTo(this.clientRegistration.getRegistrationId()); assertThat(authorizeRequest.getAuthorizedClient()).isNull(); @@ -86,14 +86,13 @@ public class OAuth2AuthorizeRequestTests { @Test public void withAuthorizedClientWhenAllValuesProvidedThenAllValuesAreSet() { OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .attributes(attrs -> { + .principal(this.principal).attributes(attrs -> { attrs.put("name1", "value1"); attrs.put("name2", "value2"); - }) - .build(); + }).build(); - assertThat(authorizeRequest.getClientRegistrationId()).isEqualTo(this.authorizedClient.getClientRegistration().getRegistrationId()); + assertThat(authorizeRequest.getClientRegistrationId()) + .isEqualTo(this.authorizedClient.getClientRegistration().getRegistrationId()); assertThat(authorizeRequest.getAuthorizedClient()).isEqualTo(this.authorizedClient); assertThat(authorizeRequest.getPrincipal()).isEqualTo(this.principal); assertThat(authorizeRequest.getAttributes()).contains(entry("name1", "value1"), entry("name2", "value2")); @@ -101,12 +100,13 @@ public class OAuth2AuthorizeRequestTests { @Test public void withClientRegistrationIdWhenPrincipalNameProvidedThenPrincipalCreated() { - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal("principalName") + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal("principalName") .build(); assertThat(authorizeRequest.getClientRegistrationId()).isEqualTo(this.clientRegistration.getRegistrationId()); assertThat(authorizeRequest.getAuthorizedClient()).isNull(); assertThat(authorizeRequest.getPrincipal().getName()).isEqualTo("principalName"); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientIdTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientIdTests.java index 338f929eaf..b5f803e27e 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientIdTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientIdTests.java @@ -30,15 +30,13 @@ public class OAuth2AuthorizedClientIdTests { @Test public void constructorWhenRegistrationIdNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new OAuth2AuthorizedClientId(null, "test-principal")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clientRegistrationId cannot be empty"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clientRegistrationId cannot be empty"); } @Test public void constructorWhenPrincipalNameNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new OAuth2AuthorizedClientId("test-client", null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("principalName cannot be empty"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("principalName cannot be empty"); } @Test @@ -82,4 +80,5 @@ public class OAuth2AuthorizedClientIdTests { OAuth2AuthorizedClientId id2 = new OAuth2AuthorizedClientId("test-client", "test-principal2"); assertThat(id1.hashCode()).isNotEqualTo(id2.hashCode()); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProviderBuilderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProviderBuilderTests.java index d2ea51f1b9..473e28e0d2 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProviderBuilderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProviderBuilderTests.java @@ -46,10 +46,15 @@ import static org.mockito.Mockito.*; * @author Joe Grandja */ public class OAuth2AuthorizedClientProviderBuilderTests { + private RestOperations accessTokenClient; + private DefaultClientCredentialsTokenResponseClient clientCredentialsTokenResponseClient; + private DefaultRefreshTokenTokenResponseClient refreshTokenTokenResponseClient; + private DefaultPasswordTokenResponseClient passwordTokenResponseClient; + private Authentication principal; @SuppressWarnings("unchecked") @@ -76,36 +81,28 @@ public class OAuth2AuthorizedClientProviderBuilderTests { @Test public void buildWhenAuthorizationCodeProviderThenProviderAuthorizes() { - OAuth2AuthorizedClientProvider authorizedClientProvider = - OAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .build(); + OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() + .authorizationCode().build(); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(TestClientRegistrations.clientRegistration().build()) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(TestClientRegistrations.clientRegistration().build()).principal(this.principal) + .build(); assertThatThrownBy(() -> authorizedClientProvider.authorize(authorizationContext)) .isInstanceOf(ClientAuthorizationRequiredException.class); } @Test public void buildWhenRefreshTokenProviderThenProviderReauthorizes() { - OAuth2AuthorizedClientProvider authorizedClientProvider = - OAuth2AuthorizedClientProviderBuilder.builder() - .refreshToken(configurer -> configurer.accessTokenResponseClient(this.refreshTokenTokenResponseClient)) - .build(); + OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() + .refreshToken(configurer -> configurer.accessTokenResponseClient(this.refreshTokenTokenResponseClient)) + .build(); OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - TestClientRegistrations.clientRegistration().build(), - this.principal.getName(), - expiredAccessToken(), + TestClientRegistrations.clientRegistration().build(), this.principal.getName(), expiredAccessToken(), TestOAuth2RefreshTokens.refreshToken()); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); OAuth2AuthorizedClient reauthorizedClient = authorizedClientProvider.authorize(authorizationContext); assertThat(reauthorizedClient).isNotNull(); @@ -114,15 +111,14 @@ public class OAuth2AuthorizedClientProviderBuilderTests { @Test public void buildWhenClientCredentialsProviderThenProviderAuthorizes() { - OAuth2AuthorizedClientProvider authorizedClientProvider = - OAuth2AuthorizedClientProviderBuilder.builder() - .clientCredentials(configurer -> configurer.accessTokenResponseClient(this.clientCredentialsTokenResponseClient)) - .build(); + OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() + .clientCredentials( + configurer -> configurer.accessTokenResponseClient(this.clientCredentialsTokenResponseClient)) + .build(); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(TestClientRegistrations.clientCredentials().build()) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(TestClientRegistrations.clientCredentials().build()).principal(this.principal) + .build(); OAuth2AuthorizedClient authorizedClient = authorizedClientProvider.authorize(authorizationContext); assertThat(authorizedClient).isNotNull(); @@ -131,17 +127,13 @@ public class OAuth2AuthorizedClientProviderBuilderTests { @Test public void buildWhenPasswordProviderThenProviderAuthorizes() { - OAuth2AuthorizedClientProvider authorizedClientProvider = - OAuth2AuthorizedClientProviderBuilder.builder() - .password(configurer -> configurer.accessTokenResponseClient(this.passwordTokenResponseClient)) - .build(); + OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() + .password(configurer -> configurer.accessTokenResponseClient(this.passwordTokenResponseClient)).build(); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(TestClientRegistrations.password().build()) - .principal(this.principal) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password") - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(TestClientRegistrations.password().build()).principal(this.principal) + .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password").build(); OAuth2AuthorizedClient authorizedClient = authorizedClientProvider.authorize(authorizationContext); assertThat(authorizedClient).isNotNull(); @@ -150,79 +142,65 @@ public class OAuth2AuthorizedClientProviderBuilderTests { @Test public void buildWhenAllProvidersThenProvidersAuthorize() { - OAuth2AuthorizedClientProvider authorizedClientProvider = - OAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .refreshToken(configurer -> configurer.accessTokenResponseClient(this.refreshTokenTokenResponseClient)) - .clientCredentials(configurer -> configurer.accessTokenResponseClient(this.clientCredentialsTokenResponseClient)) - .password(configurer -> configurer.accessTokenResponseClient(this.passwordTokenResponseClient)) - .build(); + OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() + .authorizationCode() + .refreshToken(configurer -> configurer.accessTokenResponseClient(this.refreshTokenTokenResponseClient)) + .clientCredentials( + configurer -> configurer.accessTokenResponseClient(this.clientCredentialsTokenResponseClient)) + .password(configurer -> configurer.accessTokenResponseClient(this.passwordTokenResponseClient)).build(); ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); - // authorization_code - OAuth2AuthorizationContext authorizationCodeContext = - OAuth2AuthorizationContext.withClientRegistration(clientRegistration) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationCodeContext = OAuth2AuthorizationContext + .withClientRegistration(clientRegistration).principal(this.principal).build(); assertThatThrownBy(() -> authorizedClientProvider.authorize(authorizationCodeContext)) .isInstanceOf(ClientAuthorizationRequiredException.class); - // refresh_token - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - clientRegistration, - this.principal.getName(), - expiredAccessToken(), - TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(clientRegistration, + this.principal.getName(), expiredAccessToken(), TestOAuth2RefreshTokens.refreshToken()); - OAuth2AuthorizationContext refreshTokenContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext refreshTokenContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); OAuth2AuthorizedClient reauthorizedClient = authorizedClientProvider.authorize(refreshTokenContext); assertThat(reauthorizedClient).isNotNull(); - verify(this.accessTokenClient, times(1)).exchange(any(RequestEntity.class), eq(OAuth2AccessTokenResponse.class)); - + verify(this.accessTokenClient, times(1)).exchange(any(RequestEntity.class), + eq(OAuth2AccessTokenResponse.class)); // client_credentials - OAuth2AuthorizationContext clientCredentialsContext = - OAuth2AuthorizationContext.withClientRegistration(TestClientRegistrations.clientCredentials().build()) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext clientCredentialsContext = OAuth2AuthorizationContext + .withClientRegistration(TestClientRegistrations.clientCredentials().build()).principal(this.principal) + .build(); authorizedClient = authorizedClientProvider.authorize(clientCredentialsContext); assertThat(authorizedClient).isNotNull(); - verify(this.accessTokenClient, times(2)).exchange(any(RequestEntity.class), eq(OAuth2AccessTokenResponse.class)); + verify(this.accessTokenClient, times(2)).exchange(any(RequestEntity.class), + eq(OAuth2AccessTokenResponse.class)); // password - OAuth2AuthorizationContext passwordContext = - OAuth2AuthorizationContext.withClientRegistration(TestClientRegistrations.password().build()) - .principal(this.principal) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password") - .build(); + OAuth2AuthorizationContext passwordContext = OAuth2AuthorizationContext + .withClientRegistration(TestClientRegistrations.password().build()).principal(this.principal) + .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password").build(); authorizedClient = authorizedClientProvider.authorize(passwordContext); assertThat(authorizedClient).isNotNull(); - verify(this.accessTokenClient, times(3)).exchange(any(RequestEntity.class), eq(OAuth2AccessTokenResponse.class)); + verify(this.accessTokenClient, times(3)).exchange(any(RequestEntity.class), + eq(OAuth2AccessTokenResponse.class)); } @Test public void buildWhenCustomProviderThenProviderCalled() { OAuth2AuthorizedClientProvider customProvider = mock(OAuth2AuthorizedClientProvider.class); - OAuth2AuthorizedClientProvider authorizedClientProvider = - OAuth2AuthorizedClientProviderBuilder.builder() - .provider(customProvider) - .build(); + OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() + .provider(customProvider).build(); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(TestClientRegistrations.clientRegistration().build()) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(TestClientRegistrations.clientRegistration().build()).principal(this.principal) + .build(); authorizedClientProvider.authorize(authorizationContext); verify(customProvider).authorize(any(OAuth2AuthorizationContext.class)); @@ -233,4 +211,5 @@ public class OAuth2AuthorizedClientProviderBuilderTests { Instant expiresAt = issuedAt.plus(Duration.ofMinutes(60)); return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token-1234", issuedAt, expiresAt); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientTests.java index 64925ee25d..942c460ea2 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientTests.java @@ -31,8 +31,11 @@ import static org.springframework.security.oauth2.core.TestOAuth2AccessTokens.no * @author Joe Grandja */ public class OAuth2AuthorizedClientTests { + private ClientRegistration clientRegistration; + private String principalName; + private OAuth2AccessToken accessToken; @Before @@ -59,11 +62,12 @@ public class OAuth2AuthorizedClientTests { @Test public void constructorWhenAllParametersProvidedAndValidThenCreated() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principalName, this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principalName, this.accessToken); assertThat(authorizedClient.getClientRegistration()).isEqualTo(this.clientRegistration); assertThat(authorizedClient.getPrincipalName()).isEqualTo(this.principalName); assertThat(authorizedClient.getAccessToken()).isEqualTo(this.accessToken); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/PasswordOAuth2AuthorizedClientProviderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/PasswordOAuth2AuthorizedClientProviderTests.java index 8e2dcb1182..5507ddbcdd 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/PasswordOAuth2AuthorizedClientProviderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/PasswordOAuth2AuthorizedClientProviderTests.java @@ -43,9 +43,13 @@ import static org.mockito.Mockito.when; * @author Joe Grandja */ public class PasswordOAuth2AuthorizedClientProviderTests { + private PasswordOAuth2AuthorizedClientProvider authorizedClientProvider; + private OAuth2AccessTokenResponseClient accessTokenResponseClient; + private ClientRegistration clientRegistration; + private Authentication principal; @Before @@ -60,68 +64,57 @@ public class PasswordOAuth2AuthorizedClientProviderTests { @Test public void setAccessTokenResponseClientWhenClientIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setAccessTokenResponseClient(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("accessTokenResponseClient cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("accessTokenResponseClient cannot be null"); } @Test public void setClockSkewWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClockSkew(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clockSkew cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clockSkew cannot be null"); } @Test public void setClockSkewWhenNegativeSecondsThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClockSkew(Duration.ofSeconds(-1))) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clockSkew must be >= 0"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clockSkew must be >= 0"); } @Test public void setClockWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClock(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clock cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clock cannot be null"); } @Test public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.authorize(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("context cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("context cannot be null"); } @Test public void authorizeWhenNotPasswordThenUnableToAuthorize() { ClientRegistration clientRegistration = TestClientRegistrations.clientCredentials().build(); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(clientRegistration) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(clientRegistration).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext)).isNull(); } @Test public void authorizeWhenPasswordAndNotAuthorizedAndEmptyUsernameThenUnableToAuthorize() { - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistration) - .principal(this.principal) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, null) - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password") - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistration).principal(this.principal) + .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, null) + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password").build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext)).isNull(); } @Test public void authorizeWhenPasswordAndNotAuthorizedAndEmptyPasswordThenUnableToAuthorize() { - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistration) - .principal(this.principal) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, null) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistration).principal(this.principal) + .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, null).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext)).isNull(); } @@ -130,12 +123,10 @@ public class PasswordOAuth2AuthorizedClientProviderTests { OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistration) - .principal(this.principal) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password") - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistration).principal(this.principal) + .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password").build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientProvider.authorize(authorizationContext); assertThat(authorizedClient.getClientRegistration()).isSameAs(this.clientRegistration); @@ -147,20 +138,19 @@ public class PasswordOAuth2AuthorizedClientProviderTests { public void authorizeWhenPasswordAndAuthorizedWithoutRefreshTokenAndTokenExpiredThenReauthorize() { Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant expiresAt = issuedAt.plus(Duration.ofMinutes(60)); - OAuth2AccessToken accessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-expired", issuedAt, expiresAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), accessToken); // without refresh token + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + "access-token-expired", issuedAt, expiresAt); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), accessToken); // without refresh token OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password") - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient) + .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password").principal(this.principal) + .build(); authorizedClient = this.authorizedClientProvider.authorize(authorizationContext); assertThat(authorizedClient.getClientRegistration()).isSameAs(this.clientRegistration); @@ -173,18 +163,18 @@ public class PasswordOAuth2AuthorizedClientProviderTests { public void authorizeWhenPasswordAndAuthorizedWithRefreshTokenAndTokenExpiredThenNotReauthorize() { Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant expiresAt = issuedAt.plus(Duration.ofMinutes(60)); - OAuth2AccessToken accessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-expired", issuedAt, expiresAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - accessToken, TestOAuth2RefreshTokens.refreshToken()); // with refresh token + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + "access-token-expired", issuedAt, expiresAt); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), accessToken, TestOAuth2RefreshTokens.refreshToken()); // with + // refresh + // token - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password") - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient) + .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password").principal(this.principal) + .build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext)).isNull(); } @@ -194,23 +184,24 @@ public class PasswordOAuth2AuthorizedClientProviderTests { Instant now = Instant.now(); Instant issuedAt = now.minus(Duration.ofMinutes(60)); Instant expiresAt = now.minus(Duration.ofMinutes(1)); - OAuth2AccessToken expiresInOneMinAccessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-1234", issuedAt, expiresAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), expiresInOneMinAccessToken); // without refresh token + OAuth2AccessToken expiresInOneMinAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + "access-token-1234", issuedAt, expiresAt); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), expiresInOneMinAccessToken); // without refresh + // token - // Shorten the lifespan of the access token by 90 seconds, which will ultimately force it to expire on the client + // Shorten the lifespan of the access token by 90 seconds, which will ultimately + // force it to expire on the client this.authorizedClientProvider.setClockSkew(Duration.ofSeconds(90)); OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password") - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient) + .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password").principal(this.principal) + .build(); OAuth2AuthorizedClient reauthorizedClient = this.authorizedClientProvider.authorize(authorizationContext); @@ -218,4 +209,5 @@ public class PasswordOAuth2AuthorizedClientProviderTests { assertThat(reauthorizedClient.getPrincipalName()).isEqualTo(this.principal.getName()); assertThat(reauthorizedClient.getAccessToken()).isEqualTo(accessTokenResponse.getAccessToken()); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/PasswordReactiveOAuth2AuthorizedClientProviderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/PasswordReactiveOAuth2AuthorizedClientProviderTests.java index 9fefec4b1f..272c710fce 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/PasswordReactiveOAuth2AuthorizedClientProviderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/PasswordReactiveOAuth2AuthorizedClientProviderTests.java @@ -44,9 +44,13 @@ import static org.mockito.Mockito.when; * @author Joe Grandja */ public class PasswordReactiveOAuth2AuthorizedClientProviderTests { + private PasswordReactiveOAuth2AuthorizedClientProvider authorizedClientProvider; + private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient; + private ClientRegistration clientRegistration; + private Authentication principal; @Before @@ -61,68 +65,57 @@ public class PasswordReactiveOAuth2AuthorizedClientProviderTests { @Test public void setAccessTokenResponseClientWhenClientIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setAccessTokenResponseClient(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("accessTokenResponseClient cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("accessTokenResponseClient cannot be null"); } @Test public void setClockSkewWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClockSkew(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clockSkew cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clockSkew cannot be null"); } @Test public void setClockSkewWhenNegativeSecondsThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClockSkew(Duration.ofSeconds(-1))) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clockSkew must be >= 0"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clockSkew must be >= 0"); } @Test public void setClockWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClock(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clock cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clock cannot be null"); } @Test public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.authorize(null).block()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("context cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("context cannot be null"); } @Test public void authorizeWhenNotPasswordThenUnableToAuthorize() { ClientRegistration clientRegistration = TestClientRegistrations.clientCredentials().build(); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(clientRegistration) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(clientRegistration).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext).block()).isNull(); } @Test public void authorizeWhenPasswordAndNotAuthorizedAndEmptyUsernameThenUnableToAuthorize() { - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistration) - .principal(this.principal) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, null) - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password") - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistration).principal(this.principal) + .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, null) + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password").build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext).block()).isNull(); } @Test public void authorizeWhenPasswordAndNotAuthorizedAndEmptyPasswordThenUnableToAuthorize() { - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistration) - .principal(this.principal) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, null) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistration).principal(this.principal) + .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, null).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext).block()).isNull(); } @@ -131,12 +124,10 @@ public class PasswordReactiveOAuth2AuthorizedClientProviderTests { OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistration) - .principal(this.principal) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password") - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistration).principal(this.principal) + .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password").build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientProvider.authorize(authorizationContext).block(); assertThat(authorizedClient.getClientRegistration()).isSameAs(this.clientRegistration); @@ -148,20 +139,19 @@ public class PasswordReactiveOAuth2AuthorizedClientProviderTests { public void authorizeWhenPasswordAndAuthorizedWithoutRefreshTokenAndTokenExpiredThenReauthorize() { Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant expiresAt = issuedAt.plus(Duration.ofMinutes(60)); - OAuth2AccessToken accessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-expired", issuedAt, expiresAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), accessToken); // without refresh token + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + "access-token-expired", issuedAt, expiresAt); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), accessToken); // without refresh token OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password") - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient) + .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password").principal(this.principal) + .build(); authorizedClient = this.authorizedClientProvider.authorize(authorizationContext).block(); assertThat(authorizedClient.getClientRegistration()).isSameAs(this.clientRegistration); @@ -174,18 +164,18 @@ public class PasswordReactiveOAuth2AuthorizedClientProviderTests { public void authorizeWhenPasswordAndAuthorizedWithRefreshTokenAndTokenExpiredThenNotReauthorize() { Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant expiresAt = issuedAt.plus(Duration.ofMinutes(60)); - OAuth2AccessToken accessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-expired", issuedAt, expiresAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - accessToken, TestOAuth2RefreshTokens.refreshToken()); // with refresh token + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + "access-token-expired", issuedAt, expiresAt); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), accessToken, TestOAuth2RefreshTokens.refreshToken()); // with + // refresh + // token - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password") - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient) + .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password").principal(this.principal) + .build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext).block()).isNull(); } @@ -195,28 +185,31 @@ public class PasswordReactiveOAuth2AuthorizedClientProviderTests { Instant now = Instant.now(); Instant issuedAt = now.minus(Duration.ofMinutes(60)); Instant expiresAt = now.minus(Duration.ofMinutes(1)); - OAuth2AccessToken expiresInOneMinAccessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-1234", issuedAt, expiresAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), expiresInOneMinAccessToken); // without refresh token + OAuth2AccessToken expiresInOneMinAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + "access-token-1234", issuedAt, expiresAt); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), expiresInOneMinAccessToken); // without refresh + // token - // Shorten the lifespan of the access token by 90 seconds, which will ultimately force it to expire on the client + // Shorten the lifespan of the access token by 90 seconds, which will ultimately + // force it to expire on the client this.authorizedClientProvider.setClockSkew(Duration.ofSeconds(90)); OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password") - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient) + .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password").principal(this.principal) + .build(); - OAuth2AuthorizedClient reauthorizedClient = this.authorizedClientProvider.authorize(authorizationContext).block(); + OAuth2AuthorizedClient reauthorizedClient = this.authorizedClientProvider.authorize(authorizationContext) + .block(); assertThat(reauthorizedClient.getClientRegistration()).isSameAs(this.clientRegistration); assertThat(reauthorizedClient.getPrincipalName()).isEqualTo(this.principal.getName()); assertThat(reauthorizedClient.getAccessToken()).isEqualTo(accessTokenResponse.getAccessToken()); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProviderBuilderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProviderBuilderTests.java index be877f2ce0..cf4e77b63b 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProviderBuilderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProviderBuilderTests.java @@ -45,8 +45,11 @@ import static org.mockito.Mockito.*; * @author Joe Grandja */ public class ReactiveOAuth2AuthorizedClientProviderBuilderTests { + private ClientRegistration.Builder clientRegistrationBuilder; + private Authentication principal; + private MockWebServer server; @Before @@ -71,43 +74,29 @@ public class ReactiveOAuth2AuthorizedClientProviderBuilderTests { @Test public void buildWhenAuthorizationCodeProviderThenProviderAuthorizes() { - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = - ReactiveOAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .build(); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder + .builder().authorizationCode().build(); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistrationBuilder.build()) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistrationBuilder.build()).principal(this.principal).build(); assertThatThrownBy(() -> authorizedClientProvider.authorize(authorizationContext).block()) .isInstanceOf(ClientAuthorizationRequiredException.class); } @Test public void buildWhenRefreshTokenProviderThenProviderReauthorizes() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = - ReactiveOAuth2AuthorizedClientProviderBuilder.builder() - .refreshToken() - .build(); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder + .builder().refreshToken().build(); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistrationBuilder.build(), - this.principal.getName(), - expiredAccessToken(), - TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistrationBuilder.build(), + this.principal.getName(), expiredAccessToken(), TestOAuth2RefreshTokens.refreshToken()); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); OAuth2AuthorizedClient reauthorizedClient = authorizedClientProvider.authorize(authorizationContext).block(); assertThat(reauthorizedClient).isNotNull(); @@ -121,22 +110,17 @@ public class ReactiveOAuth2AuthorizedClientProviderBuilderTests { @Test public void buildWhenClientCredentialsProviderThenProviderAuthorizes() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = - ReactiveOAuth2AuthorizedClientProviderBuilder.builder() - .clientCredentials() - .build(); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder + .builder().clientCredentials().build(); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistrationBuilder.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).build()) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistrationBuilder + .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).build()) + .principal(this.principal).build(); OAuth2AuthorizedClient authorizedClient = authorizedClientProvider.authorize(authorizationContext).block(); assertThat(authorizedClient).isNotNull(); @@ -150,24 +134,18 @@ public class ReactiveOAuth2AuthorizedClientProviderBuilderTests { @Test public void buildWhenPasswordProviderThenProviderAuthorizes() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = - ReactiveOAuth2AuthorizedClientProviderBuilder.builder() - .password() - .build(); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder + .builder().password().build(); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistrationBuilder.authorizationGrantType(AuthorizationGrantType.PASSWORD).build()) - .principal(this.principal) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password") - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration( + this.clientRegistrationBuilder.authorizationGrantType(AuthorizationGrantType.PASSWORD).build()) + .principal(this.principal).attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password").build(); OAuth2AuthorizedClient authorizedClient = authorizedClientProvider.authorize(authorizationContext).block(); assertThat(authorizedClient).isNotNull(); @@ -181,43 +159,27 @@ public class ReactiveOAuth2AuthorizedClientProviderBuilderTests { @Test public void buildWhenAllProvidersThenProvidersAuthorize() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = - ReactiveOAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .refreshToken() - .clientCredentials() - .password() - .build(); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder + .builder().authorizationCode().refreshToken().clientCredentials().password().build(); // authorization_code - OAuth2AuthorizationContext authorizationCodeContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistrationBuilder.build()) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationCodeContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistrationBuilder.build()).principal(this.principal).build(); assertThatThrownBy(() -> authorizedClientProvider.authorize(authorizationCodeContext).block()) .isInstanceOf(ClientAuthorizationRequiredException.class); - // refresh_token - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistrationBuilder.build(), - this.principal.getName(), - expiredAccessToken(), - TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistrationBuilder.build(), + this.principal.getName(), expiredAccessToken(), TestOAuth2RefreshTokens.refreshToken()); - OAuth2AuthorizationContext refreshTokenContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext refreshTokenContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); OAuth2AuthorizedClient reauthorizedClient = authorizedClientProvider.authorize(refreshTokenContext).block(); assertThat(reauthorizedClient).isNotNull(); @@ -228,12 +190,11 @@ public class ReactiveOAuth2AuthorizedClientProviderBuilderTests { String formParameters = recordedRequest.getBody().readUtf8(); assertThat(formParameters).contains("grant_type=refresh_token"); - // client_credentials - OAuth2AuthorizationContext clientCredentialsContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistrationBuilder.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).build()) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext clientCredentialsContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistrationBuilder + .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).build()) + .principal(this.principal).build(); authorizedClient = authorizedClientProvider.authorize(clientCredentialsContext).block(); assertThat(authorizedClient).isNotNull(); @@ -245,12 +206,11 @@ public class ReactiveOAuth2AuthorizedClientProviderBuilderTests { assertThat(formParameters).contains("grant_type=client_credentials"); // password - OAuth2AuthorizationContext passwordContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistrationBuilder.authorizationGrantType(AuthorizationGrantType.PASSWORD).build()) - .principal(this.principal) - .attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") - .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password") - .build(); + OAuth2AuthorizationContext passwordContext = OAuth2AuthorizationContext + .withClientRegistration( + this.clientRegistrationBuilder.authorizationGrantType(AuthorizationGrantType.PASSWORD).build()) + .principal(this.principal).attribute(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "username") + .attribute(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password").build(); authorizedClient = authorizedClientProvider.authorize(passwordContext).block(); assertThat(authorizedClient).isNotNull(); @@ -267,15 +227,11 @@ public class ReactiveOAuth2AuthorizedClientProviderBuilderTests { ReactiveOAuth2AuthorizedClientProvider customProvider = mock(ReactiveOAuth2AuthorizedClientProvider.class); when(customProvider.authorize(any())).thenReturn(Mono.empty()); - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = - ReactiveOAuth2AuthorizedClientProviderBuilder.builder() - .provider(customProvider) - .build(); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder + .builder().provider(customProvider).build(); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistrationBuilder.build()) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistrationBuilder.build()).principal(this.principal).build(); authorizedClientProvider.authorize(authorizationContext).block(); verify(customProvider).authorize(any(OAuth2AuthorizationContext.class)); @@ -288,8 +244,7 @@ public class ReactiveOAuth2AuthorizedClientProviderBuilderTests { } private MockResponse jsonResponse(String json) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json); + return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/RefreshTokenOAuth2AuthorizedClientProviderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/RefreshTokenOAuth2AuthorizedClientProviderTests.java index 3b373000b3..1676183e8c 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/RefreshTokenOAuth2AuthorizedClientProviderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/RefreshTokenOAuth2AuthorizedClientProviderTests.java @@ -45,10 +45,15 @@ import static org.mockito.Mockito.*; * @author Joe Grandja */ public class RefreshTokenOAuth2AuthorizedClientProviderTests { + private RefreshTokenOAuth2AuthorizedClientProvider authorizedClientProvider; + private OAuth2AccessTokenResponseClient accessTokenResponseClient; + private ClientRegistration clientRegistration; + private Authentication principal; + private OAuth2AuthorizedClient authorizedClient; @Before @@ -60,8 +65,8 @@ public class RefreshTokenOAuth2AuthorizedClientProviderTests { this.principal = new TestingAuthenticationToken("principal", "password"); Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant expiresAt = issuedAt.plus(Duration.ofMinutes(60)); - OAuth2AccessToken expiredAccessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-1234", issuedAt, expiresAt); + OAuth2AccessToken expiredAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + "access-token-1234", issuedAt, expiresAt); this.authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, this.principal.getName(), expiredAccessToken, TestOAuth2RefreshTokens.refreshToken()); } @@ -69,56 +74,47 @@ public class RefreshTokenOAuth2AuthorizedClientProviderTests { @Test public void setAccessTokenResponseClientWhenClientIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setAccessTokenResponseClient(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("accessTokenResponseClient cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("accessTokenResponseClient cannot be null"); } @Test public void setClockSkewWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClockSkew(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clockSkew cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clockSkew cannot be null"); } @Test public void setClockSkewWhenNegativeSecondsThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClockSkew(Duration.ofSeconds(-1))) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clockSkew must be >= 0"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clockSkew must be >= 0"); } @Test public void setClockWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClock(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clock cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clock cannot be null"); } @Test public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.authorize(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("context cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("context cannot be null"); } @Test public void authorizeWhenNotAuthorizedThenUnableToReauthorize() { - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistration) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistration).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext)).isNull(); } @Test public void authorizeWhenAuthorizedAndRefreshTokenIsNullThenUnableToReauthorize() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), this.authorizedClient.getAccessToken()); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), this.authorizedClient.getAccessToken()); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext)).isNull(); } @@ -127,10 +123,8 @@ public class RefreshTokenOAuth2AuthorizedClientProviderTests { OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, this.principal.getName(), TestOAuth2AccessTokens.noScopes(), this.authorizedClient.getRefreshToken()); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext)).isNull(); } @@ -138,25 +132,23 @@ public class RefreshTokenOAuth2AuthorizedClientProviderTests { @Test public void authorizeWhenAuthorizedAndAccessTokenNotExpiredButClockSkewForcesExpiryThenReauthorize() { OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse() - .refreshToken("new-refresh-token") - .build(); + .refreshToken("new-refresh-token").build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); Instant now = Instant.now(); Instant issuedAt = now.minus(Duration.ofMinutes(60)); Instant expiresAt = now.minus(Duration.ofMinutes(1)); - OAuth2AccessToken expiresInOneMinAccessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-1234", issuedAt, expiresAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, this.principal.getName(), - expiresInOneMinAccessToken, this.authorizedClient.getRefreshToken()); + OAuth2AccessToken expiresInOneMinAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + "access-token-1234", issuedAt, expiresAt); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), expiresInOneMinAccessToken, this.authorizedClient.getRefreshToken()); - // Shorten the lifespan of the access token by 90 seconds, which will ultimately force it to expire on the client + // Shorten the lifespan of the access token by 90 seconds, which will ultimately + // force it to expire on the client this.authorizedClientProvider.setClockSkew(Duration.ofSeconds(90)); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); OAuth2AuthorizedClient reauthorizedClient = this.authorizedClientProvider.authorize(authorizationContext); @@ -169,14 +161,11 @@ public class RefreshTokenOAuth2AuthorizedClientProviderTests { @Test public void authorizeWhenAuthorizedAndAccessTokenExpiredThenReauthorize() { OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse() - .refreshToken("new-refresh-token") - .build(); + .refreshToken("new-refresh-token").build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(this.authorizedClient).principal(this.principal).build(); OAuth2AuthorizedClient reauthorizedClient = this.authorizedClientProvider.authorize(authorizationContext); @@ -189,37 +178,34 @@ public class RefreshTokenOAuth2AuthorizedClientProviderTests { @Test public void authorizeWhenAuthorizedAndRequestScopeProvidedThenScopeRequested() { OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse() - .refreshToken("new-refresh-token") - .build(); + .refreshToken("new-refresh-token").build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); String[] requestScope = new String[] { "read", "write" }; - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .attribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME, requestScope) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(this.authorizedClient).principal(this.principal) + .attribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME, requestScope).build(); this.authorizedClientProvider.authorize(authorizationContext); - ArgumentCaptor refreshTokenGrantRequestArgCaptor = - ArgumentCaptor.forClass(OAuth2RefreshTokenGrantRequest.class); + ArgumentCaptor refreshTokenGrantRequestArgCaptor = ArgumentCaptor + .forClass(OAuth2RefreshTokenGrantRequest.class); verify(this.accessTokenResponseClient).getTokenResponse(refreshTokenGrantRequestArgCaptor.capture()); - assertThat(refreshTokenGrantRequestArgCaptor.getValue().getScopes()).isEqualTo(new HashSet<>(Arrays.asList(requestScope))); + assertThat(refreshTokenGrantRequestArgCaptor.getValue().getScopes()) + .isEqualTo(new HashSet<>(Arrays.asList(requestScope))); } @Test public void authorizeWhenAuthorizedAndInvalidRequestScopeProvidedThenThrowIllegalArgumentException() { String invalidRequestScope = "read write"; - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .attribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME, invalidRequestScope) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(this.authorizedClient).principal(this.principal) + .attribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME, invalidRequestScope).build(); assertThatThrownBy(() -> this.authorizedClientProvider.authorize(authorizationContext)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageStartingWith("The context attribute must be of type String[] '" + - OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME + "'"); + .hasMessageStartingWith("The context attribute must be of type String[] '" + + OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME + "'"); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/RefreshTokenReactiveOAuth2AuthorizedClientProviderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/RefreshTokenReactiveOAuth2AuthorizedClientProviderTests.java index 6ba450f15c..82d915ee40 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/RefreshTokenReactiveOAuth2AuthorizedClientProviderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/RefreshTokenReactiveOAuth2AuthorizedClientProviderTests.java @@ -46,10 +46,15 @@ import static org.mockito.Mockito.*; * @author Joe Grandja */ public class RefreshTokenReactiveOAuth2AuthorizedClientProviderTests { + private RefreshTokenReactiveOAuth2AuthorizedClientProvider authorizedClientProvider; + private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient; + private ClientRegistration clientRegistration; + private Authentication principal; + private OAuth2AuthorizedClient authorizedClient; @Before @@ -61,8 +66,8 @@ public class RefreshTokenReactiveOAuth2AuthorizedClientProviderTests { this.principal = new TestingAuthenticationToken("principal", "password"); Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant expiresAt = issuedAt.plus(Duration.ofMinutes(60)); - OAuth2AccessToken expiredAccessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-1234", issuedAt, expiresAt); + OAuth2AccessToken expiredAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + "access-token-1234", issuedAt, expiresAt); this.authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, this.principal.getName(), expiredAccessToken, TestOAuth2RefreshTokens.refreshToken()); } @@ -70,56 +75,47 @@ public class RefreshTokenReactiveOAuth2AuthorizedClientProviderTests { @Test public void setAccessTokenResponseClientWhenClientIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setAccessTokenResponseClient(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("accessTokenResponseClient cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("accessTokenResponseClient cannot be null"); } @Test public void setClockSkewWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClockSkew(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clockSkew cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clockSkew cannot be null"); } @Test public void setClockSkewWhenNegativeSecondsThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClockSkew(Duration.ofSeconds(-1))) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clockSkew must be >= 0"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clockSkew must be >= 0"); } @Test public void setClockWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.setClock(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clock cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clock cannot be null"); } @Test public void authorizeWhenContextIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientProvider.authorize(null).block()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("context cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("context cannot be null"); } @Test public void authorizeWhenNotAuthorizedThenUnableToReauthorize() { - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withClientRegistration(this.clientRegistration) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withClientRegistration(this.clientRegistration).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext).block()).isNull(); } @Test public void authorizeWhenAuthorizedAndRefreshTokenIsNullThenUnableToReauthorize() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), this.authorizedClient.getAccessToken()); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), this.authorizedClient.getAccessToken()); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext).block()).isNull(); } @@ -128,10 +124,8 @@ public class RefreshTokenReactiveOAuth2AuthorizedClientProviderTests { OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, this.principal.getName(), TestOAuth2AccessTokens.noScopes(), this.authorizedClient.getRefreshToken()); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); assertThat(this.authorizedClientProvider.authorize(authorizationContext).block()).isNull(); } @@ -139,27 +133,26 @@ public class RefreshTokenReactiveOAuth2AuthorizedClientProviderTests { @Test public void authorizeWhenAuthorizedAndAccessTokenNotExpiredButClockSkewForcesExpiryThenReauthorize() { OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse() - .refreshToken("new-refresh-token") - .build(); + .refreshToken("new-refresh-token").build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); Instant now = Instant.now(); Instant issuedAt = now.minus(Duration.ofMinutes(60)); Instant expiresAt = now.minus(Duration.ofMinutes(1)); - OAuth2AccessToken expiresInOneMinAccessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-1234", issuedAt, expiresAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, this.principal.getName(), - expiresInOneMinAccessToken, this.authorizedClient.getRefreshToken()); + OAuth2AccessToken expiresInOneMinAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, + "access-token-1234", issuedAt, expiresAt); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), expiresInOneMinAccessToken, this.authorizedClient.getRefreshToken()); - // Shorten the lifespan of the access token by 90 seconds, which will ultimately force it to expire on the client + // Shorten the lifespan of the access token by 90 seconds, which will ultimately + // force it to expire on the client this.authorizedClientProvider.setClockSkew(Duration.ofSeconds(90)); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(authorizedClient).principal(this.principal).build(); - OAuth2AuthorizedClient reauthorizedClient = this.authorizedClientProvider.authorize(authorizationContext).block(); + OAuth2AuthorizedClient reauthorizedClient = this.authorizedClientProvider.authorize(authorizationContext) + .block(); assertThat(reauthorizedClient.getClientRegistration()).isSameAs(this.clientRegistration); assertThat(reauthorizedClient.getPrincipalName()).isEqualTo(this.principal.getName()); @@ -170,16 +163,14 @@ public class RefreshTokenReactiveOAuth2AuthorizedClientProviderTests { @Test public void authorizeWhenAuthorizedAndAccessTokenExpiredThenReauthorize() { OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse() - .refreshToken("new-refresh-token") - .build(); + .refreshToken("new-refresh-token").build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(this.authorizedClient).principal(this.principal).build(); - OAuth2AuthorizedClient reauthorizedClient = this.authorizedClientProvider.authorize(authorizationContext).block(); + OAuth2AuthorizedClient reauthorizedClient = this.authorizedClientProvider.authorize(authorizationContext) + .block(); assertThat(reauthorizedClient.getClientRegistration()).isSameAs(this.clientRegistration); assertThat(reauthorizedClient.getPrincipalName()).isEqualTo(this.principal.getName()); @@ -190,37 +181,34 @@ public class RefreshTokenReactiveOAuth2AuthorizedClientProviderTests { @Test public void authorizeWhenAuthorizedAndRequestScopeProvidedThenScopeRequested() { OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse() - .refreshToken("new-refresh-token") - .build(); + .refreshToken("new-refresh-token").build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); String[] requestScope = new String[] { "read", "write" }; - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .attribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME, requestScope) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(this.authorizedClient).principal(this.principal) + .attribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME, requestScope).build(); this.authorizedClientProvider.authorize(authorizationContext).block(); - ArgumentCaptor refreshTokenGrantRequestArgCaptor = - ArgumentCaptor.forClass(OAuth2RefreshTokenGrantRequest.class); + ArgumentCaptor refreshTokenGrantRequestArgCaptor = ArgumentCaptor + .forClass(OAuth2RefreshTokenGrantRequest.class); verify(this.accessTokenResponseClient).getTokenResponse(refreshTokenGrantRequestArgCaptor.capture()); - assertThat(refreshTokenGrantRequestArgCaptor.getValue().getScopes()).isEqualTo(new HashSet<>(Arrays.asList(requestScope))); + assertThat(refreshTokenGrantRequestArgCaptor.getValue().getScopes()) + .isEqualTo(new HashSet<>(Arrays.asList(requestScope))); } @Test public void authorizeWhenAuthorizedAndInvalidRequestScopeProvidedThenThrowIllegalArgumentException() { String invalidRequestScope = "read write"; - OAuth2AuthorizationContext authorizationContext = - OAuth2AuthorizationContext.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .attribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME, invalidRequestScope) - .build(); + OAuth2AuthorizationContext authorizationContext = OAuth2AuthorizationContext + .withAuthorizedClient(this.authorizedClient).principal(this.principal) + .attribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME, invalidRequestScope).build(); assertThatThrownBy(() -> this.authorizedClientProvider.authorize(authorizationContext).block()) .isInstanceOf(IllegalArgumentException.class) - .hasMessageStartingWith("The context attribute must be of type String[] '" + - OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME + "'"); + .hasMessageStartingWith("The context attribute must be of type String[] '" + + OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME + "'"); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthenticationTokenTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthenticationTokenTests.java index 8e0823fe76..13cfd2be38 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthenticationTokenTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthenticationTokenTests.java @@ -32,8 +32,11 @@ import static org.mockito.Mockito.mock; * @author Joe Grandja */ public class OAuth2AuthenticationTokenTests { + private OAuth2User principal; + private Collection authorities; + private String authorizedClientRegistrationId; @Before @@ -65,8 +68,8 @@ public class OAuth2AuthenticationTokenTests { @Test public void constructorWhenAllParametersProvidedAndValidThenCreated() { - OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken( - this.principal, this.authorities, this.authorizedClientRegistrationId); + OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken(this.principal, this.authorities, + this.authorizedClientRegistrationId); assertThat(authentication.getPrincipal()).isEqualTo(this.principal); assertThat(authentication.getCredentials()).isEqualTo(""); @@ -74,4 +77,5 @@ public class OAuth2AuthenticationTokenTests { assertThat(authentication.getAuthorizedClientRegistrationId()).isEqualTo(this.authorizedClientRegistrationId); assertThat(authentication.isAuthenticated()).isEqualTo(true); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java index 41ebe4a1e6..46e79722d2 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java @@ -49,9 +49,13 @@ import static org.springframework.security.oauth2.core.endpoint.TestOAuth2Author * @author Joe Grandja */ public class OAuth2AuthorizationCodeAuthenticationProviderTests { + private ClientRegistration clientRegistration; + private OAuth2AuthorizationRequest authorizationRequest; + private OAuth2AccessTokenResponseClient accessTokenResponseClient; + private OAuth2AuthorizationCodeAuthenticationProvider authenticationProvider; @Before @@ -77,26 +81,24 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests { @Test public void authenticateWhenAuthorizationErrorResponseThenThrowOAuth2AuthorizationException() { OAuth2AuthorizationResponse authorizationResponse = error().errorCode(OAuth2ErrorCodes.INVALID_REQUEST).build(); - OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange( - this.authorizationRequest, authorizationResponse); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(this.authorizationRequest, + authorizationResponse); assertThatThrownBy(() -> { this.authenticationProvider.authenticate( - new OAuth2AuthorizationCodeAuthenticationToken( - this.clientRegistration, authorizationExchange)); + new OAuth2AuthorizationCodeAuthenticationToken(this.clientRegistration, authorizationExchange)); }).isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining(OAuth2ErrorCodes.INVALID_REQUEST); } @Test public void authenticateWhenAuthorizationResponseStateNotEqualAuthorizationRequestStateThenThrowOAuth2AuthorizationException() { OAuth2AuthorizationResponse authorizationResponse = success().state("67890").build(); - OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange( - this.authorizationRequest, authorizationResponse); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(this.authorizationRequest, + authorizationResponse); assertThatThrownBy(() -> { this.authenticationProvider.authenticate( - new OAuth2AuthorizationCodeAuthenticationToken( - this.clientRegistration, authorizationExchange)); + new OAuth2AuthorizationCodeAuthenticationToken(this.clientRegistration, authorizationExchange)); }).isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining("invalid_state_parameter"); } @@ -105,11 +107,11 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests { OAuth2AccessTokenResponse accessTokenResponse = accessTokenResponse().refreshToken("refresh").build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); - OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange( - this.authorizationRequest, success().build()); - OAuth2AuthorizationCodeAuthenticationToken authenticationResult = - (OAuth2AuthorizationCodeAuthenticationToken) this.authenticationProvider.authenticate( - new OAuth2AuthorizationCodeAuthenticationToken(this.clientRegistration, authorizationExchange)); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(this.authorizationRequest, + success().build()); + OAuth2AuthorizationCodeAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeAuthenticationToken) this.authenticationProvider + .authenticate( + new OAuth2AuthorizationCodeAuthenticationToken(this.clientRegistration, authorizationExchange)); assertThat(authenticationResult.isAuthenticated()).isTrue(); assertThat(authenticationResult.getPrincipal()).isEqualTo(this.clientRegistration.getClientId()); @@ -143,4 +145,5 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests { assertThat(authentication.getAdditionalParameters()) .containsAllEntriesOf(accessTokenResponse.getAdditionalParameters()); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationTokenTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationTokenTests.java index e153e63e56..33d2e8a7e8 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationTokenTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeAuthenticationTokenTests.java @@ -37,15 +37,17 @@ import static org.springframework.security.oauth2.core.endpoint.TestOAuth2Author * @author Joe Grandja */ public class OAuth2AuthorizationCodeAuthenticationTokenTests { + private ClientRegistration clientRegistration; + private OAuth2AuthorizationExchange authorizationExchange; + private OAuth2AccessToken accessToken; @Before public void setUp() { this.clientRegistration = clientRegistration().build(); - this.authorizationExchange = new OAuth2AuthorizationExchange(request().build(), - success().code("code").build()); + this.authorizationExchange = new OAuth2AuthorizationExchange(request().build(), success().code("code").build()); this.accessToken = noScopes(); } @@ -63,11 +65,12 @@ public class OAuth2AuthorizationCodeAuthenticationTokenTests { @Test public void constructorAuthorizationRequestResponseWhenAllParametersProvidedAndValidThenCreated() { - OAuth2AuthorizationCodeAuthenticationToken authentication = - new OAuth2AuthorizationCodeAuthenticationToken(this.clientRegistration, this.authorizationExchange); + OAuth2AuthorizationCodeAuthenticationToken authentication = new OAuth2AuthorizationCodeAuthenticationToken( + this.clientRegistration, this.authorizationExchange); assertThat(authentication.getPrincipal()).isEqualTo(this.clientRegistration.getClientId()); - assertThat(authentication.getCredentials()).isEqualTo(this.authorizationExchange.getAuthorizationResponse().getCode()); + assertThat(authentication.getCredentials()) + .isEqualTo(this.authorizationExchange.getAuthorizationResponse().getCode()); assertThat(authentication.getAuthorities()).isEqualTo(Collections.emptyList()); assertThat(authentication.getClientRegistration()).isEqualTo(this.clientRegistration); assertThat(authentication.getAuthorizationExchange()).isEqualTo(this.authorizationExchange); @@ -77,26 +80,27 @@ public class OAuth2AuthorizationCodeAuthenticationTokenTests { @Test public void constructorTokenRequestResponseWhenClientRegistrationIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new OAuth2AuthorizationCodeAuthenticationToken(null, this.authorizationExchange, this.accessToken)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> new OAuth2AuthorizationCodeAuthenticationToken(null, this.authorizationExchange, + this.accessToken)).isInstanceOf(IllegalArgumentException.class); } @Test public void constructorTokenRequestResponseWhenAuthorizationExchangeIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new OAuth2AuthorizationCodeAuthenticationToken(this.clientRegistration, null, this.accessToken)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> new OAuth2AuthorizationCodeAuthenticationToken(this.clientRegistration, null, this.accessToken)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void constructorTokenRequestResponseWhenAccessTokenIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new OAuth2AuthorizationCodeAuthenticationToken(this.clientRegistration, this.authorizationExchange, null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> new OAuth2AuthorizationCodeAuthenticationToken(this.clientRegistration, + this.authorizationExchange, null)).isInstanceOf(IllegalArgumentException.class); } @Test public void constructorTokenRequestResponseWhenAllParametersProvidedAndValidThenCreated() { OAuth2AuthorizationCodeAuthenticationToken authentication = new OAuth2AuthorizationCodeAuthenticationToken( - this.clientRegistration, this.authorizationExchange, this.accessToken); + this.clientRegistration, this.authorizationExchange, this.accessToken); assertThat(authentication.getPrincipal()).isEqualTo(this.clientRegistration.getClientId()); assertThat(authentication.getCredentials()).isEqualTo(this.accessToken.getTokenValue()); @@ -106,4 +110,5 @@ public class OAuth2AuthorizationCodeAuthenticationTokenTests { assertThat(authentication.getAccessToken()).isEqualTo(this.accessToken); assertThat(authentication.isAuthenticated()).isEqualTo(true); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeReactiveAuthenticationManagerTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeReactiveAuthenticationManagerTests.java index f375342212..101adcf47b 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeReactiveAuthenticationManagerTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2AuthorizationCodeReactiveAuthenticationManagerTests.java @@ -48,6 +48,7 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class OAuth2AuthorizationCodeReactiveAuthenticationManagerTests { + @Mock private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient; @@ -59,8 +60,7 @@ public class OAuth2AuthorizationCodeReactiveAuthenticationManagerTests { private OAuth2AuthorizationResponse.Builder authorizationResponse = TestOAuth2AuthorizationResponses.success(); - private OAuth2AccessTokenResponse.Builder tokenResponse = TestOAuth2AccessTokenResponses - .accessTokenResponse(); + private OAuth2AccessTokenResponse.Builder tokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse(); @Before public void setup() { @@ -70,15 +70,13 @@ public class OAuth2AuthorizationCodeReactiveAuthenticationManagerTests { @Test public void authenticateWhenErrorThenOAuth2AuthorizationException() { this.authorizationResponse = TestOAuth2AuthorizationResponses.error(); - assertThatCode(() -> authenticate()) - .isInstanceOf(OAuth2AuthorizationException.class); + assertThatCode(() -> authenticate()).isInstanceOf(OAuth2AuthorizationException.class); } @Test public void authenticateWhenStateNotEqualThenOAuth2AuthorizationException() { this.authorizationRequest.state("notequal"); - assertThatCode(() -> authenticate()) - .isInstanceOf(OAuth2AuthorizationException.class); + assertThatCode(() -> authenticate()).isInstanceOf(OAuth2AuthorizationException.class); } @Test @@ -101,17 +99,18 @@ public class OAuth2AuthorizationCodeReactiveAuthenticationManagerTests { @Test public void authenticateWhenOAuth2AuthorizationExceptionThenOAuth2AuthorizationException() { - when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.error(() -> new OAuth2AuthorizationException(new OAuth2Error("error")))); + when(this.accessTokenResponseClient.getTokenResponse(any())) + .thenReturn(Mono.error(() -> new OAuth2AuthorizationException(new OAuth2Error("error")))); - assertThatCode(() -> authenticate()) - .isInstanceOf(OAuth2AuthorizationException.class); + assertThatCode(() -> authenticate()).isInstanceOf(OAuth2AuthorizationException.class); } private OAuth2AuthorizationCodeAuthenticationToken authenticate() { - OAuth2AuthorizationExchange exchange = new OAuth2AuthorizationExchange( - this.authorizationRequest.build(), this.authorizationResponse.build()); + OAuth2AuthorizationExchange exchange = new OAuth2AuthorizationExchange(this.authorizationRequest.build(), + this.authorizationResponse.build()); OAuth2AuthorizationCodeAuthenticationToken token = new OAuth2AuthorizationCodeAuthenticationToken( this.registration.build(), exchange); return (OAuth2AuthorizationCodeAuthenticationToken) this.manager.authenticate(token).block(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationProviderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationProviderTests.java index 8a2aaa10d1..c60f2ce919 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationProviderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationProviderTests.java @@ -64,12 +64,19 @@ import static org.springframework.security.oauth2.core.endpoint.TestOAuth2Author * @author Joe Grandja */ public class OAuth2LoginAuthenticationProviderTests { + private ClientRegistration clientRegistration; + private OAuth2AuthorizationRequest authorizationRequest; + private OAuth2AuthorizationResponse authorizationResponse; + private OAuth2AuthorizationExchange authorizationExchange; + private OAuth2AccessTokenResponseClient accessTokenResponseClient; + private OAuth2UserService userService; + private OAuth2LoginAuthenticationProvider authenticationProvider; @Rule @@ -81,10 +88,12 @@ public class OAuth2LoginAuthenticationProviderTests { this.clientRegistration = clientRegistration().build(); this.authorizationRequest = request().scope("scope1", "scope2").build(); this.authorizationResponse = success().build(); - this.authorizationExchange = new OAuth2AuthorizationExchange(this.authorizationRequest, this.authorizationResponse); + this.authorizationExchange = new OAuth2AuthorizationExchange(this.authorizationRequest, + this.authorizationResponse); this.accessTokenResponseClient = mock(OAuth2AccessTokenResponseClient.class); this.userService = mock(OAuth2UserService.class); - this.authenticationProvider = new OAuth2LoginAuthenticationProvider(this.accessTokenResponseClient, this.userService); + this.authenticationProvider = new OAuth2LoginAuthenticationProvider(this.accessTokenResponseClient, + this.userService); } @Test @@ -113,12 +122,11 @@ public class OAuth2LoginAuthenticationProviderTests { @Test public void authenticateWhenAuthorizationRequestContainsOpenidScopeThenReturnNull() { OAuth2AuthorizationRequest authorizationRequest = request().scope("openid").build(); - OAuth2AuthorizationExchange authorizationExchange = - new OAuth2AuthorizationExchange(authorizationRequest, this.authorizationResponse); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, + this.authorizationResponse); - OAuth2LoginAuthenticationToken authentication = - (OAuth2LoginAuthenticationToken) this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(this.clientRegistration, authorizationExchange)); + OAuth2LoginAuthenticationToken authentication = (OAuth2LoginAuthenticationToken) this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, authorizationExchange)); assertThat(authentication).isNull(); } @@ -128,13 +136,12 @@ public class OAuth2LoginAuthenticationProviderTests { this.exception.expect(OAuth2AuthenticationException.class); this.exception.expectMessage(containsString(OAuth2ErrorCodes.INVALID_REQUEST)); - OAuth2AuthorizationResponse authorizationResponse = - error().errorCode(OAuth2ErrorCodes.INVALID_REQUEST).build(); - OAuth2AuthorizationExchange authorizationExchange = - new OAuth2AuthorizationExchange(this.authorizationRequest, authorizationResponse); + OAuth2AuthorizationResponse authorizationResponse = error().errorCode(OAuth2ErrorCodes.INVALID_REQUEST).build(); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(this.authorizationRequest, + authorizationResponse); - this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(this.clientRegistration, authorizationExchange)); + this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, authorizationExchange)); } @Test @@ -142,13 +149,12 @@ public class OAuth2LoginAuthenticationProviderTests { this.exception.expect(OAuth2AuthenticationException.class); this.exception.expectMessage(containsString("invalid_state_parameter")); - OAuth2AuthorizationResponse authorizationResponse = - success().state("67890").build(); - OAuth2AuthorizationExchange authorizationExchange = - new OAuth2AuthorizationExchange(this.authorizationRequest, authorizationResponse); + OAuth2AuthorizationResponse authorizationResponse = success().state("67890").build(); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(this.authorizationRequest, + authorizationResponse); - this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(this.clientRegistration, authorizationExchange)); + this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, authorizationExchange)); } @Test @@ -158,13 +164,11 @@ public class OAuth2LoginAuthenticationProviderTests { OAuth2User principal = mock(OAuth2User.class); List authorities = AuthorityUtils.createAuthorityList("ROLE_USER"); - when(principal.getAuthorities()).thenAnswer( - (Answer>) invocation -> authorities); + when(principal.getAuthorities()).thenAnswer((Answer>) invocation -> authorities); when(this.userService.loadUser(any())).thenReturn(principal); - OAuth2LoginAuthenticationToken authentication = - (OAuth2LoginAuthenticationToken) this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); + OAuth2LoginAuthenticationToken authentication = (OAuth2LoginAuthenticationToken) this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); assertThat(authentication.isAuthenticated()).isTrue(); assertThat(authentication.getPrincipal()).isEqualTo(principal); @@ -183,19 +187,17 @@ public class OAuth2LoginAuthenticationProviderTests { OAuth2User principal = mock(OAuth2User.class); List authorities = AuthorityUtils.createAuthorityList("ROLE_USER"); - when(principal.getAuthorities()).thenAnswer( - (Answer>) invocation -> authorities); + when(principal.getAuthorities()).thenAnswer((Answer>) invocation -> authorities); when(this.userService.loadUser(any())).thenReturn(principal); List mappedAuthorities = AuthorityUtils.createAuthorityList("ROLE_OAUTH2_USER"); GrantedAuthoritiesMapper authoritiesMapper = mock(GrantedAuthoritiesMapper.class); - when(authoritiesMapper.mapAuthorities(anyCollection())).thenAnswer( - (Answer>) invocation -> mappedAuthorities); + when(authoritiesMapper.mapAuthorities(anyCollection())) + .thenAnswer((Answer>) invocation -> mappedAuthorities); this.authenticationProvider.setAuthoritiesMapper(authoritiesMapper); - OAuth2LoginAuthenticationToken authentication = - (OAuth2LoginAuthenticationToken) this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); + OAuth2LoginAuthenticationToken authentication = (OAuth2LoginAuthenticationToken) this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); assertThat(authentication.getAuthorities()).isEqualTo(mappedAuthorities); } @@ -208,16 +210,15 @@ public class OAuth2LoginAuthenticationProviderTests { OAuth2User principal = mock(OAuth2User.class); List authorities = AuthorityUtils.createAuthorityList("ROLE_USER"); - when(principal.getAuthorities()).thenAnswer( - (Answer>) invocation -> authorities); + when(principal.getAuthorities()).thenAnswer((Answer>) invocation -> authorities); ArgumentCaptor userRequestArgCaptor = ArgumentCaptor.forClass(OAuth2UserRequest.class); when(this.userService.loadUser(userRequestArgCaptor.capture())).thenReturn(principal); - this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); + this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); - assertThat(userRequestArgCaptor.getValue().getAdditionalParameters()).containsAllEntriesOf( - accessTokenResponse.getAdditionalParameters()); + assertThat(userRequestArgCaptor.getValue().getAdditionalParameters()) + .containsAllEntriesOf(accessTokenResponse.getAdditionalParameters()); } private OAuth2AccessTokenResponse accessTokenSuccessResponse() { @@ -227,14 +228,10 @@ public class OAuth2LoginAuthenticationProviderTests { additionalParameters.put("param1", "value1"); additionalParameters.put("param2", "value2"); - return OAuth2AccessTokenResponse - .withToken("access-token-1234") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(expiresAt.getEpochSecond()) - .scopes(scopes) - .refreshToken("refresh-token-1234") - .additionalParameters(additionalParameters) - .build(); + return OAuth2AccessTokenResponse.withToken("access-token-1234").tokenType(OAuth2AccessToken.TokenType.BEARER) + .expiresIn(expiresAt.getEpochSecond()).scopes(scopes).refreshToken("refresh-token-1234") + .additionalParameters(additionalParameters).build(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationTokenTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationTokenTests.java index 66feaa0838..c2c3c312e0 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationTokenTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationTokenTests.java @@ -40,10 +40,15 @@ import static org.springframework.security.oauth2.core.endpoint.TestOAuth2Author * @author Joe Grandja */ public class OAuth2LoginAuthenticationTokenTests { + private OAuth2User principal; + private Collection authorities; + private ClientRegistration clientRegistration; + private OAuth2AuthorizationExchange authorizationExchange; + private OAuth2AccessToken accessToken; @Before @@ -51,8 +56,7 @@ public class OAuth2LoginAuthenticationTokenTests { this.principal = mock(OAuth2User.class); this.authorities = Collections.emptyList(); this.clientRegistration = clientRegistration().build(); - this.authorizationExchange = new OAuth2AuthorizationExchange( - request().build(), success().code("code").build()); + this.authorizationExchange = new OAuth2AuthorizationExchange(request().build(), success().code("code").build()); this.accessToken = noScopes(); } @@ -68,8 +72,8 @@ public class OAuth2LoginAuthenticationTokenTests { @Test public void constructorAuthorizationRequestResponseWhenAllParametersProvidedAndValidThenCreated() { - OAuth2LoginAuthenticationToken authentication = new OAuth2LoginAuthenticationToken( - this.clientRegistration, this.authorizationExchange); + OAuth2LoginAuthenticationToken authentication = new OAuth2LoginAuthenticationToken(this.clientRegistration, + this.authorizationExchange); assertThat(authentication.getPrincipal()).isNull(); assertThat(authentication.getCredentials()).isEqualTo(""); @@ -82,44 +86,44 @@ public class OAuth2LoginAuthenticationTokenTests { @Test(expected = IllegalArgumentException.class) public void constructorTokenRequestResponseWhenClientRegistrationIsNullThenThrowIllegalArgumentException() { - new OAuth2LoginAuthenticationToken(null, this.authorizationExchange, this.principal, - this.authorities, this.accessToken); + new OAuth2LoginAuthenticationToken(null, this.authorizationExchange, this.principal, this.authorities, + this.accessToken); } @Test(expected = IllegalArgumentException.class) public void constructorTokenRequestResponseWhenAuthorizationExchangeIsNullThenThrowIllegalArgumentException() { - new OAuth2LoginAuthenticationToken(this.clientRegistration, null, this.principal, - this.authorities, this.accessToken); + new OAuth2LoginAuthenticationToken(this.clientRegistration, null, this.principal, this.authorities, + this.accessToken); } @Test(expected = IllegalArgumentException.class) public void constructorTokenRequestResponseWhenPrincipalIsNullThenThrowIllegalArgumentException() { - new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange, null, - this.authorities, this.accessToken); + new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange, null, this.authorities, + this.accessToken); } @Test public void constructorTokenRequestResponseWhenAuthoritiesIsNullThenCreated() { - new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange, - this.principal, null, this.accessToken); + new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange, this.principal, null, + this.accessToken); } @Test public void constructorTokenRequestResponseWhenAuthoritiesIsEmptyThenCreated() { - new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange, - this.principal, Collections.emptyList(), this.accessToken); + new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange, this.principal, + Collections.emptyList(), this.accessToken); } @Test(expected = IllegalArgumentException.class) public void constructorTokenRequestResponseWhenAccessTokenIsNullThenThrowIllegalArgumentException() { new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange, this.principal, - this.authorities, null); + this.authorities, null); } @Test public void constructorTokenRequestResponseWhenAllParametersProvidedAndValidThenCreated() { - OAuth2LoginAuthenticationToken authentication = new OAuth2LoginAuthenticationToken( - this.clientRegistration, this.authorizationExchange, this.principal, this.authorities, this.accessToken); + OAuth2LoginAuthenticationToken authentication = new OAuth2LoginAuthenticationToken(this.clientRegistration, + this.authorizationExchange, this.principal, this.authorities, this.accessToken); assertThat(authentication.getPrincipal()).isEqualTo(this.principal); assertThat(authentication.getCredentials()).isEqualTo(""); @@ -129,4 +133,5 @@ public class OAuth2LoginAuthenticationTokenTests { assertThat(authentication.getAccessToken()).isEqualTo(this.accessToken); assertThat(authentication.isAuthenticated()).isEqualTo(true); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginReactiveAuthenticationManagerTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginReactiveAuthenticationManagerTests.java index dd27077582..dbba4bbb0c 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginReactiveAuthenticationManagerTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginReactiveAuthenticationManagerTests.java @@ -59,13 +59,13 @@ import org.springframework.security.oauth2.core.user.OAuth2User; import reactor.core.publisher.Mono; - /** * @author Rob Winch * @since 5.1 */ @RunWith(MockitoJUnitRunner.class) public class OAuth2LoginReactiveAuthenticationManagerTests { + @Mock private ReactiveOAuth2UserService userService; @@ -77,8 +77,7 @@ public class OAuth2LoginReactiveAuthenticationManagerTests { private ClientRegistration.Builder registration = TestClientRegistrations.clientRegistration(); - OAuth2AuthorizationResponse.Builder authorizationResponseBldr = OAuth2AuthorizationResponse - .success("code") + OAuth2AuthorizationResponse.Builder authorizationResponseBldr = OAuth2AuthorizationResponse.success("code") .state("state"); private OAuth2LoginReactiveAuthenticationManager manager; @@ -91,33 +90,33 @@ public class OAuth2LoginReactiveAuthenticationManagerTests { @Test public void constructorWhenNullAccessTokenResponseClientThenIllegalArgumentException() { this.accessTokenResponseClient = null; - assertThatThrownBy(() -> new OAuth2LoginReactiveAuthenticationManager(this.accessTokenResponseClient, this.userService)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> new OAuth2LoginReactiveAuthenticationManager(this.accessTokenResponseClient, this.userService)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void constructorWhenNullUserServiceThenIllegalArgumentException() { this.userService = null; - assertThatThrownBy(() -> new OAuth2LoginReactiveAuthenticationManager(this.accessTokenResponseClient, this.userService)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> new OAuth2LoginReactiveAuthenticationManager(this.accessTokenResponseClient, this.userService)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void setAuthoritiesMapperWhenAuthoritiesMapperIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.manager.setAuthoritiesMapper(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.manager.setAuthoritiesMapper(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void authenticateWhenNoSubscriptionThenDoesNothing() { - // we didn't do anything because it should cause a ClassCastException (as verified below) + // we didn't do anything because it should cause a ClassCastException (as verified + // below) TestingAuthenticationToken token = new TestingAuthenticationToken("a", "b"); - assertThatCode(()-> this.manager.authenticate(token)) - .doesNotThrowAnyException(); + assertThatCode(() -> this.manager.authenticate(token)).doesNotThrowAnyException(); - assertThatThrownBy(() -> this.manager.authenticate(token).block()) - .isInstanceOf(Throwable.class); + assertThatThrownBy(() -> this.manager.authenticate(token).block()).isInstanceOf(Throwable.class); } @Test @@ -129,9 +128,7 @@ public class OAuth2LoginReactiveAuthenticationManagerTests { @Test public void authenticationWhenErrorThenOAuth2AuthenticationException() { - this.authorizationResponseBldr = OAuth2AuthorizationResponse - .error("error") - .state("state"); + this.authorizationResponseBldr = OAuth2AuthorizationResponse.error("error").state("state"); assertThatThrownBy(() -> this.manager.authenticate(loginToken()).block()) .isInstanceOf(OAuth2AuthenticationException.class); } @@ -146,8 +143,7 @@ public class OAuth2LoginReactiveAuthenticationManagerTests { @Test public void authenticationWhenOAuth2UserNotFoundThenEmpty() { OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .build(); + .tokenType(OAuth2AccessToken.TokenType.BEARER).build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); when(this.userService.loadUser(any())).thenReturn(Mono.empty()); assertThat(this.manager.authenticate(loginToken()).block()).isNull(); @@ -156,13 +152,14 @@ public class OAuth2LoginReactiveAuthenticationManagerTests { @Test public void authenticationWhenOAuth2UserFoundThenSuccess() { OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .build(); + .tokenType(OAuth2AccessToken.TokenType.BEARER).build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); - DefaultOAuth2User user = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), Collections.singletonMap("user", "rob"), "user"); + DefaultOAuth2User user = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), + Collections.singletonMap("user", "rob"), "user"); when(this.userService.loadUser(any())).thenReturn(Mono.just(user)); - OAuth2LoginAuthenticationToken result = (OAuth2LoginAuthenticationToken) this.manager.authenticate(loginToken()).block(); + OAuth2LoginAuthenticationToken result = (OAuth2LoginAuthenticationToken) this.manager.authenticate(loginToken()) + .block(); assertThat(result.getPrincipal()).isEqualTo(user); assertThat(result.getAuthorities()).containsOnlyElementsOf(user.getAuthorities()); @@ -176,11 +173,10 @@ public class OAuth2LoginReactiveAuthenticationManagerTests { additionalParameters.put("param1", "value1"); additionalParameters.put("param2", "value2"); OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .additionalParameters(additionalParameters) - .build(); + .tokenType(OAuth2AccessToken.TokenType.BEARER).additionalParameters(additionalParameters).build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); - DefaultOAuth2User user = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), Collections.singletonMap("user", "rob"), "user"); + DefaultOAuth2User user = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), + Collections.singletonMap("user", "rob"), "user"); ArgumentCaptor userRequestArgCaptor = ArgumentCaptor.forClass(OAuth2UserRequest.class); when(this.userService.loadUser(userRequestArgCaptor.capture())).thenReturn(Mono.just(user)); @@ -193,36 +189,34 @@ public class OAuth2LoginReactiveAuthenticationManagerTests { @Test public void authenticateWhenAuthoritiesMapperSetThenReturnMappedAuthorities() { OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .build(); + .tokenType(OAuth2AccessToken.TokenType.BEARER).build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); - DefaultOAuth2User user = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), Collections.singletonMap("user", "rob"), "user"); + DefaultOAuth2User user = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), + Collections.singletonMap("user", "rob"), "user"); when(this.userService.loadUser(any())).thenReturn(Mono.just(user)); List mappedAuthorities = AuthorityUtils.createAuthorityList("ROLE_OAUTH_USER"); GrantedAuthoritiesMapper authoritiesMapper = mock(GrantedAuthoritiesMapper.class); - when(authoritiesMapper.mapAuthorities(anyCollection())).thenAnswer((Answer>) invocation -> mappedAuthorities); + when(authoritiesMapper.mapAuthorities(anyCollection())) + .thenAnswer((Answer>) invocation -> mappedAuthorities); manager.setAuthoritiesMapper(authoritiesMapper); - OAuth2LoginAuthenticationToken result = (OAuth2LoginAuthenticationToken) this.manager.authenticate(loginToken()).block(); + OAuth2LoginAuthenticationToken result = (OAuth2LoginAuthenticationToken) this.manager.authenticate(loginToken()) + .block(); assertThat(result.getAuthorities()).isEqualTo(mappedAuthorities); } private OAuth2AuthorizationCodeAuthenticationToken loginToken() { ClientRegistration clientRegistration = this.registration.build(); - OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest - .authorizationCode() - .state("state") + OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode().state("state") .clientId(clientRegistration.getClientId()) .authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()) - .redirectUri(clientRegistration.getRedirectUri()) - .scopes(clientRegistration.getScopes()) - .build(); + .redirectUri(clientRegistration.getRedirectUri()).scopes(clientRegistration.getScopes()).build(); OAuth2AuthorizationResponse authorizationResponse = this.authorizationResponseBldr - .redirectUri(clientRegistration.getRedirectUri()) - .build(); + .redirectUri(clientRegistration.getRedirectUri()).build(); OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse); return new OAuth2AuthorizationCodeAuthenticationToken(clientRegistration, authorizationExchange); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/TestOAuth2AuthenticationTokens.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/TestOAuth2AuthenticationTokens.java index e3b3815287..ead6b2d65d 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/TestOAuth2AuthenticationTokens.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/TestOAuth2AuthenticationTokens.java @@ -38,4 +38,5 @@ public class TestOAuth2AuthenticationTokens { String registrationId = "registration-id"; return new OAuth2AuthenticationToken(principal, principal.getAuthorities(), registrationId); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/TestOAuth2AuthorizationCodeAuthenticationTokens.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/TestOAuth2AuthorizationCodeAuthenticationTokens.java index a17ec5008f..5951b62808 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/TestOAuth2AuthorizationCodeAuthenticationTokens.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/TestOAuth2AuthorizationCodeAuthenticationTokens.java @@ -44,4 +44,5 @@ public class TestOAuth2AuthorizationCodeAuthenticationTokens { OAuth2RefreshToken refreshToken = TestOAuth2RefreshTokens.refreshToken(); return new OAuth2AuthorizationCodeAuthenticationToken(registration, exchange, accessToken, refreshToken); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClientTests.java index 2ac1750edb..24793c06f6 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClientTests.java @@ -46,9 +46,11 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class DefaultAuthorizationCodeTokenResponseClientTests { - private DefaultAuthorizationCodeTokenResponseClient tokenResponseClient = - new DefaultAuthorizationCodeTokenResponseClient(); + + private DefaultAuthorizationCodeTokenResponseClient tokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient(); + private ClientRegistration clientRegistration; + private MockWebServer server; @Before @@ -56,19 +58,12 @@ public class DefaultAuthorizationCodeTokenResponseClientTests { this.server = new MockWebServer(); this.server.start(); String tokenUri = this.server.url("/oauth2/token").toString(); - this.clientRegistration = ClientRegistration.withRegistrationId("registration-1") - .clientId("client-1") - .clientSecret("secret") - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + this.clientRegistration = ClientRegistration.withRegistrationId("registration-1").clientId("client-1") + .clientSecret("secret").clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri("https://client.com/callback/client-1") - .scope("read", "write") - .authorizationUri("https://provider.com/oauth2/authorize") - .tokenUri(tokenUri) - .userInfoUri("https://provider.com/user") - .userNameAttributeName("id") - .clientName("client-1") - .build(); + .redirectUri("https://client.com/callback/client-1").scope("read", "write") + .authorizationUri("https://provider.com/oauth2/authorize").tokenUri(tokenUri) + .userInfoUri("https://provider.com/user").userNameAttributeName("id").clientName("client-1").build(); } @After @@ -96,28 +91,25 @@ public class DefaultAuthorizationCodeTokenResponseClientTests { @Test public void getTokenResponseWhenSuccessResponseThenReturnAccessTokenResponse() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read write\",\n" + - " \"refresh_token\": \"refresh-token-1234\",\n" + - " \"custom_parameter_1\": \"custom-value-1\",\n" + - " \"custom_parameter_2\": \"custom-value-2\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"read write\",\n" + " \"refresh_token\": \"refresh-token-1234\",\n" + + " \"custom_parameter_1\": \"custom-value-1\",\n" + " \"custom_parameter_2\": \"custom-value-2\"\n" + + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); Instant expiresAtBefore = Instant.now().plusSeconds(3600); - OAuth2AccessTokenResponse accessTokenResponse = - this.tokenResponseClient.getTokenResponse(this.authorizationCodeGrantRequest()); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient + .getTokenResponse(this.authorizationCodeGrantRequest()); Instant expiresAtAfter = Instant.now().plusSeconds(3600); RecordedRequest recordedRequest = this.server.takeRequest(); assertThat(recordedRequest.getMethod()).isEqualTo(HttpMethod.POST.toString()); assertThat(recordedRequest.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON_UTF8_VALUE); - assertThat(recordedRequest.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"); + assertThat(recordedRequest.getHeader(HttpHeaders.CONTENT_TYPE)) + .isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"); String formParameters = recordedRequest.getBody().readUtf8(); assertThat(formParameters).contains("grant_type=authorization_code"); @@ -136,11 +128,8 @@ public class DefaultAuthorizationCodeTokenResponseClientTests { @Test public void getTokenResponseWhenClientAuthenticationBasicThenAuthorizationHeaderIsSent() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); this.tokenResponseClient.getTokenResponse(this.authorizationCodeGrantRequest()); @@ -151,16 +140,12 @@ public class DefaultAuthorizationCodeTokenResponseClientTests { @Test public void getTokenResponseWhenClientAuthenticationPostThenFormParametersAreSent() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); ClientRegistration clientRegistration = this.from(this.clientRegistration) - .clientAuthenticationMethod(ClientAuthenticationMethod.POST) - .build(); + .clientAuthenticationMethod(ClientAuthenticationMethod.POST).build(); this.tokenResponseClient.getTokenResponse(this.authorizationCodeGrantRequest(clientRegistration)); @@ -174,61 +159,51 @@ public class DefaultAuthorizationCodeTokenResponseClientTests { @Test public void getTokenResponseWhenSuccessResponseAndNotBearerTokenTypeThenThrowOAuth2AuthorizationException() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"not-bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"not-bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(this.authorizationCodeGrantRequest())) .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response") + .hasMessageContaining( + "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response") .hasMessageContaining("tokenType cannot be null"); } @Test public void getTokenResponseWhenSuccessResponseAndMissingTokenTypeParameterThenThrowOAuth2AuthorizationException() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(this.authorizationCodeGrantRequest())) .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response") + .hasMessageContaining( + "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response") .hasMessageContaining("tokenType cannot be null"); } @Test public void getTokenResponseWhenSuccessResponseIncludesScopeThenAccessTokenHasResponseScope() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"refresh_token\": \"refresh-token-1234\",\n" + - " \"scope\": \"read\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"refresh_token\": \"refresh-token-1234\",\n" + " \"scope\": \"read\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); - OAuth2AccessTokenResponse accessTokenResponse = - this.tokenResponseClient.getTokenResponse(this.authorizationCodeGrantRequest()); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient + .getTokenResponse(this.authorizationCodeGrantRequest()); assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("read"); } @Test public void getTokenResponseWhenSuccessResponseDoesNotIncludeScopeThenAccessTokenHasDefaultScope() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"refresh_token\": \"refresh-token-1234\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"refresh_token\": \"refresh-token-1234\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); - OAuth2AccessTokenResponse accessTokenResponse = - this.tokenResponseClient.getTokenResponse(this.authorizationCodeGrantRequest()); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient + .getTokenResponse(this.authorizationCodeGrantRequest()); assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("read", "write"); } @@ -236,43 +211,35 @@ public class DefaultAuthorizationCodeTokenResponseClientTests { @Test public void getTokenResponseWhenTokenUriInvalidThenThrowOAuth2AuthorizationException() { String invalidTokenUri = "https://invalid-provider.com/oauth2/token"; - ClientRegistration clientRegistration = this.from(this.clientRegistration) - .tokenUri(invalidTokenUri) - .build(); + ClientRegistration clientRegistration = this.from(this.clientRegistration).tokenUri(invalidTokenUri).build(); - assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(this.authorizationCodeGrantRequest(clientRegistration))) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); + assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(this.authorizationCodeGrantRequest( + clientRegistration))).isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining( + "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); } @Test public void getTokenResponseWhenMalformedResponseThenThrowOAuth2AuthorizationException() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read write\",\n" + - " \"refresh_token\": \"refresh-token-1234\",\n" + - " \"custom_parameter_1\": \"custom-value-1\",\n" + - " \"custom_parameter_2\": \"custom-value-2\"\n"; -// "}\n"; // Make the JSON invalid/malformed + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"read write\",\n" + " \"refresh_token\": \"refresh-token-1234\",\n" + + " \"custom_parameter_1\": \"custom-value-1\",\n" + + " \"custom_parameter_2\": \"custom-value-2\"\n"; + // "}\n"; // Make the JSON invalid/malformed this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(this.authorizationCodeGrantRequest())) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); + .isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining( + "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); } @Test public void getTokenResponseWhenErrorResponseThenThrowOAuth2AuthorizationException() { - String accessTokenErrorResponse = "{\n" + - " \"error\": \"unauthorized_client\"\n" + - "}\n"; + String accessTokenErrorResponse = "{\n" + " \"error\": \"unauthorized_client\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenErrorResponse).setResponseCode(400)); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(this.authorizationCodeGrantRequest())) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[unauthorized_client]"); + .isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining("[unauthorized_client]"); } @Test @@ -280,52 +247,42 @@ public class DefaultAuthorizationCodeTokenResponseClientTests { this.server.enqueue(new MockResponse().setResponseCode(500)); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(this.authorizationCodeGrantRequest())) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); + .isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining( + "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); } private OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest() { return this.authorizationCodeGrantRequest(this.clientRegistration); } - private OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest( - ClientRegistration clientRegistration) { - OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest - .authorizationCode() - .clientId(clientRegistration.getClientId()) - .state("state-1234") + private OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest(ClientRegistration clientRegistration) { + OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() + .clientId(clientRegistration.getClientId()).state("state-1234") .authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()) - .redirectUri(clientRegistration.getRedirectUri()) - .scopes(clientRegistration.getScopes()) - .build(); - OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponse - .success("code-1234") - .state("state-1234") - .redirectUri(clientRegistration.getRedirectUri()) - .build(); - OAuth2AuthorizationExchange authorizationExchange = - new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse); + .redirectUri(clientRegistration.getRedirectUri()).scopes(clientRegistration.getScopes()).build(); + OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponse.success("code-1234") + .state("state-1234").redirectUri(clientRegistration.getRedirectUri()).build(); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, + authorizationResponse); return new OAuth2AuthorizationCodeGrantRequest(clientRegistration, authorizationExchange); } private MockResponse jsonResponse(String json) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json); + return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } private ClientRegistration.Builder from(ClientRegistration registration) { return ClientRegistration.withRegistrationId(registration.getRegistrationId()) - .clientId(registration.getClientId()) - .clientSecret(registration.getClientSecret()) + .clientId(registration.getClientId()).clientSecret(registration.getClientSecret()) .clientAuthenticationMethod(registration.getClientAuthenticationMethod()) .authorizationGrantType(registration.getAuthorizationGrantType()) - .redirectUri(registration.getRedirectUri()) - .scope(registration.getScopes()) + .redirectUri(registration.getRedirectUri()).scope(registration.getScopes()) .authorizationUri(registration.getProviderDetails().getAuthorizationUri()) .tokenUri(registration.getProviderDetails().getTokenUri()) .userInfoUri(registration.getProviderDetails().getUserInfoEndpoint().getUri()) - .userNameAttributeName(registration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName()) + .userNameAttributeName( + registration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName()) .clientName(registration.getClientName()); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClientTests.java index b24de2720b..345a4aeb35 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClientTests.java @@ -43,8 +43,11 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class DefaultClientCredentialsTokenResponseClientTests { + private DefaultClientCredentialsTokenResponseClient tokenResponseClient = new DefaultClientCredentialsTokenResponseClient(); + private ClientRegistration clientRegistration; + private MockWebServer server; @Before @@ -52,14 +55,10 @@ public class DefaultClientCredentialsTokenResponseClientTests { this.server = new MockWebServer(); this.server.start(); String tokenUri = this.server.url("/oauth2/token").toString(); - this.clientRegistration = ClientRegistration.withRegistrationId("registration-1") - .clientId("client-1") - .clientSecret("secret") - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) - .scope("read", "write") - .tokenUri(tokenUri) - .build(); + this.clientRegistration = ClientRegistration.withRegistrationId("registration-1").clientId("client-1") + .clientSecret("secret").clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).scope("read", "write") + .tokenUri(tokenUri).build(); } @After @@ -87,29 +86,27 @@ public class DefaultClientCredentialsTokenResponseClientTests { @Test public void getTokenResponseWhenSuccessResponseThenReturnAccessTokenResponse() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read write\",\n" + - " \"custom_parameter_1\": \"custom-value-1\",\n" + - " \"custom_parameter_2\": \"custom-value-2\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"read write\",\n" + " \"custom_parameter_1\": \"custom-value-1\",\n" + + " \"custom_parameter_2\": \"custom-value-2\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); Instant expiresAtBefore = Instant.now().plusSeconds(3600); - OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = - new OAuth2ClientCredentialsGrantRequest(this.clientRegistration); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + this.clientRegistration); - OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(clientCredentialsGrantRequest); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient + .getTokenResponse(clientCredentialsGrantRequest); Instant expiresAtAfter = Instant.now().plusSeconds(3600); RecordedRequest recordedRequest = this.server.takeRequest(); assertThat(recordedRequest.getMethod()).isEqualTo(HttpMethod.POST.toString()); assertThat(recordedRequest.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON_UTF8_VALUE); - assertThat(recordedRequest.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"); + assertThat(recordedRequest.getHeader(HttpHeaders.CONTENT_TYPE)) + .isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"); String formParameters = recordedRequest.getBody().readUtf8(); assertThat(formParameters).contains("grant_type=client_credentials"); @@ -127,15 +124,12 @@ public class DefaultClientCredentialsTokenResponseClientTests { @Test public void getTokenResponseWhenClientAuthenticationBasicThenAuthorizationHeaderIsSent() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); - OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = - new OAuth2ClientCredentialsGrantRequest(this.clientRegistration); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + this.clientRegistration); this.tokenResponseClient.getTokenResponse(clientCredentialsGrantRequest); @@ -145,19 +139,15 @@ public class DefaultClientCredentialsTokenResponseClientTests { @Test public void getTokenResponseWhenClientAuthenticationPostThenFormParametersAreSent() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); ClientRegistration clientRegistration = this.from(this.clientRegistration) - .clientAuthenticationMethod(ClientAuthenticationMethod.POST) - .build(); + .clientAuthenticationMethod(ClientAuthenticationMethod.POST).build(); - OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = - new OAuth2ClientCredentialsGrantRequest(clientRegistration); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + clientRegistration); this.tokenResponseClient.getTokenResponse(clientCredentialsGrantRequest); @@ -171,69 +161,62 @@ public class DefaultClientCredentialsTokenResponseClientTests { @Test public void getTokenResponseWhenSuccessResponseAndNotBearerTokenTypeThenThrowOAuth2AuthorizationException() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"not-bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"not-bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); - OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = - new OAuth2ClientCredentialsGrantRequest(this.clientRegistration); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + this.clientRegistration); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(clientCredentialsGrantRequest)) .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response") + .hasMessageContaining( + "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response") .hasMessageContaining("tokenType cannot be null"); } @Test public void getTokenResponseWhenSuccessResponseAndMissingTokenTypeParameterThenThrowOAuth2AuthorizationException() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); - OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = - new OAuth2ClientCredentialsGrantRequest(this.clientRegistration); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + this.clientRegistration); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(clientCredentialsGrantRequest)) .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response") + .hasMessageContaining( + "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response") .hasMessageContaining("tokenType cannot be null"); } @Test public void getTokenResponseWhenSuccessResponseIncludesScopeThenAccessTokenHasResponseScope() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + " \"scope\": \"read\"\n" + + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); - OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = - new OAuth2ClientCredentialsGrantRequest(this.clientRegistration); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + this.clientRegistration); - OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(clientCredentialsGrantRequest); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient + .getTokenResponse(clientCredentialsGrantRequest); assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("read"); } @Test public void getTokenResponseWhenSuccessResponseDoesNotIncludeScopeThenAccessTokenHasDefaultScope() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); - OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = - new OAuth2ClientCredentialsGrantRequest(this.clientRegistration); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + this.clientRegistration); - OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(clientCredentialsGrantRequest); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient + .getTokenResponse(clientCredentialsGrantRequest); assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("read", "write"); } @@ -241,78 +224,67 @@ public class DefaultClientCredentialsTokenResponseClientTests { @Test public void getTokenResponseWhenTokenUriInvalidThenThrowOAuth2AuthorizationException() { String invalidTokenUri = "https://invalid-provider.com/oauth2/token"; - ClientRegistration clientRegistration = this.from(this.clientRegistration) - .tokenUri(invalidTokenUri) - .build(); + ClientRegistration clientRegistration = this.from(this.clientRegistration).tokenUri(invalidTokenUri).build(); - OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = - new OAuth2ClientCredentialsGrantRequest(clientRegistration); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + clientRegistration); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(clientCredentialsGrantRequest)) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); + .isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining( + "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); } @Test public void getTokenResponseWhenMalformedResponseThenThrowOAuth2AuthorizationException() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read write\",\n" + - " \"custom_parameter_1\": \"custom-value-1\",\n" + - " \"custom_parameter_2\": \"custom-value-2\"\n"; -// "}\n"; // Make the JSON invalid/malformed + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"read write\",\n" + " \"custom_parameter_1\": \"custom-value-1\",\n" + + " \"custom_parameter_2\": \"custom-value-2\"\n"; + // "}\n"; // Make the JSON invalid/malformed this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); - OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = - new OAuth2ClientCredentialsGrantRequest(this.clientRegistration); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + this.clientRegistration); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(clientCredentialsGrantRequest)) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); + .isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining( + "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); } @Test public void getTokenResponseWhenErrorResponseThenThrowOAuth2AuthorizationException() { - String accessTokenErrorResponse = "{\n" + - " \"error\": \"unauthorized_client\"\n" + - "}\n"; + String accessTokenErrorResponse = "{\n" + " \"error\": \"unauthorized_client\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenErrorResponse).setResponseCode(400)); - OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = - new OAuth2ClientCredentialsGrantRequest(this.clientRegistration); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + this.clientRegistration); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(clientCredentialsGrantRequest)) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[unauthorized_client]"); + .isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining("[unauthorized_client]"); } @Test public void getTokenResponseWhenServerErrorResponseThenThrowOAuth2AuthorizationException() { this.server.enqueue(new MockResponse().setResponseCode(500)); - OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = - new OAuth2ClientCredentialsGrantRequest(this.clientRegistration); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + this.clientRegistration); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(clientCredentialsGrantRequest)) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); + .isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining( + "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); } private MockResponse jsonResponse(String json) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json); + return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } private ClientRegistration.Builder from(ClientRegistration registration) { return ClientRegistration.withRegistrationId(registration.getRegistrationId()) - .clientId(registration.getClientId()) - .clientSecret(registration.getClientSecret()) + .clientId(registration.getClientId()).clientSecret(registration.getClientSecret()) .clientAuthenticationMethod(registration.getClientAuthenticationMethod()) - .authorizationGrantType(registration.getAuthorizationGrantType()) - .scope(registration.getScopes()) + .authorizationGrantType(registration.getAuthorizationGrantType()).scope(registration.getScopes()) .tokenUri(registration.getProviderDetails().getTokenUri()); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultPasswordTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultPasswordTokenResponseClientTests.java index 6390ae3959..0e52a574cd 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultPasswordTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultPasswordTokenResponseClientTests.java @@ -44,10 +44,15 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class DefaultPasswordTokenResponseClientTests { + private DefaultPasswordTokenResponseClient tokenResponseClient = new DefaultPasswordTokenResponseClient(); + private ClientRegistration.Builder clientRegistrationBuilder; + private String username = "user1"; + private String password = "password"; + private MockWebServer server; @Before @@ -56,9 +61,7 @@ public class DefaultPasswordTokenResponseClientTests { this.server.start(); String tokenUri = this.server.url("/oauth2/token").toString(); this.clientRegistrationBuilder = TestClientRegistrations.clientRegistration() - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .scope("read", "write") - .tokenUri(tokenUri); + .authorizationGrantType(AuthorizationGrantType.PASSWORD).scope("read", "write").tokenUri(tokenUri); } @After @@ -86,18 +89,15 @@ public class DefaultPasswordTokenResponseClientTests { @Test public void getTokenResponseWhenSuccessResponseThenReturnAccessTokenResponse() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); Instant expiresAtBefore = Instant.now().plusSeconds(3600); ClientRegistration clientRegistration = this.clientRegistrationBuilder.build(); - OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest( - clientRegistration, this.username, this.password); + OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest(clientRegistration, + this.username, this.password); OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(passwordGrantRequest); @@ -106,7 +106,8 @@ public class DefaultPasswordTokenResponseClientTests { RecordedRequest recordedRequest = this.server.takeRequest(); assertThat(recordedRequest.getMethod()).isEqualTo(HttpMethod.POST.toString()); assertThat(recordedRequest.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON_UTF8_VALUE); - assertThat(recordedRequest.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"); + assertThat(recordedRequest.getHeader(HttpHeaders.CONTENT_TYPE)) + .isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"); String formParameters = recordedRequest.getBody().readUtf8(); assertThat(formParameters).contains("grant_type=password"); @@ -117,24 +118,21 @@ public class DefaultPasswordTokenResponseClientTests { assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo("access-token-1234"); assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER); assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween(expiresAtBefore, expiresAtAfter); - assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly(clientRegistration.getScopes().toArray(new String[0])); + assertThat(accessTokenResponse.getAccessToken().getScopes()) + .containsExactly(clientRegistration.getScopes().toArray(new String[0])); assertThat(accessTokenResponse.getRefreshToken()).isNull(); } @Test public void getTokenResponseWhenClientAuthenticationPostThenFormParametersAreSent() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); ClientRegistration clientRegistration = this.clientRegistrationBuilder - .clientAuthenticationMethod(ClientAuthenticationMethod.POST) - .build(); - OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest( - clientRegistration, this.username, this.password); + .clientAuthenticationMethod(ClientAuthenticationMethod.POST).build(); + OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest(clientRegistration, + this.username, this.password); this.tokenResponseClient.getTokenResponse(passwordGrantRequest); @@ -148,11 +146,8 @@ public class DefaultPasswordTokenResponseClientTests { @Test public void getTokenResponseWhenSuccessResponseAndNotBearerTokenTypeThenThrowOAuth2AuthorizationException() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"not-bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"not-bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest( @@ -160,18 +155,16 @@ public class DefaultPasswordTokenResponseClientTests { assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(passwordGrantRequest)) .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response") + .hasMessageContaining( + "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response") .hasMessageContaining("tokenType cannot be null"); } @Test public void getTokenResponseWhenSuccessResponseIncludesScopeThenAccessTokenHasResponseScope() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + " \"scope\": \"read\"\n" + + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest( @@ -188,17 +181,14 @@ public class DefaultPasswordTokenResponseClientTests { @Test public void getTokenResponseWhenErrorResponseThenThrowOAuth2AuthorizationException() { - String accessTokenErrorResponse = "{\n" + - " \"error\": \"unauthorized_client\"\n" + - "}\n"; + String accessTokenErrorResponse = "{\n" + " \"error\": \"unauthorized_client\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenErrorResponse).setResponseCode(400)); OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest( this.clientRegistrationBuilder.build(), this.username, this.password); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(passwordGrantRequest)) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[unauthorized_client]"); + .isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining("[unauthorized_client]"); } @Test @@ -209,13 +199,12 @@ public class DefaultPasswordTokenResponseClientTests { this.clientRegistrationBuilder.build(), this.username, this.password); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(passwordGrantRequest)) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); + .isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining( + "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); } private MockResponse jsonResponse(String json) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json); + return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClientTests.java index 44c455a944..25c786f36c 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClientTests.java @@ -47,10 +47,15 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class DefaultRefreshTokenTokenResponseClientTests { + private DefaultRefreshTokenTokenResponseClient tokenResponseClient = new DefaultRefreshTokenTokenResponseClient(); + private ClientRegistration.Builder clientRegistrationBuilder; + private OAuth2AccessToken accessToken; + private OAuth2RefreshToken refreshToken; + private MockWebServer server; @Before @@ -88,11 +93,8 @@ public class DefaultRefreshTokenTokenResponseClientTests { @Test public void getTokenResponseWhenSuccessResponseThenReturnAccessTokenResponse() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); Instant expiresAtBefore = Instant.now().plusSeconds(3600); @@ -100,14 +102,16 @@ public class DefaultRefreshTokenTokenResponseClientTests { OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest( this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken); - OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient + .getTokenResponse(refreshTokenGrantRequest); Instant expiresAtAfter = Instant.now().plusSeconds(3600); RecordedRequest recordedRequest = this.server.takeRequest(); assertThat(recordedRequest.getMethod()).isEqualTo(HttpMethod.POST.toString()); assertThat(recordedRequest.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON_UTF8_VALUE); - assertThat(recordedRequest.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"); + assertThat(recordedRequest.getHeader(HttpHeaders.CONTENT_TYPE)) + .isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"); assertThat(recordedRequest.getHeader(HttpHeaders.AUTHORIZATION)).startsWith("Basic "); String formParameters = recordedRequest.getBody().readUtf8(); @@ -117,25 +121,22 @@ public class DefaultRefreshTokenTokenResponseClientTests { assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo("access-token-1234"); assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER); assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween(expiresAtBefore, expiresAtAfter); - assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly(this.accessToken.getScopes().toArray(new String[0])); + assertThat(accessTokenResponse.getAccessToken().getScopes()) + .containsExactly(this.accessToken.getScopes().toArray(new String[0])); assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo(this.refreshToken.getTokenValue()); } @Test public void getTokenResponseWhenClientAuthenticationPostThenFormParametersAreSent() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); ClientRegistration clientRegistration = this.clientRegistrationBuilder - .clientAuthenticationMethod(ClientAuthenticationMethod.POST) - .build(); + .clientAuthenticationMethod(ClientAuthenticationMethod.POST).build(); - OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = - new OAuth2RefreshTokenGrantRequest(clientRegistration, this.accessToken, this.refreshToken); + OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest(clientRegistration, + this.accessToken, this.refreshToken); this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest); @@ -149,11 +150,8 @@ public class DefaultRefreshTokenTokenResponseClientTests { @Test public void getTokenResponseWhenSuccessResponseAndNotBearerTokenTypeThenThrowOAuth2AuthorizationException() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"not-bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"not-bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest( @@ -161,24 +159,24 @@ public class DefaultRefreshTokenTokenResponseClientTests { assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest)) .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response") + .hasMessageContaining( + "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response") .hasMessageContaining("tokenType cannot be null"); } @Test public void getTokenResponseWhenSuccessResponseIncludesScopeThenAccessTokenHasResponseScope() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + " \"scope\": \"read\"\n" + + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest( - this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken, Collections.singleton("read")); + this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken, + Collections.singleton("read")); - OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient + .getTokenResponse(refreshTokenGrantRequest); RecordedRequest recordedRequest = this.server.takeRequest(); String formParameters = recordedRequest.getBody().readUtf8(); @@ -189,17 +187,14 @@ public class DefaultRefreshTokenTokenResponseClientTests { @Test public void getTokenResponseWhenErrorResponseThenThrowOAuth2AuthorizationException() { - String accessTokenErrorResponse = "{\n" + - " \"error\": \"unauthorized_client\"\n" + - "}\n"; + String accessTokenErrorResponse = "{\n" + " \"error\": \"unauthorized_client\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenErrorResponse).setResponseCode(400)); OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest( this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest)) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[unauthorized_client]"); + .isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining("[unauthorized_client]"); } @Test @@ -210,13 +205,12 @@ public class DefaultRefreshTokenTokenResponseClientTests { this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest)) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); + .isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining( + "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); } private MockResponse jsonResponse(String json) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json); + return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/NimbusAuthorizationCodeTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/NimbusAuthorizationCodeTokenResponseClientTests.java index e26cb0b18d..27f5322891 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/NimbusAuthorizationCodeTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/NimbusAuthorizationCodeTokenResponseClientTests.java @@ -47,10 +47,15 @@ import static org.springframework.security.oauth2.core.endpoint.TestOAuth2Author * @author Joe Grandja */ public class NimbusAuthorizationCodeTokenResponseClientTests { + private ClientRegistration.Builder clientRegistrationBuilder; + private OAuth2AuthorizationRequest authorizationRequest; + private OAuth2AuthorizationResponse authorizationResponse; + private OAuth2AuthorizationExchange authorizationExchange; + private NimbusAuthorizationCodeTokenResponseClient tokenResponseClient = new NimbusAuthorizationCodeTokenResponseClient(); @Rule @@ -62,25 +67,21 @@ public class NimbusAuthorizationCodeTokenResponseClientTests { .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC); this.authorizationRequest = request().build(); this.authorizationResponse = success().build(); - this.authorizationExchange = new OAuth2AuthorizationExchange(this.authorizationRequest, this.authorizationResponse); + this.authorizationExchange = new OAuth2AuthorizationExchange(this.authorizationRequest, + this.authorizationResponse); } @Test public void getTokenResponseWhenSuccessResponseThenReturnAccessTokenResponse() throws Exception { MockWebServer server = new MockWebServer(); - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"openid profile\",\n" + - " \"refresh_token\": \"refresh-token-1234\",\n" + - " \"custom_parameter_1\": \"custom-value-1\",\n" + - " \"custom_parameter_2\": \"custom-value-2\"\n" + - "}\n"; - server.enqueue(new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(accessTokenSuccessResponse)); + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"openid profile\",\n" + " \"refresh_token\": \"refresh-token-1234\",\n" + + " \"custom_parameter_1\": \"custom-value-1\",\n" + " \"custom_parameter_2\": \"custom-value-2\"\n" + + "}\n"; + server.enqueue(new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .setBody(accessTokenSuccessResponse)); server.start(); String tokenUri = server.url("/oauth2/token").toString(); @@ -88,9 +89,9 @@ public class NimbusAuthorizationCodeTokenResponseClientTests { Instant expiresAtBefore = Instant.now().plusSeconds(3600); - OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse( - new OAuth2AuthorizationCodeGrantRequest( - this.clientRegistrationBuilder.build(), this.authorizationExchange)); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient + .getTokenResponse(new OAuth2AuthorizationCodeGrantRequest(this.clientRegistrationBuilder.build(), + this.authorizationExchange)); Instant expiresAtAfter = Instant.now().plusSeconds(3600); @@ -112,12 +113,11 @@ public class NimbusAuthorizationCodeTokenResponseClientTests { String redirectUri = "http:\\example.com"; OAuth2AuthorizationRequest authorizationRequest = request().redirectUri(redirectUri).build(); - OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange( - authorizationRequest, this.authorizationResponse); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, + this.authorizationResponse); this.tokenResponseClient.getTokenResponse( - new OAuth2AuthorizationCodeGrantRequest( - this.clientRegistrationBuilder.build(), authorizationExchange)); + new OAuth2AuthorizationCodeGrantRequest(this.clientRegistrationBuilder.build(), authorizationExchange)); } @Test @@ -127,9 +127,8 @@ public class NimbusAuthorizationCodeTokenResponseClientTests { String tokenUri = "http:\\provider.com\\oauth2\\token"; this.clientRegistrationBuilder.tokenUri(tokenUri); - this.tokenResponseClient.getTokenResponse( - new OAuth2AuthorizationCodeGrantRequest( - this.clientRegistrationBuilder.build(), this.authorizationExchange)); + this.tokenResponseClient.getTokenResponse(new OAuth2AuthorizationCodeGrantRequest( + this.clientRegistrationBuilder.build(), this.authorizationExchange)); } @Test @@ -139,28 +138,24 @@ public class NimbusAuthorizationCodeTokenResponseClientTests { MockWebServer server = new MockWebServer(); - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"openid profile\",\n" + - " \"custom_parameter_1\": \"custom-value-1\",\n" + - " \"custom_parameter_2\": \"custom-value-2\"\n"; -// "}\n"; // Make the JSON invalid/malformed + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"openid profile\",\n" + " \"custom_parameter_1\": \"custom-value-1\",\n" + + " \"custom_parameter_2\": \"custom-value-2\"\n"; + // "}\n"; // Make the JSON invalid/malformed - server.enqueue(new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(accessTokenSuccessResponse)); + server.enqueue(new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .setBody(accessTokenSuccessResponse)); server.start(); String tokenUri = server.url("/oauth2/token").toString(); this.clientRegistrationBuilder.tokenUri(tokenUri); try { - this.tokenResponseClient.getTokenResponse( - new OAuth2AuthorizationCodeGrantRequest( - this.clientRegistrationBuilder.build(), this.authorizationExchange)); - } finally { + this.tokenResponseClient.getTokenResponse(new OAuth2AuthorizationCodeGrantRequest( + this.clientRegistrationBuilder.build(), this.authorizationExchange)); + } + finally { server.shutdown(); } } @@ -172,9 +167,8 @@ public class NimbusAuthorizationCodeTokenResponseClientTests { String tokenUri = "https://invalid-provider.com/oauth2/token"; this.clientRegistrationBuilder.tokenUri(tokenUri); - this.tokenResponseClient.getTokenResponse( - new OAuth2AuthorizationCodeGrantRequest( - this.clientRegistrationBuilder.build(), this.authorizationExchange)); + this.tokenResponseClient.getTokenResponse(new OAuth2AuthorizationCodeGrantRequest( + this.clientRegistrationBuilder.build(), this.authorizationExchange)); } @Test @@ -184,23 +178,19 @@ public class NimbusAuthorizationCodeTokenResponseClientTests { MockWebServer server = new MockWebServer(); - String accessTokenErrorResponse = "{\n" + - " \"error\": \"unauthorized_client\"\n" + - "}\n"; - server.enqueue(new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setResponseCode(500) - .setBody(accessTokenErrorResponse)); + String accessTokenErrorResponse = "{\n" + " \"error\": \"unauthorized_client\"\n" + "}\n"; + server.enqueue(new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .setResponseCode(500).setBody(accessTokenErrorResponse)); server.start(); String tokenUri = server.url("/oauth2/token").toString(); this.clientRegistrationBuilder.tokenUri(tokenUri); try { - this.tokenResponseClient.getTokenResponse( - new OAuth2AuthorizationCodeGrantRequest( - this.clientRegistrationBuilder.build(), this.authorizationExchange)); - } finally { + this.tokenResponseClient.getTokenResponse(new OAuth2AuthorizationCodeGrantRequest( + this.clientRegistrationBuilder.build(), this.authorizationExchange)); + } + finally { server.shutdown(); } } @@ -220,70 +210,63 @@ public class NimbusAuthorizationCodeTokenResponseClientTests { this.clientRegistrationBuilder.tokenUri(tokenUri); try { - this.tokenResponseClient.getTokenResponse( - new OAuth2AuthorizationCodeGrantRequest( - this.clientRegistrationBuilder.build(), this.authorizationExchange)); - } finally { + this.tokenResponseClient.getTokenResponse(new OAuth2AuthorizationCodeGrantRequest( + this.clientRegistrationBuilder.build(), this.authorizationExchange)); + } + finally { server.shutdown(); } } @Test - public void getTokenResponseWhenSuccessResponseAndNotBearerTokenTypeThenThrowOAuth2AuthorizationException() throws Exception { + public void getTokenResponseWhenSuccessResponseAndNotBearerTokenTypeThenThrowOAuth2AuthorizationException() + throws Exception { this.exception.expect(OAuth2AuthorizationException.class); this.exception.expectMessage(containsString("invalid_token_response")); MockWebServer server = new MockWebServer(); - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"not-bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"not-bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; - server.enqueue(new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(accessTokenSuccessResponse)); + server.enqueue(new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .setBody(accessTokenSuccessResponse)); server.start(); String tokenUri = server.url("/oauth2/token").toString(); this.clientRegistrationBuilder.tokenUri(tokenUri); try { - this.tokenResponseClient.getTokenResponse( - new OAuth2AuthorizationCodeGrantRequest( - this.clientRegistrationBuilder.build(), this.authorizationExchange)); - } finally { + this.tokenResponseClient.getTokenResponse(new OAuth2AuthorizationCodeGrantRequest( + this.clientRegistrationBuilder.build(), this.authorizationExchange)); + } + finally { server.shutdown(); } } @Test - public void getTokenResponseWhenSuccessResponseIncludesScopeThenReturnAccessTokenResponseUsingResponseScope() throws Exception { + public void getTokenResponseWhenSuccessResponseIncludesScopeThenReturnAccessTokenResponseUsingResponseScope() + throws Exception { MockWebServer server = new MockWebServer(); - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"openid profile\"\n" + - "}\n"; - server.enqueue(new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(accessTokenSuccessResponse)); + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"openid profile\"\n" + "}\n"; + server.enqueue(new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .setBody(accessTokenSuccessResponse)); server.start(); String tokenUri = server.url("/oauth2/token").toString(); this.clientRegistrationBuilder.tokenUri(tokenUri); - OAuth2AuthorizationRequest authorizationRequest = - request().scope("openid", "profile", "email", "address").build(); - OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange( - authorizationRequest, this.authorizationResponse); + OAuth2AuthorizationRequest authorizationRequest = request().scope("openid", "profile", "email", "address") + .build(); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, + this.authorizationResponse); OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse( - new OAuth2AuthorizationCodeGrantRequest( - this.clientRegistrationBuilder.build(), authorizationExchange)); + new OAuth2AuthorizationCodeGrantRequest(this.clientRegistrationBuilder.build(), authorizationExchange)); server.shutdown(); @@ -291,33 +274,31 @@ public class NimbusAuthorizationCodeTokenResponseClientTests { } @Test - public void getTokenResponseWhenSuccessResponseDoesNotIncludeScopeThenReturnAccessTokenResponseUsingRequestedScope() throws Exception { + public void getTokenResponseWhenSuccessResponseDoesNotIncludeScopeThenReturnAccessTokenResponseUsingRequestedScope() + throws Exception { MockWebServer server = new MockWebServer(); - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; - server.enqueue(new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(accessTokenSuccessResponse)); + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; + server.enqueue(new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .setBody(accessTokenSuccessResponse)); server.start(); String tokenUri = server.url("/oauth2/token").toString(); this.clientRegistrationBuilder.tokenUri(tokenUri); - OAuth2AuthorizationRequest authorizationRequest = - request().scope("openid", "profile", "email", "address").build(); - OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange( - authorizationRequest, this.authorizationResponse); + OAuth2AuthorizationRequest authorizationRequest = request().scope("openid", "profile", "email", "address") + .build(); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, + this.authorizationResponse); OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse( - new OAuth2AuthorizationCodeGrantRequest( - this.clientRegistrationBuilder.build(), authorizationExchange)); + new OAuth2AuthorizationCodeGrantRequest(this.clientRegistrationBuilder.build(), authorizationExchange)); server.shutdown(); - assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("openid", "profile", "email", "address"); + assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("openid", "profile", "email", + "address"); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequestEntityConverterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequestEntityConverterTests.java index ab3003f98e..2fc9a2c6e0 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequestEntityConverterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequestEntityConverterTests.java @@ -44,31 +44,24 @@ import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VAL * @author Joe Grandja */ public class OAuth2AuthorizationCodeGrantRequestEntityConverterTests { + private OAuth2AuthorizationCodeGrantRequestEntityConverter converter = new OAuth2AuthorizationCodeGrantRequestEntityConverter(); + private ClientRegistration.Builder clientRegistrationBuilder = ClientRegistration - .withRegistrationId("registration-1") - .clientId("client-1") - .clientSecret("secret") - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri("https://client.com/callback/client-1") - .scope("read", "write") - .authorizationUri("https://provider.com/oauth2/authorize") - .tokenUri("https://provider.com/oauth2/token") - .userInfoUri("https://provider.com/user") - .userNameAttributeName("id") - .clientName("client-1"); + .withRegistrationId("registration-1").clientId("client-1").clientSecret("secret") + .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) + .redirectUri("https://client.com/callback/client-1").scope("read", "write") + .authorizationUri("https://provider.com/oauth2/authorize").tokenUri("https://provider.com/oauth2/token") + .userInfoUri("https://provider.com/user").userNameAttributeName("id").clientName("client-1"); + private OAuth2AuthorizationRequest.Builder authorizationRequestBuilder = OAuth2AuthorizationRequest - .authorizationCode() - .clientId("client-1") - .state("state-1234") - .authorizationUri("https://provider.com/oauth2/authorize") - .redirectUri("https://client.com/callback/client-1") - .scopes(new HashSet(Arrays.asList("read", "write"))); + .authorizationCode().clientId("client-1").state("state-1234") + .authorizationUri("https://provider.com/oauth2/authorize") + .redirectUri("https://client.com/callback/client-1").scopes(new HashSet(Arrays.asList("read", "write"))); + private OAuth2AuthorizationResponse.Builder authorizationResponseBuilder = OAuth2AuthorizationResponse - .success("code-1234") - .state("state-1234") - .redirectUri("https://client.com/callback/client-1"); + .success("code-1234").state("state-1234").redirectUri("https://client.com/callback/client-1"); @SuppressWarnings("unchecked") @Test @@ -76,39 +69,37 @@ public class OAuth2AuthorizationCodeGrantRequestEntityConverterTests { ClientRegistration clientRegistration = clientRegistrationBuilder.build(); OAuth2AuthorizationRequest authorizationRequest = authorizationRequestBuilder.build(); OAuth2AuthorizationResponse authorizationResponse = authorizationResponseBuilder.build(); - OAuth2AuthorizationExchange authorizationExchange = - new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, + authorizationResponse); OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest = new OAuth2AuthorizationCodeGrantRequest( clientRegistration, authorizationExchange); RequestEntity requestEntity = this.converter.convert(authorizationCodeGrantRequest); assertThat(requestEntity.getMethod()).isEqualTo(HttpMethod.POST); - assertThat(requestEntity.getUrl().toASCIIString()).isEqualTo( - clientRegistration.getProviderDetails().getTokenUri()); + assertThat(requestEntity.getUrl().toASCIIString()) + .isEqualTo(clientRegistration.getProviderDetails().getTokenUri()); HttpHeaders headers = requestEntity.getHeaders(); assertThat(headers.getAccept()).contains(MediaType.APPLICATION_JSON_UTF8); - assertThat(headers.getContentType()).isEqualTo( - MediaType.valueOf(APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")); + assertThat(headers.getContentType()) + .isEqualTo(MediaType.valueOf(APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")); assertThat(headers.getFirst(HttpHeaders.AUTHORIZATION)).startsWith("Basic "); MultiValueMap formParameters = (MultiValueMap) requestEntity.getBody(); - assertThat(formParameters.getFirst(OAuth2ParameterNames.GRANT_TYPE)).isEqualTo( - AuthorizationGrantType.AUTHORIZATION_CODE.getValue()); + assertThat(formParameters.getFirst(OAuth2ParameterNames.GRANT_TYPE)) + .isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE.getValue()); assertThat(formParameters.getFirst(OAuth2ParameterNames.CODE)).isEqualTo("code-1234"); assertThat(formParameters.getFirst(OAuth2ParameterNames.CLIENT_ID)).isNull(); - assertThat(formParameters.getFirst(OAuth2ParameterNames.REDIRECT_URI)).isEqualTo( - clientRegistration.getRedirectUri()); + assertThat(formParameters.getFirst(OAuth2ParameterNames.REDIRECT_URI)) + .isEqualTo(clientRegistration.getRedirectUri()); } @SuppressWarnings("unchecked") @Test public void convertWhenPkceGrantRequestValidThenConverts() { - ClientRegistration clientRegistration = clientRegistrationBuilder - .clientAuthenticationMethod(null) - .clientSecret(null) - .build(); + ClientRegistration clientRegistration = clientRegistrationBuilder.clientAuthenticationMethod(null) + .clientSecret(null).build(); Map attributes = new HashMap<>(); attributes.put(PkceParameterNames.CODE_VERIFIER, "code-verifier-1234"); @@ -117,36 +108,35 @@ public class OAuth2AuthorizationCodeGrantRequestEntityConverterTests { additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, "code-challenge-1234"); additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256"); - OAuth2AuthorizationRequest authorizationRequest = authorizationRequestBuilder - .attributes(attributes) - .additionalParameters(additionalParameters) - .build(); + OAuth2AuthorizationRequest authorizationRequest = authorizationRequestBuilder.attributes(attributes) + .additionalParameters(additionalParameters).build(); OAuth2AuthorizationResponse authorizationResponse = authorizationResponseBuilder.build(); - OAuth2AuthorizationExchange authorizationExchange = - new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, + authorizationResponse); OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest = new OAuth2AuthorizationCodeGrantRequest( clientRegistration, authorizationExchange); RequestEntity requestEntity = this.converter.convert(authorizationCodeGrantRequest); assertThat(requestEntity.getMethod()).isEqualTo(HttpMethod.POST); - assertThat(requestEntity.getUrl().toASCIIString()).isEqualTo( - clientRegistration.getProviderDetails().getTokenUri()); + assertThat(requestEntity.getUrl().toASCIIString()) + .isEqualTo(clientRegistration.getProviderDetails().getTokenUri()); HttpHeaders headers = requestEntity.getHeaders(); assertThat(headers.getAccept()).contains(MediaType.APPLICATION_JSON_UTF8); - assertThat(headers.getContentType()).isEqualTo( - MediaType.valueOf(APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")); + assertThat(headers.getContentType()) + .isEqualTo(MediaType.valueOf(APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")); assertThat(headers.getFirst(HttpHeaders.AUTHORIZATION)).isNull(); MultiValueMap formParameters = (MultiValueMap) requestEntity.getBody(); - assertThat(formParameters.getFirst(OAuth2ParameterNames.GRANT_TYPE)).isEqualTo( - AuthorizationGrantType.AUTHORIZATION_CODE.getValue()); + assertThat(formParameters.getFirst(OAuth2ParameterNames.GRANT_TYPE)) + .isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE.getValue()); assertThat(formParameters.getFirst(OAuth2ParameterNames.CODE)).isEqualTo("code-1234"); - assertThat(formParameters.getFirst(OAuth2ParameterNames.REDIRECT_URI)).isEqualTo( - clientRegistration.getRedirectUri()); + assertThat(formParameters.getFirst(OAuth2ParameterNames.REDIRECT_URI)) + .isEqualTo(clientRegistration.getRedirectUri()); assertThat(formParameters.getFirst(OAuth2ParameterNames.CLIENT_ID)).isEqualTo("client-1"); assertThat(formParameters.getFirst(PkceParameterNames.CODE_VERIFIER)).isEqualTo("code-verifier-1234"); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequestTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequestTests.java index 991ec80c0a..2a70175ca1 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequestTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2AuthorizationCodeGrantRequestTests.java @@ -32,7 +32,9 @@ import static org.springframework.security.oauth2.core.endpoint.TestOAuth2Author * @author Joe Grandja */ public class OAuth2AuthorizationCodeGrantRequestTests { + private ClientRegistration clientRegistration; + private OAuth2AuthorizationExchange authorizationExchange; @Before @@ -53,11 +55,12 @@ public class OAuth2AuthorizationCodeGrantRequestTests { @Test public void constructorWhenAllParametersProvidedAndValidThenCreated() { - OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest = - new OAuth2AuthorizationCodeGrantRequest(this.clientRegistration, this.authorizationExchange); + OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest = new OAuth2AuthorizationCodeGrantRequest( + this.clientRegistration, this.authorizationExchange); assertThat(authorizationCodeGrantRequest.getClientRegistration()).isEqualTo(this.clientRegistration); assertThat(authorizationCodeGrantRequest.getAuthorizationExchange()).isEqualTo(this.authorizationExchange); assertThat(authorizationCodeGrantRequest.getGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequestEntityConverterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequestEntityConverterTests.java index 28233c9a16..72a9735ca9 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequestEntityConverterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequestEntityConverterTests.java @@ -36,19 +36,18 @@ import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VAL * @author Joe Grandja */ public class OAuth2ClientCredentialsGrantRequestEntityConverterTests { + private OAuth2ClientCredentialsGrantRequestEntityConverter converter = new OAuth2ClientCredentialsGrantRequestEntityConverter(); + private OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest; @Before public void setup() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId("registration-1") - .clientId("client-1") - .clientSecret("secret") + .clientId("client-1").clientSecret("secret") .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) - .scope("read", "write") - .tokenUri("https://provider.com/oauth2/token") - .build(); + .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).scope("read", "write") + .tokenUri("https://provider.com/oauth2/token").build(); this.clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest(clientRegistration); } @@ -60,18 +59,19 @@ public class OAuth2ClientCredentialsGrantRequestEntityConverterTests { ClientRegistration clientRegistration = this.clientCredentialsGrantRequest.getClientRegistration(); assertThat(requestEntity.getMethod()).isEqualTo(HttpMethod.POST); - assertThat(requestEntity.getUrl().toASCIIString()).isEqualTo( - clientRegistration.getProviderDetails().getTokenUri()); + assertThat(requestEntity.getUrl().toASCIIString()) + .isEqualTo(clientRegistration.getProviderDetails().getTokenUri()); HttpHeaders headers = requestEntity.getHeaders(); assertThat(headers.getAccept()).contains(MediaType.APPLICATION_JSON_UTF8); - assertThat(headers.getContentType()).isEqualTo( - MediaType.valueOf(APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")); + assertThat(headers.getContentType()) + .isEqualTo(MediaType.valueOf(APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")); assertThat(headers.getFirst(HttpHeaders.AUTHORIZATION)).startsWith("Basic "); MultiValueMap formParameters = (MultiValueMap) requestEntity.getBody(); - assertThat(formParameters.getFirst(OAuth2ParameterNames.GRANT_TYPE)).isEqualTo( - AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()); + assertThat(formParameters.getFirst(OAuth2ParameterNames.GRANT_TYPE)) + .isEqualTo(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()); assertThat(formParameters.getFirst(OAuth2ParameterNames.SCOPE)).isEqualTo("read write"); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequestTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequestTests.java index 965a552404..b6c4bf7f2b 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequestTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2ClientCredentialsGrantRequestTests.java @@ -30,18 +30,15 @@ import static org.assertj.core.api.Java6Assertions.assertThatThrownBy; * @author Joe Grandja */ public class OAuth2ClientCredentialsGrantRequestTests { + private ClientRegistration clientRegistration; @Before public void setup() { - this.clientRegistration = ClientRegistration.withRegistrationId("registration-1") - .clientId("client-1") - .clientSecret("secret") - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) - .scope("read", "write") - .tokenUri("https://provider.com/oauth2/token") - .build(); + this.clientRegistration = ClientRegistration.withRegistrationId("registration-1").clientId("client-1") + .clientSecret("secret").clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).scope("read", "write") + .tokenUri("https://provider.com/oauth2/token").build(); } @Test @@ -53,24 +50,22 @@ public class OAuth2ClientCredentialsGrantRequestTests { @Test public void constructorWhenClientRegistrationInvalidGrantTypeThenThrowIllegalArgumentException() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId("registration-1") - .clientId("client-1") - .authorizationGrantType(AuthorizationGrantType.IMPLICIT) - .redirectUri("https://localhost:8080/redirect-uri") - .authorizationUri("https://provider.com/oauth2/auth") - .clientName("Client 1") - .build(); + .clientId("client-1").authorizationGrantType(AuthorizationGrantType.IMPLICIT) + .redirectUri("https://localhost:8080/redirect-uri").authorizationUri("https://provider.com/oauth2/auth") + .clientName("Client 1").build(); assertThatThrownBy(() -> new OAuth2ClientCredentialsGrantRequest(clientRegistration)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clientRegistration.authorizationGrantType must be AuthorizationGrantType.CLIENT_CREDENTIALS"); + .isInstanceOf(IllegalArgumentException.class).hasMessage( + "clientRegistration.authorizationGrantType must be AuthorizationGrantType.CLIENT_CREDENTIALS"); } @Test public void constructorWhenValidParametersProvidedThenCreated() { - OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = - new OAuth2ClientCredentialsGrantRequest(this.clientRegistration); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + this.clientRegistration); assertThat(clientCredentialsGrantRequest.getClientRegistration()).isEqualTo(this.clientRegistration); assertThat(clientCredentialsGrantRequest.getGrantType()).isEqualTo(AuthorizationGrantType.CLIENT_CREDENTIALS); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequestEntityConverterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequestEntityConverterTests.java index 0fd6eb4a2c..a2146f925f 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequestEntityConverterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequestEntityConverterTests.java @@ -36,15 +36,15 @@ import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VAL * @author Joe Grandja */ public class OAuth2PasswordGrantRequestEntityConverterTests { + private OAuth2PasswordGrantRequestEntityConverter converter = new OAuth2PasswordGrantRequestEntityConverter(); + private OAuth2PasswordGrantRequest passwordGrantRequest; @Before public void setup() { ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration() - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .scope("read", "write") - .build(); + .authorizationGrantType(AuthorizationGrantType.PASSWORD).scope("read", "write").build(); this.passwordGrantRequest = new OAuth2PasswordGrantRequest(clientRegistration, "user1", "password"); } @@ -56,18 +56,18 @@ public class OAuth2PasswordGrantRequestEntityConverterTests { ClientRegistration clientRegistration = this.passwordGrantRequest.getClientRegistration(); assertThat(requestEntity.getMethod()).isEqualTo(HttpMethod.POST); - assertThat(requestEntity.getUrl().toASCIIString()).isEqualTo( - clientRegistration.getProviderDetails().getTokenUri()); + assertThat(requestEntity.getUrl().toASCIIString()) + .isEqualTo(clientRegistration.getProviderDetails().getTokenUri()); HttpHeaders headers = requestEntity.getHeaders(); assertThat(headers.getAccept()).contains(MediaType.APPLICATION_JSON_UTF8); - assertThat(headers.getContentType()).isEqualTo( - MediaType.valueOf(APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")); + assertThat(headers.getContentType()) + .isEqualTo(MediaType.valueOf(APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")); assertThat(headers.getFirst(HttpHeaders.AUTHORIZATION)).startsWith("Basic "); MultiValueMap formParameters = (MultiValueMap) requestEntity.getBody(); - assertThat(formParameters.getFirst(OAuth2ParameterNames.GRANT_TYPE)).isEqualTo( - AuthorizationGrantType.PASSWORD.getValue()); + assertThat(formParameters.getFirst(OAuth2ParameterNames.GRANT_TYPE)) + .isEqualTo(AuthorizationGrantType.PASSWORD.getValue()); assertThat(formParameters.getFirst(OAuth2ParameterNames.USERNAME)).isEqualTo("user1"); assertThat(formParameters.getFirst(OAuth2ParameterNames.PASSWORD)).isEqualTo("password"); assertThat(formParameters.getFirst(OAuth2ParameterNames.SCOPE)).isEqualTo("read write"); diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequestTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequestTests.java index 7c821f9897..e736b5b83d 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequestTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2PasswordGrantRequestTests.java @@ -29,36 +29,34 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class OAuth2PasswordGrantRequestTests { + private ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration() .authorizationGrantType(AuthorizationGrantType.PASSWORD).build(); + private String username = "user1"; + private String password = "password"; @Test public void constructorWhenClientRegistrationIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new OAuth2PasswordGrantRequest(null, this.username, this.password)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clientRegistration cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clientRegistration cannot be null"); } @Test public void constructorWhenUsernameIsEmptyThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new OAuth2PasswordGrantRequest(this.clientRegistration, null, this.password)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("username cannot be empty"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("username cannot be empty"); assertThatThrownBy(() -> new OAuth2PasswordGrantRequest(this.clientRegistration, "", this.password)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("username cannot be empty"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("username cannot be empty"); } @Test public void constructorWhenPasswordIsEmptyThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new OAuth2PasswordGrantRequest(this.clientRegistration, this.username, null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("password cannot be empty"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("password cannot be empty"); assertThatThrownBy(() -> new OAuth2PasswordGrantRequest(this.clientRegistration, this.username, "")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("password cannot be empty"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("password cannot be empty"); } @Test @@ -71,11 +69,12 @@ public class OAuth2PasswordGrantRequestTests { @Test public void constructorWhenValidParametersProvidedThenCreated() { - OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest( - this.clientRegistration, this.username, this.password); + OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest(this.clientRegistration, + this.username, this.password); assertThat(passwordGrantRequest.getGrantType()).isEqualTo(AuthorizationGrantType.PASSWORD); assertThat(passwordGrantRequest.getClientRegistration()).isSameAs(this.clientRegistration); assertThat(passwordGrantRequest.getUsername()).isEqualTo(this.username); assertThat(passwordGrantRequest.getPassword()).isEqualTo(this.password); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2RefreshTokenGrantRequestEntityConverterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2RefreshTokenGrantRequestEntityConverterTests.java index 2f73174039..240f23a3b2 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2RefreshTokenGrantRequestEntityConverterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2RefreshTokenGrantRequestEntityConverterTests.java @@ -41,16 +41,16 @@ import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VAL * @author Joe Grandja */ public class OAuth2RefreshTokenGrantRequestEntityConverterTests { + private OAuth2RefreshTokenGrantRequestEntityConverter converter = new OAuth2RefreshTokenGrantRequestEntityConverter(); + private OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest; @Before public void setup() { this.refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest( - TestClientRegistrations.clientRegistration().build(), - TestOAuth2AccessTokens.scopes("read", "write"), - TestOAuth2RefreshTokens.refreshToken(), - Collections.singleton("read")); + TestClientRegistrations.clientRegistration().build(), TestOAuth2AccessTokens.scopes("read", "write"), + TestOAuth2RefreshTokens.refreshToken(), Collections.singleton("read")); } @SuppressWarnings("unchecked") @@ -62,20 +62,20 @@ public class OAuth2RefreshTokenGrantRequestEntityConverterTests { OAuth2RefreshToken refreshToken = this.refreshTokenGrantRequest.getRefreshToken(); assertThat(requestEntity.getMethod()).isEqualTo(HttpMethod.POST); - assertThat(requestEntity.getUrl().toASCIIString()).isEqualTo( - clientRegistration.getProviderDetails().getTokenUri()); + assertThat(requestEntity.getUrl().toASCIIString()) + .isEqualTo(clientRegistration.getProviderDetails().getTokenUri()); HttpHeaders headers = requestEntity.getHeaders(); assertThat(headers.getAccept()).contains(MediaType.APPLICATION_JSON_UTF8); - assertThat(headers.getContentType()).isEqualTo( - MediaType.valueOf(APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")); + assertThat(headers.getContentType()) + .isEqualTo(MediaType.valueOf(APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")); assertThat(headers.getFirst(HttpHeaders.AUTHORIZATION)).startsWith("Basic "); MultiValueMap formParameters = (MultiValueMap) requestEntity.getBody(); - assertThat(formParameters.getFirst(OAuth2ParameterNames.GRANT_TYPE)).isEqualTo( - AuthorizationGrantType.REFRESH_TOKEN.getValue()); - assertThat(formParameters.getFirst(OAuth2ParameterNames.REFRESH_TOKEN)).isEqualTo( - refreshToken.getTokenValue()); + assertThat(formParameters.getFirst(OAuth2ParameterNames.GRANT_TYPE)) + .isEqualTo(AuthorizationGrantType.REFRESH_TOKEN.getValue()); + assertThat(formParameters.getFirst(OAuth2ParameterNames.REFRESH_TOKEN)).isEqualTo(refreshToken.getTokenValue()); assertThat(formParameters.getFirst(OAuth2ParameterNames.SCOPE)).isEqualTo("read"); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2RefreshTokenGrantRequestTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2RefreshTokenGrantRequestTests.java index dc90a388a5..b0595f15a8 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2RefreshTokenGrantRequestTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/OAuth2RefreshTokenGrantRequestTests.java @@ -37,8 +37,11 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class OAuth2RefreshTokenGrantRequestTests { + private ClientRegistration clientRegistration; + private OAuth2AccessToken accessToken; + private OAuth2RefreshToken refreshToken; @Before @@ -51,22 +54,19 @@ public class OAuth2RefreshTokenGrantRequestTests { @Test public void constructorWhenClientRegistrationIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new OAuth2RefreshTokenGrantRequest(null, this.accessToken, this.refreshToken)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clientRegistration cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clientRegistration cannot be null"); } @Test public void constructorWhenAccessTokenIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new OAuth2RefreshTokenGrantRequest(this.clientRegistration, null, this.refreshToken)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("accessToken cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("accessToken cannot be null"); } @Test public void constructorWhenRefreshTokenIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new OAuth2RefreshTokenGrantRequest(this.clientRegistration, this.accessToken, null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("refreshToken cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("refreshToken cannot be null"); } @Test @@ -79,4 +79,5 @@ public class OAuth2RefreshTokenGrantRequestTests { assertThat(refreshTokenGrantRequest.getRefreshToken()).isSameAs(this.refreshToken); assertThat(refreshTokenGrantRequest.getScopes()).isEqualTo(scopes); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClientTests.java index 64186e10cb..190b925f2b 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClientTests.java @@ -51,6 +51,7 @@ import static org.mockito.Mockito.when; * @since 5.1 */ public class WebClientReactiveAuthorizationCodeTokenResponseClientTests { + private ClientRegistration.Builder clientRegistration; private WebClientReactiveAuthorizationCodeTokenResponseClient tokenResponseClient = new WebClientReactiveAuthorizationCodeTokenResponseClient(); @@ -64,8 +65,7 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClientTests { String tokenUri = this.server.url("/oauth2/token").toString(); - this.clientRegistration = TestClientRegistrations.clientRegistration() - .tokenUri(tokenUri); + this.clientRegistration = TestClientRegistrations.clientRegistration().tokenUri(tokenUri); } @After @@ -75,30 +75,26 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClientTests { @Test public void getTokenResponseWhenSuccessResponseThenReturnAccessTokenResponse() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"openid profile\",\n" + - " \"refresh_token\": \"refresh-token-1234\",\n" + - " \"custom_parameter_1\": \"custom-value-1\",\n" + - " \"custom_parameter_2\": \"custom-value-2\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"openid profile\",\n" + " \"refresh_token\": \"refresh-token-1234\",\n" + + " \"custom_parameter_1\": \"custom-value-1\",\n" + " \"custom_parameter_2\": \"custom-value-2\"\n" + + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); - Instant expiresAtBefore = Instant.now().plusSeconds(3600); - OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block(); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient + .getTokenResponse(authorizationCodeGrantRequest()).block(); String body = this.server.takeRequest().getBody().readUtf8(); - assertThat(body).isEqualTo("grant_type=authorization_code&code=code&redirect_uri=%7BbaseUrl%7D%2F%7Baction%7D%2Foauth2%2Fcode%2F%7BregistrationId%7D"); + assertThat(body).isEqualTo( + "grant_type=authorization_code&code=code&redirect_uri=%7BbaseUrl%7D%2F%7Baction%7D%2Foauth2%2Fcode%2F%7BregistrationId%7D"); Instant expiresAtAfter = Instant.now().plusSeconds(3600); assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo("access-token-1234"); - assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo( - OAuth2AccessToken.TokenType.BEARER); + assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER); assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween(expiresAtBefore, expiresAtAfter); assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("openid", "profile"); assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo("refresh-token-1234"); @@ -107,172 +103,167 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClientTests { assertThat(accessTokenResponse.getAdditionalParameters()).containsEntry("custom_parameter_2", "custom-value-2"); } -// @Test -// public void getTokenResponseWhenRedirectUriMalformedThenThrowIllegalArgumentException() throws Exception { -// this.exception.expect(IllegalArgumentException.class); -// -// String redirectUri = "http:\\example.com"; -// when(this.clientRegistration.getRedirectUri()).thenReturn(redirectUri); -// -// this.tokenResponseClient.getTokenResponse( -// new OAuth2AuthorizationCodeGrantRequest(this.clientRegistration, this.authorizationExchange)); -// } -// -// @Test -// public void getTokenResponseWhenTokenUriMalformedThenThrowIllegalArgumentException() throws Exception { -// this.exception.expect(IllegalArgumentException.class); -// -// String tokenUri = "http:\\provider.com\\oauth2\\token"; -// when(this.providerDetails.getTokenUri()).thenReturn(tokenUri); -// -// this.tokenResponseClient.getTokenResponse( -// new OAuth2AuthorizationCodeGrantRequest(this.clientRegistration, this.authorizationExchange)); -// } -// -// @Test -// public void getTokenResponseWhenSuccessResponseInvalidThenThrowOAuth2AuthorizationException() throws Exception { -// this.exception.expect(OAuth2AuthorizationException.class); -// this.exception.expectMessage(containsString("invalid_token_response")); -// -// MockWebServer server = new MockWebServer(); -// -// String accessTokenSuccessResponse = "{\n" + -// " \"access_token\": \"access-token-1234\",\n" + -// " \"token_type\": \"bearer\",\n" + -// " \"expires_in\": \"3600\",\n" + -// " \"scope\": \"openid profile\",\n" + -// " \"custom_parameter_1\": \"custom-value-1\",\n" + -// " \"custom_parameter_2\": \"custom-value-2\"\n"; -// // "}\n"; // Make the JSON invalid/malformed -// -// server.enqueue(new MockResponse() -// .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) -// .setBody(accessTokenSuccessResponse)); -// server.start(); -// -// String tokenUri = server.url("/oauth2/token").toString(); -// when(this.providerDetails.getTokenUri()).thenReturn(tokenUri); -// -// try { -// this.tokenResponseClient.getTokenResponse( -// new OAuth2AuthorizationCodeGrantRequest(this.clientRegistration, this.authorizationExchange)); -// } finally { -// server.shutdown(); -// } -// } -// -// @Test -// public void getTokenResponseWhenTokenUriInvalidThenThrowAuthenticationServiceException() throws Exception { -// this.exception.expect(AuthenticationServiceException.class); -// -// String tokenUri = "https://invalid-provider.com/oauth2/token"; -// when(this.providerDetails.getTokenUri()).thenReturn(tokenUri); -// -// this.tokenResponseClient.getTokenResponse( -// new OAuth2AuthorizationCodeGrantRequest(this.clientRegistration, this.authorizationExchange)); -// } -// + // @Test + // public void + // getTokenResponseWhenRedirectUriMalformedThenThrowIllegalArgumentException() throws + // Exception { + // this.exception.expect(IllegalArgumentException.class); + // + // String redirectUri = "http:\\example.com"; + // when(this.clientRegistration.getRedirectUri()).thenReturn(redirectUri); + // + // this.tokenResponseClient.getTokenResponse( + // new OAuth2AuthorizationCodeGrantRequest(this.clientRegistration, + // this.authorizationExchange)); + // } + // + // @Test + // public void + // getTokenResponseWhenTokenUriMalformedThenThrowIllegalArgumentException() throws + // Exception { + // this.exception.expect(IllegalArgumentException.class); + // + // String tokenUri = "http:\\provider.com\\oauth2\\token"; + // when(this.providerDetails.getTokenUri()).thenReturn(tokenUri); + // + // this.tokenResponseClient.getTokenResponse( + // new OAuth2AuthorizationCodeGrantRequest(this.clientRegistration, + // this.authorizationExchange)); + // } + // + // @Test + // public void + // getTokenResponseWhenSuccessResponseInvalidThenThrowOAuth2AuthorizationException() + // throws Exception { + // this.exception.expect(OAuth2AuthorizationException.class); + // this.exception.expectMessage(containsString("invalid_token_response")); + // + // MockWebServer server = new MockWebServer(); + // + // String accessTokenSuccessResponse = "{\n" + + // " \"access_token\": \"access-token-1234\",\n" + + // " \"token_type\": \"bearer\",\n" + + // " \"expires_in\": \"3600\",\n" + + // " \"scope\": \"openid profile\",\n" + + // " \"custom_parameter_1\": \"custom-value-1\",\n" + + // " \"custom_parameter_2\": \"custom-value-2\"\n"; + // // "}\n"; // Make the JSON invalid/malformed + // + // server.enqueue(new MockResponse() + // .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + // .setBody(accessTokenSuccessResponse)); + // server.start(); + // + // String tokenUri = server.url("/oauth2/token").toString(); + // when(this.providerDetails.getTokenUri()).thenReturn(tokenUri); + // + // try { + // this.tokenResponseClient.getTokenResponse( + // new OAuth2AuthorizationCodeGrantRequest(this.clientRegistration, + // this.authorizationExchange)); + // } finally { + // server.shutdown(); + // } + // } + // + // @Test + // public void + // getTokenResponseWhenTokenUriInvalidThenThrowAuthenticationServiceException() throws + // Exception { + // this.exception.expect(AuthenticationServiceException.class); + // + // String tokenUri = "https://invalid-provider.com/oauth2/token"; + // when(this.providerDetails.getTokenUri()).thenReturn(tokenUri); + // + // this.tokenResponseClient.getTokenResponse( + // new OAuth2AuthorizationCodeGrantRequest(this.clientRegistration, + // this.authorizationExchange)); + // } + // @Test public void getTokenResponseWhenErrorResponseThenThrowOAuth2AuthorizationException() { - String accessTokenErrorResponse = "{\n" + - " \"error\": \"unauthorized_client\"\n" + - "}\n"; + String accessTokenErrorResponse = "{\n" + " \"error\": \"unauthorized_client\"\n" + "}\n"; - this.server.enqueue(jsonResponse(accessTokenErrorResponse).setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value())); + this.server.enqueue( + jsonResponse(accessTokenErrorResponse).setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value())); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block()) - .isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client")) - .hasMessageContaining("unauthorized_client"); + .isInstanceOfSatisfying(OAuth2AuthorizationException.class, + e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client")) + .hasMessageContaining("unauthorized_client"); } // gh-5594 @Test public void getTokenResponseWhenServerErrorResponseThenThrowOAuth2AuthorizationException() { String accessTokenErrorResponse = "{}"; - this.server.enqueue(jsonResponse(accessTokenErrorResponse).setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value())); + this.server.enqueue( + jsonResponse(accessTokenErrorResponse).setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value())); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block()) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("server_error"); + .isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining("server_error"); } @Test public void getTokenResponseWhenSuccessResponseAndNotBearerTokenTypeThenThrowOAuth2AuthorizationException() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"not-bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"not-bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block()) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("invalid_token_response"); + .isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining("invalid_token_response"); } @Test public void getTokenResponseWhenSuccessResponseIncludesScopeThenReturnAccessTokenResponseUsingResponseScope() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"openid profile\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"openid profile\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); this.clientRegistration.scope("openid", "profile", "email", "address"); - OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block(); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient + .getTokenResponse(authorizationCodeGrantRequest()).block(); assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("openid", "profile"); } @Test public void getTokenResponseWhenSuccessResponseDoesNotIncludeScopeThenReturnAccessTokenResponseUsingRequestedScope() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); - this.clientRegistration.scope("openid", "profile", "email", "address"); - OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block(); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient + .getTokenResponse(authorizationCodeGrantRequest()).block(); - assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("openid", "profile", "email", "address"); + assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("openid", "profile", "email", + "address"); } private OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest() { ClientRegistration registration = this.clientRegistration.build(); - OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest - .authorizationCode() - .clientId(registration.getClientId()) - .state("state") + OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() + .clientId(registration.getClientId()).state("state") .authorizationUri(registration.getProviderDetails().getAuthorizationUri()) - .redirectUri(registration.getRedirectUri()) - .scopes(registration.getScopes()) - .build(); - OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponse - .success("code") - .state("state") - .redirectUri(registration.getRedirectUri()) - .build(); + .redirectUri(registration.getRedirectUri()).scopes(registration.getScopes()).build(); + OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponse.success("code").state("state") + .redirectUri(registration.getRedirectUri()).build(); OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse); return new OAuth2AuthorizationCodeGrantRequest(registration, authorizationExchange); } private MockResponse jsonResponse(String json) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json); + return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } - @Test(expected=IllegalArgumentException.class) - public void setWebClientNullThenIllegalArgumentException(){ + @Test(expected = IllegalArgumentException.class) + public void setWebClientNullThenIllegalArgumentException() { tokenResponseClient.setWebClient(null); } @@ -283,40 +274,35 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClientTests { tokenResponseClient.setWebClient(customClient); - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"openid profile\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"openid profile\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); this.clientRegistration.scope("openid", "profile", "email", "address"); - OAuth2AccessTokenResponse response = this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()).block(); + OAuth2AccessTokenResponse response = this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest()) + .block(); verify(customClient, atLeastOnce()).post(); } @Test - public void getTokenResponseWhenOAuth2AuthorizationRequestContainsPkceParametersThenTokenRequestBodyShouldContainCodeVerifier() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + public void getTokenResponseWhenOAuth2AuthorizationRequestContainsPkceParametersThenTokenRequestBodyShouldContainCodeVerifier() + throws Exception { + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); this.tokenResponseClient.getTokenResponse(pkceAuthorizationCodeGrantRequest()).block(); String body = this.server.takeRequest().getBody().readUtf8(); - assertThat(body).isEqualTo("grant_type=authorization_code&client_id=client-id&code=code&redirect_uri=%7BbaseUrl%7D%2F%7Baction%7D%2Foauth2%2Fcode%2F%7BregistrationId%7D&code_verifier=code-verifier-1234"); + assertThat(body).isEqualTo( + "grant_type=authorization_code&client_id=client-id&code=code&redirect_uri=%7BbaseUrl%7D%2F%7Baction%7D%2Foauth2%2Fcode%2F%7BregistrationId%7D&code_verifier=code-verifier-1234"); } private OAuth2AuthorizationCodeGrantRequest pkceAuthorizationCodeGrantRequest() { - ClientRegistration registration = this.clientRegistration - .clientAuthenticationMethod(null) - .clientSecret(null) + ClientRegistration registration = this.clientRegistration.clientAuthenticationMethod(null).clientSecret(null) .build(); Map attributes = new HashMap<>(); @@ -326,23 +312,16 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClientTests { additionalParameters.put(PkceParameterNames.CODE_CHALLENGE, "code-challenge-1234"); additionalParameters.put(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256"); - OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest - .authorizationCode() - .clientId(registration.getClientId()) - .state("state") + OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() + .clientId(registration.getClientId()).state("state") .authorizationUri(registration.getProviderDetails().getAuthorizationUri()) - .redirectUri(registration.getRedirectUri()) - .scopes(registration.getScopes()) - .attributes(attributes) - .additionalParameters(additionalParameters) - .build(); - OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponse - .success("code") - .state("state") - .redirectUri(registration.getRedirectUri()) - .build(); + .redirectUri(registration.getRedirectUri()).scopes(registration.getScopes()).attributes(attributes) + .additionalParameters(additionalParameters).build(); + OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponse.success("code").state("state") + .redirectUri(registration.getRedirectUri()).build(); OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse); return new OAuth2AuthorizationCodeGrantRequest(registration, authorizationExchange); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClientTests.java index 5128f7b779..4c1f2da432 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClientTests.java @@ -56,8 +56,7 @@ public class WebClientReactiveClientCredentialsTokenResponseClientTests { this.server = new MockWebServer(); this.server.start(); - this.clientRegistration = TestClientRegistrations - .clientCredentials() + this.clientRegistration = TestClientRegistrations.clientCredentials() .tokenUri(this.server.url("/oauth2/token").uri().toASCIIString()); } @@ -69,37 +68,29 @@ public class WebClientReactiveClientCredentialsTokenResponseClientTests { @Test public void getTokenResponseWhenHeaderThenSuccess() throws Exception { - enqueueJson("{\n" - + " \"access_token\":\"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3\",\n" - + " \"token_type\":\"bearer\",\n" - + " \"expires_in\":3600,\n" - + " \"refresh_token\":\"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk\",\n" - + " \"scope\":\"create\"\n" - + "}"); - OAuth2ClientCredentialsGrantRequest request = new OAuth2ClientCredentialsGrantRequest(this.clientRegistration - .build()); + enqueueJson("{\n" + " \"access_token\":\"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3\",\n" + + " \"token_type\":\"bearer\",\n" + " \"expires_in\":3600,\n" + + " \"refresh_token\":\"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk\",\n" + " \"scope\":\"create\"\n" + "}"); + OAuth2ClientCredentialsGrantRequest request = new OAuth2ClientCredentialsGrantRequest( + this.clientRegistration.build()); OAuth2AccessTokenResponse response = this.client.getTokenResponse(request).block(); RecordedRequest actualRequest = this.server.takeRequest(); String body = actualRequest.getUtf8Body(); assertThat(response.getAccessToken()).isNotNull(); - assertThat(actualRequest.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("Basic Y2xpZW50LWlkOmNsaWVudC1zZWNyZXQ="); + assertThat(actualRequest.getHeader(HttpHeaders.AUTHORIZATION)) + .isEqualTo("Basic Y2xpZW50LWlkOmNsaWVudC1zZWNyZXQ="); assertThat(body).isEqualTo("grant_type=client_credentials&scope=read%3Auser"); } @Test public void getTokenResponseWhenPostThenSuccess() throws Exception { ClientRegistration registration = this.clientRegistration - .clientAuthenticationMethod(ClientAuthenticationMethod.POST) - .build(); - enqueueJson("{\n" - + " \"access_token\":\"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3\",\n" - + " \"token_type\":\"bearer\",\n" - + " \"expires_in\":3600,\n" - + " \"refresh_token\":\"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk\",\n" - + " \"scope\":\"create\"\n" - + "}"); + .clientAuthenticationMethod(ClientAuthenticationMethod.POST).build(); + enqueueJson("{\n" + " \"access_token\":\"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3\",\n" + + " \"token_type\":\"bearer\",\n" + " \"expires_in\":3600,\n" + + " \"refresh_token\":\"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk\",\n" + " \"scope\":\"create\"\n" + "}"); OAuth2ClientCredentialsGrantRequest request = new OAuth2ClientCredentialsGrantRequest(registration); @@ -109,18 +100,16 @@ public class WebClientReactiveClientCredentialsTokenResponseClientTests { assertThat(response.getAccessToken()).isNotNull(); assertThat(actualRequest.getHeader(HttpHeaders.AUTHORIZATION)).isNull(); - assertThat(body).isEqualTo("grant_type=client_credentials&client_id=client-id&client_secret=client-secret&scope=read%3Auser"); + assertThat(body).isEqualTo( + "grant_type=client_credentials&client_id=client-id&client_secret=client-secret&scope=read%3Auser"); } @Test public void getTokenResponseWhenNoScopeThenClientRegistrationScopesDefaulted() { ClientRegistration registration = this.clientRegistration.build(); - enqueueJson("{\n" - + " \"access_token\":\"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3\",\n" - + " \"token_type\":\"bearer\",\n" - + " \"expires_in\":3600,\n" - + " \"refresh_token\":\"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk\"\n" - + "}"); + enqueueJson("{\n" + " \"access_token\":\"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3\",\n" + + " \"token_type\":\"bearer\",\n" + " \"expires_in\":3600,\n" + + " \"refresh_token\":\"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk\"\n" + "}"); OAuth2ClientCredentialsGrantRequest request = new OAuth2ClientCredentialsGrantRequest(registration); OAuth2AccessTokenResponse response = this.client.getTokenResponse(request).block(); @@ -128,8 +117,8 @@ public class WebClientReactiveClientCredentialsTokenResponseClientTests { assertThat(response.getAccessToken().getScopes()).isEqualTo(registration.getScopes()); } - @Test(expected=IllegalArgumentException.class) - public void setWebClientNullThenIllegalArgumentException(){ + @Test(expected = IllegalArgumentException.class) + public void setWebClientNullThenIllegalArgumentException() { client.setWebClient(null); } @@ -140,12 +129,9 @@ public class WebClientReactiveClientCredentialsTokenResponseClientTests { this.client.setWebClient(customClient); ClientRegistration registration = this.clientRegistration.build(); - enqueueJson("{\n" - + " \"access_token\":\"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3\",\n" - + " \"token_type\":\"bearer\",\n" - + " \"expires_in\":3600,\n" - + " \"refresh_token\":\"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk\"\n" - + "}"); + enqueueJson("{\n" + " \"access_token\":\"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3\",\n" + + " \"token_type\":\"bearer\",\n" + " \"expires_in\":3600,\n" + + " \"refresh_token\":\"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk\"\n" + "}"); OAuth2ClientCredentialsGrantRequest request = new OAuth2ClientCredentialsGrantRequest(registration); OAuth2AccessTokenResponse response = this.client.getTokenResponse(request).block(); @@ -161,23 +147,23 @@ public class WebClientReactiveClientCredentialsTokenResponseClientTests { OAuth2ClientCredentialsGrantRequest request = new OAuth2ClientCredentialsGrantRequest(registration); assertThatThrownBy(() -> this.client.getTokenResponse(request).block()) - .isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) + .isInstanceOfSatisfying(OAuth2AuthorizationException.class, + e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) .hasMessageContaining("[invalid_token_response]") .hasMessageContaining("Empty OAuth 2.0 Access Token Response"); } - private void enqueueUnexpectedResponse(){ - MockResponse response = new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + private void enqueueUnexpectedResponse() { + MockResponse response = new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .setResponseCode(301); this.server.enqueue(response); } private void enqueueJson(String body) { - MockResponse response = new MockResponse() - .setBody(body) - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + MockResponse response = new MockResponse().setBody(body).setHeader(HttpHeaders.CONTENT_TYPE, + MediaType.APPLICATION_JSON_VALUE); this.server.enqueue(response); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactivePasswordTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactivePasswordTokenResponseClientTests.java index 2cef538c1e..12001a2f47 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactivePasswordTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactivePasswordTokenResponseClientTests.java @@ -42,10 +42,15 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class WebClientReactivePasswordTokenResponseClientTests { + private WebClientReactivePasswordTokenResponseClient tokenResponseClient = new WebClientReactivePasswordTokenResponseClient(); + private ClientRegistration.Builder clientRegistrationBuilder; + private String username = "user1"; + private String password = "password"; + private MockWebServer server; @Before @@ -75,27 +80,26 @@ public class WebClientReactivePasswordTokenResponseClientTests { @Test public void getTokenResponseWhenSuccessResponseThenReturnAccessTokenResponse() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); Instant expiresAtBefore = Instant.now().plusSeconds(3600); ClientRegistration clientRegistration = this.clientRegistrationBuilder.build(); - OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest( - clientRegistration, this.username, this.password); + OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest(clientRegistration, + this.username, this.password); - OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(passwordGrantRequest).block(); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(passwordGrantRequest) + .block(); Instant expiresAtAfter = Instant.now().plusSeconds(3600); RecordedRequest recordedRequest = this.server.takeRequest(); assertThat(recordedRequest.getMethod()).isEqualTo(HttpMethod.POST.toString()); assertThat(recordedRequest.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON_VALUE); - assertThat(recordedRequest.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"); + assertThat(recordedRequest.getHeader(HttpHeaders.CONTENT_TYPE)) + .isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"); String formParameters = recordedRequest.getBody().readUtf8(); assertThat(formParameters).contains("grant_type=password"); @@ -106,24 +110,21 @@ public class WebClientReactivePasswordTokenResponseClientTests { assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo("access-token-1234"); assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER); assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween(expiresAtBefore, expiresAtAfter); - assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly(clientRegistration.getScopes().toArray(new String[0])); + assertThat(accessTokenResponse.getAccessToken().getScopes()) + .containsExactly(clientRegistration.getScopes().toArray(new String[0])); assertThat(accessTokenResponse.getRefreshToken()).isNull(); } @Test public void getTokenResponseWhenClientAuthenticationPostThenFormParametersAreSent() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); ClientRegistration clientRegistration = this.clientRegistrationBuilder - .clientAuthenticationMethod(ClientAuthenticationMethod.POST) - .build(); - OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest( - clientRegistration, this.username, this.password); + .clientAuthenticationMethod(ClientAuthenticationMethod.POST).build(); + OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest(clientRegistration, + this.username, this.password); this.tokenResponseClient.getTokenResponse(passwordGrantRequest).block(); @@ -137,18 +138,16 @@ public class WebClientReactivePasswordTokenResponseClientTests { @Test public void getTokenResponseWhenSuccessResponseAndNotBearerTokenTypeThenThrowOAuth2AuthorizationException() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"not-bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"not-bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest( this.clientRegistrationBuilder.build(), this.username, this.password); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(passwordGrantRequest).block()) - .isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) + .isInstanceOfSatisfying(OAuth2AuthorizationException.class, + e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) .hasMessageContaining("[invalid_token_response]") .hasMessageContaining("An error occurred parsing the Access Token response") .hasCauseInstanceOf(Throwable.class); @@ -156,18 +155,16 @@ public class WebClientReactivePasswordTokenResponseClientTests { @Test public void getTokenResponseWhenSuccessResponseIncludesScopeThenAccessTokenHasResponseScope() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + " \"scope\": \"read\"\n" + + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest( this.clientRegistrationBuilder.build(), this.username, this.password); - OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(passwordGrantRequest).block(); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(passwordGrantRequest) + .block(); RecordedRequest recordedRequest = this.server.takeRequest(); String formParameters = recordedRequest.getBody().readUtf8(); @@ -178,16 +175,15 @@ public class WebClientReactivePasswordTokenResponseClientTests { @Test public void getTokenResponseWhenErrorResponseThenThrowOAuth2AuthorizationException() { - String accessTokenErrorResponse = "{\n" + - " \"error\": \"unauthorized_client\"\n" + - "}\n"; + String accessTokenErrorResponse = "{\n" + " \"error\": \"unauthorized_client\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenErrorResponse).setResponseCode(400)); OAuth2PasswordGrantRequest passwordGrantRequest = new OAuth2PasswordGrantRequest( this.clientRegistrationBuilder.build(), this.username, this.password); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(passwordGrantRequest).block()) - .isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client")) + .isInstanceOfSatisfying(OAuth2AuthorizationException.class, + e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client")) .hasMessageContaining("[unauthorized_client]"); } @@ -199,14 +195,14 @@ public class WebClientReactivePasswordTokenResponseClientTests { this.clientRegistrationBuilder.build(), this.username, this.password); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(passwordGrantRequest).block()) - .isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) + .isInstanceOfSatisfying(OAuth2AuthorizationException.class, + e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) .hasMessageContaining("[invalid_token_response]") .hasMessageContaining("Empty OAuth 2.0 Access Token Response"); } private MockResponse jsonResponse(String json) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json); + return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClientTests.java index 272e175b9e..3c461eeb9b 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClientTests.java @@ -46,10 +46,15 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class WebClientReactiveRefreshTokenTokenResponseClientTests { + private WebClientReactiveRefreshTokenTokenResponseClient tokenResponseClient = new WebClientReactiveRefreshTokenTokenResponseClient(); + private ClientRegistration.Builder clientRegistrationBuilder; + private OAuth2AccessToken accessToken; + private OAuth2RefreshToken refreshToken; + private MockWebServer server; @Before @@ -81,11 +86,8 @@ public class WebClientReactiveRefreshTokenTokenResponseClientTests { @Test public void getTokenResponseWhenSuccessResponseThenReturnAccessTokenResponse() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); Instant expiresAtBefore = Instant.now().plusSeconds(3600); @@ -93,14 +95,16 @@ public class WebClientReactiveRefreshTokenTokenResponseClientTests { OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest( this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken); - OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block(); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient + .getTokenResponse(refreshTokenGrantRequest).block(); Instant expiresAtAfter = Instant.now().plusSeconds(3600); RecordedRequest recordedRequest = this.server.takeRequest(); assertThat(recordedRequest.getMethod()).isEqualTo(HttpMethod.POST.toString()); assertThat(recordedRequest.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON_VALUE); - assertThat(recordedRequest.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"); + assertThat(recordedRequest.getHeader(HttpHeaders.CONTENT_TYPE)) + .isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"); assertThat(recordedRequest.getHeader(HttpHeaders.AUTHORIZATION)).startsWith("Basic "); String formParameters = recordedRequest.getBody().readUtf8(); @@ -110,25 +114,22 @@ public class WebClientReactiveRefreshTokenTokenResponseClientTests { assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo("access-token-1234"); assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER); assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween(expiresAtBefore, expiresAtAfter); - assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly(this.accessToken.getScopes().toArray(new String[0])); + assertThat(accessTokenResponse.getAccessToken().getScopes()) + .containsExactly(this.accessToken.getScopes().toArray(new String[0])); assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo(this.refreshToken.getTokenValue()); } @Test public void getTokenResponseWhenClientAuthenticationPostThenFormParametersAreSent() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); ClientRegistration clientRegistration = this.clientRegistrationBuilder - .clientAuthenticationMethod(ClientAuthenticationMethod.POST) - .build(); + .clientAuthenticationMethod(ClientAuthenticationMethod.POST).build(); - OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest( - clientRegistration, this.accessToken, this.refreshToken); + OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest(clientRegistration, + this.accessToken, this.refreshToken); this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block(); @@ -142,37 +143,32 @@ public class WebClientReactiveRefreshTokenTokenResponseClientTests { @Test public void getTokenResponseWhenSuccessResponseAndNotBearerTokenTypeThenThrowOAuth2AuthorizationException() { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"not-bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"not-bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest( this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block()) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining("[invalid_token_response]") + .isInstanceOf(OAuth2AuthorizationException.class).hasMessageContaining("[invalid_token_response]") .hasMessageContaining("An error occurred parsing the Access Token response") .hasCauseInstanceOf(Throwable.class); } @Test public void getTokenResponseWhenSuccessResponseIncludesScopeThenAccessTokenHasResponseScope() throws Exception { - String accessTokenSuccessResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read\"\n" + - "}\n"; + String accessTokenSuccessResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + " \"scope\": \"read\"\n" + + "}\n"; this.server.enqueue(jsonResponse(accessTokenSuccessResponse)); OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest( - this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken, Collections.singleton("read")); + this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken, + Collections.singleton("read")); - OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block(); + OAuth2AccessTokenResponse accessTokenResponse = this.tokenResponseClient + .getTokenResponse(refreshTokenGrantRequest).block(); RecordedRequest recordedRequest = this.server.takeRequest(); String formParameters = recordedRequest.getBody().readUtf8(); @@ -183,16 +179,15 @@ public class WebClientReactiveRefreshTokenTokenResponseClientTests { @Test public void getTokenResponseWhenErrorResponseThenThrowOAuth2AuthorizationException() { - String accessTokenErrorResponse = "{\n" + - " \"error\": \"unauthorized_client\"\n" + - "}\n"; + String accessTokenErrorResponse = "{\n" + " \"error\": \"unauthorized_client\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenErrorResponse).setResponseCode(400)); OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest( this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block()) - .isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client")) + .isInstanceOfSatisfying(OAuth2AuthorizationException.class, + e -> assertThat(e.getError().getErrorCode()).isEqualTo("unauthorized_client")) .hasMessageContaining("[unauthorized_client]"); } @@ -204,14 +199,14 @@ public class WebClientReactiveRefreshTokenTokenResponseClientTests { this.clientRegistrationBuilder.build(), this.accessToken, this.refreshToken); assertThatThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block()) - .isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) + .isInstanceOfSatisfying(OAuth2AuthorizationException.class, + e -> assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token_response")) .hasMessageContaining("[invalid_token_response]") .hasMessageContaining("Empty OAuth 2.0 Access Token Response"); } private MockResponse jsonResponse(String json) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json); + return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorResponseErrorHandlerTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorResponseErrorHandlerTests.java index 98e2b72bb2..1652e8a9fc 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorResponseErrorHandlerTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/http/OAuth2ErrorResponseErrorHandlerTests.java @@ -29,17 +29,15 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class OAuth2ErrorResponseErrorHandlerTests { + private OAuth2ErrorResponseErrorHandler errorHandler = new OAuth2ErrorResponseErrorHandler(); @Test public void handleErrorWhenErrorResponseBodyThenHandled() { - String errorResponse = "{\n" + - " \"error\": \"unauthorized_client\",\n" + - " \"error_description\": \"The client is not authorized\"\n" + - "}\n"; + String errorResponse = "{\n" + " \"error\": \"unauthorized_client\",\n" + + " \"error_description\": \"The client is not authorized\"\n" + "}\n"; - MockClientHttpResponse response = new MockClientHttpResponse( - errorResponse.getBytes(), HttpStatus.BAD_REQUEST); + MockClientHttpResponse response = new MockClientHttpResponse(errorResponse.getBytes(), HttpStatus.BAD_REQUEST); assertThatThrownBy(() -> this.errorHandler.handleError(response)) .isInstanceOf(OAuth2AuthorizationException.class) @@ -50,12 +48,12 @@ public class OAuth2ErrorResponseErrorHandlerTests { public void handleErrorWhenErrorResponseWwwAuthenticateHeaderThenHandled() { String wwwAuthenticateHeader = "Bearer realm=\"auth-realm\" error=\"insufficient_scope\" error_description=\"The access token expired\""; - MockClientHttpResponse response = new MockClientHttpResponse( - new byte[0], HttpStatus.BAD_REQUEST); + MockClientHttpResponse response = new MockClientHttpResponse(new byte[0], HttpStatus.BAD_REQUEST); response.getHeaders().add(HttpHeaders.WWW_AUTHENTICATE, wwwAuthenticateHeader); assertThatThrownBy(() -> this.errorHandler.handleError(response)) .isInstanceOf(OAuth2AuthorizationException.class) .hasMessage("[insufficient_scope] The access token expired"); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationExceptionMixinTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationExceptionMixinTests.java index 537c90026d..574cf4c566 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationExceptionMixinTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationExceptionMixinTests.java @@ -46,11 +46,9 @@ public class OAuth2AuthenticationExceptionMixinTests { @Test public void serializeWhenMixinRegisteredThenSerializes() throws Exception { - OAuth2AuthenticationException exception = new OAuth2AuthenticationException(new OAuth2Error( - "[authorization_request_not_found]", - "Authorization Request Not Found", - "/foo/bar" - ), "Authorization Request Not Found"); + OAuth2AuthenticationException exception = new OAuth2AuthenticationException( + new OAuth2Error("[authorization_request_not_found]", "Authorization Request Not Found", "/foo/bar"), + "Authorization Request Not Found"); String serializedJson = this.mapper.writeValueAsString(exception); String expected = asJson(exception); @@ -60,8 +58,7 @@ public class OAuth2AuthenticationExceptionMixinTests { @Test public void serializeWhenRequiredAttributesOnlyThenSerializes() throws Exception { OAuth2AuthenticationException exception = new OAuth2AuthenticationException( - new OAuth2Error("[authorization_request_not_found]") - ); + new OAuth2Error("[authorization_request_not_found]")); String serializedJson = this.mapper.writeValueAsString(exception); String expected = asJson(exception); @@ -70,22 +67,19 @@ public class OAuth2AuthenticationExceptionMixinTests { @Test public void deserializeWhenMixinNotRegisteredThenThrowJsonProcessingException() { - String json = asJson(new OAuth2AuthenticationException( - new OAuth2Error("[authorization_request_not_found]") - )); + String json = asJson(new OAuth2AuthenticationException(new OAuth2Error("[authorization_request_not_found]"))); assertThatThrownBy(() -> new ObjectMapper().readValue(json, OAuth2AuthenticationException.class)) .isInstanceOf(JsonProcessingException.class); } @Test public void deserializeWhenMixinRegisteredThenDeserializes() throws Exception { - OAuth2AuthenticationException expected = new OAuth2AuthenticationException(new OAuth2Error( - "[authorization_request_not_found]", - "Authorization Request Not Found", - "/foo/bar" - ), "Authorization Request Not Found"); + OAuth2AuthenticationException expected = new OAuth2AuthenticationException( + new OAuth2Error("[authorization_request_not_found]", "Authorization Request Not Found", "/foo/bar"), + "Authorization Request Not Found"); - OAuth2AuthenticationException exception = this.mapper.readValue(asJson(expected), OAuth2AuthenticationException.class); + OAuth2AuthenticationException exception = this.mapper.readValue(asJson(expected), + OAuth2AuthenticationException.class); assertThat(exception).isNotNull(); assertThat(exception.getCause()).isNull(); assertThat(exception.getMessage()).isEqualTo(expected.getMessage()); @@ -100,10 +94,10 @@ public class OAuth2AuthenticationExceptionMixinTests { @Test public void deserializeWhenRequiredAttributesOnlyThenDeserializes() throws Exception { OAuth2AuthenticationException expected = new OAuth2AuthenticationException( - new OAuth2Error("[authorization_request_not_found]") - ); + new OAuth2Error("[authorization_request_not_found]")); - OAuth2AuthenticationException exception = this.mapper.readValue(asJson(expected), OAuth2AuthenticationException.class); + OAuth2AuthenticationException exception = this.mapper.readValue(asJson(expected), + OAuth2AuthenticationException.class); assertThat(exception).isNotNull(); assertThat(exception.getCause()).isNull(); assertThat(exception.getMessage()).isNull(); @@ -133,8 +127,7 @@ public class OAuth2AuthenticationExceptionMixinTests { } private String jsonStringOrNull(String input) { - return input != null - ? "\"" + input + "\"" - : "null"; + return input != null ? "\"" + input + "\"" : "null"; } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationTokenMixinTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationTokenMixinTests.java index 8ac3721ecc..88154d9a96 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationTokenMixinTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthenticationTokenMixinTests.java @@ -54,6 +54,7 @@ import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.N * @author Joe Grandja */ public class OAuth2AuthenticationTokenMixinTests { + private ObjectMapper mapper; @Before @@ -82,8 +83,8 @@ public class OAuth2AuthenticationTokenMixinTests { public void serializeWhenRequiredAttributesOnlyThenSerializes() throws Exception { DefaultOidcUser principal = TestOidcUsers.create(); principal = new DefaultOidcUser(principal.getAuthorities(), principal.getIdToken()); - OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken( - principal, Collections.emptyList(), "registration-id"); + OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken(principal, Collections.emptyList(), + "registration-id"); String expectedJson = asJson(authentication); String json = this.mapper.writeValueAsString(authentication); JSONAssert.assertEquals(expectedJson, json, true); @@ -103,95 +104,72 @@ public class OAuth2AuthenticationTokenMixinTests { OAuth2AuthenticationToken expectedAuthentication = TestOAuth2AuthenticationTokens.oidcAuthenticated(); String json = asJson(expectedAuthentication); OAuth2AuthenticationToken authentication = this.mapper.readValue(json, OAuth2AuthenticationToken.class); - assertThat(authentication.getAuthorities()) - .containsExactlyElementsOf(expectedAuthentication.getAuthorities()); - assertThat(authentication.getDetails()) - .isEqualTo(expectedAuthentication.getDetails()); - assertThat(authentication.isAuthenticated()) - .isEqualTo(expectedAuthentication.isAuthenticated()); + assertThat(authentication.getAuthorities()).containsExactlyElementsOf(expectedAuthentication.getAuthorities()); + assertThat(authentication.getDetails()).isEqualTo(expectedAuthentication.getDetails()); + assertThat(authentication.isAuthenticated()).isEqualTo(expectedAuthentication.isAuthenticated()); assertThat(authentication.getAuthorizedClientRegistrationId()) .isEqualTo(expectedAuthentication.getAuthorizedClientRegistrationId()); DefaultOidcUser expectedOidcUser = (DefaultOidcUser) expectedAuthentication.getPrincipal(); DefaultOidcUser oidcUser = (DefaultOidcUser) authentication.getPrincipal(); assertThat(oidcUser.getAuthorities().containsAll(expectedOidcUser.getAuthorities())).isTrue(); - assertThat(oidcUser.getAttributes()) - .containsExactlyEntriesOf(expectedOidcUser.getAttributes()); - assertThat(oidcUser.getName()) - .isEqualTo(expectedOidcUser.getName()); + assertThat(oidcUser.getAttributes()).containsExactlyEntriesOf(expectedOidcUser.getAttributes()); + assertThat(oidcUser.getName()).isEqualTo(expectedOidcUser.getName()); OidcIdToken expectedIdToken = expectedOidcUser.getIdToken(); OidcIdToken idToken = oidcUser.getIdToken(); - assertThat(idToken.getTokenValue()) - .isEqualTo(expectedIdToken.getTokenValue()); - assertThat(idToken.getIssuedAt()) - .isEqualTo(expectedIdToken.getIssuedAt()); - assertThat(idToken.getExpiresAt()) - .isEqualTo(expectedIdToken.getExpiresAt()); - assertThat(idToken.getClaims()) - .containsExactlyEntriesOf(expectedIdToken.getClaims()); + assertThat(idToken.getTokenValue()).isEqualTo(expectedIdToken.getTokenValue()); + assertThat(idToken.getIssuedAt()).isEqualTo(expectedIdToken.getIssuedAt()); + assertThat(idToken.getExpiresAt()).isEqualTo(expectedIdToken.getExpiresAt()); + assertThat(idToken.getClaims()).containsExactlyEntriesOf(expectedIdToken.getClaims()); OidcUserInfo expectedUserInfo = expectedOidcUser.getUserInfo(); OidcUserInfo userInfo = oidcUser.getUserInfo(); - assertThat(userInfo.getClaims()) - .containsExactlyEntriesOf(expectedUserInfo.getClaims()); + assertThat(userInfo.getClaims()).containsExactlyEntriesOf(expectedUserInfo.getClaims()); // OAuth2User expectedAuthentication = TestOAuth2AuthenticationTokens.authenticated(); json = asJson(expectedAuthentication); authentication = this.mapper.readValue(json, OAuth2AuthenticationToken.class); - assertThat(authentication.getAuthorities()) - .containsExactlyElementsOf(expectedAuthentication.getAuthorities()); - assertThat(authentication.getDetails()) - .isEqualTo(expectedAuthentication.getDetails()); - assertThat(authentication.isAuthenticated()) - .isEqualTo(expectedAuthentication.isAuthenticated()); + assertThat(authentication.getAuthorities()).containsExactlyElementsOf(expectedAuthentication.getAuthorities()); + assertThat(authentication.getDetails()).isEqualTo(expectedAuthentication.getDetails()); + assertThat(authentication.isAuthenticated()).isEqualTo(expectedAuthentication.isAuthenticated()); assertThat(authentication.getAuthorizedClientRegistrationId()) .isEqualTo(expectedAuthentication.getAuthorizedClientRegistrationId()); DefaultOAuth2User expectedOauth2User = (DefaultOAuth2User) expectedAuthentication.getPrincipal(); DefaultOAuth2User oauth2User = (DefaultOAuth2User) authentication.getPrincipal(); assertThat(oauth2User.getAuthorities().containsAll(expectedOauth2User.getAuthorities())).isTrue(); - assertThat(oauth2User.getAttributes()) - .containsExactlyEntriesOf(expectedOauth2User.getAttributes()); - assertThat(oauth2User.getName()) - .isEqualTo(expectedOauth2User.getName()); + assertThat(oauth2User.getAttributes()).containsExactlyEntriesOf(expectedOauth2User.getAttributes()); + assertThat(oauth2User.getName()).isEqualTo(expectedOauth2User.getName()); } @Test public void deserializeWhenRequiredAttributesOnlyThenDeserializes() throws Exception { DefaultOidcUser expectedPrincipal = TestOidcUsers.create(); expectedPrincipal = new DefaultOidcUser(expectedPrincipal.getAuthorities(), expectedPrincipal.getIdToken()); - OAuth2AuthenticationToken expectedAuthentication = new OAuth2AuthenticationToken( - expectedPrincipal, Collections.emptyList(), "registration-id"); + OAuth2AuthenticationToken expectedAuthentication = new OAuth2AuthenticationToken(expectedPrincipal, + Collections.emptyList(), "registration-id"); String json = asJson(expectedAuthentication); OAuth2AuthenticationToken authentication = this.mapper.readValue(json, OAuth2AuthenticationToken.class); assertThat(authentication.getAuthorities()).isEmpty(); - assertThat(authentication.getDetails()) - .isEqualTo(expectedAuthentication.getDetails()); - assertThat(authentication.isAuthenticated()) - .isEqualTo(expectedAuthentication.isAuthenticated()); + assertThat(authentication.getDetails()).isEqualTo(expectedAuthentication.getDetails()); + assertThat(authentication.isAuthenticated()).isEqualTo(expectedAuthentication.isAuthenticated()); assertThat(authentication.getAuthorizedClientRegistrationId()) .isEqualTo(expectedAuthentication.getAuthorizedClientRegistrationId()); DefaultOidcUser principal = (DefaultOidcUser) authentication.getPrincipal(); assertThat(principal.getAuthorities().containsAll(expectedPrincipal.getAuthorities())).isTrue(); - assertThat(principal.getAttributes()) - .containsExactlyEntriesOf(expectedPrincipal.getAttributes()); - assertThat(principal.getName()) - .isEqualTo(expectedPrincipal.getName()); + assertThat(principal.getAttributes()).containsExactlyEntriesOf(expectedPrincipal.getAttributes()); + assertThat(principal.getName()).isEqualTo(expectedPrincipal.getName()); OidcIdToken expectedIdToken = expectedPrincipal.getIdToken(); OidcIdToken idToken = principal.getIdToken(); - assertThat(idToken.getTokenValue()) - .isEqualTo(expectedIdToken.getTokenValue()); - assertThat(idToken.getIssuedAt()) - .isEqualTo(expectedIdToken.getIssuedAt()); - assertThat(idToken.getExpiresAt()) - .isEqualTo(expectedIdToken.getExpiresAt()); - assertThat(idToken.getClaims()) - .containsExactlyEntriesOf(expectedIdToken.getClaims()); + assertThat(idToken.getTokenValue()).isEqualTo(expectedIdToken.getTokenValue()); + assertThat(idToken.getIssuedAt()).isEqualTo(expectedIdToken.getIssuedAt()); + assertThat(idToken.getExpiresAt()).isEqualTo(expectedIdToken.getExpiresAt()); + assertThat(idToken.getClaims()).containsExactlyEntriesOf(expectedIdToken.getClaims()); assertThat(principal.getUserInfo()).isNull(); } private static String asJson(OAuth2AuthenticationToken authentication) { - String principalJson = authentication.getPrincipal() instanceof DefaultOidcUser ? - asJson((DefaultOidcUser) authentication.getPrincipal()) : - asJson((DefaultOAuth2User) authentication.getPrincipal()); + String principalJson = authentication.getPrincipal() instanceof DefaultOidcUser + ? asJson((DefaultOidcUser) authentication.getPrincipal()) + : asJson((DefaultOAuth2User) authentication.getPrincipal()); // @formatter:off return "{\n" + " \"@class\": \"org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken\",\n" + @@ -236,17 +214,16 @@ public class OAuth2AuthenticationTokenMixinTests { for (GrantedAuthority authority : authorities) { if (authority instanceof OidcUserAuthority) { oidcUserAuthority = (OidcUserAuthority) authority; - } else if (authority instanceof OAuth2UserAuthority) { + } + else if (authority instanceof OAuth2UserAuthority) { oauth2UserAuthority = (OAuth2UserAuthority) authority; - } else if (authority instanceof SimpleGrantedAuthority) { + } + else if (authority instanceof SimpleGrantedAuthority) { simpleAuthorities.add((SimpleGrantedAuthority) authority); } } - String authoritiesJson = oidcUserAuthority != null ? - asJson(oidcUserAuthority) : - oauth2UserAuthority != null ? - asJson(oauth2UserAuthority) : - ""; + String authoritiesJson = oidcUserAuthority != null ? asJson(oidcUserAuthority) + : oauth2UserAuthority != null ? asJson(oauth2UserAuthority) : ""; if (!simpleAuthorities.isEmpty()) { if (!StringUtils.isEmpty(authoritiesJson)) { authoritiesJson += ","; @@ -351,4 +328,5 @@ public class OAuth2AuthenticationTokenMixinTests { } return DecimalUtils.toBigDecimal(instant.getEpochSecond(), instant.getNano()).toString(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizationRequestMixinTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizationRequestMixinTests.java index 2630efeabc..32bd7413db 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizationRequestMixinTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizationRequestMixinTests.java @@ -40,7 +40,9 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class OAuth2AuthorizationRequestMixinTests { + private ObjectMapper mapper; + private OAuth2AuthorizationRequest.Builder authorizationRequestBuilder; @Before @@ -51,8 +53,7 @@ public class OAuth2AuthorizationRequestMixinTests { Map additionalParameters = new LinkedHashMap<>(); additionalParameters.put("param1", "value1"); additionalParameters.put("param2", "value2"); - this.authorizationRequestBuilder = TestOAuth2AuthorizationRequests.request() - .scope("read", "write") + this.authorizationRequestBuilder = TestOAuth2AuthorizationRequests.request().scope("read", "write") .additionalParameters(additionalParameters); } @@ -66,13 +67,8 @@ public class OAuth2AuthorizationRequestMixinTests { @Test public void serializeWhenRequiredAttributesOnlyThenSerializes() throws Exception { - OAuth2AuthorizationRequest authorizationRequest = - this.authorizationRequestBuilder - .scopes(null) - .state(null) - .additionalParameters(Map::clear) - .attributes(Map::clear) - .build(); + OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestBuilder.scopes(null).state(null) + .additionalParameters(Map::clear).attributes(Map::clear).build(); String expectedJson = asJson(authorizationRequest); String json = this.mapper.writeValueAsString(authorizationRequest); JSONAssert.assertEquals(expectedJson, json, true); @@ -92,18 +88,12 @@ public class OAuth2AuthorizationRequestMixinTests { OAuth2AuthorizationRequest authorizationRequest = this.mapper.readValue(json, OAuth2AuthorizationRequest.class); assertThat(authorizationRequest.getAuthorizationUri()) .isEqualTo(expectedAuthorizationRequest.getAuthorizationUri()); - assertThat(authorizationRequest.getGrantType()) - .isEqualTo(expectedAuthorizationRequest.getGrantType()); - assertThat(authorizationRequest.getResponseType()) - .isEqualTo(expectedAuthorizationRequest.getResponseType()); - assertThat(authorizationRequest.getClientId()) - .isEqualTo(expectedAuthorizationRequest.getClientId()); - assertThat(authorizationRequest.getRedirectUri()) - .isEqualTo(expectedAuthorizationRequest.getRedirectUri()); - assertThat(authorizationRequest.getScopes()) - .isEqualTo(expectedAuthorizationRequest.getScopes()); - assertThat(authorizationRequest.getState()) - .isEqualTo(expectedAuthorizationRequest.getState()); + assertThat(authorizationRequest.getGrantType()).isEqualTo(expectedAuthorizationRequest.getGrantType()); + assertThat(authorizationRequest.getResponseType()).isEqualTo(expectedAuthorizationRequest.getResponseType()); + assertThat(authorizationRequest.getClientId()).isEqualTo(expectedAuthorizationRequest.getClientId()); + assertThat(authorizationRequest.getRedirectUri()).isEqualTo(expectedAuthorizationRequest.getRedirectUri()); + assertThat(authorizationRequest.getScopes()).isEqualTo(expectedAuthorizationRequest.getScopes()); + assertThat(authorizationRequest.getState()).isEqualTo(expectedAuthorizationRequest.getState()); assertThat(authorizationRequest.getAdditionalParameters()) .containsExactlyEntriesOf(expectedAuthorizationRequest.getAdditionalParameters()); assertThat(authorizationRequest.getAuthorizationRequestUri()) @@ -114,25 +104,16 @@ public class OAuth2AuthorizationRequestMixinTests { @Test public void deserializeWhenRequiredAttributesOnlyThenDeserializes() throws Exception { - OAuth2AuthorizationRequest expectedAuthorizationRequest = - this.authorizationRequestBuilder - .scopes(null) - .state(null) - .additionalParameters(Map::clear) - .attributes(Map::clear) - .build(); + OAuth2AuthorizationRequest expectedAuthorizationRequest = this.authorizationRequestBuilder.scopes(null) + .state(null).additionalParameters(Map::clear).attributes(Map::clear).build(); String json = asJson(expectedAuthorizationRequest); OAuth2AuthorizationRequest authorizationRequest = this.mapper.readValue(json, OAuth2AuthorizationRequest.class); assertThat(authorizationRequest.getAuthorizationUri()) .isEqualTo(expectedAuthorizationRequest.getAuthorizationUri()); - assertThat(authorizationRequest.getGrantType()) - .isEqualTo(expectedAuthorizationRequest.getGrantType()); - assertThat(authorizationRequest.getResponseType()) - .isEqualTo(expectedAuthorizationRequest.getResponseType()); - assertThat(authorizationRequest.getClientId()) - .isEqualTo(expectedAuthorizationRequest.getClientId()); - assertThat(authorizationRequest.getRedirectUri()) - .isEqualTo(expectedAuthorizationRequest.getRedirectUri()); + assertThat(authorizationRequest.getGrantType()).isEqualTo(expectedAuthorizationRequest.getGrantType()); + assertThat(authorizationRequest.getResponseType()).isEqualTo(expectedAuthorizationRequest.getResponseType()); + assertThat(authorizationRequest.getClientId()).isEqualTo(expectedAuthorizationRequest.getClientId()); + assertThat(authorizationRequest.getRedirectUri()).isEqualTo(expectedAuthorizationRequest.getRedirectUri()); assertThat(authorizationRequest.getScopes()).isEmpty(); assertThat(authorizationRequest.getState()).isNull(); assertThat(authorizationRequest.getAdditionalParameters()).isEmpty(); @@ -146,8 +127,7 @@ public class OAuth2AuthorizationRequestMixinTests { OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestBuilder.build(); String json = asJson(authorizationRequest).replace("authorization_code", "client_credentials"); assertThatThrownBy(() -> this.mapper.readValue(json, OAuth2AuthorizationRequest.class)) - .isInstanceOf(JsonParseException.class) - .hasMessageContaining("Invalid authorizationGrantType"); + .isInstanceOf(JsonParseException.class).hasMessageContaining("Invalid authorizationGrantType"); } private static String asJson(OAuth2AuthorizationRequest authorizationRequest) { @@ -194,4 +174,5 @@ public class OAuth2AuthorizationRequestMixinTests { "}"; // @formatter:on } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizedClientMixinTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizedClientMixinTests.java index 893e99d5a0..71e4be37f8 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizedClientMixinTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/jackson2/OAuth2AuthorizedClientMixinTests.java @@ -46,10 +46,15 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class OAuth2AuthorizedClientMixinTests { + private ObjectMapper mapper; + private ClientRegistration.Builder clientRegistrationBuilder; + private OAuth2AccessToken accessToken; + private OAuth2RefreshToken refreshToken; + private String principalName; @Before @@ -60,8 +65,7 @@ public class OAuth2AuthorizedClientMixinTests { Map providerConfigurationMetadata = new LinkedHashMap<>(); providerConfigurationMetadata.put("config1", "value1"); providerConfigurationMetadata.put("config2", "value2"); - this.clientRegistrationBuilder = TestClientRegistrations.clientRegistration() - .scope("read", "write") + this.clientRegistrationBuilder = TestClientRegistrations.clientRegistration().scope("read", "write") .providerConfigurationMetadata(providerConfigurationMetadata); this.accessToken = TestOAuth2AccessTokens.scopes("read", "write"); this.refreshToken = TestOAuth2RefreshTokens.refreshToken(); @@ -70,8 +74,8 @@ public class OAuth2AuthorizedClientMixinTests { @Test public void serializeWhenMixinRegisteredThenSerializes() throws Exception { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistrationBuilder.build(), this.principalName, this.accessToken, this.refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistrationBuilder.build(), + this.principalName, this.accessToken, this.refreshToken); String expectedJson = asJson(authorizedClient); String json = this.mapper.writeValueAsString(authorizedClient); JSONAssert.assertEquals(expectedJson, json, true); @@ -79,17 +83,10 @@ public class OAuth2AuthorizedClientMixinTests { @Test public void serializeWhenRequiredAttributesOnlyThenSerializes() throws Exception { - ClientRegistration clientRegistration = - TestClientRegistrations.clientRegistration() - .clientSecret(null) - .clientName(null) - .userInfoUri(null) - .userNameAttributeName(null) - .jwkSetUri(null) - .issuerUri(null) - .build(); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - clientRegistration, this.principalName, TestOAuth2AccessTokens.noScopes()); + ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().clientSecret(null) + .clientName(null).userInfoUri(null).userNameAttributeName(null).jwkSetUri(null).issuerUri(null).build(); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(clientRegistration, this.principalName, + TestOAuth2AccessTokens.noScopes()); String expectedJson = asJson(authorizedClient); String json = this.mapper.writeValueAsString(authorizedClient); JSONAssert.assertEquals(expectedJson, json, true); @@ -97,8 +94,8 @@ public class OAuth2AuthorizedClientMixinTests { @Test public void deserializeWhenMixinNotRegisteredThenThrowJsonProcessingException() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistrationBuilder.build(), this.principalName, this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistrationBuilder.build(), + this.principalName, this.accessToken); String json = asJson(authorizedClient); assertThatThrownBy(() -> new ObjectMapper().readValue(json, OAuth2AuthorizedClient.class)) .isInstanceOf(JsonProcessingException.class); @@ -109,120 +106,88 @@ public class OAuth2AuthorizedClientMixinTests { ClientRegistration expectedClientRegistration = this.clientRegistrationBuilder.build(); OAuth2AccessToken expectedAccessToken = this.accessToken; OAuth2RefreshToken expectedRefreshToken = this.refreshToken; - OAuth2AuthorizedClient expectedAuthorizedClient = new OAuth2AuthorizedClient( - expectedClientRegistration, this.principalName, expectedAccessToken, expectedRefreshToken); + OAuth2AuthorizedClient expectedAuthorizedClient = new OAuth2AuthorizedClient(expectedClientRegistration, + this.principalName, expectedAccessToken, expectedRefreshToken); String json = asJson(expectedAuthorizedClient); OAuth2AuthorizedClient authorizedClient = this.mapper.readValue(json, OAuth2AuthorizedClient.class); ClientRegistration clientRegistration = authorizedClient.getClientRegistration(); - assertThat(clientRegistration.getRegistrationId()) - .isEqualTo(expectedClientRegistration.getRegistrationId()); - assertThat(clientRegistration.getClientId()) - .isEqualTo(expectedClientRegistration.getClientId()); - assertThat(clientRegistration.getClientSecret()) - .isEqualTo(expectedClientRegistration.getClientSecret()); + assertThat(clientRegistration.getRegistrationId()).isEqualTo(expectedClientRegistration.getRegistrationId()); + assertThat(clientRegistration.getClientId()).isEqualTo(expectedClientRegistration.getClientId()); + assertThat(clientRegistration.getClientSecret()).isEqualTo(expectedClientRegistration.getClientSecret()); assertThat(clientRegistration.getClientAuthenticationMethod()) .isEqualTo(expectedClientRegistration.getClientAuthenticationMethod()); assertThat(clientRegistration.getAuthorizationGrantType()) .isEqualTo(expectedClientRegistration.getAuthorizationGrantType()); - assertThat(clientRegistration.getRedirectUri()) - .isEqualTo(expectedClientRegistration.getRedirectUri()); - assertThat(clientRegistration.getScopes()) - .isEqualTo(expectedClientRegistration.getScopes()); + assertThat(clientRegistration.getRedirectUri()).isEqualTo(expectedClientRegistration.getRedirectUri()); + assertThat(clientRegistration.getScopes()).isEqualTo(expectedClientRegistration.getScopes()); assertThat(clientRegistration.getProviderDetails().getAuthorizationUri()) .isEqualTo(expectedClientRegistration.getProviderDetails().getAuthorizationUri()); assertThat(clientRegistration.getProviderDetails().getTokenUri()) .isEqualTo(expectedClientRegistration.getProviderDetails().getTokenUri()); assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUri()) .isEqualTo(expectedClientRegistration.getProviderDetails().getUserInfoEndpoint().getUri()); - assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod()) - .isEqualTo(expectedClientRegistration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod()); - assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName()) - .isEqualTo(expectedClientRegistration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName()); + assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod()).isEqualTo( + expectedClientRegistration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod()); + assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName()).isEqualTo( + expectedClientRegistration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName()); assertThat(clientRegistration.getProviderDetails().getJwkSetUri()) .isEqualTo(expectedClientRegistration.getProviderDetails().getJwkSetUri()); assertThat(clientRegistration.getProviderDetails().getIssuerUri()) .isEqualTo(expectedClientRegistration.getProviderDetails().getIssuerUri()); assertThat(clientRegistration.getProviderDetails().getConfigurationMetadata()) .containsExactlyEntriesOf(clientRegistration.getProviderDetails().getConfigurationMetadata()); - assertThat(clientRegistration.getClientName()) - .isEqualTo(expectedClientRegistration.getClientName()); - assertThat(authorizedClient.getPrincipalName()) - .isEqualTo(expectedAuthorizedClient.getPrincipalName()); + assertThat(clientRegistration.getClientName()).isEqualTo(expectedClientRegistration.getClientName()); + assertThat(authorizedClient.getPrincipalName()).isEqualTo(expectedAuthorizedClient.getPrincipalName()); OAuth2AccessToken accessToken = authorizedClient.getAccessToken(); - assertThat(accessToken.getTokenType()) - .isEqualTo(expectedAccessToken.getTokenType()); - assertThat(accessToken.getScopes()) - .isEqualTo(expectedAccessToken.getScopes()); - assertThat(accessToken.getTokenValue()) - .isEqualTo(expectedAccessToken.getTokenValue()); - assertThat(accessToken.getIssuedAt()) - .isEqualTo(expectedAccessToken.getIssuedAt()); - assertThat(accessToken.getExpiresAt()) - .isEqualTo(expectedAccessToken.getExpiresAt()); + assertThat(accessToken.getTokenType()).isEqualTo(expectedAccessToken.getTokenType()); + assertThat(accessToken.getScopes()).isEqualTo(expectedAccessToken.getScopes()); + assertThat(accessToken.getTokenValue()).isEqualTo(expectedAccessToken.getTokenValue()); + assertThat(accessToken.getIssuedAt()).isEqualTo(expectedAccessToken.getIssuedAt()); + assertThat(accessToken.getExpiresAt()).isEqualTo(expectedAccessToken.getExpiresAt()); OAuth2RefreshToken refreshToken = authorizedClient.getRefreshToken(); - assertThat(refreshToken.getTokenValue()) - .isEqualTo(expectedRefreshToken.getTokenValue()); - assertThat(refreshToken.getIssuedAt()) - .isEqualTo(expectedRefreshToken.getIssuedAt()); - assertThat(refreshToken.getExpiresAt()) - .isEqualTo(expectedRefreshToken.getExpiresAt()); + assertThat(refreshToken.getTokenValue()).isEqualTo(expectedRefreshToken.getTokenValue()); + assertThat(refreshToken.getIssuedAt()).isEqualTo(expectedRefreshToken.getIssuedAt()); + assertThat(refreshToken.getExpiresAt()).isEqualTo(expectedRefreshToken.getExpiresAt()); } @Test public void deserializeWhenRequiredAttributesOnlyThenDeserializes() throws Exception { - ClientRegistration expectedClientRegistration = - TestClientRegistrations.clientRegistration() - .clientSecret(null) - .clientName(null) - .userInfoUri(null) - .userNameAttributeName(null) - .jwkSetUri(null) - .issuerUri(null) - .build(); + ClientRegistration expectedClientRegistration = TestClientRegistrations.clientRegistration().clientSecret(null) + .clientName(null).userInfoUri(null).userNameAttributeName(null).jwkSetUri(null).issuerUri(null).build(); OAuth2AccessToken expectedAccessToken = TestOAuth2AccessTokens.noScopes(); - OAuth2AuthorizedClient expectedAuthorizedClient = new OAuth2AuthorizedClient( - expectedClientRegistration, this.principalName, expectedAccessToken); + OAuth2AuthorizedClient expectedAuthorizedClient = new OAuth2AuthorizedClient(expectedClientRegistration, + this.principalName, expectedAccessToken); String json = asJson(expectedAuthorizedClient); OAuth2AuthorizedClient authorizedClient = this.mapper.readValue(json, OAuth2AuthorizedClient.class); ClientRegistration clientRegistration = authorizedClient.getClientRegistration(); - assertThat(clientRegistration.getRegistrationId()) - .isEqualTo(expectedClientRegistration.getRegistrationId()); - assertThat(clientRegistration.getClientId()) - .isEqualTo(expectedClientRegistration.getClientId()); + assertThat(clientRegistration.getRegistrationId()).isEqualTo(expectedClientRegistration.getRegistrationId()); + assertThat(clientRegistration.getClientId()).isEqualTo(expectedClientRegistration.getClientId()); assertThat(clientRegistration.getClientSecret()).isEmpty(); assertThat(clientRegistration.getClientAuthenticationMethod()) .isEqualTo(expectedClientRegistration.getClientAuthenticationMethod()); assertThat(clientRegistration.getAuthorizationGrantType()) .isEqualTo(expectedClientRegistration.getAuthorizationGrantType()); - assertThat(clientRegistration.getRedirectUri()) - .isEqualTo(expectedClientRegistration.getRedirectUri()); - assertThat(clientRegistration.getScopes()) - .isEqualTo(expectedClientRegistration.getScopes()); + assertThat(clientRegistration.getRedirectUri()).isEqualTo(expectedClientRegistration.getRedirectUri()); + assertThat(clientRegistration.getScopes()).isEqualTo(expectedClientRegistration.getScopes()); assertThat(clientRegistration.getProviderDetails().getAuthorizationUri()) .isEqualTo(expectedClientRegistration.getProviderDetails().getAuthorizationUri()); assertThat(clientRegistration.getProviderDetails().getTokenUri()) .isEqualTo(expectedClientRegistration.getProviderDetails().getTokenUri()); assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUri()).isNull(); - assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod()) - .isEqualTo(expectedClientRegistration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod()); + assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod()).isEqualTo( + expectedClientRegistration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod()); assertThat(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName()).isNull(); assertThat(clientRegistration.getProviderDetails().getJwkSetUri()).isNull(); assertThat(clientRegistration.getProviderDetails().getIssuerUri()).isNull(); assertThat(clientRegistration.getProviderDetails().getConfigurationMetadata()).isEmpty(); - assertThat(clientRegistration.getClientName()) - .isEqualTo(clientRegistration.getRegistrationId()); - assertThat(authorizedClient.getPrincipalName()) - .isEqualTo(expectedAuthorizedClient.getPrincipalName()); + assertThat(clientRegistration.getClientName()).isEqualTo(clientRegistration.getRegistrationId()); + assertThat(authorizedClient.getPrincipalName()).isEqualTo(expectedAuthorizedClient.getPrincipalName()); OAuth2AccessToken accessToken = authorizedClient.getAccessToken(); - assertThat(accessToken.getTokenType()) - .isEqualTo(expectedAccessToken.getTokenType()); + assertThat(accessToken.getTokenType()).isEqualTo(expectedAccessToken.getTokenType()); assertThat(accessToken.getScopes()).isEmpty(); - assertThat(accessToken.getTokenValue()) - .isEqualTo(expectedAccessToken.getTokenValue()); - assertThat(accessToken.getIssuedAt()) - .isEqualTo(expectedAccessToken.getIssuedAt()); - assertThat(accessToken.getExpiresAt()) - .isEqualTo(expectedAccessToken.getExpiresAt()); + assertThat(accessToken.getTokenValue()).isEqualTo(expectedAccessToken.getTokenValue()); + assertThat(accessToken.getIssuedAt()).isEqualTo(expectedAccessToken.getIssuedAt()); + assertThat(accessToken.getExpiresAt()).isEqualTo(expectedAccessToken.getExpiresAt()); assertThat(authorizedClient.getRefreshToken()).isNull(); } @@ -333,4 +298,5 @@ public class OAuth2AuthorizedClientMixinTests { } return DecimalUtils.toBigDecimal(instant.getEpochSecond(), instant.getNano()).toString(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProviderTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProviderTests.java index 4c9fc9acbe..667a256004 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProviderTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProviderTests.java @@ -76,15 +76,26 @@ import static org.springframework.security.oauth2.jwt.TestJwts.jwt; * @author Mark Heckler */ public class OidcAuthorizationCodeAuthenticationProviderTests { + private ClientRegistration clientRegistration; + private OAuth2AuthorizationRequest authorizationRequest; + private OAuth2AuthorizationResponse authorizationResponse; + private OAuth2AuthorizationExchange authorizationExchange; + private OAuth2AccessTokenResponseClient accessTokenResponseClient; + private OAuth2AccessTokenResponse accessTokenResponse; + private OAuth2UserService userService; + private OidcAuthorizationCodeAuthenticationProvider authenticationProvider; - private StringKeyGenerator secureKeyGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96); + + private StringKeyGenerator secureKeyGenerator = new Base64StringKeyGenerator( + Base64.getUrlEncoder().withoutPadding(), 96); + private String nonceHash; @Rule @@ -101,19 +112,19 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { this.nonceHash = createHash(nonce); attributes.put(OidcParameterNames.NONCE, nonce); additionalParameters.put(OidcParameterNames.NONCE, this.nonceHash); - } catch (NoSuchAlgorithmException e) { } - this.authorizationRequest = request() - .scope("openid", "profile", "email") - .attributes(attributes) - .additionalParameters(additionalParameters) - .build(); + } + catch (NoSuchAlgorithmException e) { + } + this.authorizationRequest = request().scope("openid", "profile", "email").attributes(attributes) + .additionalParameters(additionalParameters).build(); this.authorizationResponse = success().build(); - this.authorizationExchange = new OAuth2AuthorizationExchange(this.authorizationRequest, this.authorizationResponse); + this.authorizationExchange = new OAuth2AuthorizationExchange(this.authorizationRequest, + this.authorizationResponse); this.accessTokenResponseClient = mock(OAuth2AccessTokenResponseClient.class); this.accessTokenResponse = this.accessTokenSuccessResponse(); this.userService = mock(OAuth2UserService.class); - this.authenticationProvider = - new OidcAuthorizationCodeAuthenticationProvider(this.accessTokenResponseClient, this.userService); + this.authenticationProvider = new OidcAuthorizationCodeAuthenticationProvider(this.accessTokenResponseClient, + this.userService); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(this.accessTokenResponse); } @@ -150,12 +161,11 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { @Test public void authenticateWhenAuthorizationRequestDoesNotContainOpenidScopeThenReturnNull() { OAuth2AuthorizationRequest authorizationRequest = request().scope("scope1").build(); - OAuth2AuthorizationExchange authorizationExchange = - new OAuth2AuthorizationExchange(authorizationRequest, this.authorizationResponse); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, + this.authorizationResponse); - OAuth2LoginAuthenticationToken authentication = - (OAuth2LoginAuthenticationToken) this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(this.clientRegistration, authorizationExchange)); + OAuth2LoginAuthenticationToken authentication = (OAuth2LoginAuthenticationToken) this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, authorizationExchange)); assertThat(authentication).isNull(); } @@ -166,11 +176,11 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { this.exception.expectMessage(containsString(OAuth2ErrorCodes.INVALID_SCOPE)); OAuth2AuthorizationResponse authorizationResponse = error().errorCode(OAuth2ErrorCodes.INVALID_SCOPE).build(); - OAuth2AuthorizationExchange authorizationExchange = - new OAuth2AuthorizationExchange(this.authorizationRequest, authorizationResponse); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(this.authorizationRequest, + authorizationResponse); - this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(this.clientRegistration, authorizationExchange)); + this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, authorizationExchange)); } @Test @@ -179,11 +189,11 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { this.exception.expectMessage(containsString("invalid_state_parameter")); OAuth2AuthorizationResponse authorizationResponse = success().state("89012").build(); - OAuth2AuthorizationExchange authorizationExchange = - new OAuth2AuthorizationExchange(this.authorizationRequest, authorizationResponse); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(this.authorizationRequest, + authorizationResponse); - this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(this.clientRegistration, authorizationExchange)); + this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, authorizationExchange)); } @Test @@ -191,14 +201,12 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { this.exception.expect(OAuth2AuthenticationException.class); this.exception.expectMessage(containsString("invalid_id_token")); - OAuth2AccessTokenResponse accessTokenResponse = - OAuth2AccessTokenResponse.withResponse(this.accessTokenSuccessResponse()) - .additionalParameters(Collections.emptyMap()) - .build(); + OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse + .withResponse(this.accessTokenSuccessResponse()).additionalParameters(Collections.emptyMap()).build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); - this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); + this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); } @Test @@ -208,8 +216,8 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { ClientRegistration clientRegistration = clientRegistration().jwkSetUri(null).build(); - this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(clientRegistration, this.authorizationExchange)); + this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(clientRegistration, this.authorizationExchange)); } @Test @@ -221,8 +229,8 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { when(jwtDecoder.decode(anyString())).thenThrow(new JwtException("ID Token Validation Error")); this.authenticationProvider.setJwtDecoderFactory(registration -> jwtDecoder); - this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); + this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); } @Test @@ -238,8 +246,8 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { claims.put(IdTokenClaimNames.NONCE, "invalid-nonce-hash"); this.setUpIdToken(claims); - this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); + this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); } @Test @@ -254,13 +262,11 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { OidcUser principal = mock(OidcUser.class); List authorities = AuthorityUtils.createAuthorityList("ROLE_USER"); - when(principal.getAuthorities()).thenAnswer( - (Answer>) invocation -> authorities); + when(principal.getAuthorities()).thenAnswer((Answer>) invocation -> authorities); when(this.userService.loadUser(any())).thenReturn(principal); - OAuth2LoginAuthenticationToken authentication = - (OAuth2LoginAuthenticationToken) this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); + OAuth2LoginAuthenticationToken authentication = (OAuth2LoginAuthenticationToken) this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); assertThat(authentication.isAuthenticated()).isTrue(); assertThat(authentication.getPrincipal()).isEqualTo(principal); @@ -284,19 +290,17 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { OidcUser principal = mock(OidcUser.class); List authorities = AuthorityUtils.createAuthorityList("ROLE_USER"); - when(principal.getAuthorities()).thenAnswer( - (Answer>) invocation -> authorities); + when(principal.getAuthorities()).thenAnswer((Answer>) invocation -> authorities); when(this.userService.loadUser(any())).thenReturn(principal); List mappedAuthorities = AuthorityUtils.createAuthorityList("ROLE_OIDC_USER"); GrantedAuthoritiesMapper authoritiesMapper = mock(GrantedAuthoritiesMapper.class); - when(authoritiesMapper.mapAuthorities(anyCollection())).thenAnswer( - (Answer>) invocation -> mappedAuthorities); + when(authoritiesMapper.mapAuthorities(anyCollection())) + .thenAnswer((Answer>) invocation -> mappedAuthorities); this.authenticationProvider.setAuthoritiesMapper(authoritiesMapper); - OAuth2LoginAuthenticationToken authentication = - (OAuth2LoginAuthenticationToken) this.authenticationProvider.authenticate( - new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); + OAuth2LoginAuthenticationToken authentication = (OAuth2LoginAuthenticationToken) this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); assertThat(authentication.getAuthorities()).isEqualTo(mappedAuthorities); } @@ -314,16 +318,15 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { OidcUser principal = mock(OidcUser.class); List authorities = AuthorityUtils.createAuthorityList("ROLE_USER"); - when(principal.getAuthorities()).thenAnswer( - (Answer>) invocation -> authorities); + when(principal.getAuthorities()).thenAnswer((Answer>) invocation -> authorities); ArgumentCaptor userRequestArgCaptor = ArgumentCaptor.forClass(OidcUserRequest.class); when(this.userService.loadUser(userRequestArgCaptor.capture())).thenReturn(principal); - this.authenticationProvider.authenticate(new OAuth2LoginAuthenticationToken( - this.clientRegistration, this.authorizationExchange)); + this.authenticationProvider + .authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange)); - assertThat(userRequestArgCaptor.getValue().getAdditionalParameters()).containsAllEntriesOf( - this.accessTokenResponse.getAdditionalParameters()); + assertThat(userRequestArgCaptor.getValue().getAdditionalParameters()) + .containsAllEntriesOf(this.accessTokenResponse.getAdditionalParameters()); } private void setUpIdToken(Map claims) { @@ -341,14 +344,10 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { additionalParameters.put("param2", "value2"); additionalParameters.put(OidcParameterNames.ID_TOKEN, "id-token"); - return OAuth2AccessTokenResponse - .withToken("access-token-1234") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(expiresAt.getEpochSecond()) - .scopes(scopes) - .refreshToken("refresh-token-1234") - .additionalParameters(additionalParameters) - .build(); + return OAuth2AccessTokenResponse.withToken("access-token-1234").tokenType(OAuth2AccessToken.TokenType.BEARER) + .expiresIn(expiresAt.getEpochSecond()).scopes(scopes).refreshToken("refresh-token-1234") + .additionalParameters(additionalParameters).build(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeReactiveAuthenticationManagerTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeReactiveAuthenticationManagerTests.java index 4faec435a1..ea88bf4460 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeReactiveAuthenticationManagerTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeReactiveAuthenticationManagerTests.java @@ -81,6 +81,7 @@ import static org.springframework.security.oauth2.jwt.TestJwts.jwt; */ @RunWith(MockitoJUnitRunner.class) public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { + @Mock private ReactiveOAuth2UserService userService; @@ -90,62 +91,59 @@ public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { @Mock private ReactiveJwtDecoder jwtDecoder; - private ClientRegistration.Builder registration = TestClientRegistrations.clientRegistration() - .scope("openid"); + private ClientRegistration.Builder registration = TestClientRegistrations.clientRegistration().scope("openid"); - private OAuth2AuthorizationResponse.Builder authorizationResponseBldr = OAuth2AuthorizationResponse - .success("code") + private OAuth2AuthorizationResponse.Builder authorizationResponseBldr = OAuth2AuthorizationResponse.success("code") .state("state"); private OidcIdToken idToken = TestOidcIdTokens.idToken().build(); private OidcAuthorizationCodeReactiveAuthenticationManager manager; - private StringKeyGenerator secureKeyGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96); + private StringKeyGenerator secureKeyGenerator = new Base64StringKeyGenerator( + Base64.getUrlEncoder().withoutPadding(), 96); private String nonceHash; @Before public void setup() { - this.manager = new OidcAuthorizationCodeReactiveAuthenticationManager(this.accessTokenResponseClient, this.userService); + this.manager = new OidcAuthorizationCodeReactiveAuthenticationManager(this.accessTokenResponseClient, + this.userService); } @Test public void constructorWhenNullAccessTokenResponseClientThenIllegalArgumentException() { this.accessTokenResponseClient = null; - assertThatThrownBy(() -> new OidcAuthorizationCodeReactiveAuthenticationManager(this.accessTokenResponseClient, this.userService)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> new OidcAuthorizationCodeReactiveAuthenticationManager(this.accessTokenResponseClient, + this.userService)).isInstanceOf(IllegalArgumentException.class); } @Test public void constructorWhenNullUserServiceThenIllegalArgumentException() { this.userService = null; - assertThatThrownBy(() -> new OidcAuthorizationCodeReactiveAuthenticationManager(this.accessTokenResponseClient, this.userService)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> new OidcAuthorizationCodeReactiveAuthenticationManager(this.accessTokenResponseClient, + this.userService)).isInstanceOf(IllegalArgumentException.class); } @Test public void setJwtDecoderFactoryWhenNullThenIllegalArgumentException() { - assertThatThrownBy(() -> this.manager.setJwtDecoderFactory(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.manager.setJwtDecoderFactory(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void setAuthoritiesMapperWhenAuthoritiesMapperIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.manager.setAuthoritiesMapper(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.manager.setAuthoritiesMapper(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void authenticateWhenNoSubscriptionThenDoesNothing() { - // we didn't do anything because it should cause a ClassCastException (as verified below) + // we didn't do anything because it should cause a ClassCastException (as verified + // below) TestingAuthenticationToken token = new TestingAuthenticationToken("a", "b"); - assertThatCode(()-> this.manager.authenticate(token)) - .doesNotThrowAnyException(); + assertThatCode(() -> this.manager.authenticate(token)).doesNotThrowAnyException(); - assertThatThrownBy(() -> this.manager.authenticate(token).block()) - .isInstanceOf(Throwable.class); + assertThatThrownBy(() -> this.manager.authenticate(token).block()).isInstanceOf(Throwable.class); } @Test @@ -156,9 +154,7 @@ public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { @Test public void authenticationWhenErrorThenOAuth2AuthenticationException() { - this.authorizationResponseBldr = OAuth2AuthorizationResponse - .error("error") - .state("state"); + this.authorizationResponseBldr = OAuth2AuthorizationResponse.error("error").state("state"); assertThatThrownBy(() -> this.manager.authenticate(loginToken()).block()) .isInstanceOf(OAuth2AuthenticationException.class); } @@ -173,8 +169,8 @@ public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { @Test public void authenticateWhenIdTokenValidationErrorThenOAuth2AuthenticationException() { OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .additionalParameters(Collections.singletonMap(OidcParameterNames.ID_TOKEN, this.idToken.getTokenValue())) + .tokenType(OAuth2AccessToken.TokenType.BEARER).additionalParameters( + Collections.singletonMap(OidcParameterNames.ID_TOKEN, this.idToken.getTokenValue())) .build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); @@ -189,8 +185,8 @@ public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { @Test public void authenticateWhenIdTokenInvalidNonceThenOAuth2AuthenticationException() { OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .additionalParameters(Collections.singletonMap(OidcParameterNames.ID_TOKEN, this.idToken.getTokenValue())) + .tokenType(OAuth2AccessToken.TokenType.BEARER).additionalParameters( + Collections.singletonMap(OidcParameterNames.ID_TOKEN, this.idToken.getTokenValue())) .build(); OAuth2AuthorizationCodeAuthenticationToken authorizationCodeAuthentication = loginToken(); @@ -207,15 +203,15 @@ public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { this.manager.setJwtDecoderFactory(c -> this.jwtDecoder); assertThatThrownBy(() -> this.manager.authenticate(authorizationCodeAuthentication).block()) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageContaining("[invalid_nonce]"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageContaining("[invalid_nonce]"); } @Test public void authenticationWhenOAuth2UserNotFoundThenEmpty() { OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") .tokenType(OAuth2AccessToken.TokenType.BEARER) - .additionalParameters(Collections.singletonMap(OidcParameterNames.ID_TOKEN, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.")) + .additionalParameters(Collections.singletonMap(OidcParameterNames.ID_TOKEN, + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.")) .build(); OAuth2AuthorizationCodeAuthenticationToken authorizationCodeAuthentication = loginToken(); @@ -237,8 +233,8 @@ public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { @Test public void authenticationWhenOAuth2UserFoundThenSuccess() { OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .additionalParameters(Collections.singletonMap(OidcParameterNames.ID_TOKEN, this.idToken.getTokenValue())) + .tokenType(OAuth2AccessToken.TokenType.BEARER).additionalParameters( + Collections.singletonMap(OidcParameterNames.ID_TOKEN, this.idToken.getTokenValue())) .build(); OAuth2AuthorizationCodeAuthenticationToken authorizationCodeAuthentication = loginToken(); @@ -256,7 +252,8 @@ public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { when(this.jwtDecoder.decode(any())).thenReturn(Mono.just(idToken)); this.manager.setJwtDecoderFactory(c -> this.jwtDecoder); - OAuth2LoginAuthenticationToken result = (OAuth2LoginAuthenticationToken) this.manager.authenticate(authorizationCodeAuthentication).block(); + OAuth2LoginAuthenticationToken result = (OAuth2LoginAuthenticationToken) this.manager + .authenticate(authorizationCodeAuthentication).block(); assertThat(result.getPrincipal()).isEqualTo(user); assertThat(result.getAuthorities()).containsOnlyElementsOf(user.getAuthorities()); @@ -267,9 +264,9 @@ public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { public void authenticationWhenRefreshTokenThenRefreshTokenInAuthorizedClient() { OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") .tokenType(OAuth2AccessToken.TokenType.BEARER) - .additionalParameters(Collections.singletonMap(OidcParameterNames.ID_TOKEN, this.idToken.getTokenValue())) - .refreshToken("refresh-token") - .build(); + .additionalParameters( + Collections.singletonMap(OidcParameterNames.ID_TOKEN, this.idToken.getTokenValue())) + .refreshToken("refresh-token").build(); OAuth2AuthorizationCodeAuthenticationToken authorizationCodeAuthentication = loginToken(); @@ -286,7 +283,8 @@ public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { when(this.jwtDecoder.decode(any())).thenReturn(Mono.just(idToken)); this.manager.setJwtDecoderFactory(c -> this.jwtDecoder); - OAuth2LoginAuthenticationToken result = (OAuth2LoginAuthenticationToken) this.manager.authenticate(authorizationCodeAuthentication).block(); + OAuth2LoginAuthenticationToken result = (OAuth2LoginAuthenticationToken) this.manager + .authenticate(authorizationCodeAuthentication).block(); assertThat(result.getPrincipal()).isEqualTo(user); assertThat(result.getAuthorities()).containsOnlyElementsOf(user.getAuthorities()); @@ -303,9 +301,7 @@ public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { additionalParameters.put("param1", "value1"); additionalParameters.put("param2", "value2"); OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .additionalParameters(additionalParameters) - .build(); + .tokenType(OAuth2AccessToken.TokenType.BEARER).additionalParameters(additionalParameters).build(); OAuth2AuthorizationCodeAuthenticationToken authorizationCodeAuthentication = loginToken(); @@ -333,8 +329,8 @@ public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { public void authenticateWhenAuthoritiesMapperSetThenReturnMappedAuthorities() { ClientRegistration clientRegistration = this.registration.build(); OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .additionalParameters(Collections.singletonMap(OidcParameterNames.ID_TOKEN, this.idToken.getTokenValue())) + .tokenType(OAuth2AccessToken.TokenType.BEARER).additionalParameters( + Collections.singletonMap(OidcParameterNames.ID_TOKEN, this.idToken.getTokenValue())) .build(); OAuth2AuthorizationCodeAuthenticationToken authorizationCodeAuthentication = loginToken(); @@ -346,7 +342,6 @@ public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { claims.put(IdTokenClaimNames.NONCE, this.nonceHash); Jwt idToken = jwt().claims(c -> c.putAll(claims)).build(); - when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); DefaultOidcUser user = new DefaultOidcUser(AuthorityUtils.createAuthorityList("ROLE_USER"), this.idToken); ArgumentCaptor userRequestArgCaptor = ArgumentCaptor.forClass(OidcUserRequest.class); @@ -354,8 +349,8 @@ public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { List mappedAuthorities = AuthorityUtils.createAuthorityList("ROLE_OIDC_USER"); GrantedAuthoritiesMapper authoritiesMapper = mock(GrantedAuthoritiesMapper.class); - when(authoritiesMapper.mapAuthorities(anyCollection())).thenAnswer( - (Answer>) invocation -> mappedAuthorities); + when(authoritiesMapper.mapAuthorities(anyCollection())) + .thenAnswer((Answer>) invocation -> mappedAuthorities); when(this.jwtDecoder.decode(any())).thenReturn(Mono.just(idToken)); this.manager.setJwtDecoderFactory(c -> this.jwtDecoder); this.manager.setAuthoritiesMapper(authoritiesMapper); @@ -374,22 +369,19 @@ public class OidcAuthorizationCodeReactiveAuthenticationManagerTests { this.nonceHash = createHash(nonce); attributes.put(OidcParameterNames.NONCE, nonce); additionalParameters.put(OidcParameterNames.NONCE, this.nonceHash); - } catch (NoSuchAlgorithmException e) { } - OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest - .authorizationCode() - .state("state") + } + catch (NoSuchAlgorithmException e) { + } + OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode().state("state") .clientId(clientRegistration.getClientId()) .authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()) - .redirectUri(clientRegistration.getRedirectUri()) - .scopes(clientRegistration.getScopes()) - .additionalParameters(additionalParameters) - .attributes(attributes) - .build(); + .redirectUri(clientRegistration.getRedirectUri()).scopes(clientRegistration.getScopes()) + .additionalParameters(additionalParameters).attributes(attributes).build(); OAuth2AuthorizationResponse authorizationResponse = this.authorizationResponseBldr - .redirectUri(clientRegistration.getRedirectUri()) - .build(); + .redirectUri(clientRegistration.getRedirectUri()).build(); OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse); return new OAuth2AuthorizationCodeAuthenticationToken(clientRegistration, authorizationExchange); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenDecoderFactoryTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenDecoderFactoryTests.java index 0b26a0d03f..3679a7797e 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenDecoderFactoryTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenDecoderFactoryTests.java @@ -44,8 +44,7 @@ import static org.mockito.Mockito.*; */ public class OidcIdTokenDecoderFactoryTests { - private ClientRegistration.Builder registration = TestClientRegistrations.clientRegistration() - .scope("openid"); + private ClientRegistration.Builder registration = TestClientRegistrations.clientRegistration().scope("openid"); private OidcIdTokenDecoderFactory idTokenDecoderFactory; @@ -56,7 +55,8 @@ public class OidcIdTokenDecoderFactoryTests { @Test public void createDefaultClaimTypeConvertersWhenCalledThenDefaultsAreCorrect() { - Map> claimTypeConverters = OidcIdTokenDecoderFactory.createDefaultClaimTypeConverters(); + Map> claimTypeConverters = OidcIdTokenDecoderFactory + .createDefaultClaimTypeConverters(); assertThat(claimTypeConverters).containsKey(IdTokenClaimNames.ISS); assertThat(claimTypeConverters).containsKey(IdTokenClaimNames.AUD); assertThat(claimTypeConverters).containsKey(IdTokenClaimNames.NONCE); @@ -97,9 +97,9 @@ public class OidcIdTokenDecoderFactoryTests { public void createDecoderWhenJwsAlgorithmDefaultAndJwkSetUriEmptyThenThrowOAuth2AuthenticationException() { assertThatThrownBy(() -> this.idTokenDecoderFactory.createDecoder(this.registration.jwkSetUri(null).build())) .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + - "for Client Registration: 'registration-id'. " + - "Check to ensure you have configured the JwkSet URI."); + .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + + "for Client Registration: 'registration-id'. " + + "Check to ensure you have configured the JwkSet URI."); } @Test @@ -107,9 +107,9 @@ public class OidcIdTokenDecoderFactoryTests { this.idTokenDecoderFactory.setJwsAlgorithmResolver(clientRegistration -> SignatureAlgorithm.ES256); assertThatThrownBy(() -> this.idTokenDecoderFactory.createDecoder(this.registration.jwkSetUri(null).build())) .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + - "for Client Registration: 'registration-id'. " + - "Check to ensure you have configured the JwkSet URI."); + .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + + "for Client Registration: 'registration-id'. " + + "Check to ensure you have configured the JwkSet URI."); } @Test @@ -117,9 +117,9 @@ public class OidcIdTokenDecoderFactoryTests { this.idTokenDecoderFactory.setJwsAlgorithmResolver(clientRegistration -> MacAlgorithm.HS256); assertThatThrownBy(() -> this.idTokenDecoderFactory.createDecoder(this.registration.clientSecret(null).build())) .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + - "for Client Registration: 'registration-id'. " + - "Check to ensure you have configured the client secret."); + .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + + "for Client Registration: 'registration-id'. " + + "Check to ensure you have configured the client secret."); } @Test @@ -127,15 +127,14 @@ public class OidcIdTokenDecoderFactoryTests { this.idTokenDecoderFactory.setJwsAlgorithmResolver(clientRegistration -> null); assertThatThrownBy(() -> this.idTokenDecoderFactory.createDecoder(this.registration.build())) .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + - "for Client Registration: 'registration-id'. " + - "Check to ensure you have configured a valid JWS Algorithm: 'null'"); + .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + + "for Client Registration: 'registration-id'. " + + "Check to ensure you have configured a valid JWS Algorithm: 'null'"); } @Test public void createDecoderWhenClientRegistrationValidThenReturnDecoder() { - assertThat(this.idTokenDecoderFactory.createDecoder(this.registration.build())) - .isNotNull(); + assertThat(this.idTokenDecoderFactory.createDecoder(this.registration.build())).isNotNull(); } @Test @@ -160,8 +159,7 @@ public class OidcIdTokenDecoderFactoryTests { ClientRegistration clientRegistration = this.registration.build(); - when(customJwsAlgorithmResolver.apply(same(clientRegistration))) - .thenReturn(MacAlgorithm.HS256); + when(customJwsAlgorithmResolver.apply(same(clientRegistration))).thenReturn(MacAlgorithm.HS256); this.idTokenDecoderFactory.createDecoder(clientRegistration); @@ -170,7 +168,8 @@ public class OidcIdTokenDecoderFactoryTests { @Test public void createDecoderWhenCustomClaimTypeConverterFactorySetThenApplied() { - Function, Map>> customClaimTypeConverterFactory = mock(Function.class); + Function, Map>> customClaimTypeConverterFactory = mock( + Function.class); this.idTokenDecoderFactory.setClaimTypeConverterFactory(customClaimTypeConverterFactory); ClientRegistration clientRegistration = this.registration.build(); @@ -182,4 +181,5 @@ public class OidcIdTokenDecoderFactoryTests { verify(customClaimTypeConverterFactory).apply(same(clientRegistration)); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenValidatorTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenValidatorTests.java index 098fe8d1f2..e813ac2da7 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenValidatorTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenValidatorTests.java @@ -41,11 +41,17 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @since 5.1 */ public class OidcIdTokenValidatorTests { + private ClientRegistration.Builder registration = TestClientRegistrations.clientRegistration(); + private Map headers = new HashMap<>(); + private Map claims = new HashMap<>(); + private Instant issuedAt = Instant.now(); + private Instant expiresAt = this.issuedAt.plusSeconds(3600); + private Duration clockSkew = Duration.ofSeconds(60); @Before @@ -61,12 +67,10 @@ public class OidcIdTokenValidatorTests { assertThat(this.validateIdToken()).isEmpty(); } - @Test public void setClockSkewWhenNullThenThrowIllegalArgumentException() { OidcIdTokenValidator idTokenValidator = new OidcIdTokenValidator(this.registration.build()); - assertThatThrownBy(() -> idTokenValidator.setClockSkew(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> idTokenValidator.setClockSkew(null)).isInstanceOf(IllegalArgumentException.class); } @Test @@ -79,38 +83,33 @@ public class OidcIdTokenValidatorTests { @Test public void setClockWhenNullThenThrowIllegalArgumentException() { OidcIdTokenValidator idTokenValidator = new OidcIdTokenValidator(this.registration.build()); - assertThatThrownBy(() -> idTokenValidator.setClock(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> idTokenValidator.setClock(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void validateWhenIssuerNullThenHasErrors() { this.claims.remove(IdTokenClaimNames.ISS); - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.contains(IdTokenClaimNames.ISS)); } @Test public void validateWhenMetadataIssuerMismatchThenHasErrors() { /* - * When the issuer is set in the provider metadata, and it does not match the issuer in the ID Token, - * the validation must fail + * When the issuer is set in the provider metadata, and it does not match the + * issuer in the ID Token, the validation must fail */ this.registration = this.registration.issuerUri("https://somethingelse.com"); - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.contains(IdTokenClaimNames.ISS)); } @Test public void validateWhenMetadataIssuerMatchThenNoErrors() { /* - * When the issuer is set in the provider metadata, and it does match the issuer in the ID Token, - * the validation must succeed + * When the issuer is set in the provider metadata, and it does match the issuer + * in the ID Token, the validation must succeed */ this.registration = this.registration.issuerUri("https://example.com"); @@ -120,54 +119,42 @@ public class OidcIdTokenValidatorTests { @Test public void validateWhenSubNullThenHasErrors() { this.claims.remove(IdTokenClaimNames.SUB); - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.contains(IdTokenClaimNames.SUB)); } @Test public void validateWhenAudNullThenHasErrors() { this.claims.remove(IdTokenClaimNames.AUD); - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.contains(IdTokenClaimNames.AUD)); } @Test public void validateWhenIssuedAtNullThenHasErrors() { this.issuedAt = null; - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.contains(IdTokenClaimNames.IAT)); } @Test public void validateWhenExpiresAtNullThenHasErrors() { this.expiresAt = null; - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.contains(IdTokenClaimNames.EXP)); } @Test public void validateWhenAudMultipleAndAzpNullThenHasErrors() { this.claims.put(IdTokenClaimNames.AUD, Arrays.asList("client-id", "other")); - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.contains(IdTokenClaimNames.AZP)); } @Test public void validateWhenAzpNotClientIdThenHasErrors() { this.claims.put(IdTokenClaimNames.AZP, "other"); - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.contains(IdTokenClaimNames.AZP)); } @@ -182,18 +169,14 @@ public class OidcIdTokenValidatorTests { public void validateWhenMultipleAudAzpNotClientIdThenHasErrors() { this.claims.put(IdTokenClaimNames.AUD, Arrays.asList("client-id-1", "client-id-2")); this.claims.put(IdTokenClaimNames.AZP, "other-client"); - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.contains(IdTokenClaimNames.AZP)); } @Test public void validateWhenAudNotClientIdThenHasErrors() { this.claims.put(IdTokenClaimNames.AUD, Collections.singletonList("other-client")); - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.contains(IdTokenClaimNames.AUD)); } @@ -210,9 +193,7 @@ public class OidcIdTokenValidatorTests { this.issuedAt = Instant.now().minus(Duration.ofSeconds(60)); this.expiresAt = this.issuedAt.plus(Duration.ofSeconds(30)); this.clockSkew = Duration.ofSeconds(0); - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.contains(IdTokenClaimNames.EXP)); } @@ -229,9 +210,7 @@ public class OidcIdTokenValidatorTests { this.issuedAt = Instant.now().plus(Duration.ofMinutes(1)); this.expiresAt = this.issuedAt.plus(Duration.ofSeconds(60)); this.clockSkew = Duration.ofMinutes(0); - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.contains(IdTokenClaimNames.IAT)); } @@ -240,9 +219,7 @@ public class OidcIdTokenValidatorTests { this.issuedAt = Instant.now().minus(Duration.ofSeconds(10)); this.expiresAt = this.issuedAt.plus(Duration.ofSeconds(5)); this.clockSkew = Duration.ofSeconds(0); - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.contains(IdTokenClaimNames.EXP)); } @@ -252,9 +229,7 @@ public class OidcIdTokenValidatorTests { this.claims.remove(IdTokenClaimNames.AUD); this.issuedAt = null; this.expiresAt = null; - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.contains(IdTokenClaimNames.SUB)) .allMatch(msg -> msg.contains(IdTokenClaimNames.AUD)) .allMatch(msg -> msg.contains(IdTokenClaimNames.IAT)) @@ -265,21 +240,16 @@ public class OidcIdTokenValidatorTests { public void validateFormatError() { this.claims.remove(IdTokenClaimNames.SUB); this.claims.remove(IdTokenClaimNames.AUD); - assertThat(this.validateIdToken()) - .hasSize(1) - .extracting(OAuth2Error::getDescription) + assertThat(this.validateIdToken()).hasSize(1).extracting(OAuth2Error::getDescription) .allMatch(msg -> msg.equals("The ID Token contains invalid claims: {sub=null, aud=null}")); } private Collection validateIdToken() { - Jwt idToken = Jwt.withTokenValue("token") - .issuedAt(this.issuedAt) - .expiresAt(this.expiresAt) - .headers(h -> h.putAll(this.headers)) - .claims(c -> c.putAll(this.claims)) - .build(); + Jwt idToken = Jwt.withTokenValue("token").issuedAt(this.issuedAt).expiresAt(this.expiresAt) + .headers(h -> h.putAll(this.headers)).claims(c -> c.putAll(this.claims)).build(); OidcIdTokenValidator validator = new OidcIdTokenValidator(this.registration.build()); validator.setClockSkew(this.clockSkew); return validator.validate(idToken).getErrors(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/ReactiveOidcIdTokenDecoderFactoryTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/ReactiveOidcIdTokenDecoderFactoryTests.java index bb2122a5cc..dc9f2b0513 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/ReactiveOidcIdTokenDecoderFactoryTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/authentication/ReactiveOidcIdTokenDecoderFactoryTests.java @@ -44,8 +44,7 @@ import static org.mockito.Mockito.*; */ public class ReactiveOidcIdTokenDecoderFactoryTests { - private ClientRegistration.Builder registration = TestClientRegistrations.clientRegistration() - .scope("openid"); + private ClientRegistration.Builder registration = TestClientRegistrations.clientRegistration().scope("openid"); private ReactiveOidcIdTokenDecoderFactory idTokenDecoderFactory; @@ -56,7 +55,8 @@ public class ReactiveOidcIdTokenDecoderFactoryTests { @Test public void createDefaultClaimTypeConvertersWhenCalledThenDefaultsAreCorrect() { - Map> claimTypeConverters = ReactiveOidcIdTokenDecoderFactory.createDefaultClaimTypeConverters(); + Map> claimTypeConverters = ReactiveOidcIdTokenDecoderFactory + .createDefaultClaimTypeConverters(); assertThat(claimTypeConverters).containsKey(IdTokenClaimNames.ISS); assertThat(claimTypeConverters).containsKey(IdTokenClaimNames.AUD); assertThat(claimTypeConverters).containsKey(IdTokenClaimNames.NONCE); @@ -97,9 +97,9 @@ public class ReactiveOidcIdTokenDecoderFactoryTests { public void createDecoderWhenJwsAlgorithmDefaultAndJwkSetUriEmptyThenThrowOAuth2AuthenticationException() { assertThatThrownBy(() -> this.idTokenDecoderFactory.createDecoder(this.registration.jwkSetUri(null).build())) .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + - "for Client Registration: 'registration-id'. " + - "Check to ensure you have configured the JwkSet URI."); + .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + + "for Client Registration: 'registration-id'. " + + "Check to ensure you have configured the JwkSet URI."); } @Test @@ -107,9 +107,9 @@ public class ReactiveOidcIdTokenDecoderFactoryTests { this.idTokenDecoderFactory.setJwsAlgorithmResolver(clientRegistration -> SignatureAlgorithm.ES256); assertThatThrownBy(() -> this.idTokenDecoderFactory.createDecoder(this.registration.jwkSetUri(null).build())) .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + - "for Client Registration: 'registration-id'. " + - "Check to ensure you have configured the JwkSet URI."); + .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + + "for Client Registration: 'registration-id'. " + + "Check to ensure you have configured the JwkSet URI."); } @Test @@ -117,9 +117,9 @@ public class ReactiveOidcIdTokenDecoderFactoryTests { this.idTokenDecoderFactory.setJwsAlgorithmResolver(clientRegistration -> MacAlgorithm.HS256); assertThatThrownBy(() -> this.idTokenDecoderFactory.createDecoder(this.registration.clientSecret(null).build())) .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + - "for Client Registration: 'registration-id'. " + - "Check to ensure you have configured the client secret."); + .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + + "for Client Registration: 'registration-id'. " + + "Check to ensure you have configured the client secret."); } @Test @@ -127,15 +127,14 @@ public class ReactiveOidcIdTokenDecoderFactoryTests { this.idTokenDecoderFactory.setJwsAlgorithmResolver(clientRegistration -> null); assertThatThrownBy(() -> this.idTokenDecoderFactory.createDecoder(this.registration.build())) .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + - "for Client Registration: 'registration-id'. " + - "Check to ensure you have configured a valid JWS Algorithm: 'null'"); + .hasMessage("[missing_signature_verifier] Failed to find a Signature Verifier " + + "for Client Registration: 'registration-id'. " + + "Check to ensure you have configured a valid JWS Algorithm: 'null'"); } @Test public void createDecoderWhenClientRegistrationValidThenReturnDecoder() { - assertThat(this.idTokenDecoderFactory.createDecoder(this.registration.build())) - .isNotNull(); + assertThat(this.idTokenDecoderFactory.createDecoder(this.registration.build())).isNotNull(); } @Test @@ -160,8 +159,7 @@ public class ReactiveOidcIdTokenDecoderFactoryTests { ClientRegistration clientRegistration = this.registration.build(); - when(customJwsAlgorithmResolver.apply(same(clientRegistration))) - .thenReturn(MacAlgorithm.HS256); + when(customJwsAlgorithmResolver.apply(same(clientRegistration))).thenReturn(MacAlgorithm.HS256); this.idTokenDecoderFactory.createDecoder(clientRegistration); @@ -170,7 +168,8 @@ public class ReactiveOidcIdTokenDecoderFactoryTests { @Test public void createDecoderWhenCustomClaimTypeConverterFactorySetThenApplied() { - Function, Map>> customClaimTypeConverterFactory = mock(Function.class); + Function, Map>> customClaimTypeConverterFactory = mock( + Function.class); this.idTokenDecoderFactory.setClaimTypeConverterFactory(customClaimTypeConverterFactory); ClientRegistration clientRegistration = this.registration.build(); @@ -182,4 +181,5 @@ public class ReactiveOidcIdTokenDecoderFactoryTests { verify(customClaimTypeConverterFactory).apply(same(clientRegistration)); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcReactiveOAuth2UserServiceTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcReactiveOAuth2UserServiceTests.java index e84e9f38dd..52c101f0c9 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcReactiveOAuth2UserServiceTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcReactiveOAuth2UserServiceTests.java @@ -69,6 +69,7 @@ import static org.springframework.security.oauth2.core.oidc.TestOidcIdTokens.idT */ @RunWith(MockitoJUnitRunner.class) public class OidcReactiveOAuth2UserServiceTests { + @Mock private ReactiveOAuth2UserService oauth2UserService; @@ -77,11 +78,8 @@ public class OidcReactiveOAuth2UserServiceTests { private OidcIdToken idToken = idToken().build(); - private OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "token", - Instant.now(), - Instant.now().plus(Duration.ofDays(1)), - Collections.singleton("read:user")); + private OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token", + Instant.now(), Instant.now().plus(Duration.ofDays(1)), Collections.singleton("read:user")); private OidcReactiveOAuth2UserService userService = new OidcReactiveOAuth2UserService(); @@ -92,7 +90,8 @@ public class OidcReactiveOAuth2UserServiceTests { @Test public void createDefaultClaimTypeConvertersWhenCalledThenDefaultsAreCorrect() { - Map> claimTypeConverters = OidcReactiveOAuth2UserService.createDefaultClaimTypeConverters(); + Map> claimTypeConverters = OidcReactiveOAuth2UserService + .createDefaultClaimTypeConverters(); assertThat(claimTypeConverters).containsKey(StandardClaimNames.EMAIL_VERIFIED); assertThat(claimTypeConverters).containsKey(StandardClaimNames.PHONE_NUMBER_VERIFIED); assertThat(claimTypeConverters).containsKey(StandardClaimNames.UPDATED_AT); @@ -124,11 +123,12 @@ public class OidcReactiveOAuth2UserServiceTests { @Test public void loadUserWhenOAuth2UserSubjectNullThenOAuth2AuthenticationException() { - OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), Collections.singletonMap("user", "rob"), "user"); + OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), + Collections.singletonMap("user", "rob"), "user"); when(this.oauth2UserService.loadUser(any())).thenReturn(Mono.just(oauth2User)); assertThatCode(() -> this.userService.loadUser(userRequest()).block()) - .isInstanceOf(OAuth2AuthenticationException.class); + .isInstanceOf(OAuth2AuthenticationException.class); } @Test @@ -136,8 +136,8 @@ public class OidcReactiveOAuth2UserServiceTests { Map attributes = new HashMap<>(); attributes.put(StandardClaimNames.SUB, "not-equal"); attributes.put("user", "rob"); - OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), - attributes, "user"); + OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), attributes, + "user"); when(this.oauth2UserService.loadUser(any())).thenReturn(Mono.just(oauth2User)); assertThatCode(() -> this.userService.loadUser(userRequest()).block()) @@ -149,8 +149,8 @@ public class OidcReactiveOAuth2UserServiceTests { Map attributes = new HashMap<>(); attributes.put(StandardClaimNames.SUB, "subject"); attributes.put("user", "rob"); - OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), - attributes, "user"); + OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), attributes, + "user"); when(this.oauth2UserService.loadUser(any())).thenReturn(Mono.just(oauth2User)); assertThat(this.userService.loadUser(userRequest()).block().getUserInfo()).isNotNull(); @@ -162,8 +162,8 @@ public class OidcReactiveOAuth2UserServiceTests { Map attributes = new HashMap<>(); attributes.put(StandardClaimNames.SUB, "subject"); attributes.put("user", "rob"); - OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), - attributes, "user"); + OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), attributes, + "user"); when(this.oauth2UserService.loadUser(any())).thenReturn(Mono.just(oauth2User)); assertThat(this.userService.loadUser(userRequest()).block().getName()).isEqualTo("rob"); @@ -174,13 +174,14 @@ public class OidcReactiveOAuth2UserServiceTests { Map attributes = new HashMap<>(); attributes.put(StandardClaimNames.SUB, "subject"); attributes.put("user", "rob"); - OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), - attributes, "user"); + OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), attributes, + "user"); when(this.oauth2UserService.loadUser(any())).thenReturn(Mono.just(oauth2User)); OidcUserRequest userRequest = userRequest(); - Function, Map>> customClaimTypeConverterFactory = mock(Function.class); + Function, Map>> customClaimTypeConverterFactory = mock( + Function.class); this.userService.setClaimTypeConverterFactory(customClaimTypeConverterFactory); when(customClaimTypeConverterFactory.apply(same(userRequest.getClientRegistration()))) @@ -194,8 +195,8 @@ public class OidcReactiveOAuth2UserServiceTests { @Test public void loadUserWhenTokenContainsScopesThenIndividualScopeAuthorities() { OidcReactiveOAuth2UserService userService = new OidcReactiveOAuth2UserService(); - OidcUserRequest request = new OidcUserRequest( - clientRegistration().build(), scopes("message:read", "message:write"), idToken().build()); + OidcUserRequest request = new OidcUserRequest(clientRegistration().build(), + scopes("message:read", "message:write"), idToken().build()); OidcUser user = userService.loadUser(request).block(); assertThat(user.getAuthorities()).hasSize(3); @@ -208,8 +209,7 @@ public class OidcReactiveOAuth2UserServiceTests { @Test public void loadUserWhenTokenDoesNotContainScopesThenNoScopeAuthorities() { OidcReactiveOAuth2UserService userService = new OidcReactiveOAuth2UserService(); - OidcUserRequest request = new OidcUserRequest( - clientRegistration().build(), noScopes(), idToken().build()); + OidcUserRequest request = new OidcUserRequest(clientRegistration().build(), noScopes(), idToken().build()); OidcUser user = userService.loadUser(request).block(); assertThat(user.getAuthorities()).hasSize(1); @@ -220,4 +220,5 @@ public class OidcReactiveOAuth2UserServiceTests { private OidcUserRequest userRequest() { return new OidcUserRequest(this.registration.build(), this.accessToken, this.idToken); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequestTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequestTests.java index b1e2b5481b..88f668af69 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequestTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequestTests.java @@ -39,17 +39,20 @@ import static org.springframework.security.oauth2.core.oidc.TestOidcIdTokens.idT * @author Joe Grandja */ public class OidcUserRequestTests { + private ClientRegistration clientRegistration; + private OAuth2AccessToken accessToken; + private OidcIdToken idToken; + private Map additionalParameters; @Before public void setUp() { this.clientRegistration = clientRegistration().build(); - this.accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "access-token-1234", Instant.now(), Instant.now().plusSeconds(60), - new LinkedHashSet<>(Arrays.asList("scope1", "scope2"))); + this.accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token-1234", Instant.now(), + Instant.now().plusSeconds(60), new LinkedHashSet<>(Arrays.asList("scope1", "scope2"))); this.idToken = idToken().authorizedParty(this.clientRegistration.getClientId()).build(); this.additionalParameters = new HashMap<>(); this.additionalParameters.put("param1", "value1"); @@ -76,12 +79,13 @@ public class OidcUserRequestTests { @Test public void constructorWhenAllParametersProvidedAndValidThenCreated() { - OidcUserRequest userRequest = new OidcUserRequest( - this.clientRegistration, this.accessToken, this.idToken, this.additionalParameters); + OidcUserRequest userRequest = new OidcUserRequest(this.clientRegistration, this.accessToken, this.idToken, + this.additionalParameters); assertThat(userRequest.getClientRegistration()).isEqualTo(this.clientRegistration); assertThat(userRequest.getAccessToken()).isEqualTo(this.accessToken); assertThat(userRequest.getIdToken()).isEqualTo(this.idToken); assertThat(userRequest.getAdditionalParameters()).containsAllEntriesOf(this.additionalParameters); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequestUtilsTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequestUtilsTests.java index f5270813f7..79fc3ad856 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequestUtilsTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserRequestUtilsTests.java @@ -36,15 +36,13 @@ import static org.assertj.core.api.Assertions.assertThat; * @since 5.1 */ public class OidcUserRequestUtilsTests { + private ClientRegistration.Builder registration = TestClientRegistrations.clientRegistration(); OidcIdToken idToken = TestOidcIdTokens.idToken().build(); - OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "token", - Instant.now(), - Instant.now().plus(Duration.ofDays(1)), - Collections.singleton("read:user")); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token", Instant.now(), + Instant.now().plus(Duration.ofDays(1)), Collections.singleton("read:user")); @Test public void shouldRetrieveUserInfoWhenEndpointDefinedAndScopesOverlapThenTrue() { @@ -75,4 +73,5 @@ public class OidcUserRequestUtilsTests { private OidcUserRequest userRequest() { return new OidcUserRequest(this.registration.build(), this.accessToken, this.idToken); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserServiceTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserServiceTests.java index 8a5a495d7a..9f3c338456 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserServiceTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserServiceTests.java @@ -69,10 +69,15 @@ import static org.springframework.security.oauth2.core.oidc.TestOidcIdTokens.idT * @author Joe Grandja */ public class OidcUserServiceTests { + private ClientRegistration.Builder clientRegistrationBuilder; + private OAuth2AccessToken accessToken; + private OidcIdToken idToken; + private OidcUserService userService = new OidcUserService(); + private MockWebServer server; @Rule @@ -82,8 +87,7 @@ public class OidcUserServiceTests { public void setup() throws Exception { this.server = new MockWebServer(); this.server.start(); - this.clientRegistrationBuilder = clientRegistration() - .userInfoUri(null) + this.clientRegistrationBuilder = clientRegistration().userInfoUri(null) .userInfoAuthenticationMethod(AuthenticationMethod.HEADER) .userNameAttributeName(StandardClaimNames.SUB); @@ -141,116 +145,92 @@ public class OidcUserServiceTests { @Test public void loadUserWhenUserInfoUriIsNullThenUserInfoEndpointNotRequested() { - OidcUser user = this.userService.loadUser( - new OidcUserRequest(this.clientRegistrationBuilder.build(), this.accessToken, this.idToken)); + OidcUser user = this.userService + .loadUser(new OidcUserRequest(this.clientRegistrationBuilder.build(), this.accessToken, this.idToken)); assertThat(user.getUserInfo()).isNull(); } @Test public void loadUserWhenNonStandardScopesAuthorizedThenUserInfoEndpointNotRequested() { - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri("https://provider.com/user").build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri("https://provider.com/user") + .build(); this.accessToken = scopes("scope1", "scope2"); - OidcUser user = this.userService.loadUser( - new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); + OidcUser user = this.userService + .loadUser(new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); assertThat(user.getUserInfo()).isNull(); } // gh-6886 @Test public void loadUserWhenNonStandardScopesAuthorizedAndAccessibleScopesMatchThenUserInfoEndpointRequested() { - String userInfoResponse = "{\n" + - " \"sub\": \"subject1\",\n" + - " \"name\": \"first last\",\n" + - " \"given_name\": \"first\",\n" + - " \"family_name\": \"last\",\n" + - " \"preferred_username\": \"user1\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"sub\": \"subject1\",\n" + " \"name\": \"first last\",\n" + + " \"given_name\": \"first\",\n" + " \"family_name\": \"last\",\n" + + " \"preferred_username\": \"user1\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri).build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); this.accessToken = scopes("scope1", "scope2"); this.userService.setAccessibleScopes(Collections.singleton("scope2")); - OidcUser user = this.userService.loadUser( - new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); + OidcUser user = this.userService + .loadUser(new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); assertThat(user.getUserInfo()).isNotNull(); } // gh-6886 @Test public void loadUserWhenNonStandardScopesAuthorizedAndAccessibleScopesEmptyThenUserInfoEndpointRequested() { - String userInfoResponse = "{\n" + - " \"sub\": \"subject1\",\n" + - " \"name\": \"first last\",\n" + - " \"given_name\": \"first\",\n" + - " \"family_name\": \"last\",\n" + - " \"preferred_username\": \"user1\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"sub\": \"subject1\",\n" + " \"name\": \"first last\",\n" + + " \"given_name\": \"first\",\n" + " \"family_name\": \"last\",\n" + + " \"preferred_username\": \"user1\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri).build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); this.accessToken = scopes("scope1", "scope2"); this.userService.setAccessibleScopes(Collections.emptySet()); - OidcUser user = this.userService.loadUser( - new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); + OidcUser user = this.userService + .loadUser(new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); assertThat(user.getUserInfo()).isNotNull(); } // gh-6886 @Test public void loadUserWhenStandardScopesAuthorizedThenUserInfoEndpointRequested() { - String userInfoResponse = "{\n" + - " \"sub\": \"subject1\",\n" + - " \"name\": \"first last\",\n" + - " \"given_name\": \"first\",\n" + - " \"family_name\": \"last\",\n" + - " \"preferred_username\": \"user1\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"sub\": \"subject1\",\n" + " \"name\": \"first last\",\n" + + " \"given_name\": \"first\",\n" + " \"family_name\": \"last\",\n" + + " \"preferred_username\": \"user1\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri).build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); - OidcUser user = this.userService.loadUser( - new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); + OidcUser user = this.userService + .loadUser(new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); assertThat(user.getUserInfo()).isNotNull(); } @Test public void loadUserWhenUserInfoSuccessResponseThenReturnUser() { - String userInfoResponse = "{\n" + - " \"sub\": \"subject1\",\n" + - " \"name\": \"first last\",\n" + - " \"given_name\": \"first\",\n" + - " \"family_name\": \"last\",\n" + - " \"preferred_username\": \"user1\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"sub\": \"subject1\",\n" + " \"name\": \"first last\",\n" + + " \"given_name\": \"first\",\n" + " \"family_name\": \"last\",\n" + + " \"preferred_username\": \"user1\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri).build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); - OidcUser user = this.userService.loadUser( - new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); + OidcUser user = this.userService + .loadUser(new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); assertThat(user.getIdToken()).isNotNull(); assertThat(user.getUserInfo()).isNotNull(); @@ -278,16 +258,13 @@ public class OidcUserServiceTests { this.exception.expect(OAuth2AuthenticationException.class); this.exception.expectMessage(containsString("invalid_user_info_response")); - String userInfoResponse = "{\n" + - " \"email\": \"full_name@provider.com\",\n" + - " \"name\": \"full name\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"email\": \"full_name@provider.com\",\n" + " \"name\": \"full name\"\n" + + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri) + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri) .userNameAttributeName(StandardClaimNames.EMAIL).build(); this.userService.loadUser(new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); @@ -298,15 +275,12 @@ public class OidcUserServiceTests { this.exception.expect(OAuth2AuthenticationException.class); this.exception.expectMessage(containsString("invalid_user_info_response")); - String userInfoResponse = "{\n" + - " \"sub\": \"other-subject\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"sub\": \"other-subject\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri).build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); this.userService.loadUser(new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); } @@ -314,22 +288,18 @@ public class OidcUserServiceTests { @Test public void loadUserWhenUserInfoSuccessResponseInvalidThenThrowOAuth2AuthenticationException() { this.exception.expect(OAuth2AuthenticationException.class); - this.exception.expectMessage(containsString("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); + this.exception.expectMessage(containsString( + "[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); - String userInfoResponse = "{\n" + - " \"sub\": \"subject1\",\n" + - " \"name\": \"first last\",\n" + - " \"given_name\": \"first\",\n" + - " \"family_name\": \"last\",\n" + - " \"preferred_username\": \"user1\",\n" + - " \"email\": \"user1@example.com\"\n"; -// "}\n"; // Make the JSON invalid/malformed + String userInfoResponse = "{\n" + " \"sub\": \"subject1\",\n" + " \"name\": \"first last\",\n" + + " \"given_name\": \"first\",\n" + " \"family_name\": \"last\",\n" + + " \"preferred_username\": \"user1\",\n" + " \"email\": \"user1@example.com\"\n"; + // "}\n"; // Make the JSON invalid/malformed this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri).build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); this.userService.loadUser(new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); } @@ -337,14 +307,14 @@ public class OidcUserServiceTests { @Test public void loadUserWhenServerErrorThenThrowOAuth2AuthenticationException() { this.exception.expect(OAuth2AuthenticationException.class); - this.exception.expectMessage(containsString("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource: 500 Server Error")); + this.exception.expectMessage(containsString( + "[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource: 500 Server Error")); this.server.enqueue(new MockResponse().setResponseCode(500)); String userInfoUri = server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri).build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); this.userService.loadUser(new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); } @@ -352,36 +322,30 @@ public class OidcUserServiceTests { @Test public void loadUserWhenUserInfoUriInvalidThenThrowOAuth2AuthenticationException() { this.exception.expect(OAuth2AuthenticationException.class); - this.exception.expectMessage(containsString("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); + this.exception.expectMessage(containsString( + "[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); String userInfoUri = "https://invalid-provider.com/user"; - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri).build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); this.userService.loadUser(new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); } @Test public void loadUserWhenCustomUserNameAttributeNameThenGetNameReturnsCustomUserName() { - String userInfoResponse = "{\n" + - " \"sub\": \"subject1\",\n" + - " \"name\": \"first last\",\n" + - " \"given_name\": \"first\",\n" + - " \"family_name\": \"last\",\n" + - " \"preferred_username\": \"user1\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"sub\": \"subject1\",\n" + " \"name\": \"first last\",\n" + + " \"given_name\": \"first\",\n" + " \"family_name\": \"last\",\n" + + " \"preferred_username\": \"user1\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri) + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri) .userNameAttributeName(StandardClaimNames.EMAIL).build(); - OidcUser user = this.userService.loadUser( - new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); + OidcUser user = this.userService + .loadUser(new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); assertThat(user.getName()).isEqualTo("user1@example.com"); } @@ -389,20 +353,14 @@ public class OidcUserServiceTests { // gh-5294 @Test public void loadUserWhenUserInfoSuccessResponseThenAcceptHeaderJson() throws Exception { - String userInfoResponse = "{\n" + - " \"sub\": \"subject1\",\n" + - " \"name\": \"first last\",\n" + - " \"given_name\": \"first\",\n" + - " \"family_name\": \"last\",\n" + - " \"preferred_username\": \"user1\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"sub\": \"subject1\",\n" + " \"name\": \"first last\",\n" + + " \"given_name\": \"first\",\n" + " \"family_name\": \"last\",\n" + + " \"preferred_username\": \"user1\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri).build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); this.userService.loadUser(new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); assertThat(this.server.takeRequest(1, TimeUnit.SECONDS).getHeader(HttpHeaders.ACCEPT)) @@ -412,45 +370,34 @@ public class OidcUserServiceTests { // gh-5500 @Test public void loadUserWhenAuthenticationMethodHeaderSuccessResponseThenHttpMethodGet() throws Exception { - String userInfoResponse = "{\n" + - " \"sub\": \"subject1\",\n" + - " \"name\": \"first last\",\n" + - " \"given_name\": \"first\",\n" + - " \"family_name\": \"last\",\n" + - " \"preferred_username\": \"user1\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"sub\": \"subject1\",\n" + " \"name\": \"first last\",\n" + + " \"given_name\": \"first\",\n" + " \"family_name\": \"last\",\n" + + " \"preferred_username\": \"user1\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri).build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); this.userService.loadUser(new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); RecordedRequest request = this.server.takeRequest(); assertThat(request.getMethod()).isEqualTo(HttpMethod.GET.name()); assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON_VALUE); - assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("Bearer " + this.accessToken.getTokenValue()); + assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)) + .isEqualTo("Bearer " + this.accessToken.getTokenValue()); } // gh-5500 @Test public void loadUserWhenAuthenticationMethodFormSuccessResponseThenHttpMethodPost() throws Exception { - String userInfoResponse = "{\n" + - " \"sub\": \"subject1\",\n" + - " \"name\": \"first last\",\n" + - " \"given_name\": \"first\",\n" + - " \"family_name\": \"last\",\n" + - " \"preferred_username\": \"user1\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"sub\": \"subject1\",\n" + " \"name\": \"first last\",\n" + + " \"given_name\": \"first\",\n" + " \"family_name\": \"last\",\n" + + " \"preferred_username\": \"user1\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri) + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri) .userInfoAuthenticationMethod(AuthenticationMethod.FORM).build(); this.userService.loadUser(new OidcUserRequest(clientRegistration, this.accessToken, this.idToken)); @@ -463,23 +410,17 @@ public class OidcUserServiceTests { @Test public void loadUserWhenCustomClaimTypeConverterFactorySetThenApplied() { - String userInfoResponse = "{\n" + - " \"sub\": \"subject1\",\n" + - " \"name\": \"first last\",\n" + - " \"given_name\": \"first\",\n" + - " \"family_name\": \"last\",\n" + - " \"preferred_username\": \"user1\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"sub\": \"subject1\",\n" + " \"name\": \"first last\",\n" + + " \"given_name\": \"first\",\n" + " \"family_name\": \"last\",\n" + + " \"preferred_username\": \"user1\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri) - .build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); - Function, Map>> customClaimTypeConverterFactory = mock(Function.class); + Function, Map>> customClaimTypeConverterFactory = mock( + Function.class); this.userService.setClaimTypeConverterFactory(customClaimTypeConverterFactory); when(customClaimTypeConverterFactory.apply(same(clientRegistration))) @@ -507,8 +448,7 @@ public class OidcUserServiceTests { @Test public void loadUserWhenTokenDoesNotContainScopesThenNoScopeAuthorities() { OidcUserService userService = new OidcUserService(); - OidcUserRequest request = new OidcUserRequest(clientRegistration().build(), - noScopes(), idToken().build()); + OidcUserRequest request = new OidcUserRequest(clientRegistration().build(), noScopes(), idToken().build()); OidcUser user = userService.loadUser(request); assertThat(user.getAuthorities()).hasSize(1); @@ -517,8 +457,7 @@ public class OidcUserServiceTests { } private MockResponse jsonResponse(String json) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json); + return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/web/logout/OidcClientInitiatedLogoutSuccessHandlerTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/web/logout/OidcClientInitiatedLogoutSuccessHandlerTests.java index 59a7c08150..8413106273 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/web/logout/OidcClientInitiatedLogoutSuccessHandlerTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/web/logout/OidcClientInitiatedLogoutSuccessHandlerTests.java @@ -47,14 +47,15 @@ import static org.mockito.Mockito.mock; */ @RunWith(MockitoJUnitRunner.class) public class OidcClientInitiatedLogoutSuccessHandlerTests { - ClientRegistration registration = TestClientRegistrations - .clientRegistration() - .providerConfigurationMetadata( - Collections.singletonMap("end_session_endpoint", "https://endpoint")) + + ClientRegistration registration = TestClientRegistrations.clientRegistration() + .providerConfigurationMetadata(Collections.singletonMap("end_session_endpoint", "https://endpoint")) .build(); + ClientRegistrationRepository repository = new InMemoryClientRegistrationRepository(registration); MockHttpServletRequest request; + MockHttpServletResponse response; OidcClientInitiatedLogoutSuccessHandler handler; @@ -67,12 +68,9 @@ public class OidcClientInitiatedLogoutSuccessHandlerTests { } @Test - public void logoutWhenOidcRedirectUrlConfiguredThenRedirects() - throws IOException, ServletException { - OAuth2AuthenticationToken token = new OAuth2AuthenticationToken( - TestOidcUsers.create(), - AuthorityUtils.NO_AUTHORITIES, - this.registration.getRegistrationId()); + public void logoutWhenOidcRedirectUrlConfiguredThenRedirects() throws IOException, ServletException { + OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(), + AuthorityUtils.NO_AUTHORITIES, this.registration.getRegistrationId()); this.request.setUserPrincipal(token); this.handler.onLogoutSuccess(this.request, this.response, token); @@ -81,8 +79,7 @@ public class OidcClientInitiatedLogoutSuccessHandlerTests { } @Test - public void logoutWhenNotOAuth2AuthenticationThenDefaults() - throws IOException, ServletException { + public void logoutWhenNotOAuth2AuthenticationThenDefaults() throws IOException, ServletException { Authentication token = mock(Authentication.class); this.request.setUserPrincipal(token); @@ -93,12 +90,9 @@ public class OidcClientInitiatedLogoutSuccessHandlerTests { } @Test - public void logoutWhenNotOidcUserThenDefaults() - throws IOException, ServletException { - OAuth2AuthenticationToken token = new OAuth2AuthenticationToken( - TestOAuth2Users.create(), - AuthorityUtils.NO_AUTHORITIES, - this.registration.getRegistrationId()); + public void logoutWhenNotOidcUserThenDefaults() throws IOException, ServletException { + OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOAuth2Users.create(), + AuthorityUtils.NO_AUTHORITIES, this.registration.getRegistrationId()); this.request.setUserPrincipal(token); this.handler.setDefaultTargetUrl("https://default"); @@ -108,17 +102,14 @@ public class OidcClientInitiatedLogoutSuccessHandlerTests { } @Test - public void logoutWhenClientRegistrationHasNoEndSessionEndpointThenDefaults() - throws Exception { + public void logoutWhenClientRegistrationHasNoEndSessionEndpointThenDefaults() throws Exception { ClientRegistration registration = TestClientRegistrations.clientRegistration().build(); ClientRegistrationRepository repository = new InMemoryClientRegistrationRepository(registration); OidcClientInitiatedLogoutSuccessHandler handler = new OidcClientInitiatedLogoutSuccessHandler(repository); - OAuth2AuthenticationToken token = new OAuth2AuthenticationToken( - TestOidcUsers.create(), - AuthorityUtils.NO_AUTHORITIES, - registration.getRegistrationId()); + OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(), + AuthorityUtils.NO_AUTHORITIES, registration.getRegistrationId()); this.request.setUserPrincipal(token); handler.setDefaultTargetUrl("https://default"); @@ -128,31 +119,25 @@ public class OidcClientInitiatedLogoutSuccessHandlerTests { } @Test - public void logoutWhenUsingPostLogoutRedirectUriThenIncludesItInRedirect() - throws IOException, ServletException { + public void logoutWhenUsingPostLogoutRedirectUriThenIncludesItInRedirect() throws IOException, ServletException { - OAuth2AuthenticationToken token = new OAuth2AuthenticationToken( - TestOidcUsers.create(), - AuthorityUtils.NO_AUTHORITIES, - this.registration.getRegistrationId()); + OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(), + AuthorityUtils.NO_AUTHORITIES, this.registration.getRegistrationId()); this.handler.setPostLogoutRedirectUri(URI.create("https://postlogout?encodedparam=value")); this.request.setUserPrincipal(token); this.handler.onLogoutSuccess(this.request, this.response, token); - assertThat(this.response.getRedirectedUrl()).isEqualTo("https://endpoint?" + - "id_token_hint=id-token&" + - "post_logout_redirect_uri=https://postlogout?encodedparam%3Dvalue"); + assertThat(this.response.getRedirectedUrl()).isEqualTo("https://endpoint?" + "id_token_hint=id-token&" + + "post_logout_redirect_uri=https://postlogout?encodedparam%3Dvalue"); } @Test public void logoutWhenUsingPostLogoutRedirectUriTemplateThenBuildsItForRedirect() throws IOException, ServletException { - OAuth2AuthenticationToken token = new OAuth2AuthenticationToken( - TestOidcUsers.create(), - AuthorityUtils.NO_AUTHORITIES, - this.registration.getRegistrationId()); + OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(), + AuthorityUtils.NO_AUTHORITIES, this.registration.getRegistrationId()); this.handler.setPostLogoutRedirectUri("{baseUrl}"); this.request.setScheme("https"); this.request.setServerPort(443); @@ -160,9 +145,8 @@ public class OidcClientInitiatedLogoutSuccessHandlerTests { this.request.setUserPrincipal(token); this.handler.onLogoutSuccess(this.request, this.response, token); - assertThat(this.response.getRedirectedUrl()).isEqualTo("https://endpoint?" + - "id_token_hint=id-token&" + - "post_logout_redirect_uri=https://rp.example.org"); + assertThat(this.response.getRedirectedUrl()).isEqualTo( + "https://endpoint?" + "id_token_hint=id-token&" + "post_logout_redirect_uri=https://rp.example.org"); } @Test @@ -176,4 +160,5 @@ public class OidcClientInitiatedLogoutSuccessHandlerTests { assertThatThrownBy(() -> this.handler.setPostLogoutRedirectUri((String) null)) .isInstanceOf(IllegalArgumentException.class); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandlerTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandlerTests.java index 0dd7ad7209..3ef91ffb3c 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandlerTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/oidc/web/server/logout/OidcClientInitiatedServerLogoutSuccessHandlerTests.java @@ -49,14 +49,15 @@ import static org.mockito.Mockito.when; * Tests for {@link OidcClientInitiatedServerLogoutSuccessHandler} */ public class OidcClientInitiatedServerLogoutSuccessHandlerTests { - ClientRegistration registration = TestClientRegistrations - .clientRegistration() - .providerConfigurationMetadata( - Collections.singletonMap("end_session_endpoint", "https://endpoint")) + + ClientRegistration registration = TestClientRegistrations.clientRegistration() + .providerConfigurationMetadata(Collections.singletonMap("end_session_endpoint", "https://endpoint")) .build(); + ReactiveClientRegistrationRepository repository = new InMemoryReactiveClientRegistrationRepository(registration); ServerWebExchange exchange; + WebFilterChain chain; OidcClientInitiatedServerLogoutSuccessHandler handler; @@ -72,10 +73,8 @@ public class OidcClientInitiatedServerLogoutSuccessHandlerTests { @Test public void logoutWhenOidcRedirectUrlConfiguredThenRedirects() { - OAuth2AuthenticationToken token = new OAuth2AuthenticationToken( - TestOidcUsers.create(), - AuthorityUtils.NO_AUTHORITIES, - this.registration.getRegistrationId()); + OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(), + AuthorityUtils.NO_AUTHORITIES, this.registration.getRegistrationId()); when(this.exchange.getPrincipal()).thenReturn(Mono.just(token)); WebFilterExchange f = new WebFilterExchange(exchange, this.chain); @@ -99,10 +98,8 @@ public class OidcClientInitiatedServerLogoutSuccessHandlerTests { @Test public void logoutWhenNotOidcUserThenDefaults() { - OAuth2AuthenticationToken token = new OAuth2AuthenticationToken( - TestOAuth2Users.create(), - AuthorityUtils.NO_AUTHORITIES, - this.registration.getRegistrationId()); + OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOAuth2Users.create(), + AuthorityUtils.NO_AUTHORITIES, this.registration.getRegistrationId()); when(this.exchange.getPrincipal()).thenReturn(Mono.just(token)); WebFilterExchange f = new WebFilterExchange(exchange, this.chain); @@ -117,15 +114,13 @@ public class OidcClientInitiatedServerLogoutSuccessHandlerTests { public void logoutWhenClientRegistrationHasNoEndSessionEndpointThenDefaults() { ClientRegistration registration = TestClientRegistrations.clientRegistration().build(); - ReactiveClientRegistrationRepository repository = - new InMemoryReactiveClientRegistrationRepository(registration); - OidcClientInitiatedServerLogoutSuccessHandler handler = - new OidcClientInitiatedServerLogoutSuccessHandler(repository); + ReactiveClientRegistrationRepository repository = new InMemoryReactiveClientRegistrationRepository( + registration); + OidcClientInitiatedServerLogoutSuccessHandler handler = new OidcClientInitiatedServerLogoutSuccessHandler( + repository); - OAuth2AuthenticationToken token = new OAuth2AuthenticationToken( - TestOidcUsers.create(), - AuthorityUtils.NO_AUTHORITIES, - registration.getRegistrationId()); + OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(), + AuthorityUtils.NO_AUTHORITIES, registration.getRegistrationId()); when(this.exchange.getPrincipal()).thenReturn(Mono.just(token)); WebFilterExchange f = new WebFilterExchange(exchange, this.chain); @@ -139,10 +134,8 @@ public class OidcClientInitiatedServerLogoutSuccessHandlerTests { @Test public void logoutWhenUsingPostLogoutRedirectUriThenIncludesItInRedirect() { - OAuth2AuthenticationToken token = new OAuth2AuthenticationToken( - TestOidcUsers.create(), - AuthorityUtils.NO_AUTHORITIES, - this.registration.getRegistrationId()); + OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(), + AuthorityUtils.NO_AUTHORITIES, this.registration.getRegistrationId()); when(this.exchange.getPrincipal()).thenReturn(Mono.just(token)); WebFilterExchange f = new WebFilterExchange(exchange, this.chain); @@ -150,20 +143,16 @@ public class OidcClientInitiatedServerLogoutSuccessHandlerTests { this.handler.setPostLogoutRedirectUri(URI.create("https://postlogout?encodedparam=value")); this.handler.onLogoutSuccess(f, token).block(); - assertThat(redirectedUrl(this.exchange)) - .isEqualTo("https://endpoint?" + - "id_token_hint=id-token&" + - "post_logout_redirect_uri=https://postlogout?encodedparam%3Dvalue"); + assertThat(redirectedUrl(this.exchange)).isEqualTo("https://endpoint?" + "id_token_hint=id-token&" + + "post_logout_redirect_uri=https://postlogout?encodedparam%3Dvalue"); } @Test public void logoutWhenUsingPostLogoutRedirectUriTemplateThenBuildsItForRedirect() throws IOException, ServletException { - OAuth2AuthenticationToken token = new OAuth2AuthenticationToken( - TestOidcUsers.create(), - AuthorityUtils.NO_AUTHORITIES, - this.registration.getRegistrationId()); + OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(), + AuthorityUtils.NO_AUTHORITIES, this.registration.getRegistrationId()); when(this.exchange.getPrincipal()).thenReturn(Mono.just(token)); MockServerHttpRequest request = MockServerHttpRequest.get("https://rp.example.org/").build(); when(this.exchange.getRequest()).thenReturn(request); @@ -172,10 +161,8 @@ public class OidcClientInitiatedServerLogoutSuccessHandlerTests { this.handler.setPostLogoutRedirectUri("{baseUrl}"); this.handler.onLogoutSuccess(f, token).block(); - assertThat(redirectedUrl(this.exchange)) - .isEqualTo("https://endpoint?" + - "id_token_hint=id-token&" + - "post_logout_redirect_uri=https://rp.example.org"); + assertThat(redirectedUrl(this.exchange)).isEqualTo( + "https://endpoint?" + "id_token_hint=id-token&" + "post_logout_redirect_uri=https://rp.example.org"); } @Test @@ -193,4 +180,5 @@ public class OidcClientInitiatedServerLogoutSuccessHandlerTests { private String redirectedUrl(ServerWebExchange exchange) { return exchange.getResponse().getHeaders().getFirst("Location"); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationTests.java index f934e1fb34..b841824ae5 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationTests.java @@ -39,19 +39,30 @@ import static org.springframework.security.oauth2.client.registration.TestClient * @author Joe Grandja */ public class ClientRegistrationTests { + private static final String REGISTRATION_ID = "registration-1"; + private static final String CLIENT_ID = "client-1"; + private static final String CLIENT_SECRET = "secret"; + private static final String REDIRECT_URI = "https://example.com"; - private static final Set SCOPES = Collections.unmodifiableSet( - Stream.of("openid", "profile", "email").collect(Collectors.toSet())); + + private static final Set SCOPES = Collections + .unmodifiableSet(Stream.of("openid", "profile", "email").collect(Collectors.toSet())); + private static final String AUTHORIZATION_URI = "https://provider.com/oauth2/authorization"; + private static final String TOKEN_URI = "https://provider.com/oauth2/token"; + private static final String JWK_SET_URI = "https://provider.com/oauth2/keys"; + private static final String ISSUER_URI = "https://provider.com"; + private static final String CLIENT_NAME = "Client 1"; - private static final Map PROVIDER_CONFIGURATION_METADATA = - Collections.unmodifiableMap(createProviderConfigurationMetadata()); + + private static final Map PROVIDER_CONFIGURATION_METADATA = Collections + .unmodifiableMap(createProviderConfigurationMetadata()); private static Map createProviderConfigurationMetadata() { Map configurationMetadata = new LinkedHashMap<>(); @@ -62,38 +73,21 @@ public class ClientRegistrationTests { @Test(expected = IllegalArgumentException.class) public void buildWhenAuthorizationGrantTypeIsNullThenThrowIllegalArgumentException() { - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(null) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .jwkSetUri(JWK_SET_URI) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID).clientSecret(CLIENT_SECRET) + .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC).authorizationGrantType(null) + .redirectUri(REDIRECT_URI).scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI) + .tokenUri(TOKEN_URI).userInfoAuthenticationMethod(AuthenticationMethod.FORM).jwkSetUri(JWK_SET_URI) + .clientName(CLIENT_NAME).build(); } @Test public void buildWhenAuthorizationCodeGrantAllAttributesProvidedThenAllAttributesAreSet() { - ClientRegistration registration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .jwkSetUri(JWK_SET_URI) - .issuerUri(ISSUER_URI) - .providerConfigurationMetadata(PROVIDER_CONFIGURATION_METADATA) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration registration = ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID) + .clientSecret(CLIENT_SECRET).clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI).tokenUri(TOKEN_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).jwkSetUri(JWK_SET_URI).issuerUri(ISSUER_URI) + .providerConfigurationMetadata(PROVIDER_CONFIGURATION_METADATA).clientName(CLIENT_NAME).build(); assertThat(registration.getRegistrationId()).isEqualTo(REGISTRATION_ID); assertThat(registration.getClientId()).isEqualTo(CLIENT_ID); @@ -104,61 +98,42 @@ public class ClientRegistrationTests { assertThat(registration.getScopes()).isEqualTo(SCOPES); assertThat(registration.getProviderDetails().getAuthorizationUri()).isEqualTo(AUTHORIZATION_URI); assertThat(registration.getProviderDetails().getTokenUri()).isEqualTo(TOKEN_URI); - assertThat(registration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod()).isEqualTo(AuthenticationMethod.FORM); + assertThat(registration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod()) + .isEqualTo(AuthenticationMethod.FORM); assertThat(registration.getProviderDetails().getJwkSetUri()).isEqualTo(JWK_SET_URI); assertThat(registration.getProviderDetails().getIssuerUri()).isEqualTo(ISSUER_URI); - assertThat(registration.getProviderDetails().getConfigurationMetadata()).isEqualTo(PROVIDER_CONFIGURATION_METADATA); + assertThat(registration.getProviderDetails().getConfigurationMetadata()) + .isEqualTo(PROVIDER_CONFIGURATION_METADATA); assertThat(registration.getClientName()).isEqualTo(CLIENT_NAME); } @Test(expected = IllegalArgumentException.class) public void buildWhenAuthorizationCodeGrantRegistrationIdIsNullThenThrowIllegalArgumentException() { - ClientRegistration.withRegistrationId(null) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .jwkSetUri(JWK_SET_URI) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration.withRegistrationId(null).clientId(CLIENT_ID).clientSecret(CLIENT_SECRET) + .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI).tokenUri(TOKEN_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).jwkSetUri(JWK_SET_URI).clientName(CLIENT_NAME) + .build(); } @Test(expected = IllegalArgumentException.class) public void buildWhenAuthorizationCodeGrantClientIdIsNullThenThrowIllegalArgumentException() { - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(null) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .jwkSetUri(JWK_SET_URI) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(null).clientSecret(CLIENT_SECRET) + .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI).tokenUri(TOKEN_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).jwkSetUri(JWK_SET_URI).clientName(CLIENT_NAME) + .build(); } @Test public void buildWhenAuthorizationCodeGrantClientSecretIsNullThenDefaultToEmpty() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(null) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .jwkSetUri(JWK_SET_URI) - .clientName(CLIENT_NAME) + .clientId(CLIENT_ID).clientSecret(null).clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI).tokenUri(TOKEN_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).jwkSetUri(JWK_SET_URI).clientName(CLIENT_NAME) .build(); assertThat(clientRegistration.getClientSecret()).isEqualTo(""); } @@ -166,16 +141,10 @@ public class ClientRegistrationTests { @Test public void buildWhenAuthorizationCodeGrantClientAuthenticationMethodNotProvidedThenDefaultToBasic() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .jwkSetUri(JWK_SET_URI) - .clientName(CLIENT_NAME) + .clientId(CLIENT_ID).clientSecret(CLIENT_SECRET) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI).tokenUri(TOKEN_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).jwkSetUri(JWK_SET_URI).clientName(CLIENT_NAME) .build(); assertThat(clientRegistration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.BASIC); } @@ -183,16 +152,10 @@ public class ClientRegistrationTests { @Test public void buildWhenAuthorizationCodeGrantClientAuthenticationMethodNotProvidedAndClientSecretNullThenDefaultToNone() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(null) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .jwkSetUri(JWK_SET_URI) - .clientName(CLIENT_NAME) + .clientId(CLIENT_ID).clientSecret(null) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI).tokenUri(TOKEN_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).jwkSetUri(JWK_SET_URI).clientName(CLIENT_NAME) .build(); assertThat(clientRegistration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.NONE); } @@ -200,154 +163,94 @@ public class ClientRegistrationTests { @Test public void buildWhenAuthorizationCodeGrantClientAuthenticationMethodNotProvidedAndClientSecretBlankThenDefaultToNone() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(" ") - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .jwkSetUri(JWK_SET_URI) - .clientName(CLIENT_NAME) - .build(); + .clientId(CLIENT_ID).clientSecret(" ").authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) + .redirectUri(REDIRECT_URI).scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI) + .tokenUri(TOKEN_URI).userInfoAuthenticationMethod(AuthenticationMethod.FORM).jwkSetUri(JWK_SET_URI) + .clientName(CLIENT_NAME).build(); assertThat(clientRegistration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.NONE); assertThat(clientRegistration.getClientSecret()).isEqualTo(""); } @Test(expected = IllegalArgumentException.class) public void buildWhenAuthorizationCodeGrantRedirectUriIsNullThenThrowIllegalArgumentException() { - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(null) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .jwkSetUri(JWK_SET_URI) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID).clientSecret(CLIENT_SECRET) + .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(null) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI).tokenUri(TOKEN_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).jwkSetUri(JWK_SET_URI).clientName(CLIENT_NAME) + .build(); } // gh-5494 @Test public void buildWhenAuthorizationCodeGrantScopeIsNullThenScopeNotRequired() { - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope((String[]) null) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .jwkSetUri(JWK_SET_URI) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID).clientSecret(CLIENT_SECRET) + .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .scope((String[]) null).authorizationUri(AUTHORIZATION_URI).tokenUri(TOKEN_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).jwkSetUri(JWK_SET_URI).clientName(CLIENT_NAME) + .build(); } @Test(expected = IllegalArgumentException.class) public void buildWhenAuthorizationCodeGrantAuthorizationUriIsNullThenThrowIllegalArgumentException() { - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(null) - .tokenUri(TOKEN_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .jwkSetUri(JWK_SET_URI) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID).clientSecret(CLIENT_SECRET) + .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(null).tokenUri(TOKEN_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).jwkSetUri(JWK_SET_URI).clientName(CLIENT_NAME) + .build(); } @Test(expected = IllegalArgumentException.class) public void buildWhenAuthorizationCodeGrantTokenUriIsNullThenThrowIllegalArgumentException() { - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(null) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .jwkSetUri(JWK_SET_URI) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID).clientSecret(CLIENT_SECRET) + .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI).tokenUri(null) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).jwkSetUri(JWK_SET_URI).clientName(CLIENT_NAME) + .build(); } @Test public void buildWhenAuthorizationCodeGrantClientNameNotProvidedThenDefaultToRegistrationId() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) + .clientId(CLIENT_ID).clientSecret(CLIENT_SECRET) .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .jwkSetUri(JWK_SET_URI) - .build(); + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI).tokenUri(TOKEN_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).jwkSetUri(JWK_SET_URI).build(); assertThat(clientRegistration.getClientName()).isEqualTo(clientRegistration.getRegistrationId()); } @Test public void buildWhenAuthorizationCodeGrantScopeDoesNotContainOpenidThenJwkSetUriNotRequired() { - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope("scope1") - .authorizationUri(AUTHORIZATION_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .tokenUri(TOKEN_URI) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID).clientSecret(CLIENT_SECRET) + .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .scope("scope1").authorizationUri(AUTHORIZATION_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).tokenUri(TOKEN_URI).clientName(CLIENT_NAME) + .build(); } // gh-5494 @Test public void buildWhenAuthorizationCodeGrantScopeIsNullThenJwkSetUriNotRequired() { - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) + ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID).clientSecret(CLIENT_SECRET) .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .clientName(CLIENT_NAME) - .build(); + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .authorizationUri(AUTHORIZATION_URI).tokenUri(TOKEN_URI).clientName(CLIENT_NAME).build(); } @Test public void buildWhenAuthorizationCodeGrantProviderConfigurationMetadataIsNullThenDefaultToEmpty() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) + .clientId(CLIENT_ID).clientSecret(CLIENT_SECRET) .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.HEADER) - .providerConfigurationMetadata(null) - .jwkSetUri(JWK_SET_URI) - .clientName(CLIENT_NAME) - .build(); + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI).tokenUri(TOKEN_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.HEADER).providerConfigurationMetadata(null) + .jwkSetUri(JWK_SET_URI).clientName(CLIENT_NAME).build(); assertThat(clientRegistration.getProviderDetails().getConfigurationMetadata()).isNotNull(); assertThat(clientRegistration.getProviderDetails().getConfigurationMetadata()).isEmpty(); } @@ -355,18 +258,12 @@ public class ClientRegistrationTests { @Test public void buildWhenAuthorizationCodeGrantProviderConfigurationMetadataEmptyThenIsEmpty() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) + .clientId(CLIENT_ID).clientSecret(CLIENT_SECRET) .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI).tokenUri(TOKEN_URI) .userInfoAuthenticationMethod(AuthenticationMethod.HEADER) - .providerConfigurationMetadata(Collections.emptyMap()) - .jwkSetUri(JWK_SET_URI) - .clientName(CLIENT_NAME) + .providerConfigurationMetadata(Collections.emptyMap()).jwkSetUri(JWK_SET_URI).clientName(CLIENT_NAME) .build(); assertThat(clientRegistration.getProviderDetails().getConfigurationMetadata()).isNotNull(); assertThat(clientRegistration.getProviderDetails().getConfigurationMetadata()).isEmpty(); @@ -374,15 +271,10 @@ public class ClientRegistrationTests { @Test public void buildWhenImplicitGrantAllAttributesProvidedThenAllAttributesAreSet() { - ClientRegistration registration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .authorizationGrantType(AuthorizationGrantType.IMPLICIT) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration registration = ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID) + .authorizationGrantType(AuthorizationGrantType.IMPLICIT).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).clientName(CLIENT_NAME).build(); assertThat(registration.getRegistrationId()).isEqualTo(REGISTRATION_ID); assertThat(registration.getClientId()).isEqualTo(CLIENT_ID); @@ -390,86 +282,58 @@ public class ClientRegistrationTests { assertThat(registration.getRedirectUri()).isEqualTo(REDIRECT_URI); assertThat(registration.getScopes()).isEqualTo(SCOPES); assertThat(registration.getProviderDetails().getAuthorizationUri()).isEqualTo(AUTHORIZATION_URI); - assertThat(registration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod()).isEqualTo(AuthenticationMethod.FORM); + assertThat(registration.getProviderDetails().getUserInfoEndpoint().getAuthenticationMethod()) + .isEqualTo(AuthenticationMethod.FORM); assertThat(registration.getClientName()).isEqualTo(CLIENT_NAME); } @Test(expected = IllegalArgumentException.class) public void buildWhenImplicitGrantRegistrationIdIsNullThenThrowIllegalArgumentException() { - ClientRegistration.withRegistrationId(null) - .clientId(CLIENT_ID) - .authorizationGrantType(AuthorizationGrantType.IMPLICIT) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration.withRegistrationId(null).clientId(CLIENT_ID) + .authorizationGrantType(AuthorizationGrantType.IMPLICIT).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).clientName(CLIENT_NAME).build(); } @Test(expected = IllegalArgumentException.class) public void buildWhenImplicitGrantClientIdIsNullThenThrowIllegalArgumentException() { - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(null) - .authorizationGrantType(AuthorizationGrantType.IMPLICIT) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(null) + .authorizationGrantType(AuthorizationGrantType.IMPLICIT).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).clientName(CLIENT_NAME).build(); } @Test(expected = IllegalArgumentException.class) public void buildWhenImplicitGrantRedirectUriIsNullThenThrowIllegalArgumentException() { - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .authorizationGrantType(AuthorizationGrantType.IMPLICIT) - .redirectUri(null) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID) + .authorizationGrantType(AuthorizationGrantType.IMPLICIT).redirectUri(null) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).clientName(CLIENT_NAME).build(); } // gh-5494 @Test public void buildWhenImplicitGrantScopeIsNullThenScopeNotRequired() { - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .authorizationGrantType(AuthorizationGrantType.IMPLICIT) - .redirectUri(REDIRECT_URI) - .scope((String[]) null) - .authorizationUri(AUTHORIZATION_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID) + .authorizationGrantType(AuthorizationGrantType.IMPLICIT).redirectUri(REDIRECT_URI) + .scope((String[]) null).authorizationUri(AUTHORIZATION_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).clientName(CLIENT_NAME).build(); } @Test(expected = IllegalArgumentException.class) public void buildWhenImplicitGrantAuthorizationUriIsNullThenThrowIllegalArgumentException() { - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .authorizationGrantType(AuthorizationGrantType.IMPLICIT) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(null) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID) + .authorizationGrantType(AuthorizationGrantType.IMPLICIT).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(null) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).clientName(CLIENT_NAME).build(); } @Test public void buildWhenImplicitGrantClientNameNotProvidedThenDefaultToRegistrationId() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .authorizationGrantType(AuthorizationGrantType.IMPLICIT) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .build(); + .clientId(CLIENT_ID).authorizationGrantType(AuthorizationGrantType.IMPLICIT).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).build(); assertThat(clientRegistration.getClientName()).isEqualTo(clientRegistration.getRegistrationId()); } @@ -477,33 +341,21 @@ public class ClientRegistrationTests { public void buildWhenOverrideRegistrationIdThenOverridden() { String overriddenId = "override"; ClientRegistration registration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .registrationId(overriddenId) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) + .registrationId(overriddenId).clientId(CLIENT_ID).clientSecret(CLIENT_SECRET) .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri(REDIRECT_URI) - .scope(SCOPES.toArray(new String[0])) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .jwkSetUri(JWK_SET_URI) - .clientName(CLIENT_NAME) - .build(); + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri(REDIRECT_URI) + .scope(SCOPES.toArray(new String[0])).authorizationUri(AUTHORIZATION_URI).tokenUri(TOKEN_URI) + .jwkSetUri(JWK_SET_URI).clientName(CLIENT_NAME).build(); assertThat(registration.getRegistrationId()).isEqualTo(overriddenId); } @Test public void buildWhenClientCredentialsGrantAllAttributesProvidedThenAllAttributesAreSet() { - ClientRegistration registration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) - .scope(SCOPES.toArray(new String[0])) - .tokenUri(TOKEN_URI) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration registration = ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID) + .clientSecret(CLIENT_SECRET).clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).scope(SCOPES.toArray(new String[0])) + .tokenUri(TOKEN_URI).clientName(CLIENT_NAME).build(); assertThat(registration.getRegistrationId()).isEqualTo(REGISTRATION_ID); assertThat(registration.getClientId()).isEqualTo(CLIENT_ID); @@ -517,96 +369,63 @@ public class ClientRegistrationTests { @Test public void buildWhenClientCredentialsGrantRegistrationIdIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> - ClientRegistration.withRegistrationId(null) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) - .tokenUri(TOKEN_URI) - .build() - ).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> ClientRegistration.withRegistrationId(null).clientId(CLIENT_ID) + .clientSecret(CLIENT_SECRET).clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).tokenUri(TOKEN_URI).build()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void buildWhenClientCredentialsGrantClientIdIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(null) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) - .tokenUri(TOKEN_URI) - .build() - ).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(null) + .clientSecret(CLIENT_SECRET).clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).tokenUri(TOKEN_URI).build()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void buildWhenClientCredentialsGrantClientSecretIsNullThenDefaultToEmpty() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(null) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) - .tokenUri(TOKEN_URI) - .build(); + .clientId(CLIENT_ID).clientSecret(null).clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).tokenUri(TOKEN_URI).build(); assertThat(clientRegistration.getClientSecret()).isEqualTo(""); } @Test public void buildWhenClientCredentialsGrantClientAuthenticationMethodNotProvidedThenDefaultToBasic() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) - .tokenUri(TOKEN_URI) - .build(); + .clientId(CLIENT_ID).clientSecret(CLIENT_SECRET) + .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).tokenUri(TOKEN_URI).build(); assertThat(clientRegistration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.BASIC); } @Test public void buildWhenClientCredentialsGrantTokenUriIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) - .tokenUri(null) - .build() - ).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID) + .clientSecret(CLIENT_SECRET).clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).tokenUri(null).build()) + .isInstanceOf(IllegalArgumentException.class); } // gh-6256 @Test public void buildWhenScopesContainASpaceThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> - TestClientRegistrations.clientCredentials() - .scope("openid profile email") - .build() - ).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> TestClientRegistrations.clientCredentials().scope("openid profile email").build()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void buildWhenScopesContainAnInvalidCharacterThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> - TestClientRegistrations.clientCredentials() - .scope("an\"invalid\"scope") - .build() - ).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> TestClientRegistrations.clientCredentials().scope("an\"invalid\"scope").build()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void buildWhenPasswordGrantAllAttributesProvidedThenAllAttributesAreSet() { - ClientRegistration registration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .scope(SCOPES.toArray(new String[0])) - .tokenUri(TOKEN_URI) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration registration = ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID) + .clientSecret(CLIENT_SECRET).clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.PASSWORD).scope(SCOPES.toArray(new String[0])) + .tokenUri(TOKEN_URI).clientName(CLIENT_NAME).build(); assertThat(registration.getRegistrationId()).isEqualTo(REGISTRATION_ID); assertThat(registration.getClientId()).isEqualTo(CLIENT_ID); @@ -620,78 +439,51 @@ public class ClientRegistrationTests { @Test public void buildWhenPasswordGrantRegistrationIdIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> - ClientRegistration.withRegistrationId(null) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .tokenUri(TOKEN_URI) - .build() - ).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> ClientRegistration.withRegistrationId(null).clientId(CLIENT_ID) + .clientSecret(CLIENT_SECRET).clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.PASSWORD).tokenUri(TOKEN_URI).build()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void buildWhenPasswordGrantClientIdIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(null) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .tokenUri(TOKEN_URI) - .build() - ).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(null) + .clientSecret(CLIENT_SECRET).clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.PASSWORD).tokenUri(TOKEN_URI).build()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void buildWhenPasswordGrantClientSecretIsNullThenDefaultToEmpty() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(null) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .tokenUri(TOKEN_URI) - .build(); + .clientId(CLIENT_ID).clientSecret(null).clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.PASSWORD).tokenUri(TOKEN_URI).build(); assertThat(clientRegistration.getClientSecret()).isEqualTo(""); } @Test public void buildWhenPasswordGrantClientAuthenticationMethodNotProvidedThenDefaultToBasic() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .tokenUri(TOKEN_URI) - .build(); + .clientId(CLIENT_ID).clientSecret(CLIENT_SECRET).authorizationGrantType(AuthorizationGrantType.PASSWORD) + .tokenUri(TOKEN_URI).build(); assertThat(clientRegistration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.BASIC); } @Test public void buildWhenPasswordGrantTokenUriIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> - ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .tokenUri(null) - .build() - ).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID) + .clientSecret(CLIENT_SECRET).clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.PASSWORD).tokenUri(null).build()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void buildWhenCustomGrantAllAttributesProvidedThenAllAttributesAreSet() { AuthorizationGrantType customGrantType = new AuthorizationGrantType("CUSTOM"); - ClientRegistration registration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(customGrantType) - .scope(SCOPES.toArray(new String[0])) - .tokenUri(TOKEN_URI) - .clientName(CLIENT_NAME) - .build(); + ClientRegistration registration = ClientRegistration.withRegistrationId(REGISTRATION_ID).clientId(CLIENT_ID) + .clientSecret(CLIENT_SECRET).clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(customGrantType).scope(SCOPES.toArray(new String[0])).tokenUri(TOKEN_URI) + .clientName(CLIENT_NAME).build(); assertThat(registration.getRegistrationId()).isEqualTo(REGISTRATION_ID); assertThat(registration.getClientId()).isEqualTo(CLIENT_ID); @@ -724,21 +516,18 @@ public class ClientRegistrationTests { assertThat(clientRegistration.getClientSecret()).isEqualTo(updated.getClientSecret()); assertThat(clientRegistration.getClientAuthenticationMethod()) .isEqualTo(updated.getClientAuthenticationMethod()); - assertThat(clientRegistration.getAuthorizationGrantType()) - .isEqualTo(updated.getAuthorizationGrantType()); - assertThat(clientRegistration.getRedirectUri()) - .isEqualTo(updated.getRedirectUri()); + assertThat(clientRegistration.getAuthorizationGrantType()).isEqualTo(updated.getAuthorizationGrantType()); + assertThat(clientRegistration.getRedirectUri()).isEqualTo(updated.getRedirectUri()); assertThat(clientRegistration.getScopes()).isEqualTo(updated.getScopes()); ClientRegistration.ProviderDetails providerDetails = clientRegistration.getProviderDetails(); ClientRegistration.ProviderDetails updatedProviderDetails = updated.getProviderDetails(); - assertThat(providerDetails.getAuthorizationUri()) - .isEqualTo(updatedProviderDetails.getAuthorizationUri()); - assertThat(providerDetails.getTokenUri()) - .isEqualTo(updatedProviderDetails.getTokenUri()); + assertThat(providerDetails.getAuthorizationUri()).isEqualTo(updatedProviderDetails.getAuthorizationUri()); + assertThat(providerDetails.getTokenUri()).isEqualTo(updatedProviderDetails.getTokenUri()); ClientRegistration.ProviderDetails.UserInfoEndpoint userInfoEndpoint = providerDetails.getUserInfoEndpoint(); - ClientRegistration.ProviderDetails.UserInfoEndpoint updatedUserInfoEndpoint = updatedProviderDetails.getUserInfoEndpoint(); + ClientRegistration.ProviderDetails.UserInfoEndpoint updatedUserInfoEndpoint = updatedProviderDetails + .getUserInfoEndpoint(); assertThat(userInfoEndpoint.getUri()).isEqualTo(updatedUserInfoEndpoint.getUri()); assertThat(userInfoEndpoint.getAuthenticationMethod()) .isEqualTo(updatedUserInfoEndpoint.getAuthenticationMethod()); @@ -756,20 +545,18 @@ public class ClientRegistrationTests { @Test public void buildWhenClientRegistrationValuesOverriddenThenPropagated() { ClientRegistration clientRegistration = clientRegistration().build(); - ClientRegistration updated = withClientRegistration(clientRegistration) - .clientSecret("a-new-secret") + ClientRegistration updated = withClientRegistration(clientRegistration).clientSecret("a-new-secret") .scope("a-new-scope") - .providerConfigurationMetadata(Collections.singletonMap("a-new-config", "a-new-value")) - .build(); + .providerConfigurationMetadata(Collections.singletonMap("a-new-config", "a-new-value")).build(); assertThat(clientRegistration.getClientSecret()).isNotEqualTo(updated.getClientSecret()); assertThat(updated.getClientSecret()).isEqualTo("a-new-secret"); assertThat(clientRegistration.getScopes()).doesNotContain("a-new-scope"); assertThat(updated.getScopes()).containsExactly("a-new-scope"); - assertThat(clientRegistration.getProviderDetails().getConfigurationMetadata()) - .doesNotContainKey("a-new-config").doesNotContainValue("a-new-value"); - assertThat(updated.getProviderDetails().getConfigurationMetadata()) - .containsOnlyKeys("a-new-config").containsValue("a-new-value"); + assertThat(clientRegistration.getProviderDetails().getConfigurationMetadata()).doesNotContainKey("a-new-config") + .doesNotContainValue("a-new-value"); + assertThat(updated.getProviderDetails().getConfigurationMetadata()).containsOnlyKeys("a-new-config") + .containsValue("a-new-value"); } // gh-8903 @@ -777,13 +564,10 @@ public class ClientRegistrationTests { public void buildWhenCustomClientAuthenticationMethodProvidedThenSet() { ClientAuthenticationMethod clientAuthenticationMethod = new ClientAuthenticationMethod("tls_client_auth"); ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(REGISTRATION_ID) - .clientId(CLIENT_ID) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .clientAuthenticationMethod(clientAuthenticationMethod) - .redirectUri(REDIRECT_URI) - .authorizationUri(AUTHORIZATION_URI) - .tokenUri(TOKEN_URI) - .build(); + .clientId(CLIENT_ID).authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) + .clientAuthenticationMethod(clientAuthenticationMethod).redirectUri(REDIRECT_URI) + .authorizationUri(AUTHORIZATION_URI).tokenUri(TOKEN_URI).build(); assertThat(clientRegistration.getClientAuthenticationMethod()).isEqualTo(clientAuthenticationMethod); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationsTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationsTests.java index 2f3a239738..ee51e2cf1d 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationsTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationsTests.java @@ -47,60 +47,27 @@ public class ClientRegistrationsTests { /** * Contains all optional parameters that are found in ClientRegistration */ - private static final String DEFAULT_RESPONSE = - "{\n" + private static final String DEFAULT_RESPONSE = "{\n" + " \"authorization_endpoint\": \"https://example.com/o/oauth2/v2/auth\", \n" - + " \"claims_supported\": [\n" - + " \"aud\", \n" - + " \"email\", \n" - + " \"email_verified\", \n" - + " \"exp\", \n" - + " \"family_name\", \n" - + " \"given_name\", \n" - + " \"iat\", \n" - + " \"iss\", \n" - + " \"locale\", \n" - + " \"name\", \n" - + " \"picture\", \n" - + " \"sub\"\n" - + " ], \n" - + " \"code_challenge_methods_supported\": [\n" - + " \"plain\", \n" - + " \"S256\"\n" - + " ], \n" - + " \"id_token_signing_alg_values_supported\": [\n" - + " \"RS256\"\n" - + " ], \n" + + " \"claims_supported\": [\n" + " \"aud\", \n" + " \"email\", \n" + + " \"email_verified\", \n" + " \"exp\", \n" + " \"family_name\", \n" + + " \"given_name\", \n" + " \"iat\", \n" + " \"iss\", \n" + " \"locale\", \n" + + " \"name\", \n" + " \"picture\", \n" + " \"sub\"\n" + " ], \n" + + " \"code_challenge_methods_supported\": [\n" + " \"plain\", \n" + " \"S256\"\n" + + " ], \n" + " \"id_token_signing_alg_values_supported\": [\n" + " \"RS256\"\n" + " ], \n" + " \"issuer\": \"https://example.com\", \n" - + " \"jwks_uri\": \"https://example.com/oauth2/v3/certs\", \n" - + " \"response_types_supported\": [\n" - + " \"code\", \n" - + " \"token\", \n" - + " \"id_token\", \n" - + " \"code token\", \n" - + " \"code id_token\", \n" - + " \"token id_token\", \n" - + " \"code token id_token\", \n" - + " \"none\"\n" - + " ], \n" + + " \"jwks_uri\": \"https://example.com/oauth2/v3/certs\", \n" + " \"response_types_supported\": [\n" + + " \"code\", \n" + " \"token\", \n" + " \"id_token\", \n" + + " \"code token\", \n" + " \"code id_token\", \n" + " \"token id_token\", \n" + + " \"code token id_token\", \n" + " \"none\"\n" + " ], \n" + " \"revocation_endpoint\": \"https://example.com/o/oauth2/revoke\", \n" - + " \"scopes_supported\": [\n" - + " \"openid\", \n" - + " \"email\", \n" - + " \"profile\"\n" - + " ], \n" - + " \"subject_types_supported\": [\n" - + " \"public\"\n" - + " ], \n" - + " \"grant_types_supported\" : [\"authorization_code\"], \n" + + " \"scopes_supported\": [\n" + " \"openid\", \n" + " \"email\", \n" + + " \"profile\"\n" + " ], \n" + " \"subject_types_supported\": [\n" + " \"public\"\n" + + " ], \n" + " \"grant_types_supported\" : [\"authorization_code\"], \n" + " \"token_endpoint\": \"https://example.com/oauth2/v4/token\", \n" - + " \"token_endpoint_auth_methods_supported\": [\n" - + " \"client_secret_post\", \n" - + " \"client_secret_basic\", \n" - + " \"none\"\n" - + " ], \n" - + " \"userinfo_endpoint\": \"https://example.com/oauth2/v3/userinfo\"\n" - + "}"; + + " \"token_endpoint_auth_methods_supported\": [\n" + " \"client_secret_post\", \n" + + " \"client_secret_basic\", \n" + " \"none\"\n" + " ], \n" + + " \"userinfo_endpoint\": \"https://example.com/oauth2/v3/userinfo\"\n" + "}"; private MockWebServer server; @@ -114,7 +81,8 @@ public class ClientRegistrationsTests { public void setup() throws Exception { this.server = new MockWebServer(); this.server.start(); - this.response = this.mapper.readValue(DEFAULT_RESPONSE, new TypeReference>(){}); + this.response = this.mapper.readValue(DEFAULT_RESPONSE, new TypeReference>() { + }); } @After @@ -132,10 +100,11 @@ public class ClientRegistrationsTests { /** * - * Test compatibility with OpenID v1 discovery endpoint by making a - * OpenID Provider - * Configuration Request as highlighted - * Compatibility Notes of RFC 8414 specification. + * Test compatibility with OpenID v1 discovery endpoint by making a OpenID + * Provider Configuration Request as highlighted + * Compatibility Notes of + * RFC 8414 specification. */ @Test public void issuerWhenOidcFallbackAllInformationThenSuccess() throws Exception { @@ -152,8 +121,7 @@ public class ClientRegistrationsTests { assertIssuerMetadata(registration, provider); } - private void assertIssuerMetadata(ClientRegistration registration, - ClientRegistration.ProviderDetails provider) { + private void assertIssuerMetadata(ClientRegistration registration, ClientRegistration.ProviderDetails provider) { assertThat(registration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.BASIC); assertThat(registration.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); assertThat(registration.getRegistrationId()).isEqualTo(this.server.getHostName()); @@ -166,15 +134,15 @@ public class ClientRegistrationsTests { assertThat(provider.getConfigurationMetadata()).containsKeys("authorization_endpoint", "claims_supported", "code_challenge_methods_supported", "id_token_signing_alg_values_supported", "issuer", "jwks_uri", "response_types_supported", "revocation_endpoint", "scopes_supported", "subject_types_supported", - "grant_types_supported", "token_endpoint", "token_endpoint_auth_methods_supported", "userinfo_endpoint"); + "grant_types_supported", "token_endpoint", "token_endpoint_auth_methods_supported", + "userinfo_endpoint"); } // gh-7512 @Test public void issuerWhenResponseMissingJwksUriThenThrowsIllegalArgumentException() throws Exception { this.response.remove("jwks_uri"); - assertThatThrownBy(() -> registration("").build()) - .isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> registration("").build()).isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("The public JWK set URI must not be null"); } @@ -225,8 +193,8 @@ public class ClientRegistrationsTests { /** * https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata * - * RECOMMENDED. JSON array containing a list of the OAuth 2.0 [RFC6749] scope values that this server supports. The - * server MUST support the openid scope value. + * RECOMMENDED. JSON array containing a list of the OAuth 2.0 [RFC6749] scope values + * that this server supports. The server MUST support the openid scope value. * @throws Exception */ @Test @@ -256,7 +224,6 @@ public class ClientRegistrationsTests { assertThat(registration.getScopes()).containsOnly("openid"); } - @Test public void issuerWhenGrantTypesSupportedNullThenDefaulted() throws Exception { this.response.remove("grant_types_supported"); @@ -276,24 +243,25 @@ public class ClientRegistrationsTests { } /** - * We currently only support authorization_code, so verify we have a meaningful error until we add support. + * We currently only support authorization_code, so verify we have a meaningful error + * until we add support. */ @Test public void issuerWhenGrantTypesSupportedInvalidThenException() { this.response.put("grant_types_supported", Arrays.asList("implicit")); - assertThatThrownBy(() -> registration("")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Only AuthorizationGrantType.AUTHORIZATION_CODE is supported. The issuer \"" + this.issuer + "\" returned a configuration of [implicit]"); + assertThatThrownBy(() -> registration("")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Only AuthorizationGrantType.AUTHORIZATION_CODE is supported. The issuer \"" + + this.issuer + "\" returned a configuration of [implicit]"); } @Test public void issuerWhenOAuth2GrantTypesSupportedInvalidThenException() { this.response.put("grant_types_supported", Arrays.asList("implicit")); - assertThatThrownBy(() -> registrationOAuth2("", null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Only AuthorizationGrantType.AUTHORIZATION_CODE is supported. The issuer \"" + this.issuer + "\" returned a configuration of [implicit]"); + assertThatThrownBy(() -> registrationOAuth2("", null)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Only AuthorizationGrantType.AUTHORIZATION_CODE is supported. The issuer \"" + + this.issuer + "\" returned a configuration of [implicit]"); } @Test @@ -351,24 +319,26 @@ public class ClientRegistrationsTests { } /** - * We currently only support client_secret_basic, so verify we have a meaningful error until we add support. + * We currently only support client_secret_basic, so verify we have a meaningful error + * until we add support. */ @Test public void issuerWhenTokenEndpointAuthMethodsInvalidThenException() { this.response.put("token_endpoint_auth_methods_supported", Arrays.asList("tls_client_auth")); - assertThatThrownBy(() -> registration("")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Only ClientAuthenticationMethod.BASIC, ClientAuthenticationMethod.POST and ClientAuthenticationMethod.NONE are supported. The issuer \"" + this.issuer + "\" returned a configuration of [tls_client_auth]"); + assertThatThrownBy(() -> registration("")).isInstanceOf(IllegalArgumentException.class).hasMessageContaining( + "Only ClientAuthenticationMethod.BASIC, ClientAuthenticationMethod.POST and ClientAuthenticationMethod.NONE are supported. The issuer \"" + + this.issuer + "\" returned a configuration of [tls_client_auth]"); } @Test public void issuerWhenOAuth2TokenEndpointAuthMethodsInvalidThenException() { this.response.put("token_endpoint_auth_methods_supported", Arrays.asList("tls_client_auth")); - assertThatThrownBy(() -> registrationOAuth2("", null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Only ClientAuthenticationMethod.BASIC, ClientAuthenticationMethod.POST and ClientAuthenticationMethod.NONE are supported. The issuer \"" + this.issuer + "\" returned a configuration of [tls_client_auth]"); + assertThatThrownBy(() -> registrationOAuth2("", null)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining( + "Only ClientAuthenticationMethod.BASIC, ClientAuthenticationMethod.POST and ClientAuthenticationMethod.NONE are supported. The issuer \"" + + this.issuer + "\" returned a configuration of [tls_client_auth]"); } @Test @@ -384,41 +354,39 @@ public class ClientRegistrationsTests { } @Test - public void issuerWhenOpenIdConfigurationDoesNotMatchThenMeaningfulErrorMessage() throws Exception { + public void issuerWhenOpenIdConfigurationDoesNotMatchThenMeaningfulErrorMessage() throws Exception { this.issuer = createIssuerFromServer(""); String body = this.mapper.writeValueAsString(this.response); - MockResponse mockResponse = new MockResponse() - .setBody(body) - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + MockResponse mockResponse = new MockResponse().setBody(body).setHeader(HttpHeaders.CONTENT_TYPE, + MediaType.APPLICATION_JSON_VALUE); this.server.enqueue(mockResponse); - assertThatThrownBy(() -> ClientRegistrations.fromOidcIssuerLocation(this.issuer)) - .hasMessageContaining("The Issuer \"https://example.com\" provided in the configuration metadata did not match the requested issuer \"" + this.issuer + "\""); + assertThatThrownBy(() -> ClientRegistrations.fromOidcIssuerLocation(this.issuer)).hasMessageContaining( + "The Issuer \"https://example.com\" provided in the configuration metadata did not match the requested issuer \"" + + this.issuer + "\""); } @Test - public void issuerWhenOAuth2ConfigurationDoesNotMatchThenMeaningfulErrorMessage() throws Exception { + public void issuerWhenOAuth2ConfigurationDoesNotMatchThenMeaningfulErrorMessage() throws Exception { this.issuer = createIssuerFromServer(""); String body = this.mapper.writeValueAsString(this.response); - MockResponse mockResponse = new MockResponse() - .setBody(body) - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + MockResponse mockResponse = new MockResponse().setBody(body).setHeader(HttpHeaders.CONTENT_TYPE, + MediaType.APPLICATION_JSON_VALUE); this.server.enqueue(mockResponse); - assertThatThrownBy(() -> ClientRegistrations.fromIssuerLocation(this.issuer)) - .hasMessageContaining("The Issuer \"https://example.com\" provided in the configuration metadata did not match the requested issuer \"" + this.issuer + "\""); + assertThatThrownBy(() -> ClientRegistrations.fromIssuerLocation(this.issuer)).hasMessageContaining( + "The Issuer \"https://example.com\" provided in the configuration metadata did not match the requested issuer \"" + + this.issuer + "\""); } private ClientRegistration.Builder registration(String path) throws Exception { this.issuer = createIssuerFromServer(path); this.response.put("issuer", this.issuer); String body = this.mapper.writeValueAsString(this.response); - MockResponse mockResponse = new MockResponse() - .setBody(body) - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + MockResponse mockResponse = new MockResponse().setBody(body).setHeader(HttpHeaders.CONTENT_TYPE, + MediaType.APPLICATION_JSON_VALUE); this.server.enqueue(mockResponse); - return ClientRegistrations.fromOidcIssuerLocation(this.issuer) - .clientId("client-id") - .clientSecret("client-secret"); + return ClientRegistrations.fromOidcIssuerLocation(this.issuer).clientId("client-id") + .clientSecret("client-secret"); } private ClientRegistration.Builder registrationOAuth2(String path, String body) throws Exception { @@ -430,10 +398,10 @@ public class ClientRegistrationsTests { final Dispatcher dispatcher = new Dispatcher() { @Override public MockResponse dispatch(RecordedRequest request) { - switch(request.getPath()) { - case "/.well-known/oauth-authorization-server/issuer1": - case "/.well-known/oauth-authorization-server/": - return buildSuccessMockResponse(responseBody); + switch (request.getPath()) { + case "/.well-known/oauth-authorization-server/issuer1": + case "/.well-known/oauth-authorization-server/": + return buildSuccessMockResponse(responseBody); } return new MockResponse().setResponseCode(404); } @@ -441,23 +409,21 @@ public class ClientRegistrationsTests { this.server.setDispatcher(dispatcher); - return ClientRegistrations.fromIssuerLocation(this.issuer) - .clientId("client-id") - .clientSecret("client-secret"); + return ClientRegistrations.fromIssuerLocation(this.issuer).clientId("client-id").clientSecret("client-secret"); } - private String createIssuerFromServer(String path) { return this.server.url(path).toString(); } /** - * Simulates a situation when the ClientRegistration is used with a legacy application where the OIDC - * Discovery Endpoint is "/issuer1/.well-known/openid-configuration" instead of - * "/.well-known/openid-configuration/issuer1" in which case the first attempt results in HTTP 404 and - * the subsequent call results in 200 OK. + * Simulates a situation when the ClientRegistration is used with a legacy application + * where the OIDC Discovery Endpoint is "/issuer1/.well-known/openid-configuration" + * instead of "/.well-known/openid-configuration/issuer1" in which case the first + * attempt results in HTTP 404 and the subsequent call results in 200 OK. * - * @see Section 5 for more details. + * @see Section 5 for more + * details. */ private ClientRegistration.Builder registrationOidcFallback(String path, String body) throws Exception { this.issuer = createIssuerFromServer(path); @@ -468,24 +434,22 @@ public class ClientRegistrationsTests { final Dispatcher dispatcher = new Dispatcher() { @Override public MockResponse dispatch(RecordedRequest request) { - switch(request.getPath()) { - case "/issuer1/.well-known/openid-configuration": - case "/.well-known/openid-configuration/": - return buildSuccessMockResponse(responseBody); + switch (request.getPath()) { + case "/issuer1/.well-known/openid-configuration": + case "/.well-known/openid-configuration/": + return buildSuccessMockResponse(responseBody); } return new MockResponse().setResponseCode(404); } }; this.server.setDispatcher(dispatcher); - return ClientRegistrations.fromIssuerLocation(this.issuer) - .clientId("client-id") - .clientSecret("client-secret"); + return ClientRegistrations.fromIssuerLocation(this.issuer).clientId("client-id").clientSecret("client-secret"); } private MockResponse buildSuccessMockResponse(String body) { - return new MockResponse().setResponseCode(200) - .setBody(body) - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + return new MockResponse().setResponseCode(200).setBody(body).setHeader(HttpHeaders.CONTENT_TYPE, + MediaType.APPLICATION_JSON_VALUE); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/InMemoryClientRegistrationRepositoryTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/InMemoryClientRegistrationRepositoryTests.java index 0778afafec..182ef5b3d2 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/InMemoryClientRegistrationRepositoryTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/InMemoryClientRegistrationRepositoryTests.java @@ -34,6 +34,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @since 5.0 */ public class InMemoryClientRegistrationRepositoryTests { + private ClientRegistration registration = TestClientRegistrations.clientRegistration().build(); private InMemoryClientRegistrationRepository clients = new InMemoryClientRegistrationRepository(this.registration); @@ -94,4 +95,5 @@ public class InMemoryClientRegistrationRepositoryTests { public void iteratorWhenGetThenContainsAll() { assertThat(this.clients).containsOnly(this.registration); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/InMemoryReactiveClientRegistrationRepositoryTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/InMemoryReactiveClientRegistrationRepositoryTests.java index 5ca19c509b..92fccfc27f 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/InMemoryReactiveClientRegistrationRepositoryTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/InMemoryReactiveClientRegistrationRepositoryTests.java @@ -44,7 +44,7 @@ public class InMemoryReactiveClientRegistrationRepositoryTests { @Test public void constructorWhenZeroVarArgsThenIllegalArgumentException() { assertThatThrownBy(() -> new InMemoryReactiveClientRegistrationRepository()) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -77,8 +77,7 @@ public class InMemoryReactiveClientRegistrationRepositoryTests { @Test public void findByRegistrationIdWhenValidIdThenFound() { StepVerifier.create(this.repository.findByRegistrationId(this.registration.getRegistrationId())) - .expectNext(this.registration) - .verifyComplete(); + .expectNext(this.registration).verifyComplete(); } @Test @@ -91,4 +90,5 @@ public class InMemoryReactiveClientRegistrationRepositoryTests { public void iteratorWhenContainsGithubThenContains() { assertThat(this.repository).containsOnly(this.registration); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/TestClientRegistrations.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/TestClientRegistrations.java index 37f65b6487..f108252f7a 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/TestClientRegistrations.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/TestClientRegistrations.java @@ -24,53 +24,41 @@ import org.springframework.security.oauth2.core.ClientAuthenticationMethod; * @since 5.1 */ public class TestClientRegistrations { + public static ClientRegistration.Builder clientRegistration() { return ClientRegistration.withRegistrationId("registration-id") - .redirectUri("{baseUrl}/{action}/oauth2/code/{registrationId}") - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .scope("read:user") - .authorizationUri("https://example.com/login/oauth/authorize") - .tokenUri("https://example.com/login/oauth/access_token") - .jwkSetUri("https://example.com/oauth2/jwk") - .issuerUri("https://example.com") - .userInfoUri("https://api.example.com/user") - .userNameAttributeName("id") - .clientName("Client Name") - .clientId("client-id") - .clientSecret("client-secret"); + .redirectUri("{baseUrl}/{action}/oauth2/code/{registrationId}") + .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).scope("read:user") + .authorizationUri("https://example.com/login/oauth/authorize") + .tokenUri("https://example.com/login/oauth/access_token").jwkSetUri("https://example.com/oauth2/jwk") + .issuerUri("https://example.com").userInfoUri("https://api.example.com/user") + .userNameAttributeName("id").clientName("Client Name").clientId("client-id") + .clientSecret("client-secret"); } public static ClientRegistration.Builder clientRegistration2() { return ClientRegistration.withRegistrationId("registration-id-2") .redirectUri("{baseUrl}/{action}/oauth2/code/{registrationId}") .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .scope("read:user") + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).scope("read:user") .authorizationUri("https://example.com/login/oauth/authorize") - .tokenUri("https://example.com/login/oauth/access_token") - .userInfoUri("https://api.example.com/user") - .userNameAttributeName("id") - .clientName("Client Name") - .clientId("client-id-2") + .tokenUri("https://example.com/login/oauth/access_token").userInfoUri("https://api.example.com/user") + .userNameAttributeName("id").clientName("Client Name").clientId("client-id-2") .clientSecret("client-secret"); } public static ClientRegistration.Builder clientCredentials() { - return clientRegistration() - .registrationId("client-credentials") - .clientId("client-id") + return clientRegistration().registrationId("client-credentials").clientId("client-id") .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS); } public static ClientRegistration.Builder password() { return ClientRegistration.withRegistrationId("password") .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .scope("read", "write") - .tokenUri("https://example.com/login/oauth/access_token") - .clientName("Client Name") - .clientId("client-id") - .clientSecret("client-secret"); + .authorizationGrantType(AuthorizationGrantType.PASSWORD).scope("read", "write") + .tokenUri("https://example.com/login/oauth/access_token").clientName("Client Name") + .clientId("client-id").clientSecret("client-secret"); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/CustomUserTypesOAuth2UserServiceTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/CustomUserTypesOAuth2UserServiceTests.java index 3305a1ebd9..1fde0671fd 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/CustomUserTypesOAuth2UserServiceTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/CustomUserTypesOAuth2UserServiceTests.java @@ -51,9 +51,13 @@ import static org.springframework.security.oauth2.core.TestOAuth2AccessTokens.no * @author Eddú Meléndez */ public class CustomUserTypesOAuth2UserServiceTests { + private ClientRegistration.Builder clientRegistrationBuilder; + private OAuth2AccessToken accessToken; + private CustomUserTypesOAuth2UserService userService; + private MockWebServer server; @Rule @@ -109,8 +113,8 @@ public class CustomUserTypesOAuth2UserServiceTests { @Test public void loadUserWhenCustomUserTypeNotFoundThenReturnNull() { - ClientRegistration clientRegistration = - clientRegistration().registrationId("other-client-registration-id-1").build(); + ClientRegistration clientRegistration = clientRegistration().registrationId("other-client-registration-id-1") + .build(); OAuth2User user = this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); assertThat(user).isNull(); @@ -118,18 +122,13 @@ public class CustomUserTypesOAuth2UserServiceTests { @Test public void loadUserWhenUserInfoSuccessResponseThenReturnUser() { - String userInfoResponse = "{\n" + - " \"id\": \"12345\",\n" + - " \"name\": \"first last\",\n" + - " \"login\": \"user1\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"id\": \"12345\",\n" + " \"name\": \"first last\",\n" + + " \"login\": \"user1\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri).build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); OAuth2User user = this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); @@ -147,20 +146,17 @@ public class CustomUserTypesOAuth2UserServiceTests { @Test public void loadUserWhenUserInfoSuccessResponseInvalidThenThrowOAuth2AuthenticationException() { this.exception.expect(OAuth2AuthenticationException.class); - this.exception.expectMessage(containsString("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); + this.exception.expectMessage(containsString( + "[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); - String userInfoResponse = "{\n" + - " \"id\": \"12345\",\n" + - " \"name\": \"first last\",\n" + - " \"login\": \"user1\",\n" + - " \"email\": \"user1@example.com\"\n"; -// "}\n"; // Make the JSON invalid/malformed + String userInfoResponse = "{\n" + " \"id\": \"12345\",\n" + " \"name\": \"first last\",\n" + + " \"login\": \"user1\",\n" + " \"email\": \"user1@example.com\"\n"; + // "}\n"; // Make the JSON invalid/malformed this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri).build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); } @@ -168,14 +164,14 @@ public class CustomUserTypesOAuth2UserServiceTests { @Test public void loadUserWhenServerErrorThenThrowOAuth2AuthenticationException() { this.exception.expect(OAuth2AuthenticationException.class); - this.exception.expectMessage(containsString("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource: 500 Server Error")); + this.exception.expectMessage(containsString( + "[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource: 500 Server Error")); this.server.enqueue(new MockResponse().setResponseCode(500)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri).build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); } @@ -183,35 +179,36 @@ public class CustomUserTypesOAuth2UserServiceTests { @Test public void loadUserWhenUserInfoUriInvalidThenThrowOAuth2AuthenticationException() { this.exception.expect(OAuth2AuthenticationException.class); - this.exception.expectMessage(containsString("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); + this.exception.expectMessage(containsString( + "[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); String userInfoUri = "https://invalid-provider.com/user"; - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri).build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build(); this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); } private ClientRegistration.Builder withRegistrationId(String registrationId) { - return ClientRegistration - .withRegistrationId(registrationId) - .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) - .clientId("client") + return ClientRegistration.withRegistrationId(registrationId) + .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).clientId("client") .tokenUri("/token"); } private MockResponse jsonResponse(String json) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json); + return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } public static class CustomOAuth2User implements OAuth2User { + private List authorities = AuthorityUtils.createAuthorityList("ROLE_USER"); + private String id; + private String name; + private String login; + private String email; public CustomOAuth2User() { @@ -264,5 +261,7 @@ public class CustomUserTypesOAuth2UserServiceTests { public void setEmail(String email) { this.email = email; } + } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserServiceTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserServiceTests.java index 6324322bea..2343e07b14 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserServiceTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserServiceTests.java @@ -64,9 +64,13 @@ import static org.springframework.security.oauth2.core.TestOAuth2AccessTokens.sc * @author Eddú Meléndez */ public class DefaultOAuth2UserServiceTests { + private ClientRegistration.Builder clientRegistrationBuilder; + private OAuth2AccessToken accessToken; + private DefaultOAuth2UserService userService = new DefaultOAuth2UserService(); + private MockWebServer server; @Rule @@ -76,9 +80,7 @@ public class DefaultOAuth2UserServiceTests { public void setup() throws Exception { this.server = new MockWebServer(); this.server.start(); - this.clientRegistrationBuilder = clientRegistration() - .userInfoUri(null) - .userNameAttributeName(null); + this.clientRegistrationBuilder = clientRegistration().userInfoUri(null).userNameAttributeName(null); this.accessToken = noScopes(); } @@ -119,29 +121,22 @@ public class DefaultOAuth2UserServiceTests { this.exception.expect(OAuth2AuthenticationException.class); this.exception.expectMessage(containsString("missing_user_name_attribute")); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri("https://provider.com/user").build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri("https://provider.com/user") + .build(); this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); } @Test public void loadUserWhenUserInfoSuccessResponseThenReturnUser() { - String userInfoResponse = "{\n" + - " \"user-name\": \"user1\",\n" + - " \"first-name\": \"first\",\n" + - " \"last-name\": \"last\",\n" + - " \"middle-name\": \"middle\",\n" + - " \"address\": \"address\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"user-name\": \"user1\",\n" + " \"first-name\": \"first\",\n" + + " \"last-name\": \"last\",\n" + " \"middle-name\": \"middle\",\n" + + " \"address\": \"address\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri) - .userInfoAuthenticationMethod(AuthenticationMethod.HEADER) - .userNameAttributeName("user-name").build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri) + .userInfoAuthenticationMethod(AuthenticationMethod.HEADER).userNameAttributeName("user-name").build(); OAuth2User user = this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); @@ -164,24 +159,19 @@ public class DefaultOAuth2UserServiceTests { @Test public void loadUserWhenUserInfoSuccessResponseInvalidThenThrowOAuth2AuthenticationException() { this.exception.expect(OAuth2AuthenticationException.class); - this.exception.expectMessage(containsString("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); + this.exception.expectMessage(containsString( + "[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); - String userInfoResponse = "{\n" + - " \"user-name\": \"user1\",\n" + - " \"first-name\": \"first\",\n" + - " \"last-name\": \"last\",\n" + - " \"middle-name\": \"middle\",\n" + - " \"address\": \"address\",\n" + - " \"email\": \"user1@example.com\"\n"; -// "}\n"; // Make the JSON invalid/malformed + String userInfoResponse = "{\n" + " \"user-name\": \"user1\",\n" + " \"first-name\": \"first\",\n" + + " \"last-name\": \"last\",\n" + " \"middle-name\": \"middle\",\n" + + " \"address\": \"address\",\n" + " \"email\": \"user1@example.com\"\n"; + // "}\n"; // Make the JSON invalid/malformed this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri) - .userInfoAuthenticationMethod(AuthenticationMethod.HEADER) - .userNameAttributeName("user-name").build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri) + .userInfoAuthenticationMethod(AuthenticationMethod.HEADER).userNameAttributeName("user-name").build(); this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); } @@ -189,8 +179,10 @@ public class DefaultOAuth2UserServiceTests { @Test public void loadUserWhenUserInfoErrorResponseWwwAuthenticateHeaderThenThrowOAuth2AuthenticationException() { this.exception.expect(OAuth2AuthenticationException.class); - this.exception.expectMessage(containsString("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); - this.exception.expectMessage(containsString("Error Code: insufficient_scope, Error Description: The access token expired")); + this.exception.expectMessage(containsString( + "[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); + this.exception.expectMessage( + containsString("Error Code: insufficient_scope, Error Description: The access token expired")); String wwwAuthenticateHeader = "Bearer realm=\"auth-realm\" error=\"insufficient_scope\" error_description=\"The access token expired\""; @@ -201,10 +193,8 @@ public class DefaultOAuth2UserServiceTests { String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri) - .userInfoAuthenticationMethod(AuthenticationMethod.HEADER) - .userNameAttributeName("user-name").build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri) + .userInfoAuthenticationMethod(AuthenticationMethod.HEADER).userNameAttributeName("user-name").build(); this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); } @@ -212,20 +202,17 @@ public class DefaultOAuth2UserServiceTests { @Test public void loadUserWhenUserInfoErrorResponseThenThrowOAuth2AuthenticationException() { this.exception.expect(OAuth2AuthenticationException.class); - this.exception.expectMessage(containsString("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); + this.exception.expectMessage(containsString( + "[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); this.exception.expectMessage(containsString("Error Code: invalid_token")); - String userInfoErrorResponse = "{\n" + - " \"error\": \"invalid_token\"\n" + - "}\n"; + String userInfoErrorResponse = "{\n" + " \"error\": \"invalid_token\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoErrorResponse).setResponseCode(400)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri) - .userInfoAuthenticationMethod(AuthenticationMethod.HEADER) - .userNameAttributeName("user-name").build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri) + .userInfoAuthenticationMethod(AuthenticationMethod.HEADER).userNameAttributeName("user-name").build(); this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); } @@ -233,16 +220,15 @@ public class DefaultOAuth2UserServiceTests { @Test public void loadUserWhenServerErrorThenThrowOAuth2AuthenticationException() { this.exception.expect(OAuth2AuthenticationException.class); - this.exception.expectMessage(containsString("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource: 500 Server Error")); + this.exception.expectMessage(containsString( + "[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource: 500 Server Error")); this.server.enqueue(new MockResponse().setResponseCode(500)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri) - .userInfoAuthenticationMethod(AuthenticationMethod.HEADER) - .userNameAttributeName("user-name").build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri) + .userInfoAuthenticationMethod(AuthenticationMethod.HEADER).userNameAttributeName("user-name").build(); this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); } @@ -250,14 +236,13 @@ public class DefaultOAuth2UserServiceTests { @Test public void loadUserWhenUserInfoUriInvalidThenThrowOAuth2AuthenticationException() { this.exception.expect(OAuth2AuthenticationException.class); - this.exception.expectMessage(containsString("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); + this.exception.expectMessage(containsString( + "[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource")); String userInfoUri = "https://invalid-provider.com/user"; - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri) - .userInfoAuthenticationMethod(AuthenticationMethod.HEADER) - .userNameAttributeName("user-name").build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri) + .userInfoAuthenticationMethod(AuthenticationMethod.HEADER).userNameAttributeName("user-name").build(); this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); } @@ -265,22 +250,15 @@ public class DefaultOAuth2UserServiceTests { // gh-5294 @Test public void loadUserWhenUserInfoSuccessResponseThenAcceptHeaderJson() throws Exception { - String userInfoResponse = "{\n" + - " \"user-name\": \"user1\",\n" + - " \"first-name\": \"first\",\n" + - " \"last-name\": \"last\",\n" + - " \"middle-name\": \"middle\",\n" + - " \"address\": \"address\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"user-name\": \"user1\",\n" + " \"first-name\": \"first\",\n" + + " \"last-name\": \"last\",\n" + " \"middle-name\": \"middle\",\n" + + " \"address\": \"address\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri) - .userInfoAuthenticationMethod(AuthenticationMethod.HEADER) - .userNameAttributeName("user-name").build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri) + .userInfoAuthenticationMethod(AuthenticationMethod.HEADER).userNameAttributeName("user-name").build(); this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); assertThat(this.server.takeRequest(1, TimeUnit.SECONDS).getHeader(HttpHeaders.ACCEPT)) @@ -290,49 +268,36 @@ public class DefaultOAuth2UserServiceTests { // gh-5500 @Test public void loadUserWhenAuthenticationMethodHeaderSuccessResponseThenHttpMethodGet() throws Exception { - String userInfoResponse = "{\n" + - " \"user-name\": \"user1\",\n" + - " \"first-name\": \"first\",\n" + - " \"last-name\": \"last\",\n" + - " \"middle-name\": \"middle\",\n" + - " \"address\": \"address\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"user-name\": \"user1\",\n" + " \"first-name\": \"first\",\n" + + " \"last-name\": \"last\",\n" + " \"middle-name\": \"middle\",\n" + + " \"address\": \"address\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri) - .userInfoAuthenticationMethod(AuthenticationMethod.HEADER) - .userNameAttributeName("user-name").build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri) + .userInfoAuthenticationMethod(AuthenticationMethod.HEADER).userNameAttributeName("user-name").build(); this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); RecordedRequest request = this.server.takeRequest(); assertThat(request.getMethod()).isEqualTo(HttpMethod.GET.name()); assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON_VALUE); - assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("Bearer " + this.accessToken.getTokenValue()); + assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)) + .isEqualTo("Bearer " + this.accessToken.getTokenValue()); } // gh-5500 @Test public void loadUserWhenAuthenticationMethodFormSuccessResponseThenHttpMethodPost() throws Exception { - String userInfoResponse = "{\n" + - " \"user-name\": \"user1\",\n" + - " \"first-name\": \"first\",\n" + - " \"last-name\": \"last\",\n" + - " \"middle-name\": \"middle\",\n" + - " \"address\": \"address\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"user-name\": \"user1\",\n" + " \"first-name\": \"first\",\n" + + " \"last-name\": \"last\",\n" + " \"middle-name\": \"middle\",\n" + + " \"address\": \"address\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; this.server.enqueue(jsonResponse(userInfoResponse)); String userInfoUri = this.server.url("/user").toString(); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri) - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .userNameAttributeName("user-name").build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri) + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).userNameAttributeName("user-name").build(); this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); RecordedRequest request = this.server.takeRequest(); @@ -347,8 +312,8 @@ public class DefaultOAuth2UserServiceTests { Map body = new HashMap<>(); body.put("id", "id"); DefaultOAuth2UserService userService = withMockResponse(body); - OAuth2UserRequest request = new OAuth2UserRequest( - clientRegistration().build(), scopes("message:read", "message:write")); + OAuth2UserRequest request = new OAuth2UserRequest(clientRegistration().build(), + scopes("message:read", "message:write")); OAuth2User user = userService.loadUser(request); assertThat(user.getAuthorities()).hasSize(3); @@ -363,8 +328,7 @@ public class DefaultOAuth2UserServiceTests { Map body = new HashMap<>(); body.put("id", "id"); DefaultOAuth2UserService userService = withMockResponse(body); - OAuth2UserRequest request = new OAuth2UserRequest( - clientRegistration().build(), noScopes()); + OAuth2UserRequest request = new OAuth2UserRequest(clientRegistration().build(), noScopes()); OAuth2User user = userService.loadUser(request); assertThat(user.getAuthorities()).hasSize(1); @@ -379,18 +343,16 @@ public class DefaultOAuth2UserServiceTests { this.exception.expect(OAuth2AuthenticationException.class); this.exception.expectMessage(containsString( - "[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource " + - "from '" + userInfoUri + "': response contains invalid content type 'text/plain'.")); + "[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource " + + "from '" + userInfoUri + "': response contains invalid content type 'text/plain'.")); MockResponse response = new MockResponse(); response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE); response.setBody("invalid content type"); this.server.enqueue(response); - ClientRegistration clientRegistration = this.clientRegistrationBuilder - .userInfoUri(userInfoUri) - .userInfoAuthenticationMethod(AuthenticationMethod.HEADER) - .userNameAttributeName("user-name").build(); + ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri) + .userInfoAuthenticationMethod(AuthenticationMethod.HEADER).userNameAttributeName("user-name").build(); this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)); } @@ -408,8 +370,7 @@ public class DefaultOAuth2UserServiceTests { } private MockResponse jsonResponse(String json) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json); + return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/DefaultReactiveOAuth2UserServiceTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/DefaultReactiveOAuth2UserServiceTests.java index 476033286a..c4bbe2b1e2 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/DefaultReactiveOAuth2UserServiceTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/DefaultReactiveOAuth2UserServiceTests.java @@ -65,12 +65,13 @@ import static org.springframework.security.oauth2.core.TestOAuth2AccessTokens.sc * @since 5.1 */ public class DefaultReactiveOAuth2UserServiceTests { + private ClientRegistration.Builder clientRegistration; private DefaultReactiveOAuth2UserService userService = new DefaultReactiveOAuth2UserService(); - private OAuth2AccessToken accessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token", Instant.now(), Instant.now().plus(Duration.ofDays(1))); + private OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", + Instant.now(), Instant.now().plus(Duration.ofDays(1))); private MockWebServer server; @@ -81,8 +82,7 @@ public class DefaultReactiveOAuth2UserServiceTests { String userInfoUri = this.server.url("/user").toString(); - this.clientRegistration = TestClientRegistrations.clientRegistration() - .userInfoUri(userInfoUri); + this.clientRegistration = TestClientRegistrations.clientRegistration().userInfoUri(userInfoUri); } @After @@ -93,20 +93,15 @@ public class DefaultReactiveOAuth2UserServiceTests { @Test public void loadUserWhenUserRequestIsNullThenThrowIllegalArgumentException() { OAuth2UserRequest request = null; - StepVerifier.create(this.userService.loadUser(request)) - .expectError(IllegalArgumentException.class) - .verify(); + StepVerifier.create(this.userService.loadUser(request)).expectError(IllegalArgumentException.class).verify(); } @Test public void loadUserWhenUserInfoUriIsNullThenThrowOAuth2AuthenticationException() { this.clientRegistration.userInfoUri(null); - StepVerifier.create(this.userService.loadUser(oauth2UserRequest())) - .expectErrorSatisfies(t -> assertThat(t) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageContaining("missing_user_info_uri") - ) + StepVerifier.create(this.userService.loadUser(oauth2UserRequest())).expectErrorSatisfies(t -> assertThat(t) + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageContaining("missing_user_info_uri")) .verify(); } @@ -114,24 +109,16 @@ public class DefaultReactiveOAuth2UserServiceTests { public void loadUserWhenUserNameAttributeNameIsNullThenThrowOAuth2AuthenticationException() { this.clientRegistration.userNameAttributeName(null); - StepVerifier.create(this.userService.loadUser(oauth2UserRequest())) - .expectErrorSatisfies(t -> assertThat(t) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageContaining("missing_user_name_attribute") - ) + StepVerifier.create(this.userService.loadUser(oauth2UserRequest())).expectErrorSatisfies(t -> assertThat(t) + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageContaining("missing_user_name_attribute")) .verify(); } @Test public void loadUserWhenUserInfoSuccessResponseThenReturnUser() { - String userInfoResponse = "{\n" + - " \"id\": \"user1\",\n" + - " \"first-name\": \"first\",\n" + - " \"last-name\": \"last\",\n" + - " \"middle-name\": \"middle\",\n" + - " \"address\": \"address\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"id\": \"user1\",\n" + " \"first-name\": \"first\",\n" + + " \"last-name\": \"last\",\n" + " \"middle-name\": \"middle\",\n" + + " \"address\": \"address\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; enqueueApplicationJsonBody(userInfoResponse); OAuth2User user = this.userService.loadUser(oauth2UserRequest()).block(); @@ -156,14 +143,9 @@ public class DefaultReactiveOAuth2UserServiceTests { @Test public void loadUserWhenAuthenticationMethodHeaderSuccessResponseThenHttpMethodGet() throws Exception { this.clientRegistration.userInfoAuthenticationMethod(AuthenticationMethod.HEADER); - String userInfoResponse = "{\n" + - " \"id\": \"user1\",\n" + - " \"first-name\": \"first\",\n" + - " \"last-name\": \"last\",\n" + - " \"middle-name\": \"middle\",\n" + - " \"address\": \"address\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + String userInfoResponse = "{\n" + " \"id\": \"user1\",\n" + " \"first-name\": \"first\",\n" + + " \"last-name\": \"last\",\n" + " \"middle-name\": \"middle\",\n" + + " \"address\": \"address\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; enqueueApplicationJsonBody(userInfoResponse); this.userService.loadUser(oauth2UserRequest()).block(); @@ -171,21 +153,17 @@ public class DefaultReactiveOAuth2UserServiceTests { RecordedRequest request = this.server.takeRequest(); assertThat(request.getMethod()).isEqualTo(HttpMethod.GET.name()); assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON_VALUE); - assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("Bearer " + this.accessToken.getTokenValue()); + assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)) + .isEqualTo("Bearer " + this.accessToken.getTokenValue()); } // gh-5500 @Test public void loadUserWhenAuthenticationMethodFormSuccessResponseThenHttpMethodPost() throws Exception { - this.clientRegistration.userInfoAuthenticationMethod( AuthenticationMethod.FORM); - String userInfoResponse = "{\n" + - " \"id\": \"user1\",\n" + - " \"first-name\": \"first\",\n" + - " \"last-name\": \"last\",\n" + - " \"middle-name\": \"middle\",\n" + - " \"address\": \"address\",\n" + - " \"email\": \"user1@example.com\"\n" + - "}\n"; + this.clientRegistration.userInfoAuthenticationMethod(AuthenticationMethod.FORM); + String userInfoResponse = "{\n" + " \"id\": \"user1\",\n" + " \"first-name\": \"first\",\n" + + " \"last-name\": \"last\",\n" + " \"middle-name\": \"middle\",\n" + + " \"address\": \"address\",\n" + " \"email\": \"user1@example.com\"\n" + "}\n"; enqueueApplicationJsonBody(userInfoResponse); this.userService.loadUser(oauth2UserRequest()).block(); @@ -199,28 +177,23 @@ public class DefaultReactiveOAuth2UserServiceTests { @Test public void loadUserWhenUserInfoSuccessResponseInvalidThenThrowOAuth2AuthenticationException() { - String userInfoResponse = "{\n" + - " \"id\": \"user1\",\n" + - " \"first-name\": \"first\",\n" + - " \"last-name\": \"last\",\n" + - " \"middle-name\": \"middle\",\n" + - " \"address\": \"address\",\n" + - " \"email\": \"user1@example.com\"\n"; - // "}\n"; // Make the JSON invalid/malformed + String userInfoResponse = "{\n" + " \"id\": \"user1\",\n" + " \"first-name\": \"first\",\n" + + " \"last-name\": \"last\",\n" + " \"middle-name\": \"middle\",\n" + + " \"address\": \"address\",\n" + " \"email\": \"user1@example.com\"\n"; + // "}\n"; // Make the JSON invalid/malformed enqueueApplicationJsonBody(userInfoResponse); assertThatThrownBy(() -> this.userService.loadUser(oauth2UserRequest()).block()) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageContaining("invalid_user_info_response"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageContaining("invalid_user_info_response"); } @Test public void loadUserWhenUserInfoErrorResponseThenThrowOAuth2AuthenticationException() { - this.server.enqueue(new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setResponseCode(500).setBody("{}")); + this.server.enqueue(new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .setResponseCode(500).setBody("{}")); assertThatThrownBy(() -> this.userService.loadUser(oauth2UserRequest()).block()) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageContaining("invalid_user_info_response"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageContaining("invalid_user_info_response"); } @Test @@ -235,8 +208,8 @@ public class DefaultReactiveOAuth2UserServiceTests { Map body = new HashMap<>(); body.put("id", "id"); DefaultReactiveOAuth2UserService userService = withMockResponse(body); - OAuth2UserRequest request = new OAuth2UserRequest( - clientRegistration().build(), scopes("message:read", "message:write")); + OAuth2UserRequest request = new OAuth2UserRequest(clientRegistration().build(), + scopes("message:read", "message:write")); OAuth2User user = userService.loadUser(request).block(); assertThat(user.getAuthorities()).hasSize(3); @@ -251,8 +224,7 @@ public class DefaultReactiveOAuth2UserServiceTests { Map body = new HashMap<>(); body.put("id", "id"); DefaultReactiveOAuth2UserService userService = withMockResponse(body); - OAuth2UserRequest request = new OAuth2UserRequest( - clientRegistration().build(), noScopes()); + OAuth2UserRequest request = new OAuth2UserRequest(clientRegistration().build(), noScopes()); OAuth2User user = userService.loadUser(request).block(); assertThat(user.getAuthorities()).hasSize(1); @@ -271,10 +243,11 @@ public class DefaultReactiveOAuth2UserServiceTests { OAuth2UserRequest userRequest = oauth2UserRequest(); assertThatThrownBy(() -> this.userService.loadUser(userRequest).block()) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageContaining("[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource from '" + - userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri() + "': " + - "response contains invalid content type 'text/plain'"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageContaining( + "[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource from '" + + userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint() + .getUri() + + "': " + "response contains invalid content type 'text/plain'"); } private DefaultReactiveOAuth2UserService withMockResponse(Map body) { @@ -284,10 +257,8 @@ public class DefaultReactiveOAuth2UserServiceTests { WebClient.ResponseSpec clientResponse = mock(WebClient.ResponseSpec.class); when(rest.get()).thenReturn(spec); when(spec.retrieve()).thenReturn(clientResponse); - when(clientResponse.onStatus(any(Predicate.class), any(Function.class))) - .thenReturn(clientResponse); - when(clientResponse.bodyToMono(any(ParameterizedTypeReference.class))) - .thenReturn(Mono.just(body)); + when(clientResponse.onStatus(any(Predicate.class), any(Function.class))).thenReturn(clientResponse); + when(clientResponse.bodyToMono(any(ParameterizedTypeReference.class))).thenReturn(Mono.just(body)); DefaultReactiveOAuth2UserService userService = new DefaultReactiveOAuth2UserService(); userService.setWebClient(rest); @@ -300,8 +271,8 @@ public class DefaultReactiveOAuth2UserServiceTests { private void enqueueApplicationJsonBody(String json) { - this.server.enqueue(new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json)); + this.server.enqueue( + new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json)); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/DelegatingOAuth2UserServiceTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/DelegatingOAuth2UserServiceTests.java index f43b18a0ae..976841b553 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/DelegatingOAuth2UserServiceTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/DelegatingOAuth2UserServiceTests.java @@ -46,8 +46,7 @@ public class DelegatingOAuth2UserServiceTests { @Test(expected = IllegalArgumentException.class) @SuppressWarnings("unchecked") public void loadUserWhenUserRequestIsNullThenThrowIllegalArgumentException() { - DelegatingOAuth2UserService delegatingUserService = - new DelegatingOAuth2UserService<>( + DelegatingOAuth2UserService delegatingUserService = new DelegatingOAuth2UserService<>( Arrays.asList(mock(OAuth2UserService.class), mock(OAuth2UserService.class))); delegatingUserService.loadUser(null); } @@ -61,8 +60,8 @@ public class DelegatingOAuth2UserServiceTests { OAuth2User mockUser = mock(OAuth2User.class); when(userService3.loadUser(any(OAuth2UserRequest.class))).thenReturn(mockUser); - DelegatingOAuth2UserService delegatingUserService = - new DelegatingOAuth2UserService<>(Arrays.asList(userService1, userService2, userService3)); + DelegatingOAuth2UserService delegatingUserService = new DelegatingOAuth2UserService<>( + Arrays.asList(userService1, userService2, userService3)); OAuth2User loadedUser = delegatingUserService.loadUser(mock(OAuth2UserRequest.class)); assertThat(loadedUser).isEqualTo(mockUser); @@ -75,10 +74,11 @@ public class DelegatingOAuth2UserServiceTests { OAuth2UserService userService2 = mock(OAuth2UserService.class); OAuth2UserService userService3 = mock(OAuth2UserService.class); - DelegatingOAuth2UserService delegatingUserService = - new DelegatingOAuth2UserService<>(Arrays.asList(userService1, userService2, userService3)); + DelegatingOAuth2UserService delegatingUserService = new DelegatingOAuth2UserService<>( + Arrays.asList(userService1, userService2, userService3)); OAuth2User loadedUser = delegatingUserService.loadUser(mock(OAuth2UserRequest.class)); assertThat(loadedUser).isNull(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequestEntityConverterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequestEntityConverterTests.java index 4ad9d4e4aa..1d24762f7d 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequestEntityConverterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequestEntityConverterTests.java @@ -40,56 +40,54 @@ import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VAL * @author Joe Grandja */ public class OAuth2UserRequestEntityConverterTests { + private OAuth2UserRequestEntityConverter converter = new OAuth2UserRequestEntityConverter(); @SuppressWarnings("unchecked") @Test public void convertWhenAuthenticationMethodHeaderThenGetRequest() { ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); - OAuth2UserRequest userRequest = new OAuth2UserRequest( - clientRegistration, this.createAccessToken()); + OAuth2UserRequest userRequest = new OAuth2UserRequest(clientRegistration, this.createAccessToken()); RequestEntity requestEntity = this.converter.convert(userRequest); assertThat(requestEntity.getMethod()).isEqualTo(HttpMethod.GET); - assertThat(requestEntity.getUrl().toASCIIString()).isEqualTo( - clientRegistration.getProviderDetails().getUserInfoEndpoint().getUri()); + assertThat(requestEntity.getUrl().toASCIIString()) + .isEqualTo(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUri()); HttpHeaders headers = requestEntity.getHeaders(); assertThat(headers.getAccept()).contains(MediaType.APPLICATION_JSON); - assertThat(headers.getFirst(HttpHeaders.AUTHORIZATION)).isEqualTo( - "Bearer " + userRequest.getAccessToken().getTokenValue()); + assertThat(headers.getFirst(HttpHeaders.AUTHORIZATION)) + .isEqualTo("Bearer " + userRequest.getAccessToken().getTokenValue()); } @SuppressWarnings("unchecked") @Test public void convertWhenAuthenticationMethodFormThenPostRequest() { ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration() - .userInfoAuthenticationMethod(AuthenticationMethod.FORM) - .build(); - OAuth2UserRequest userRequest = new OAuth2UserRequest( - clientRegistration, this.createAccessToken()); + .userInfoAuthenticationMethod(AuthenticationMethod.FORM).build(); + OAuth2UserRequest userRequest = new OAuth2UserRequest(clientRegistration, this.createAccessToken()); RequestEntity requestEntity = this.converter.convert(userRequest); assertThat(requestEntity.getMethod()).isEqualTo(HttpMethod.POST); - assertThat(requestEntity.getUrl().toASCIIString()).isEqualTo( - clientRegistration.getProviderDetails().getUserInfoEndpoint().getUri()); + assertThat(requestEntity.getUrl().toASCIIString()) + .isEqualTo(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUri()); HttpHeaders headers = requestEntity.getHeaders(); assertThat(headers.getAccept()).contains(MediaType.APPLICATION_JSON); - assertThat(headers.getContentType()).isEqualTo( - MediaType.valueOf(APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")); + assertThat(headers.getContentType()) + .isEqualTo(MediaType.valueOf(APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")); MultiValueMap formParameters = (MultiValueMap) requestEntity.getBody(); - assertThat(formParameters.getFirst(OAuth2ParameterNames.ACCESS_TOKEN)).isEqualTo( - userRequest.getAccessToken().getTokenValue()); + assertThat(formParameters.getFirst(OAuth2ParameterNames.ACCESS_TOKEN)) + .isEqualTo(userRequest.getAccessToken().getTokenValue()); } private OAuth2AccessToken createAccessToken() { - OAuth2AccessToken accessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token-1234", Instant.now(), - Instant.now().plusSeconds(3600), new LinkedHashSet<>(Arrays.asList("read", "write"))); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token-1234", + Instant.now(), Instant.now().plusSeconds(3600), new LinkedHashSet<>(Arrays.asList("read", "write"))); return accessToken; } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequestTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequestTests.java index 48dcd5eea4..4b683b86cb 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequestTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/userinfo/OAuth2UserRequestTests.java @@ -37,26 +37,23 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class OAuth2UserRequestTests { + private ClientRegistration clientRegistration; + private OAuth2AccessToken accessToken; + private Map additionalParameters; @Before public void setUp() { - this.clientRegistration = ClientRegistration.withRegistrationId("registration-1") - .clientId("client-1") - .clientSecret("secret") - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri("https://client.com") + this.clientRegistration = ClientRegistration.withRegistrationId("registration-1").clientId("client-1") + .clientSecret("secret").clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUri("https://client.com") .scope(new LinkedHashSet<>(Arrays.asList("scope1", "scope2"))) .authorizationUri("https://provider.com/oauth2/authorization") - .tokenUri("https://provider.com/oauth2/token") - .clientName("Client 1") - .build(); - this.accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "access-token-1234", Instant.now(), Instant.now().plusSeconds(60), - new LinkedHashSet<>(Arrays.asList("scope1", "scope2"))); + .tokenUri("https://provider.com/oauth2/token").clientName("Client 1").build(); + this.accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token-1234", Instant.now(), + Instant.now().plusSeconds(60), new LinkedHashSet<>(Arrays.asList("scope1", "scope2"))); this.additionalParameters = new HashMap<>(); this.additionalParameters.put("param1", "value1"); this.additionalParameters.put("param2", "value2"); @@ -76,11 +73,12 @@ public class OAuth2UserRequestTests { @Test public void constructorWhenAllParametersProvidedAndValidThenCreated() { - OAuth2UserRequest userRequest = new OAuth2UserRequest( - this.clientRegistration, this.accessToken, this.additionalParameters); + OAuth2UserRequest userRequest = new OAuth2UserRequest(this.clientRegistration, this.accessToken, + this.additionalParameters); assertThat(userRequest.getClientRegistration()).isEqualTo(this.clientRegistration); assertThat(userRequest.getAccessToken()).isEqualTo(this.accessToken); assertThat(userRequest.getAdditionalParameters()).containsAllEntriesOf(this.additionalParameters); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/AuthenticatedPrincipalOAuth2AuthorizedClientRepositoryTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/AuthenticatedPrincipalOAuth2AuthorizedClientRepositoryTests.java index e625e362b7..6d1f516676 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/AuthenticatedPrincipalOAuth2AuthorizedClientRepositoryTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/AuthenticatedPrincipalOAuth2AuthorizedClientRepositoryTests.java @@ -36,20 +36,29 @@ import static org.mockito.Mockito.verify; * @author Joe Grandja */ public class AuthenticatedPrincipalOAuth2AuthorizedClientRepositoryTests { + private String registrationId = "registrationId"; + private String principalName = "principalName"; + private OAuth2AuthorizedClientService authorizedClientService; + private OAuth2AuthorizedClientRepository anonymousAuthorizedClientRepository; + private AuthenticatedPrincipalOAuth2AuthorizedClientRepository authorizedClientRepository; + private MockHttpServletRequest request; + private MockHttpServletResponse response; @Before public void setup() { this.authorizedClientService = mock(OAuth2AuthorizedClientService.class); this.anonymousAuthorizedClientRepository = mock(OAuth2AuthorizedClientRepository.class); - this.authorizedClientRepository = new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(this.authorizedClientService); - this.authorizedClientRepository.setAnonymousAuthorizedClientRepository(this.anonymousAuthorizedClientRepository); + this.authorizedClientRepository = new AuthenticatedPrincipalOAuth2AuthorizedClientRepository( + this.authorizedClientService); + this.authorizedClientRepository + .setAnonymousAuthorizedClientRepository(this.anonymousAuthorizedClientRepository); this.request = new MockHttpServletRequest(); this.response = new MockHttpServletResponse(); } @@ -77,14 +86,16 @@ public class AuthenticatedPrincipalOAuth2AuthorizedClientRepositoryTests { public void loadAuthorizedClientWhenAnonymousPrincipalThenLoadFromAnonymousRepository() { Authentication authentication = this.createAnonymousPrincipal(); this.authorizedClientRepository.loadAuthorizedClient(this.registrationId, authentication, this.request); - verify(this.anonymousAuthorizedClientRepository).loadAuthorizedClient(this.registrationId, authentication, this.request); + verify(this.anonymousAuthorizedClientRepository).loadAuthorizedClient(this.registrationId, authentication, + this.request); } @Test public void saveAuthorizedClientWhenAuthenticatedPrincipalThenSaveToService() { Authentication authentication = this.createAuthenticatedPrincipal(); OAuth2AuthorizedClient authorizedClient = mock(OAuth2AuthorizedClient.class); - this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, authentication, this.request, this.response); + this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, authentication, this.request, + this.response); verify(this.authorizedClientService).saveAuthorizedClient(authorizedClient, authentication); } @@ -92,22 +103,27 @@ public class AuthenticatedPrincipalOAuth2AuthorizedClientRepositoryTests { public void saveAuthorizedClientWhenAnonymousPrincipalThenSaveToAnonymousRepository() { Authentication authentication = this.createAnonymousPrincipal(); OAuth2AuthorizedClient authorizedClient = mock(OAuth2AuthorizedClient.class); - this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, authentication, this.request, this.response); - verify(this.anonymousAuthorizedClientRepository).saveAuthorizedClient(authorizedClient, authentication, this.request, this.response); + this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, authentication, this.request, + this.response); + verify(this.anonymousAuthorizedClientRepository).saveAuthorizedClient(authorizedClient, authentication, + this.request, this.response); } @Test public void removeAuthorizedClientWhenAuthenticatedPrincipalThenRemoveFromService() { Authentication authentication = this.createAuthenticatedPrincipal(); - this.authorizedClientRepository.removeAuthorizedClient(this.registrationId, authentication, this.request, this.response); + this.authorizedClientRepository.removeAuthorizedClient(this.registrationId, authentication, this.request, + this.response); verify(this.authorizedClientService).removeAuthorizedClient(this.registrationId, this.principalName); } @Test public void removeAuthorizedClientWhenAnonymousPrincipalThenRemoveFromAnonymousRepository() { Authentication authentication = this.createAnonymousPrincipal(); - this.authorizedClientRepository.removeAuthorizedClient(this.registrationId, authentication, this.request, this.response); - verify(this.anonymousAuthorizedClientRepository).removeAuthorizedClient(this.registrationId, authentication, this.request, this.response); + this.authorizedClientRepository.removeAuthorizedClient(this.registrationId, authentication, this.request, + this.response); + verify(this.anonymousAuthorizedClientRepository).removeAuthorizedClient(this.registrationId, authentication, + this.request, this.response); } private Authentication createAuthenticatedPrincipal() { @@ -117,6 +133,8 @@ public class AuthenticatedPrincipalOAuth2AuthorizedClientRepositoryTests { } private Authentication createAnonymousPrincipal() { - return new AnonymousAuthenticationToken("key-1234", "anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); + return new AnonymousAuthenticationToken("key-1234", "anonymousUser", + AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizationRequestResolverTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizationRequestResolverTests.java index 2a861520a5..06272933ec 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizationRequestResolverTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizationRequestResolverTests.java @@ -45,13 +45,21 @@ import static org.assertj.core.api.Assertions.entry; * @author Joe Grandja */ public class DefaultOAuth2AuthorizationRequestResolverTests { + private ClientRegistration registration1; + private ClientRegistration registration2; + private ClientRegistration fineRedirectUriTemplateRegistration; + private ClientRegistration pkceRegistration; + private ClientRegistration oidcRegistration; + private ClientRegistrationRepository clientRegistrationRepository; + private final String authorizationRequestBaseUri = "/oauth2/authorization"; + private DefaultOAuth2AuthorizationRequestResolver resolver; @Before @@ -60,19 +68,15 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { this.registration2 = TestClientRegistrations.clientRegistration2().build(); this.fineRedirectUriTemplateRegistration = fineRedirectUriTemplateClientRegistration().build(); this.pkceRegistration = TestClientRegistrations.clientRegistration() - .registrationId("pkce-client-registration-id") - .clientId("pkce-client-id") - .clientAuthenticationMethod(ClientAuthenticationMethod.NONE) - .clientSecret(null) - .build(); - this.oidcRegistration = TestClientRegistrations.clientRegistration() - .registrationId("oidc-registration-id") + .registrationId("pkce-client-registration-id").clientId("pkce-client-id") + .clientAuthenticationMethod(ClientAuthenticationMethod.NONE).clientSecret(null).build(); + this.oidcRegistration = TestClientRegistrations.clientRegistration().registrationId("oidc-registration-id") .scope(OidcScopes.OPENID).build(); - this.clientRegistrationRepository = new InMemoryClientRegistrationRepository( - this.registration1, this.registration2, this.fineRedirectUriTemplateRegistration, - this.pkceRegistration, this.oidcRegistration); - this.resolver = new DefaultOAuth2AuthorizationRequestResolver( - this.clientRegistrationRepository, this.authorizationRequestBaseUri); + this.clientRegistrationRepository = new InMemoryClientRegistrationRepository(this.registration1, + this.registration2, this.fineRedirectUriTemplateRegistration, this.pkceRegistration, + this.oidcRegistration); + this.resolver = new DefaultOAuth2AuthorizationRequestResolver(this.clientRegistrationRepository, + this.authorizationRequestBaseUri); } @Test @@ -125,13 +129,14 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { @Test public void resolveWhenAuthorizationRequestWithInvalidClientThenThrowIllegalArgumentException() { ClientRegistration clientRegistration = this.registration1; - String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId() + "-invalid"; + String requestUri = this.authorizationRequestBaseUri + "/" + clientRegistration.getRegistrationId() + + "-invalid"; MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); - assertThatThrownBy(() -> this.resolver.resolve(request)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Invalid Client Registration with Id: " + clientRegistration.getRegistrationId() + "-invalid"); + assertThatThrownBy(() -> this.resolver.resolve(request)).isInstanceOf(IllegalArgumentException.class) + .hasMessage( + "Invalid Client Registration with Id: " + clientRegistration.getRegistrationId() + "-invalid"); } @Test @@ -143,8 +148,8 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest).isNotNull(); - assertThat(authorizationRequest.getAuthorizationUri()).isEqualTo( - clientRegistration.getProviderDetails().getAuthorizationUri()); + assertThat(authorizationRequest.getAuthorizationUri()) + .isEqualTo(clientRegistration.getProviderDetails().getAuthorizationUri()); assertThat(authorizationRequest.getGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); assertThat(authorizationRequest.getResponseType()).isEqualTo(OAuth2AuthorizationResponseType.CODE); assertThat(authorizationRequest.getClientId()).isEqualTo(clientRegistration.getClientId()); @@ -152,14 +157,14 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { .isEqualTo("http://localhost/login/oauth2/code/" + clientRegistration.getRegistrationId()); assertThat(authorizationRequest.getScopes()).isEqualTo(clientRegistration.getScopes()); assertThat(authorizationRequest.getState()).isNotNull(); - assertThat(authorizationRequest.getAdditionalParameters()).doesNotContainKey(OAuth2ParameterNames.REGISTRATION_ID); + assertThat(authorizationRequest.getAdditionalParameters()) + .doesNotContainKey(OAuth2ParameterNames.REGISTRATION_ID); assertThat(authorizationRequest.getAttributes()) .containsExactly(entry(OAuth2ParameterNames.REGISTRATION_ID, clientRegistration.getRegistrationId())); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=read:user&state=.{15,}&" + - "redirect_uri=http://localhost/login/oauth2/code/registration-id"); + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" + + "scope=read:user&state=.{15,}&" + + "redirect_uri=http://localhost/login/oauth2/code/registration-id"); } @Test @@ -169,7 +174,8 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); - OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request, clientRegistration.getRegistrationId()); + OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request, + clientRegistration.getRegistrationId()); assertThat(authorizationRequest).isNotNull(); assertThat(authorizationRequest.getAttributes()) .containsExactly(entry(OAuth2ParameterNames.REGISTRATION_ID, clientRegistration.getRegistrationId())); @@ -183,10 +189,9 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { request.setServletPath(requestUri); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); - assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo( - clientRegistration.getRedirectUri()); - assertThat(authorizationRequest.getRedirectUri()).isEqualTo( - "http://localhost/login/oauth2/code/" + clientRegistration.getRegistrationId()); + assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo(clientRegistration.getRedirectUri()); + assertThat(authorizationRequest.getRedirectUri()) + .isEqualTo("http://localhost/login/oauth2/code/" + clientRegistration.getRegistrationId()); } @Test @@ -199,8 +204,8 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo(clientRegistration.getRedirectUri()); - assertThat(authorizationRequest.getRedirectUri()).isEqualTo( - "http://localhost:8080/login/oauth2/code/" + clientRegistration.getRegistrationId()); + assertThat(authorizationRequest.getRedirectUri()) + .isEqualTo("http://localhost:8080/login/oauth2/code/" + clientRegistration.getRegistrationId()); } @Test @@ -214,8 +219,8 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo(clientRegistration.getRedirectUri()); - assertThat(authorizationRequest.getRedirectUri()).isEqualTo( - "https://localhost:8081/login/oauth2/code/" + clientRegistration.getRegistrationId()); + assertThat(authorizationRequest.getRedirectUri()) + .isEqualTo("https://localhost:8081/login/oauth2/code/" + clientRegistration.getRegistrationId()); } @Test @@ -229,8 +234,8 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo(clientRegistration.getRedirectUri()); - assertThat(authorizationRequest.getRedirectUri()).isEqualTo( - "http://localhost/login/oauth2/code/" + clientRegistration.getRegistrationId()); + assertThat(authorizationRequest.getRedirectUri()) + .isEqualTo("http://localhost/login/oauth2/code/" + clientRegistration.getRegistrationId()); } @Test @@ -244,8 +249,8 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo(clientRegistration.getRedirectUri()); - assertThat(authorizationRequest.getRedirectUri()).isEqualTo( - "https://localhost/login/oauth2/code/" + clientRegistration.getRegistrationId()); + assertThat(authorizationRequest.getRedirectUri()) + .isEqualTo("https://localhost/login/oauth2/code/" + clientRegistration.getRegistrationId()); } @Test @@ -259,8 +264,8 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo(clientRegistration.getRedirectUri()); - assertThat(authorizationRequest.getRedirectUri()).isEqualTo( - "https://localhost/login/oauth2/code/" + clientRegistration.getRegistrationId()); + assertThat(authorizationRequest.getRedirectUri()) + .isEqualTo("https://localhost/login/oauth2/code/" + clientRegistration.getRegistrationId()); } // gh-5520 @@ -273,10 +278,9 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { request.setQueryString("foo=bar"); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); - assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo( - clientRegistration.getRedirectUri()); - assertThat(authorizationRequest.getRedirectUri()).isEqualTo( - "http://localhost/login/oauth2/code/" + clientRegistration.getRegistrationId()); + assertThat(authorizationRequest.getRedirectUri()).isNotEqualTo(clientRegistration.getRedirectUri()); + assertThat(authorizationRequest.getRedirectUri()) + .isEqualTo("http://localhost/login/oauth2/code/" + clientRegistration.getRegistrationId()); } @Test @@ -291,10 +295,9 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=read:user&state=.{15,}&" + - "redirect_uri=http://localhost/login/oauth2/code/registration-id"); + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" + + "scope=read:user&state=.{15,}&" + + "redirect_uri=http://localhost/login/oauth2/code/registration-id"); } @Test @@ -309,10 +312,9 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=read:user&state=.{15,}&" + - "redirect_uri=https://example.com/login/oauth2/code/registration-id"); + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" + + "scope=read:user&state=.{15,}&" + + "redirect_uri=https://example.com/login/oauth2/code/registration-id"); } @Test @@ -322,12 +324,12 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); - OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request, clientRegistration.getRegistrationId()); + OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request, + clientRegistration.getRegistrationId()); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=read:user&state=.{15,}&" + - "redirect_uri=http://localhost/authorize/oauth2/code/registration-id"); + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" + + "scope=read:user&state=.{15,}&" + + "redirect_uri=http://localhost/authorize/oauth2/code/registration-id"); } @Test @@ -339,10 +341,9 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id-2&" + - "scope=read:user&state=.{15,}&" + - "redirect_uri=http://localhost/login/oauth2/code/registration-id-2"); + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id-2&" + + "scope=read:user&state=.{15,}&" + + "redirect_uri=http://localhost/login/oauth2/code/registration-id-2"); } @Test @@ -355,10 +356,9 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=read:user&state=.{15,}&" + - "redirect_uri=http://localhost/authorize/oauth2/code/registration-id"); + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" + + "scope=read:user&state=.{15,}&" + + "redirect_uri=http://localhost/authorize/oauth2/code/registration-id"); } @Test @@ -371,10 +371,9 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id-2&" + - "scope=read:user&state=.{15,}&" + - "redirect_uri=http://localhost/login/oauth2/code/registration-id-2"); + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id-2&" + + "scope=read:user&state=.{15,}&" + + "redirect_uri=http://localhost/login/oauth2/code/registration-id-2"); } @Test @@ -386,8 +385,8 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest).isNotNull(); - assertThat(authorizationRequest.getAuthorizationUri()).isEqualTo( - clientRegistration.getProviderDetails().getAuthorizationUri()); + assertThat(authorizationRequest.getAuthorizationUri()) + .isEqualTo(clientRegistration.getProviderDetails().getAuthorizationUri()); assertThat(authorizationRequest.getGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); assertThat(authorizationRequest.getResponseType()).isEqualTo(OAuth2AuthorizationResponseType.CODE); assertThat(authorizationRequest.getClientId()).isEqualTo(clientRegistration.getClientId()); @@ -395,22 +394,21 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { .isEqualTo("http://localhost/login/oauth2/code/" + clientRegistration.getRegistrationId()); assertThat(authorizationRequest.getScopes()).isEqualTo(clientRegistration.getScopes()); assertThat(authorizationRequest.getState()).isNotNull(); - assertThat(authorizationRequest.getAdditionalParameters()).doesNotContainKey(OAuth2ParameterNames.REGISTRATION_ID); + assertThat(authorizationRequest.getAdditionalParameters()) + .doesNotContainKey(OAuth2ParameterNames.REGISTRATION_ID); assertThat(authorizationRequest.getAdditionalParameters()).containsKey(PkceParameterNames.CODE_CHALLENGE); assertThat(authorizationRequest.getAdditionalParameters()) .contains(entry(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256")); assertThat(authorizationRequest.getAttributes()) .contains(entry(OAuth2ParameterNames.REGISTRATION_ID, clientRegistration.getRegistrationId())); - assertThat(authorizationRequest.getAttributes()) - .containsKey(PkceParameterNames.CODE_VERIFIER); - assertThat((String) authorizationRequest.getAttribute(PkceParameterNames.CODE_VERIFIER)).matches("^([a-zA-Z0-9\\-\\.\\_\\~]){128}$"); + assertThat(authorizationRequest.getAttributes()).containsKey(PkceParameterNames.CODE_VERIFIER); + assertThat((String) authorizationRequest.getAttribute(PkceParameterNames.CODE_VERIFIER)) + .matches("^([a-zA-Z0-9\\-\\.\\_\\~]){128}$"); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=pkce-client-id&" + - "scope=read:user&state=.{15,}&" + - "redirect_uri=http://localhost/login/oauth2/code/pkce-client-registration-id&" + - "code_challenge_method=S256&" + - "code_challenge=([a-zA-Z0-9\\-\\.\\_\\~]){43}"); + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=pkce-client-id&" + + "scope=read:user&state=.{15,}&" + + "redirect_uri=http://localhost/login/oauth2/code/pkce-client-registration-id&" + + "code_challenge_method=S256&" + "code_challenge=([a-zA-Z0-9\\-\\.\\_\\~]){43}"); } @Test @@ -422,8 +420,8 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest).isNotNull(); - assertThat(authorizationRequest.getAuthorizationUri()).isEqualTo( - clientRegistration.getProviderDetails().getAuthorizationUri()); + assertThat(authorizationRequest.getAuthorizationUri()) + .isEqualTo(clientRegistration.getProviderDetails().getAuthorizationUri()); assertThat(authorizationRequest.getGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); assertThat(authorizationRequest.getResponseType()).isEqualTo(OAuth2AuthorizationResponseType.CODE); assertThat(authorizationRequest.getClientId()).isEqualTo(clientRegistration.getClientId()); @@ -431,18 +429,19 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { .isEqualTo("http://localhost/login/oauth2/code/" + clientRegistration.getRegistrationId()); assertThat(authorizationRequest.getScopes()).isEqualTo(clientRegistration.getScopes()); assertThat(authorizationRequest.getState()).isNotNull(); - assertThat(authorizationRequest.getAdditionalParameters()).doesNotContainKey(OAuth2ParameterNames.REGISTRATION_ID); + assertThat(authorizationRequest.getAdditionalParameters()) + .doesNotContainKey(OAuth2ParameterNames.REGISTRATION_ID); assertThat(authorizationRequest.getAdditionalParameters()).containsKey(OidcParameterNames.NONCE); assertThat(authorizationRequest.getAttributes()) .contains(entry(OAuth2ParameterNames.REGISTRATION_ID, clientRegistration.getRegistrationId())); assertThat(authorizationRequest.getAttributes()).containsKey(OidcParameterNames.NONCE); - assertThat((String) authorizationRequest.getAttribute(OidcParameterNames.NONCE)).matches("^([a-zA-Z0-9\\-\\.\\_\\~]){128}$"); + assertThat((String) authorizationRequest.getAttribute(OidcParameterNames.NONCE)) + .matches("^([a-zA-Z0-9\\-\\.\\_\\~]){128}$"); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=openid&state=.{15,}&" + - "redirect_uri=http://localhost/login/oauth2/code/oidc-registration-id&" + - "nonce=([a-zA-Z0-9\\-\\.\\_\\~]){43}"); + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" + + "scope=openid&state=.{15,}&" + + "redirect_uri=http://localhost/login/oauth2/code/oidc-registration-id&" + + "nonce=([a-zA-Z0-9\\-\\.\\_\\~]){43}"); } // gh-7696 @@ -453,19 +452,18 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); - this.resolver.setAuthorizationRequestCustomizer(customizer -> customizer - .additionalParameters(params -> params.remove(OidcParameterNames.NONCE)) - .attributes(attrs -> attrs.remove(OidcParameterNames.NONCE))); + this.resolver.setAuthorizationRequestCustomizer( + customizer -> customizer.additionalParameters(params -> params.remove(OidcParameterNames.NONCE)) + .attributes(attrs -> attrs.remove(OidcParameterNames.NONCE))); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getAdditionalParameters()).doesNotContainKey(OidcParameterNames.NONCE); assertThat(authorizationRequest.getAttributes()).doesNotContainKey(OidcParameterNames.NONCE); assertThat(authorizationRequest.getAttributes()).containsKey(OAuth2ParameterNames.REGISTRATION_ID); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=openid&state=.{15,}&" + - "redirect_uri=http://localhost/login/oauth2/code/oidc-registration-id"); + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" + + "scope=openid&state=.{15,}&" + + "redirect_uri=http://localhost/login/oauth2/code/oidc-registration-id"); } @Test @@ -475,21 +473,17 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); - this.resolver.setAuthorizationRequestCustomizer(customizer -> - customizer.authorizationRequestUri(uriBuilder -> { - uriBuilder.queryParam("param1", "value1"); - return uriBuilder.build(); - }) - ); + this.resolver.setAuthorizationRequestCustomizer(customizer -> customizer.authorizationRequestUri(uriBuilder -> { + uriBuilder.queryParam("param1", "value1"); + return uriBuilder.build(); + })); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=openid&state=.{15,}&" + - "redirect_uri=http://localhost/login/oauth2/code/oidc-registration-id&" + - "nonce=([a-zA-Z0-9\\-\\.\\_\\~]){43}&" + - "param1=value1"); + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" + + "scope=openid&state=.{15,}&" + + "redirect_uri=http://localhost/login/oauth2/code/oidc-registration-id&" + + "nonce=([a-zA-Z0-9\\-\\.\\_\\~]){43}&" + "param1=value1"); } @Test @@ -499,35 +493,27 @@ public class DefaultOAuth2AuthorizationRequestResolverTests { MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); - this.resolver.setAuthorizationRequestCustomizer(customizer -> - customizer.parameters(params -> { - params.put("appid", params.get("client_id")); - params.remove("client_id"); - }) - ); + this.resolver.setAuthorizationRequestCustomizer(customizer -> customizer.parameters(params -> { + params.put("appid", params.get("client_id")); + params.remove("client_id"); + })); OAuth2AuthorizationRequest authorizationRequest = this.resolver.resolve(request); - assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&" + - "scope=openid&state=.{15,}&" + - "redirect_uri=http://localhost/login/oauth2/code/oidc-registration-id&" + - "nonce=([a-zA-Z0-9\\-\\.\\_\\~]){43}&" + - "appid=client-id"); + assertThat(authorizationRequest.getAuthorizationRequestUri()).matches( + "https://example.com/login/oauth/authorize\\?" + "response_type=code&" + "scope=openid&state=.{15,}&" + + "redirect_uri=http://localhost/login/oauth2/code/oidc-registration-id&" + + "nonce=([a-zA-Z0-9\\-\\.\\_\\~]){43}&" + "appid=client-id"); } private static ClientRegistration.Builder fineRedirectUriTemplateClientRegistration() { return ClientRegistration.withRegistrationId("fine-redirect-uri-template-client-registration") .redirectUri("{baseScheme}://{baseHost}{basePort}{basePath}/{action}/oauth2/code/{registrationId}") .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .scope("read:user") + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).scope("read:user") .authorizationUri("https://example.com/login/oauth/authorize") - .tokenUri("https://example.com/login/oauth/access_token") - .userInfoUri("https://api.example.com/user") - .userNameAttributeName("id") - .clientName("Fine Redirect Uri Template Client") - .clientId("fine-redirect-uri-template-client") - .clientSecret("client-secret"); + .tokenUri("https://example.com/login/oauth/access_token").userInfoUri("https://api.example.com/user") + .userNameAttributeName("id").clientName("Fine Redirect Uri Template Client") + .clientId("fine-redirect-uri-template-client").clientSecret("client-secret"); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizedClientManagerTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizedClientManagerTests.java index aa13f0c879..df43c8d154 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizedClientManagerTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultOAuth2AuthorizedClientManagerTests.java @@ -64,18 +64,31 @@ import static org.mockito.Mockito.when; * @author Joe Grandja */ public class DefaultOAuth2AuthorizedClientManagerTests { + private ClientRegistrationRepository clientRegistrationRepository; + private OAuth2AuthorizedClientRepository authorizedClientRepository; + private OAuth2AuthorizedClientProvider authorizedClientProvider; + private Function contextAttributesMapper; + private OAuth2AuthorizationSuccessHandler authorizationSuccessHandler; + private OAuth2AuthorizationFailureHandler authorizationFailureHandler; + private DefaultOAuth2AuthorizedClientManager authorizedClientManager; + private ClientRegistration clientRegistration; + private Authentication principal; + private OAuth2AuthorizedClient authorizedClient; + private MockHttpServletRequest request; + private MockHttpServletResponse response; + private ArgumentCaptor authorizationContextCaptor; @SuppressWarnings("unchecked") @@ -87,19 +100,20 @@ public class DefaultOAuth2AuthorizedClientManagerTests { this.contextAttributesMapper = mock(Function.class); this.authorizationSuccessHandler = spy(new OAuth2AuthorizationSuccessHandler() { @Override - public void onAuthorizationSuccess(OAuth2AuthorizedClient authorizedClient, Authentication principal, Map attributes) { + public void onAuthorizationSuccess(OAuth2AuthorizedClient authorizedClient, Authentication principal, + Map attributes) { authorizedClientRepository.saveAuthorizedClient(authorizedClient, principal, (HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), (HttpServletResponse) attributes.get(HttpServletResponse.class.getName())); } }); - this.authorizationFailureHandler = spy(new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler( - (clientRegistrationId, principal, attributes) -> - authorizedClientRepository.removeAuthorizedClient(clientRegistrationId, principal, - (HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), + this.authorizationFailureHandler = spy( + new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler((clientRegistrationId, principal, + attributes) -> authorizedClientRepository.removeAuthorizedClient(clientRegistrationId, + principal, (HttpServletRequest) attributes.get(HttpServletRequest.class.getName()), (HttpServletResponse) attributes.get(HttpServletResponse.class.getName())))); - this.authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( - this.clientRegistrationRepository, this.authorizedClientRepository); + this.authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(this.clientRegistrationRepository, + this.authorizedClientRepository); this.authorizedClientManager.setAuthorizedClientProvider(this.authorizedClientProvider); this.authorizedClientManager.setContextAttributesMapper(this.contextAttributesMapper); this.authorizedClientManager.setAuthorizationSuccessHandler(this.authorizationSuccessHandler); @@ -116,82 +130,70 @@ public class DefaultOAuth2AuthorizedClientManagerTests { @Test public void constructorWhenClientRegistrationRepositoryIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new DefaultOAuth2AuthorizedClientManager(null, this.authorizedClientRepository)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clientRegistrationRepository cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("clientRegistrationRepository cannot be null"); } @Test public void constructorWhenOAuth2AuthorizedClientRepositoryIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new DefaultOAuth2AuthorizedClientManager(this.clientRegistrationRepository, null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizedClientRepository cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizedClientRepository cannot be null"); } @Test public void setAuthorizedClientProviderWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setAuthorizedClientProvider(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizedClientProvider cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizedClientProvider cannot be null"); } @Test public void setContextAttributesMapperWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setContextAttributesMapper(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("contextAttributesMapper cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("contextAttributesMapper cannot be null"); } @Test public void setAuthorizationSuccessHandlerWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setAuthorizationSuccessHandler(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizationSuccessHandler cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizationSuccessHandler cannot be null"); } @Test public void setAuthorizationFailureHandlerWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setAuthorizationFailureHandler(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizationFailureHandler cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizationFailureHandler cannot be null"); } @Test public void authorizeWhenRequestIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.authorize(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizeRequest cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizeRequest cannot be null"); } @Test public void authorizeWhenHttpServletRequestIsNullThenThrowIllegalArgumentException() { - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); assertThatThrownBy(() -> this.authorizedClientManager.authorize(authorizeRequest)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("servletRequest cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("servletRequest cannot be null"); } @Test public void authorizeWhenHttpServletResponseIsNullThenThrowIllegalArgumentException() { - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) - .attribute(HttpServletRequest.class.getName(), this.request) - .build(); + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) + .attribute(HttpServletRequest.class.getName(), this.request).build(); assertThatThrownBy(() -> this.authorizedClientManager.authorize(authorizeRequest)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("servletResponse cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("servletResponse cannot be null"); } @Test public void authorizeWhenClientRegistrationNotFoundThenThrowIllegalArgumentException() { - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("invalid-registration-id") - .principal(this.principal) - .attributes(attrs -> { + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId("invalid-registration-id").principal(this.principal).attributes(attrs -> { attrs.put(HttpServletRequest.class.getName(), this.request); attrs.put(HttpServletResponse.class.getName(), this.response); - }) - .build(); + }).build(); assertThatThrownBy(() -> this.authorizedClientManager.authorize(authorizeRequest)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Could not find ClientRegistration with id 'invalid-registration-id'"); @@ -200,16 +202,15 @@ public class DefaultOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void authorizeWhenNotAuthorizedAndUnsupportedProviderThenNotAuthorized() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(this.clientRegistration); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(this.clientRegistration); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .attributes(attrs -> { attrs.put(HttpServletRequest.class.getName(), this.request); attrs.put(HttpServletResponse.class.getName(), this.response); - }) - .build(); + }).build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); @@ -228,18 +229,18 @@ public class DefaultOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void authorizeWhenNotAuthorizedAndSupportedProviderThenAuthorized() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(this.clientRegistration); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(this.clientRegistration); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(this.authorizedClient); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(this.authorizedClient); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .attributes(attrs -> { attrs.put(HttpServletRequest.class.getName(), this.request); attrs.put(HttpServletResponse.class.getName(), this.response); - }) - .build(); + }).build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); @@ -251,33 +252,32 @@ public class DefaultOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); assertThat(authorizedClient).isSameAs(this.authorizedClient); - verify(this.authorizationSuccessHandler).onAuthorizationSuccess( - eq(this.authorizedClient), eq(this.principal), any()); - verify(this.authorizedClientRepository).saveAuthorizedClient( - eq(this.authorizedClient), eq(this.principal), eq(this.request), eq(this.response)); + verify(this.authorizationSuccessHandler).onAuthorizationSuccess(eq(this.authorizedClient), eq(this.principal), + any()); + verify(this.authorizedClientRepository).saveAuthorizedClient(eq(this.authorizedClient), eq(this.principal), + eq(this.request), eq(this.response)); } @SuppressWarnings("unchecked") @Test public void authorizeWhenAuthorizedAndSupportedProviderThenReauthorized() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(this.clientRegistration); - when(this.authorizedClientRepository.loadAuthorizedClient( - eq(this.clientRegistration.getRegistrationId()), eq(this.principal), eq(this.request))).thenReturn(this.authorizedClient); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(this.clientRegistration); + when(this.authorizedClientRepository.loadAuthorizedClient(eq(this.clientRegistration.getRegistrationId()), + eq(this.principal), eq(this.request))).thenReturn(this.authorizedClient); - OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(reauthorizedClient); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(reauthorizedClient); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .attributes(attrs -> { attrs.put(HttpServletRequest.class.getName(), this.request); attrs.put(HttpServletResponse.class.getName(), this.response); - }) - .build(); + }).build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); @@ -289,18 +289,19 @@ public class DefaultOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); assertThat(authorizedClient).isSameAs(reauthorizedClient); - verify(this.authorizationSuccessHandler).onAuthorizationSuccess( - eq(reauthorizedClient), eq(this.principal), any()); - verify(this.authorizedClientRepository).saveAuthorizedClient( - eq(reauthorizedClient), eq(this.principal), eq(this.request), eq(this.response)); + verify(this.authorizationSuccessHandler).onAuthorizationSuccess(eq(reauthorizedClient), eq(this.principal), + any()); + verify(this.authorizedClientRepository).saveAuthorizedClient(eq(reauthorizedClient), eq(this.principal), + eq(this.request), eq(this.response)); } @Test public void authorizeWhenRequestParameterUsernamePasswordThenMappedToContext() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(this.clientRegistration); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(this.clientRegistration); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(this.authorizedClient); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(this.authorizedClient); // Set custom contextAttributesMapper this.authorizedClientManager.setContextAttributesMapper(authorizeRequest -> { @@ -318,13 +319,12 @@ public class DefaultOAuth2AuthorizedClientManagerTests { this.request.addParameter(OAuth2ParameterNames.USERNAME, "username"); this.request.addParameter(OAuth2ParameterNames.PASSWORD, "password"); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .attributes(attrs -> { attrs.put(HttpServletRequest.class.getName(), this.request); attrs.put(HttpServletResponse.class.getName(), this.response); - }) - .build(); + }).build(); this.authorizedClientManager.authorize(authorizeRequest); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); @@ -340,12 +340,10 @@ public class DefaultOAuth2AuthorizedClientManagerTests { @Test public void reauthorizeWhenUnsupportedProviderThenNotReauthorized() { OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .attributes(attrs -> { + .principal(this.principal).attributes(attrs -> { attrs.put(HttpServletRequest.class.getName(), this.request); attrs.put(HttpServletResponse.class.getName(), this.response); - }) - .build(); + }).build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(reauthorizeRequest); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); @@ -358,26 +356,24 @@ public class DefaultOAuth2AuthorizedClientManagerTests { assertThat(authorizedClient).isSameAs(this.authorizedClient); verifyNoInteractions(this.authorizationSuccessHandler); - verify(this.authorizedClientRepository, never()).saveAuthorizedClient( - any(OAuth2AuthorizedClient.class), eq(this.principal), eq(this.request), eq(this.response)); + verify(this.authorizedClientRepository, never()).saveAuthorizedClient(any(OAuth2AuthorizedClient.class), + eq(this.principal), eq(this.request), eq(this.response)); } @SuppressWarnings("unchecked") @Test public void reauthorizeWhenSupportedProviderThenReauthorized() { - OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(reauthorizedClient); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(reauthorizedClient); OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .attributes(attrs -> { + .principal(this.principal).attributes(attrs -> { attrs.put(HttpServletRequest.class.getName(), this.request); attrs.put(HttpServletResponse.class.getName(), this.response); - }) - .build(); + }).build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(reauthorizeRequest); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); @@ -389,39 +385,38 @@ public class DefaultOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); assertThat(authorizedClient).isSameAs(reauthorizedClient); - verify(this.authorizationSuccessHandler).onAuthorizationSuccess( - eq(reauthorizedClient), eq(this.principal), any()); - verify(this.authorizedClientRepository).saveAuthorizedClient( - eq(reauthorizedClient), eq(this.principal), eq(this.request), eq(this.response)); + verify(this.authorizationSuccessHandler).onAuthorizationSuccess(eq(reauthorizedClient), eq(this.principal), + any()); + verify(this.authorizedClientRepository).saveAuthorizedClient(eq(reauthorizedClient), eq(this.principal), + eq(this.request), eq(this.response)); } @Test public void reauthorizeWhenRequestParameterScopeThenMappedToContext() { - OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(reauthorizedClient); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(reauthorizedClient); // Override the mock with the default - this.authorizedClientManager.setContextAttributesMapper( - new DefaultOAuth2AuthorizedClientManager.DefaultContextAttributesMapper()); + this.authorizedClientManager + .setContextAttributesMapper(new DefaultOAuth2AuthorizedClientManager.DefaultContextAttributesMapper()); this.request.addParameter(OAuth2ParameterNames.SCOPE, "read write"); OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .attributes(attrs -> { + .principal(this.principal).attributes(attrs -> { attrs.put(HttpServletRequest.class.getName(), this.request); attrs.put(HttpServletResponse.class.getName(), this.response); - }) - .build(); + }).build(); this.authorizedClientManager.authorize(reauthorizeRequest); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); OAuth2AuthorizationContext authorizationContext = this.authorizationContextCaptor.getValue(); - String[] requestScopeAttribute = authorizationContext.getAttribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME); + String[] requestScopeAttribute = authorizationContext + .getAttribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME); assertThat(requestScopeAttribute).contains("read", "write"); } @@ -435,44 +430,40 @@ public class DefaultOAuth2AuthorizedClientManagerTests { .thenThrow(authorizationException); OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .attributes(attrs -> { + .principal(this.principal).attributes(attrs -> { attrs.put(HttpServletRequest.class.getName(), this.request); attrs.put(HttpServletResponse.class.getName(), this.response); - }) - .build(); + }).build(); assertThatCode(() -> this.authorizedClientManager.authorize(reauthorizeRequest)) .isEqualTo(authorizationException); - verify(this.authorizationFailureHandler).onAuthorizationFailure( - eq(authorizationException), eq(this.principal), any()); - verify(this.authorizedClientRepository).removeAuthorizedClient( - eq(this.clientRegistration.getRegistrationId()), eq(this.principal), eq(this.request), eq(this.response)); + verify(this.authorizationFailureHandler).onAuthorizationFailure(eq(authorizationException), eq(this.principal), + any()); + verify(this.authorizedClientRepository).removeAuthorizedClient(eq(this.clientRegistration.getRegistrationId()), + eq(this.principal), eq(this.request), eq(this.response)); } @Test public void reauthorizeWhenErrorCodeDoesNotMatchThenDoNotRemoveAuthorizedClient() { ClientAuthorizationException authorizationException = new ClientAuthorizationException( - new OAuth2Error("non-matching-error-code", null, null), - this.clientRegistration.getRegistrationId()); + new OAuth2Error("non-matching-error-code", null, null), this.clientRegistration.getRegistrationId()); when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) .thenThrow(authorizationException); OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .attributes(attrs -> { + .principal(this.principal).attributes(attrs -> { attrs.put(HttpServletRequest.class.getName(), this.request); attrs.put(HttpServletResponse.class.getName(), this.response); - }) - .build(); + }).build(); assertThatCode(() -> this.authorizedClientManager.authorize(reauthorizeRequest)) .isEqualTo(authorizationException); - verify(this.authorizationFailureHandler).onAuthorizationFailure( - eq(authorizationException), eq(this.principal), any()); + verify(this.authorizationFailureHandler).onAuthorizationFailure(eq(authorizationException), eq(this.principal), + any()); verifyNoInteractions(this.authorizedClientRepository); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultReactiveOAuth2AuthorizedClientManagerTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultReactiveOAuth2AuthorizedClientManagerTests.java index de74b188fc..070a1367df 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultReactiveOAuth2AuthorizedClientManagerTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/DefaultReactiveOAuth2AuthorizedClientManagerTests.java @@ -59,37 +59,51 @@ import static org.mockito.Mockito.*; * @author Joe Grandja */ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { + private ReactiveClientRegistrationRepository clientRegistrationRepository; + private ServerOAuth2AuthorizedClientRepository authorizedClientRepository; + private ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider; + private Function contextAttributesMapper; + private DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager; + private ClientRegistration clientRegistration; + private Authentication principal; + private OAuth2AuthorizedClient authorizedClient; + private MockServerWebExchange serverWebExchange; + private Context context; + private ArgumentCaptor authorizationContextCaptor; + private PublisherProbe loadAuthorizedClientProbe; + private PublisherProbe saveAuthorizedClientProbe; + private PublisherProbe removeAuthorizedClientProbe; @SuppressWarnings("unchecked") @Before public void setup() { this.clientRegistrationRepository = mock(ReactiveClientRegistrationRepository.class); - when(this.clientRegistrationRepository.findByRegistrationId( - anyString())).thenReturn(Mono.empty()); + when(this.clientRegistrationRepository.findByRegistrationId(anyString())).thenReturn(Mono.empty()); this.authorizedClientRepository = mock(ServerOAuth2AuthorizedClientRepository.class); this.loadAuthorizedClientProbe = PublisherProbe.empty(); - when(this.authorizedClientRepository.loadAuthorizedClient( - anyString(), any(Authentication.class), any(ServerWebExchange.class))).thenReturn(this.loadAuthorizedClientProbe.mono()); + when(this.authorizedClientRepository.loadAuthorizedClient(anyString(), any(Authentication.class), + any(ServerWebExchange.class))).thenReturn(this.loadAuthorizedClientProbe.mono()); this.saveAuthorizedClientProbe = PublisherProbe.empty(); - when(this.authorizedClientRepository.saveAuthorizedClient( - any(OAuth2AuthorizedClient.class), any(Authentication.class), any(ServerWebExchange.class))).thenReturn(this.saveAuthorizedClientProbe.mono()); + when(this.authorizedClientRepository.saveAuthorizedClient(any(OAuth2AuthorizedClient.class), + any(Authentication.class), any(ServerWebExchange.class))) + .thenReturn(this.saveAuthorizedClientProbe.mono()); this.removeAuthorizedClientProbe = PublisherProbe.empty(); - when(this.authorizedClientRepository.removeAuthorizedClient( - any(String.class), any(Authentication.class), any(ServerWebExchange.class))).thenReturn(this.removeAuthorizedClientProbe.mono()); + when(this.authorizedClientRepository.removeAuthorizedClient(any(String.class), any(Authentication.class), + any(ServerWebExchange.class))).thenReturn(this.removeAuthorizedClientProbe.mono()); this.authorizedClientProvider = mock(ReactiveOAuth2AuthorizedClientProvider.class); when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.empty()); this.contextAttributesMapper = mock(Function.class); @@ -109,81 +123,77 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { @Test public void constructorWhenClientRegistrationRepositoryIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new DefaultReactiveOAuth2AuthorizedClientManager(null, this.authorizedClientRepository)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("clientRegistrationRepository cannot be null"); + assertThatThrownBy( + () -> new DefaultReactiveOAuth2AuthorizedClientManager(null, this.authorizedClientRepository)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("clientRegistrationRepository cannot be null"); } @Test public void constructorWhenOAuth2AuthorizedClientRepositoryIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new DefaultReactiveOAuth2AuthorizedClientManager(this.clientRegistrationRepository, null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizedClientRepository cannot be null"); + assertThatThrownBy( + () -> new DefaultReactiveOAuth2AuthorizedClientManager(this.clientRegistrationRepository, null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("authorizedClientRepository cannot be null"); } @Test public void setAuthorizedClientProviderWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setAuthorizedClientProvider(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizedClientProvider cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizedClientProvider cannot be null"); } @Test public void setAuthorizationSuccessHandlerWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setAuthorizationSuccessHandler(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizationSuccessHandler cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizationSuccessHandler cannot be null"); } @Test public void setAuthorizationFailureHandlerWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setAuthorizationFailureHandler(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizationFailureHandler cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizationFailureHandler cannot be null"); } @Test public void setContextAttributesMapperWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.setContextAttributesMapper(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("contextAttributesMapper cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("contextAttributesMapper cannot be null"); } @Test public void authorizeWhenRequestIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authorizedClientManager.authorize(null).block()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizeRequest cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("authorizeRequest cannot be null"); } @Test public void authorizeWhenExchangeIsNullThenThrowIllegalArgumentException() { - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); assertThatThrownBy(() -> this.authorizedClientManager.authorize(authorizeRequest).block()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("serverWebExchange cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("serverWebExchange cannot be null"); } @Test public void authorizeWhenClientRegistrationNotFoundThenThrowIllegalArgumentException() { - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("invalid-registration-id") - .principal(this.principal) - .build(); - assertThatThrownBy(() -> this.authorizedClientManager.authorize(authorizeRequest).subscriberContext(this.context).block()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Could not find ClientRegistration with id 'invalid-registration-id'"); + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId("invalid-registration-id").principal(this.principal).build(); + assertThatThrownBy( + () -> this.authorizedClientManager.authorize(authorizeRequest).subscriberContext(this.context).block()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Could not find ClientRegistration with id 'invalid-registration-id'"); } @SuppressWarnings("unchecked") @Test public void authorizeWhenNotAuthorizedAndUnsupportedProviderThenNotAuthorized() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest) .subscriberContext(this.context).block(); @@ -204,13 +214,13 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void authorizeWhenNotAuthorizedAndSupportedProviderThenAuthorized() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); - when(this.authorizedClientProvider.authorize( - any(OAuth2AuthorizationContext.class))).thenReturn(Mono.just(this.authorizedClient)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.just(this.authorizedClient)); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest) .subscriberContext(this.context).block(); @@ -224,8 +234,8 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); assertThat(authorizedClient).isSameAs(this.authorizedClient); - verify(this.authorizedClientRepository).saveAuthorizedClient( - eq(this.authorizedClient), eq(this.principal), eq(this.serverWebExchange)); + verify(this.authorizedClientRepository).saveAuthorizedClient(eq(this.authorizedClient), eq(this.principal), + eq(this.serverWebExchange)); this.saveAuthorizedClientProbe.assertWasSubscribed(); verify(this.authorizedClientRepository, never()).removeAuthorizedClient(any(), any(), any()); } @@ -233,17 +243,18 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void authorizeWhenNotAuthorizedAndSupportedProviderAndCustomSuccessHandlerThenInvokeCustomSuccessHandler() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); - when(this.authorizedClientProvider.authorize( - any(OAuth2AuthorizationContext.class))).thenReturn(Mono.just(this.authorizedClient)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.just(this.authorizedClient)); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); PublisherProbe authorizationSuccessHandlerProbe = PublisherProbe.empty(); - this.authorizedClientManager.setAuthorizationSuccessHandler((client, principal, attributes) -> authorizationSuccessHandlerProbe.mono()); + this.authorizedClientManager.setAuthorizationSuccessHandler( + (client, principal, attributes) -> authorizationSuccessHandlerProbe.mono()); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest) .subscriberContext(this.context).block(); @@ -265,23 +276,23 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void authorizeWhenInvalidTokenThenRemoveAuthorizedClient() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); ClientAuthorizationException exception = new ClientAuthorizationException( new OAuth2Error(OAuth2ErrorCodes.INVALID_TOKEN, null, null), this.clientRegistration.getRegistrationId()); - when(this.authorizedClientProvider.authorize( - any(OAuth2AuthorizationContext.class))).thenReturn(Mono.error(exception)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.error(exception)); - assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest) - .subscriberContext(this.context).block()) - .isEqualTo(exception); + assertThatCode( + () -> this.authorizedClientManager.authorize(authorizeRequest).subscriberContext(this.context).block()) + .isEqualTo(exception); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(authorizeRequest)); @@ -291,8 +302,8 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getAuthorizedClient()).isNull(); assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); - verify(this.authorizedClientRepository).removeAuthorizedClient( - eq(this.clientRegistration.getRegistrationId()), eq(this.principal), eq(this.serverWebExchange)); + verify(this.authorizedClientRepository).removeAuthorizedClient(eq(this.clientRegistration.getRegistrationId()), + eq(this.principal), eq(this.serverWebExchange)); this.removeAuthorizedClientProbe.assertWasSubscribed(); verify(this.authorizedClientRepository, never()).saveAuthorizedClient(any(), any(), any()); } @@ -300,23 +311,23 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void authorizeWhenInvalidGrantThenRemoveAuthorizedClient() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); ClientAuthorizationException exception = new ClientAuthorizationException( new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT, null, null), this.clientRegistration.getRegistrationId()); - when(this.authorizedClientProvider.authorize( - any(OAuth2AuthorizationContext.class))).thenReturn(Mono.error(exception)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.error(exception)); - assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest) - .subscriberContext(this.context).block()) - .isEqualTo(exception); + assertThatCode( + () -> this.authorizedClientManager.authorize(authorizeRequest).subscriberContext(this.context).block()) + .isEqualTo(exception); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(authorizeRequest)); @@ -326,8 +337,8 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getAuthorizedClient()).isNull(); assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); - verify(this.authorizedClientRepository).removeAuthorizedClient( - eq(this.clientRegistration.getRegistrationId()), eq(this.principal), eq(this.serverWebExchange)); + verify(this.authorizedClientRepository).removeAuthorizedClient(eq(this.clientRegistration.getRegistrationId()), + eq(this.principal), eq(this.serverWebExchange)); this.removeAuthorizedClientProbe.assertWasSubscribed(); verify(this.authorizedClientRepository, never()).saveAuthorizedClient(any(), any(), any()); } @@ -335,23 +346,23 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void authorizeWhenServerErrorThenDoNotRemoveAuthorizedClient() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); ClientAuthorizationException exception = new ClientAuthorizationException( new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR, null, null), this.clientRegistration.getRegistrationId()); - when(this.authorizedClientProvider.authorize( - any(OAuth2AuthorizationContext.class))).thenReturn(Mono.error(exception)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.error(exception)); - assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest) - .subscriberContext(this.context).block()) - .isEqualTo(exception); + assertThatCode( + () -> this.authorizedClientManager.authorize(authorizeRequest).subscriberContext(this.context).block()) + .isEqualTo(exception); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(authorizeRequest)); @@ -368,22 +379,22 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void authorizeWhenOAuth2AuthorizationExceptionThenDoNotRemoveAuthorizedClient() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); OAuth2AuthorizationException exception = new OAuth2AuthorizationException( new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT, null, null)); - when(this.authorizedClientProvider.authorize( - any(OAuth2AuthorizationContext.class))).thenReturn(Mono.error(exception)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.error(exception)); - assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest) - .subscriberContext(this.context).block()) - .isEqualTo(exception); + assertThatCode( + () -> this.authorizedClientManager.authorize(authorizeRequest).subscriberContext(this.context).block()) + .isEqualTo(exception); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(authorizeRequest)); @@ -400,25 +411,26 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void authorizeWhenOAuth2AuthorizationExceptionAndCustomFailureHandlerThenInvokeCustomFailureHandler() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); OAuth2AuthorizationException exception = new OAuth2AuthorizationException( new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT, null, null)); - when(this.authorizedClientProvider.authorize( - any(OAuth2AuthorizationContext.class))).thenReturn(Mono.error(exception)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.error(exception)); PublisherProbe authorizationFailureHandlerProbe = PublisherProbe.empty(); - this.authorizedClientManager.setAuthorizationFailureHandler((client, principal, attributes) -> authorizationFailureHandlerProbe.mono()); + this.authorizedClientManager.setAuthorizationFailureHandler( + (client, principal, attributes) -> authorizationFailureHandlerProbe.mono()); - assertThatCode(() -> this.authorizedClientManager.authorize(authorizeRequest) - .subscriberContext(this.context).block()) - .isEqualTo(exception); + assertThatCode( + () -> this.authorizedClientManager.authorize(authorizeRequest).subscriberContext(this.context).block()) + .isEqualTo(exception); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); verify(this.contextAttributesMapper).apply(eq(authorizeRequest)); @@ -432,23 +444,24 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { verify(this.authorizedClientRepository, never()).removeAuthorizedClient(any(), any(), any()); verify(this.authorizedClientRepository, never()).saveAuthorizedClient(any(), any(), any()); } + @SuppressWarnings("unchecked") @Test public void authorizeWhenAuthorizedAndSupportedProviderThenReauthorized() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); this.loadAuthorizedClientProbe = PublisherProbe.of(Mono.just(this.authorizedClient)); - when(this.authorizedClientRepository.loadAuthorizedClient( - eq(this.clientRegistration.getRegistrationId()), eq(this.principal), eq(this.serverWebExchange))).thenReturn(this.loadAuthorizedClientProbe.mono()); + when(this.authorizedClientRepository.loadAuthorizedClient(eq(this.clientRegistration.getRegistrationId()), + eq(this.principal), eq(this.serverWebExchange))).thenReturn(this.loadAuthorizedClientProbe.mono()); - OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.just(reauthorizedClient)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.just(reauthorizedClient)); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest) .subscriberContext(this.context).block(); @@ -462,43 +475,38 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); assertThat(authorizedClient).isSameAs(reauthorizedClient); - verify(this.authorizedClientRepository).saveAuthorizedClient( - eq(reauthorizedClient), eq(this.principal), eq(this.serverWebExchange)); + verify(this.authorizedClientRepository).saveAuthorizedClient(eq(reauthorizedClient), eq(this.principal), + eq(this.serverWebExchange)); this.saveAuthorizedClientProbe.assertWasSubscribed(); verify(this.authorizedClientRepository, never()).removeAuthorizedClient(any(), any(), any()); } @Test public void authorizeWhenRequestFormParameterUsernamePasswordThenMappedToContext() { - when(this.clientRegistrationRepository.findByRegistrationId( - eq(this.clientRegistration.getRegistrationId()))).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(this.clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(this.clientRegistration)); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.just(this.authorizedClient)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.just(this.authorizedClient)); // Set custom contextAttributesMapper capable of mapping the form parameters - this.authorizedClientManager.setContextAttributesMapper(authorizeRequest -> - currentServerWebExchange() - .flatMap(ServerWebExchange::getFormData) - .map(formData -> { - Map contextAttributes = new HashMap<>(); - String username = formData.getFirst(OAuth2ParameterNames.USERNAME); - contextAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username); - String password = formData.getFirst(OAuth2ParameterNames.PASSWORD); - contextAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password); - return contextAttributes; - }) - ); + this.authorizedClientManager.setContextAttributesMapper( + authorizeRequest -> currentServerWebExchange().flatMap(ServerWebExchange::getFormData).map(formData -> { + Map contextAttributes = new HashMap<>(); + String username = formData.getFirst(OAuth2ParameterNames.USERNAME); + contextAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username); + String password = formData.getFirst(OAuth2ParameterNames.PASSWORD); + contextAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password); + return contextAttributes; + })); - this.serverWebExchange = MockServerWebExchange.builder( - MockServerHttpRequest - .post("/") - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .body("username=username&password=password")) + this.serverWebExchange = MockServerWebExchange.builder(MockServerHttpRequest.post("/") + .contentType(MediaType.APPLICATION_FORM_URLENCODED).body("username=username&password=password")) .build(); this.context = Context.of(ServerWebExchange.class, this.serverWebExchange); - OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId(this.clientRegistration.getRegistrationId()) - .principal(this.principal) + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest + .withClientRegistrationId(this.clientRegistration.getRegistrationId()).principal(this.principal) .build(); this.authorizedClientManager.authorize(authorizeRequest).subscriberContext(this.context).block(); @@ -515,8 +523,7 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { @Test public void reauthorizeWhenUnsupportedProviderThenNotReauthorized() { OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .build(); + .principal(this.principal).build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(reauthorizeRequest) .subscriberContext(this.context).block(); @@ -535,15 +542,14 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { @SuppressWarnings("unchecked") @Test public void reauthorizeWhenSupportedProviderThenReauthorized() { - OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.just(reauthorizedClient)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.just(reauthorizedClient)); OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .build(); + .principal(this.principal).build(); OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(reauthorizeRequest) .subscriberContext(this.context).block(); @@ -556,46 +562,43 @@ public class DefaultReactiveOAuth2AuthorizedClientManagerTests { assertThat(authorizationContext.getPrincipal()).isEqualTo(this.principal); assertThat(authorizedClient).isSameAs(reauthorizedClient); - verify(this.authorizedClientRepository).saveAuthorizedClient( - eq(reauthorizedClient), eq(this.principal), eq(this.serverWebExchange)); + verify(this.authorizedClientRepository).saveAuthorizedClient(eq(reauthorizedClient), eq(this.principal), + eq(this.serverWebExchange)); this.saveAuthorizedClientProbe.assertWasSubscribed(); verify(this.authorizedClientRepository, never()).removeAuthorizedClient(any(), any(), any()); } @Test public void reauthorizeWhenRequestParameterScopeThenMappedToContext() { - OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.principal.getName(), - TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); + OAuth2AuthorizedClient reauthorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, + this.principal.getName(), TestOAuth2AccessTokens.noScopes(), TestOAuth2RefreshTokens.refreshToken()); - when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))).thenReturn(Mono.just(reauthorizedClient)); + when(this.authorizedClientProvider.authorize(any(OAuth2AuthorizationContext.class))) + .thenReturn(Mono.just(reauthorizedClient)); // Override the mock with the default this.authorizedClientManager.setContextAttributesMapper( new DefaultReactiveOAuth2AuthorizedClientManager.DefaultContextAttributesMapper()); - this.serverWebExchange = MockServerWebExchange.builder( - MockServerHttpRequest - .get("/") - .queryParam(OAuth2ParameterNames.SCOPE, "read write")) - .build(); + this.serverWebExchange = MockServerWebExchange + .builder(MockServerHttpRequest.get("/").queryParam(OAuth2ParameterNames.SCOPE, "read write")).build(); this.context = Context.of(ServerWebExchange.class, this.serverWebExchange); OAuth2AuthorizeRequest reauthorizeRequest = OAuth2AuthorizeRequest.withAuthorizedClient(this.authorizedClient) - .principal(this.principal) - .build(); + .principal(this.principal).build(); this.authorizedClientManager.authorize(reauthorizeRequest).subscriberContext(this.context).block(); verify(this.authorizedClientProvider).authorize(this.authorizationContextCaptor.capture()); OAuth2AuthorizationContext authorizationContext = this.authorizationContextCaptor.getValue(); - String[] requestScopeAttribute = authorizationContext.getAttribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME); + String[] requestScopeAttribute = authorizationContext + .getAttribute(OAuth2AuthorizationContext.REQUEST_SCOPE_ATTRIBUTE_NAME); assertThat(requestScopeAttribute).contains("read", "write"); } private Mono currentServerWebExchange() { - return Mono.subscriberContext() - .filter(c -> c.hasKey(ServerWebExchange.class)) + return Mono.subscriberContext().filter(c -> c.hasKey(ServerWebExchange.class)) .map(c -> c.get(ServerWebExchange.class)); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizationRequestRepositoryTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizationRequestRepositoryTests.java index fe8fc5514a..9f4de6dc62 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizationRequestRepositoryTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizationRequestRepositoryTests.java @@ -37,8 +37,8 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; */ @RunWith(MockitoJUnitRunner.class) public class HttpSessionOAuth2AuthorizationRequestRepositoryTests { - private HttpSessionOAuth2AuthorizationRequestRepository authorizationRequestRepository = - new HttpSessionOAuth2AuthorizationRequestRepository(); + + private HttpSessionOAuth2AuthorizationRequestRepository authorizationRequestRepository = new HttpSessionOAuth2AuthorizationRequestRepository(); @Test(expected = IllegalArgumentException.class) public void loadAuthorizationRequestWhenHttpServletRequestIsNullThenThrowIllegalArgumentException() { @@ -49,8 +49,8 @@ public class HttpSessionOAuth2AuthorizationRequestRepositoryTests { public void loadAuthorizationRequestWhenNotSavedThenReturnNull() { MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter(OAuth2ParameterNames.STATE, "state-1234"); - OAuth2AuthorizationRequest authorizationRequest = - this.authorizationRequestRepository.loadAuthorizationRequest(request); + OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestRepository + .loadAuthorizationRequest(request); assertThat(authorizationRequest).isNull(); } @@ -64,8 +64,8 @@ public class HttpSessionOAuth2AuthorizationRequestRepositoryTests { this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, request, response); request.addParameter(OAuth2ParameterNames.STATE, authorizationRequest.getState()); - OAuth2AuthorizationRequest loadedAuthorizationRequest = - this.authorizationRequestRepository.loadAuthorizationRequest(request); + OAuth2AuthorizationRequest loadedAuthorizationRequest = this.authorizationRequestRepository + .loadAuthorizationRequest(request); assertThat(loadedAuthorizationRequest).isEqualTo(authorizationRequest); } @@ -89,20 +89,20 @@ public class HttpSessionOAuth2AuthorizationRequestRepositoryTests { this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest3, request, response); request.addParameter(OAuth2ParameterNames.STATE, state1); - OAuth2AuthorizationRequest loadedAuthorizationRequest1 = - this.authorizationRequestRepository.loadAuthorizationRequest(request); + OAuth2AuthorizationRequest loadedAuthorizationRequest1 = this.authorizationRequestRepository + .loadAuthorizationRequest(request); assertThat(loadedAuthorizationRequest1).isEqualTo(authorizationRequest1); request.removeParameter(OAuth2ParameterNames.STATE); request.addParameter(OAuth2ParameterNames.STATE, state2); - OAuth2AuthorizationRequest loadedAuthorizationRequest2 = - this.authorizationRequestRepository.loadAuthorizationRequest(request); + OAuth2AuthorizationRequest loadedAuthorizationRequest2 = this.authorizationRequestRepository + .loadAuthorizationRequest(request); assertThat(loadedAuthorizationRequest2).isEqualTo(authorizationRequest2); request.removeParameter(OAuth2ParameterNames.STATE); request.addParameter(OAuth2ParameterNames.STATE, state3); - OAuth2AuthorizationRequest loadedAuthorizationRequest3 = - this.authorizationRequestRepository.loadAuthorizationRequest(request); + OAuth2AuthorizationRequest loadedAuthorizationRequest3 = this.authorizationRequestRepository + .loadAuthorizationRequest(request); assertThat(loadedAuthorizationRequest3).isEqualTo(authorizationRequest3); } @@ -111,8 +111,8 @@ public class HttpSessionOAuth2AuthorizationRequestRepositoryTests { MockHttpServletRequest request = new MockHttpServletRequest(); OAuth2AuthorizationRequest authorizationRequest = createAuthorizationRequest().build(); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, request, new MockHttpServletResponse()); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, request, + new MockHttpServletResponse()); assertThat(this.authorizationRequestRepository.loadAuthorizationRequest(request)).isNull(); } @@ -121,28 +121,24 @@ public class HttpSessionOAuth2AuthorizationRequestRepositoryTests { public void saveAuthorizationRequestWhenHttpServletRequestIsNullThenThrowIllegalArgumentException() { OAuth2AuthorizationRequest authorizationRequest = createAuthorizationRequest().build(); - assertThatThrownBy(() -> this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, null, new MockHttpServletResponse())) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, + null, new MockHttpServletResponse())).isInstanceOf(IllegalArgumentException.class); } @Test public void saveAuthorizationRequestWhenHttpServletResponseIsNullThenThrowIllegalArgumentException() { OAuth2AuthorizationRequest authorizationRequest = createAuthorizationRequest().build(); - assertThatThrownBy(() -> this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, new MockHttpServletRequest(), null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, + new MockHttpServletRequest(), null)).isInstanceOf(IllegalArgumentException.class); } @Test public void saveAuthorizationRequestWhenStateNullThenThrowIllegalArgumentException() { - OAuth2AuthorizationRequest authorizationRequest = createAuthorizationRequest() - .state(null) - .build(); - assertThatThrownBy(() -> this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, new MockHttpServletRequest(), new MockHttpServletResponse())) - .isInstanceOf(IllegalArgumentException.class); + OAuth2AuthorizationRequest authorizationRequest = createAuthorizationRequest().state(null).build(); + assertThatThrownBy(() -> this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, + new MockHttpServletRequest(), new MockHttpServletResponse())) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -150,12 +146,12 @@ public class HttpSessionOAuth2AuthorizationRequestRepositoryTests { MockHttpServletRequest request = new MockHttpServletRequest(); OAuth2AuthorizationRequest authorizationRequest = createAuthorizationRequest().build(); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, request, new MockHttpServletResponse()); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, request, + new MockHttpServletResponse()); request.addParameter(OAuth2ParameterNames.STATE, authorizationRequest.getState()); - OAuth2AuthorizationRequest loadedAuthorizationRequest = - this.authorizationRequestRepository.loadAuthorizationRequest(request); + OAuth2AuthorizationRequest loadedAuthorizationRequest = this.authorizationRequestRepository + .loadAuthorizationRequest(request); assertThat(loadedAuthorizationRequest).isEqualTo(authorizationRequest); } @@ -166,12 +162,12 @@ public class HttpSessionOAuth2AuthorizationRequestRepositoryTests { request.setSession(new MockDistributedHttpSession()); OAuth2AuthorizationRequest authorizationRequest = createAuthorizationRequest().build(); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, request, new MockHttpServletResponse()); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, request, + new MockHttpServletResponse()); request.addParameter(OAuth2ParameterNames.STATE, authorizationRequest.getState()); - OAuth2AuthorizationRequest loadedAuthorizationRequest = - this.authorizationRequestRepository.loadAuthorizationRequest(request); + OAuth2AuthorizationRequest loadedAuthorizationRequest = this.authorizationRequestRepository + .loadAuthorizationRequest(request); assertThat(loadedAuthorizationRequest).isEqualTo(authorizationRequest); } @@ -182,16 +178,16 @@ public class HttpSessionOAuth2AuthorizationRequestRepositoryTests { request.setSession(new MockDistributedHttpSession()); OAuth2AuthorizationRequest authorizationRequest1 = createAuthorizationRequest().build(); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest1, request, new MockHttpServletResponse()); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest1, request, + new MockHttpServletResponse()); OAuth2AuthorizationRequest authorizationRequest2 = createAuthorizationRequest().build(); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest2, request, new MockHttpServletResponse()); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest2, request, + new MockHttpServletResponse()); request.addParameter(OAuth2ParameterNames.STATE, authorizationRequest2.getState()); - OAuth2AuthorizationRequest loadedAuthorizationRequest = - this.authorizationRequestRepository.loadAuthorizationRequest(request); + OAuth2AuthorizationRequest loadedAuthorizationRequest = this.authorizationRequestRepository + .loadAuthorizationRequest(request); assertThat(loadedAuthorizationRequest).isEqualTo(authorizationRequest2); } @@ -201,32 +197,33 @@ public class HttpSessionOAuth2AuthorizationRequestRepositoryTests { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); - OAuth2AuthorizationRequest authorizationRequest = createAuthorizationRequest().build(); - this.authorizationRequestRepository.saveAuthorizationRequest( // Save - authorizationRequest, request, response); + this.authorizationRequestRepository.saveAuthorizationRequest( // Save + authorizationRequest, request, response); request.addParameter(OAuth2ParameterNames.STATE, authorizationRequest.getState()); - this.authorizationRequestRepository.saveAuthorizationRequest( // Null value removes - null, request, response); + this.authorizationRequestRepository.saveAuthorizationRequest( // Null value + // removes + null, request, response); - OAuth2AuthorizationRequest loadedAuthorizationRequest = - this.authorizationRequestRepository.loadAuthorizationRequest(request); + OAuth2AuthorizationRequest loadedAuthorizationRequest = this.authorizationRequestRepository + .loadAuthorizationRequest(request); assertThat(loadedAuthorizationRequest).isNull(); } @Test public void removeAuthorizationRequestWhenHttpServletRequestIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.authorizationRequestRepository.removeAuthorizationRequest( - null, new MockHttpServletResponse())).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.authorizationRequestRepository.removeAuthorizationRequest(null, + new MockHttpServletResponse())).isInstanceOf(IllegalArgumentException.class); } @Test public void removeAuthorizationRequestWhenHttpServletResponseIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.authorizationRequestRepository.removeAuthorizationRequest( - new MockHttpServletRequest(), null)).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.authorizationRequestRepository + .removeAuthorizationRequest(new MockHttpServletRequest(), null)) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -236,14 +233,13 @@ public class HttpSessionOAuth2AuthorizationRequestRepositoryTests { OAuth2AuthorizationRequest authorizationRequest = createAuthorizationRequest().build(); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, request, response); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, request, response); request.addParameter(OAuth2ParameterNames.STATE, authorizationRequest.getState()); - OAuth2AuthorizationRequest removedAuthorizationRequest = - this.authorizationRequestRepository.removeAuthorizationRequest(request, response); - OAuth2AuthorizationRequest loadedAuthorizationRequest = - this.authorizationRequestRepository.loadAuthorizationRequest(request); + OAuth2AuthorizationRequest removedAuthorizationRequest = this.authorizationRequestRepository + .removeAuthorizationRequest(request, response); + OAuth2AuthorizationRequest loadedAuthorizationRequest = this.authorizationRequestRepository + .loadAuthorizationRequest(request); assertThat(removedAuthorizationRequest).isNotNull(); assertThat(loadedAuthorizationRequest).isNull(); @@ -257,15 +253,14 @@ public class HttpSessionOAuth2AuthorizationRequestRepositoryTests { OAuth2AuthorizationRequest authorizationRequest = createAuthorizationRequest().build(); - this.authorizationRequestRepository.saveAuthorizationRequest( - authorizationRequest, request, response); + this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, request, response); request.addParameter(OAuth2ParameterNames.STATE, authorizationRequest.getState()); - OAuth2AuthorizationRequest removedAuthorizationRequest = - this.authorizationRequestRepository.removeAuthorizationRequest(request, response); + OAuth2AuthorizationRequest removedAuthorizationRequest = this.authorizationRequestRepository + .removeAuthorizationRequest(request, response); - String sessionAttributeName = HttpSessionOAuth2AuthorizationRequestRepository.class.getName() + - ".AUTHORIZATION_REQUEST"; + String sessionAttributeName = HttpSessionOAuth2AuthorizationRequestRepository.class.getName() + + ".AUTHORIZATION_REQUEST"; assertThat(removedAuthorizationRequest).isNotNull(); assertThat(request.getSession().getAttribute(sessionAttributeName)).isNull(); @@ -278,20 +273,19 @@ public class HttpSessionOAuth2AuthorizationRequestRepositoryTests { MockHttpServletResponse response = new MockHttpServletResponse(); - OAuth2AuthorizationRequest removedAuthorizationRequest = - this.authorizationRequestRepository.removeAuthorizationRequest(request, response); + OAuth2AuthorizationRequest removedAuthorizationRequest = this.authorizationRequestRepository + .removeAuthorizationRequest(request, response); assertThat(removedAuthorizationRequest).isNull(); } private OAuth2AuthorizationRequest.Builder createAuthorizationRequest() { - return OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri("https://example.com/oauth2/authorize") - .clientId("client-id-1234") - .state("state-1234"); + return OAuth2AuthorizationRequest.authorizationCode().authorizationUri("https://example.com/oauth2/authorize") + .clientId("client-id-1234").state("state-1234"); } static class MockDistributedHttpSession extends MockHttpSession { + @Override public Object getAttribute(String name) { return wrap(super.getAttribute(name)); @@ -308,5 +302,7 @@ public class HttpSessionOAuth2AuthorizationRequestRepositoryTests { } return object; } + } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizedClientRepositoryTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizedClientRepositoryTests.java index 9646ce8c1e..60a4020465 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizedClientRepositoryTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/HttpSessionOAuth2AuthorizedClientRepositoryTests.java @@ -37,6 +37,7 @@ import static org.mockito.Mockito.mock; * @author Joe Grandja */ public class HttpSessionOAuth2AuthorizedClientRepositoryTests { + private String principalName1 = "principalName-1"; private ClientRegistration registration1 = TestClientRegistrations.clientRegistration().build(); @@ -47,8 +48,7 @@ public class HttpSessionOAuth2AuthorizedClientRepositoryTests { private String registrationId2 = this.registration2.getRegistrationId(); - private HttpSessionOAuth2AuthorizedClientRepository authorizedClientRepository = - new HttpSessionOAuth2AuthorizedClientRepository(); + private HttpSessionOAuth2AuthorizedClientRepository authorizedClientRepository = new HttpSessionOAuth2AuthorizedClientRepository(); private MockHttpServletRequest request; @@ -79,63 +79,66 @@ public class HttpSessionOAuth2AuthorizedClientRepositoryTests { @Test public void loadAuthorizedClientWhenClientRegistrationNotFoundThenReturnNull() { - OAuth2AuthorizedClient authorizedClient = - this.authorizedClientRepository.loadAuthorizedClient("registration-not-found", null, this.request); + OAuth2AuthorizedClient authorizedClient = this.authorizedClientRepository + .loadAuthorizedClient("registration-not-found", null, this.request); assertThat(authorizedClient).isNull(); } @Test public void loadAuthorizedClientWhenSavedThenReturnAuthorizedClient() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration1, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration1, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, this.request, this.response); - OAuth2AuthorizedClient loadedAuthorizedClient = - this.authorizedClientRepository.loadAuthorizedClient(this.registrationId1, null, this.request); + OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientRepository + .loadAuthorizedClient(this.registrationId1, null, this.request); assertThat(loadedAuthorizedClient).isEqualTo(authorizedClient); } @Test public void saveAuthorizedClientWhenAuthorizedClientIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.authorizedClientRepository.saveAuthorizedClient(null, null, this.request, this.response)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> this.authorizedClientRepository.saveAuthorizedClient(null, null, this.request, this.response)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void saveAuthorizedClientWhenAuthenticationIsNullThenExceptionNotThrown() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration2, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration2, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, this.request, this.response); } @Test public void saveAuthorizedClientWhenRequestIsNullThenThrowIllegalArgumentException() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration2, this.principalName1, mock(OAuth2AccessToken.class)); - assertThatThrownBy(() -> this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, null, this.response)) - .isInstanceOf(IllegalArgumentException.class); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration2, this.principalName1, + mock(OAuth2AccessToken.class)); + assertThatThrownBy( + () -> this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, null, this.response)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void saveAuthorizedClientWhenResponseIsNullThenThrowIllegalArgumentException() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration2, this.principalName1, mock(OAuth2AccessToken.class)); - assertThatThrownBy(() -> this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, this.request, null)) - .isInstanceOf(IllegalArgumentException.class); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration2, this.principalName1, + mock(OAuth2AccessToken.class)); + assertThatThrownBy( + () -> this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, this.request, null)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void saveAuthorizedClientWhenSavedThenSavedToSession() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration2, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration2, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, this.request, this.response); HttpSession session = this.request.getSession(false); assertThat(session).isNotNull(); @SuppressWarnings("unchecked") - Map authorizedClients = (Map) - session.getAttribute(HttpSessionOAuth2AuthorizedClientRepository.class.getName() + ".AUTHORIZED_CLIENTS"); + Map authorizedClients = (Map) session + .getAttribute(HttpSessionOAuth2AuthorizedClientRepository.class.getName() + ".AUTHORIZED_CLIENTS"); assertThat(authorizedClients).isNotEmpty(); assertThat(authorizedClients).hasSize(1); assertThat(authorizedClients.values().iterator().next()).isSameAs(authorizedClient); @@ -143,8 +146,9 @@ public class HttpSessionOAuth2AuthorizedClientRepositoryTests { @Test public void removeAuthorizedClientWhenClientRegistrationIdIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.authorizedClientRepository.removeAuthorizedClient( - null, null, this.request, this.response)).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> this.authorizedClientRepository.removeAuthorizedClient(null, null, this.request, this.response)) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -154,8 +158,8 @@ public class HttpSessionOAuth2AuthorizedClientRepositoryTests { @Test public void removeAuthorizedClientWhenRequestIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.authorizedClientRepository.removeAuthorizedClient( - this.registrationId1, null, null, this.response)).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.authorizedClientRepository.removeAuthorizedClient(this.registrationId1, null, + null, this.response)).isInstanceOf(IllegalArgumentException.class); } @Test @@ -165,74 +169,72 @@ public class HttpSessionOAuth2AuthorizedClientRepositoryTests { @Test public void removeAuthorizedClientWhenNotSavedThenSessionNotCreated() { - this.authorizedClientRepository.removeAuthorizedClient( - this.registrationId2, null, this.request, this.response); + this.authorizedClientRepository.removeAuthorizedClient(this.registrationId2, null, this.request, this.response); assertThat(this.request.getSession(false)).isNull(); } @Test public void removeAuthorizedClientWhenClient1SavedAndClient2RemovedThenClient1NotRemoved() { - OAuth2AuthorizedClient authorizedClient1 = new OAuth2AuthorizedClient( - this.registration1, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient1 = new OAuth2AuthorizedClient(this.registration1, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient1, null, this.request, this.response); // Remove registrationId2 (never added so is not removed either) - this.authorizedClientRepository.removeAuthorizedClient( - this.registrationId2, null, this.request, this.response); + this.authorizedClientRepository.removeAuthorizedClient(this.registrationId2, null, this.request, this.response); - OAuth2AuthorizedClient loadedAuthorizedClient1 = this.authorizedClientRepository.loadAuthorizedClient( - this.registrationId1, null, this.request); + OAuth2AuthorizedClient loadedAuthorizedClient1 = this.authorizedClientRepository + .loadAuthorizedClient(this.registrationId1, null, this.request); assertThat(loadedAuthorizedClient1).isNotNull(); assertThat(loadedAuthorizedClient1).isSameAs(authorizedClient1); } @Test public void removeAuthorizedClientWhenSavedThenRemoved() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration2, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration2, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, this.request, this.response); - OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientRepository.loadAuthorizedClient( - this.registrationId2, null, this.request); + OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientRepository + .loadAuthorizedClient(this.registrationId2, null, this.request); assertThat(loadedAuthorizedClient).isSameAs(authorizedClient); - this.authorizedClientRepository.removeAuthorizedClient( - this.registrationId2, null, this.request, this.response); - loadedAuthorizedClient = this.authorizedClientRepository.loadAuthorizedClient( - this.registrationId2, null, this.request); + this.authorizedClientRepository.removeAuthorizedClient(this.registrationId2, null, this.request, this.response); + loadedAuthorizedClient = this.authorizedClientRepository.loadAuthorizedClient(this.registrationId2, null, + this.request); assertThat(loadedAuthorizedClient).isNull(); } @Test public void removeAuthorizedClientWhenSavedThenRemovedFromSession() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration1, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration1, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, this.request, this.response); - OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientRepository.loadAuthorizedClient( - this.registrationId1, null, this.request); + OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientRepository + .loadAuthorizedClient(this.registrationId1, null, this.request); assertThat(loadedAuthorizedClient).isSameAs(authorizedClient); - this.authorizedClientRepository.removeAuthorizedClient( - this.registrationId1, null, this.request, this.response); + this.authorizedClientRepository.removeAuthorizedClient(this.registrationId1, null, this.request, this.response); HttpSession session = this.request.getSession(false); assertThat(session).isNotNull(); - assertThat(session.getAttribute(HttpSessionOAuth2AuthorizedClientRepository.class.getName() + ".AUTHORIZED_CLIENTS")).isNull(); + assertThat(session + .getAttribute(HttpSessionOAuth2AuthorizedClientRepository.class.getName() + ".AUTHORIZED_CLIENTS")) + .isNull(); } @Test public void removeAuthorizedClientWhenClient1Client2SavedAndClient1RemovedThenClient2NotRemoved() { - OAuth2AuthorizedClient authorizedClient1 = new OAuth2AuthorizedClient( - this.registration1, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient1 = new OAuth2AuthorizedClient(this.registration1, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient1, null, this.request, this.response); - OAuth2AuthorizedClient authorizedClient2 = new OAuth2AuthorizedClient( - this.registration2, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient2 = new OAuth2AuthorizedClient(this.registration2, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient2, null, this.request, this.response); - this.authorizedClientRepository.removeAuthorizedClient( - this.registrationId1, null, this.request, this.response); + this.authorizedClientRepository.removeAuthorizedClient(this.registrationId1, null, this.request, this.response); - OAuth2AuthorizedClient loadedAuthorizedClient2 = this.authorizedClientRepository.loadAuthorizedClient( - this.registrationId2, null, this.request); + OAuth2AuthorizedClient loadedAuthorizedClient2 = this.authorizedClientRepository + .loadAuthorizedClient(this.registrationId2, null, this.request); assertThat(loadedAuthorizedClient2).isNotNull(); assertThat(loadedAuthorizedClient2).isSameAs(authorizedClient2); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationCodeGrantFilterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationCodeGrantFilterTests.java index d1dba0d899..765cec6535 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationCodeGrantFilterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationCodeGrantFilterTests.java @@ -75,13 +75,21 @@ import static org.springframework.security.oauth2.core.endpoint.TestOAuth2Author * @author Parikshit Dutta */ public class OAuth2AuthorizationCodeGrantFilterTests { + private ClientRegistration registration1; + private String principalName1 = "principal-1"; + private ClientRegistrationRepository clientRegistrationRepository; + private OAuth2AuthorizedClientService authorizedClientService; + private OAuth2AuthorizedClientRepository authorizedClientRepository; + private AuthenticationManager authenticationManager; + private AuthorizationRequestRepository authorizationRequestRepository; + private OAuth2AuthorizationCodeGrantFilter filter; @Before @@ -89,11 +97,12 @@ public class OAuth2AuthorizationCodeGrantFilterTests { this.registration1 = TestClientRegistrations.clientRegistration().build(); this.clientRegistrationRepository = new InMemoryClientRegistrationRepository(this.registration1); this.authorizedClientService = new InMemoryOAuth2AuthorizedClientService(this.clientRegistrationRepository); - this.authorizedClientRepository = new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(this.authorizedClientService); + this.authorizedClientRepository = new AuthenticatedPrincipalOAuth2AuthorizedClientRepository( + this.authorizedClientService); this.authorizationRequestRepository = new HttpSessionOAuth2AuthorizationRequestRepository(); this.authenticationManager = mock(AuthenticationManager.class); - this.filter = spy(new OAuth2AuthorizationCodeGrantFilter( - this.clientRegistrationRepository, this.authorizedClientRepository, this.authenticationManager)); + this.filter = spy(new OAuth2AuthorizationCodeGrantFilter(this.clientRegistrationRepository, + this.authorizedClientRepository, this.authenticationManager)); this.filter.setAuthorizationRequestRepository(this.authorizationRequestRepository); TestingAuthenticationToken authentication = new TestingAuthenticationToken(this.principalName1, "password"); authentication.setAuthenticated(true); @@ -109,20 +118,20 @@ public class OAuth2AuthorizationCodeGrantFilterTests { @Test public void constructorWhenClientRegistrationRepositoryIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new OAuth2AuthorizationCodeGrantFilter(null, this.authorizedClientRepository, this.authenticationManager)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> new OAuth2AuthorizationCodeGrantFilter(null, this.authorizedClientRepository, + this.authenticationManager)).isInstanceOf(IllegalArgumentException.class); } @Test public void constructorWhenAuthorizedClientRepositoryIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new OAuth2AuthorizationCodeGrantFilter(this.clientRegistrationRepository, null, this.authenticationManager)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> new OAuth2AuthorizationCodeGrantFilter(this.clientRegistrationRepository, null, + this.authenticationManager)).isInstanceOf(IllegalArgumentException.class); } @Test public void constructorWhenAuthenticationManagerIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new OAuth2AuthorizationCodeGrantFilter(this.clientRegistrationRepository, this.authorizedClientRepository, null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> new OAuth2AuthorizationCodeGrantFilter(this.clientRegistrationRepository, + this.authorizedClientRepository, null)).isInstanceOf(IllegalArgumentException.class); } @Test @@ -133,8 +142,7 @@ public class OAuth2AuthorizationCodeGrantFilterTests { @Test public void setRequestCacheWhenRequestCacheIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.filter.setRequestCache(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.filter.setRequestCache(null)).isInstanceOf(IllegalArgumentException.class); } @Test @@ -142,7 +150,8 @@ public class OAuth2AuthorizationCodeGrantFilterTests { String requestUri = "/path"; MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); - // NOTE: A valid Authorization Response contains either a 'code' or 'error' parameter. + // NOTE: A valid Authorization Response contains either a 'code' or 'error' + // parameter. MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); @@ -195,7 +204,8 @@ public class OAuth2AuthorizationCodeGrantFilterTests { this.filter.doFilter(authorizationResponse, response, filterChain); verifyNoInteractions(filterChain); - // 2) redirect_uri with query parameters AND authorization response additional parameters + // 2) redirect_uri with query parameters AND authorization response additional + // parameters Map additionalParameters = new LinkedHashMap<>(); additionalParameters.put("auth-param1", "value1"); additionalParameters.put("auth-param2", "value2"); @@ -232,8 +242,7 @@ public class OAuth2AuthorizationCodeGrantFilterTests { parametersNotMatch = new LinkedHashMap<>(); parametersNotMatch.put("param2", "value2"); parametersNotMatch.put("param1", "value1"); - authorizationResponse = createAuthorizationResponse( - createAuthorizationRequest(requestUri, parametersNotMatch)); + authorizationResponse = createAuthorizationResponse(createAuthorizationRequest(requestUri, parametersNotMatch)); authorizationResponse.setSession(authorizationRequest.getSession()); this.filter.doFilter(authorizationResponse, response, filterChain); verify(filterChain, times(2)).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class)); @@ -241,8 +250,7 @@ public class OAuth2AuthorizationCodeGrantFilterTests { // 3) Parameter missing parametersNotMatch = new LinkedHashMap<>(parameters); parametersNotMatch.remove("param2"); - authorizationResponse = createAuthorizationResponse( - createAuthorizationRequest(requestUri, parametersNotMatch)); + authorizationResponse = createAuthorizationResponse(createAuthorizationRequest(requestUri, parametersNotMatch)); authorizationResponse.setSession(authorizationRequest.getSession()); this.filter.doFilter(authorizationResponse, response, filterChain); verify(filterChain, times(3)).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class)); @@ -272,7 +280,7 @@ public class OAuth2AuthorizationCodeGrantFilterTests { OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT); when(this.authenticationManager.authenticate(any(Authentication.class))) - .thenThrow(new OAuth2AuthorizationException(error)); + .thenThrow(new OAuth2AuthorizationException(error)); this.filter.doFilter(authorizationResponse, response, filterChain); @@ -290,8 +298,8 @@ public class OAuth2AuthorizationCodeGrantFilterTests { this.filter.doFilter(authorizationResponse, response, filterChain); - OAuth2AuthorizedClient authorizedClient = this.authorizedClientService.loadAuthorizedClient( - this.registration1.getRegistrationId(), this.principalName1); + OAuth2AuthorizedClient authorizedClient = this.authorizedClientService + .loadAuthorizedClient(this.registration1.getRegistrationId(), this.principalName1); assertThat(authorizedClient).isNotNull(); assertThat(authorizedClient.getClientRegistration()).isEqualTo(this.registration1); assertThat(authorizedClient.getPrincipalName()).isEqualTo(this.principalName1); @@ -356,9 +364,10 @@ public class OAuth2AuthorizationCodeGrantFilterTests { } @Test - public void doFilterWhenAuthorizationSucceedsAndAnonymousAccessThenAuthorizedClientSavedToHttpSession() throws Exception { - AnonymousAuthenticationToken anonymousPrincipal = - new AnonymousAuthenticationToken("key-1234", "anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); + public void doFilterWhenAuthorizationSucceedsAndAnonymousAccessThenAuthorizedClientSavedToHttpSession() + throws Exception { + AnonymousAuthenticationToken anonymousPrincipal = new AnonymousAuthenticationToken("key-1234", "anonymousUser", + AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); securityContext.setAuthentication(anonymousPrincipal); SecurityContextHolder.setContext(securityContext); @@ -383,17 +392,18 @@ public class OAuth2AuthorizationCodeGrantFilterTests { assertThat(session).isNotNull(); @SuppressWarnings("unchecked") - Map authorizedClients = (Map) - session.getAttribute(HttpSessionOAuth2AuthorizedClientRepository.class.getName() + ".AUTHORIZED_CLIENTS"); + Map authorizedClients = (Map) session + .getAttribute(HttpSessionOAuth2AuthorizedClientRepository.class.getName() + ".AUTHORIZED_CLIENTS"); assertThat(authorizedClients).isNotEmpty(); assertThat(authorizedClients).hasSize(1); assertThat(authorizedClients.values().iterator().next()).isSameAs(authorizedClient); } @Test - public void doFilterWhenAuthorizationSucceedsAndAnonymousAccessNullAuthenticationThenAuthorizedClientSavedToHttpSession() throws Exception { + public void doFilterWhenAuthorizationSucceedsAndAnonymousAccessNullAuthenticationThenAuthorizedClientSavedToHttpSession() + throws Exception { SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); - SecurityContextHolder.setContext(securityContext); // null Authentication + SecurityContextHolder.setContext(securityContext); // null Authentication MockHttpServletRequest authorizationRequest = createAuthorizationRequest("/callback/client-1"); MockHttpServletRequest authorizationResponse = createAuthorizationResponse(authorizationRequest); @@ -404,8 +414,8 @@ public class OAuth2AuthorizationCodeGrantFilterTests { this.filter.doFilter(authorizationResponse, response, filterChain); - OAuth2AuthorizedClient authorizedClient = this.authorizedClientRepository.loadAuthorizedClient( - this.registration1.getRegistrationId(), null, authorizationResponse); + OAuth2AuthorizedClient authorizedClient = this.authorizedClientRepository + .loadAuthorizedClient(this.registration1.getRegistrationId(), null, authorizationResponse); assertThat(authorizedClient).isNotNull(); assertThat(authorizedClient.getClientRegistration()).isEqualTo(this.registration1); assertThat(authorizedClient.getPrincipalName()).isEqualTo("anonymousUser"); @@ -415,8 +425,8 @@ public class OAuth2AuthorizationCodeGrantFilterTests { assertThat(session).isNotNull(); @SuppressWarnings("unchecked") - Map authorizedClients = (Map) - session.getAttribute(HttpSessionOAuth2AuthorizedClientRepository.class.getName() + ".AUTHORIZED_CLIENTS"); + Map authorizedClients = (Map) session + .getAttribute(HttpSessionOAuth2AuthorizedClientRepository.class.getName() + ".AUTHORIZED_CLIENTS"); assertThat(authorizedClients).isNotEmpty(); assertThat(authorizedClients).hasSize(1); assertThat(authorizedClients.values().iterator().next()).isSameAs(authorizedClient); @@ -426,15 +436,14 @@ public class OAuth2AuthorizationCodeGrantFilterTests { return createAuthorizationRequest(requestUri, new LinkedHashMap<>()); } - private static MockHttpServletRequest createAuthorizationRequest(String requestUri, Map parameters) { + private static MockHttpServletRequest createAuthorizationRequest(String requestUri, + Map parameters) { MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); if (!CollectionUtils.isEmpty(parameters)) { parameters.forEach(request::addParameter); - request.setQueryString( - parameters.entrySet().stream() - .map(e -> e.getKey() + "=" + e.getValue()) - .collect(Collectors.joining("&"))); + request.setQueryString(parameters.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()) + .collect(Collectors.joining("&"))); } return request; } @@ -443,36 +452,34 @@ public class OAuth2AuthorizationCodeGrantFilterTests { return createAuthorizationResponse(authorizationRequest, new LinkedHashMap<>()); } - private static MockHttpServletRequest createAuthorizationResponse( - MockHttpServletRequest authorizationRequest, Map additionalParameters) { - MockHttpServletRequest authorizationResponse = new MockHttpServletRequest( - authorizationRequest.getMethod(), authorizationRequest.getRequestURI()); + private static MockHttpServletRequest createAuthorizationResponse(MockHttpServletRequest authorizationRequest, + Map additionalParameters) { + MockHttpServletRequest authorizationResponse = new MockHttpServletRequest(authorizationRequest.getMethod(), + authorizationRequest.getRequestURI()); authorizationResponse.setServletPath(authorizationRequest.getRequestURI()); authorizationRequest.getParameterMap().forEach(authorizationResponse::addParameter); authorizationResponse.addParameter(OAuth2ParameterNames.CODE, "code"); authorizationResponse.addParameter(OAuth2ParameterNames.STATE, "state"); additionalParameters.forEach(authorizationResponse::addParameter); - authorizationResponse.setQueryString( - authorizationResponse.getParameterMap().entrySet().stream() - .map(e -> e.getKey() + "=" + e.getValue()[0]) - .collect(Collectors.joining("&"))); + authorizationResponse.setQueryString(authorizationResponse.getParameterMap().entrySet().stream() + .map(e -> e.getKey() + "=" + e.getValue()[0]).collect(Collectors.joining("&"))); authorizationResponse.setSession(authorizationRequest.getSession()); return authorizationResponse; } private void setUpAuthorizationRequest(HttpServletRequest request, HttpServletResponse response, - ClientRegistration registration) { + ClientRegistration registration) { Map attributes = new HashMap<>(); attributes.put(OAuth2ParameterNames.REGISTRATION_ID, registration.getRegistrationId()); - OAuth2AuthorizationRequest authorizationRequest = request() - .attributes(attributes) + OAuth2AuthorizationRequest authorizationRequest = request().attributes(attributes) .redirectUri(UrlUtils.buildFullRequestUrl(request)).build(); this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, request, response); } private void setUpAuthenticationResult(ClientRegistration registration) { - OAuth2AuthorizationCodeAuthenticationToken authentication = - new OAuth2AuthorizationCodeAuthenticationToken(registration, success(), noScopes(), refreshToken()); + OAuth2AuthorizationCodeAuthenticationToken authentication = new OAuth2AuthorizationCodeAuthenticationToken( + registration, success(), noScopes(), refreshToken()); when(this.authenticationManager.authenticate(any(Authentication.class))).thenReturn(authentication); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilterTests.java index 7cc320e770..3208657a9c 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilterTests.java @@ -51,24 +51,28 @@ import static org.mockito.Mockito.*; * @author Joe Grandja */ public class OAuth2AuthorizationRequestRedirectFilterTests { + private ClientRegistration registration1; + private ClientRegistration registration2; + private ClientRegistration registration3; + private ClientRegistrationRepository clientRegistrationRepository; + private OAuth2AuthorizationRequestRedirectFilter filter; + private RequestCache requestCache; @Before public void setUp() { this.registration1 = TestClientRegistrations.clientRegistration().build(); this.registration2 = TestClientRegistrations.clientRegistration2().build(); - this.registration3 = TestClientRegistrations.clientRegistration() - .registrationId("registration-3") - .authorizationGrantType(AuthorizationGrantType.IMPLICIT) - .redirectUri("{baseUrl}/authorize/oauth2/implicit/{registrationId}") - .build(); - this.clientRegistrationRepository = new InMemoryClientRegistrationRepository( - this.registration1, this.registration2, this.registration3); + this.registration3 = TestClientRegistrations.clientRegistration().registrationId("registration-3") + .authorizationGrantType(AuthorizationGrantType.IMPLICIT) + .redirectUri("{baseUrl}/authorize/oauth2/implicit/{registrationId}").build(); + this.clientRegistrationRepository = new InMemoryClientRegistrationRepository(this.registration1, + this.registration2, this.registration3); this.filter = new OAuth2AuthorizationRequestRedirectFilter(this.clientRegistrationRepository); this.requestCache = mock(RequestCache.class); this.filter.setRequestCache(this.requestCache); @@ -78,8 +82,7 @@ public class OAuth2AuthorizationRequestRedirectFilterTests { public void constructorWhenClientRegistrationRepositoryIsNullThenThrowIllegalArgumentException() { Constructor constructor = ClassUtils.getConstructorIfAvailable( OAuth2AuthorizationRequestRedirectFilter.class, ClientRegistrationRepository.class); - assertThatThrownBy(() -> constructor.newInstance(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> constructor.newInstance(null)).isInstanceOf(IllegalArgumentException.class); } @Test @@ -92,8 +95,7 @@ public class OAuth2AuthorizationRequestRedirectFilterTests { public void constructorWhenAuthorizationRequestResolverIsNullThenThrowIllegalArgumentException() { Constructor constructor = ClassUtils.getConstructorIfAvailable( OAuth2AuthorizationRequestRedirectFilter.class, OAuth2AuthorizationRequestResolver.class); - assertThatThrownBy(() -> constructor.newInstance(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> constructor.newInstance(null)).isInstanceOf(IllegalArgumentException.class); } @Test @@ -104,8 +106,7 @@ public class OAuth2AuthorizationRequestRedirectFilterTests { @Test public void setRequestCacheWhenRequestCacheIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.filter.setRequestCache(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.filter.setRequestCache(null)).isInstanceOf(IllegalArgumentException.class); } @Test @@ -123,8 +124,8 @@ public class OAuth2AuthorizationRequestRedirectFilterTests { @Test public void doFilterWhenAuthorizationRequestWithInvalidClientThenStatusInternalServerError() throws Exception { - String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + - "/" + this.registration1.getRegistrationId() + "-invalid"; + String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + + this.registration1.getRegistrationId() + "-invalid"; MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -140,8 +141,8 @@ public class OAuth2AuthorizationRequestRedirectFilterTests { @Test public void doFilterWhenAuthorizationRequestOAuth2LoginThenRedirectForAuthorization() throws Exception { - String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + - "/" + this.registration1.getRegistrationId(); + String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + + this.registration1.getRegistrationId(); MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -151,36 +152,35 @@ public class OAuth2AuthorizationRequestRedirectFilterTests { verifyZeroInteractions(filterChain); - assertThat(response.getRedirectedUrl()).matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=read:user&state=.{15,}&" + - "redirect_uri=http://localhost/login/oauth2/code/registration-id"); + assertThat(response.getRedirectedUrl()).matches("https://example.com/login/oauth/authorize\\?" + + "response_type=code&client_id=client-id&" + "scope=read:user&state=.{15,}&" + + "redirect_uri=http://localhost/login/oauth2/code/registration-id"); } @Test public void doFilterWhenAuthorizationRequestOAuth2LoginThenAuthorizationRequestSaved() throws Exception { - String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + - "/" + this.registration2.getRegistrationId(); + String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + + this.registration2.getRegistrationId(); MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); - AuthorizationRequestRepository authorizationRequestRepository = - mock(AuthorizationRequestRepository.class); + AuthorizationRequestRepository authorizationRequestRepository = mock( + AuthorizationRequestRepository.class); this.filter.setAuthorizationRequestRepository(authorizationRequestRepository); this.filter.doFilter(request, response, filterChain); verifyZeroInteractions(filterChain); - verify(authorizationRequestRepository).saveAuthorizationRequest( - any(OAuth2AuthorizationRequest.class), any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(authorizationRequestRepository).saveAuthorizationRequest(any(OAuth2AuthorizationRequest.class), + any(HttpServletRequest.class), any(HttpServletResponse.class)); } @Test public void doFilterWhenAuthorizationRequestImplicitGrantThenRedirectForAuthorization() throws Exception { - String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + - "/" + this.registration3.getRegistrationId(); + String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + + this.registration3.getRegistrationId(); MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -190,36 +190,36 @@ public class OAuth2AuthorizationRequestRedirectFilterTests { verifyZeroInteractions(filterChain); - assertThat(response.getRedirectedUrl()).matches("https://example.com/login/oauth/authorize\\?" + - "response_type=token&client_id=client-id&" + - "scope=read:user&state=.{15,}&" + - "redirect_uri=http://localhost/authorize/oauth2/implicit/registration-3"); + assertThat(response.getRedirectedUrl()).matches("https://example.com/login/oauth/authorize\\?" + + "response_type=token&client_id=client-id&" + "scope=read:user&state=.{15,}&" + + "redirect_uri=http://localhost/authorize/oauth2/implicit/registration-3"); } @Test public void doFilterWhenAuthorizationRequestImplicitGrantThenAuthorizationRequestNotSaved() throws Exception { - String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + - "/" + this.registration3.getRegistrationId(); + String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + + this.registration3.getRegistrationId(); MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); - AuthorizationRequestRepository authorizationRequestRepository = - mock(AuthorizationRequestRepository.class); + AuthorizationRequestRepository authorizationRequestRepository = mock( + AuthorizationRequestRepository.class); this.filter.setAuthorizationRequestRepository(authorizationRequestRepository); this.filter.doFilter(request, response, filterChain); verifyZeroInteractions(filterChain); - verify(authorizationRequestRepository, times(0)).saveAuthorizationRequest( - any(OAuth2AuthorizationRequest.class), any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(authorizationRequestRepository, times(0)).saveAuthorizationRequest(any(OAuth2AuthorizationRequest.class), + any(HttpServletRequest.class), any(HttpServletResponse.class)); } @Test public void doFilterWhenCustomAuthorizationRequestBaseUriThenRedirectForAuthorization() throws Exception { String authorizationRequestBaseUri = "/custom/authorization"; - this.filter = new OAuth2AuthorizationRequestRedirectFilter(this.clientRegistrationRepository, authorizationRequestBaseUri); + this.filter = new OAuth2AuthorizationRequestRedirectFilter(this.clientRegistrationRepository, + authorizationRequestBaseUri); String requestUri = authorizationRequestBaseUri + "/" + this.registration1.getRegistrationId(); MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); @@ -231,44 +231,44 @@ public class OAuth2AuthorizationRequestRedirectFilterTests { verifyZeroInteractions(filterChain); - assertThat(response.getRedirectedUrl()).matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=read:user&state=.{15,}&" + - "redirect_uri=http://localhost/login/oauth2/code/registration-id"); + assertThat(response.getRedirectedUrl()).matches("https://example.com/login/oauth/authorize\\?" + + "response_type=code&client_id=client-id&" + "scope=read:user&state=.{15,}&" + + "redirect_uri=http://localhost/login/oauth2/code/registration-id"); } @Test - public void doFilterWhenNotAuthorizationRequestAndClientAuthorizationRequiredExceptionThrownThenRedirectForAuthorization() throws Exception { + public void doFilterWhenNotAuthorizationRequestAndClientAuthorizationRequiredExceptionThrownThenRedirectForAuthorization() + throws Exception { String requestUri = "/path"; MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); - doThrow(new ClientAuthorizationRequiredException(this.registration1.getRegistrationId())) - .when(filterChain).doFilter(any(ServletRequest.class), any(ServletResponse.class)); + doThrow(new ClientAuthorizationRequiredException(this.registration1.getRegistrationId())).when(filterChain) + .doFilter(any(ServletRequest.class), any(ServletResponse.class)); this.filter.doFilter(request, response, filterChain); verify(filterChain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class)); - assertThat(response.getRedirectedUrl()).matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=read:user&state=.{15,}&" + - "redirect_uri=http://localhost/authorize/oauth2/code/registration-id"); + assertThat(response.getRedirectedUrl()).matches("https://example.com/login/oauth/authorize\\?" + + "response_type=code&client_id=client-id&" + "scope=read:user&state=.{15,}&" + + "redirect_uri=http://localhost/authorize/oauth2/code/registration-id"); verify(this.requestCache).saveRequest(any(HttpServletRequest.class), any(HttpServletResponse.class)); } @Test - public void doFilterWhenNotAuthorizationRequestAndClientAuthorizationRequiredExceptionThrownButAuthorizationRequestNotResolvedThenStatusInternalServerError() throws Exception { + public void doFilterWhenNotAuthorizationRequestAndClientAuthorizationRequiredExceptionThrownButAuthorizationRequestNotResolvedThenStatusInternalServerError() + throws Exception { String requestUri = "/path"; MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); MockHttpServletResponse response = new MockHttpServletResponse(); FilterChain filterChain = mock(FilterChain.class); - doThrow(new ClientAuthorizationRequiredException(this.registration1.getRegistrationId())) - .when(filterChain).doFilter(any(ServletRequest.class), any(ServletResponse.class)); + doThrow(new ClientAuthorizationRequiredException(this.registration1.getRegistrationId())).when(filterChain) + .doFilter(any(ServletRequest.class), any(ServletResponse.class)); OAuth2AuthorizationRequestResolver resolver = mock(OAuth2AuthorizationRequestResolver.class); OAuth2AuthorizationRequestRedirectFilter filter = new OAuth2AuthorizationRequestRedirectFilter(resolver); @@ -285,9 +285,10 @@ public class OAuth2AuthorizationRequestRedirectFilterTests { // gh-4911 @Test - public void doFilterWhenAuthorizationRequestAndAdditionalParametersProvidedThenAuthorizationRequestIncludesAdditionalParameters() throws Exception { - String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + - "/" + this.registration1.getRegistrationId(); + public void doFilterWhenAuthorizationRequestAndAdditionalParametersProvidedThenAuthorizationRequestIncludesAdditionalParameters() + throws Exception { + String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + + this.registration1.getRegistrationId(); MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); request.addParameter("idp", "https://other.provider.com"); @@ -295,14 +296,13 @@ public class OAuth2AuthorizationRequestRedirectFilterTests { FilterChain filterChain = mock(FilterChain.class); OAuth2AuthorizationRequestResolver defaultAuthorizationRequestResolver = new DefaultOAuth2AuthorizationRequestResolver( - this.clientRegistrationRepository, OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI); + this.clientRegistrationRepository, + OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI); OAuth2AuthorizationRequestResolver resolver = mock(OAuth2AuthorizationRequestResolver.class); OAuth2AuthorizationRequest result = OAuth2AuthorizationRequest .from(defaultAuthorizationRequestResolver.resolve(request)) - .additionalParameters( - Collections.singletonMap("idp", request.getParameter("idp"))) - .build(); + .additionalParameters(Collections.singletonMap("idp", request.getParameter("idp"))).build(); when(resolver.resolve(any())).thenReturn(result); OAuth2AuthorizationRequestRedirectFilter filter = new OAuth2AuthorizationRequestRedirectFilter(resolver); @@ -310,18 +310,18 @@ public class OAuth2AuthorizationRequestRedirectFilterTests { verifyZeroInteractions(filterChain); - assertThat(response.getRedirectedUrl()).matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=read:user&state=.{15,}&" + - "redirect_uri=http://localhost/login/oauth2/code/registration-id&" + - "idp=https://other.provider.com"); + assertThat(response.getRedirectedUrl()).matches("https://example.com/login/oauth/authorize\\?" + + "response_type=code&client_id=client-id&" + "scope=read:user&state=.{15,}&" + + "redirect_uri=http://localhost/login/oauth2/code/registration-id&" + + "idp=https://other.provider.com"); } // gh-4911, gh-5244 @Test - public void doFilterWhenAuthorizationRequestAndCustomAuthorizationRequestUriSetThenCustomAuthorizationRequestUriUsed() throws Exception { - String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + - "/" + this.registration1.getRegistrationId(); + public void doFilterWhenAuthorizationRequestAndCustomAuthorizationRequestUriSetThenCustomAuthorizationRequestUriUsed() + throws Exception { + String requestUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + + this.registration1.getRegistrationId(); MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); String loginHintParamName = "login_hint"; @@ -330,7 +330,8 @@ public class OAuth2AuthorizationRequestRedirectFilterTests { FilterChain filterChain = mock(FilterChain.class); OAuth2AuthorizationRequestResolver defaultAuthorizationRequestResolver = new DefaultOAuth2AuthorizationRequestResolver( - this.clientRegistrationRepository, OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI); + this.clientRegistrationRepository, + OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI); OAuth2AuthorizationRequestResolver resolver = mock(OAuth2AuthorizationRequestResolver.class); @@ -339,14 +340,11 @@ public class OAuth2AuthorizationRequestRedirectFilterTests { additionalParameters.put(loginHintParamName, request.getParameter(loginHintParamName)); String customAuthorizationRequestUri = UriComponentsBuilder .fromUriString(defaultAuthorizationRequest.getAuthorizationRequestUri()) - .queryParam(loginHintParamName, additionalParameters.get(loginHintParamName)) - .build(true).toUriString(); + .queryParam(loginHintParamName, additionalParameters.get(loginHintParamName)).build(true).toUriString(); OAuth2AuthorizationRequest result = OAuth2AuthorizationRequest .from(defaultAuthorizationRequestResolver.resolve(request)) - .additionalParameters( - Collections.singletonMap("idp", request.getParameter("idp"))) - .authorizationRequestUri(customAuthorizationRequestUri) - .build(); + .additionalParameters(Collections.singletonMap("idp", request.getParameter("idp"))) + .authorizationRequestUri(customAuthorizationRequestUri).build(); when(resolver.resolve(any())).thenReturn(result); OAuth2AuthorizationRequestRedirectFilter filter = new OAuth2AuthorizationRequestRedirectFilter(resolver); @@ -355,10 +353,10 @@ public class OAuth2AuthorizationRequestRedirectFilterTests { verifyZeroInteractions(filterChain); - assertThat(response.getRedirectedUrl()).matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=read:user&state=.{15,}&" + - "redirect_uri=http://localhost/login/oauth2/code/registration-id&" + - "login_hint=user@provider\\.com"); + assertThat(response.getRedirectedUrl()).matches("https://example.com/login/oauth/authorize\\?" + + "response_type=code&client_id=client-id&" + "scope=read:user&state=.{15,}&" + + "redirect_uri=http://localhost/login/oauth2/code/registration-id&" + + "login_hint=user@provider\\.com"); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilterTests.java index 07f8ebed92..00e584296f 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilterTests.java @@ -72,27 +72,40 @@ import static org.springframework.security.oauth2.core.endpoint.TestOAuth2Author * @author Joe Grandja */ public class OAuth2LoginAuthenticationFilterTests { + private ClientRegistration registration1; + private ClientRegistration registration2; + private String principalName1 = "principal-1"; + private ClientRegistrationRepository clientRegistrationRepository; + private OAuth2AuthorizedClientRepository authorizedClientRepository; + private OAuth2AuthorizedClientService authorizedClientService; + private AuthorizationRequestRepository authorizationRequestRepository; + private AuthenticationFailureHandler failureHandler; + private AuthenticationManager authenticationManager; + private AuthenticationDetailsSource authenticationDetailsSource; + private OAuth2LoginAuthenticationToken loginAuthentication; + private OAuth2LoginAuthenticationFilter filter; @Before public void setUp() { this.registration1 = TestClientRegistrations.clientRegistration().build(); this.registration2 = TestClientRegistrations.clientRegistration2().build(); - this.clientRegistrationRepository = new InMemoryClientRegistrationRepository( - this.registration1, this.registration2); + this.clientRegistrationRepository = new InMemoryClientRegistrationRepository(this.registration1, + this.registration2); this.authorizedClientService = new InMemoryOAuth2AuthorizedClientService(this.clientRegistrationRepository); - this.authorizedClientRepository = new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(this.authorizedClientService); + this.authorizedClientRepository = new AuthenticatedPrincipalOAuth2AuthorizedClientRepository( + this.authorizedClientService); this.authorizationRequestRepository = new HttpSessionOAuth2AuthorizationRequestRepository(); this.failureHandler = mock(AuthenticationFailureHandler.class); this.authenticationManager = mock(AuthenticationManager.class); @@ -121,13 +134,13 @@ public class OAuth2LoginAuthenticationFilterTests { public void constructorWhenAuthorizedClientRepositoryIsNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new OAuth2LoginAuthenticationFilter(this.clientRegistrationRepository, (OAuth2AuthorizedClientRepository) null, OAuth2LoginAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @Test public void constructorWhenFilterProcessesUrlIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new OAuth2LoginAuthenticationFilter(this.clientRegistrationRepository, this.authorizedClientRepository, null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> new OAuth2LoginAuthenticationFilter(this.clientRegistrationRepository, + this.authorizedClientRepository, null)).isInstanceOf(IllegalArgumentException.class); } @Test @@ -147,7 +160,8 @@ public class OAuth2LoginAuthenticationFilterTests { this.filter.doFilter(request, response, filterChain); verify(filterChain).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class)); - verify(this.filter, never()).attemptAuthentication(any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(this.filter, never()).attemptAuthentication(any(HttpServletRequest.class), + any(HttpServletResponse.class)); } @Test @@ -164,17 +178,20 @@ public class OAuth2LoginAuthenticationFilterTests { this.filter.doFilter(request, response, filterChain); - ArgumentCaptor authenticationExceptionArgCaptor = ArgumentCaptor.forClass(AuthenticationException.class); - verify(this.failureHandler).onAuthenticationFailure(any(HttpServletRequest.class), any(HttpServletResponse.class), - authenticationExceptionArgCaptor.capture()); + ArgumentCaptor authenticationExceptionArgCaptor = ArgumentCaptor + .forClass(AuthenticationException.class); + verify(this.failureHandler).onAuthenticationFailure(any(HttpServletRequest.class), + any(HttpServletResponse.class), authenticationExceptionArgCaptor.capture()); assertThat(authenticationExceptionArgCaptor.getValue()).isInstanceOf(OAuth2AuthenticationException.class); - OAuth2AuthenticationException authenticationException = (OAuth2AuthenticationException) authenticationExceptionArgCaptor.getValue(); + OAuth2AuthenticationException authenticationException = (OAuth2AuthenticationException) authenticationExceptionArgCaptor + .getValue(); assertThat(authenticationException.getError().getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_REQUEST); } @Test - public void doFilterWhenAuthorizationResponseAuthorizationRequestNotFoundThenAuthorizationRequestNotFoundError() throws Exception { + public void doFilterWhenAuthorizationResponseAuthorizationRequestNotFoundThenAuthorizationRequestNotFoundError() + throws Exception { String requestUri = "/login/oauth2/code/" + this.registration2.getRegistrationId(); MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); request.setServletPath(requestUri); @@ -186,18 +203,21 @@ public class OAuth2LoginAuthenticationFilterTests { this.filter.doFilter(request, response, filterChain); - ArgumentCaptor authenticationExceptionArgCaptor = ArgumentCaptor.forClass(AuthenticationException.class); - verify(this.failureHandler).onAuthenticationFailure(any(HttpServletRequest.class), any(HttpServletResponse.class), - authenticationExceptionArgCaptor.capture()); + ArgumentCaptor authenticationExceptionArgCaptor = ArgumentCaptor + .forClass(AuthenticationException.class); + verify(this.failureHandler).onAuthenticationFailure(any(HttpServletRequest.class), + any(HttpServletResponse.class), authenticationExceptionArgCaptor.capture()); assertThat(authenticationExceptionArgCaptor.getValue()).isInstanceOf(OAuth2AuthenticationException.class); - OAuth2AuthenticationException authenticationException = (OAuth2AuthenticationException) authenticationExceptionArgCaptor.getValue(); + OAuth2AuthenticationException authenticationException = (OAuth2AuthenticationException) authenticationExceptionArgCaptor + .getValue(); assertThat(authenticationException.getError().getErrorCode()).isEqualTo("authorization_request_not_found"); } // gh-5251 @Test - public void doFilterWhenAuthorizationResponseClientRegistrationNotFoundThenClientRegistrationNotFoundError() throws Exception { + public void doFilterWhenAuthorizationResponseClientRegistrationNotFoundThenClientRegistrationNotFoundError() + throws Exception { String requestUri = "/login/oauth2/code/" + this.registration2.getRegistrationId(); String state = "state"; MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); @@ -209,28 +229,25 @@ public class OAuth2LoginAuthenticationFilterTests { FilterChain filterChain = mock(FilterChain.class); ClientRegistration registrationNotFound = ClientRegistration.withRegistrationId("registration-not-found") - .clientId("client-1") - .clientSecret("secret") + .clientId("client-1").clientSecret("secret") .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri("{baseUrl}/login/oauth2/code/{registrationId}") - .scope("user") - .authorizationUri("https://provider.com/oauth2/authorize") - .tokenUri("https://provider.com/oauth2/token") - .userInfoUri("https://provider.com/oauth2/user") - .userNameAttributeName("id") - .clientName("client-1") + .redirectUri("{baseUrl}/login/oauth2/code/{registrationId}").scope("user") + .authorizationUri("https://provider.com/oauth2/authorize").tokenUri("https://provider.com/oauth2/token") + .userInfoUri("https://provider.com/oauth2/user").userNameAttributeName("id").clientName("client-1") .build(); this.setUpAuthorizationRequest(request, response, registrationNotFound, state); this.filter.doFilter(request, response, filterChain); - ArgumentCaptor authenticationExceptionArgCaptor = ArgumentCaptor.forClass(AuthenticationException.class); - verify(this.failureHandler).onAuthenticationFailure(any(HttpServletRequest.class), any(HttpServletResponse.class), - authenticationExceptionArgCaptor.capture()); + ArgumentCaptor authenticationExceptionArgCaptor = ArgumentCaptor + .forClass(AuthenticationException.class); + verify(this.failureHandler).onAuthenticationFailure(any(HttpServletRequest.class), + any(HttpServletResponse.class), authenticationExceptionArgCaptor.capture()); assertThat(authenticationExceptionArgCaptor.getValue()).isInstanceOf(OAuth2AuthenticationException.class); - OAuth2AuthenticationException authenticationException = (OAuth2AuthenticationException) authenticationExceptionArgCaptor.getValue(); + OAuth2AuthenticationException authenticationException = (OAuth2AuthenticationException) authenticationExceptionArgCaptor + .getValue(); assertThat(authenticationException.getError().getErrorCode()).isEqualTo("client_registration_not_found"); } @@ -271,8 +288,8 @@ public class OAuth2LoginAuthenticationFilterTests { this.filter.doFilter(request, response, filterChain); - OAuth2AuthorizedClient authorizedClient = this.authorizedClientRepository.loadAuthorizedClient( - this.registration1.getRegistrationId(), this.loginAuthentication, request); + OAuth2AuthorizedClient authorizedClient = this.authorizedClientRepository + .loadAuthorizedClient(this.registration1.getRegistrationId(), this.loginAuthentication, request); assertThat(authorizedClient).isNotNull(); assertThat(authorizedClient.getClientRegistration()).isEqualTo(this.registration1); assertThat(authorizedClient.getPrincipalName()).isEqualTo(this.principalName1); @@ -283,8 +300,8 @@ public class OAuth2LoginAuthenticationFilterTests { @Test public void doFilterWhenCustomFilterProcessesUrlThenFilterProcesses() throws Exception { String filterProcessesUrl = "/login/oauth2/custom/*"; - this.filter = spy(new OAuth2LoginAuthenticationFilter( - this.clientRegistrationRepository, this.authorizedClientRepository, filterProcessesUrl)); + this.filter = spy(new OAuth2LoginAuthenticationFilter(this.clientRegistrationRepository, + this.authorizedClientRepository, filterProcessesUrl)); this.filter.setAuthenticationManager(this.authenticationManager); String requestUri = "/login/oauth2/custom/" + this.registration2.getRegistrationId(); @@ -308,7 +325,8 @@ public class OAuth2LoginAuthenticationFilterTests { // gh-5890 @Test - public void doFilterWhenAuthorizationResponseHasDefaultPort80ThenRedirectUriMatchingExcludesPort() throws Exception { + public void doFilterWhenAuthorizationResponseHasDefaultPort80ThenRedirectUriMatchingExcludesPort() + throws Exception { String requestUri = "/login/oauth2/code/" + this.registration2.getRegistrationId(); String state = "state"; MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); @@ -330,9 +348,12 @@ public class OAuth2LoginAuthenticationFilterTests { ArgumentCaptor authenticationArgCaptor = ArgumentCaptor.forClass(Authentication.class); verify(this.authenticationManager).authenticate(authenticationArgCaptor.capture()); - OAuth2LoginAuthenticationToken authentication = (OAuth2LoginAuthenticationToken) authenticationArgCaptor.getValue(); - OAuth2AuthorizationRequest authorizationRequest = authentication.getAuthorizationExchange().getAuthorizationRequest(); - OAuth2AuthorizationResponse authorizationResponse = authentication.getAuthorizationExchange().getAuthorizationResponse(); + OAuth2LoginAuthenticationToken authentication = (OAuth2LoginAuthenticationToken) authenticationArgCaptor + .getValue(); + OAuth2AuthorizationRequest authorizationRequest = authentication.getAuthorizationExchange() + .getAuthorizationRequest(); + OAuth2AuthorizationResponse authorizationResponse = authentication.getAuthorizationExchange() + .getAuthorizationResponse(); String expectedRedirectUri = "http://localhost/login/oauth2/code/registration-id-2"; assertThat(authorizationRequest.getRedirectUri()).isEqualTo(expectedRedirectUri); @@ -341,7 +362,8 @@ public class OAuth2LoginAuthenticationFilterTests { // gh-5890 @Test - public void doFilterWhenAuthorizationResponseHasDefaultPort443ThenRedirectUriMatchingExcludesPort() throws Exception { + public void doFilterWhenAuthorizationResponseHasDefaultPort443ThenRedirectUriMatchingExcludesPort() + throws Exception { String requestUri = "/login/oauth2/code/" + this.registration2.getRegistrationId(); String state = "state"; MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); @@ -363,9 +385,12 @@ public class OAuth2LoginAuthenticationFilterTests { ArgumentCaptor authenticationArgCaptor = ArgumentCaptor.forClass(Authentication.class); verify(this.authenticationManager).authenticate(authenticationArgCaptor.capture()); - OAuth2LoginAuthenticationToken authentication = (OAuth2LoginAuthenticationToken) authenticationArgCaptor.getValue(); - OAuth2AuthorizationRequest authorizationRequest = authentication.getAuthorizationExchange().getAuthorizationRequest(); - OAuth2AuthorizationResponse authorizationResponse = authentication.getAuthorizationExchange().getAuthorizationResponse(); + OAuth2LoginAuthenticationToken authentication = (OAuth2LoginAuthenticationToken) authenticationArgCaptor + .getValue(); + OAuth2AuthorizationRequest authorizationRequest = authentication.getAuthorizationExchange() + .getAuthorizationRequest(); + OAuth2AuthorizationResponse authorizationResponse = authentication.getAuthorizationExchange() + .getAuthorizationResponse(); String expectedRedirectUri = "https://example.com/login/oauth2/code/registration-id-2"; assertThat(authorizationRequest.getRedirectUri()).isEqualTo(expectedRedirectUri); @@ -374,7 +399,8 @@ public class OAuth2LoginAuthenticationFilterTests { // gh-5890 @Test - public void doFilterWhenAuthorizationResponseHasNonDefaultPortThenRedirectUriMatchingIncludesPort() throws Exception { + public void doFilterWhenAuthorizationResponseHasNonDefaultPortThenRedirectUriMatchingIncludesPort() + throws Exception { String requestUri = "/login/oauth2/code/" + this.registration2.getRegistrationId(); String state = "state"; MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); @@ -396,9 +422,12 @@ public class OAuth2LoginAuthenticationFilterTests { ArgumentCaptor authenticationArgCaptor = ArgumentCaptor.forClass(Authentication.class); verify(this.authenticationManager).authenticate(authenticationArgCaptor.capture()); - OAuth2LoginAuthenticationToken authentication = (OAuth2LoginAuthenticationToken) authenticationArgCaptor.getValue(); - OAuth2AuthorizationRequest authorizationRequest = authentication.getAuthorizationExchange().getAuthorizationRequest(); - OAuth2AuthorizationResponse authorizationResponse = authentication.getAuthorizationExchange().getAuthorizationResponse(); + OAuth2LoginAuthenticationToken authentication = (OAuth2LoginAuthenticationToken) authenticationArgCaptor + .getValue(); + OAuth2AuthorizationRequest authorizationRequest = authentication.getAuthorizationExchange() + .getAuthorizationRequest(); + OAuth2AuthorizationResponse authorizationResponse = authentication.getAuthorizationExchange() + .getAuthorizationResponse(); String expectedRedirectUri = "https://example.com:9090/login/oauth2/code/registration-id-2"; assertThat(authorizationRequest.getRedirectUri()).isEqualTo(expectedRedirectUri); @@ -429,34 +458,26 @@ public class OAuth2LoginAuthenticationFilterTests { } private void setUpAuthorizationRequest(HttpServletRequest request, HttpServletResponse response, - ClientRegistration registration, String state) { + ClientRegistration registration, String state) { Map attributes = new HashMap<>(); attributes.put(OAuth2ParameterNames.REGISTRATION_ID, registration.getRegistrationId()); OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() .authorizationUri(registration.getProviderDetails().getAuthorizationUri()) - .clientId(registration.getClientId()) - .redirectUri(expandRedirectUri(request, registration)) - .scopes(registration.getScopes()) - .state(state) - .attributes(attributes) - .build(); + .clientId(registration.getClientId()).redirectUri(expandRedirectUri(request, registration)) + .scopes(registration.getScopes()).state(state).attributes(attributes).build(); this.authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, request, response); } private String expandRedirectUri(HttpServletRequest request, ClientRegistration clientRegistration) { - String baseUrl = UriComponentsBuilder.fromHttpUrl(UrlUtils.buildFullRequestUrl(request)) - .replaceQuery(null) - .replacePath(request.getContextPath()) - .build() - .toUriString(); + String baseUrl = UriComponentsBuilder.fromHttpUrl(UrlUtils.buildFullRequestUrl(request)).replaceQuery(null) + .replacePath(request.getContextPath()).build().toUriString(); Map uriVariables = new HashMap<>(); uriVariables.put("baseUrl", baseUrl); uriVariables.put("action", "login"); uriVariables.put("registrationId", clientRegistration.getRegistrationId()); - return UriComponentsBuilder.fromUriString(clientRegistration.getRedirectUri()) - .buildAndExpand(uriVariables) + return UriComponentsBuilder.fromUriString(clientRegistration.getRedirectUri()).buildAndExpand(uriVariables) .toUriString(); } @@ -474,4 +495,5 @@ public class OAuth2LoginAuthenticationFilterTests { when(this.loginAuthentication.isAuthenticated()).thenReturn(true); when(this.authenticationManager.authenticate(any(Authentication.class))).thenReturn(this.loginAuthentication); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/method/annotation/OAuth2AuthorizedClientArgumentResolverTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/method/annotation/OAuth2AuthorizedClientArgumentResolverTests.java index ba563f4399..088a992959 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/method/annotation/OAuth2AuthorizedClientArgumentResolverTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/method/annotation/OAuth2AuthorizedClientArgumentResolverTests.java @@ -69,17 +69,29 @@ import static org.mockito.Mockito.*; * @author Joe Grandja */ public class OAuth2AuthorizedClientArgumentResolverTests { + private TestingAuthenticationToken authentication; + private String principalName = "principal-1"; + private ClientRegistration registration1; + private ClientRegistration registration2; + private ClientRegistration registration3; + private ClientRegistrationRepository clientRegistrationRepository; + private OAuth2AuthorizedClient authorizedClient1; + private OAuth2AuthorizedClient authorizedClient2; + private OAuth2AuthorizedClientRepository authorizedClientRepository; + private OAuth2AuthorizedClientArgumentResolver argumentResolver; + private MockHttpServletRequest request; + private MockHttpServletResponse response; @Before @@ -89,49 +101,35 @@ public class OAuth2AuthorizedClientArgumentResolverTests { securityContext.setAuthentication(this.authentication); SecurityContextHolder.setContext(securityContext); - this.registration1 = ClientRegistration.withRegistrationId("client1") - .clientId("client-1") - .clientSecret("secret") - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + this.registration1 = ClientRegistration.withRegistrationId("client1").clientId("client-1") + .clientSecret("secret").clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .redirectUri("{baseUrl}/login/oauth2/code/{registrationId}") - .scope("user") - .authorizationUri("https://provider.com/oauth2/authorize") - .tokenUri("https://provider.com/oauth2/token") - .userInfoUri("https://provider.com/oauth2/user") - .userNameAttributeName("id") - .clientName("client-1") - .build(); - this.registration2 = ClientRegistration.withRegistrationId("client2") - .clientId("client-2") - .clientSecret("secret") - .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) - .scope("read", "write") - .tokenUri("https://provider.com/oauth2/token") + .redirectUri("{baseUrl}/login/oauth2/code/{registrationId}").scope("user") + .authorizationUri("https://provider.com/oauth2/authorize").tokenUri("https://provider.com/oauth2/token") + .userInfoUri("https://provider.com/oauth2/user").userNameAttributeName("id").clientName("client-1") .build(); + this.registration2 = ClientRegistration.withRegistrationId("client2").clientId("client-2") + .clientSecret("secret").clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) + .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).scope("read", "write") + .tokenUri("https://provider.com/oauth2/token").build(); this.registration3 = TestClientRegistrations.password().registrationId("client3").build(); - this.clientRegistrationRepository = new InMemoryClientRegistrationRepository( - this.registration1, this.registration2, this.registration3); + this.clientRegistrationRepository = new InMemoryClientRegistrationRepository(this.registration1, + this.registration2, this.registration3); this.authorizedClientRepository = mock(OAuth2AuthorizedClientRepository.class); - OAuth2AuthorizedClientProvider authorizedClientProvider = - OAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .refreshToken() - .clientCredentials() - .build(); + OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() + .authorizationCode().refreshToken().clientCredentials().build(); DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( this.clientRegistrationRepository, this.authorizedClientRepository); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); this.argumentResolver = new OAuth2AuthorizedClientArgumentResolver(authorizedClientManager); - this.authorizedClient1 = new OAuth2AuthorizedClient(this.registration1, this.principalName, mock(OAuth2AccessToken.class)); - when(this.authorizedClientRepository.loadAuthorizedClient( - eq(this.registration1.getRegistrationId()), any(Authentication.class), any(HttpServletRequest.class))) - .thenReturn(this.authorizedClient1); - this.authorizedClient2 = new OAuth2AuthorizedClient(this.registration2, this.principalName, mock(OAuth2AccessToken.class)); - when(this.authorizedClientRepository.loadAuthorizedClient( - eq(this.registration2.getRegistrationId()), any(Authentication.class), any(HttpServletRequest.class))) - .thenReturn(this.authorizedClient2); + this.authorizedClient1 = new OAuth2AuthorizedClient(this.registration1, this.principalName, + mock(OAuth2AccessToken.class)); + when(this.authorizedClientRepository.loadAuthorizedClient(eq(this.registration1.getRegistrationId()), + any(Authentication.class), any(HttpServletRequest.class))).thenReturn(this.authorizedClient1); + this.authorizedClient2 = new OAuth2AuthorizedClient(this.registration2, this.principalName, + mock(OAuth2AccessToken.class)); + when(this.authorizedClientRepository.loadAuthorizedClient(eq(this.registration2.getRegistrationId()), + any(Authentication.class), any(HttpServletRequest.class))).thenReturn(this.authorizedClient2); this.request = new MockHttpServletRequest(); this.response = new MockHttpServletResponse(); } @@ -168,21 +166,24 @@ public class OAuth2AuthorizedClientArgumentResolverTests { @Test public void setClientCredentialsTokenResponseClientWhenNotDefaultAuthorizedClientManagerThenThrowIllegalStateException() { - assertThatThrownBy(() -> this.argumentResolver.setClientCredentialsTokenResponseClient(new DefaultClientCredentialsTokenResponseClient())) - .isInstanceOf(IllegalStateException.class) - .hasMessage("The client cannot be set when the constructor used is \"OAuth2AuthorizedClientArgumentResolver(OAuth2AuthorizedClientManager)\". " + - "Instead, use the constructor \"OAuth2AuthorizedClientArgumentResolver(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\"."); + assertThatThrownBy(() -> this.argumentResolver + .setClientCredentialsTokenResponseClient(new DefaultClientCredentialsTokenResponseClient())) + .isInstanceOf(IllegalStateException.class).hasMessage( + "The client cannot be set when the constructor used is \"OAuth2AuthorizedClientArgumentResolver(OAuth2AuthorizedClientManager)\". " + + "Instead, use the constructor \"OAuth2AuthorizedClientArgumentResolver(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\"."); } @Test public void supportsParameterWhenParameterTypeOAuth2AuthorizedClientThenTrue() { - MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClient", OAuth2AuthorizedClient.class); + MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClient", + OAuth2AuthorizedClient.class); assertThat(this.argumentResolver.supportsParameter(methodParameter)).isTrue(); } @Test public void supportsParameterWhenParameterTypeOAuth2AuthorizedClientWithoutAnnotationThenFalse() { - MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClientWithoutAnnotation", OAuth2AuthorizedClient.class); + MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClientWithoutAnnotation", + OAuth2AuthorizedClient.class); assertThat(this.argumentResolver.supportsParameter(methodParameter)).isFalse(); } @@ -194,7 +195,8 @@ public class OAuth2AuthorizedClientArgumentResolverTests { @Test public void supportsParameterWhenParameterTypeUnsupportedWithoutAnnotationThenFalse() { - MethodParameter methodParameter = this.getMethodParameter("paramTypeUnsupportedWithoutAnnotation", String.class); + MethodParameter methodParameter = this.getMethodParameter("paramTypeUnsupportedWithoutAnnotation", + String.class); assertThat(this.argumentResolver.supportsParameter(methodParameter)).isFalse(); } @@ -202,8 +204,8 @@ public class OAuth2AuthorizedClientArgumentResolverTests { public void resolveArgumentWhenRegistrationIdEmptyAndNotOAuth2AuthenticationThenThrowIllegalArgumentException() { MethodParameter methodParameter = this.getMethodParameter("registrationIdEmpty", OAuth2AuthorizedClient.class); assertThatThrownBy(() -> this.argumentResolver.resolveArgument(methodParameter, null, null, null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Unable to resolve the Client Registration Identifier. It must be provided via @RegisteredOAuth2AuthorizedClient(\"client1\") or @RegisteredOAuth2AuthorizedClient(registrationId = \"client1\")."); + .isInstanceOf(IllegalArgumentException.class).hasMessage( + "Unable to resolve the Client Registration Identifier. It must be provided via @RegisteredOAuth2AuthorizedClient(\"client1\") or @RegisteredOAuth2AuthorizedClient(registrationId = \"client1\")."); } @Test @@ -214,77 +216,79 @@ public class OAuth2AuthorizedClientArgumentResolverTests { securityContext.setAuthentication(authentication); SecurityContextHolder.setContext(securityContext); MethodParameter methodParameter = this.getMethodParameter("registrationIdEmpty", OAuth2AuthorizedClient.class); - assertThat(this.argumentResolver.resolveArgument( - methodParameter, null, new ServletWebRequest(this.request, this.response), null)).isSameAs(this.authorizedClient1); + assertThat(this.argumentResolver.resolveArgument(methodParameter, null, + new ServletWebRequest(this.request, this.response), null)).isSameAs(this.authorizedClient1); } @Test public void resolveArgumentWhenAuthorizedClientFoundThenResolves() throws Exception { - MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClient", OAuth2AuthorizedClient.class); - assertThat(this.argumentResolver.resolveArgument( - methodParameter, null, new ServletWebRequest(this.request, this.response), null)).isSameAs(this.authorizedClient1); + MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClient", + OAuth2AuthorizedClient.class); + assertThat(this.argumentResolver.resolveArgument(methodParameter, null, + new ServletWebRequest(this.request, this.response), null)).isSameAs(this.authorizedClient1); } @Test public void resolveArgumentWhenRegistrationIdInvalidThenThrowIllegalArgumentException() { - MethodParameter methodParameter = this.getMethodParameter("registrationIdInvalid", OAuth2AuthorizedClient.class); - assertThatThrownBy(() -> this.argumentResolver.resolveArgument(methodParameter, null, new ServletWebRequest(this.request, this.response), null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Could not find ClientRegistration with id 'invalid'"); + MethodParameter methodParameter = this.getMethodParameter("registrationIdInvalid", + OAuth2AuthorizedClient.class); + assertThatThrownBy(() -> this.argumentResolver.resolveArgument(methodParameter, null, + new ServletWebRequest(this.request, this.response), null)).isInstanceOf(IllegalArgumentException.class) + .hasMessage("Could not find ClientRegistration with id 'invalid'"); } @Test public void resolveArgumentWhenAuthorizedClientNotFoundForAuthorizationCodeClientThenThrowClientAuthorizationRequiredException() { when(this.authorizedClientRepository.loadAuthorizedClient(anyString(), any(), any(HttpServletRequest.class))) .thenReturn(null); - MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClient", OAuth2AuthorizedClient.class); - assertThatThrownBy(() -> this.argumentResolver.resolveArgument(methodParameter, null, new ServletWebRequest(this.request, this.response), null)) - .isInstanceOf(ClientAuthorizationRequiredException.class); + MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClient", + OAuth2AuthorizedClient.class); + assertThatThrownBy(() -> this.argumentResolver.resolveArgument(methodParameter, null, + new ServletWebRequest(this.request, this.response), null)) + .isInstanceOf(ClientAuthorizationRequiredException.class); } @SuppressWarnings("unchecked") @Test - public void resolveArgumentWhenAuthorizedClientNotFoundForClientCredentialsClientThenResolvesFromTokenResponseClient() throws Exception { - OAuth2AccessTokenResponseClient clientCredentialsTokenResponseClient = - mock(OAuth2AccessTokenResponseClient.class); - ClientCredentialsOAuth2AuthorizedClientProvider clientCredentialsAuthorizedClientProvider = - new ClientCredentialsOAuth2AuthorizedClientProvider(); + public void resolveArgumentWhenAuthorizedClientNotFoundForClientCredentialsClientThenResolvesFromTokenResponseClient() + throws Exception { + OAuth2AccessTokenResponseClient clientCredentialsTokenResponseClient = mock( + OAuth2AccessTokenResponseClient.class); + ClientCredentialsOAuth2AuthorizedClientProvider clientCredentialsAuthorizedClientProvider = new ClientCredentialsOAuth2AuthorizedClientProvider(); clientCredentialsAuthorizedClientProvider.setAccessTokenResponseClient(clientCredentialsTokenResponseClient); DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( this.clientRegistrationRepository, this.authorizedClientRepository); authorizedClientManager.setAuthorizedClientProvider(clientCredentialsAuthorizedClientProvider); this.argumentResolver = new OAuth2AuthorizedClientArgumentResolver(authorizedClientManager); - OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse - .withToken("access-token-1234") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(3600) - .build(); + OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("access-token-1234") + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(3600).build(); when(clientCredentialsTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); when(this.authorizedClientRepository.loadAuthorizedClient(anyString(), any(), any(HttpServletRequest.class))) .thenReturn(null); - MethodParameter methodParameter = this.getMethodParameter("clientCredentialsClient", OAuth2AuthorizedClient.class); + MethodParameter methodParameter = this.getMethodParameter("clientCredentialsClient", + OAuth2AuthorizedClient.class); - OAuth2AuthorizedClient authorizedClient = (OAuth2AuthorizedClient) this.argumentResolver.resolveArgument( - methodParameter, null, new ServletWebRequest(this.request, this.response), null); + OAuth2AuthorizedClient authorizedClient = (OAuth2AuthorizedClient) this.argumentResolver + .resolveArgument(methodParameter, null, new ServletWebRequest(this.request, this.response), null); assertThat(authorizedClient).isNotNull(); assertThat(authorizedClient.getClientRegistration()).isSameAs(this.registration2); assertThat(authorizedClient.getPrincipalName()).isEqualTo(this.principalName); assertThat(authorizedClient.getAccessToken()).isSameAs(accessTokenResponse.getAccessToken()); - verify(this.authorizedClientRepository).saveAuthorizedClient( - eq(authorizedClient), eq(this.authentication), any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(this.authorizedClientRepository).saveAuthorizedClient(eq(authorizedClient), eq(this.authentication), + any(HttpServletRequest.class), any(HttpServletResponse.class)); } @SuppressWarnings("unchecked") @Test - public void resolveArgumentWhenAuthorizedClientNotFoundForPasswordClientThenResolvesFromTokenResponseClient() throws Exception { - OAuth2AccessTokenResponseClient passwordTokenResponseClient = - mock(OAuth2AccessTokenResponseClient.class); - PasswordOAuth2AuthorizedClientProvider passwordAuthorizedClientProvider = - new PasswordOAuth2AuthorizedClientProvider(); + public void resolveArgumentWhenAuthorizedClientNotFoundForPasswordClientThenResolvesFromTokenResponseClient() + throws Exception { + OAuth2AccessTokenResponseClient passwordTokenResponseClient = mock( + OAuth2AccessTokenResponseClient.class); + PasswordOAuth2AuthorizedClientProvider passwordAuthorizedClientProvider = new PasswordOAuth2AuthorizedClientProvider(); passwordAuthorizedClientProvider.setAccessTokenResponseClient(passwordTokenResponseClient); DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( this.clientRegistrationRepository, this.authorizedClientRepository); @@ -305,11 +309,8 @@ public class OAuth2AuthorizedClientArgumentResolverTests { this.argumentResolver = new OAuth2AuthorizedClientArgumentResolver(authorizedClientManager); - OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse - .withToken("access-token-1234") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(3600) - .build(); + OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("access-token-1234") + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(3600).build(); when(passwordTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); when(this.authorizedClientRepository.loadAuthorizedClient(anyString(), any(), any(HttpServletRequest.class))) @@ -319,16 +320,16 @@ public class OAuth2AuthorizedClientArgumentResolverTests { this.request.setParameter(OAuth2ParameterNames.USERNAME, "username"); this.request.setParameter(OAuth2ParameterNames.PASSWORD, "password"); - OAuth2AuthorizedClient authorizedClient = (OAuth2AuthorizedClient) this.argumentResolver.resolveArgument( - methodParameter, null, new ServletWebRequest(this.request, this.response), null); + OAuth2AuthorizedClient authorizedClient = (OAuth2AuthorizedClient) this.argumentResolver + .resolveArgument(methodParameter, null, new ServletWebRequest(this.request, this.response), null); assertThat(authorizedClient).isNotNull(); assertThat(authorizedClient.getClientRegistration()).isSameAs(this.registration3); assertThat(authorizedClient.getPrincipalName()).isEqualTo(this.principalName); assertThat(authorizedClient.getAccessToken()).isSameAs(accessTokenResponse.getAccessToken()); - verify(this.authorizedClientRepository).saveAuthorizedClient( - eq(authorizedClient), eq(this.authentication), any(HttpServletRequest.class), any(HttpServletResponse.class)); + verify(this.authorizedClientRepository).saveAuthorizedClient(eq(authorizedClient), eq(this.authentication), + any(HttpServletRequest.class), any(HttpServletResponse.class)); } private MethodParameter getMethodParameter(String methodName, Class... paramTypes) { @@ -337,7 +338,9 @@ public class OAuth2AuthorizedClientArgumentResolverTests { } static class TestController { - void paramTypeAuthorizedClient(@RegisteredOAuth2AuthorizedClient("client1") OAuth2AuthorizedClient authorizedClient) { + + void paramTypeAuthorizedClient( + @RegisteredOAuth2AuthorizedClient("client1") OAuth2AuthorizedClient authorizedClient) { } void paramTypeAuthorizedClientWithoutAnnotation(OAuth2AuthorizedClient authorizedClient) { @@ -352,13 +355,17 @@ public class OAuth2AuthorizedClientArgumentResolverTests { void registrationIdEmpty(@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient) { } - void registrationIdInvalid(@RegisteredOAuth2AuthorizedClient("invalid") OAuth2AuthorizedClient authorizedClient) { + void registrationIdInvalid( + @RegisteredOAuth2AuthorizedClient("invalid") OAuth2AuthorizedClient authorizedClient) { } - void clientCredentialsClient(@RegisteredOAuth2AuthorizedClient("client2") OAuth2AuthorizedClient authorizedClient) { + void clientCredentialsClient( + @RegisteredOAuth2AuthorizedClient("client2") OAuth2AuthorizedClient authorizedClient) { } void passwordClient(@RegisteredOAuth2AuthorizedClient("client3") OAuth2AuthorizedClient authorizedClient) { } + } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/MockExchangeFunction.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/MockExchangeFunction.java index ac9f31b6ff..e581fca243 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/MockExchangeFunction.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/MockExchangeFunction.java @@ -32,6 +32,7 @@ import java.util.List; * @since 5.1 */ public class MockExchangeFunction implements ExchangeFunction { + private List requests = new ArrayList<>(); private ClientResponse response = mock(ClientResponse.class); @@ -55,4 +56,5 @@ public class MockExchangeFunction implements ExchangeFunction { return Mono.just(this.response); }); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunctionITests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunctionITests.java index f656d981a1..9bc02e8427 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunctionITests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunctionITests.java @@ -70,12 +70,19 @@ import static org.springframework.security.oauth2.client.web.reactive.function.c public class ServerOAuth2AuthorizedClientExchangeFilterFunctionITests { private ReactiveClientRegistrationRepository clientRegistrationRepository; + private ServerOAuth2AuthorizedClientRepository authorizedClientRepository; + private ServerOAuth2AuthorizedClientExchangeFilterFunction authorizedClientFilter; + private MockWebServer server; + private String serverUrl; + private WebClient webClient; + private Authentication authentication; + private MockServerWebExchange exchange; @Before @@ -86,23 +93,20 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionITests { this.authorizedClientRepository = spy(new ServerOAuth2AuthorizedClientRepository() { @Override - public Mono loadAuthorizedClient( - String clientRegistrationId, + public Mono loadAuthorizedClient(String clientRegistrationId, Authentication principal, ServerWebExchange exchange) { return delegate.loadAuthorizedClient(clientRegistrationId, principal, exchange); } @Override - public Mono saveAuthorizedClient( - OAuth2AuthorizedClient authorizedClient, - Authentication principal, ServerWebExchange exchange) { + public Mono saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal, + ServerWebExchange exchange) { return delegate.saveAuthorizedClient(authorizedClient, principal, exchange); } @Override - public Mono removeAuthorizedClient( - String clientRegistrationId, - Authentication principal, ServerWebExchange exchange) { + public Mono removeAuthorizedClient(String clientRegistrationId, Authentication principal, + ServerWebExchange exchange) { return delegate.removeAuthorizedClient(clientRegistrationId, principal, exchange); } @@ -112,9 +116,7 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionITests { this.server = new MockWebServer(); this.server.start(); this.serverUrl = this.server.url("/").toString(); - this.webClient = WebClient.builder() - .filter(this.authorizedClientFilter) - .build(); + this.webClient = WebClient.builder().filter(this.authorizedClientFilter).build(); this.authentication = new TestingAuthenticationToken("principal", "password"); this.exchange = MockServerWebExchange.builder(MockServerHttpRequest.get("/").build()).build(); } @@ -126,83 +128,67 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionITests { @Test public void requestWhenNotAuthorizedThenAuthorizeAndSendRequest() { - String accessTokenResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read write\"\n" + - "}\n"; - String clientResponse = "{\n" + - " \"attribute1\": \"value1\",\n" + - " \"attribute2\": \"value2\"\n" + - "}\n"; + String accessTokenResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"read write\"\n" + "}\n"; + String clientResponse = "{\n" + " \"attribute1\": \"value1\",\n" + " \"attribute2\": \"value2\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenResponse)); this.server.enqueue(jsonResponse(clientResponse)); - ClientRegistration clientRegistration = TestClientRegistrations.clientCredentials().tokenUri(this.serverUrl).build(); - when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration.getRegistrationId()))).thenReturn(Mono.just(clientRegistration)); + ClientRegistration clientRegistration = TestClientRegistrations.clientCredentials().tokenUri(this.serverUrl) + .build(); + when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(clientRegistration)); - this.webClient - .get() - .uri(this.serverUrl) - .attributes(clientRegistrationId(clientRegistration.getRegistrationId())) - .retrieve() - .bodyToMono(String.class) - .subscriberContext(Context.of(ServerWebExchange.class, this.exchange)) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(this.authentication)) - .block(); + this.webClient.get().uri(this.serverUrl) + .attributes(clientRegistrationId(clientRegistration.getRegistrationId())).retrieve() + .bodyToMono(String.class).subscriberContext(Context.of(ServerWebExchange.class, this.exchange)) + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(this.authentication)).block(); assertThat(this.server.getRequestCount()).isEqualTo(2); - ArgumentCaptor authorizedClientCaptor = ArgumentCaptor.forClass(OAuth2AuthorizedClient.class); - verify(this.authorizedClientRepository).saveAuthorizedClient( - authorizedClientCaptor.capture(), eq(this.authentication), eq(this.exchange)); + ArgumentCaptor authorizedClientCaptor = ArgumentCaptor + .forClass(OAuth2AuthorizedClient.class); + verify(this.authorizedClientRepository).saveAuthorizedClient(authorizedClientCaptor.capture(), + eq(this.authentication), eq(this.exchange)); assertThat(authorizedClientCaptor.getValue().getClientRegistration()).isSameAs(clientRegistration); } @Test public void requestWhenAuthorizedButExpiredThenRefreshAndSendRequest() { - String accessTokenResponse = "{\n" + - " \"access_token\": \"refreshed-access-token\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; - String clientResponse = "{\n" + - " \"attribute1\": \"value1\",\n" + - " \"attribute2\": \"value2\"\n" + - "}\n"; + String accessTokenResponse = "{\n" + " \"access_token\": \"refreshed-access-token\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; + String clientResponse = "{\n" + " \"attribute1\": \"value1\",\n" + " \"attribute2\": \"value2\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenResponse)); this.server.enqueue(jsonResponse(clientResponse)); - ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().tokenUri(this.serverUrl).build(); - when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration.getRegistrationId()))).thenReturn(Mono.just(clientRegistration)); + ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().tokenUri(this.serverUrl) + .build(); + when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(clientRegistration)); Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant expiresAt = issuedAt.plus(Duration.ofHours(1)); OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "expired-access-token", issuedAt, expiresAt, new HashSet<>(Arrays.asList("read", "write"))); OAuth2RefreshToken refreshToken = TestOAuth2RefreshTokens.refreshToken(); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - clientRegistration, this.authentication.getName(), accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(clientRegistration, + this.authentication.getName(), accessToken, refreshToken); doReturn(Mono.just(authorizedClient)).when(this.authorizedClientRepository).loadAuthorizedClient( eq(clientRegistration.getRegistrationId()), eq(this.authentication), eq(this.exchange)); - this.webClient - .get() - .uri(this.serverUrl) - .attributes(clientRegistrationId(clientRegistration.getRegistrationId())) - .retrieve() - .bodyToMono(String.class) - .subscriberContext(Context.of(ServerWebExchange.class, this.exchange)) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(this.authentication)) - .block(); + this.webClient.get().uri(this.serverUrl) + .attributes(clientRegistrationId(clientRegistration.getRegistrationId())).retrieve() + .bodyToMono(String.class).subscriberContext(Context.of(ServerWebExchange.class, this.exchange)) + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(this.authentication)).block(); assertThat(this.server.getRequestCount()).isEqualTo(2); - ArgumentCaptor authorizedClientCaptor = ArgumentCaptor.forClass(OAuth2AuthorizedClient.class); - verify(this.authorizedClientRepository).saveAuthorizedClient( - authorizedClientCaptor.capture(), eq(this.authentication), eq(this.exchange)); + ArgumentCaptor authorizedClientCaptor = ArgumentCaptor + .forClass(OAuth2AuthorizedClient.class); + verify(this.authorizedClientRepository).saveAuthorizedClient(authorizedClientCaptor.capture(), + eq(this.authentication), eq(this.exchange)); OAuth2AuthorizedClient refreshedAuthorizedClient = authorizedClientCaptor.getValue(); assertThat(refreshedAuthorizedClient.getClientRegistration()).isSameAs(clientRegistration); assertThat(refreshedAuthorizedClient.getAccessToken().getTokenValue()).isEqualTo("refreshed-access-token"); @@ -210,124 +196,104 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionITests { @Test public void requestMultipleWhenNoneAuthorizedThenAuthorizeAndSendRequest() { - String accessTokenResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read write\"\n" + - "}\n"; - String clientResponse = "{\n" + - " \"attribute1\": \"value1\",\n" + - " \"attribute2\": \"value2\"\n" + - "}\n"; + String accessTokenResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"read write\"\n" + "}\n"; + String clientResponse = "{\n" + " \"attribute1\": \"value1\",\n" + " \"attribute2\": \"value2\"\n" + "}\n"; // Client 1 this.server.enqueue(jsonResponse(accessTokenResponse)); this.server.enqueue(jsonResponse(clientResponse)); - ClientRegistration clientRegistration1 = TestClientRegistrations.clientCredentials() - .registrationId("client-1").tokenUri(this.serverUrl).build(); - when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration1.getRegistrationId()))).thenReturn(Mono.just(clientRegistration1)); + ClientRegistration clientRegistration1 = TestClientRegistrations.clientCredentials().registrationId("client-1") + .tokenUri(this.serverUrl).build(); + when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration1.getRegistrationId()))) + .thenReturn(Mono.just(clientRegistration1)); // Client 2 this.server.enqueue(jsonResponse(accessTokenResponse)); this.server.enqueue(jsonResponse(clientResponse)); - ClientRegistration clientRegistration2 = TestClientRegistrations.clientCredentials() - .registrationId("client-2").tokenUri(this.serverUrl).build(); - when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration2.getRegistrationId()))).thenReturn(Mono.just(clientRegistration2)); + ClientRegistration clientRegistration2 = TestClientRegistrations.clientCredentials().registrationId("client-2") + .tokenUri(this.serverUrl).build(); + when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration2.getRegistrationId()))) + .thenReturn(Mono.just(clientRegistration2)); - this.webClient - .get() - .uri(this.serverUrl) - .attributes(clientRegistrationId(clientRegistration1.getRegistrationId())) - .retrieve() + this.webClient.get().uri(this.serverUrl) + .attributes(clientRegistrationId(clientRegistration1.getRegistrationId())).retrieve() .bodyToMono(String.class) - .flatMap(response -> this.webClient - .get() - .uri(this.serverUrl) - .attributes(clientRegistrationId(clientRegistration2.getRegistrationId())) - .retrieve() + .flatMap(response -> this.webClient.get().uri(this.serverUrl) + .attributes(clientRegistrationId(clientRegistration2.getRegistrationId())).retrieve() .bodyToMono(String.class)) .subscriberContext(Context.of(ServerWebExchange.class, this.exchange)) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(this.authentication)) - .block(); + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(this.authentication)).block(); assertThat(this.server.getRequestCount()).isEqualTo(4); - ArgumentCaptor authorizedClientCaptor = ArgumentCaptor.forClass(OAuth2AuthorizedClient.class); - verify(this.authorizedClientRepository, times(2)).saveAuthorizedClient( - authorizedClientCaptor.capture(), eq(this.authentication), eq(this.exchange)); + ArgumentCaptor authorizedClientCaptor = ArgumentCaptor + .forClass(OAuth2AuthorizedClient.class); + verify(this.authorizedClientRepository, times(2)).saveAuthorizedClient(authorizedClientCaptor.capture(), + eq(this.authentication), eq(this.exchange)); assertThat(authorizedClientCaptor.getAllValues().get(0).getClientRegistration()).isSameAs(clientRegistration1); assertThat(authorizedClientCaptor.getAllValues().get(1).getClientRegistration()).isSameAs(clientRegistration2); } /** - * When a non-expired {@link OAuth2AuthorizedClient} exists - * but the resource server returns 401, - * then remove the {@link OAuth2AuthorizedClient} from the repository. + * When a non-expired {@link OAuth2AuthorizedClient} exists but the resource server + * returns 401, then remove the {@link OAuth2AuthorizedClient} from the repository. */ @Test public void requestWhenUnauthorizedThenReAuthorize() { - String accessTokenResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read write\"\n" + - "}\n"; - String clientResponse = "{\n" + - " \"attribute1\": \"value1\",\n" + - " \"attribute2\": \"value2\"\n" + - "}\n"; + String accessTokenResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"read write\"\n" + "}\n"; + String clientResponse = "{\n" + " \"attribute1\": \"value1\",\n" + " \"attribute2\": \"value2\"\n" + "}\n"; this.server.enqueue(new MockResponse().setResponseCode(HttpStatus.UNAUTHORIZED.value())); this.server.enqueue(jsonResponse(accessTokenResponse)); this.server.enqueue(jsonResponse(clientResponse)); - ClientRegistration clientRegistration = TestClientRegistrations.clientCredentials().tokenUri(this.serverUrl).build(); - when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration.getRegistrationId()))).thenReturn(Mono.just(clientRegistration)); + ClientRegistration clientRegistration = TestClientRegistrations.clientCredentials().tokenUri(this.serverUrl) + .build(); + when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration.getRegistrationId()))) + .thenReturn(Mono.just(clientRegistration)); OAuth2AccessToken accessToken = TestOAuth2AccessTokens.scopes("read", "write"); OAuth2RefreshToken refreshToken = TestOAuth2RefreshTokens.refreshToken(); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - clientRegistration, this.authentication.getName(), accessToken, refreshToken); - doReturn(Mono.just(authorizedClient)) - .doReturn(Mono.empty()) - .when(this.authorizedClientRepository).loadAuthorizedClient( - eq(clientRegistration.getRegistrationId()), eq(this.authentication), eq(this.exchange)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(clientRegistration, + this.authentication.getName(), accessToken, refreshToken); + doReturn(Mono.just(authorizedClient)).doReturn(Mono.empty()).when(this.authorizedClientRepository) + .loadAuthorizedClient(eq(clientRegistration.getRegistrationId()), eq(this.authentication), + eq(this.exchange)); - Mono requestMono = this.webClient - .get() - .uri(this.serverUrl) - .attributes(clientRegistrationId(clientRegistration.getRegistrationId())) - .retrieve() - .bodyToMono(String.class) - .subscriberContext(Context.of(ServerWebExchange.class, this.exchange)) + Mono requestMono = this.webClient.get().uri(this.serverUrl) + .attributes(clientRegistrationId(clientRegistration.getRegistrationId())).retrieve() + .bodyToMono(String.class).subscriberContext(Context.of(ServerWebExchange.class, this.exchange)) .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(this.authentication)); // first try should fail, and remove the cached authorized client - assertThatCode(requestMono::block) - .isInstanceOfSatisfying(WebClientResponseException.class, e -> assertThat(e.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED)); + assertThatCode(requestMono::block).isInstanceOfSatisfying(WebClientResponseException.class, + e -> assertThat(e.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED)); assertThat(this.server.getRequestCount()).isEqualTo(1); verify(this.authorizedClientRepository, never()).saveAuthorizedClient(any(), any(), any()); - verify(this.authorizedClientRepository).removeAuthorizedClient( - eq(clientRegistration.getRegistrationId()), eq(this.authentication), eq(this.exchange)); + verify(this.authorizedClientRepository).removeAuthorizedClient(eq(clientRegistration.getRegistrationId()), + eq(this.authentication), eq(this.exchange)); // second try should retrieve the authorized client and succeed requestMono.block(); assertThat(this.server.getRequestCount()).isEqualTo(3); - ArgumentCaptor authorizedClientCaptor = ArgumentCaptor.forClass(OAuth2AuthorizedClient.class); - verify(this.authorizedClientRepository).saveAuthorizedClient( - authorizedClientCaptor.capture(), eq(this.authentication), eq(this.exchange)); + ArgumentCaptor authorizedClientCaptor = ArgumentCaptor + .forClass(OAuth2AuthorizedClient.class); + verify(this.authorizedClientRepository).saveAuthorizedClient(authorizedClientCaptor.capture(), + eq(this.authentication), eq(this.exchange)); assertThat(authorizedClientCaptor.getValue().getClientRegistration()).isSameAs(clientRegistration); } private MockResponse jsonResponse(String json) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json); + return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunctionTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunctionTests.java index 15a603953a..50612fc76a 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunctionTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunctionTests.java @@ -115,6 +115,7 @@ import static org.springframework.security.oauth2.client.web.reactive.function.c */ @RunWith(MockitoJUnitRunner.class) public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { + @Mock private ServerOAuth2AuthorizedClientRepository authorizedClientRepository; @@ -151,25 +152,21 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { private MockExchangeFunction exchange = new MockExchangeFunction(); - private ClientRegistration registration = TestClientRegistrations.clientRegistration() - .build(); + private ClientRegistration registration = TestClientRegistrations.clientRegistration().build(); - private OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "token-0", - Instant.now(), - Instant.now().plus(Duration.ofDays(1))); + private OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token-0", + Instant.now(), Instant.now().plus(Duration.ofDays(1))); private DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager; @Before public void setup() { - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = - ReactiveOAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .refreshToken(configurer -> configurer.accessTokenResponseClient(this.refreshTokenTokenResponseClient)) - .clientCredentials(configurer -> configurer.accessTokenResponseClient(this.clientCredentialsTokenResponseClient)) - .password(configurer -> configurer.accessTokenResponseClient(this.passwordTokenResponseClient)) - .build(); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder + .builder().authorizationCode() + .refreshToken(configurer -> configurer.accessTokenResponseClient(this.refreshTokenTokenResponseClient)) + .clientCredentials( + configurer -> configurer.accessTokenResponseClient(this.clientCredentialsTokenResponseClient)) + .password(configurer -> configurer.accessTokenResponseClient(this.passwordTokenResponseClient)).build(); this.authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager( this.clientRegistrationRepository, this.authorizedClientRepository); this.authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); @@ -193,24 +190,24 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void setClientCredentialsTokenResponseClientWhenNotDefaultAuthorizedClientManagerThenThrowIllegalStateException() { - assertThatThrownBy(() -> this.function.setClientCredentialsTokenResponseClient(new WebClientReactiveClientCredentialsTokenResponseClient())) - .isInstanceOf(IllegalStateException.class) - .hasMessage("The client cannot be set when the constructor used is \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)\". " + - "Instead, use the constructor \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\"."); + assertThatThrownBy(() -> this.function + .setClientCredentialsTokenResponseClient(new WebClientReactiveClientCredentialsTokenResponseClient())) + .isInstanceOf(IllegalStateException.class).hasMessage( + "The client cannot be set when the constructor used is \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)\". " + + "Instead, use the constructor \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\"."); } @Test public void setAccessTokenExpiresSkewWhenNotDefaultAuthorizedClientManagerThenThrowIllegalStateException() { assertThatThrownBy(() -> this.function.setAccessTokenExpiresSkew(Duration.ofSeconds(30))) - .isInstanceOf(IllegalStateException.class) - .hasMessage("The accessTokenExpiresSkew cannot be set when the constructor used is \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)\". " + - "Instead, use the constructor \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\"."); + .isInstanceOf(IllegalStateException.class).hasMessage( + "The accessTokenExpiresSkew cannot be set when the constructor used is \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ReactiveOAuth2AuthorizedClientManager)\". " + + "Instead, use the constructor \"ServerOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\"."); } @Test public void filterWhenAuthorizedClientNullThenAuthorizationHeaderNull() { - ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .build(); + ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")).build(); this.function.filter(request, this.exchange).block(); @@ -219,31 +216,26 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenAuthorizedClientThenAuthorizationHeader() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); - this.function.filter(request, this.exchange) - .subscriberContext(serverWebExchange()) - .block(); + this.function.filter(request, this.exchange).subscriberContext(serverWebExchange()).block(); - assertThat(this.exchange.getRequest().headers().getFirst(HttpHeaders.AUTHORIZATION)).isEqualTo("Bearer " + this.accessToken.getTokenValue()); + assertThat(this.exchange.getRequest().headers().getFirst(HttpHeaders.AUTHORIZATION)) + .isEqualTo("Bearer " + this.accessToken.getTokenValue()); } @Test public void filterWhenExistingAuthorizationThenSingleAuthorizationHeader() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .header(HttpHeaders.AUTHORIZATION, "Existing") - .attributes(oauth2AuthorizedClient(authorizedClient)) + .header(HttpHeaders.AUTHORIZATION, "Existing").attributes(oauth2AuthorizedClient(authorizedClient)) .build(); - this.function.filter(request, this.exchange) - .subscriberContext(serverWebExchange()) - .block(); + this.function.filter(request, this.exchange).subscriberContext(serverWebExchange()).block(); HttpHeaders headers = this.exchange.getRequest().headers(); assertThat(headers.get(HttpHeaders.AUTHORIZATION)).containsOnly("Bearer " + this.accessToken.getTokenValue()); @@ -252,31 +244,26 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenClientCredentialsTokenExpiredThenGetNewToken() { OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("new-token") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(360) - .build(); - when(this.clientCredentialsTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(360).build(); + when(this.clientCredentialsTokenResponseClient.getTokenResponse(any())) + .thenReturn(Mono.just(accessTokenResponse)); ClientRegistration registration = TestClientRegistrations.clientCredentials().build(); Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant accessTokenExpiresAt = issuedAt.plus(Duration.ofHours(1)); OAuth2AccessToken accessToken = new OAuth2AccessToken(this.accessToken.getTokenType(), - this.accessToken.getTokenValue(), - issuedAt, - accessTokenExpiresAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(registration, - "principalName", accessToken, null); + this.accessToken.getTokenValue(), issuedAt, accessTokenExpiresAt); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(registration, "principalName", accessToken, + null); TestingAuthenticationToken authentication = new TestingAuthenticationToken("test", "this"); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); this.function.filter(request, this.exchange) .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) - .subscriberContext(serverWebExchange()) - .block(); + .subscriberContext(serverWebExchange()).block(); verify(this.clientCredentialsTokenResponseClient).getTokenResponse(any()); verify(this.authorizedClientRepository).saveAuthorizedClient(any(), eq(authentication), any()); @@ -295,16 +282,14 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { TestingAuthenticationToken authentication = new TestingAuthenticationToken("test", "this"); ClientRegistration registration = TestClientRegistrations.clientCredentials().build(); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(registration, - "principalName", this.accessToken, null); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(registration, "principalName", + this.accessToken, null); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); this.function.filter(request, this.exchange) .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) - .subscriberContext(serverWebExchange()) - .block(); + .subscriberContext(serverWebExchange()).block(); verify(this.clientCredentialsTokenResponseClient, never()).getTokenResponse(any()); @@ -320,34 +305,28 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenRefreshRequiredThenRefresh() { OAuth2AccessTokenResponse response = OAuth2AccessTokenResponse.withToken("token-1") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(3600) - .refreshToken("refresh-1") - .build(); + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(3600).refreshToken("refresh-1").build(); when(this.refreshTokenTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(response)); Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant accessTokenExpiresAt = issuedAt.plus(Duration.ofHours(1)); - this.accessToken = new OAuth2AccessToken(this.accessToken.getTokenType(), - this.accessToken.getTokenValue(), - issuedAt, - accessTokenExpiresAt); + this.accessToken = new OAuth2AccessToken(this.accessToken.getTokenType(), this.accessToken.getTokenValue(), + issuedAt, accessTokenExpiresAt); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", issuedAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); TestingAuthenticationToken authentication = new TestingAuthenticationToken("test", "this"); this.function.filter(request, this.exchange) .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) - .subscriberContext(serverWebExchange()) - .block(); + .subscriberContext(serverWebExchange()).block(); verify(this.refreshTokenTokenResponseClient).getTokenResponse(any()); - verify(this.authorizedClientRepository).saveAuthorizedClient(this.authorizedClientCaptor.capture(), eq(authentication), any()); + verify(this.authorizedClientRepository).saveAuthorizedClient(this.authorizedClientCaptor.capture(), + eq(authentication), any()); OAuth2AuthorizedClient newAuthorizedClient = authorizedClientCaptor.getValue(); assertThat(newAuthorizedClient.getAccessToken()).isEqualTo(response.getAccessToken()); @@ -366,29 +345,21 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenRefreshRequiredAndEmptyReactiveSecurityContextThenSaved() { OAuth2AccessTokenResponse response = OAuth2AccessTokenResponse.withToken("token-1") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(3600) - .refreshToken("refresh-1") - .build(); + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(3600).refreshToken("refresh-1").build(); when(this.refreshTokenTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(response)); Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant accessTokenExpiresAt = issuedAt.plus(Duration.ofHours(1)); - this.accessToken = new OAuth2AccessToken(this.accessToken.getTokenType(), - this.accessToken.getTokenValue(), - issuedAt, - accessTokenExpiresAt); + this.accessToken = new OAuth2AccessToken(this.accessToken.getTokenType(), this.accessToken.getTokenValue(), + issuedAt, accessTokenExpiresAt); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", issuedAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); - this.function.filter(request, this.exchange) - .subscriberContext(serverWebExchange()) - .block(); + this.function.filter(request, this.exchange).subscriberContext(serverWebExchange()).block(); verify(this.refreshTokenTokenResponseClient).getTokenResponse(any()); verify(this.authorizedClientRepository).saveAuthorizedClient(any(), any(), any()); @@ -405,15 +376,12 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenRefreshTokenNullThenShouldRefreshFalse() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); - this.function.filter(request, this.exchange) - .subscriberContext(serverWebExchange()) - .block(); + this.function.filter(request, this.exchange).subscriberContext(serverWebExchange()).block(); List requests = this.exchange.getRequests(); assertThat(requests).hasSize(1); @@ -428,15 +396,12 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenNotExpiredThenShouldRefreshFalse() { OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", this.accessToken.getIssuedAt()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); - this.function.filter(request, this.exchange) - .subscriberContext(serverWebExchange()) - .block(); + this.function.filter(request, this.exchange).subscriberContext(serverWebExchange()).block(); List requests = this.exchange.getRequests(); assertThat(requests).hasSize(1); @@ -456,34 +421,28 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { when(authorizationFailureHandler.onAuthorizationFailure(any(), any(), any())).thenReturn(publisherProbe.mono()); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", this.accessToken.getIssuedAt()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); when(exchange.getResponse().rawStatusCode()).thenReturn(HttpStatus.UNAUTHORIZED.value()); - this.function.filter(request, this.exchange) - .subscriberContext(serverWebExchange()) - .block(); + this.function.filter(request, this.exchange).subscriberContext(serverWebExchange()).block(); assertThat(publisherProbe.wasSubscribed()).isTrue(); - verify(authorizationFailureHandler).onAuthorizationFailure( - authorizationExceptionCaptor.capture(), - authenticationCaptor.capture(), - attributesCaptor.capture()); + verify(authorizationFailureHandler).onAuthorizationFailure(authorizationExceptionCaptor.capture(), + authenticationCaptor.capture(), attributesCaptor.capture()); - assertThat(authorizationExceptionCaptor.getValue()) - .isInstanceOfSatisfying(ClientAuthorizationException.class, e -> { + assertThat(authorizationExceptionCaptor.getValue()).isInstanceOfSatisfying(ClientAuthorizationException.class, + e -> { assertThat(e.getClientRegistrationId()).isEqualTo(registration.getRegistrationId()); assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token"); assertThat(e).hasNoCause(); assertThat(e).hasMessageContaining("[invalid_token]"); }); - assertThat(authenticationCaptor.getValue()) - .isInstanceOf(AnonymousAuthenticationToken.class); + assertThat(authenticationCaptor.getValue()).isInstanceOf(AnonymousAuthenticationToken.class); assertThat(attributesCaptor.getValue()) .containsExactly(entry(ServerWebExchange.class.getName(), this.serverWebExchange)); } @@ -496,42 +455,32 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { when(authorizationFailureHandler.onAuthorizationFailure(any(), any(), any())).thenReturn(publisherProbe.mono()); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", this.accessToken.getIssuedAt()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); - WebClientResponseException exception = WebClientResponseException.create( - HttpStatus.UNAUTHORIZED.value(), - HttpStatus.UNAUTHORIZED.getReasonPhrase(), - HttpHeaders.EMPTY, - new byte[0], - StandardCharsets.UTF_8); + WebClientResponseException exception = WebClientResponseException.create(HttpStatus.UNAUTHORIZED.value(), + HttpStatus.UNAUTHORIZED.getReasonPhrase(), HttpHeaders.EMPTY, new byte[0], StandardCharsets.UTF_8); ExchangeFunction throwingExchangeFunction = r -> Mono.error(exception); assertThatCode(() -> this.function.filter(request, throwingExchangeFunction) - .subscriberContext(serverWebExchange()) - .block()) - .isEqualTo(exception); + .subscriberContext(serverWebExchange()).block()).isEqualTo(exception); assertThat(publisherProbe.wasSubscribed()).isTrue(); - verify(authorizationFailureHandler).onAuthorizationFailure( - authorizationExceptionCaptor.capture(), - authenticationCaptor.capture(), - attributesCaptor.capture()); + verify(authorizationFailureHandler).onAuthorizationFailure(authorizationExceptionCaptor.capture(), + authenticationCaptor.capture(), attributesCaptor.capture()); - assertThat(authorizationExceptionCaptor.getValue()) - .isInstanceOfSatisfying(ClientAuthorizationException.class, e -> { + assertThat(authorizationExceptionCaptor.getValue()).isInstanceOfSatisfying(ClientAuthorizationException.class, + e -> { assertThat(e.getClientRegistrationId()).isEqualTo(registration.getRegistrationId()); assertThat(e.getError().getErrorCode()).isEqualTo("invalid_token"); assertThat(e).hasCause(exception); assertThat(e).hasMessageContaining("[invalid_token]"); }); - assertThat(authenticationCaptor.getValue()) - .isInstanceOf(AnonymousAuthenticationToken.class); + assertThat(authenticationCaptor.getValue()).isInstanceOf(AnonymousAuthenticationToken.class); assertThat(attributesCaptor.getValue()) .containsExactly(entry(ServerWebExchange.class.getName(), this.serverWebExchange)); } @@ -544,34 +493,28 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { when(authorizationFailureHandler.onAuthorizationFailure(any(), any(), any())).thenReturn(publisherProbe.mono()); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", this.accessToken.getIssuedAt()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); when(exchange.getResponse().rawStatusCode()).thenReturn(HttpStatus.FORBIDDEN.value()); - this.function.filter(request, this.exchange) - .subscriberContext(serverWebExchange()) - .block(); + this.function.filter(request, this.exchange).subscriberContext(serverWebExchange()).block(); assertThat(publisherProbe.wasSubscribed()).isTrue(); - verify(authorizationFailureHandler).onAuthorizationFailure( - authorizationExceptionCaptor.capture(), - authenticationCaptor.capture(), - attributesCaptor.capture()); + verify(authorizationFailureHandler).onAuthorizationFailure(authorizationExceptionCaptor.capture(), + authenticationCaptor.capture(), attributesCaptor.capture()); - assertThat(authorizationExceptionCaptor.getValue()) - .isInstanceOfSatisfying(ClientAuthorizationException.class, e -> { + assertThat(authorizationExceptionCaptor.getValue()).isInstanceOfSatisfying(ClientAuthorizationException.class, + e -> { assertThat(e.getClientRegistrationId()).isEqualTo(registration.getRegistrationId()); assertThat(e.getError().getErrorCode()).isEqualTo("insufficient_scope"); assertThat(e).hasNoCause(); assertThat(e).hasMessageContaining("[insufficient_scope]"); }); - assertThat(authenticationCaptor.getValue()) - .isInstanceOf(AnonymousAuthenticationToken.class); + assertThat(authenticationCaptor.getValue()).isInstanceOf(AnonymousAuthenticationToken.class); assertThat(attributesCaptor.getValue()) .containsExactly(entry(ServerWebExchange.class.getName(), this.serverWebExchange)); } @@ -584,42 +527,32 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { when(authorizationFailureHandler.onAuthorizationFailure(any(), any(), any())).thenReturn(publisherProbe.mono()); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", this.accessToken.getIssuedAt()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); - WebClientResponseException exception = WebClientResponseException.create( - HttpStatus.FORBIDDEN.value(), - HttpStatus.FORBIDDEN.getReasonPhrase(), - HttpHeaders.EMPTY, - new byte[0], - StandardCharsets.UTF_8); + WebClientResponseException exception = WebClientResponseException.create(HttpStatus.FORBIDDEN.value(), + HttpStatus.FORBIDDEN.getReasonPhrase(), HttpHeaders.EMPTY, new byte[0], StandardCharsets.UTF_8); ExchangeFunction throwingExchangeFunction = r -> Mono.error(exception); assertThatCode(() -> this.function.filter(request, throwingExchangeFunction) - .subscriberContext(serverWebExchange()) - .block()) - .isEqualTo(exception); + .subscriberContext(serverWebExchange()).block()).isEqualTo(exception); assertThat(publisherProbe.wasSubscribed()).isTrue(); - verify(authorizationFailureHandler).onAuthorizationFailure( - authorizationExceptionCaptor.capture(), - authenticationCaptor.capture(), - attributesCaptor.capture()); + verify(authorizationFailureHandler).onAuthorizationFailure(authorizationExceptionCaptor.capture(), + authenticationCaptor.capture(), attributesCaptor.capture()); - assertThat(authorizationExceptionCaptor.getValue()) - .isInstanceOfSatisfying(ClientAuthorizationException.class, e -> { + assertThat(authorizationExceptionCaptor.getValue()).isInstanceOfSatisfying(ClientAuthorizationException.class, + e -> { assertThat(e.getClientRegistrationId()).isEqualTo(registration.getRegistrationId()); assertThat(e.getError().getErrorCode()).isEqualTo("insufficient_scope"); assertThat(e).hasCause(exception); assertThat(e).hasMessageContaining("[insufficient_scope]"); }); - assertThat(authenticationCaptor.getValue()) - .isInstanceOf(AnonymousAuthenticationToken.class); + assertThat(authenticationCaptor.getValue()).isInstanceOf(AnonymousAuthenticationToken.class); assertThat(attributesCaptor.getValue()) .containsExactly(entry(ServerWebExchange.class.getName(), this.serverWebExchange)); } @@ -632,42 +565,37 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { when(authorizationFailureHandler.onAuthorizationFailure(any(), any(), any())).thenReturn(publisherProbe.mono()); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", this.accessToken.getIssuedAt()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); - String wwwAuthenticateHeader = "Bearer error=\"insufficient_scope\", " + - "error_description=\"The request requires higher privileges than provided by the access token.\", " + - "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\""; + String wwwAuthenticateHeader = "Bearer error=\"insufficient_scope\", " + + "error_description=\"The request requires higher privileges than provided by the access token.\", " + + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\""; ClientResponse.Headers headers = mock(ClientResponse.Headers.class); when(headers.header(eq(HttpHeaders.WWW_AUTHENTICATE))) .thenReturn(Collections.singletonList(wwwAuthenticateHeader)); when(this.exchange.getResponse().headers()).thenReturn(headers); - this.function.filter(request, this.exchange) - .subscriberContext(serverWebExchange()) - .block(); + this.function.filter(request, this.exchange).subscriberContext(serverWebExchange()).block(); assertThat(publisherProbe.wasSubscribed()).isTrue(); - verify(authorizationFailureHandler).onAuthorizationFailure( - authorizationExceptionCaptor.capture(), - authenticationCaptor.capture(), - attributesCaptor.capture()); + verify(authorizationFailureHandler).onAuthorizationFailure(authorizationExceptionCaptor.capture(), + authenticationCaptor.capture(), attributesCaptor.capture()); - assertThat(authorizationExceptionCaptor.getValue()) - .isInstanceOfSatisfying(ClientAuthorizationException.class, e -> { + assertThat(authorizationExceptionCaptor.getValue()).isInstanceOfSatisfying(ClientAuthorizationException.class, + e -> { assertThat(e.getClientRegistrationId()).isEqualTo(registration.getRegistrationId()); assertThat(e.getError().getErrorCode()).isEqualTo(OAuth2ErrorCodes.INSUFFICIENT_SCOPE); - assertThat(e.getError().getDescription()).isEqualTo("The request requires higher privileges than provided by the access token."); + assertThat(e.getError().getDescription()) + .isEqualTo("The request requires higher privileges than provided by the access token."); assertThat(e.getError().getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1"); assertThat(e).hasNoCause(); assertThat(e).hasMessageContaining(OAuth2ErrorCodes.INSUFFICIENT_SCOPE); }); - assertThat(authenticationCaptor.getValue()) - .isInstanceOf(AnonymousAuthenticationToken.class); + assertThat(authenticationCaptor.getValue()).isInstanceOf(AnonymousAuthenticationToken.class); assertThat(attributesCaptor.getValue()) .containsExactly(entry(ServerWebExchange.class.getName(), this.serverWebExchange)); } @@ -680,32 +608,26 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { when(authorizationFailureHandler.onAuthorizationFailure(any(), any(), any())).thenReturn(publisherProbe.mono()); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", this.accessToken.getIssuedAt()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); - OAuth2AuthorizationException exception = new OAuth2AuthorizationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_TOKEN, null, null)); + OAuth2AuthorizationException exception = new OAuth2AuthorizationException( + new OAuth2Error(OAuth2ErrorCodes.INVALID_TOKEN, null, null)); ExchangeFunction throwingExchangeFunction = r -> Mono.error(exception); assertThatCode(() -> this.function.filter(request, throwingExchangeFunction) - .subscriberContext(serverWebExchange()) - .block()) - .isEqualTo(exception); + .subscriberContext(serverWebExchange()).block()).isEqualTo(exception); assertThat(publisherProbe.wasSubscribed()).isTrue(); - verify(authorizationFailureHandler).onAuthorizationFailure( - authorizationExceptionCaptor.capture(), - authenticationCaptor.capture(), - attributesCaptor.capture()); + verify(authorizationFailureHandler).onAuthorizationFailure(authorizationExceptionCaptor.capture(), + authenticationCaptor.capture(), attributesCaptor.capture()); - assertThat(authorizationExceptionCaptor.getValue()) - .isSameAs(exception); - assertThat(authenticationCaptor.getValue()) - .isInstanceOf(AnonymousAuthenticationToken.class); + assertThat(authorizationExceptionCaptor.getValue()).isSameAs(exception); + assertThat(authenticationCaptor.getValue()).isInstanceOf(AnonymousAuthenticationToken.class); assertThat(attributesCaptor.getValue()) .containsExactly(entry(ServerWebExchange.class.getName(), this.serverWebExchange)); } @@ -715,17 +637,14 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { function.setAuthorizationFailureHandler(authorizationFailureHandler); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", this.accessToken.getIssuedAt()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).build(); when(exchange.getResponse().rawStatusCode()).thenReturn(HttpStatus.BAD_REQUEST.value()); - this.function.filter(request, this.exchange) - .subscriberContext(serverWebExchange()) - .block(); + this.function.filter(request, this.exchange).subscriberContext(serverWebExchange()).block(); verify(authorizationFailureHandler, never()).onAuthorizationFailure(any(), any(), any()); } @@ -736,46 +655,39 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { ClientRegistration registration = TestClientRegistrations.password().build(); OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("new-token") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(360) - .build(); + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(360).build(); when(this.passwordTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); - when(this.clientRegistrationRepository.findByRegistrationId(eq(registration.getRegistrationId()))).thenReturn(Mono.just(registration)); - when(this.authorizedClientRepository.loadAuthorizedClient(eq(registration.getRegistrationId()), eq(authentication), any())).thenReturn(Mono.empty()); + when(this.clientRegistrationRepository.findByRegistrationId(eq(registration.getRegistrationId()))) + .thenReturn(Mono.just(registration)); + when(this.authorizedClientRepository.loadAuthorizedClient(eq(registration.getRegistrationId()), + eq(authentication), any())).thenReturn(Mono.empty()); // Set custom contextAttributesMapper capable of mapping the form parameters this.authorizedClientManager.setContextAttributesMapper(authorizeRequest -> { ServerWebExchange serverWebExchange = authorizeRequest.getAttribute(ServerWebExchange.class.getName()); - return Mono.just(serverWebExchange) - .flatMap(ServerWebExchange::getFormData) - .map(formData -> { - Map contextAttributes = new HashMap<>(); - String username = formData.getFirst(OAuth2ParameterNames.USERNAME); - String password = formData.getFirst(OAuth2ParameterNames.PASSWORD); - if (StringUtils.hasText(username) && StringUtils.hasText(password)) { - contextAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username); - contextAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password); - } - return contextAttributes; - }); + return Mono.just(serverWebExchange).flatMap(ServerWebExchange::getFormData).map(formData -> { + Map contextAttributes = new HashMap<>(); + String username = formData.getFirst(OAuth2ParameterNames.USERNAME); + String password = formData.getFirst(OAuth2ParameterNames.PASSWORD); + if (StringUtils.hasText(username) && StringUtils.hasText(password)) { + contextAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username); + contextAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password); + } + return contextAttributes; + }); }); - this.serverWebExchange = MockServerWebExchange.builder( - MockServerHttpRequest - .post("/") - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .body("username=username&password=password")) + this.serverWebExchange = MockServerWebExchange.builder(MockServerHttpRequest.post("/") + .contentType(MediaType.APPLICATION_FORM_URLENCODED).body("username=username&password=password")) .build(); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(clientRegistrationId(registration.getRegistrationId())) - .build(); + .attributes(clientRegistrationId(registration.getRegistrationId())).build(); this.function.filter(request, this.exchange) .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) - .subscriberContext(serverWebExchange()) - .block(); + .subscriberContext(serverWebExchange()).block(); verify(this.passwordTokenResponseClient).getTokenResponse(any()); verify(this.authorizedClientRepository).saveAuthorizedClient(any(), eq(authentication), any()); @@ -792,16 +704,14 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenClientRegistrationIdThenAuthorizedClientResolved() { OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", this.accessToken.getIssuedAt()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); - when(this.authorizedClientRepository.loadAuthorizedClient(any(), any(), any())).thenReturn(Mono.just(authorizedClient)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); + when(this.authorizedClientRepository.loadAuthorizedClient(any(), any(), any())) + .thenReturn(Mono.just(authorizedClient)); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(clientRegistrationId(this.registration.getRegistrationId())) - .build(); + .attributes(clientRegistrationId(this.registration.getRegistrationId())).build(); - this.function.filter(request, this.exchange) - .subscriberContext(serverWebExchange()) - .block(); + this.function.filter(request, this.exchange).subscriberContext(serverWebExchange()).block(); List requests = this.exchange.getRequests(); assertThat(requests).hasSize(1); @@ -817,15 +727,13 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { public void filterWhenDefaultClientRegistrationIdThenAuthorizedClientResolved() { this.function.setDefaultClientRegistrationId(this.registration.getRegistrationId()); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", this.accessToken.getIssuedAt()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); - when(this.authorizedClientRepository.loadAuthorizedClient(any(), any(), any())).thenReturn(Mono.just(authorizedClient)); - ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .build(); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); + when(this.authorizedClientRepository.loadAuthorizedClient(any(), any(), any())) + .thenReturn(Mono.just(authorizedClient)); + ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")).build(); - this.function.filter(request, this.exchange) - .subscriberContext(serverWebExchange()) - .block(); + this.function.filter(request, this.exchange).subscriberContext(serverWebExchange()).block(); List requests = this.exchange.getRequests(); assertThat(requests).hasSize(1); @@ -842,20 +750,19 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { this.function.setDefaultOAuth2AuthorizedClient(true); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", this.accessToken.getIssuedAt()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); - when(this.authorizedClientRepository.loadAuthorizedClient(any(), any(), any())).thenReturn(Mono.just(authorizedClient)); - ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .build(); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); + when(this.authorizedClientRepository.loadAuthorizedClient(any(), any(), any())) + .thenReturn(Mono.just(authorizedClient)); + ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")).build(); - OAuth2User user = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), Collections - .singletonMap("user", "rob"), "user"); - OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken(user, user.getAuthorities(), "client-id"); - this.function - .filter(request, this.exchange) + OAuth2User user = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), + Collections.singletonMap("user", "rob"), "user"); + OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken(user, user.getAuthorities(), + "client-id"); + this.function.filter(request, this.exchange) .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) - .subscriberContext(serverWebExchange()) - .block(); + .subscriberContext(serverWebExchange()).block(); List requests = this.exchange.getRequests(); assertThat(requests).hasSize(1); @@ -869,17 +776,15 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenDefaultOAuth2AuthorizedClientFalseThenEmpty() { - ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .build(); + ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")).build(); - OAuth2User user = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), Collections - .singletonMap("user", "rob"), "user"); - OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken(user, user.getAuthorities(), "client-id"); + OAuth2User user = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), + Collections.singletonMap("user", "rob"), "user"); + OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken(user, user.getAuthorities(), + "client-id"); - this.function - .filter(request, this.exchange) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) - .block(); + this.function.filter(request, this.exchange) + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)).block(); List requests = this.exchange.getRequests(); assertThat(requests).hasSize(1); @@ -890,41 +795,41 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenClientRegistrationIdAndServerWebExchangeFromContextThenServerWebExchangeFromContext() { OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", this.accessToken.getIssuedAt()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); - when(this.authorizedClientRepository.loadAuthorizedClient(any(), any(), any())).thenReturn(Mono.just(authorizedClient)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); + when(this.authorizedClientRepository.loadAuthorizedClient(any(), any(), any())) + .thenReturn(Mono.just(authorizedClient)); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(clientRegistrationId(this.registration.getRegistrationId())) - .build(); + .attributes(clientRegistrationId(this.registration.getRegistrationId())).build(); - this.function.filter(request, this.exchange) - .subscriberContext(serverWebExchange()) - .block(); + this.function.filter(request, this.exchange).subscriberContext(serverWebExchange()).block(); - verify(this.authorizedClientRepository).loadAuthorizedClient(eq(this.registration.getRegistrationId()), any(), eq(this.serverWebExchange)); + verify(this.authorizedClientRepository).loadAuthorizedClient(eq(this.registration.getRegistrationId()), any(), + eq(this.serverWebExchange)); } // gh-7544 @Test public void filterWhenClientCredentialsClientNotAuthorizedAndOutsideRequestContextThenGetNewToken() { - // Use UnAuthenticatedServerOAuth2AuthorizedClientRepository when operating outside of a request context - ServerOAuth2AuthorizedClientRepository unauthenticatedAuthorizedClientRepository = spy(new UnAuthenticatedServerOAuth2AuthorizedClientRepository()); - this.function = new ServerOAuth2AuthorizedClientExchangeFilterFunction( - this.clientRegistrationRepository, unauthenticatedAuthorizedClientRepository); + // Use UnAuthenticatedServerOAuth2AuthorizedClientRepository when operating + // outside of a request context + ServerOAuth2AuthorizedClientRepository unauthenticatedAuthorizedClientRepository = spy( + new UnAuthenticatedServerOAuth2AuthorizedClientRepository()); + this.function = new ServerOAuth2AuthorizedClientExchangeFilterFunction(this.clientRegistrationRepository, + unauthenticatedAuthorizedClientRepository); this.function.setClientCredentialsTokenResponseClient(this.clientCredentialsTokenResponseClient); OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("new-token") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(360) - .build(); - when(this.clientCredentialsTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(360).build(); + when(this.clientCredentialsTokenResponseClient.getTokenResponse(any())) + .thenReturn(Mono.just(accessTokenResponse)); ClientRegistration registration = TestClientRegistrations.clientCredentials().build(); - when(this.clientRegistrationRepository.findByRegistrationId(eq(registration.getRegistrationId()))).thenReturn(Mono.just(registration)); + when(this.clientRegistrationRepository.findByRegistrationId(eq(registration.getRegistrationId()))) + .thenReturn(Mono.just(registration)); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(clientRegistrationId(registration.getRegistrationId())) - .build(); + .attributes(clientRegistrationId(registration.getRegistrationId())).build(); this.function.filter(request, this.exchange).block(); @@ -978,4 +883,5 @@ public class ServerOAuth2AuthorizedClientExchangeFilterFunctionTests { request.body().insert(body, context).block(); return body.getBodyAsString().block(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunctionITests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunctionITests.java index 4fc245d31b..280323e56b 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunctionITests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunctionITests.java @@ -63,26 +63,36 @@ import static org.springframework.security.oauth2.client.web.reactive.function.c * @author Joe Grandja */ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionITests { + private ClientRegistrationRepository clientRegistrationRepository; + private OAuth2AuthorizedClientRepository authorizedClientRepository; + private ServletOAuth2AuthorizedClientExchangeFilterFunction authorizedClientFilter; + private MockWebServer server; + private String serverUrl; + private WebClient webClient; + private Authentication authentication; + private MockHttpServletRequest request; + private MockHttpServletResponse response; @BeforeClass public static void setUpBlockingChecks() { // IMPORTANT: - // Before enabling BlockHound, we need to white-list `java.lang.Class.getPackage()`. + // Before enabling BlockHound, we need to white-list + // `java.lang.Class.getPackage()`. // When the JVM loads `java.lang.Package.getSystemPackage()`, it attempts to - // `java.lang.Package.loadManifest()` which is blocking I/O and triggers BlockHound to error. - // NOTE: This is an issue with JDK 8. It's been tested on JDK 10 and works fine w/o this white-list. - BlockHound.builder() - .allowBlockingCallsInside(Class.class.getName(), "getPackage") - .install(); + // `java.lang.Package.loadManifest()` which is blocking I/O and triggers + // BlockHound to error. + // NOTE: This is an issue with JDK 8. It's been tested on JDK 10 and works fine + // w/o this white-list. + BlockHound.builder().allowBlockingCallsInside(Class.class.getName(), "getPackage").install(); } @Before @@ -92,17 +102,20 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionITests { new InMemoryOAuth2AuthorizedClientService(this.clientRegistrationRepository)); this.authorizedClientRepository = spy(new OAuth2AuthorizedClientRepository() { @Override - public T loadAuthorizedClient(String clientRegistrationId, Authentication principal, HttpServletRequest request) { + public T loadAuthorizedClient(String clientRegistrationId, + Authentication principal, HttpServletRequest request) { return delegate.loadAuthorizedClient(clientRegistrationId, principal, request); } @Override - public void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal, HttpServletRequest request, HttpServletResponse response) { + public void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal, + HttpServletRequest request, HttpServletResponse response) { delegate.saveAuthorizedClient(authorizedClient, principal, request, response); } @Override - public void removeAuthorizedClient(String clientRegistrationId, Authentication principal, HttpServletRequest request, HttpServletResponse response) { + public void removeAuthorizedClient(String clientRegistrationId, Authentication principal, + HttpServletRequest request, HttpServletResponse response) { delegate.removeAuthorizedClient(clientRegistrationId, principal, request, response); } }); @@ -111,9 +124,7 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionITests { this.server = new MockWebServer(); this.server.start(); this.serverUrl = this.server.url("/").toString(); - this.webClient = WebClient.builder() - .apply(this.authorizedClientFilter.oauth2Configuration()) - .build(); + this.webClient = WebClient.builder().apply(this.authorizedClientFilter.oauth2Configuration()).build(); this.authentication = new TestingAuthenticationToken("principal", "password"); SecurityContextHolder.getContext().setAuthentication(this.authentication); this.request = new MockHttpServletRequest(); @@ -130,80 +141,66 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionITests { @Test public void requestWhenNotAuthorizedThenAuthorizeAndSendRequest() { - String accessTokenResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read write\"\n" + - "}\n"; - String clientResponse = "{\n" + - " \"attribute1\": \"value1\",\n" + - " \"attribute2\": \"value2\"\n" + - "}\n"; + String accessTokenResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"read write\"\n" + "}\n"; + String clientResponse = "{\n" + " \"attribute1\": \"value1\",\n" + " \"attribute2\": \"value2\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenResponse)); this.server.enqueue(jsonResponse(clientResponse)); - ClientRegistration clientRegistration = TestClientRegistrations.clientCredentials().tokenUri(this.serverUrl).build(); - when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration.getRegistrationId()))).thenReturn(clientRegistration); + ClientRegistration clientRegistration = TestClientRegistrations.clientCredentials().tokenUri(this.serverUrl) + .build(); + when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration.getRegistrationId()))) + .thenReturn(clientRegistration); - this.webClient - .get() - .uri(this.serverUrl) - .attributes(clientRegistrationId(clientRegistration.getRegistrationId())) - .retrieve() - .bodyToMono(String.class) - .block(); + this.webClient.get().uri(this.serverUrl) + .attributes(clientRegistrationId(clientRegistration.getRegistrationId())).retrieve() + .bodyToMono(String.class).block(); assertThat(this.server.getRequestCount()).isEqualTo(2); - ArgumentCaptor authorizedClientCaptor = ArgumentCaptor.forClass(OAuth2AuthorizedClient.class); - verify(this.authorizedClientRepository).saveAuthorizedClient( - authorizedClientCaptor.capture(), eq(this.authentication), eq(this.request), eq(this.response)); + ArgumentCaptor authorizedClientCaptor = ArgumentCaptor + .forClass(OAuth2AuthorizedClient.class); + verify(this.authorizedClientRepository).saveAuthorizedClient(authorizedClientCaptor.capture(), + eq(this.authentication), eq(this.request), eq(this.response)); assertThat(authorizedClientCaptor.getValue().getClientRegistration()).isSameAs(clientRegistration); } @Test public void requestWhenAuthorizedButExpiredThenRefreshAndSendRequest() { - String accessTokenResponse = "{\n" + - " \"access_token\": \"refreshed-access-token\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\"\n" + - "}\n"; - String clientResponse = "{\n" + - " \"attribute1\": \"value1\",\n" + - " \"attribute2\": \"value2\"\n" + - "}\n"; + String accessTokenResponse = "{\n" + " \"access_token\": \"refreshed-access-token\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\"\n" + "}\n"; + String clientResponse = "{\n" + " \"attribute1\": \"value1\",\n" + " \"attribute2\": \"value2\"\n" + "}\n"; this.server.enqueue(jsonResponse(accessTokenResponse)); this.server.enqueue(jsonResponse(clientResponse)); - ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().tokenUri(this.serverUrl).build(); - when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration.getRegistrationId()))).thenReturn(clientRegistration); + ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().tokenUri(this.serverUrl) + .build(); + when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration.getRegistrationId()))) + .thenReturn(clientRegistration); Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant expiresAt = issuedAt.plus(Duration.ofHours(1)); OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "expired-access-token", issuedAt, expiresAt, new HashSet<>(Arrays.asList("read", "write"))); OAuth2RefreshToken refreshToken = TestOAuth2RefreshTokens.refreshToken(); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - clientRegistration, this.authentication.getName(), accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(clientRegistration, + this.authentication.getName(), accessToken, refreshToken); doReturn(authorizedClient).when(this.authorizedClientRepository).loadAuthorizedClient( eq(clientRegistration.getRegistrationId()), eq(this.authentication), eq(this.request)); - this.webClient - .get() - .uri(this.serverUrl) - .attributes(clientRegistrationId(clientRegistration.getRegistrationId())) - .retrieve() - .bodyToMono(String.class) - .block(); + this.webClient.get().uri(this.serverUrl) + .attributes(clientRegistrationId(clientRegistration.getRegistrationId())).retrieve() + .bodyToMono(String.class).block(); assertThat(this.server.getRequestCount()).isEqualTo(2); - ArgumentCaptor authorizedClientCaptor = ArgumentCaptor.forClass(OAuth2AuthorizedClient.class); - verify(this.authorizedClientRepository).saveAuthorizedClient( - authorizedClientCaptor.capture(), eq(this.authentication), eq(this.request), eq(this.response)); + ArgumentCaptor authorizedClientCaptor = ArgumentCaptor + .forClass(OAuth2AuthorizedClient.class); + verify(this.authorizedClientRepository).saveAuthorizedClient(authorizedClientCaptor.capture(), + eq(this.authentication), eq(this.request), eq(this.response)); OAuth2AuthorizedClient refreshedAuthorizedClient = authorizedClientCaptor.getValue(); assertThat(refreshedAuthorizedClient.getClientRegistration()).isSameAs(clientRegistration); assertThat(refreshedAuthorizedClient.getAccessToken().getTokenValue()).isEqualTo("refreshed-access-token"); @@ -211,53 +208,43 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionITests { @Test public void requestMultipleWhenNoneAuthorizedThenAuthorizeAndSendRequest() { - String accessTokenResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read write\"\n" + - "}\n"; - String clientResponse = "{\n" + - " \"attribute1\": \"value1\",\n" + - " \"attribute2\": \"value2\"\n" + - "}\n"; + String accessTokenResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"read write\"\n" + "}\n"; + String clientResponse = "{\n" + " \"attribute1\": \"value1\",\n" + " \"attribute2\": \"value2\"\n" + "}\n"; // Client 1 this.server.enqueue(jsonResponse(accessTokenResponse)); this.server.enqueue(jsonResponse(clientResponse)); - ClientRegistration clientRegistration1 = TestClientRegistrations.clientCredentials() - .registrationId("client-1").tokenUri(this.serverUrl).build(); - when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration1.getRegistrationId()))).thenReturn(clientRegistration1); + ClientRegistration clientRegistration1 = TestClientRegistrations.clientCredentials().registrationId("client-1") + .tokenUri(this.serverUrl).build(); + when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration1.getRegistrationId()))) + .thenReturn(clientRegistration1); // Client 2 this.server.enqueue(jsonResponse(accessTokenResponse)); this.server.enqueue(jsonResponse(clientResponse)); - ClientRegistration clientRegistration2 = TestClientRegistrations.clientCredentials() - .registrationId("client-2").tokenUri(this.serverUrl).build(); - when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration2.getRegistrationId()))).thenReturn(clientRegistration2); + ClientRegistration clientRegistration2 = TestClientRegistrations.clientCredentials().registrationId("client-2") + .tokenUri(this.serverUrl).build(); + when(this.clientRegistrationRepository.findByRegistrationId(eq(clientRegistration2.getRegistrationId()))) + .thenReturn(clientRegistration2); - this.webClient - .get() - .uri(this.serverUrl) - .attributes(clientRegistrationId(clientRegistration1.getRegistrationId())) - .retrieve() + this.webClient.get().uri(this.serverUrl) + .attributes(clientRegistrationId(clientRegistration1.getRegistrationId())).retrieve() .bodyToMono(String.class) - .flatMap(response -> this.webClient - .get() - .uri(this.serverUrl) - .attributes(clientRegistrationId(clientRegistration2.getRegistrationId())) - .retrieve() + .flatMap(response -> this.webClient.get().uri(this.serverUrl) + .attributes(clientRegistrationId(clientRegistration2.getRegistrationId())).retrieve() .bodyToMono(String.class)) - .subscriberContext(context()) - .block(); + .subscriberContext(context()).block(); assertThat(this.server.getRequestCount()).isEqualTo(4); - ArgumentCaptor authorizedClientCaptor = ArgumentCaptor.forClass(OAuth2AuthorizedClient.class); - verify(this.authorizedClientRepository, times(2)).saveAuthorizedClient( - authorizedClientCaptor.capture(), eq(this.authentication), eq(this.request), eq(this.response)); + ArgumentCaptor authorizedClientCaptor = ArgumentCaptor + .forClass(OAuth2AuthorizedClient.class); + verify(this.authorizedClientRepository, times(2)).saveAuthorizedClient(authorizedClientCaptor.capture(), + eq(this.authentication), eq(this.request), eq(this.response)); assertThat(authorizedClientCaptor.getAllValues().get(0).getClientRegistration()).isSameAs(clientRegistration1); assertThat(authorizedClientCaptor.getAllValues().get(1).getClientRegistration()).isSameAs(clientRegistration2); } @@ -271,8 +258,7 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionITests { } private MockResponse jsonResponse(String json) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setBody(json); + return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunctionTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunctionTests.java index 2a0c9cf841..726f7891c1 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunctionTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunctionTests.java @@ -129,28 +129,40 @@ import static org.springframework.security.oauth2.client.web.reactive.function.c */ @RunWith(MockitoJUnitRunner.class) public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { + @Mock private OAuth2AuthorizedClientRepository authorizedClientRepository; + @Mock private ClientRegistrationRepository clientRegistrationRepository; + @Mock private OAuth2AccessTokenResponseClient clientCredentialsTokenResponseClient; + @Mock private OAuth2AccessTokenResponseClient refreshTokenTokenResponseClient; + @Mock private OAuth2AccessTokenResponseClient passwordTokenResponseClient; + @Mock private OAuth2AuthorizationFailureHandler authorizationFailureHandler; + @Captor private ArgumentCaptor authorizationExceptionCaptor; + @Captor private ArgumentCaptor authenticationCaptor; + @Captor private ArgumentCaptor> attributesCaptor; + @Mock private WebClient.RequestHeadersSpec spec; + @Captor private ArgumentCaptor>> attrs; + @Captor private ArgumentCaptor authorizedClientCaptor; @@ -169,23 +181,20 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { private ClientRegistration registration = TestClientRegistrations.clientRegistration().build(); - private OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "token-0", - Instant.now(), - Instant.now().plus(Duration.ofDays(1))); + private OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token-0", + Instant.now(), Instant.now().plus(Duration.ofDays(1))); @Before public void setup() { this.authentication = new TestingAuthenticationToken("test", "this"); - OAuth2AuthorizedClientProvider authorizedClientProvider = - OAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .refreshToken(configurer -> configurer.accessTokenResponseClient(this.refreshTokenTokenResponseClient)) - .clientCredentials(configurer -> configurer.accessTokenResponseClient(this.clientCredentialsTokenResponseClient)) - .password(configurer -> configurer.accessTokenResponseClient(this.passwordTokenResponseClient)) - .build(); - this.authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( - this.clientRegistrationRepository, this.authorizedClientRepository); + OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() + .authorizationCode() + .refreshToken(configurer -> configurer.accessTokenResponseClient(this.refreshTokenTokenResponseClient)) + .clientCredentials( + configurer -> configurer.accessTokenResponseClient(this.clientCredentialsTokenResponseClient)) + .password(configurer -> configurer.accessTokenResponseClient(this.passwordTokenResponseClient)).build(); + this.authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(this.clientRegistrationRepository, + this.authorizedClientRepository); this.authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); this.function = new ServletOAuth2AuthorizedClientExchangeFilterFunction(this.authorizedClientManager); } @@ -211,18 +220,19 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void setClientCredentialsTokenResponseClientWhenNotDefaultAuthorizedClientManagerThenThrowIllegalStateException() { - assertThatThrownBy(() -> this.function.setClientCredentialsTokenResponseClient(new DefaultClientCredentialsTokenResponseClient())) - .isInstanceOf(IllegalStateException.class) - .hasMessage("The client cannot be set when the constructor used is \"ServletOAuth2AuthorizedClientExchangeFilterFunction(OAuth2AuthorizedClientManager)\". " + - "Instead, use the constructor \"ServletOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\"."); + assertThatThrownBy(() -> this.function + .setClientCredentialsTokenResponseClient(new DefaultClientCredentialsTokenResponseClient())) + .isInstanceOf(IllegalStateException.class).hasMessage( + "The client cannot be set when the constructor used is \"ServletOAuth2AuthorizedClientExchangeFilterFunction(OAuth2AuthorizedClientManager)\". " + + "Instead, use the constructor \"ServletOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\"."); } @Test public void setAccessTokenExpiresSkewWhenNotDefaultAuthorizedClientManagerThenThrowIllegalStateException() { assertThatThrownBy(() -> this.function.setAccessTokenExpiresSkew(Duration.ofSeconds(30))) - .isInstanceOf(IllegalStateException.class) - .hasMessage("The accessTokenExpiresSkew cannot be set when the constructor used is \"ServletOAuth2AuthorizedClientExchangeFilterFunction(OAuth2AuthorizedClientManager)\". " + - "Instead, use the constructor \"ServletOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\"."); + .isInstanceOf(IllegalStateException.class).hasMessage( + "The accessTokenExpiresSkew cannot be set when the constructor used is \"ServletOAuth2AuthorizedClientExchangeFilterFunction(OAuth2AuthorizedClientManager)\". " + + "Instead, use the constructor \"ServletOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository, OAuth2AuthorizedClientRepository)\"."); } @Test @@ -267,8 +277,7 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenAuthorizedClientNullThenAuthorizationHeaderNull() { - ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .build(); + ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")).build(); this.function.filter(request, this.exchange).block(); @@ -277,31 +286,29 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenAuthorizedClientThenAuthorizationHeader() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) .attributes(oauth2AuthorizedClient(authorizedClient)) .attributes(httpServletRequest(new MockHttpServletRequest())) - .attributes(httpServletResponse(new MockHttpServletResponse())) - .build(); + .attributes(httpServletResponse(new MockHttpServletResponse())).build(); this.function.filter(request, this.exchange).block(); - assertThat(this.exchange.getRequest().headers().getFirst(HttpHeaders.AUTHORIZATION)).isEqualTo("Bearer " + this.accessToken.getTokenValue()); + assertThat(this.exchange.getRequest().headers().getFirst(HttpHeaders.AUTHORIZATION)) + .isEqualTo("Bearer " + this.accessToken.getTokenValue()); } @Test public void filterWhenExistingAuthorizationThenSingleAuthorizationHeader() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .header(HttpHeaders.AUTHORIZATION, "Existing") - .attributes(oauth2AuthorizedClient(authorizedClient)) + .header(HttpHeaders.AUTHORIZATION, "Existing").attributes(oauth2AuthorizedClient(authorizedClient)) .attributes(httpServletRequest(new MockHttpServletRequest())) - .attributes(httpServletResponse(new MockHttpServletResponse())) - .build(); + .attributes(httpServletResponse(new MockHttpServletResponse())).build(); this.function.filter(request, this.exchange).block(); @@ -312,34 +319,27 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenRefreshRequiredThenRefresh() { OAuth2AccessTokenResponse response = OAuth2AccessTokenResponse.withToken("token-1") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(3600) - .refreshToken("refresh-1") - .build(); + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(3600).refreshToken("refresh-1").build(); when(this.refreshTokenTokenResponseClient.getTokenResponse(any())).thenReturn(response); Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant accessTokenExpiresAt = issuedAt.plus(Duration.ofHours(1)); - this.accessToken = new OAuth2AccessToken(this.accessToken.getTokenType(), - this.accessToken.getTokenValue(), - issuedAt, - accessTokenExpiresAt); + this.accessToken = new OAuth2AccessToken(this.accessToken.getTokenType(), this.accessToken.getTokenValue(), + issuedAt, accessTokenExpiresAt); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", issuedAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .attributes(authentication(this.authentication)) + .attributes(oauth2AuthorizedClient(authorizedClient)).attributes(authentication(this.authentication)) .attributes(httpServletRequest(new MockHttpServletRequest())) - .attributes(httpServletResponse(new MockHttpServletResponse())) - .build(); + .attributes(httpServletResponse(new MockHttpServletResponse())).build(); this.function.filter(request, this.exchange).block(); verify(this.refreshTokenTokenResponseClient).getTokenResponse(any()); - verify(this.authorizedClientRepository).saveAuthorizedClient( - this.authorizedClientCaptor.capture(), eq(this.authentication), any(), any()); + verify(this.authorizedClientRepository).saveAuthorizedClient(this.authorizedClientCaptor.capture(), + eq(this.authentication), any(), any()); OAuth2AuthorizedClient newAuthorizedClient = authorizedClientCaptor.getValue(); assertThat(newAuthorizedClient.getAccessToken()).isEqualTo(response.getAccessToken()); @@ -358,9 +358,8 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenRefreshRequiredThenRefreshAndResponseDoesNotContainRefreshToken() { OAuth2AccessTokenResponse response = OAuth2AccessTokenResponse.withToken("token-1") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(3600) -// .refreshToken(xxx) // No refreshToken in response + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(3600) + // .refreshToken(xxx) // No refreshToken in response .build(); RestOperations refreshTokenClient = mock(RestOperations.class); @@ -378,25 +377,22 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant accessTokenExpiresAt = issuedAt.plus(Duration.ofHours(1)); - this.accessToken = new OAuth2AccessToken(this.accessToken.getTokenType(), - this.accessToken.getTokenValue(), - issuedAt, - accessTokenExpiresAt); + this.accessToken = new OAuth2AccessToken(this.accessToken.getTokenType(), this.accessToken.getTokenValue(), + issuedAt, accessTokenExpiresAt); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", issuedAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .attributes(authentication(this.authentication)) + .attributes(oauth2AuthorizedClient(authorizedClient)).attributes(authentication(this.authentication)) .attributes(httpServletRequest(new MockHttpServletRequest())) - .attributes(httpServletResponse(new MockHttpServletResponse())) - .build(); + .attributes(httpServletResponse(new MockHttpServletResponse())).build(); this.function.filter(request, this.exchange).block(); verify(refreshTokenClient).exchange(any(RequestEntity.class), eq(OAuth2AccessTokenResponse.class)); - verify(this.authorizedClientRepository).saveAuthorizedClient(this.authorizedClientCaptor.capture(), eq(this.authentication), any(), any()); + verify(this.authorizedClientRepository).saveAuthorizedClient(this.authorizedClientCaptor.capture(), + eq(this.authentication), any(), any()); OAuth2AuthorizedClient newAuthorizedClient = authorizedClientCaptor.getValue(); assertThat(newAuthorizedClient.getAccessToken()).isEqualTo(response.getAccessToken()); @@ -415,19 +411,18 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenClientCredentialsTokenNotExpiredThenUseCurrentToken() { this.registration = TestClientRegistrations.clientCredentials().build(); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, null); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, null); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .attributes(authentication(this.authentication)) + .attributes(oauth2AuthorizedClient(authorizedClient)).attributes(authentication(this.authentication)) .attributes(httpServletRequest(new MockHttpServletRequest())) - .attributes(httpServletResponse(new MockHttpServletResponse())) - .build(); + .attributes(httpServletResponse(new MockHttpServletResponse())).build(); this.function.filter(request, this.exchange).block(); - verify(this.authorizedClientRepository, never()).saveAuthorizedClient(any(), eq(this.authentication), any(), any()); + verify(this.authorizedClientRepository, never()).saveAuthorizedClient(any(), eq(this.authentication), any(), + any()); verify(clientCredentialsTokenResponseClient, never()).getTokenResponse(any()); @@ -445,27 +440,21 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { public void filterWhenClientCredentialsTokenExpiredThenGetNewToken() { this.registration = TestClientRegistrations.clientCredentials().build(); - OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses - .accessTokenResponse().build(); - when(this.clientCredentialsTokenResponseClient.getTokenResponse(any())).thenReturn( - accessTokenResponse); + OAuth2AccessTokenResponse accessTokenResponse = TestOAuth2AccessTokenResponses.accessTokenResponse().build(); + when(this.clientCredentialsTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant accessTokenExpiresAt = issuedAt.plus(Duration.ofHours(1)); - this.accessToken = new OAuth2AccessToken(this.accessToken.getTokenType(), - this.accessToken.getTokenValue(), - issuedAt, - accessTokenExpiresAt); + this.accessToken = new OAuth2AccessToken(this.accessToken.getTokenType(), this.accessToken.getTokenValue(), + issuedAt, accessTokenExpiresAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, null); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, null); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .attributes(authentication(this.authentication)) + .attributes(oauth2AuthorizedClient(authorizedClient)).attributes(authentication(this.authentication)) .attributes(httpServletRequest(new MockHttpServletRequest())) - .attributes(httpServletResponse(new MockHttpServletResponse())) - .build(); + .attributes(httpServletResponse(new MockHttpServletResponse())).build(); this.function.filter(request, this.exchange).block(); @@ -486,13 +475,12 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenPasswordClientNotAuthorizedThenGetNewToken() { OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("new-token") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(360) - .build(); + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(360).build(); when(this.passwordTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); ClientRegistration registration = TestClientRegistrations.password().build(); - when(this.clientRegistrationRepository.findByRegistrationId(eq(registration.getRegistrationId()))).thenReturn(registration); + when(this.clientRegistrationRepository.findByRegistrationId(eq(registration.getRegistrationId()))) + .thenReturn(registration); // Set custom contextAttributesMapper this.authorizedClientManager.setContextAttributesMapper(authorizeRequest -> { @@ -514,10 +502,8 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) .attributes(clientRegistrationId(registration.getRegistrationId())) - .attributes(authentication(this.authentication)) - .attributes(httpServletRequest(servletRequest)) - .attributes(httpServletResponse(servletResponse)) - .build(); + .attributes(authentication(this.authentication)).attributes(httpServletRequest(servletRequest)) + .attributes(httpServletResponse(servletResponse)).build(); this.function.filter(request, this.exchange).block(); @@ -536,25 +522,21 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenRefreshRequiredAndEmptyReactiveSecurityContextThenSaved() { OAuth2AccessTokenResponse response = OAuth2AccessTokenResponse.withToken("token-1") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(3600) - .refreshToken("refresh-1") - .build(); + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(3600).refreshToken("refresh-1").build(); when(this.refreshTokenTokenResponseClient.getTokenResponse(any())).thenReturn(response); Instant issuedAt = Instant.now().minus(Duration.ofDays(1)); Instant accessTokenExpiresAt = issuedAt.plus(Duration.ofHours(1)); - this.accessToken = new OAuth2AccessToken(this.accessToken.getTokenType(), - this.accessToken.getTokenValue(), issuedAt, accessTokenExpiresAt); + this.accessToken = new OAuth2AccessToken(this.accessToken.getTokenType(), this.accessToken.getTokenValue(), + issuedAt, accessTokenExpiresAt); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", issuedAt); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) .attributes(oauth2AuthorizedClient(authorizedClient)) .attributes(httpServletRequest(new MockHttpServletRequest())) - .attributes(httpServletResponse(new MockHttpServletResponse())) - .build(); + .attributes(httpServletResponse(new MockHttpServletResponse())).build(); this.function.filter(request, this.exchange).block(); @@ -573,14 +555,13 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenRefreshTokenNullThenShouldRefreshFalse() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) .attributes(oauth2AuthorizedClient(authorizedClient)) .attributes(httpServletRequest(new MockHttpServletRequest())) - .attributes(httpServletResponse(new MockHttpServletResponse())) - .build(); + .attributes(httpServletResponse(new MockHttpServletResponse())).build(); this.function.filter(request, this.exchange).block(); @@ -597,14 +578,13 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { @Test public void filterWhenNotExpiredThenShouldRefreshFalse() { OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", this.accessToken.getIssuedAt()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, - "principalName", this.accessToken, refreshToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken, refreshToken); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) .attributes(oauth2AuthorizedClient(authorizedClient)) .attributes(httpServletRequest(new MockHttpServletRequest())) - .attributes(httpServletResponse(new MockHttpServletResponse())) - .build(); + .attributes(httpServletResponse(new MockHttpServletResponse())).build(); this.function.filter(request, this.exchange).block(); @@ -628,14 +608,15 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { OAuth2User user = mock(OAuth2User.class); List authorities = AuthorityUtils.createAuthorityList("ROLE_USER"); - OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken( - user, authorities, this.registration.getRegistrationId()); + OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken(user, authorities, + this.registration.getRegistrationId()); - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration, "principalName", this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken); - when(this.authorizedClientRepository.loadAuthorizedClient(eq(authentication.getAuthorizedClientRegistrationId()), - eq(authentication), eq(servletRequest))).thenReturn(authorizedClient); + when(this.authorizedClientRepository.loadAuthorizedClient( + eq(authentication.getAuthorizedClientRegistrationId()), eq(authentication), eq(servletRequest))) + .thenReturn(authorizedClient); // Default request attributes set final ClientRequest request1 = ClientRequest.create(GET, URI.create("https://example1.com")) @@ -646,10 +627,8 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { Context context = context(servletRequest, servletResponse, authentication); - this.function.filter(request1, this.exchange) - .flatMap(response -> this.function.filter(request2, this.exchange)) - .subscriberContext(context) - .block(); + this.function.filter(request1, this.exchange).flatMap(response -> this.function.filter(request2, this.exchange)) + .subscriberContext(context).block(); List requests = this.exchange.getRequests(); assertThat(requests).hasSize(2); @@ -678,15 +657,13 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { } private void assertHttpStatusInvokesFailureHandler(HttpStatus httpStatus, String expectedErrorCode) { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration, "principalName", this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken); MockHttpServletRequest servletRequest = new MockHttpServletRequest(); MockHttpServletResponse servletResponse = new MockHttpServletResponse(); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .attributes(httpServletRequest(servletRequest)) - .attributes(httpServletResponse(servletResponse)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).attributes(httpServletRequest(servletRequest)) + .attributes(httpServletResponse(servletResponse)).build(); when(this.exchange.getResponse().rawStatusCode()).thenReturn(httpStatus.value()); when(this.exchange.getResponse().headers()).thenReturn(mock(ClientResponse.Headers.class)); @@ -694,10 +671,8 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { this.function.filter(request, this.exchange).block(); - verify(this.authorizationFailureHandler).onAuthorizationFailure( - this.authorizationExceptionCaptor.capture(), - this.authenticationCaptor.capture(), - this.attributesCaptor.capture()); + verify(this.authorizationFailureHandler).onAuthorizationFailure(this.authorizationExceptionCaptor.capture(), + this.authenticationCaptor.capture(), this.attributesCaptor.capture()); assertThat(this.authorizationExceptionCaptor.getValue()) .isInstanceOfSatisfying(ClientAuthorizationException.class, e -> { @@ -706,29 +681,25 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { assertThat(e).hasNoCause(); assertThat(e).hasMessageContaining(expectedErrorCode); }); - assertThat(this.authenticationCaptor.getValue().getName()) - .isEqualTo(authorizedClient.getPrincipalName()); - assertThat(this.attributesCaptor.getValue()) - .containsExactly( - entry(HttpServletRequest.class.getName(), servletRequest), - entry(HttpServletResponse.class.getName(), servletResponse)); + assertThat(this.authenticationCaptor.getValue().getName()).isEqualTo(authorizedClient.getPrincipalName()); + assertThat(this.attributesCaptor.getValue()).containsExactly( + entry(HttpServletRequest.class.getName(), servletRequest), + entry(HttpServletResponse.class.getName(), servletResponse)); } @Test public void filterWhenWWWAuthenticateHeaderIncludesErrorThenInvokeFailureHandler() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration, "principalName", this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken); MockHttpServletRequest servletRequest = new MockHttpServletRequest(); MockHttpServletResponse servletResponse = new MockHttpServletResponse(); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .attributes(httpServletRequest(servletRequest)) - .attributes(httpServletResponse(servletResponse)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).attributes(httpServletRequest(servletRequest)) + .attributes(httpServletResponse(servletResponse)).build(); - String wwwAuthenticateHeader = "Bearer error=\"insufficient_scope\", " + - "error_description=\"The request requires higher privileges than provided by the access token.\", " + - "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\""; + String wwwAuthenticateHeader = "Bearer error=\"insufficient_scope\", " + + "error_description=\"The request requires higher privileges than provided by the access token.\", " + + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\""; ClientResponse.Headers headers = mock(ClientResponse.Headers.class); when(headers.header(eq(HttpHeaders.WWW_AUTHENTICATE))) .thenReturn(Collections.singletonList(wwwAuthenticateHeader)); @@ -737,69 +708,57 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { this.function.filter(request, this.exchange).block(); - verify(this.authorizationFailureHandler).onAuthorizationFailure( - this.authorizationExceptionCaptor.capture(), - this.authenticationCaptor.capture(), - this.attributesCaptor.capture()); + verify(this.authorizationFailureHandler).onAuthorizationFailure(this.authorizationExceptionCaptor.capture(), + this.authenticationCaptor.capture(), this.attributesCaptor.capture()); assertThat(this.authorizationExceptionCaptor.getValue()) .isInstanceOfSatisfying(ClientAuthorizationException.class, e -> { assertThat(e.getClientRegistrationId()).isEqualTo(this.registration.getRegistrationId()); assertThat(e.getError().getErrorCode()).isEqualTo(OAuth2ErrorCodes.INSUFFICIENT_SCOPE); - assertThat(e.getError().getDescription()).isEqualTo("The request requires higher privileges than provided by the access token."); + assertThat(e.getError().getDescription()) + .isEqualTo("The request requires higher privileges than provided by the access token."); assertThat(e.getError().getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1"); assertThat(e).hasNoCause(); assertThat(e).hasMessageContaining(OAuth2ErrorCodes.INSUFFICIENT_SCOPE); }); - assertThat(this.authenticationCaptor.getValue().getName()) - .isEqualTo(authorizedClient.getPrincipalName()); - assertThat(this.attributesCaptor.getValue()) - .containsExactly( - entry(HttpServletRequest.class.getName(), servletRequest), - entry(HttpServletResponse.class.getName(), servletResponse)); + assertThat(this.authenticationCaptor.getValue().getName()).isEqualTo(authorizedClient.getPrincipalName()); + assertThat(this.attributesCaptor.getValue()).containsExactly( + entry(HttpServletRequest.class.getName(), servletRequest), + entry(HttpServletResponse.class.getName(), servletResponse)); } @Test public void filterWhenUnauthorizedWithWebClientExceptionThenInvokeFailureHandler() { - assertHttpStatusWithWebClientExceptionInvokesFailureHandler( - HttpStatus.UNAUTHORIZED, OAuth2ErrorCodes.INVALID_TOKEN); + assertHttpStatusWithWebClientExceptionInvokesFailureHandler(HttpStatus.UNAUTHORIZED, + OAuth2ErrorCodes.INVALID_TOKEN); } @Test public void filterWhenForbiddenWithWebClientExceptionThenInvokeFailureHandler() { - assertHttpStatusWithWebClientExceptionInvokesFailureHandler( - HttpStatus.FORBIDDEN, OAuth2ErrorCodes.INSUFFICIENT_SCOPE); + assertHttpStatusWithWebClientExceptionInvokesFailureHandler(HttpStatus.FORBIDDEN, + OAuth2ErrorCodes.INSUFFICIENT_SCOPE); } - private void assertHttpStatusWithWebClientExceptionInvokesFailureHandler( - HttpStatus httpStatus, String expectedErrorCode) { + private void assertHttpStatusWithWebClientExceptionInvokesFailureHandler(HttpStatus httpStatus, + String expectedErrorCode) { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration, "principalName", this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken); MockHttpServletRequest servletRequest = new MockHttpServletRequest(); MockHttpServletResponse servletResponse = new MockHttpServletResponse(); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .attributes(httpServletRequest(servletRequest)) - .attributes(httpServletResponse(servletResponse)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).attributes(httpServletRequest(servletRequest)) + .attributes(httpServletResponse(servletResponse)).build(); - WebClientResponseException exception = WebClientResponseException.create( - httpStatus.value(), - httpStatus.getReasonPhrase(), - HttpHeaders.EMPTY, - new byte[0], - StandardCharsets.UTF_8); + WebClientResponseException exception = WebClientResponseException.create(httpStatus.value(), + httpStatus.getReasonPhrase(), HttpHeaders.EMPTY, new byte[0], StandardCharsets.UTF_8); ExchangeFunction throwingExchangeFunction = r -> Mono.error(exception); this.function.setAuthorizationFailureHandler(this.authorizationFailureHandler); - assertThatCode(() -> this.function.filter(request, throwingExchangeFunction).block()) - .isEqualTo(exception); + assertThatCode(() -> this.function.filter(request, throwingExchangeFunction).block()).isEqualTo(exception); - verify(this.authorizationFailureHandler).onAuthorizationFailure( - this.authorizationExceptionCaptor.capture(), - this.authenticationCaptor.capture(), - this.attributesCaptor.capture()); + verify(this.authorizationFailureHandler).onAuthorizationFailure(this.authorizationExceptionCaptor.capture(), + this.authenticationCaptor.capture(), this.attributesCaptor.capture()); assertThat(this.authorizationExceptionCaptor.getValue()) .isInstanceOfSatisfying(ClientAuthorizationException.class, e -> { @@ -808,25 +767,21 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { assertThat(e).hasCause(exception); assertThat(e).hasMessageContaining(expectedErrorCode); }); - assertThat(this.authenticationCaptor.getValue().getName()) - .isEqualTo(authorizedClient.getPrincipalName()); - assertThat(this.attributesCaptor.getValue()) - .containsExactly( - entry(HttpServletRequest.class.getName(), servletRequest), - entry(HttpServletResponse.class.getName(), servletResponse)); + assertThat(this.authenticationCaptor.getValue().getName()).isEqualTo(authorizedClient.getPrincipalName()); + assertThat(this.attributesCaptor.getValue()).containsExactly( + entry(HttpServletRequest.class.getName(), servletRequest), + entry(HttpServletResponse.class.getName(), servletResponse)); } @Test public void filterWhenAuthorizationExceptionThenInvokeFailureHandler() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration, "principalName", this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken); MockHttpServletRequest servletRequest = new MockHttpServletRequest(); MockHttpServletResponse servletResponse = new MockHttpServletResponse(); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .attributes(httpServletRequest(servletRequest)) - .attributes(httpServletResponse(servletResponse)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).attributes(httpServletRequest(servletRequest)) + .attributes(httpServletResponse(servletResponse)).build(); OAuth2AuthorizationException authorizationException = new OAuth2AuthorizationException( new OAuth2Error(OAuth2ErrorCodes.INVALID_TOKEN)); @@ -836,10 +791,8 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { assertThatCode(() -> this.function.filter(request, throwingExchangeFunction).block()) .isEqualTo(authorizationException); - verify(this.authorizationFailureHandler).onAuthorizationFailure( - this.authorizationExceptionCaptor.capture(), - this.authenticationCaptor.capture(), - this.attributesCaptor.capture()); + verify(this.authorizationFailureHandler).onAuthorizationFailure(this.authorizationExceptionCaptor.capture(), + this.authenticationCaptor.capture(), this.attributesCaptor.capture()); assertThat(this.authorizationExceptionCaptor.getValue()) .isInstanceOfSatisfying(OAuth2AuthorizationException.class, e -> { @@ -847,25 +800,21 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { assertThat(e).hasNoCause(); assertThat(e).hasMessageContaining(OAuth2ErrorCodes.INVALID_TOKEN); }); - assertThat(this.authenticationCaptor.getValue().getName()) - .isEqualTo(authorizedClient.getPrincipalName()); - assertThat(this.attributesCaptor.getValue()) - .containsExactly( - entry(HttpServletRequest.class.getName(), servletRequest), - entry(HttpServletResponse.class.getName(), servletResponse)); + assertThat(this.authenticationCaptor.getValue().getName()).isEqualTo(authorizedClient.getPrincipalName()); + assertThat(this.attributesCaptor.getValue()).containsExactly( + entry(HttpServletRequest.class.getName(), servletRequest), + entry(HttpServletResponse.class.getName(), servletResponse)); } @Test public void filterWhenOtherHttpStatusThenDoesNotInvokeFailureHandler() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration, "principalName", this.accessToken); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration, "principalName", + this.accessToken); MockHttpServletRequest servletRequest = new MockHttpServletRequest(); MockHttpServletResponse servletResponse = new MockHttpServletResponse(); ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .attributes(oauth2AuthorizedClient(authorizedClient)) - .attributes(httpServletRequest(servletRequest)) - .attributes(httpServletResponse(servletResponse)) - .build(); + .attributes(oauth2AuthorizedClient(authorizedClient)).attributes(httpServletRequest(servletRequest)) + .attributes(httpServletResponse(servletResponse)).build(); when(this.exchange.getResponse().rawStatusCode()).thenReturn(HttpStatus.BAD_REQUEST.value()); when(this.exchange.getResponse().headers()).thenReturn(mock(ClientResponse.Headers.class)); @@ -876,7 +825,8 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { verifyNoInteractions(this.authorizationFailureHandler); } - private Context context(HttpServletRequest servletRequest, HttpServletResponse servletResponse, Authentication authentication) { + private Context context(HttpServletRequest servletRequest, HttpServletResponse servletResponse, + Authentication authentication) { Map contextAttributes = new HashMap<>(); contextAttributes.put(HttpServletRequest.class, servletRequest); contextAttributes.put(HttpServletResponse.class, servletResponse); @@ -917,4 +867,5 @@ public class ServletOAuth2AuthorizedClientExchangeFilterFunctionTests { request.body().insert(body, context).block(); return body.getBodyAsString().block(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/result/method/annotation/OAuth2AuthorizedClientArgumentResolverTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/result/method/annotation/OAuth2AuthorizedClientArgumentResolverTests.java index 0c66fb9f44..5068c43d65 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/result/method/annotation/OAuth2AuthorizedClientArgumentResolverTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/reactive/result/method/annotation/OAuth2AuthorizedClientArgumentResolverTests.java @@ -59,34 +59,36 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class OAuth2AuthorizedClientArgumentResolverTests { + @Mock private ReactiveClientRegistrationRepository clientRegistrationRepository; + @Mock private ServerOAuth2AuthorizedClientRepository authorizedClientRepository; private ServerWebExchange serverWebExchange = MockServerWebExchange.builder(MockServerHttpRequest.get("/")).build(); private OAuth2AuthorizedClientArgumentResolver argumentResolver; + private ClientRegistration clientRegistration; + private OAuth2AuthorizedClient authorizedClient; + private Authentication authentication = new TestingAuthenticationToken("test", "this"); @Before public void setUp() { - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = - ReactiveOAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .refreshToken() - .clientCredentials() - .build(); + ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder + .builder().authorizationCode().refreshToken().clientCredentials().build(); DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager( this.clientRegistrationRepository, this.authorizedClientRepository); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); this.argumentResolver = new OAuth2AuthorizedClientArgumentResolver(authorizedClientManager); this.clientRegistration = TestClientRegistrations.clientRegistration().build(); - this.authorizedClient = new OAuth2AuthorizedClient( - this.clientRegistration, this.authentication.getName(), TestOAuth2AccessTokens.noScopes()); - when(this.authorizedClientRepository.loadAuthorizedClient(anyString(), any(), any())).thenReturn(Mono.just(this.authorizedClient)); + this.authorizedClient = new OAuth2AuthorizedClient(this.clientRegistration, this.authentication.getName(), + TestOAuth2AccessTokens.noScopes()); + when(this.authorizedClientRepository.loadAuthorizedClient(anyString(), any(), any())) + .thenReturn(Mono.just(this.authorizedClient)); } @Test @@ -109,34 +111,37 @@ public class OAuth2AuthorizedClientArgumentResolverTests { @Test public void supportsParameterWhenParameterTypeOAuth2AuthorizedClientThenTrue() { - MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClient", OAuth2AuthorizedClient.class); + MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClient", + OAuth2AuthorizedClient.class); assertThat(this.argumentResolver.supportsParameter(methodParameter)).isTrue(); } @Test public void supportsParameterWhenParameterTypeOAuth2AuthorizedClientWithoutAnnotationThenFalse() { - MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClientWithoutAnnotation", OAuth2AuthorizedClient.class); + MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClientWithoutAnnotation", + OAuth2AuthorizedClient.class); assertThat(this.argumentResolver.supportsParameter(methodParameter)).isFalse(); } @Test public void supportsParameterWhenParameterTypeUnsupportedWithoutAnnotationThenFalse() { - MethodParameter methodParameter = this.getMethodParameter("paramTypeUnsupportedWithoutAnnotation", String.class); + MethodParameter methodParameter = this.getMethodParameter("paramTypeUnsupportedWithoutAnnotation", + String.class); assertThat(this.argumentResolver.supportsParameter(methodParameter)).isFalse(); } @Test public void resolveArgumentWhenRegistrationIdEmptyAndNotOAuth2AuthenticationThenThrowIllegalArgumentException() { MethodParameter methodParameter = this.getMethodParameter("registrationIdEmpty", OAuth2AuthorizedClient.class); - assertThatThrownBy(() -> resolveArgument(methodParameter)) - .isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> resolveArgument(methodParameter)).isInstanceOf(IllegalArgumentException.class) .hasMessage("The clientRegistrationId could not be resolved. Please provide one"); } @Test public void resolveArgumentWhenRegistrationIdEmptyAndOAuth2AuthenticationThenResolves() { this.authentication = mock(OAuth2AuthenticationToken.class); - when(((OAuth2AuthenticationToken) this.authentication).getAuthorizedClientRegistrationId()).thenReturn("client1"); + when(((OAuth2AuthenticationToken) this.authentication).getAuthorizedClientRegistrationId()) + .thenReturn("client1"); MethodParameter methodParameter = this.getMethodParameter("registrationIdEmpty", OAuth2AuthorizedClient.class); resolveArgument(methodParameter); } @@ -144,30 +149,34 @@ public class OAuth2AuthorizedClientArgumentResolverTests { @Test public void resolveArgumentWhenParameterTypeOAuth2AuthorizedClientAndCurrentAuthenticationNullThenResolves() { this.authentication = null; - MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClient", OAuth2AuthorizedClient.class); + MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClient", + OAuth2AuthorizedClient.class); assertThat(resolveArgument(methodParameter)).isSameAs(this.authorizedClient); } @Test public void resolveArgumentWhenOAuth2AuthorizedClientFoundThenResolves() { - MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClient", OAuth2AuthorizedClient.class); + MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClient", + OAuth2AuthorizedClient.class); assertThat(resolveArgument(methodParameter)).isSameAs(this.authorizedClient); } @Test public void resolveArgumentWhenOAuth2AuthorizedClientNotFoundThenThrowClientAuthorizationRequiredException() { - when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(Mono.just(this.clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(any())) + .thenReturn(Mono.just(this.clientRegistration)); when(this.authorizedClientRepository.loadAuthorizedClient(anyString(), any(), any())).thenReturn(Mono.empty()); - MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClient", OAuth2AuthorizedClient.class); + MethodParameter methodParameter = this.getMethodParameter("paramTypeAuthorizedClient", + OAuth2AuthorizedClient.class); assertThatThrownBy(() -> resolveArgument(methodParameter)) .isInstanceOf(ClientAuthorizationRequiredException.class); } private Object resolveArgument(MethodParameter methodParameter) { return this.argumentResolver.resolveArgument(methodParameter, null, null) - .subscriberContext(this.authentication == null ? Context.empty() : ReactiveSecurityContextHolder.withAuthentication(this.authentication)) - .subscriberContext(serverWebExchange()) - .block(); + .subscriberContext(this.authentication == null ? Context.empty() + : ReactiveSecurityContextHolder.withAuthentication(this.authentication)) + .subscriberContext(serverWebExchange()).block(); } private Context serverWebExchange() { @@ -175,13 +184,14 @@ public class OAuth2AuthorizedClientArgumentResolverTests { } private MethodParameter getMethodParameter(String methodName, Class... paramTypes) { - Method method = ReflectionUtils.findMethod( - TestController.class, methodName, paramTypes); + Method method = ReflectionUtils.findMethod(TestController.class, methodName, paramTypes); return new MethodParameter(method, 0); } static class TestController { - void paramTypeAuthorizedClient(@RegisteredOAuth2AuthorizedClient("client1") OAuth2AuthorizedClient authorizedClient) { + + void paramTypeAuthorizedClient( + @RegisteredOAuth2AuthorizedClient("client1") OAuth2AuthorizedClient authorizedClient) { } void paramTypeAuthorizedClientWithoutAnnotation(OAuth2AuthorizedClient authorizedClient) { @@ -195,5 +205,7 @@ public class OAuth2AuthorizedClientArgumentResolverTests { void registrationIdEmpty(@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient) { } + } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/AuthenticatedPrincipalServerOAuth2AuthorizedClientRepositoryTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/AuthenticatedPrincipalServerOAuth2AuthorizedClientRepositoryTests.java index 0021ebd6bf..274413e8a7 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/AuthenticatedPrincipalServerOAuth2AuthorizedClientRepositoryTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/AuthenticatedPrincipalServerOAuth2AuthorizedClientRepositoryTests.java @@ -37,14 +37,18 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** - * * @author Rob Winch */ public class AuthenticatedPrincipalServerOAuth2AuthorizedClientRepositoryTests { + private String registrationId = "registrationId"; + private String principalName = "principalName"; + private ReactiveOAuth2AuthorizedClientService authorizedClientService; + private ServerOAuth2AuthorizedClientRepository anonymousAuthorizedClientRepository; + private AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository authorizedClientRepository; private MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/")); @@ -52,10 +56,11 @@ public class AuthenticatedPrincipalServerOAuth2AuthorizedClientRepositoryTests { @Before public void setup() { this.authorizedClientService = mock(ReactiveOAuth2AuthorizedClientService.class); - this.anonymousAuthorizedClientRepository = mock( - ServerOAuth2AuthorizedClientRepository.class); - this.authorizedClientRepository = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(this.authorizedClientService); - this.authorizedClientRepository.setAnonymousAuthorizedClientRepository(this.anonymousAuthorizedClientRepository); + this.anonymousAuthorizedClientRepository = mock(ServerOAuth2AuthorizedClientRepository.class); + this.authorizedClientRepository = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository( + this.authorizedClientService); + this.authorizedClientRepository + .setAnonymousAuthorizedClientRepository(this.anonymousAuthorizedClientRepository); } @Test @@ -74,16 +79,20 @@ public class AuthenticatedPrincipalServerOAuth2AuthorizedClientRepositoryTests { public void loadAuthorizedClientWhenAuthenticatedPrincipalThenLoadFromService() { when(this.authorizedClientService.loadAuthorizedClient(any(), any())).thenReturn(Mono.empty()); Authentication authentication = this.createAuthenticatedPrincipal(); - this.authorizedClientRepository.loadAuthorizedClient(this.registrationId, authentication, this.exchange).block(); + this.authorizedClientRepository.loadAuthorizedClient(this.registrationId, authentication, this.exchange) + .block(); verify(this.authorizedClientService).loadAuthorizedClient(this.registrationId, this.principalName); } @Test public void loadAuthorizedClientWhenAnonymousPrincipalThenLoadFromAnonymousRepository() { - when(this.anonymousAuthorizedClientRepository.loadAuthorizedClient(any(), any(), any())).thenReturn(Mono.empty()); + when(this.anonymousAuthorizedClientRepository.loadAuthorizedClient(any(), any(), any())) + .thenReturn(Mono.empty()); Authentication authentication = this.createAnonymousPrincipal(); - this.authorizedClientRepository.loadAuthorizedClient(this.registrationId, authentication, this.exchange).block(); - verify(this.anonymousAuthorizedClientRepository).loadAuthorizedClient(this.registrationId, authentication, this.exchange); + this.authorizedClientRepository.loadAuthorizedClient(this.registrationId, authentication, this.exchange) + .block(); + verify(this.anonymousAuthorizedClientRepository).loadAuthorizedClient(this.registrationId, authentication, + this.exchange); } @Test @@ -97,27 +106,33 @@ public class AuthenticatedPrincipalServerOAuth2AuthorizedClientRepositoryTests { @Test public void saveAuthorizedClientWhenAnonymousPrincipalThenSaveToAnonymousRepository() { - when(this.anonymousAuthorizedClientRepository.saveAuthorizedClient(any(), any(), any())).thenReturn(Mono.empty()); + when(this.anonymousAuthorizedClientRepository.saveAuthorizedClient(any(), any(), any())) + .thenReturn(Mono.empty()); Authentication authentication = this.createAnonymousPrincipal(); OAuth2AuthorizedClient authorizedClient = mock(OAuth2AuthorizedClient.class); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, authentication, this.exchange).block(); - verify(this.anonymousAuthorizedClientRepository).saveAuthorizedClient(authorizedClient, authentication, this.exchange); + verify(this.anonymousAuthorizedClientRepository).saveAuthorizedClient(authorizedClient, authentication, + this.exchange); } @Test public void removeAuthorizedClientWhenAuthenticatedPrincipalThenRemoveFromService() { when(this.authorizedClientService.removeAuthorizedClient(any(), any())).thenReturn(Mono.empty()); Authentication authentication = this.createAuthenticatedPrincipal(); - this.authorizedClientRepository.removeAuthorizedClient(this.registrationId, authentication, this.exchange).block(); + this.authorizedClientRepository.removeAuthorizedClient(this.registrationId, authentication, this.exchange) + .block(); verify(this.authorizedClientService).removeAuthorizedClient(this.registrationId, this.principalName); } @Test public void removeAuthorizedClientWhenAnonymousPrincipalThenRemoveFromAnonymousRepository() { - when(this.anonymousAuthorizedClientRepository.removeAuthorizedClient(any(), any(), any())).thenReturn(Mono.empty()); + when(this.anonymousAuthorizedClientRepository.removeAuthorizedClient(any(), any(), any())) + .thenReturn(Mono.empty()); Authentication authentication = this.createAnonymousPrincipal(); - this.authorizedClientRepository.removeAuthorizedClient(this.registrationId, authentication, this.exchange).block(); - verify(this.anonymousAuthorizedClientRepository).removeAuthorizedClient(this.registrationId, authentication, this.exchange); + this.authorizedClientRepository.removeAuthorizedClient(this.registrationId, authentication, this.exchange) + .block(); + verify(this.anonymousAuthorizedClientRepository).removeAuthorizedClient(this.registrationId, authentication, + this.exchange); } private Authentication createAuthenticatedPrincipal() { @@ -127,6 +142,8 @@ public class AuthenticatedPrincipalServerOAuth2AuthorizedClientRepositoryTests { } private Authentication createAnonymousPrincipal() { - return new AnonymousAuthenticationToken("key-1234", "anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); + return new AnonymousAuthenticationToken("key-1234", "anonymousUser", + AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/DefaultServerOAuth2AuthorizationRequestResolverTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/DefaultServerOAuth2AuthorizationRequestResolverTests.java index 958799b014..868db33116 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/DefaultServerOAuth2AuthorizationRequestResolverTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/DefaultServerOAuth2AuthorizationRequestResolverTests.java @@ -49,6 +49,7 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class DefaultServerOAuth2AuthorizationRequestResolverTests { + @Mock private ReactiveClientRegistrationRepository clientRegistrationRepository; @@ -74,90 +75,78 @@ public class DefaultServerOAuth2AuthorizationRequestResolverTests { @Test public void resolveWhenClientRegistrationNotFoundMatchThenBadRequest() { - when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn( - Mono.empty()); + when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(Mono.empty()); - ResponseStatusException expected = catchThrowableOfType(() -> resolve("/oauth2/authorization/not-found-id"), ResponseStatusException.class); + ResponseStatusException expected = catchThrowableOfType(() -> resolve("/oauth2/authorization/not-found-id"), + ResponseStatusException.class); assertThat(expected.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST); } @Test public void resolveWhenClientRegistrationFoundThenWorks() { - when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn( - Mono.just(this.registration)); + when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(Mono.just(this.registration)); OAuth2AuthorizationRequest request = resolve("/oauth2/authorization/not-found-id"); - assertThat(request.getAuthorizationRequestUri()).matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=read:user&state=.*?&" + - "redirect_uri=/login/oauth2/code/registration-id"); + assertThat(request.getAuthorizationRequestUri()) + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" + + "scope=read:user&state=.*?&" + "redirect_uri=/login/oauth2/code/registration-id"); } @Test public void resolveWhenForwardedHeadersClientRegistrationFoundThenWorks() { - when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn( - Mono.just(this.registration)); - ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/oauth2/authorization/id").header("X-Forwarded-Host", "evil.com")); + when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(Mono.just(this.registration)); + ServerWebExchange exchange = MockServerWebExchange + .from(MockServerHttpRequest.get("/oauth2/authorization/id").header("X-Forwarded-Host", "evil.com")); OAuth2AuthorizationRequest request = this.resolver.resolve(exchange).block(); - assertThat(request.getAuthorizationRequestUri()).matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=read:user&state=.*?&" + - "redirect_uri=/login/oauth2/code/registration-id"); + assertThat(request.getAuthorizationRequestUri()) + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" + + "scope=read:user&state=.*?&" + "redirect_uri=/login/oauth2/code/registration-id"); } @Test public void resolveWhenAuthorizationRequestWithValidPkceClientThenResolves() { - when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn( - Mono.just(TestClientRegistrations.clientRegistration() - .clientAuthenticationMethod(ClientAuthenticationMethod.NONE) - .clientSecret(null) - .build())); + when(this.clientRegistrationRepository.findByRegistrationId(any())) + .thenReturn(Mono.just(TestClientRegistrations.clientRegistration() + .clientAuthenticationMethod(ClientAuthenticationMethod.NONE).clientSecret(null).build())); OAuth2AuthorizationRequest request = resolve("/oauth2/authorization/registration-id"); - assertThat((String) request.getAttribute(PkceParameterNames.CODE_VERIFIER)).matches("^([a-zA-Z0-9\\-\\.\\_\\~]){128}$"); + assertThat((String) request.getAttribute(PkceParameterNames.CODE_VERIFIER)) + .matches("^([a-zA-Z0-9\\-\\.\\_\\~]){128}$"); - assertThat(request.getAuthorizationRequestUri()).matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=read:user&state=.*?&" + - "redirect_uri=/login/oauth2/code/registration-id&" + - "code_challenge_method=S256&" + - "code_challenge=([a-zA-Z0-9\\-\\.\\_\\~]){43}"); + assertThat(request.getAuthorizationRequestUri()) + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" + + "scope=read:user&state=.*?&" + "redirect_uri=/login/oauth2/code/registration-id&" + + "code_challenge_method=S256&" + "code_challenge=([a-zA-Z0-9\\-\\.\\_\\~]){43}"); } @Test public void resolveWhenAuthenticationRequestWithValidOidcClientThenResolves() { - when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn( - Mono.just(TestClientRegistrations.clientRegistration() - .scope(OidcScopes.OPENID) - .build())); + when(this.clientRegistrationRepository.findByRegistrationId(any())) + .thenReturn(Mono.just(TestClientRegistrations.clientRegistration().scope(OidcScopes.OPENID).build())); OAuth2AuthorizationRequest request = resolve("/oauth2/authorization/registration-id"); assertThat((String) request.getAttribute(OidcParameterNames.NONCE)).matches("^([a-zA-Z0-9\\-\\.\\_\\~]){128}$"); - assertThat(request.getAuthorizationRequestUri()).matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=openid&state=.*?&" + - "redirect_uri=/login/oauth2/code/registration-id&" + - "nonce=([a-zA-Z0-9\\-\\.\\_\\~]){43}"); + assertThat(request.getAuthorizationRequestUri()).matches("https://example.com/login/oauth/authorize\\?" + + "response_type=code&client_id=client-id&" + "scope=openid&state=.*?&" + + "redirect_uri=/login/oauth2/code/registration-id&" + "nonce=([a-zA-Z0-9\\-\\.\\_\\~]){43}"); } // gh-7696 @Test public void resolveWhenAuthorizationRequestCustomizerRemovesNonceThenQueryExcludesNonce() { - when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn( - Mono.just(TestClientRegistrations.clientRegistration() - .scope(OidcScopes.OPENID) - .build())); + when(this.clientRegistrationRepository.findByRegistrationId(any())) + .thenReturn(Mono.just(TestClientRegistrations.clientRegistration().scope(OidcScopes.OPENID).build())); - this.resolver.setAuthorizationRequestCustomizer(customizer -> customizer - .additionalParameters(params -> params.remove(OidcParameterNames.NONCE)) - .attributes(attrs -> attrs.remove(OidcParameterNames.NONCE))); + this.resolver.setAuthorizationRequestCustomizer( + customizer -> customizer.additionalParameters(params -> params.remove(OidcParameterNames.NONCE)) + .attributes(attrs -> attrs.remove(OidcParameterNames.NONCE))); OAuth2AuthorizationRequest authorizationRequest = resolve("/oauth2/authorization/registration-id"); @@ -165,64 +154,49 @@ public class DefaultServerOAuth2AuthorizationRequestResolverTests { assertThat(authorizationRequest.getAttributes()).doesNotContainKey(OidcParameterNames.NONCE); assertThat(authorizationRequest.getAttributes()).containsKey(OAuth2ParameterNames.REGISTRATION_ID); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=openid&state=.{15,}&" + - "redirect_uri=/login/oauth2/code/registration-id"); + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" + + "scope=openid&state=.{15,}&" + "redirect_uri=/login/oauth2/code/registration-id"); } @Test public void resolveWhenAuthorizationRequestCustomizerAddsParameterThenQueryIncludesParameter() { - when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn( - Mono.just(TestClientRegistrations.clientRegistration() - .scope(OidcScopes.OPENID) - .build())); + when(this.clientRegistrationRepository.findByRegistrationId(any())) + .thenReturn(Mono.just(TestClientRegistrations.clientRegistration().scope(OidcScopes.OPENID).build())); - this.resolver.setAuthorizationRequestCustomizer(customizer -> - customizer.authorizationRequestUri(uriBuilder -> { - uriBuilder.queryParam("param1", "value1"); - return uriBuilder.build(); - }) - ); + this.resolver.setAuthorizationRequestCustomizer(customizer -> customizer.authorizationRequestUri(uriBuilder -> { + uriBuilder.queryParam("param1", "value1"); + return uriBuilder.build(); + })); OAuth2AuthorizationRequest authorizationRequest = resolve("/oauth2/authorization/registration-id"); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&client_id=client-id&" + - "scope=openid&state=.{15,}&" + - "redirect_uri=/login/oauth2/code/registration-id&" + - "nonce=([a-zA-Z0-9\\-\\.\\_\\~]){43}&" + - "param1=value1"); + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&client_id=client-id&" + + "scope=openid&state=.{15,}&" + "redirect_uri=/login/oauth2/code/registration-id&" + + "nonce=([a-zA-Z0-9\\-\\.\\_\\~]){43}&" + "param1=value1"); } @Test public void resolveWhenAuthorizationRequestCustomizerOverridesParameterThenQueryIncludesParameter() { - when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn( - Mono.just(TestClientRegistrations.clientRegistration() - .scope(OidcScopes.OPENID) - .build())); + when(this.clientRegistrationRepository.findByRegistrationId(any())) + .thenReturn(Mono.just(TestClientRegistrations.clientRegistration().scope(OidcScopes.OPENID).build())); - this.resolver.setAuthorizationRequestCustomizer(customizer -> - customizer.parameters(params -> { - params.put("appid", params.get("client_id")); - params.remove("client_id"); - }) - ); + this.resolver.setAuthorizationRequestCustomizer(customizer -> customizer.parameters(params -> { + params.put("appid", params.get("client_id")); + params.remove("client_id"); + })); OAuth2AuthorizationRequest authorizationRequest = resolve("/oauth2/authorization/registration-id"); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .matches("https://example.com/login/oauth/authorize\\?" + - "response_type=code&" + - "scope=openid&state=.{15,}&" + - "redirect_uri=/login/oauth2/code/registration-id&" + - "nonce=([a-zA-Z0-9\\-\\.\\_\\~]){43}&" + - "appid=client-id"); + .matches("https://example.com/login/oauth/authorize\\?" + "response_type=code&" + + "scope=openid&state=.{15,}&" + "redirect_uri=/login/oauth2/code/registration-id&" + + "nonce=([a-zA-Z0-9\\-\\.\\_\\~]){43}&" + "appid=client-id"); } private OAuth2AuthorizationRequest resolve(String path) { ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(path)); return this.resolver.resolve(exchange).block(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationCodeGrantWebFilterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationCodeGrantWebFilterTests.java index 1efd84389e..8eefa4b920 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationCodeGrantWebFilterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationCodeGrantWebFilterTests.java @@ -64,63 +64,62 @@ import static org.springframework.security.oauth2.core.endpoint.TestOAuth2Author */ @RunWith(MockitoJUnitRunner.class) public class OAuth2AuthorizationCodeGrantWebFilterTests { + private OAuth2AuthorizationCodeGrantWebFilter filter; + @Mock private ReactiveAuthenticationManager authenticationManager; + @Mock private ReactiveClientRegistrationRepository clientRegistrationRepository; + @Mock private ServerOAuth2AuthorizedClientRepository authorizedClientRepository; + @Mock private ServerAuthorizationRequestRepository authorizationRequestRepository; @Before public void setup() { - this.filter = new OAuth2AuthorizationCodeGrantWebFilter( - this.authenticationManager, this.clientRegistrationRepository, - this.authorizedClientRepository); + this.filter = new OAuth2AuthorizationCodeGrantWebFilter(this.authenticationManager, + this.clientRegistrationRepository, this.authorizedClientRepository); this.filter.setAuthorizationRequestRepository(this.authorizationRequestRepository); } @Test public void constructorWhenAuthenticationManagerNullThenIllegalArgumentException() { this.authenticationManager = null; - assertThatCode(() -> new OAuth2AuthorizationCodeGrantWebFilter( - this.authenticationManager, this.clientRegistrationRepository, - this.authorizedClientRepository)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> new OAuth2AuthorizationCodeGrantWebFilter(this.authenticationManager, + this.clientRegistrationRepository, this.authorizedClientRepository)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void constructorWhenClientRegistrationRepositoryNullThenIllegalArgumentException() { this.clientRegistrationRepository = null; - assertThatCode(() -> new OAuth2AuthorizationCodeGrantWebFilter( - this.authenticationManager, this.clientRegistrationRepository, - this.authorizedClientRepository)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> new OAuth2AuthorizationCodeGrantWebFilter(this.authenticationManager, + this.clientRegistrationRepository, this.authorizedClientRepository)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void constructorWhenAuthorizedClientRepositoryNullThenIllegalArgumentException() { this.authorizedClientRepository = null; - assertThatCode(() -> new OAuth2AuthorizationCodeGrantWebFilter( - this.authenticationManager, this.clientRegistrationRepository, - this.authorizedClientRepository)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> new OAuth2AuthorizationCodeGrantWebFilter(this.authenticationManager, + this.clientRegistrationRepository, this.authorizedClientRepository)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void setRequestCacheWhenRequestCacheIsNullThenThrowIllegalArgumentException() { - assertThatCode(() -> this.filter.setRequestCache(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> this.filter.setRequestCache(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void filterWhenNotMatchThenAuthenticationManagerNotCalled() { - MockServerWebExchange exchange = MockServerWebExchange - .from(MockServerHttpRequest.get("/")); - DefaultWebFilterChain chain = new DefaultWebFilterChain( - e -> e.getResponse().setComplete(), Collections.emptyList()); + MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/")); + DefaultWebFilterChain chain = new DefaultWebFilterChain(e -> e.getResponse().setComplete(), + Collections.emptyList()); this.filter.filter(exchange, chain).block(); @@ -130,41 +129,37 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { @Test public void filterWhenMatchThenAuthorizedClientSaved() { ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); - when(this.clientRegistrationRepository.findByRegistrationId(any())) - .thenReturn(Mono.just(clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(Mono.just(clientRegistration)); - MockServerHttpRequest authorizationRequest = - createAuthorizationRequest("/authorization/callback"); - OAuth2AuthorizationRequest oauth2AuthorizationRequest = - createOAuth2AuthorizationRequest(authorizationRequest, clientRegistration); + MockServerHttpRequest authorizationRequest = createAuthorizationRequest("/authorization/callback"); + OAuth2AuthorizationRequest oauth2AuthorizationRequest = createOAuth2AuthorizationRequest(authorizationRequest, + clientRegistration); when(this.authorizationRequestRepository.loadAuthorizationRequest(any())) .thenReturn(Mono.just(oauth2AuthorizationRequest)); when(this.authorizationRequestRepository.removeAuthorizationRequest(any())) .thenReturn(Mono.just(oauth2AuthorizationRequest)); - when(this.authorizedClientRepository.saveAuthorizedClient(any(), any(), any())) - .thenReturn(Mono.empty()); + when(this.authorizedClientRepository.saveAuthorizedClient(any(), any(), any())).thenReturn(Mono.empty()); when(this.authenticationManager.authenticate(any())) .thenReturn(Mono.just(TestOAuth2AuthorizationCodeAuthenticationTokens.authenticated())); MockServerHttpRequest authorizationResponse = createAuthorizationResponse(authorizationRequest); MockServerWebExchange exchange = MockServerWebExchange.from(authorizationResponse); - DefaultWebFilterChain chain = new DefaultWebFilterChain( - e -> e.getResponse().setComplete(), Collections.emptyList()); + DefaultWebFilterChain chain = new DefaultWebFilterChain(e -> e.getResponse().setComplete(), + Collections.emptyList()); this.filter.filter(exchange, chain).block(); - verify(this.authorizedClientRepository).saveAuthorizedClient(any(), any(AnonymousAuthenticationToken.class), any()); + verify(this.authorizedClientRepository).saveAuthorizedClient(any(), any(AnonymousAuthenticationToken.class), + any()); } // gh-7966 @Test public void filterWhenAuthorizationRequestRedirectUriParametersMatchThenProcessed() { ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); - when(this.clientRegistrationRepository.findByRegistrationId(any())) - .thenReturn(Mono.just(clientRegistration)); - when(this.authorizedClientRepository.saveAuthorizedClient(any(), any(), any())) - .thenReturn(Mono.empty()); + when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(Mono.just(clientRegistration)); + when(this.authorizedClientRepository.saveAuthorizedClient(any(), any(), any())).thenReturn(Mono.empty()); when(this.authenticationManager.authenticate(any())) .thenReturn(Mono.just(TestOAuth2AuthorizationCodeAuthenticationTokens.authenticated())); @@ -172,10 +167,9 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { Map parameters = new LinkedHashMap<>(); parameters.put("param1", "value1"); parameters.put("param2", "value2"); - MockServerHttpRequest authorizationRequest = - createAuthorizationRequest("/authorization/callback", parameters); - OAuth2AuthorizationRequest oauth2AuthorizationRequest = - createOAuth2AuthorizationRequest(authorizationRequest, clientRegistration); + MockServerHttpRequest authorizationRequest = createAuthorizationRequest("/authorization/callback", parameters); + OAuth2AuthorizationRequest oauth2AuthorizationRequest = createOAuth2AuthorizationRequest(authorizationRequest, + clientRegistration); when(this.authorizationRequestRepository.loadAuthorizationRequest(any())) .thenReturn(Mono.just(oauth2AuthorizationRequest)); when(this.authorizationRequestRepository.removeAuthorizationRequest(any())) @@ -183,13 +177,14 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { MockServerHttpRequest authorizationResponse = createAuthorizationResponse(authorizationRequest); MockServerWebExchange exchange = MockServerWebExchange.from(authorizationResponse); - DefaultWebFilterChain chain = new DefaultWebFilterChain( - e -> e.getResponse().setComplete(), Collections.emptyList()); + DefaultWebFilterChain chain = new DefaultWebFilterChain(e -> e.getResponse().setComplete(), + Collections.emptyList()); this.filter.filter(exchange, chain).block(); verify(this.authenticationManager, times(1)).authenticate(any()); - // 2) redirect_uri with query parameters AND authorization response additional parameters + // 2) redirect_uri with query parameters AND authorization response additional + // parameters Map additionalParameters = new LinkedHashMap<>(); additionalParameters.put("auth-param1", "value1"); additionalParameters.put("auth-param2", "value2"); @@ -207,11 +202,10 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { Map parameters = new LinkedHashMap<>(); parameters.put("param1", "value1"); parameters.put("param2", "value2"); - MockServerHttpRequest authorizationRequest = - createAuthorizationRequest(requestUri, parameters); + MockServerHttpRequest authorizationRequest = createAuthorizationRequest(requestUri, parameters); ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); - OAuth2AuthorizationRequest oauth2AuthorizationRequest = - createOAuth2AuthorizationRequest(authorizationRequest, clientRegistration); + OAuth2AuthorizationRequest oauth2AuthorizationRequest = createOAuth2AuthorizationRequest(authorizationRequest, + clientRegistration); when(this.authorizationRequestRepository.loadAuthorizationRequest(any())) .thenReturn(Mono.just(oauth2AuthorizationRequest)); @@ -221,8 +215,8 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { MockServerHttpRequest authorizationResponse = createAuthorizationResponse( createAuthorizationRequest(requestUri, parametersNotMatch)); MockServerWebExchange exchange = MockServerWebExchange.from(authorizationResponse); - DefaultWebFilterChain chain = new DefaultWebFilterChain( - e -> e.getResponse().setComplete(), Collections.emptyList()); + DefaultWebFilterChain chain = new DefaultWebFilterChain(e -> e.getResponse().setComplete(), + Collections.emptyList()); this.filter.filter(exchange, chain).block(); verifyNoInteractions(this.authenticationManager); @@ -231,8 +225,7 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { parametersNotMatch = new LinkedHashMap<>(); parametersNotMatch.put("param2", "value2"); parametersNotMatch.put("param1", "value1"); - authorizationResponse = createAuthorizationResponse( - createAuthorizationRequest(requestUri, parametersNotMatch)); + authorizationResponse = createAuthorizationResponse(createAuthorizationRequest(requestUri, parametersNotMatch)); exchange = MockServerWebExchange.from(authorizationResponse); this.filter.filter(exchange, chain).block(); @@ -241,8 +234,7 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { // 3) Parameter missing parametersNotMatch = new LinkedHashMap<>(parameters); parametersNotMatch.remove("param2"); - authorizationResponse = createAuthorizationResponse( - createAuthorizationRequest(requestUri, parametersNotMatch)); + authorizationResponse = createAuthorizationResponse(createAuthorizationRequest(requestUri, parametersNotMatch)); exchange = MockServerWebExchange.from(authorizationResponse); this.filter.filter(exchange, chain).block(); @@ -252,16 +244,14 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { @Test public void filterWhenAuthorizationSucceedsAndRequestCacheConfiguredThenRequestCacheUsed() { ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); - when(this.clientRegistrationRepository.findByRegistrationId(any())) - .thenReturn(Mono.just(clientRegistration)); - when(this.authorizedClientRepository.saveAuthorizedClient(any(), any(), any())) - .thenReturn(Mono.empty()); + when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(Mono.just(clientRegistration)); + when(this.authorizedClientRepository.saveAuthorizedClient(any(), any(), any())).thenReturn(Mono.empty()); when(this.authenticationManager.authenticate(any())) .thenReturn(Mono.just(TestOAuth2AuthorizationCodeAuthenticationTokens.authenticated())); MockServerHttpRequest authorizationRequest = createAuthorizationRequest("/authorization/callback"); - OAuth2AuthorizationRequest oauth2AuthorizationRequest = - createOAuth2AuthorizationRequest(authorizationRequest, clientRegistration); + OAuth2AuthorizationRequest oauth2AuthorizationRequest = createOAuth2AuthorizationRequest(authorizationRequest, + clientRegistration); when(this.authorizationRequestRepository.loadAuthorizationRequest(any())) .thenReturn(Mono.just(oauth2AuthorizationRequest)); when(this.authorizationRequestRepository.removeAuthorizationRequest(any())) @@ -269,11 +259,12 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { MockServerHttpRequest authorizationResponse = createAuthorizationResponse(authorizationRequest); MockServerWebExchange exchange = MockServerWebExchange.from(authorizationResponse); - DefaultWebFilterChain chain = new DefaultWebFilterChain( - e -> e.getResponse().setComplete(), Collections.emptyList()); + DefaultWebFilterChain chain = new DefaultWebFilterChain(e -> e.getResponse().setComplete(), + Collections.emptyList()); ServerRequestCache requestCache = mock(ServerRequestCache.class); - when(requestCache.getRedirectUri(any(ServerWebExchange.class))).thenReturn(Mono.just(URI.create("/saved-request"))); + when(requestCache.getRedirectUri(any(ServerWebExchange.class))) + .thenReturn(Mono.just(URI.create("/saved-request"))); this.filter.setRequestCache(requestCache); @@ -289,10 +280,9 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(Mono.empty()); - MockServerHttpRequest authorizationRequest = - createAuthorizationRequest("/authorization/callback"); - OAuth2AuthorizationRequest oauth2AuthorizationRequest = - createOAuth2AuthorizationRequest(authorizationRequest, clientRegistration); + MockServerHttpRequest authorizationRequest = createAuthorizationRequest("/authorization/callback"); + OAuth2AuthorizationRequest oauth2AuthorizationRequest = createOAuth2AuthorizationRequest(authorizationRequest, + clientRegistration); when(this.authorizationRequestRepository.loadAuthorizationRequest(any())) .thenReturn(Mono.just(oauth2AuthorizationRequest)); when(this.authorizationRequestRepository.removeAuthorizationRequest(any())) @@ -300,13 +290,12 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { MockServerHttpRequest authorizationResponse = createAuthorizationResponse(authorizationRequest); MockServerWebExchange exchange = MockServerWebExchange.from(authorizationResponse); - DefaultWebFilterChain chain = new DefaultWebFilterChain( - e -> e.getResponse().setComplete(), Collections.emptyList()); + DefaultWebFilterChain chain = new DefaultWebFilterChain(e -> e.getResponse().setComplete(), + Collections.emptyList()); assertThatThrownBy(() -> this.filter.filter(exchange, chain).block()) .isInstanceOf(OAuth2AuthenticationException.class) - .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) - .extracting("errorCode") + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()).extracting("errorCode") .isEqualTo("client_registration_not_found"); verifyNoInteractions(this.authenticationManager); } @@ -315,13 +304,11 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { @Test public void filterWhenAuthenticationManagerThrowsOAuth2AuthorizationExceptionThenMappedToOAuth2AuthenticationException() { ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build(); - when(this.clientRegistrationRepository.findByRegistrationId(any())) - .thenReturn(Mono.just(clientRegistration)); + when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(Mono.just(clientRegistration)); - MockServerHttpRequest authorizationRequest = - createAuthorizationRequest("/authorization/callback"); - OAuth2AuthorizationRequest oauth2AuthorizationRequest = - createOAuth2AuthorizationRequest(authorizationRequest, clientRegistration); + MockServerHttpRequest authorizationRequest = createAuthorizationRequest("/authorization/callback"); + OAuth2AuthorizationRequest oauth2AuthorizationRequest = createOAuth2AuthorizationRequest(authorizationRequest, + clientRegistration); when(this.authorizationRequestRepository.loadAuthorizationRequest(any())) .thenReturn(Mono.just(oauth2AuthorizationRequest)); when(this.authorizationRequestRepository.removeAuthorizationRequest(any())) @@ -332,13 +319,12 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { MockServerHttpRequest authorizationResponse = createAuthorizationResponse(authorizationRequest); MockServerWebExchange exchange = MockServerWebExchange.from(authorizationResponse); - DefaultWebFilterChain chain = new DefaultWebFilterChain( - e -> e.getResponse().setComplete(), Collections.emptyList()); + DefaultWebFilterChain chain = new DefaultWebFilterChain(e -> e.getResponse().setComplete(), + Collections.emptyList()); assertThatThrownBy(() -> this.filter.filter(exchange, chain).block()) .isInstanceOf(OAuth2AuthenticationException.class) - .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) - .extracting("errorCode") + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()).extracting("errorCode") .isEqualTo("authorization_error"); } @@ -346,10 +332,7 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { MockServerHttpRequest authorizationRequest, ClientRegistration registration) { Map attributes = new HashMap<>(); attributes.put(OAuth2ParameterNames.REGISTRATION_ID, registration.getRegistrationId()); - return request() - .attributes(attributes) - .redirectUri(authorizationRequest.getURI().toString()) - .build(); + return request().attributes(attributes).redirectUri(authorizationRequest.getURI().toString()).build(); } private static MockServerHttpRequest createAuthorizationRequest(String requestUri) { @@ -357,8 +340,7 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { } private static MockServerHttpRequest createAuthorizationRequest(String requestUri, Map parameters) { - MockServerHttpRequest.BaseBuilder builder = MockServerHttpRequest - .get(requestUri); + MockServerHttpRequest.BaseBuilder builder = MockServerHttpRequest.get(requestUri); if (!CollectionUtils.isEmpty(parameters)) { parameters.forEach(builder::queryParam); } @@ -369,8 +351,8 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { return createAuthorizationResponse(authorizationRequest, new LinkedHashMap<>()); } - private static MockServerHttpRequest createAuthorizationResponse( - MockServerHttpRequest authorizationRequest, Map additionalParameters) { + private static MockServerHttpRequest createAuthorizationResponse(MockServerHttpRequest authorizationRequest, + Map additionalParameters) { MockServerHttpRequest.BaseBuilder builder = MockServerHttpRequest .get(authorizationRequest.getURI().toString()); builder.queryParam(OAuth2ParameterNames.CODE, "code"); @@ -379,4 +361,5 @@ public class OAuth2AuthorizationCodeGrantWebFilterTests { builder.cookies(authorizationRequest.getCookies()); return builder.build(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilterTests.java index dd5d8443db..6a146fae58 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilterTests.java @@ -48,6 +48,7 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class OAuth2AuthorizationRequestRedirectWebFilterTests { + @Mock private ReactiveClientRegistrationRepository clientRepository; @@ -67,27 +68,25 @@ public class OAuth2AuthorizationRequestRedirectWebFilterTests { public void setup() { this.filter = new OAuth2AuthorizationRequestRedirectWebFilter(this.clientRepository); this.filter.setAuthorizationRequestRepository(this.authzRequestRepository); - FilteringWebHandler webHandler = new FilteringWebHandler(e -> e.getResponse().setComplete(), Arrays.asList(this.filter)); + FilteringWebHandler webHandler = new FilteringWebHandler(e -> e.getResponse().setComplete(), + Arrays.asList(this.filter)); this.client = WebTestClient.bindToWebHandler(webHandler).build(); - when(this.clientRepository.findByRegistrationId(this.registration.getRegistrationId())).thenReturn( - Mono.just(this.registration)); - when(this.authzRequestRepository.saveAuthorizationRequest(any(), any())).thenReturn( - Mono.empty()); + when(this.clientRepository.findByRegistrationId(this.registration.getRegistrationId())) + .thenReturn(Mono.just(this.registration)); + when(this.authzRequestRepository.saveAuthorizationRequest(any(), any())).thenReturn(Mono.empty()); } @Test public void constructorWhenClientRegistrationRepositoryNullThenIllegalArgumentException() { this.clientRepository = null; assertThatThrownBy(() -> new OAuth2AuthorizationRequestRedirectWebFilter(this.clientRepository)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @Test public void filterWhenDoesNotMatchThenClientRegistrationRepositoryNotSubscribed() { - this.client.get() - .exchange() - .expectStatus().isOk(); + this.client.get().exchange().expectStatus().isOk(); verifyZeroInteractions(this.clientRepository, this.authzRequestRepository); } @@ -95,18 +94,13 @@ public class OAuth2AuthorizationRequestRedirectWebFilterTests { @Test public void filterWhenDoesMatchThenClientRegistrationRepositoryNotSubscribed() { FluxExchangeResult result = this.client.get() - .uri("https://example.com/oauth2/authorization/registration-id").exchange() - .expectStatus().is3xxRedirection().returnResult(String.class); + .uri("https://example.com/oauth2/authorization/registration-id").exchange().expectStatus() + .is3xxRedirection().returnResult(String.class); result.assertWithDiagnostics(() -> { URI location = result.getResponseHeaders().getLocation(); - assertThat(location) - .hasScheme("https") - .hasHost("example.com") - .hasPath("/login/oauth/authorize") - .hasParameter("response_type", "code") - .hasParameter("client_id", "client-id") - .hasParameter("scope", "read:user") - .hasParameter("state") + assertThat(location).hasScheme("https").hasHost("example.com").hasPath("/login/oauth/authorize") + .hasParameter("response_type", "code").hasParameter("client_id", "client-id") + .hasParameter("scope", "read:user").hasParameter("state") .hasParameter("redirect_uri", "https://example.com/login/oauth2/code/registration-id"); }); verify(this.authzRequestRepository).saveAuthorizationRequest(any(), any()); @@ -116,32 +110,25 @@ public class OAuth2AuthorizationRequestRedirectWebFilterTests { @Test public void filterWhenDoesMatchThenResolveRedirectUriExpandedExcludesQueryString() { FluxExchangeResult result = this.client.get() - .uri("https://example.com/oauth2/authorization/registration-id?foo=bar").exchange() - .expectStatus().is3xxRedirection().returnResult(String.class); + .uri("https://example.com/oauth2/authorization/registration-id?foo=bar").exchange().expectStatus() + .is3xxRedirection().returnResult(String.class); result.assertWithDiagnostics(() -> { URI location = result.getResponseHeaders().getLocation(); - assertThat(location) - .hasScheme("https") - .hasHost("example.com") - .hasPath("/login/oauth/authorize") - .hasParameter("response_type", "code") - .hasParameter("client_id", "client-id") - .hasParameter("scope", "read:user") - .hasParameter("state") + assertThat(location).hasScheme("https").hasHost("example.com").hasPath("/login/oauth/authorize") + .hasParameter("response_type", "code").hasParameter("client_id", "client-id") + .hasParameter("scope", "read:user").hasParameter("state") .hasParameter("redirect_uri", "https://example.com/login/oauth2/code/registration-id"); }); } @Test public void filterWhenExceptionThenRedirected() { - FilteringWebHandler webHandler = new FilteringWebHandler(e -> Mono.error(new ClientAuthorizationRequiredException(this.registration - .getRegistrationId())), Arrays.asList(this.filter)); + FilteringWebHandler webHandler = new FilteringWebHandler( + e -> Mono.error(new ClientAuthorizationRequiredException(this.registration.getRegistrationId())), + Arrays.asList(this.filter)); this.client = WebTestClient.bindToWebHandler(webHandler).build(); - FluxExchangeResult result = this.client.get() - .uri("https://example.com/foo").exchange() - .expectStatus() - .is3xxRedirection() - .returnResult(String.class); + FluxExchangeResult result = this.client.get().uri("https://example.com/foo").exchange().expectStatus() + .is3xxRedirection().returnResult(String.class); } @Test @@ -152,11 +139,7 @@ public class OAuth2AuthorizationRequestRedirectWebFilterTests { e -> Mono.error(new ClientAuthorizationRequiredException(this.registration.getRegistrationId())), Arrays.asList(this.filter)); this.client = WebTestClient.bindToWebHandler(webHandler).build(); - this.client.get() - .uri("https://example.com/foo") - .exchange() - .expectStatus() - .is3xxRedirection() + this.client.get().uri("https://example.com/foo").exchange().expectStatus().is3xxRedirection() .returnResult(String.class); verify(this.requestCache).saveRequest(any()); } @@ -164,12 +147,9 @@ public class OAuth2AuthorizationRequestRedirectWebFilterTests { @Test public void filterWhenPathMatchesThenRequestSessionAttributeNotSaved() { this.filter.setRequestCache(this.requestCache); - this.client.get() - .uri("https://example.com/oauth2/authorization/registration-id") - .exchange() - .expectStatus() - .is3xxRedirection() - .returnResult(String.class); + this.client.get().uri("https://example.com/oauth2/authorization/registration-id").exchange().expectStatus() + .is3xxRedirection().returnResult(String.class); verifyZeroInteractions(this.requestCache); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests.java index feb4ab5d7c..75e833fa86 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests.java @@ -48,6 +48,7 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests { + @Mock private ReactiveClientRegistrationRepository clientRegistrationRepository; @@ -59,22 +60,14 @@ public class ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests { private ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(this.clientRegistrationId) .redirectUri("{baseUrl}/{action}/oauth2/code/{registrationId}") .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) - .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) - .scope("read:user") + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).scope("read:user") .authorizationUri("https://github.com/login/oauth/authorize") - .tokenUri("https://github.com/login/oauth/access_token") - .userInfoUri("https://api.github.com/user") - .userNameAttributeName("id") - .clientName("GitHub") - .clientId("clientId") - .clientSecret("clientSecret") - .build(); + .tokenUri("https://github.com/login/oauth/access_token").userInfoUri("https://api.github.com/user") + .userNameAttributeName("id").clientName("GitHub").clientId("clientId").clientSecret("clientSecret").build(); private OAuth2AuthorizationRequest.Builder authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri("https://example.com/oauth2/authorize") - .clientId("client-id") - .redirectUri("http://localhost/client-1") - .state("state") + .authorizationUri("https://example.com/oauth2/authorize").clientId("client-id") + .redirectUri("http://localhost/client-1").state("state") .attributes(Collections.singletonMap(OAuth2ParameterNames.REGISTRATION_ID, this.clientRegistrationId)); private final MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/"); @@ -83,7 +76,8 @@ public class ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests { @Before public void setup() { - this.converter = new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter(this.clientRegistrationRepository); + this.converter = new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter( + this.clientRegistrationRepository); this.converter.setAuthorizationRequestRepository(this.authorizationRequestRepository); } @@ -91,35 +85,38 @@ public class ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests { public void applyWhenAuthorizationRequestEmptyThenOAuth2AuthorizationException() { when(this.authorizationRequestRepository.removeAuthorizationRequest(any())).thenReturn(Mono.empty()); - assertThatThrownBy(() -> applyConverter()) - .isInstanceOf(OAuth2AuthorizationException.class); + assertThatThrownBy(() -> applyConverter()).isInstanceOf(OAuth2AuthorizationException.class); } @Test public void applyWhenAttributesMissingThenOAuth2AuthorizationException() { this.authorizationRequest.attributes(Map::clear); - when(this.authorizationRequestRepository.removeAuthorizationRequest(any())).thenReturn(Mono.just(this.authorizationRequest.build())); + when(this.authorizationRequestRepository.removeAuthorizationRequest(any())) + .thenReturn(Mono.just(this.authorizationRequest.build())); - assertThatThrownBy(() -> applyConverter()) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining(ServerOAuth2AuthorizationCodeAuthenticationTokenConverter.CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE); + assertThatThrownBy(() -> applyConverter()).isInstanceOf(OAuth2AuthorizationException.class) + .hasMessageContaining( + ServerOAuth2AuthorizationCodeAuthenticationTokenConverter.CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE); } @Test public void applyWhenClientRegistrationMissingThenOAuth2AuthorizationException() { - when(this.authorizationRequestRepository.removeAuthorizationRequest(any())).thenReturn(Mono.just(this.authorizationRequest.build())); + when(this.authorizationRequestRepository.removeAuthorizationRequest(any())) + .thenReturn(Mono.just(this.authorizationRequest.build())); when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(Mono.empty()); - assertThatThrownBy(() -> applyConverter()) - .isInstanceOf(OAuth2AuthorizationException.class) - .hasMessageContaining(ServerOAuth2AuthorizationCodeAuthenticationTokenConverter.CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE); + assertThatThrownBy(() -> applyConverter()).isInstanceOf(OAuth2AuthorizationException.class) + .hasMessageContaining( + ServerOAuth2AuthorizationCodeAuthenticationTokenConverter.CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE); } @Test public void applyWhenCodeParameterNotFoundThenErrorCode() { this.request.queryParam(OAuth2ParameterNames.ERROR, "error"); - when(this.authorizationRequestRepository.removeAuthorizationRequest(any())).thenReturn(Mono.just(this.authorizationRequest.build())); - when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(Mono.just(this.clientRegistration)); + when(this.authorizationRequestRepository.removeAuthorizationRequest(any())) + .thenReturn(Mono.just(this.authorizationRequest.build())); + when(this.clientRegistrationRepository.findByRegistrationId(any())) + .thenReturn(Mono.just(this.clientRegistration)); assertThat(applyConverter().getAuthorizationExchange().getAuthorizationResponse().getError().getErrorCode()) .isEqualTo("error"); @@ -128,13 +125,14 @@ public class ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests { @Test public void applyWhenCodeParameterFoundThenCode() { this.request.queryParam(OAuth2ParameterNames.CODE, "code"); - when(this.authorizationRequestRepository.removeAuthorizationRequest(any())).thenReturn(Mono.just(this.authorizationRequest.build())); - when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(Mono.just(this.clientRegistration)); + when(this.authorizationRequestRepository.removeAuthorizationRequest(any())) + .thenReturn(Mono.just(this.authorizationRequest.build())); + when(this.clientRegistrationRepository.findByRegistrationId(any())) + .thenReturn(Mono.just(this.clientRegistration)); OAuth2AuthorizationCodeAuthenticationToken result = applyConverter(); - OAuth2AuthorizationResponse exchange = result - .getAuthorizationExchange().getAuthorizationResponse(); + OAuth2AuthorizationResponse exchange = result.getAuthorizationExchange().getAuthorizationResponse(); assertThat(exchange.getError()).isNull(); assertThat(exchange.getCode()).isEqualTo("code"); } @@ -143,4 +141,5 @@ public class ServerOAuth2AuthorizationCodeAuthenticationTokenConverterTests { MockServerWebExchange exchange = MockServerWebExchange.from(this.request); return (OAuth2AuthorizationCodeAuthenticationToken) this.converter.convert(exchange).block(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/UnAuthenticatedServerOAuth2AuthorizedClientRepositoryTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/UnAuthenticatedServerOAuth2AuthorizedClientRepositoryTests.java index 67486bebf1..1a3f6632c9 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/UnAuthenticatedServerOAuth2AuthorizedClientRepositoryTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/UnAuthenticatedServerOAuth2AuthorizedClientRepositoryTests.java @@ -37,8 +37,8 @@ import static org.assertj.core.api.Assertions.*; * @author Rob Winch */ public class UnAuthenticatedServerOAuth2AuthorizedClientRepositoryTests { - private UnAuthenticatedServerOAuth2AuthorizedClientRepository repository = - new UnAuthenticatedServerOAuth2AuthorizedClientRepository(); + + private UnAuthenticatedServerOAuth2AuthorizedClientRepository repository = new UnAuthenticatedServerOAuth2AuthorizedClientRepository(); private ClientRegistration clientRegistration = TestClientRegistrations.clientCredentials().build(); @@ -46,7 +46,8 @@ public class UnAuthenticatedServerOAuth2AuthorizedClientRepositoryTests { private ServerWebExchange exchange; - private Authentication anonymous = new AnonymousAuthenticationToken("key", "anonymous", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); + private Authentication anonymous = new AnonymousAuthenticationToken("key", "anonymous", + AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); private Authentication authentication; @@ -63,47 +64,53 @@ public class UnAuthenticatedServerOAuth2AuthorizedClientRepositoryTests { @Test public void loadAuthorizedClientWhenClientRegistrationIdNullThenIllegalArgumentException() { this.clientRegistrationId = null; - assertThatThrownBy(() -> this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.repository + .loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void loadAuthorizedClientWhenAuthenticationNotNullThenIllegalArgumentException() { this.authentication = new TestingAuthenticationToken("a", "b", "ROLE_USER"); - assertThatThrownBy(() -> this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.repository + .loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void loadAuthorizedClientWhenServerWebExchangeNotNullThenIllegalArgumentException() { this.exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/").build()); - assertThatThrownBy(() -> this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.repository + .loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void loadAuthorizedClientWhenNotFoundThenEmpty() { - assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()).isNull(); + assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange) + .block()).isNull(); } @Test public void loadAuthorizedClientWhenFoundThenFound() { this.repository.saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block(); - assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()).isEqualTo(this.authorizedClient); + assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange) + .block()).isEqualTo(this.authorizedClient); } @Test public void loadAuthorizedClientWhenMultipleThenFound() { ClientRegistration otherClientRegistration = TestClientRegistrations.clientRegistration() - .registrationId("other-client-registration") - .build(); - OAuth2AuthorizedClient otherAuthorizedClient = new OAuth2AuthorizedClient(otherClientRegistration, "anonymousUser", this.authorizedClient.getAccessToken()); + .registrationId("other-client-registration").build(); + OAuth2AuthorizedClient otherAuthorizedClient = new OAuth2AuthorizedClient(otherClientRegistration, + "anonymousUser", this.authorizedClient.getAccessToken()); this.repository.saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block(); this.repository.saveAuthorizedClient(otherAuthorizedClient, this.authentication, this.exchange).block(); - assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()).isEqualTo(this.authorizedClient); + assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange) + .block()).isEqualTo(this.authorizedClient); } @Test @@ -111,7 +118,8 @@ public class UnAuthenticatedServerOAuth2AuthorizedClientRepositoryTests { this.authentication = this.anonymous; this.repository.saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block(); - assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()).isEqualTo(this.authorizedClient); + assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange) + .block()).isEqualTo(this.authorizedClient); } // saveAuthorizedClient @@ -119,22 +127,25 @@ public class UnAuthenticatedServerOAuth2AuthorizedClientRepositoryTests { @Test public void saveAuthorizedClientWhenAuthorizedClientNullThenIllegalArgumentException() { this.authorizedClient = null; - assertThatThrownBy(() -> this.repository.saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block()) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.repository + .saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void saveAuthorizedClientWhenAuthenticationNotNullThenIllegalArgumentException() { this.authentication = new TestingAuthenticationToken("a", "b", "ROLE_USER"); - assertThatThrownBy(() -> this.repository.saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block()) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.repository + .saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void saveAuthorizedClientWhenServerWebExchangeNotNullThenIllegalArgumentException() { this.exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/").build()); - assertThatThrownBy(() -> this.repository.saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block()) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.repository + .saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block()) + .isInstanceOf(IllegalArgumentException.class); } // removeAuthorizedClient @@ -142,22 +153,25 @@ public class UnAuthenticatedServerOAuth2AuthorizedClientRepositoryTests { @Test public void removeAuthorizedClientWhenClientRegistrationIdNullThenIllegalArgumentException() { this.clientRegistrationId = null; - assertThatThrownBy(() -> this.repository.removeAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.repository + .removeAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void removeAuthorizedClientWhenAuthenticationNotNullThenIllegalArgumentException() { this.authentication = new TestingAuthenticationToken("a", "b", "ROLE_USER"); - assertThatThrownBy(() -> this.repository.removeAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.repository + .removeAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void removeAuthorizedClientWhenServerWebExchangeNotNullThenIllegalArgumentException() { this.exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/").build()); - assertThatThrownBy(() -> this.repository.removeAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.repository + .removeAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -165,6 +179,8 @@ public class UnAuthenticatedServerOAuth2AuthorizedClientRepositoryTests { this.repository.saveAuthorizedClient(this.authorizedClient, this.authentication, this.exchange).block(); this.repository.removeAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block(); - assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange).block()).isNull(); + assertThat(this.repository.loadAuthorizedClient(this.clientRegistrationId, this.authentication, this.exchange) + .block()).isNull(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/WebSessionOAuth2ServerAuthorizationRequestRepositoryTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/WebSessionOAuth2ServerAuthorizationRequestRepositoryTests.java index b4e11c05be..1130ee5d3e 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/WebSessionOAuth2ServerAuthorizationRequestRepositoryTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/WebSessionOAuth2ServerAuthorizationRequestRepositoryTests.java @@ -49,61 +49,54 @@ import reactor.test.StepVerifier; */ public class WebSessionOAuth2ServerAuthorizationRequestRepositoryTests { - private WebSessionOAuth2ServerAuthorizationRequestRepository repository = - new WebSessionOAuth2ServerAuthorizationRequestRepository(); + private WebSessionOAuth2ServerAuthorizationRequestRepository repository = new WebSessionOAuth2ServerAuthorizationRequestRepository(); private OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri("https://example.com/oauth2/authorize") - .clientId("client-id") - .redirectUri("http://localhost/client-1") - .state("state") - .build(); + .authorizationUri("https://example.com/oauth2/authorize").clientId("client-id") + .redirectUri("http://localhost/client-1").state("state").build(); - private ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/") - .queryParam(OAuth2ParameterNames.STATE, "state")); + private ServerWebExchange exchange = MockServerWebExchange + .from(MockServerHttpRequest.get("/").queryParam(OAuth2ParameterNames.STATE, "state")); @Test public void loadAuthorizationRequestWhenNullExchangeThenIllegalArgumentException() { this.exchange = null; assertThatThrownBy(() -> this.repository.loadAuthorizationRequest(this.exchange)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @Test public void loadAuthorizationRequestWhenNoSessionThenEmpty() { - StepVerifier.create(this.repository.loadAuthorizationRequest(this.exchange)) - .verifyComplete(); + StepVerifier.create(this.repository.loadAuthorizationRequest(this.exchange)).verifyComplete(); assertSessionStartedIs(false); } @Test public void loadAuthorizationRequestWhenSessionAndNoRequestThenEmpty() { - Mono setAttrThenLoad = this.exchange.getSession() - .map(WebSession::getAttributes).doOnNext(attrs -> attrs.put("foo", "bar")) + Mono setAttrThenLoad = this.exchange.getSession().map(WebSession::getAttributes) + .doOnNext(attrs -> attrs.put("foo", "bar")) .then(this.repository.loadAuthorizationRequest(this.exchange)); - StepVerifier.create(setAttrThenLoad) - .verifyComplete(); + StepVerifier.create(setAttrThenLoad).verifyComplete(); } @Test public void loadAuthorizationRequestWhenNoStateParamThenEmpty() { this.exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/")); - Mono saveAndLoad = this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange) + Mono saveAndLoad = this.repository + .saveAuthorizationRequest(this.authorizationRequest, this.exchange) .then(this.repository.loadAuthorizationRequest(this.exchange)); - StepVerifier.create(saveAndLoad) - .verifyComplete(); + StepVerifier.create(saveAndLoad).verifyComplete(); } @Test public void loadAuthorizationRequestWhenSavedThenAuthorizationRequest() { - Mono saveAndLoad = this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange) + Mono saveAndLoad = this.repository + .saveAuthorizationRequest(this.authorizationRequest, this.exchange) .then(this.repository.loadAuthorizationRequest(this.exchange)); - StepVerifier.create(saveAndLoad) - .expectNext(this.authorizationRequest) - .verifyComplete(); + StepVerifier.create(saveAndLoad).expectNext(this.authorizationRequest).verifyComplete(); } @Test @@ -113,30 +106,25 @@ public class WebSessionOAuth2ServerAuthorizationRequestRepositoryTests { .queryParam(OAuth2ParameterNames.STATE, oldState).build(); OAuth2AuthorizationRequest oldAuthorizationRequest = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri("https://example.com/oauth2/authorize") - .clientId("client-id") - .redirectUri("http://localhost/client-1") - .state(oldState) - .build(); + .authorizationUri("https://example.com/oauth2/authorize").clientId("client-id") + .redirectUri("http://localhost/client-1").state(oldState).build(); WebSessionManager sessionManager = e -> this.exchange.getSession(); - this.exchange = new DefaultServerWebExchange(this.exchange.getRequest(), new MockServerHttpResponse(), sessionManager, - ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); - ServerWebExchange oldExchange = new DefaultServerWebExchange(oldRequest, new MockServerHttpResponse(), sessionManager, - ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); + this.exchange = new DefaultServerWebExchange(this.exchange.getRequest(), new MockServerHttpResponse(), + sessionManager, ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); + ServerWebExchange oldExchange = new DefaultServerWebExchange(oldRequest, new MockServerHttpResponse(), + sessionManager, ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); - Mono saveAndSaveAndLoad = this.repository.saveAuthorizationRequest(oldAuthorizationRequest, oldExchange) + Mono saveAndSaveAndLoad = this.repository + .saveAuthorizationRequest(oldAuthorizationRequest, oldExchange) .then(this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange)) .then(this.repository.loadAuthorizationRequest(oldExchange)); - StepVerifier.create(saveAndSaveAndLoad) - .expectNext(oldAuthorizationRequest) - .verifyComplete(); + StepVerifier.create(saveAndSaveAndLoad).expectNext(oldAuthorizationRequest).verifyComplete(); StepVerifier.create(this.repository.loadAuthorizationRequest(this.exchange)) - .expectNext(this.authorizationRequest) - .verifyComplete(); + .expectNext(this.authorizationRequest).verifyComplete(); } @Test @@ -165,8 +153,7 @@ public class WebSessionOAuth2ServerAuthorizationRequestRepositoryTests { @Test public void removeAuthorizationRequestWhenNotPresentThenThrowsIllegalArgumentException() { - StepVerifier.create(this.repository.removeAuthorizationRequest(this.exchange)) - .verifyComplete(); + StepVerifier.create(this.repository.removeAuthorizationRequest(this.exchange)).verifyComplete(); assertSessionStartedIs(false); } @@ -176,31 +163,23 @@ public class WebSessionOAuth2ServerAuthorizationRequestRepositoryTests { .saveAuthorizationRequest(this.authorizationRequest, this.exchange) .then(this.repository.removeAuthorizationRequest(this.exchange)); - StepVerifier.create(saveAndRemove).expectNext(this.authorizationRequest) - .verifyComplete(); + StepVerifier.create(saveAndRemove).expectNext(this.authorizationRequest).verifyComplete(); - StepVerifier.create(this.exchange.getSession() - .map(WebSession::getAttributes) - .map(Map::isEmpty)) - .expectNext(true) - .verifyComplete(); + StepVerifier.create(this.exchange.getSession().map(WebSession::getAttributes).map(Map::isEmpty)) + .expectNext(true).verifyComplete(); } // gh-5599 @Test public void removeAuthorizationRequestWhenStateMissingThenNoErrors() { MockServerHttpRequest otherState = MockServerHttpRequest.get("/") - .queryParam(OAuth2ParameterNames.STATE, "other") - .build(); - ServerWebExchange otherStateExchange = this.exchange.mutate() - .request(otherState) - .build(); + .queryParam(OAuth2ParameterNames.STATE, "other").build(); + ServerWebExchange otherStateExchange = this.exchange.mutate().request(otherState).build(); Mono saveAndRemove = this.repository .saveAuthorizationRequest(this.authorizationRequest, this.exchange) .then(this.repository.removeAuthorizationRequest(otherStateExchange)); - StepVerifier.create(saveAndRemove) - .verifyComplete(); + StepVerifier.create(saveAndRemove).verifyComplete(); } @Test @@ -210,32 +189,26 @@ public class WebSessionOAuth2ServerAuthorizationRequestRepositoryTests { .queryParam(OAuth2ParameterNames.STATE, oldState).build(); OAuth2AuthorizationRequest oldAuthorizationRequest = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri("https://example.com/oauth2/authorize") - .clientId("client-id") - .redirectUri("http://localhost/client-1") - .state(oldState) - .build(); + .authorizationUri("https://example.com/oauth2/authorize").clientId("client-id") + .redirectUri("http://localhost/client-1").state(oldState).build(); WebSessionManager sessionManager = e -> this.exchange.getSession(); - this.exchange = new DefaultServerWebExchange(this.exchange.getRequest(), new MockServerHttpResponse(), sessionManager, - ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); - ServerWebExchange oldExchange = new DefaultServerWebExchange(oldRequest, new MockServerHttpResponse(), sessionManager, - ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); + this.exchange = new DefaultServerWebExchange(this.exchange.getRequest(), new MockServerHttpResponse(), + sessionManager, ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); + ServerWebExchange oldExchange = new DefaultServerWebExchange(oldRequest, new MockServerHttpResponse(), + sessionManager, ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); - Mono saveAndSaveAndRemove = this.repository.saveAuthorizationRequest(oldAuthorizationRequest, oldExchange) + Mono saveAndSaveAndRemove = this.repository + .saveAuthorizationRequest(oldAuthorizationRequest, oldExchange) .then(this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange)) .then(this.repository.removeAuthorizationRequest(this.exchange)); - StepVerifier.create(saveAndSaveAndRemove) - .expectNext(this.authorizationRequest) - .verifyComplete(); + StepVerifier.create(saveAndSaveAndRemove).expectNext(this.authorizationRequest).verifyComplete(); - StepVerifier.create(this.repository.loadAuthorizationRequest(this.exchange)) - .verifyComplete(); + StepVerifier.create(this.repository.loadAuthorizationRequest(this.exchange)).verifyComplete(); - StepVerifier.create(this.repository.loadAuthorizationRequest(oldExchange)) - .expectNext(oldAuthorizationRequest) + StepVerifier.create(this.repository.loadAuthorizationRequest(oldExchange)).expectNext(oldAuthorizationRequest) .verifyComplete(); } @@ -247,40 +220,34 @@ public class WebSessionOAuth2ServerAuthorizationRequestRepositoryTests { .queryParam(OAuth2ParameterNames.STATE, oldState).build(); OAuth2AuthorizationRequest oldAuthorizationRequest = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri("https://example.com/oauth2/authorize") - .clientId("client-id") - .redirectUri("http://localhost/client-1") - .state(oldState) - .build(); + .authorizationUri("https://example.com/oauth2/authorize").clientId("client-id") + .redirectUri("http://localhost/client-1").state(oldState).build(); Map sessionAttrs = spy(new HashMap<>()); WebSession session = mock(WebSession.class); when(session.getAttributes()).thenReturn(sessionAttrs); WebSessionManager sessionManager = e -> Mono.just(session); - this.exchange = new DefaultServerWebExchange(this.exchange.getRequest(), new MockServerHttpResponse(), sessionManager, - ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); - ServerWebExchange oldExchange = new DefaultServerWebExchange(oldRequest, new MockServerHttpResponse(), sessionManager, - ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); + this.exchange = new DefaultServerWebExchange(this.exchange.getRequest(), new MockServerHttpResponse(), + sessionManager, ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); + ServerWebExchange oldExchange = new DefaultServerWebExchange(oldRequest, new MockServerHttpResponse(), + sessionManager, ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver()); - Mono saveAndSaveAndRemove = this.repository.saveAuthorizationRequest(oldAuthorizationRequest, oldExchange) + Mono saveAndSaveAndRemove = this.repository + .saveAuthorizationRequest(oldAuthorizationRequest, oldExchange) .then(this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange)) .then(this.repository.removeAuthorizationRequest(this.exchange)); - StepVerifier.create(saveAndSaveAndRemove) - .expectNext(this.authorizationRequest) - .verifyComplete(); + StepVerifier.create(saveAndSaveAndRemove).expectNext(this.authorizationRequest).verifyComplete(); - StepVerifier.create(this.repository.loadAuthorizationRequest(this.exchange)) - .verifyComplete(); + StepVerifier.create(this.repository.loadAuthorizationRequest(this.exchange)).verifyComplete(); verify(sessionAttrs, times(3)).put(any(), any()); } private void assertSessionStartedIs(boolean expected) { Mono isStarted = this.exchange.getSession().map(WebSession::isStarted); - StepVerifier.create(isStarted) - .expectNext(expected) - .verifyComplete(); + StepVerifier.create(isStarted).expectNext(expected).verifyComplete(); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/WebSessionServerOAuth2AuthorizedClientRepositoryTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/WebSessionServerOAuth2AuthorizedClientRepositoryTests.java index bc72b2a30a..0b74c0396e 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/WebSessionServerOAuth2AuthorizedClientRepositoryTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/WebSessionServerOAuth2AuthorizedClientRepositoryTests.java @@ -33,8 +33,8 @@ import static org.mockito.Mockito.mock; * @since 5.1 */ public class WebSessionServerOAuth2AuthorizedClientRepositoryTests { - private WebSessionServerOAuth2AuthorizedClientRepository authorizedClientRepository = - new WebSessionServerOAuth2AuthorizedClientRepository(); + + private WebSessionServerOAuth2AuthorizedClientRepository authorizedClientRepository = new WebSessionServerOAuth2AuthorizedClientRepository(); private MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/")); @@ -43,14 +43,16 @@ public class WebSessionServerOAuth2AuthorizedClientRepositoryTests { private ClientRegistration registration2 = TestClientRegistrations.clientRegistration2().build(); private String registrationId1 = this.registration1.getRegistrationId(); - private String registrationId2 = this.registration2.getRegistrationId(); - private String principalName1 = "principalName-1"; + private String registrationId2 = this.registration2.getRegistrationId(); + + private String principalName1 = "principalName-1"; @Test public void loadAuthorizedClientWhenClientRegistrationIdIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.authorizedClientRepository.loadAuthorizedClient(null, null, this.exchange).block()) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> this.authorizedClientRepository.loadAuthorizedClient(null, null, this.exchange).block()) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -60,53 +62,56 @@ public class WebSessionServerOAuth2AuthorizedClientRepositoryTests { @Test public void loadAuthorizedClientWhenRequestIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.authorizedClientRepository.loadAuthorizedClient(this.registrationId1, null, null).block()) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> this.authorizedClientRepository.loadAuthorizedClient(this.registrationId1, null, null).block()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void loadAuthorizedClientWhenClientRegistrationNotFoundThenReturnNull() { - OAuth2AuthorizedClient authorizedClient = - this.authorizedClientRepository.loadAuthorizedClient("registration-not-found", null, this.exchange).block(); + OAuth2AuthorizedClient authorizedClient = this.authorizedClientRepository + .loadAuthorizedClient("registration-not-found", null, this.exchange).block(); assertThat(authorizedClient).isNull(); } @Test public void loadAuthorizedClientWhenSavedThenReturnAuthorizedClient() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration1, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration1, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, this.exchange).block(); - OAuth2AuthorizedClient loadedAuthorizedClient = - this.authorizedClientRepository.loadAuthorizedClient(this.registrationId1, null, this.exchange).block(); + OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientRepository + .loadAuthorizedClient(this.registrationId1, null, this.exchange).block(); assertThat(loadedAuthorizedClient).isEqualTo(authorizedClient); } @Test public void saveAuthorizedClientWhenAuthorizedClientIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.authorizedClientRepository.saveAuthorizedClient(null, null, this.exchange).block()) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> this.authorizedClientRepository.saveAuthorizedClient(null, null, this.exchange).block()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void saveAuthorizedClientWhenAuthenticationIsNullThenExceptionNotThrown() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration2, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration2, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, this.exchange).block(); } @Test public void saveAuthorizedClientWhenRequestIsNullThenThrowIllegalArgumentException() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration2, this.principalName1, mock(OAuth2AccessToken.class)); - assertThatThrownBy(() -> this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, null).block()) - .isInstanceOf(IllegalArgumentException.class); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration2, this.principalName1, + mock(OAuth2AccessToken.class)); + assertThatThrownBy( + () -> this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, null).block()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void saveAuthorizedClientWhenSavedThenSavedToSession() { - OAuth2AuthorizedClient expected = new OAuth2AuthorizedClient( - this.registration2, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient expected = new OAuth2AuthorizedClient(this.registration2, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(expected, null, this.exchange).block(); OAuth2AuthorizedClient result = this.authorizedClientRepository @@ -117,8 +122,8 @@ public class WebSessionServerOAuth2AuthorizedClientRepositoryTests { @Test public void removeAuthorizedClientWhenClientRegistrationIdIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.authorizedClientRepository.removeAuthorizedClient( - null, null, this.exchange)).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> this.authorizedClientRepository.removeAuthorizedClient(null, null, this.exchange)) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -128,59 +133,55 @@ public class WebSessionServerOAuth2AuthorizedClientRepositoryTests { @Test public void removeAuthorizedClientWhenRequestIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> this.authorizedClientRepository.removeAuthorizedClient( - this.registrationId1, null, null)).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy( + () -> this.authorizedClientRepository.removeAuthorizedClient(this.registrationId1, null, null)) + .isInstanceOf(IllegalArgumentException.class); } - @Test public void removeAuthorizedClientWhenNotSavedThenSessionNotCreated() { - this.authorizedClientRepository.removeAuthorizedClient( - this.registrationId2, null, this.exchange); + this.authorizedClientRepository.removeAuthorizedClient(this.registrationId2, null, this.exchange); assertThat(this.exchange.getSession().block().isStarted()).isFalse(); } @Test public void removeAuthorizedClientWhenClient1SavedAndClient2RemovedThenClient1NotRemoved() { - OAuth2AuthorizedClient authorizedClient1 = new OAuth2AuthorizedClient( - this.registration1, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient1 = new OAuth2AuthorizedClient(this.registration1, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient1, null, this.exchange).block(); // Remove registrationId2 (never added so is not removed either) - this.authorizedClientRepository.removeAuthorizedClient( - this.registrationId2, null, this.exchange); + this.authorizedClientRepository.removeAuthorizedClient(this.registrationId2, null, this.exchange); - OAuth2AuthorizedClient loadedAuthorizedClient1 = this.authorizedClientRepository.loadAuthorizedClient( - this.registrationId1, null, this.exchange).block(); + OAuth2AuthorizedClient loadedAuthorizedClient1 = this.authorizedClientRepository + .loadAuthorizedClient(this.registrationId1, null, this.exchange).block(); assertThat(loadedAuthorizedClient1).isNotNull(); assertThat(loadedAuthorizedClient1).isSameAs(authorizedClient1); } @Test public void removeAuthorizedClientWhenSavedThenRemoved() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration2, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration2, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, this.exchange).block(); - OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientRepository.loadAuthorizedClient( - this.registrationId2, null, this.exchange).block(); + OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientRepository + .loadAuthorizedClient(this.registrationId2, null, this.exchange).block(); assertThat(loadedAuthorizedClient).isSameAs(authorizedClient); - this.authorizedClientRepository.removeAuthorizedClient( - this.registrationId2, null, this.exchange).block(); - loadedAuthorizedClient = this.authorizedClientRepository.loadAuthorizedClient( - this.registrationId2, null, this.exchange).block(); + this.authorizedClientRepository.removeAuthorizedClient(this.registrationId2, null, this.exchange).block(); + loadedAuthorizedClient = this.authorizedClientRepository + .loadAuthorizedClient(this.registrationId2, null, this.exchange).block(); assertThat(loadedAuthorizedClient).isNull(); } @Test public void removeAuthorizedClientWhenSavedThenRemovedFromSession() { - OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( - this.registration1, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.registration1, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, null, this.exchange).block(); - OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientRepository.loadAuthorizedClient( - this.registrationId1, null, this.exchange).block(); + OAuth2AuthorizedClient loadedAuthorizedClient = this.authorizedClientRepository + .loadAuthorizedClient(this.registrationId1, null, this.exchange).block(); assertThat(loadedAuthorizedClient).isSameAs(authorizedClient); - this.authorizedClientRepository.removeAuthorizedClient( - this.registrationId1, null, this.exchange).block(); + this.authorizedClientRepository.removeAuthorizedClient(this.registrationId1, null, this.exchange).block(); WebSession session = this.exchange.getSession().block(); assertThat(session).isNotNull(); @@ -189,20 +190,20 @@ public class WebSessionServerOAuth2AuthorizedClientRepositoryTests { @Test public void removeAuthorizedClientWhenClient1Client2SavedAndClient1RemovedThenClient2NotRemoved() { - OAuth2AuthorizedClient authorizedClient1 = new OAuth2AuthorizedClient( - this.registration1, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient1 = new OAuth2AuthorizedClient(this.registration1, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient1, null, this.exchange).block(); - OAuth2AuthorizedClient authorizedClient2 = new OAuth2AuthorizedClient( - this.registration2, this.principalName1, mock(OAuth2AccessToken.class)); + OAuth2AuthorizedClient authorizedClient2 = new OAuth2AuthorizedClient(this.registration2, this.principalName1, + mock(OAuth2AccessToken.class)); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient2, null, this.exchange).block(); - this.authorizedClientRepository.removeAuthorizedClient( - this.registrationId1, null, this.exchange).block(); + this.authorizedClientRepository.removeAuthorizedClient(this.registrationId1, null, this.exchange).block(); - OAuth2AuthorizedClient loadedAuthorizedClient2 = this.authorizedClientRepository.loadAuthorizedClient( - this.registrationId2, null, this.exchange).block(); + OAuth2AuthorizedClient loadedAuthorizedClient2 = this.authorizedClientRepository + .loadAuthorizedClient(this.registrationId2, null, this.exchange).block(); assertThat(loadedAuthorizedClient2).isNotNull(); assertThat(loadedAuthorizedClient2).isSameAs(authorizedClient2); } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/authentication/OAuth2LoginAuthenticationWebFilterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/authentication/OAuth2LoginAuthenticationWebFilterTests.java index ea3c8dd359..ba9ce10a63 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/authentication/OAuth2LoginAuthenticationWebFilterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/authentication/OAuth2LoginAuthenticationWebFilterTests.java @@ -52,28 +52,29 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class OAuth2LoginAuthenticationWebFilterTests { + @Mock private ReactiveAuthenticationManager authenticationManager; + @Mock private ServerOAuth2AuthorizedClientRepository authorizedClientRepository; private OAuth2LoginAuthenticationWebFilter filter; - private WebFilterExchange webFilterExchange; + private WebFilterExchange webFilterExchange; private ClientRegistration.Builder registration = TestClientRegistrations.clientRegistration(); - - private OAuth2AuthorizationResponse.Builder authorizationResponseBldr = OAuth2AuthorizationResponse - .success("code") + private OAuth2AuthorizationResponse.Builder authorizationResponseBldr = OAuth2AuthorizationResponse.success("code") .state("state"); @Before public void setup() { - this.filter = new OAuth2LoginAuthenticationWebFilter(this.authenticationManager, this.authorizedClientRepository); - this.webFilterExchange = new WebFilterExchange(MockServerWebExchange.from(MockServerHttpRequest.get("/")), new DefaultWebFilterChain(exchange -> exchange.getResponse().setComplete())); - when(this.authorizedClientRepository.saveAuthorizedClient(any(), any(), any())) - .thenReturn(Mono.empty()); + this.filter = new OAuth2LoginAuthenticationWebFilter(this.authenticationManager, + this.authorizedClientRepository); + this.webFilterExchange = new WebFilterExchange(MockServerWebExchange.from(MockServerHttpRequest.get("/")), + new DefaultWebFilterChain(exchange -> exchange.getResponse().setComplete())); + when(this.authorizedClientRepository.saveAuthorizedClient(any(), any(), any())).thenReturn(Mono.empty()); } @Test @@ -84,27 +85,21 @@ public class OAuth2LoginAuthenticationWebFilterTests { } private OAuth2LoginAuthenticationToken loginToken() { - OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "token", - Instant.now(), - Instant.now().plus(Duration.ofDays(1)), - Collections.singleton("user")); - DefaultOAuth2User user = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), Collections - .singletonMap("user", "rob"), "user"); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token", + Instant.now(), Instant.now().plus(Duration.ofDays(1)), Collections.singleton("user")); + DefaultOAuth2User user = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), + Collections.singletonMap("user", "rob"), "user"); ClientRegistration clientRegistration = this.registration.build(); - OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest - .authorizationCode() - .state("state") + OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode().state("state") .clientId(clientRegistration.getClientId()) .authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()) - .redirectUri(clientRegistration.getRedirectUri()) - .scopes(clientRegistration.getScopes()) - .build(); + .redirectUri(clientRegistration.getRedirectUri()).scopes(clientRegistration.getScopes()).build(); OAuth2AuthorizationResponse authorizationResponse = this.authorizationResponseBldr - .redirectUri(clientRegistration.getRedirectUri()) - .build(); + .redirectUri(clientRegistration.getRedirectUri()).build(); OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse); - return new OAuth2LoginAuthenticationToken(clientRegistration, authorizationExchange, user, user.getAuthorities(), accessToken); + return new OAuth2LoginAuthenticationToken(clientRegistration, authorizationExchange, user, + user.getAuthorities(), accessToken); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AbstractOAuth2Token.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AbstractOAuth2Token.java index e1dc4d5903..d007bfdcc2 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AbstractOAuth2Token.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AbstractOAuth2Token.java @@ -30,14 +30,17 @@ import java.time.Instant; * @see OAuth2AccessToken */ public abstract class AbstractOAuth2Token implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private final String tokenValue; + private final Instant issuedAt; + private final Instant expiresAt; /** * Sub-class constructor. - * * @param tokenValue the token value */ protected AbstractOAuth2Token(String tokenValue) { @@ -46,10 +49,10 @@ public abstract class AbstractOAuth2Token implements Serializable { /** * Sub-class constructor. - * * @param tokenValue the token value * @param issuedAt the time at which the token was issued, may be null - * @param expiresAt the expiration time on or after which the token MUST NOT be accepted, may be null + * @param expiresAt the expiration time on or after which the token MUST NOT be + * accepted, may be null */ protected AbstractOAuth2Token(String tokenValue, @Nullable Instant issuedAt, @Nullable Instant expiresAt) { Assert.hasText(tokenValue, "tokenValue cannot be empty"); @@ -63,7 +66,6 @@ public abstract class AbstractOAuth2Token implements Serializable { /** * Returns the token value. - * * @return the token value */ public String getTokenValue() { @@ -72,7 +74,6 @@ public abstract class AbstractOAuth2Token implements Serializable { /** * Returns the time at which the token was issued. - * * @return the time the token was issued or null */ public @Nullable Instant getIssuedAt() { @@ -81,7 +82,6 @@ public abstract class AbstractOAuth2Token implements Serializable { /** * Returns the expiration time on or after which the token MUST NOT be accepted. - * * @return the expiration time of the token or null */ public @Nullable Instant getExpiresAt() { @@ -105,7 +105,8 @@ public abstract class AbstractOAuth2Token implements Serializable { if (this.getIssuedAt() != null ? !this.getIssuedAt().equals(that.getIssuedAt()) : that.getIssuedAt() != null) { return false; } - return this.getExpiresAt() != null ? this.getExpiresAt().equals(that.getExpiresAt()) : that.getExpiresAt() == null; + return this.getExpiresAt() != null ? this.getExpiresAt().equals(that.getExpiresAt()) + : that.getExpiresAt() == null; } @Override @@ -115,4 +116,5 @@ public abstract class AbstractOAuth2Token implements Serializable { result = 31 * result + (this.getExpiresAt() != null ? this.getExpiresAt().hashCode() : 0); return result; } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AuthenticationMethod.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AuthenticationMethod.java index 16f7a96c34..ed5882ef02 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AuthenticationMethod.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AuthenticationMethod.java @@ -21,22 +21,28 @@ import org.springframework.security.core.SpringSecurityCoreVersion; import org.springframework.util.Assert; /** - * The authentication method used when sending bearer access tokens in resource requests to resource servers. + * The authentication method used when sending bearer access tokens in resource requests + * to resource servers. * * @author MyeongHyeon Lee * @since 5.1 - * @see Section 2 Authenticated Requests + * @see Section 2 + * Authenticated Requests */ public final class AuthenticationMethod implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + public static final AuthenticationMethod HEADER = new AuthenticationMethod("header"); + public static final AuthenticationMethod FORM = new AuthenticationMethod("form"); + public static final AuthenticationMethod QUERY = new AuthenticationMethod("query"); + private final String value; /** * Constructs an {@code AuthenticationMethod} using the provided value. - * * @param value the value of the authentication method type */ public AuthenticationMethod(String value) { @@ -46,7 +52,6 @@ public final class AuthenticationMethod implements Serializable { /** * Returns the value of the authentication method type. - * * @return the value of the authentication method type */ public String getValue() { @@ -69,4 +74,5 @@ public final class AuthenticationMethod implements Serializable { public int hashCode() { return this.getValue().hashCode(); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AuthorizationGrantType.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AuthorizationGrantType.java index db0b8eb014..1ad5709b83 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AuthorizationGrantType.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/AuthorizationGrantType.java @@ -22,39 +22,46 @@ import java.io.Serializable; /** * An authorization grant is a credential representing the resource owner's authorization - * (to access it's protected resources) to the client and used by the client to obtain an access token. + * (to access it's protected resources) to the client and used by the client to obtain an + * access token. * *

        - * The OAuth 2.0 Authorization Framework defines four standard grant types: - * authorization code, implicit, resource owner password credentials, and client credentials. - * It also provides an extensibility mechanism for defining additional grant types. + * The OAuth 2.0 Authorization Framework defines four standard grant types: authorization + * code, implicit, resource owner password credentials, and client credentials. It also + * provides an extensibility mechanism for defining additional grant types. * * @author Joe Grandja * @since 5.0 - * @see Section 1.3 Authorization Grant + * @see Section + * 1.3 Authorization Grant */ public final class AuthorizationGrantType implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + public static final AuthorizationGrantType AUTHORIZATION_CODE = new AuthorizationGrantType("authorization_code"); /** - * It is not recommended to use the implicit flow - * due to the inherent risks of returning access tokens in an HTTP redirect - * without any confirmation that it has been received by the client. + * It is not recommended to use the implicit flow due to the inherent risks of + * returning access tokens in an HTTP redirect without any confirmation that it has + * been received by the client. * - * @see OAuth 2.0 Implicit Grant + * @see OAuth 2.0 + * Implicit Grant */ @Deprecated public static final AuthorizationGrantType IMPLICIT = new AuthorizationGrantType("implicit"); public static final AuthorizationGrantType REFRESH_TOKEN = new AuthorizationGrantType("refresh_token"); + public static final AuthorizationGrantType CLIENT_CREDENTIALS = new AuthorizationGrantType("client_credentials"); + public static final AuthorizationGrantType PASSWORD = new AuthorizationGrantType("password"); + private final String value; /** * Constructs an {@code AuthorizationGrantType} using the provided value. - * * @param value the value of the authorization grant type */ public AuthorizationGrantType(String value) { @@ -64,7 +71,6 @@ public final class AuthorizationGrantType implements Serializable { /** * Returns the value of the authorization grant type. - * * @return the value of the authorization grant type */ public String getValue() { @@ -87,4 +93,5 @@ public final class AuthorizationGrantType implements Serializable { public int hashCode() { return this.getValue().hashCode(); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java index 33c8e29ced..44295ab3bb 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java @@ -34,14 +34,13 @@ public interface ClaimAccessor { /** * Returns a set of claims that may be used for assertions. - * * @return a {@code Map} of claims */ Map getClaims(); /** - * Returns the claim value as a {@code T} type. - * The claim value is expected to be of type {@code T}. + * Returns the claim value as a {@code T} type. The claim value is expected to be of + * type {@code T}. * * @since 5.2 * @param claim the name of the claim @@ -54,8 +53,8 @@ public interface ClaimAccessor { } /** - * Returns {@code true} if the claim exists in {@link #getClaims()}, otherwise {@code false}. - * + * Returns {@code true} if the claim exists in {@link #getClaims()}, otherwise + * {@code false}. * @param claim the name of the claim * @return {@code true} if the claim exists, otherwise {@code false} */ @@ -65,30 +64,29 @@ public interface ClaimAccessor { } /** - * Returns the claim value as a {@code String} or {@code null} if it does not exist or is equal to {@code null}. - * + * Returns the claim value as a {@code String} or {@code null} if it does not exist or + * is equal to {@code null}. * @param claim the name of the claim - * @return the claim value or {@code null} if it does not exist or is equal to {@code null} + * @return the claim value or {@code null} if it does not exist or is equal to + * {@code null} */ default String getClaimAsString(String claim) { - return !containsClaim(claim) ? null : - ClaimConversionService.getSharedInstance().convert(getClaims().get(claim), String.class); + return !containsClaim(claim) ? null + : ClaimConversionService.getSharedInstance().convert(getClaims().get(claim), String.class); } /** * Returns the claim value as a {@code Boolean} or {@code null} if it does not exist. - * * @param claim the name of the claim * @return the claim value or {@code null} if it does not exist */ default Boolean getClaimAsBoolean(String claim) { - return !containsClaim(claim) ? null : - ClaimConversionService.getSharedInstance().convert(getClaims().get(claim), Boolean.class); + return !containsClaim(claim) ? null + : ClaimConversionService.getSharedInstance().convert(getClaims().get(claim), Boolean.class); } /** * Returns the claim value as an {@code Instant} or {@code null} if it does not exist. - * * @param claim the name of the claim * @return the claim value or {@code null} if it does not exist */ @@ -99,15 +97,14 @@ public interface ClaimAccessor { Object claimValue = getClaims().get(claim); Instant convertedValue = ClaimConversionService.getSharedInstance().convert(claimValue, Instant.class); if (convertedValue == null) { - throw new IllegalArgumentException("Unable to convert claim '" + claim + - "' of type '" + claimValue.getClass() + "' to Instant."); + throw new IllegalArgumentException( + "Unable to convert claim '" + claim + "' of type '" + claimValue.getClass() + "' to Instant."); } return convertedValue; } /** * Returns the claim value as an {@code URL} or {@code null} if it does not exist. - * * @param claim the name of the claim * @return the claim value or {@code null} if it does not exist */ @@ -118,18 +115,18 @@ public interface ClaimAccessor { Object claimValue = getClaims().get(claim); URL convertedValue = ClaimConversionService.getSharedInstance().convert(claimValue, URL.class); if (convertedValue == null) { - throw new IllegalArgumentException("Unable to convert claim '" + claim + - "' of type '" + claimValue.getClass() + "' to URL."); + throw new IllegalArgumentException( + "Unable to convert claim '" + claim + "' of type '" + claimValue.getClass() + "' to URL."); } return convertedValue; } /** - * Returns the claim value as a {@code Map} - * or {@code null} if it does not exist or cannot be assigned to a {@code Map}. - * + * Returns the claim value as a {@code Map} or {@code null} if it does + * not exist or cannot be assigned to a {@code Map}. * @param claim the name of the claim - * @return the claim value or {@code null} if it does not exist or cannot be assigned to a {@code Map} + * @return the claim value or {@code null} if it does not exist or cannot be assigned + * to a {@code Map} */ @SuppressWarnings("unchecked") default Map getClaimAsMap(String claim) { @@ -137,24 +134,24 @@ public interface ClaimAccessor { return null; } final TypeDescriptor sourceDescriptor = TypeDescriptor.valueOf(Object.class); - final TypeDescriptor targetDescriptor = TypeDescriptor.map( - Map.class, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Object.class)); + final TypeDescriptor targetDescriptor = TypeDescriptor.map(Map.class, TypeDescriptor.valueOf(String.class), + TypeDescriptor.valueOf(Object.class)); Object claimValue = getClaims().get(claim); - Map convertedValue = (Map) ClaimConversionService.getSharedInstance().convert( - claimValue, sourceDescriptor, targetDescriptor); + Map convertedValue = (Map) ClaimConversionService.getSharedInstance() + .convert(claimValue, sourceDescriptor, targetDescriptor); if (convertedValue == null) { - throw new IllegalArgumentException("Unable to convert claim '" + claim + - "' of type '" + claimValue.getClass() + "' to Map."); + throw new IllegalArgumentException( + "Unable to convert claim '" + claim + "' of type '" + claimValue.getClass() + "' to Map."); } return convertedValue; } /** - * Returns the claim value as a {@code List} - * or {@code null} if it does not exist or cannot be assigned to a {@code List}. - * + * Returns the claim value as a {@code List} or {@code null} if it does not + * exist or cannot be assigned to a {@code List}. * @param claim the name of the claim - * @return the claim value or {@code null} if it does not exist or cannot be assigned to a {@code List} + * @return the claim value or {@code null} if it does not exist or cannot be assigned + * to a {@code List} */ @SuppressWarnings("unchecked") default List getClaimAsStringList(String claim) { @@ -162,15 +159,16 @@ public interface ClaimAccessor { return null; } final TypeDescriptor sourceDescriptor = TypeDescriptor.valueOf(Object.class); - final TypeDescriptor targetDescriptor = TypeDescriptor.collection( - List.class, TypeDescriptor.valueOf(String.class)); + final TypeDescriptor targetDescriptor = TypeDescriptor.collection(List.class, + TypeDescriptor.valueOf(String.class)); Object claimValue = getClaims().get(claim); - List convertedValue = (List) ClaimConversionService.getSharedInstance().convert( - claimValue, sourceDescriptor, targetDescriptor); + List convertedValue = (List) ClaimConversionService.getSharedInstance().convert(claimValue, + sourceDescriptor, targetDescriptor); if (convertedValue == null) { - throw new IllegalArgumentException("Unable to convert claim '" + claim + - "' of type '" + claimValue.getClass() + "' to List."); + throw new IllegalArgumentException( + "Unable to convert claim '" + claim + "' of type '" + claimValue.getClass() + "' to List."); } return convertedValue; } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClientAuthenticationMethod.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClientAuthenticationMethod.java index 48ecaaa0ca..2f988f68c1 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClientAuthenticationMethod.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClientAuthenticationMethod.java @@ -21,15 +21,20 @@ import org.springframework.util.Assert; import java.io.Serializable; /** - * The authentication method used when authenticating the client with the authorization server. + * The authentication method used when authenticating the client with the authorization + * server. * * @author Joe Grandja * @since 5.0 - * @see Section 2.3 Client Authentication + * @see Section + * 2.3 Client Authentication */ public final class ClientAuthenticationMethod implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + public static final ClientAuthenticationMethod BASIC = new ClientAuthenticationMethod("basic"); + public static final ClientAuthenticationMethod POST = new ClientAuthenticationMethod("post"); /** @@ -41,7 +46,6 @@ public final class ClientAuthenticationMethod implements Serializable { /** * Constructs a {@code ClientAuthenticationMethod} using the provided value. - * * @param value the value of the client authentication method */ public ClientAuthenticationMethod(String value) { @@ -51,7 +55,6 @@ public final class ClientAuthenticationMethod implements Serializable { /** * Returns the value of the client authentication method. - * * @return the value of the client authentication method */ public String getValue() { @@ -74,4 +77,5 @@ public final class ClientAuthenticationMethod implements Serializable { public int hashCode() { return this.getValue().hashCode(); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/DefaultOAuth2AuthenticatedPrincipal.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/DefaultOAuth2AuthenticatedPrincipal.java index 8b8dd8c677..e32052c943 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/DefaultOAuth2AuthenticatedPrincipal.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/DefaultOAuth2AuthenticatedPrincipal.java @@ -34,13 +34,16 @@ import static org.springframework.security.core.authority.AuthorityUtils.NO_AUTH * @since 5.2 */ public final class DefaultOAuth2AuthenticatedPrincipal implements OAuth2AuthenticatedPrincipal, Serializable { + private final Map attributes; + private final Collection authorities; + private final String name; /** - * Constructs an {@code DefaultOAuth2AuthenticatedPrincipal} using the provided parameters. - * + * Constructs an {@code DefaultOAuth2AuthenticatedPrincipal} using the provided + * parameters. * @param attributes the attributes of the OAuth 2.0 token * @param authorities the authorities of the OAuth 2.0 token */ @@ -51,8 +54,8 @@ public final class DefaultOAuth2AuthenticatedPrincipal implements OAuth2Authenti } /** - * Constructs an {@code DefaultOAuth2AuthenticatedPrincipal} using the provided parameters. - * + * Constructs an {@code DefaultOAuth2AuthenticatedPrincipal} using the provided + * parameters. * @param name the name attached to the OAuth 2.0 token * @param attributes the attributes of the OAuth 2.0 token * @param authorities the authorities of the OAuth 2.0 token @@ -62,14 +65,12 @@ public final class DefaultOAuth2AuthenticatedPrincipal implements OAuth2Authenti Assert.notEmpty(attributes, "attributes cannot be empty"); this.attributes = Collections.unmodifiableMap(attributes); - this.authorities = authorities == null ? - NO_AUTHORITIES : Collections.unmodifiableCollection(authorities); + this.authorities = authorities == null ? NO_AUTHORITIES : Collections.unmodifiableCollection(authorities); this.name = name == null ? (String) this.attributes.get("sub") : name; } /** * Gets the attributes of the OAuth 2.0 token in map form. - * * @return a {@link Map} of the attribute's objects keyed by the attribute's names */ public Map getAttributes() { @@ -91,4 +92,5 @@ public final class DefaultOAuth2AuthenticatedPrincipal implements OAuth2Authenti public String getName() { return this.name; } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/DelegatingOAuth2TokenValidator.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/DelegatingOAuth2TokenValidator.java index 785d3cf248..3a37ec669f 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/DelegatingOAuth2TokenValidator.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/DelegatingOAuth2TokenValidator.java @@ -26,19 +26,17 @@ import org.springframework.util.Assert; * A composite validator * * @param the type of {@link AbstractOAuth2Token} this validator validates - * * @author Josh Cummings * @since 5.1 */ -public final class DelegatingOAuth2TokenValidator - implements OAuth2TokenValidator { +public final class DelegatingOAuth2TokenValidator implements OAuth2TokenValidator { private final Collection> tokenValidators; /** * Constructs a {@code DelegatingOAuth2TokenValidator} using the provided validators. - * - * @param tokenValidators the {@link Collection} of {@link OAuth2TokenValidator}s to use + * @param tokenValidators the {@link Collection} of {@link OAuth2TokenValidator}s to + * use */ public DelegatingOAuth2TokenValidator(Collection> tokenValidators) { Assert.notNull(tokenValidators, "tokenValidators cannot be null"); @@ -48,7 +46,6 @@ public final class DelegatingOAuth2TokenValidator /** * Constructs a {@code DelegatingOAuth2TokenValidator} using the provided validators. - * * @param tokenValidators the collection of {@link OAuth2TokenValidator}s to use */ @SafeVarargs @@ -63,10 +60,11 @@ public final class DelegatingOAuth2TokenValidator public OAuth2TokenValidatorResult validate(T token) { Collection errors = new ArrayList<>(); - for ( OAuth2TokenValidator validator : this.tokenValidators) { + for (OAuth2TokenValidator validator : this.tokenValidators) { errors.addAll(validator.validate(token).getErrors()); } return OAuth2TokenValidatorResult.failure(errors); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AccessToken.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AccessToken.java index b2ff587f0d..633696e201 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AccessToken.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AccessToken.java @@ -24,29 +24,33 @@ import java.util.Collections; import java.util.Set; /** - * An implementation of an {@link AbstractOAuth2Token} representing an OAuth 2.0 Access Token. + * An implementation of an {@link AbstractOAuth2Token} representing an OAuth 2.0 Access + * Token. * *

        - * An access token is a credential that represents an authorization - * granted by the resource owner to the client. - * It is primarily used by the client to access protected resources on either a - * resource server or the authorization server that originally issued the access token. + * An access token is a credential that represents an authorization granted by the + * resource owner to the client. It is primarily used by the client to access protected + * resources on either a resource server or the authorization server that originally + * issued the access token. * * @author Joe Grandja * @since 5.0 - * @see Section 1.4 Access Token + * @see Section + * 1.4 Access Token */ public class OAuth2AccessToken extends AbstractOAuth2Token { + private final TokenType tokenType; + private final Set scopes; /** * Constructs an {@code OAuth2AccessToken} using the provided parameters. - * * @param tokenType the token type * @param tokenValue the token value * @param issuedAt the time at which the token was issued - * @param expiresAt the expiration time on or after which the token MUST NOT be accepted + * @param expiresAt the expiration time on or after which the token MUST NOT be + * accepted */ public OAuth2AccessToken(TokenType tokenType, String tokenValue, Instant issuedAt, Instant expiresAt) { this(tokenType, tokenValue, issuedAt, expiresAt, Collections.emptySet()); @@ -54,24 +58,23 @@ public class OAuth2AccessToken extends AbstractOAuth2Token { /** * Constructs an {@code OAuth2AccessToken} using the provided parameters. - * * @param tokenType the token type * @param tokenValue the token value * @param issuedAt the time at which the token was issued - * @param expiresAt the expiration time on or after which the token MUST NOT be accepted + * @param expiresAt the expiration time on or after which the token MUST NOT be + * accepted * @param scopes the scope(s) associated to the token */ - public OAuth2AccessToken(TokenType tokenType, String tokenValue, Instant issuedAt, Instant expiresAt, Set scopes) { + public OAuth2AccessToken(TokenType tokenType, String tokenValue, Instant issuedAt, Instant expiresAt, + Set scopes) { super(tokenValue, issuedAt, expiresAt); Assert.notNull(tokenType, "tokenType cannot be null"); this.tokenType = tokenType; - this.scopes = Collections.unmodifiableSet( - scopes != null ? scopes : Collections.emptySet()); + this.scopes = Collections.unmodifiableSet(scopes != null ? scopes : Collections.emptySet()); } /** * Returns the {@link TokenType token type}. - * * @return the {@link TokenType} */ public TokenType getTokenType() { @@ -80,7 +83,6 @@ public class OAuth2AccessToken extends AbstractOAuth2Token { /** * Returns the scope(s) associated to the token. - * * @return the scope(s) associated to the token */ public Set getScopes() { @@ -90,11 +92,16 @@ public class OAuth2AccessToken extends AbstractOAuth2Token { /** * Access Token Types. * - * @see Section 7.1 Access Token Types + * @see Section 7.1 Access Token + * Types */ public static final class TokenType implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + public static final TokenType BEARER = new TokenType("Bearer"); + private final String value; private TokenType(String value) { @@ -104,7 +111,6 @@ public class OAuth2AccessToken extends AbstractOAuth2Token { /** * Returns the value of the token type. - * * @return the value of the token type */ public String getValue() { @@ -127,5 +133,7 @@ public class OAuth2AccessToken extends AbstractOAuth2Token { public int hashCode() { return this.getValue().hashCode(); } + } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthenticatedPrincipal.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthenticatedPrincipal.java index b3329d2f77..f056aba43d 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthenticatedPrincipal.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthenticatedPrincipal.java @@ -24,16 +24,16 @@ import org.springframework.security.core.AuthenticatedPrincipal; import org.springframework.security.core.GrantedAuthority; /** - * An {@link AuthenticatedPrincipal} that represents the principal - * associated with an OAuth 2.0 token. + * An {@link AuthenticatedPrincipal} that represents the principal associated with an + * OAuth 2.0 token. * * @author Josh Cummings * @since 5.2 */ public interface OAuth2AuthenticatedPrincipal extends AuthenticatedPrincipal { + /** * Get the OAuth 2.0 token attribute by name - * * @param name the name of the attribute * @param the type of the attribute * @return the attribute or {@code null} otherwise @@ -45,15 +45,13 @@ public interface OAuth2AuthenticatedPrincipal extends AuthenticatedPrincipal { /** * Get the OAuth 2.0 token attributes - * * @return the OAuth 2.0 token attributes */ Map getAttributes(); /** - * Get the {@link Collection} of {@link GrantedAuthority}s associated - * with this OAuth 2.0 token - * + * Get the {@link Collection} of {@link GrantedAuthority}s associated with this OAuth + * 2.0 token * @return the OAuth 2.0 token authorities */ Collection getAuthorities(); diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthenticationException.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthenticationException.java index 0f9383181b..7feff6c666 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthenticationException.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthenticationException.java @@ -25,24 +25,25 @@ import org.springframework.util.Assert; *

        * There are a number of scenarios where an error may occur, for example: *

        * * @author Joe Grandja * @since 5.0 */ public class OAuth2AuthenticationException extends AuthenticationException { + private OAuth2Error error; /** * Constructs an {@code OAuth2AuthenticationException} using the provided parameters. - * * @param error the {@link OAuth2Error OAuth 2.0 Error} */ public OAuth2AuthenticationException(OAuth2Error error) { @@ -51,7 +52,6 @@ public class OAuth2AuthenticationException extends AuthenticationException { /** * Constructs an {@code OAuth2AuthenticationException} using the provided parameters. - * * @param error the {@link OAuth2Error OAuth 2.0 Error} * @param cause the root cause */ @@ -61,7 +61,6 @@ public class OAuth2AuthenticationException extends AuthenticationException { /** * Constructs an {@code OAuth2AuthenticationException} using the provided parameters. - * * @param error the {@link OAuth2Error OAuth 2.0 Error} * @param message the detail message */ @@ -72,7 +71,6 @@ public class OAuth2AuthenticationException extends AuthenticationException { /** * Constructs an {@code OAuth2AuthenticationException} using the provided parameters. - * * @param error the {@link OAuth2Error OAuth 2.0 Error} * @param message the detail message * @param cause the root cause @@ -84,7 +82,6 @@ public class OAuth2AuthenticationException extends AuthenticationException { /** * Returns the {@link OAuth2Error OAuth 2.0 Error}. - * * @return the {@link OAuth2Error} */ public OAuth2Error getError() { @@ -95,4 +92,5 @@ public class OAuth2AuthenticationException extends AuthenticationException { Assert.notNull(error, "error cannot be null"); this.error = error; } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthorizationException.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthorizationException.java index a894c6d6eb..5902a048a4 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthorizationException.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthorizationException.java @@ -24,11 +24,11 @@ import org.springframework.util.Assert; * @since 5.1 */ public class OAuth2AuthorizationException extends RuntimeException { + private OAuth2Error error; /** * Constructs an {@code OAuth2AuthorizationException} using the provided parameters. - * * @param error the {@link OAuth2Error OAuth 2.0 Error} */ public OAuth2AuthorizationException(OAuth2Error error) { @@ -37,7 +37,6 @@ public class OAuth2AuthorizationException extends RuntimeException { /** * Constructs an {@code OAuth2AuthorizationException} using the provided parameters. - * * @param error the {@link OAuth2Error OAuth 2.0 Error} * @param message the exception message * @since 5.3 @@ -50,7 +49,6 @@ public class OAuth2AuthorizationException extends RuntimeException { /** * Constructs an {@code OAuth2AuthorizationException} using the provided parameters. - * * @param error the {@link OAuth2Error OAuth 2.0 Error} * @param cause the root cause */ @@ -60,7 +58,6 @@ public class OAuth2AuthorizationException extends RuntimeException { /** * Constructs an {@code OAuth2AuthorizationException} using the provided parameters. - * * @param error the {@link OAuth2Error OAuth 2.0 Error} * @param message the exception message * @param cause the root cause @@ -74,10 +71,10 @@ public class OAuth2AuthorizationException extends RuntimeException { /** * Returns the {@link OAuth2Error OAuth 2.0 Error}. - * * @return the {@link OAuth2Error} */ public OAuth2Error getError() { return this.error; } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2Error.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2Error.java index 22d306a01b..032afe23f7 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2Error.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2Error.java @@ -24,25 +24,29 @@ import java.io.Serializable; * A representation of an OAuth 2.0 Error. * *

        - * At a minimum, an error response will contain an error code. - * The error code may be one of the standard codes defined by the specification, - * or a new code defined in the OAuth Extensions Error Registry, - * for cases where protocol extensions require additional error code(s) above the standard codes. + * At a minimum, an error response will contain an error code. The error code may be one + * of the standard codes defined by the specification, or a new code defined in the OAuth + * Extensions Error Registry, for cases where protocol extensions require additional error + * code(s) above the standard codes. * * @author Joe Grandja * @since 5.0 * @see OAuth2ErrorCodes - * @see Section 11.4 OAuth Extensions Error Registry + * @see Section + * 11.4 OAuth Extensions Error Registry */ public class OAuth2Error implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private final String errorCode; + private final String description; + private final String uri; /** * Constructs an {@code OAuth2Error} using the provided parameters. - * * @param errorCode the error code */ public OAuth2Error(String errorCode) { @@ -51,7 +55,6 @@ public class OAuth2Error implements Serializable { /** * Constructs an {@code OAuth2Error} using the provided parameters. - * * @param errorCode the error code * @param description the error description * @param uri the error uri @@ -65,7 +68,6 @@ public class OAuth2Error implements Serializable { /** * Returns the error code. - * * @return the error code */ public final String getErrorCode() { @@ -74,7 +76,6 @@ public class OAuth2Error implements Serializable { /** * Returns the error description. - * * @return the error description */ public final String getDescription() { @@ -83,7 +84,6 @@ public class OAuth2Error implements Serializable { /** * Returns the error uri. - * * @return the error uri */ public final String getUri() { @@ -92,7 +92,7 @@ public class OAuth2Error implements Serializable { @Override public String toString() { - return "[" + this.getErrorCode() + "] " + - (this.getDescription() != null ? this.getDescription() : ""); + return "[" + this.getErrorCode() + "] " + (this.getDescription() != null ? this.getDescription() : ""); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2ErrorCodes.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2ErrorCodes.java index 7a8f7a1677..11045ead48 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2ErrorCodes.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2ErrorCodes.java @@ -24,20 +24,21 @@ package org.springframework.security.oauth2.core; public interface OAuth2ErrorCodes { /** - * {@code invalid_request} - The request is missing a required parameter, - * includes an invalid parameter value, - * includes a parameter more than once, or is otherwise malformed. + * {@code invalid_request} - The request is missing a required parameter, includes an + * invalid parameter value, includes a parameter more than once, or is otherwise + * malformed. */ String INVALID_REQUEST = "invalid_request"; /** - * {@code unauthorized_client} - The client is not authorized to request - * an authorization code or access token using this method. + * {@code unauthorized_client} - The client is not authorized to request an + * authorization code or access token using this method. */ String UNAUTHORIZED_CLIENT = "unauthorized_client"; /** - * {@code access_denied} - The resource owner or authorization server denied the request. + * {@code access_denied} - The resource owner or authorization server denied the + * request. */ String ACCESS_DENIED = "access_denied"; @@ -54,62 +55,66 @@ public interface OAuth2ErrorCodes { String INVALID_SCOPE = "invalid_scope"; /** - * {@code insufficient_scope} - The request requires higher privileges than - * provided by the access token. - * The resource server SHOULD respond with the HTTP 403 (Forbidden) - * status code and MAY include the "scope" attribute with the scope - * necessary to access the protected resource. + * {@code insufficient_scope} - The request requires higher privileges than provided + * by the access token. The resource server SHOULD respond with the HTTP 403 + * (Forbidden) status code and MAY include the "scope" attribute with the scope + * necessary to access the protected resource. * - * @see RFC-6750 - Section 3.1 - Error Codes + * @see RFC-6750 - Section + * 3.1 - Error Codes */ String INSUFFICIENT_SCOPE = "insufficient_scope"; /** - * {@code invalid_token} - The access token provided is expired, revoked, - * malformed, or invalid for other reasons. - * The resource SHOULD respond with the HTTP 401 (Unauthorized) status code. - * The client MAY request a new access token and retry the protected resource request. + * {@code invalid_token} - The access token provided is expired, revoked, malformed, + * or invalid for other reasons. The resource SHOULD respond with the HTTP 401 + * (Unauthorized) status code. The client MAY request a new access token and retry the + * protected resource request. * - * @see RFC-6750 - Section 3.1 - Error Codes + * @see RFC-6750 - Section + * 3.1 - Error Codes */ String INVALID_TOKEN = "invalid_token"; /** - * {@code server_error} - The authorization server encountered an - * unexpected condition that prevented it from fulfilling the request. - * (This error code is needed because a 500 Internal Server Error HTTP status code - * cannot be returned to the client via a HTTP redirect.) + * {@code server_error} - The authorization server encountered an unexpected condition + * that prevented it from fulfilling the request. (This error code is needed because a + * 500 Internal Server Error HTTP status code cannot be returned to the client via a + * HTTP redirect.) */ String SERVER_ERROR = "server_error"; /** - * {@code temporarily_unavailable} - The authorization server is currently unable - * to handle the request due to a temporary overloading or maintenance of the server. + * {@code temporarily_unavailable} - The authorization server is currently unable to + * handle the request due to a temporary overloading or maintenance of the server. * (This error code is needed because a 503 Service Unavailable HTTP status code * cannot be returned to the client via an HTTP redirect.) */ String TEMPORARILY_UNAVAILABLE = "temporarily_unavailable"; /** - * {@code invalid_client} - Client authentication failed (e.g., unknown client, - * no client authentication included, or unsupported authentication method). - * The authorization server MAY return a HTTP 401 (Unauthorized) status code - * to indicate which HTTP authentication schemes are supported. - * If the client attempted to authenticate via the "Authorization" request header field, - * the authorization server MUST respond with a HTTP 401 (Unauthorized) status code and - * include the "WWW-Authenticate" response header field matching the authentication scheme used by the client. + * {@code invalid_client} - Client authentication failed (e.g., unknown client, no + * client authentication included, or unsupported authentication method). The + * authorization server MAY return a HTTP 401 (Unauthorized) status code to indicate + * which HTTP authentication schemes are supported. If the client attempted to + * authenticate via the "Authorization" request header field, the + * authorization server MUST respond with a HTTP 401 (Unauthorized) status code and + * include the "WWW-Authenticate" response header field matching the + * authentication scheme used by the client. */ String INVALID_CLIENT = "invalid_client"; /** - * {@code invalid_grant} - The provided authorization grant - * (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, - * does not match the redirection URI used in the authorization request, or was issued to another client. + * {@code invalid_grant} - The provided authorization grant (e.g., authorization code, + * resource owner credentials) or refresh token is invalid, expired, revoked, does not + * match the redirection URI used in the authorization request, or was issued to + * another client. */ String INVALID_GRANT = "invalid_grant"; /** - * {@code unsupported_grant_type} - The authorization grant type is not supported by the authorization server. + * {@code unsupported_grant_type} - The authorization grant type is not supported by + * the authorization server. */ String UNSUPPORTED_GRANT_TYPE = "unsupported_grant_type"; diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2RefreshToken.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2RefreshToken.java index e52f364399..71e2df1770 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2RefreshToken.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2RefreshToken.java @@ -18,28 +18,30 @@ package org.springframework.security.oauth2.core; import java.time.Instant; /** - * An implementation of an {@link AbstractOAuth2Token} representing an OAuth 2.0 Refresh Token. + * An implementation of an {@link AbstractOAuth2Token} representing an OAuth 2.0 Refresh + * Token. * *

        - * A refresh token is a credential that represents an authorization - * granted by the resource owner to the client. - * It is used by the client to obtain a new access token when the current access token - * becomes invalid or expires, or to obtain additional access tokens with identical or narrower scope. + * A refresh token is a credential that represents an authorization granted by the + * resource owner to the client. It is used by the client to obtain a new access token + * when the current access token becomes invalid or expires, or to obtain additional + * access tokens with identical or narrower scope. * * @author Joe Grandja * @since 5.1 * @see OAuth2AccessToken - * @see Section 1.5 Refresh Token + * @see Section + * 1.5 Refresh Token */ public class OAuth2RefreshToken extends AbstractOAuth2Token { /** * Constructs an {@code OAuth2RefreshToken} using the provided parameters. - * * @param tokenValue the token value * @param issuedAt the time at which the token was issued */ public OAuth2RefreshToken(String tokenValue, Instant issuedAt) { super(tokenValue, issuedAt, null); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenValidator.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenValidator.java index 95cd5153df..48270aac54 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenValidator.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenValidator.java @@ -16,8 +16,8 @@ package org.springframework.security.oauth2.core; /** - * Implementations of this interface are responsible for "verifying" - * the validity and/or constraints of the attributes contained in an OAuth 2.0 Token. + * Implementations of this interface are responsible for "verifying" the + * validity and/or constraints of the attributes contained in an OAuth 2.0 Token. * * @author Joe Grandja * @author Josh Cummings @@ -28,9 +28,9 @@ public interface OAuth2TokenValidator { /** * Verify the validity and/or constraints of the provided OAuth 2.0 Token. - * * @param token an OAuth 2.0 token * @return OAuth2TokenValidationResult the success or failure detail of the validation */ OAuth2TokenValidatorResult validate(T token); + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenValidatorResult.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenValidatorResult.java index 0922360aef..4a7b4bc1cc 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenValidatorResult.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenValidatorResult.java @@ -30,6 +30,7 @@ import org.springframework.util.Assert; * @since 5.1 */ public final class OAuth2TokenValidatorResult { + static final OAuth2TokenValidatorResult NO_ERRORS = new OAuth2TokenValidatorResult(Collections.emptyList()); private final Collection errors; @@ -41,7 +42,6 @@ public final class OAuth2TokenValidatorResult { /** * Say whether this result indicates success - * * @return whether this result has errors */ public boolean hasErrors() { @@ -50,8 +50,8 @@ public final class OAuth2TokenValidatorResult { /** * Return error details regarding the validation attempt - * - * @return the collection of results in this result, if any; returns an empty list otherwise + * @return the collection of results in this result, if any; returns an empty list + * otherwise */ public Collection getErrors() { return this.errors; @@ -59,7 +59,6 @@ public final class OAuth2TokenValidatorResult { /** * Construct a successful {@link OAuth2TokenValidatorResult} - * * @return an {@link OAuth2TokenValidatorResult} with no errors */ public static OAuth2TokenValidatorResult success() { @@ -68,7 +67,6 @@ public final class OAuth2TokenValidatorResult { /** * Construct a failure {@link OAuth2TokenValidatorResult} with the provided detail - * * @param errors the list of errors * @return an {@link OAuth2TokenValidatorResult} with the errors specified */ @@ -78,7 +76,6 @@ public final class OAuth2TokenValidatorResult { /** * Construct a failure {@link OAuth2TokenValidatorResult} with the provided detail - * * @param errors the list of errors * @return an {@link OAuth2TokenValidatorResult} with the errors specified */ @@ -89,4 +86,5 @@ public final class OAuth2TokenValidatorResult { return new OAuth2TokenValidatorResult(errors); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ClaimConversionService.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ClaimConversionService.java index a871537534..21939b0933 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ClaimConversionService.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ClaimConversionService.java @@ -21,8 +21,8 @@ import org.springframework.core.convert.support.GenericConversionService; import org.springframework.security.oauth2.core.ClaimAccessor; /** - * A {@link ConversionService} configured with converters - * that provide type conversion for claim values. + * A {@link ConversionService} configured with converters that provide type conversion for + * claim values. * * @author Joe Grandja * @since 5.2 @@ -30,6 +30,7 @@ import org.springframework.security.oauth2.core.ClaimAccessor; * @see ClaimAccessor */ public final class ClaimConversionService extends GenericConversionService { + private static volatile ClaimConversionService sharedInstance; private ClaimConversionService() { @@ -38,7 +39,6 @@ public final class ClaimConversionService extends GenericConversionService { /** * Returns a shared instance of {@code ClaimConversionService}. - * * @return a shared instance of {@code ClaimConversionService} */ public static ClaimConversionService getSharedInstance() { @@ -56,9 +56,8 @@ public final class ClaimConversionService extends GenericConversionService { } /** - * Adds the converters that provide type conversion for claim values - * to the provided {@link ConverterRegistry}. - * + * Adds the converters that provide type conversion for claim values to the provided + * {@link ConverterRegistry}. * @param converterRegistry the registry of converters to add to */ public static void addConverters(ConverterRegistry converterRegistry) { @@ -69,4 +68,5 @@ public final class ClaimConversionService extends GenericConversionService { converterRegistry.addConverter(new ObjectToListStringConverter()); converterRegistry.addConverter(new ObjectToMapStringObjectConverter()); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverter.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverter.java index 098cb86a01..44d88c4fb4 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverter.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverter.java @@ -32,12 +32,13 @@ import java.util.Map; * @see Converter */ public final class ClaimTypeConverter implements Converter, Map> { + private final Map> claimTypeConverters; /** * Constructs a {@code ClaimTypeConverter} using the provided parameters. - * - * @param claimTypeConverters a {@link Map} of {@link Converter}(s) keyed by claim name + * @param claimTypeConverters a {@link Map} of {@link Converter}(s) keyed by claim + * name */ public ClaimTypeConverter(Map> claimTypeConverters) { Assert.notEmpty(claimTypeConverters, "claimTypeConverters cannot be empty"); @@ -64,4 +65,5 @@ public final class ClaimTypeConverter implements Converter, return result; } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToBooleanConverter.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToBooleanConverter.java index 82c2243308..10d21f0fda 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToBooleanConverter.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToBooleanConverter.java @@ -42,4 +42,5 @@ final class ObjectToBooleanConverter implements GenericConverter { } return Boolean.valueOf(source.toString()); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToInstantConverter.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToInstantConverter.java index 65ddaae9d5..c86edb8b9c 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToInstantConverter.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToInstantConverter.java @@ -50,14 +50,17 @@ final class ObjectToInstantConverter implements GenericConverter { } try { return Instant.ofEpochSecond(Long.parseLong(source.toString())); - } catch (Exception ex) { + } + catch (Exception ex) { // Ignore } try { return Instant.parse(source.toString()); - } catch (Exception ex) { + } + catch (Exception ex) { // Ignore } return null; } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToListStringConverter.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToListStringConverter.java index daba913f25..cbc13b7a47 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToListStringConverter.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToListStringConverter.java @@ -42,10 +42,9 @@ final class ObjectToListStringConverter implements ConditionalGenericConverter { @Override public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { - if (targetType.getElementTypeDescriptor() == null || - targetType.getElementTypeDescriptor().getType().equals(String.class) || - sourceType == null || - ClassUtils.isAssignable(sourceType.getType(), targetType.getElementTypeDescriptor().getType())) { + if (targetType.getElementTypeDescriptor() == null + || targetType.getElementTypeDescriptor().getType().equals(String.class) || sourceType == null + || ClassUtils.isAssignable(sourceType.getType(), targetType.getElementTypeDescriptor().getType())) { return true; } return false; @@ -73,4 +72,5 @@ final class ObjectToListStringConverter implements ConditionalGenericConverter { } return Collections.singletonList(source.toString()); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToMapStringObjectConverter.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToMapStringObjectConverter.java index 6db09f9cf1..0ba486c558 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToMapStringObjectConverter.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToMapStringObjectConverter.java @@ -36,8 +36,8 @@ final class ObjectToMapStringObjectConverter implements ConditionalGenericConver @Override public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { - if (targetType.getElementTypeDescriptor() == null || - targetType.getMapKeyTypeDescriptor().getType().equals(String.class)) { + if (targetType.getElementTypeDescriptor() == null + || targetType.getMapKeyTypeDescriptor().getType().equals(String.class)) { return true; } return false; @@ -59,4 +59,5 @@ final class ObjectToMapStringObjectConverter implements ConditionalGenericConver sourceMap.forEach((k, v) -> result.put(k.toString(), v)); return result; } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToStringConverter.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToStringConverter.java index 8a73b71e74..1f843f3646 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToStringConverter.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToStringConverter.java @@ -36,4 +36,5 @@ final class ObjectToStringConverter implements GenericConverter { public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { return source == null ? null : source.toString(); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToURLConverter.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToURLConverter.java index f24020a378..483a31b2fb 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToURLConverter.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/converter/ObjectToURLConverter.java @@ -44,9 +44,11 @@ final class ObjectToURLConverter implements GenericConverter { } try { return new URI(source.toString()).toURL(); - } catch (Exception ex) { + } + catch (Exception ex) { // Ignore } return null; } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/MapOAuth2AccessTokenResponseConverter.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/MapOAuth2AccessTokenResponseConverter.java index 3cc3aa0ede..b11e904ad0 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/MapOAuth2AccessTokenResponseConverter.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/MapOAuth2AccessTokenResponseConverter.java @@ -27,29 +27,27 @@ import org.springframework.security.oauth2.core.OAuth2AccessToken; import org.springframework.util.StringUtils; /** - * A {@link Converter} that converts the provided - * OAuth 2.0 Access Token Response parameters to an {@link OAuth2AccessTokenResponse}. + * A {@link Converter} that converts the provided OAuth 2.0 Access Token Response + * parameters to an {@link OAuth2AccessTokenResponse}. * * @author Joe Grandja * @author Nikita Konev * @since 5.3 */ -public final class MapOAuth2AccessTokenResponseConverter implements Converter, OAuth2AccessTokenResponse> { - private static final Set TOKEN_RESPONSE_PARAMETER_NAMES = new HashSet<>(Arrays.asList( - OAuth2ParameterNames.ACCESS_TOKEN, - OAuth2ParameterNames.EXPIRES_IN, - OAuth2ParameterNames.REFRESH_TOKEN, - OAuth2ParameterNames.SCOPE, - OAuth2ParameterNames.TOKEN_TYPE - )); +public final class MapOAuth2AccessTokenResponseConverter + implements Converter, OAuth2AccessTokenResponse> { + + private static final Set TOKEN_RESPONSE_PARAMETER_NAMES = new HashSet<>( + Arrays.asList(OAuth2ParameterNames.ACCESS_TOKEN, OAuth2ParameterNames.EXPIRES_IN, + OAuth2ParameterNames.REFRESH_TOKEN, OAuth2ParameterNames.SCOPE, OAuth2ParameterNames.TOKEN_TYPE)); @Override public OAuth2AccessTokenResponse convert(Map tokenResponseParameters) { String accessToken = tokenResponseParameters.get(OAuth2ParameterNames.ACCESS_TOKEN); OAuth2AccessToken.TokenType accessTokenType = null; - if (OAuth2AccessToken.TokenType.BEARER.getValue().equalsIgnoreCase( - tokenResponseParameters.get(OAuth2ParameterNames.TOKEN_TYPE))) { + if (OAuth2AccessToken.TokenType.BEARER.getValue() + .equalsIgnoreCase(tokenResponseParameters.get(OAuth2ParameterNames.TOKEN_TYPE))) { accessTokenType = OAuth2AccessToken.TokenType.BEARER; } @@ -57,7 +55,8 @@ public final class MapOAuth2AccessTokenResponseConverter implements ConverterSection 5.1 Access Token Response + * @see Section + * 5.1 Access Token Response */ public final class OAuth2AccessTokenResponse { + private OAuth2AccessToken accessToken; + private OAuth2RefreshToken refreshToken; + private Map additionalParameters; private OAuth2AccessTokenResponse() { @@ -45,7 +49,6 @@ public final class OAuth2AccessTokenResponse { /** * Returns the {@link OAuth2AccessToken Access Token}. - * * @return the {@link OAuth2AccessToken} */ public OAuth2AccessToken getAccessToken() { @@ -64,8 +67,8 @@ public final class OAuth2AccessTokenResponse { /** * Returns the additional parameters returned in the response. - * - * @return a {@code Map} of the additional parameters returned in the response, may be empty. + * @return a {@code Map} of the additional parameters returned in the response, may be + * empty. */ public Map getAdditionalParameters() { return this.additionalParameters; @@ -73,7 +76,6 @@ public final class OAuth2AccessTokenResponse { /** * Returns a new {@link Builder}, initialized with the provided access token value. - * * @param tokenValue the value of the access token * @return the {@link Builder} */ @@ -83,7 +85,6 @@ public final class OAuth2AccessTokenResponse { /** * Returns a new {@link Builder}, initialized with the provided response. - * * @param response the response to initialize the builder with * @return the {@link Builder} */ @@ -95,13 +96,21 @@ public final class OAuth2AccessTokenResponse { * A builder for {@link OAuth2AccessTokenResponse}. */ public static class Builder { + private String tokenValue; + private OAuth2AccessToken.TokenType tokenType; + private Instant issuedAt; + private Instant expiresAt; + private long expiresIn; + private Set scopes; + private String refreshToken; + private Map additionalParameters; private Builder(OAuth2AccessTokenResponse response) { @@ -111,8 +120,7 @@ public final class OAuth2AccessTokenResponse { this.issuedAt = accessToken.getIssuedAt(); this.expiresAt = accessToken.getExpiresAt(); this.scopes = accessToken.getScopes(); - this.refreshToken = response.getRefreshToken() == null ? - null : response.getRefreshToken().getTokenValue(); + this.refreshToken = response.getRefreshToken() == null ? null : response.getRefreshToken().getTokenValue(); this.additionalParameters = response.getAdditionalParameters(); } @@ -122,7 +130,6 @@ public final class OAuth2AccessTokenResponse { /** * Sets the {@link OAuth2AccessToken.TokenType token type}. - * * @param tokenType the type of token issued * @return the {@link Builder} */ @@ -133,7 +140,6 @@ public final class OAuth2AccessTokenResponse { /** * Sets the lifetime (in seconds) of the access token. - * * @param expiresIn the lifetime of the access token, in seconds. * @return the {@link Builder} */ @@ -145,7 +151,6 @@ public final class OAuth2AccessTokenResponse { /** * Sets the scope(s) associated to the access token. - * * @param scopes the scope(s) associated to the access token. * @return the {@link Builder} */ @@ -156,7 +161,6 @@ public final class OAuth2AccessTokenResponse { /** * Sets the refresh token associated to the access token. - * * @param refreshToken the refresh token associated to the access token. * @return the {@link Builder} */ @@ -167,7 +171,6 @@ public final class OAuth2AccessTokenResponse { /** * Sets the additional parameters returned in the response. - * * @param additionalParameters the additional parameters returned in the response * @return the {@link Builder} */ @@ -178,7 +181,6 @@ public final class OAuth2AccessTokenResponse { /** * Builds a new {@link OAuth2AccessTokenResponse}. - * * @return a {@link OAuth2AccessTokenResponse} */ public OAuth2AccessTokenResponse build() { @@ -186,13 +188,14 @@ public final class OAuth2AccessTokenResponse { Instant expiresAt = getExpiresAt(); OAuth2AccessTokenResponse accessTokenResponse = new OAuth2AccessTokenResponse(); - accessTokenResponse.accessToken = new OAuth2AccessToken( - this.tokenType, this.tokenValue, issuedAt, expiresAt, this.scopes); + accessTokenResponse.accessToken = new OAuth2AccessToken(this.tokenType, this.tokenValue, issuedAt, + expiresAt, this.scopes); if (StringUtils.hasText(this.refreshToken)) { accessTokenResponse.refreshToken = new OAuth2RefreshToken(this.refreshToken, issuedAt); } - accessTokenResponse.additionalParameters = Collections.unmodifiableMap( - CollectionUtils.isEmpty(this.additionalParameters) ? Collections.emptyMap() : this.additionalParameters); + accessTokenResponse.additionalParameters = Collections + .unmodifiableMap(CollectionUtils.isEmpty(this.additionalParameters) ? Collections.emptyMap() + : this.additionalParameters); return accessTokenResponse; } @@ -204,19 +207,21 @@ public final class OAuth2AccessTokenResponse { } /** - * expires_in is RECOMMENDED, as per spec https://tools.ietf.org/html/rfc6749#section-5.1 - * Therefore, expires_in may not be returned in the Access Token response which would result in the default value of 0. - * For these instances, default the expiresAt to +1 second from issuedAt time. + * expires_in is RECOMMENDED, as per spec + * https://tools.ietf.org/html/rfc6749#section-5.1 Therefore, expires_in may not + * be returned in the Access Token response which would result in the default + * value of 0. For these instances, default the expiresAt to +1 second from + * issuedAt time. * @return */ private Instant getExpiresAt() { if (this.expiresAt == null) { Instant issuedAt = getIssuedAt(); - this.expiresAt = this.expiresIn > 0 ? - issuedAt.plusSeconds(this.expiresIn) : - issuedAt.plusSeconds(1); + this.expiresAt = this.expiresIn > 0 ? issuedAt.plusSeconds(this.expiresIn) : issuedAt.plusSeconds(1); } return this.expiresAt; } + } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseMapConverter.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseMapConverter.java index cc023ee4ce..c9aefa2d4e 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseMapConverter.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseMapConverter.java @@ -25,14 +25,15 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; /** - * A {@link Converter} that converts the provided {@link OAuth2AccessTokenResponse} - * to a {@code Map} representation of the OAuth 2.0 Access Token Response parameters. + * A {@link Converter} that converts the provided {@link OAuth2AccessTokenResponse} to a + * {@code Map} representation of the OAuth 2.0 Access Token Response parameters. * * @author Joe Grandja * @author Nikita Konev * @since 5.3 */ -public final class OAuth2AccessTokenResponseMapConverter implements Converter> { +public final class OAuth2AccessTokenResponseMapConverter + implements Converter> { @Override public Map convert(OAuth2AccessTokenResponse tokenResponse) { @@ -61,4 +62,5 @@ public final class OAuth2AccessTokenResponseMapConverter implements ConverterSection 4.1.1 Authorization Code Grant Request - * @see Section 4.2.1 Implicit Grant Request + * @see Section 4.1.1 Authorization Code + * Grant Request + * @see Section 4.2.1 Implicit Grant + * Request */ public final class OAuth2AuthorizationRequest implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private String authorizationUri; + private AuthorizationGrantType authorizationGrantType; + private OAuth2AuthorizationResponseType responseType; + private String clientId; + private String redirectUri; + private Set scopes; + private String state; + private Map additionalParameters; + private String authorizationRequestUri; + private Map attributes; private OAuth2AuthorizationRequest() { @@ -67,7 +82,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Returns the uri for the authorization endpoint. - * * @return the uri for the authorization endpoint */ public String getAuthorizationUri() { @@ -76,7 +90,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Returns the {@link AuthorizationGrantType grant type}. - * * @return the {@link AuthorizationGrantType} */ public AuthorizationGrantType getGrantType() { @@ -85,7 +98,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Returns the {@link OAuth2AuthorizationResponseType response type}. - * * @return the {@link OAuth2AuthorizationResponseType} */ public OAuth2AuthorizationResponseType getResponseType() { @@ -94,7 +106,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Returns the client identifier. - * * @return the client identifier */ public String getClientId() { @@ -103,7 +114,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Returns the uri for the redirection endpoint. - * * @return the uri for the redirection endpoint */ public String getRedirectUri() { @@ -112,7 +122,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Returns the scope(s). - * * @return the scope(s), or an empty {@code Set} if not available */ public Set getScopes() { @@ -121,7 +130,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Returns the state. - * * @return the state */ public String getState() { @@ -130,8 +138,8 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Returns the additional parameter(s) used in the request. - * - * @return a {@code Map} of the additional parameter(s), or an empty {@code Map} if not available + * @return a {@code Map} of the additional parameter(s), or an empty {@code Map} if + * not available */ public Map getAdditionalParameters() { return this.additionalParameters; @@ -153,7 +161,8 @@ public final class OAuth2AuthorizationRequest implements Serializable { * @since 5.2 * @param name the name of the attribute * @param the type of the attribute - * @return the value of the attribute associated to the request, or {@code null} if not available + * @return the value of the attribute associated to the request, or {@code null} if + * not available */ @SuppressWarnings("unchecked") public T getAttribute(String name) { @@ -161,14 +170,16 @@ public final class OAuth2AuthorizationRequest implements Serializable { } /** - * Returns the {@code URI} string representation of the OAuth 2.0 Authorization Request. + * Returns the {@code URI} string representation of the OAuth 2.0 Authorization + * Request. * *

        * NOTE: The {@code URI} string is encoded in the * {@code application/x-www-form-urlencoded} MIME format. * * @since 5.1 - * @return the {@code URI} string representation of the OAuth 2.0 Authorization Request + * @return the {@code URI} string representation of the OAuth 2.0 Authorization + * Request */ public String getAuthorizationRequestUri() { return this.authorizationRequestUri; @@ -176,7 +187,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Returns a new {@link Builder}, initialized with the authorization code grant type. - * * @return the {@link Builder} */ public static Builder authorizationCode() { @@ -185,11 +195,11 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Returns a new {@link Builder}, initialized with the implicit grant type. - * - * @deprecated It is not recommended to use the implicit flow - * due to the inherent risks of returning access tokens in an HTTP redirect - * without any confirmation that it has been received by the client. - * @see OAuth 2.0 Implicit Grant + * @deprecated It is not recommended to use the implicit flow due to the inherent + * risks of returning access tokens in an HTTP redirect without any confirmation that + * it has been received by the client. + * @see OAuth 2.0 + * Implicit Grant * @return the {@link Builder} */ @Deprecated @@ -198,11 +208,12 @@ public final class OAuth2AuthorizationRequest implements Serializable { } /** - * Returns a new {@link Builder}, initialized with the values - * from the provided {@code authorizationRequest}. + * Returns a new {@link Builder}, initialized with the values from the provided + * {@code authorizationRequest}. * * @since 5.1 - * @param authorizationRequest the authorization request used for initializing the {@link Builder} + * @param authorizationRequest the authorization request used for initializing the + * {@link Builder} * @return the {@link Builder} */ public static Builder from(OAuth2AuthorizationRequest authorizationRequest) { @@ -210,10 +221,8 @@ public final class OAuth2AuthorizationRequest implements Serializable { return new Builder(authorizationRequest.getGrantType()) .authorizationUri(authorizationRequest.getAuthorizationUri()) - .clientId(authorizationRequest.getClientId()) - .redirectUri(authorizationRequest.getRedirectUri()) - .scopes(authorizationRequest.getScopes()) - .state(authorizationRequest.getState()) + .clientId(authorizationRequest.getClientId()).redirectUri(authorizationRequest.getRedirectUri()) + .scopes(authorizationRequest.getScopes()).state(authorizationRequest.getState()) .additionalParameters(authorizationRequest.getAdditionalParameters()) .attributes(authorizationRequest.getAttributes()); } @@ -222,18 +231,32 @@ public final class OAuth2AuthorizationRequest implements Serializable { * A builder for {@link OAuth2AuthorizationRequest}. */ public static class Builder { + private String authorizationUri; + private AuthorizationGrantType authorizationGrantType; + private OAuth2AuthorizationResponseType responseType; + private String clientId; + private String redirectUri; + private Set scopes; + private String state; + private Map additionalParameters = new LinkedHashMap<>(); - private Consumer> parametersConsumer = params -> {}; + + private Consumer> parametersConsumer = params -> { + }; + private Map attributes = new LinkedHashMap<>(); + private String authorizationRequestUri; + private Function authorizationRequestUriFunction = builder -> builder.build(); + private final DefaultUriBuilderFactory uriBuilderFactory; private Builder(AuthorizationGrantType authorizationGrantType) { @@ -241,18 +264,19 @@ public final class OAuth2AuthorizationRequest implements Serializable { this.authorizationGrantType = authorizationGrantType; if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(authorizationGrantType)) { this.responseType = OAuth2AuthorizationResponseType.CODE; - } else if (AuthorizationGrantType.IMPLICIT.equals(authorizationGrantType)) { + } + else if (AuthorizationGrantType.IMPLICIT.equals(authorizationGrantType)) { this.responseType = OAuth2AuthorizationResponseType.TOKEN; } this.uriBuilderFactory = new DefaultUriBuilderFactory(); // The supplied authorizationUri may contain encoded parameters - // so disable encoding in UriBuilder and instead apply encoding within this builder + // so disable encoding in UriBuilder and instead apply encoding within this + // builder this.uriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE); } /** * Sets the uri for the authorization endpoint. - * * @param authorizationUri the uri for the authorization endpoint * @return the {@link Builder} */ @@ -263,7 +287,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Sets the client identifier. - * * @param clientId the client identifier * @return the {@link Builder} */ @@ -274,7 +297,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Sets the uri for the redirection endpoint. - * * @param redirectUri the uri for the redirection endpoint * @return the {@link Builder} */ @@ -285,7 +307,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Sets the scope(s). - * * @param scope the scope(s) * @return the {@link Builder} */ @@ -298,7 +319,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Sets the scope(s). - * * @param scopes the scope(s) * @return the {@link Builder} */ @@ -309,7 +329,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Sets the state. - * * @param state the state * @return the {@link Builder} */ @@ -320,7 +339,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Sets the additional parameter(s) used in the request. - * * @param additionalParameters the additional parameter(s) used in the request * @return the {@link Builder} */ @@ -336,7 +354,8 @@ public final class OAuth2AuthorizationRequest implements Serializable { * allowing the ability to add, replace, or remove. * * @since 5.3 - * @param additionalParametersConsumer a {@code Consumer} of the additional parameters + * @param additionalParametersConsumer a {@code Consumer} of the additional + * parameters */ public Builder additionalParameters(Consumer> additionalParametersConsumer) { if (additionalParametersConsumer != null) { @@ -346,8 +365,8 @@ public final class OAuth2AuthorizationRequest implements Serializable { } /** - * A {@code Consumer} to be provided access to all the parameters - * allowing the ability to add, replace, or remove. + * A {@code Consumer} to be provided access to all the parameters allowing the + * ability to add, replace, or remove. * * @since 5.3 * @param parametersConsumer a {@code Consumer} of all the parameters @@ -374,8 +393,8 @@ public final class OAuth2AuthorizationRequest implements Serializable { } /** - * A {@code Consumer} to be provided access to the attribute(s) - * allowing the ability to add, replace, or remove. + * A {@code Consumer} to be provided access to the attribute(s) allowing the + * ability to add, replace, or remove. * * @since 5.3 * @param attributesConsumer a {@code Consumer} of the attribute(s) @@ -388,14 +407,16 @@ public final class OAuth2AuthorizationRequest implements Serializable { } /** - * Sets the {@code URI} string representation of the OAuth 2.0 Authorization Request. + * Sets the {@code URI} string representation of the OAuth 2.0 Authorization + * Request. * *

        * NOTE: The {@code URI} string is required to be encoded in the * {@code application/x-www-form-urlencoded} MIME format. * * @since 5.1 - * @param authorizationRequestUri the {@code URI} string representation of the OAuth 2.0 Authorization Request + * @param authorizationRequestUri the {@code URI} string representation of the + * OAuth 2.0 Authorization Request * @return the {@link Builder} */ public Builder authorizationRequestUri(String authorizationRequestUri) { @@ -404,11 +425,12 @@ public final class OAuth2AuthorizationRequest implements Serializable { } /** - * A {@code Function} to be provided a {@code UriBuilder} representation - * of the OAuth 2.0 Authorization Request allowing for further customizations. + * A {@code Function} to be provided a {@code UriBuilder} representation of the + * OAuth 2.0 Authorization Request allowing for further customizations. * * @since 5.3 - * @param authorizationRequestUriFunction a {@code Function} to be provided a {@code UriBuilder} representation of the OAuth 2.0 Authorization Request + * @param authorizationRequestUriFunction a {@code Function} to be provided a + * {@code UriBuilder} representation of the OAuth 2.0 Authorization Request */ public Builder authorizationRequestUri(Function authorizationRequestUriFunction) { if (authorizationRequestUriFunction != null) { @@ -419,7 +441,6 @@ public final class OAuth2AuthorizationRequest implements Serializable { /** * Builds a new {@link OAuth2AuthorizationRequest}. - * * @return a {@link OAuth2AuthorizationRequest} */ public OAuth2AuthorizationRequest build() { @@ -437,25 +458,21 @@ public final class OAuth2AuthorizationRequest implements Serializable { authorizationRequest.redirectUri = this.redirectUri; authorizationRequest.state = this.state; authorizationRequest.scopes = Collections.unmodifiableSet( - CollectionUtils.isEmpty(this.scopes) ? - Collections.emptySet() : new LinkedHashSet<>(this.scopes)); + CollectionUtils.isEmpty(this.scopes) ? Collections.emptySet() : new LinkedHashSet<>(this.scopes)); authorizationRequest.additionalParameters = Collections.unmodifiableMap(this.additionalParameters); authorizationRequest.attributes = Collections.unmodifiableMap(this.attributes); - authorizationRequest.authorizationRequestUri = - StringUtils.hasText(this.authorizationRequestUri) ? - this.authorizationRequestUri : this.buildAuthorizationRequestUri(); + authorizationRequest.authorizationRequestUri = StringUtils.hasText(this.authorizationRequestUri) + ? this.authorizationRequestUri : this.buildAuthorizationRequestUri(); return authorizationRequest; } private String buildAuthorizationRequestUri() { - Map parameters = getParameters(); // Not encoded + Map parameters = getParameters(); // Not encoded this.parametersConsumer.accept(parameters); MultiValueMap queryParams = new LinkedMultiValueMap<>(); - parameters.forEach((k, v) -> queryParams.set( - encodeQueryParam(k), encodeQueryParam(String.valueOf(v)))); // Encoded - UriBuilder uriBuilder = this.uriBuilderFactory.uriString(this.authorizationUri) - .queryParams(queryParams); + parameters.forEach((k, v) -> queryParams.set(encodeQueryParam(k), encodeQueryParam(String.valueOf(v)))); // Encoded + UriBuilder uriBuilder = this.uriBuilderFactory.uriString(this.authorizationUri).queryParams(queryParams); return this.authorizationRequestUriFunction.apply(uriBuilder).toString(); } @@ -464,8 +481,7 @@ public final class OAuth2AuthorizationRequest implements Serializable { parameters.put(OAuth2ParameterNames.RESPONSE_TYPE, this.responseType.getValue()); parameters.put(OAuth2ParameterNames.CLIENT_ID, this.clientId); if (!CollectionUtils.isEmpty(this.scopes)) { - parameters.put(OAuth2ParameterNames.SCOPE, - StringUtils.collectionToDelimitedString(this.scopes, " ")); + parameters.put(OAuth2ParameterNames.SCOPE, StringUtils.collectionToDelimitedString(this.scopes, " ")); } if (this.state != null) { parameters.put(OAuth2ParameterNames.STATE, this.state); @@ -481,5 +497,7 @@ public final class OAuth2AuthorizationRequest implements Serializable { private static String encodeQueryParam(String value) { return UriUtils.encodeQueryParam(value, StandardCharsets.UTF_8); } + } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponse.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponse.java index 1e34de0ac4..a43785e4b2 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponse.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponse.java @@ -20,17 +20,24 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * A representation of an OAuth 2.0 Authorization Response for the authorization code grant type. + * A representation of an OAuth 2.0 Authorization Response for the authorization code + * grant type. * * @author Joe Grandja * @since 5.0 * @see OAuth2Error - * @see Section 4.1.2 Authorization Response + * @see Section 4.1.2 Authorization + * Response */ public final class OAuth2AuthorizationResponse { + private String redirectUri; + private String state; + private String code; + private OAuth2Error error; private OAuth2AuthorizationResponse() { @@ -38,7 +45,6 @@ public final class OAuth2AuthorizationResponse { /** * Returns the uri where the response was redirected to. - * * @return the uri where the response was redirected to */ public String getRedirectUri() { @@ -47,7 +53,6 @@ public final class OAuth2AuthorizationResponse { /** * Returns the state. - * * @return the state */ public String getState() { @@ -56,7 +61,6 @@ public final class OAuth2AuthorizationResponse { /** * Returns the authorization code. - * * @return the authorization code */ public String getCode() { @@ -64,18 +68,20 @@ public final class OAuth2AuthorizationResponse { } /** - * Returns the {@link OAuth2Error OAuth 2.0 Error} if the Authorization Request failed, otherwise {@code null}. - * - * @return the {@link OAuth2Error} if the Authorization Request failed, otherwise {@code null} + * Returns the {@link OAuth2Error OAuth 2.0 Error} if the Authorization Request + * failed, otherwise {@code null}. + * @return the {@link OAuth2Error} if the Authorization Request failed, otherwise + * {@code null} */ public OAuth2Error getError() { return this.error; } /** - * Returns {@code true} if the Authorization Request succeeded, otherwise {@code false}. - * - * @return {@code true} if the Authorization Request succeeded, otherwise {@code false} + * Returns {@code true} if the Authorization Request succeeded, otherwise + * {@code false}. + * @return {@code true} if the Authorization Request succeeded, otherwise + * {@code false} */ public boolean statusOk() { return !this.statusError(); @@ -83,7 +89,6 @@ public final class OAuth2AuthorizationResponse { /** * Returns {@code true} if the Authorization Request failed, otherwise {@code false}. - * * @return {@code true} if the Authorization Request failed, otherwise {@code false} */ public boolean statusError() { @@ -92,7 +97,6 @@ public final class OAuth2AuthorizationResponse { /** * Returns a new {@link Builder}, initialized with the authorization code. - * * @param code the authorization code * @return the {@link Builder} */ @@ -103,7 +107,6 @@ public final class OAuth2AuthorizationResponse { /** * Returns a new {@link Builder}, initialized with the error code. - * * @param errorCode the error code * @return the {@link Builder} */ @@ -116,11 +119,17 @@ public final class OAuth2AuthorizationResponse { * A builder for {@link OAuth2AuthorizationResponse}. */ public static class Builder { + private String redirectUri; + private String state; + private String code; + private String errorCode; + private String errorDescription; + private String errorUri; private Builder() { @@ -128,7 +137,6 @@ public final class OAuth2AuthorizationResponse { /** * Sets the uri where the response was redirected to. - * * @param redirectUri the uri where the response was redirected to * @return the {@link Builder} */ @@ -139,7 +147,6 @@ public final class OAuth2AuthorizationResponse { /** * Sets the state. - * * @param state the state * @return the {@link Builder} */ @@ -150,7 +157,6 @@ public final class OAuth2AuthorizationResponse { /** * Sets the authorization code. - * * @param code the authorization code * @return the {@link Builder} */ @@ -161,7 +167,6 @@ public final class OAuth2AuthorizationResponse { /** * Sets the error code. - * * @param errorCode the error code * @return the {@link Builder} */ @@ -172,7 +177,6 @@ public final class OAuth2AuthorizationResponse { /** * Sets the error description. - * * @param errorDescription the error description * @return the {@link Builder} */ @@ -183,7 +187,6 @@ public final class OAuth2AuthorizationResponse { /** * Sets the error uri. - * * @param errorUri the error uri * @return the {@link Builder} */ @@ -194,7 +197,6 @@ public final class OAuth2AuthorizationResponse { /** * Builds a new {@link OAuth2AuthorizationResponse}. - * * @return a {@link OAuth2AuthorizationResponse} */ public OAuth2AuthorizationResponse build() { @@ -208,11 +210,13 @@ public final class OAuth2AuthorizationResponse { authorizationResponse.state = this.state; if (StringUtils.hasText(this.code)) { authorizationResponse.code = this.code; - } else { - authorizationResponse.error = new OAuth2Error( - this.errorCode, this.errorDescription, this.errorUri); + } + else { + authorizationResponse.error = new OAuth2Error(this.errorCode, this.errorDescription, this.errorUri); } return authorizationResponse; } + } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseType.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseType.java index ffcdb4329c..70d6b0976e 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseType.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseType.java @@ -21,22 +21,29 @@ import org.springframework.util.Assert; import java.io.Serializable; /** - * The {@code response_type} parameter is consumed by the authorization endpoint which - * is used by the authorization code grant type and implicit grant type. - * The client sets the {@code response_type} parameter with the desired grant type before initiating the authorization request. + * The {@code response_type} parameter is consumed by the authorization endpoint which is + * used by the authorization code grant type and implicit grant type. The client sets the + * {@code response_type} parameter with the desired grant type before initiating the + * authorization request. * *

        - * The {@code response_type} parameter value may be one of "code" for requesting an authorization code or - * "token" for requesting an access token (implicit grant). - + * The {@code response_type} parameter value may be one of "code" for requesting + * an authorization code or "token" for requesting an access token (implicit + * grant). + * * @author Joe Grandja * @since 5.0 - * @see Section 3.1.1 Response Type + * @see Section 3.1.1 Response Type */ public final class OAuth2AuthorizationResponseType implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + public static final OAuth2AuthorizationResponseType CODE = new OAuth2AuthorizationResponseType("code"); + public static final OAuth2AuthorizationResponseType TOKEN = new OAuth2AuthorizationResponseType("token"); + private final String value; private OAuth2AuthorizationResponseType(String value) { @@ -46,7 +53,6 @@ public final class OAuth2AuthorizationResponseType implements Serializable { /** * Returns the value of the authorization response type. - * * @return the value of the authorization response type */ public String getValue() { @@ -69,4 +75,5 @@ public final class OAuth2AuthorizationResponseType implements Serializable { public int hashCode() { return this.getValue().hashCode(); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2ParameterNames.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2ParameterNames.java index 3bb5b2e910..52125853e2 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2ParameterNames.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/OAuth2ParameterNames.java @@ -16,12 +16,13 @@ package org.springframework.security.oauth2.core.endpoint; /** - * Standard and custom (non-standard) parameter names defined in the OAuth Parameters Registry - * and used by the authorization endpoint and token endpoint. + * Standard and custom (non-standard) parameter names defined in the OAuth Parameters + * Registry and used by the authorization endpoint and token endpoint. * * @author Joe Grandja * @since 5.0 - * @see 11.2 OAuth Parameters Registry + * @see 11.2 + * OAuth Parameters Registry */ public interface OAuth2ParameterNames { @@ -51,7 +52,8 @@ public interface OAuth2ParameterNames { String REDIRECT_URI = "redirect_uri"; /** - * {@code scope} - used in Authorization Request, Authorization Response, Access Token Request and Access Token Response. + * {@code scope} - used in Authorization Request, Authorization Response, Access Token + * Request and Access Token Response. */ String SCOPE = "scope"; @@ -101,7 +103,8 @@ public interface OAuth2ParameterNames { String ERROR = "error"; /** - * {@code error_description} - used in Authorization Response and Access Token Response. + * {@code error_description} - used in Authorization Response and Access Token + * Response. */ String ERROR_DESCRIPTION = "error_description"; diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/PkceParameterNames.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/PkceParameterNames.java index d258a55874..1d66dc5756 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/PkceParameterNames.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/PkceParameterNames.java @@ -16,13 +16,14 @@ package org.springframework.security.oauth2.core.endpoint; /** - * Standard parameter names defined in the OAuth Parameters Registry - * and used by the authorization endpoint and token endpoint. + * Standard parameter names defined in the OAuth Parameters Registry and used by the + * authorization endpoint and token endpoint. * * @author Stephen Doxsee * @author Kevin Bolduc * @since 5.2 - * @see 6.1 OAuth Parameters Registry + * @see 6.1 + * OAuth Parameters Registry */ public interface PkceParameterNames { @@ -40,4 +41,5 @@ public interface PkceParameterNames { * {@code code_verifier} - used in Token Request. */ String CODE_VERIFIER = "code_verifier"; + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/package-info.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/package-info.java index 6c214c76ff..29564190f2 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/package-info.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/endpoint/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Support classes that model the OAuth 2.0 Request and Response messages - * from the Authorization Endpoint and Token Endpoint. + * Support classes that model the OAuth 2.0 Request and Response messages from the + * Authorization Endpoint and Token Endpoint. */ package org.springframework.security.oauth2.core.endpoint; diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/HttpMessageConverters.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/HttpMessageConverters.java index 799599a125..4a1e104c5f 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/HttpMessageConverters.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/HttpMessageConverters.java @@ -29,14 +29,17 @@ import org.springframework.util.ClassUtils; * @since 5.1 */ final class HttpMessageConverters { + private static final boolean jackson2Present; + private static final boolean gsonPresent; + private static final boolean jsonbPresent; static { ClassLoader classLoader = HttpMessageConverters.class.getClassLoader(); - jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) && - ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader); + jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) + && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader); gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader); jsonbPresent = ClassUtils.isPresent("javax.json.bind.Jsonb", classLoader); } @@ -44,11 +47,14 @@ final class HttpMessageConverters { static GenericHttpMessageConverter getJsonMessageConverter() { if (jackson2Present) { return new MappingJackson2HttpMessageConverter(); - } else if (gsonPresent) { + } + else if (gsonPresent) { return new GsonHttpMessageConverter(); - } else if (jsonbPresent) { + } + else if (jsonbPresent) { return new JsonbHttpMessageConverter(); } return null; } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverter.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverter.java index 71e79119ee..020cc32874 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverter.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverter.java @@ -36,26 +36,27 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenRespon import org.springframework.util.Assert; /** - * A {@link HttpMessageConverter} for an {@link OAuth2AccessTokenResponse OAuth 2.0 Access Token Response}. + * A {@link HttpMessageConverter} for an {@link OAuth2AccessTokenResponse OAuth 2.0 Access + * Token Response}. * * @see AbstractHttpMessageConverter * @see OAuth2AccessTokenResponse * @author Joe Grandja * @since 5.1 */ -public class OAuth2AccessTokenResponseHttpMessageConverter extends AbstractHttpMessageConverter { +public class OAuth2AccessTokenResponseHttpMessageConverter + extends AbstractHttpMessageConverter { + private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; - private static final ParameterizedTypeReference> PARAMETERIZED_RESPONSE_TYPE = - new ParameterizedTypeReference>() {}; + private static final ParameterizedTypeReference> PARAMETERIZED_RESPONSE_TYPE = new ParameterizedTypeReference>() { + }; private GenericHttpMessageConverter jsonMessageConverter = HttpMessageConverters.getJsonMessageConverter(); - protected Converter, OAuth2AccessTokenResponse> tokenResponseConverter = - new MapOAuth2AccessTokenResponseConverter(); + protected Converter, OAuth2AccessTokenResponse> tokenResponseConverter = new MapOAuth2AccessTokenResponseConverter(); - protected Converter> tokenResponseParametersConverter = - new OAuth2AccessTokenResponseMapConverter(); + protected Converter> tokenResponseParametersConverter = new OAuth2AccessTokenResponseMapConverter(); public OAuth2AccessTokenResponseHttpMessageConverter() { super(DEFAULT_CHARSET, MediaType.APPLICATION_JSON, new MediaType("application", "*+json")); @@ -67,23 +68,23 @@ public class OAuth2AccessTokenResponseHttpMessageConverter extends AbstractHttpM } @Override - protected OAuth2AccessTokenResponse readInternal(Class clazz, HttpInputMessage inputMessage) - throws HttpMessageNotReadableException { + protected OAuth2AccessTokenResponse readInternal(Class clazz, + HttpInputMessage inputMessage) throws HttpMessageNotReadableException { try { // gh-6463 - // Parse parameter values as Object in order to handle potential JSON Object and then convert values to String + // Parse parameter values as Object in order to handle potential JSON Object + // and then convert values to String @SuppressWarnings("unchecked") - Map tokenResponseParameters = (Map) this.jsonMessageConverter.read( - PARAMETERIZED_RESPONSE_TYPE.getType(), null, inputMessage); - return this.tokenResponseConverter.convert( - tokenResponseParameters.entrySet().stream() - .collect(Collectors.toMap( - Map.Entry::getKey, - entry -> String.valueOf(entry.getValue())))); - } catch (Exception ex) { - throw new HttpMessageNotReadableException("An error occurred reading the OAuth 2.0 Access Token Response: " + - ex.getMessage(), ex, inputMessage); + Map tokenResponseParameters = (Map) this.jsonMessageConverter + .read(PARAMETERIZED_RESPONSE_TYPE.getType(), null, inputMessage); + return this.tokenResponseConverter.convert(tokenResponseParameters.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, entry -> String.valueOf(entry.getValue())))); + } + catch (Exception ex) { + throw new HttpMessageNotReadableException( + "An error occurred reading the OAuth 2.0 Access Token Response: " + ex.getMessage(), ex, + inputMessage); } } @@ -93,31 +94,36 @@ public class OAuth2AccessTokenResponseHttpMessageConverter extends AbstractHttpM try { Map tokenResponseParameters = this.tokenResponseParametersConverter.convert(tokenResponse); - this.jsonMessageConverter.write( - tokenResponseParameters, PARAMETERIZED_RESPONSE_TYPE.getType(), MediaType.APPLICATION_JSON, outputMessage); - } catch (Exception ex) { - throw new HttpMessageNotWritableException("An error occurred writing the OAuth 2.0 Access Token Response: " + ex.getMessage(), ex); + this.jsonMessageConverter.write(tokenResponseParameters, PARAMETERIZED_RESPONSE_TYPE.getType(), + MediaType.APPLICATION_JSON, outputMessage); + } + catch (Exception ex) { + throw new HttpMessageNotWritableException( + "An error occurred writing the OAuth 2.0 Access Token Response: " + ex.getMessage(), ex); } } /** - * Sets the {@link Converter} used for converting the OAuth 2.0 Access Token Response parameters - * to an {@link OAuth2AccessTokenResponse}. - * - * @param tokenResponseConverter the {@link Converter} used for converting to an {@link OAuth2AccessTokenResponse} + * Sets the {@link Converter} used for converting the OAuth 2.0 Access Token Response + * parameters to an {@link OAuth2AccessTokenResponse}. + * @param tokenResponseConverter the {@link Converter} used for converting to an + * {@link OAuth2AccessTokenResponse} */ - public final void setTokenResponseConverter(Converter, OAuth2AccessTokenResponse> tokenResponseConverter) { + public final void setTokenResponseConverter( + Converter, OAuth2AccessTokenResponse> tokenResponseConverter) { Assert.notNull(tokenResponseConverter, "tokenResponseConverter cannot be null"); this.tokenResponseConverter = tokenResponseConverter; } /** - * Sets the {@link Converter} used for converting the {@link OAuth2AccessTokenResponse} - * to a {@code Map} representation of the OAuth 2.0 Access Token Response parameters. - * - * @param tokenResponseParametersConverter the {@link Converter} used for converting to a {@code Map} representation of the Access Token Response parameters + * Sets the {@link Converter} used for converting the + * {@link OAuth2AccessTokenResponse} to a {@code Map} representation of the OAuth 2.0 + * Access Token Response parameters. + * @param tokenResponseParametersConverter the {@link Converter} used for converting + * to a {@code Map} representation of the Access Token Response parameters */ - public final void setTokenResponseParametersConverter(Converter> tokenResponseParametersConverter) { + public final void setTokenResponseParametersConverter( + Converter> tokenResponseParametersConverter) { Assert.notNull(tokenResponseParametersConverter, "tokenResponseParametersConverter cannot be null"); this.tokenResponseParametersConverter = tokenResponseParametersConverter; } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverter.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverter.java index a9901c97d9..52082de420 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverter.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverter.java @@ -45,10 +45,11 @@ import java.util.stream.Collectors; * @since 5.1 */ public class OAuth2ErrorHttpMessageConverter extends AbstractHttpMessageConverter { + private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; - private static final ParameterizedTypeReference> PARAMETERIZED_RESPONSE_TYPE = - new ParameterizedTypeReference>() {}; + private static final ParameterizedTypeReference> PARAMETERIZED_RESPONSE_TYPE = new ParameterizedTypeReference>() { + }; private GenericHttpMessageConverter jsonMessageConverter = HttpMessageConverters.getJsonMessageConverter(); @@ -71,18 +72,17 @@ public class OAuth2ErrorHttpMessageConverter extends AbstractHttpMessageConverte try { // gh-8157 - // Parse parameter values as Object in order to handle potential JSON Object and then convert values to String + // Parse parameter values as Object in order to handle potential JSON Object + // and then convert values to String @SuppressWarnings("unchecked") - Map errorParameters = (Map) this.jsonMessageConverter.read( - PARAMETERIZED_RESPONSE_TYPE.getType(), null, inputMessage); - return this.errorConverter.convert( - errorParameters.entrySet().stream() - .collect(Collectors.toMap( - Map.Entry::getKey, - entry -> String.valueOf(entry.getValue())))); - } catch (Exception ex) { - throw new HttpMessageNotReadableException("An error occurred reading the OAuth 2.0 Error: " + - ex.getMessage(), ex, inputMessage); + Map errorParameters = (Map) this.jsonMessageConverter + .read(PARAMETERIZED_RESPONSE_TYPE.getType(), null, inputMessage); + return this.errorConverter.convert(errorParameters.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, entry -> String.valueOf(entry.getValue())))); + } + catch (Exception ex) { + throw new HttpMessageNotReadableException( + "An error occurred reading the OAuth 2.0 Error: " + ex.getMessage(), ex, inputMessage); } } @@ -92,18 +92,20 @@ public class OAuth2ErrorHttpMessageConverter extends AbstractHttpMessageConverte try { Map errorParameters = this.errorParametersConverter.convert(oauth2Error); - this.jsonMessageConverter.write( - errorParameters, PARAMETERIZED_RESPONSE_TYPE.getType(), MediaType.APPLICATION_JSON, outputMessage); - } catch (Exception ex) { - throw new HttpMessageNotWritableException("An error occurred writing the OAuth 2.0 Error: " + ex.getMessage(), ex); + this.jsonMessageConverter.write(errorParameters, PARAMETERIZED_RESPONSE_TYPE.getType(), + MediaType.APPLICATION_JSON, outputMessage); + } + catch (Exception ex) { + throw new HttpMessageNotWritableException( + "An error occurred writing the OAuth 2.0 Error: " + ex.getMessage(), ex); } } /** - * Sets the {@link Converter} used for converting the OAuth 2.0 Error parameters - * to an {@link OAuth2Error}. - * - * @param errorConverter the {@link Converter} used for converting to an {@link OAuth2Error} + * Sets the {@link Converter} used for converting the OAuth 2.0 Error parameters to an + * {@link OAuth2Error}. + * @param errorConverter the {@link Converter} used for converting to an + * {@link OAuth2Error} */ public final void setErrorConverter(Converter, OAuth2Error> errorConverter) { Assert.notNull(errorConverter, "errorConverter cannot be null"); @@ -111,19 +113,20 @@ public class OAuth2ErrorHttpMessageConverter extends AbstractHttpMessageConverte } /** - * Sets the {@link Converter} used for converting the {@link OAuth2Error} - * to a {@code Map} representation of the OAuth 2.0 Error parameters. - * - * @param errorParametersConverter the {@link Converter} used for converting to a {@code Map} representation of the Error parameters + * Sets the {@link Converter} used for converting the {@link OAuth2Error} to a + * {@code Map} representation of the OAuth 2.0 Error parameters. + * @param errorParametersConverter the {@link Converter} used for converting to a + * {@code Map} representation of the Error parameters */ - public final void setErrorParametersConverter(Converter> errorParametersConverter) { + public final void setErrorParametersConverter( + Converter> errorParametersConverter) { Assert.notNull(errorParametersConverter, "errorParametersConverter cannot be null"); this.errorParametersConverter = errorParametersConverter; } /** - * A {@link Converter} that converts the provided - * OAuth 2.0 Error parameters to an {@link OAuth2Error}. + * A {@link Converter} that converts the provided OAuth 2.0 Error parameters to an + * {@link OAuth2Error}. */ private static class OAuth2ErrorConverter implements Converter, OAuth2Error> { @@ -135,11 +138,12 @@ public class OAuth2ErrorHttpMessageConverter extends AbstractHttpMessageConverte return new OAuth2Error(errorCode, errorDescription, errorUri); } + } /** - * A {@link Converter} that converts the provided {@link OAuth2Error} - * to a {@code Map} representation of OAuth 2.0 Error parameters. + * A {@link Converter} that converts the provided {@link OAuth2Error} to a {@code Map} + * representation of OAuth 2.0 Error parameters. */ private static class OAuth2ErrorParametersConverter implements Converter> { @@ -157,5 +161,7 @@ public class OAuth2ErrorHttpMessageConverter extends AbstractHttpMessageConverte return parameters; } + } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/AddressStandardClaim.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/AddressStandardClaim.java index 47037a3127..53de6bb22e 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/AddressStandardClaim.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/AddressStandardClaim.java @@ -16,55 +16,55 @@ package org.springframework.security.oauth2.core.oidc; /** - * The Address Claim represents a physical mailing address defined by the OpenID Connect Core 1.0 specification - * that can be returned either in the UserInfo Response or the ID Token. + * The Address Claim represents a physical mailing address defined by the OpenID Connect + * Core 1.0 specification that can be returned either in the UserInfo Response or the ID + * Token. * * @author Joe Grandja * @since 5.0 - * @see Address Claim - * @see UserInfo Response - * @see ID Token + * @see Address Claim + * @see UserInfo + * Response + * @see ID Token */ public interface AddressStandardClaim { /** * Returns the full mailing address, formatted for display. - * * @return the full mailing address */ String getFormatted(); /** - * Returns the full street address, which may include house number, street name, P.O. Box, etc. - * + * Returns the full street address, which may include house number, street name, P.O. + * Box, etc. * @return the full street address */ String getStreetAddress(); /** * Returns the city or locality. - * * @return the city or locality */ String getLocality(); /** * Returns the state, province, prefecture, or region. - * * @return the state, province, prefecture, or region */ String getRegion(); /** * Returns the zip code or postal code. - * * @return the zip code or postal code */ String getPostalCode(); /** * Returns the country. - * * @return the country */ String getCountry(); diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/DefaultAddressStandardClaim.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/DefaultAddressStandardClaim.java index 48e2fc8eb5..62b68f3f49 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/DefaultAddressStandardClaim.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/DefaultAddressStandardClaim.java @@ -25,11 +25,17 @@ import java.util.Map; * @see AddressStandardClaim */ public final class DefaultAddressStandardClaim implements AddressStandardClaim { + private String formatted; + private String streetAddress; + private String locality; + private String region; + private String postalCode; + private String country; private DefaultAddressStandardClaim() { @@ -76,10 +82,12 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim { AddressStandardClaim that = (AddressStandardClaim) obj; - if (this.getFormatted() != null ? !this.getFormatted().equals(that.getFormatted()) : that.getFormatted() != null) { + if (this.getFormatted() != null ? !this.getFormatted().equals(that.getFormatted()) + : that.getFormatted() != null) { return false; } - if (this.getStreetAddress() != null ? !this.getStreetAddress().equals(that.getStreetAddress()) : that.getStreetAddress() != null) { + if (this.getStreetAddress() != null ? !this.getStreetAddress().equals(that.getStreetAddress()) + : that.getStreetAddress() != null) { return false; } if (this.getLocality() != null ? !this.getLocality().equals(that.getLocality()) : that.getLocality() != null) { @@ -88,7 +96,8 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim { if (this.getRegion() != null ? !this.getRegion().equals(that.getRegion()) : that.getRegion() != null) { return false; } - if (this.getPostalCode() != null ? !this.getPostalCode().equals(that.getPostalCode()) : that.getPostalCode() != null) { + if (this.getPostalCode() != null ? !this.getPostalCode().equals(that.getPostalCode()) + : that.getPostalCode() != null) { return false; } return this.getCountry() != null ? this.getCountry().equals(that.getCountry()) : that.getCountry() == null; @@ -109,17 +118,29 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim { * A builder for {@link DefaultAddressStandardClaim}. */ public static class Builder { + private static final String FORMATTED_FIELD_NAME = "formatted"; + private static final String STREET_ADDRESS_FIELD_NAME = "street_address"; + private static final String LOCALITY_FIELD_NAME = "locality"; + private static final String REGION_FIELD_NAME = "region"; + private static final String POSTAL_CODE_FIELD_NAME = "postal_code"; + private static final String COUNTRY_FIELD_NAME = "country"; + private String formatted; + private String streetAddress; + private String locality; + private String region; + private String postalCode; + private String country; /** @@ -129,8 +150,8 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim { } /** - * Constructs and initializes the address attributes using the provided {@code addressFields}. - * + * Constructs and initializes the address attributes using the provided + * {@code addressFields}. * @param addressFields the fields used to initialize the address attributes */ public Builder(Map addressFields) { @@ -144,7 +165,6 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim { /** * Sets the full mailing address, formatted for display. - * * @param formatted the full mailing address * @return the {@link Builder} */ @@ -154,8 +174,8 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim { } /** - * Sets the full street address, which may include house number, street name, P.O. Box, etc. - * + * Sets the full street address, which may include house number, street name, P.O. + * Box, etc. * @param streetAddress the full street address * @return the {@link Builder} */ @@ -166,7 +186,6 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim { /** * Sets the city or locality. - * * @param locality the city or locality * @return the {@link Builder} */ @@ -177,7 +196,6 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim { /** * Sets the state, province, prefecture, or region. - * * @param region the state, province, prefecture, or region * @return the {@link Builder} */ @@ -188,7 +206,6 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim { /** * Sets the zip code or postal code. - * * @param postalCode the zip code or postal code * @return the {@link Builder} */ @@ -199,7 +216,6 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim { /** * Sets the country. - * * @param country the country * @return the {@link Builder} */ @@ -210,7 +226,6 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim { /** * Builds a new {@link DefaultAddressStandardClaim}. - * * @return a {@link AddressStandardClaim} */ public AddressStandardClaim build() { @@ -224,5 +239,7 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim { return address; } + } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/IdTokenClaimAccessor.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/IdTokenClaimAccessor.java index 0170f933ec..beb6107052 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/IdTokenClaimAccessor.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/IdTokenClaimAccessor.java @@ -22,16 +22,20 @@ import java.time.Instant; import java.util.List; /** - * A {@link ClaimAccessor} for the "claims" that can be returned in the ID Token, - * which provides information about the authentication of an End-User by an Authorization Server. + * A {@link ClaimAccessor} for the "claims" that can be returned in the ID + * Token, which provides information about the authentication of an End-User by an + * Authorization Server. * * @see ClaimAccessor * @see StandardClaimAccessor * @see StandardClaimNames * @see IdTokenClaimNames * @see OidcIdToken - * @see ID Token - * @see Standard Claims + * @see ID Token + * @see Standard + * Claims * @author Joe Grandja * @since 5.0 */ @@ -39,7 +43,6 @@ public interface IdTokenClaimAccessor extends StandardClaimAccessor { /** * Returns the Issuer identifier {@code (iss)}. - * * @return the Issuer identifier */ default URL getIssuer() { @@ -48,7 +51,6 @@ public interface IdTokenClaimAccessor extends StandardClaimAccessor { /** * Returns the Subject identifier {@code (sub)}. - * * @return the Subject identifier */ default String getSubject() { @@ -57,7 +59,6 @@ public interface IdTokenClaimAccessor extends StandardClaimAccessor { /** * Returns the Audience(s) {@code (aud)} that this ID Token is intended for. - * * @return the Audience(s) that this ID Token is intended for */ default List getAudience() { @@ -65,8 +66,8 @@ public interface IdTokenClaimAccessor extends StandardClaimAccessor { } /** - * Returns the Expiration time {@code (exp)} on or after which the ID Token MUST NOT be accepted. - * + * Returns the Expiration time {@code (exp)} on or after which the ID Token MUST NOT + * be accepted. * @return the Expiration time on or after which the ID Token MUST NOT be accepted */ default Instant getExpiresAt() { @@ -75,7 +76,6 @@ public interface IdTokenClaimAccessor extends StandardClaimAccessor { /** * Returns the time at which the ID Token was issued {@code (iat)}. - * * @return the time at which the ID Token was issued */ default Instant getIssuedAt() { @@ -84,7 +84,6 @@ public interface IdTokenClaimAccessor extends StandardClaimAccessor { /** * Returns the time when the End-User authentication occurred {@code (auth_time)}. - * * @return the time when the End-User authentication occurred */ default Instant getAuthenticatedAt() { @@ -92,9 +91,8 @@ public interface IdTokenClaimAccessor extends StandardClaimAccessor { } /** - * Returns a {@code String} value {@code (nonce)} used to associate a Client session with an ID Token, - * and to mitigate replay attacks. - * + * Returns a {@code String} value {@code (nonce)} used to associate a Client session + * with an ID Token, and to mitigate replay attacks. * @return the nonce used to associate a Client session with an ID Token */ default String getNonce() { @@ -103,7 +101,6 @@ public interface IdTokenClaimAccessor extends StandardClaimAccessor { /** * Returns the Authentication Context Class Reference {@code (acr)}. - * * @return the Authentication Context Class Reference */ default String getAuthenticationContextClass() { @@ -112,7 +109,6 @@ public interface IdTokenClaimAccessor extends StandardClaimAccessor { /** * Returns the Authentication Methods References {@code (amr)}. - * * @return the Authentication Methods References */ default List getAuthenticationMethods() { @@ -121,7 +117,6 @@ public interface IdTokenClaimAccessor extends StandardClaimAccessor { /** * Returns the Authorized party {@code (azp)} to which the ID Token was issued. - * * @return the Authorized party to which the ID Token was issued */ default String getAuthorizedParty() { @@ -130,7 +125,6 @@ public interface IdTokenClaimAccessor extends StandardClaimAccessor { /** * Returns the Access Token hash value {@code (at_hash)}. - * * @return the Access Token hash value */ default String getAccessTokenHash() { @@ -139,10 +133,10 @@ public interface IdTokenClaimAccessor extends StandardClaimAccessor { /** * Returns the Authorization Code hash value {@code (c_hash)}. - * * @return the Authorization Code hash value */ default String getAuthorizationCodeHash() { return this.getClaimAsString(IdTokenClaimNames.C_HASH); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/IdTokenClaimNames.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/IdTokenClaimNames.java index c73b604f3d..b8707c7e8e 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/IdTokenClaimNames.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/IdTokenClaimNames.java @@ -16,13 +16,14 @@ package org.springframework.security.oauth2.core.oidc; /** - * The names of the "claims" defined by the OpenID Connect Core 1.0 specification - * that can be returned in the ID Token. + * The names of the "claims" defined by the OpenID Connect Core 1.0 + * specification that can be returned in the ID Token. * * @author Joe Grandja * @since 5.0 * @see OidcIdToken - * @see ID Token + * @see ID Token */ public interface IdTokenClaimNames { @@ -43,7 +44,8 @@ public interface IdTokenClaimNames { String AUD = "aud"; /** - * {@code exp} - the Expiration time on or after which the ID Token MUST NOT be accepted + * {@code exp} - the Expiration time on or after which the ID Token MUST NOT be + * accepted */ String EXP = "exp"; @@ -58,8 +60,8 @@ public interface IdTokenClaimNames { String AUTH_TIME = "auth_time"; /** - * {@code nonce} - a {@code String} value used to associate a Client session with an ID Token, - * and to mitigate replay attacks. + * {@code nonce} - a {@code String} value used to associate a Client session with an + * ID Token, and to mitigate replay attacks. */ String NONCE = "nonce"; diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/OidcIdToken.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/OidcIdToken.java index 5f3740dc43..4738c784b5 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/OidcIdToken.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/OidcIdToken.java @@ -40,29 +40,34 @@ import static org.springframework.security.oauth2.core.oidc.IdTokenClaimNames.NO import static org.springframework.security.oauth2.core.oidc.IdTokenClaimNames.SUB; /** - * An implementation of an {@link AbstractOAuth2Token} representing an OpenID Connect Core 1.0 ID Token. + * An implementation of an {@link AbstractOAuth2Token} representing an OpenID Connect Core + * 1.0 ID Token. * *

        - * The {@code OidcIdToken} is a security token that contains "claims" - * about the authentication of an End-User by an Authorization Server. + * The {@code OidcIdToken} is a security token that contains "claims" about the + * authentication of an End-User by an Authorization Server. * * @author Joe Grandja * @since 5.0 * @see AbstractOAuth2Token * @see IdTokenClaimAccessor * @see StandardClaimAccessor - * @see ID Token - * @see Standard Claims + * @see ID Token + * @see Standard + * Claims */ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAccessor { + private final Map claims; /** * Constructs a {@code OidcIdToken} using the provided parameters. - * * @param tokenValue the ID Token value * @param issuedAt the time at which the ID Token was issued {@code (iat)} - * @param expiresAt the expiration time {@code (exp)} on or after which the ID Token MUST NOT be accepted + * @param expiresAt the expiration time {@code (exp)} on or after which the ID Token + * MUST NOT be accepted * @param claims the claims about the authentication of the End-User */ public OidcIdToken(String tokenValue, Instant issuedAt, Instant expiresAt, Map claims) { @@ -78,7 +83,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Create a {@link Builder} based on the given token value - * * @param tokenValue the token value to use * @return the {@link Builder} for further configuration * @since 5.3 @@ -94,7 +98,9 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce * @since 5.3 */ public static final class Builder { + private String tokenValue; + private final Map claims = new LinkedHashMap<>(); private Builder(String tokenValue) { @@ -103,7 +109,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Use this token value in the resulting {@link OidcIdToken} - * * @param tokenValue The token value to use * @return the {@link Builder} for further configurations */ @@ -114,7 +119,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Use this claim in the resulting {@link OidcIdToken} - * * @param name The claim name * @param value The claim value * @return the {@link Builder} for further configurations @@ -125,8 +129,8 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce } /** - * Provides access to every {@link #claim(String, Object)} - * declared so far with the possibility to add, replace, or remove. + * Provides access to every {@link #claim(String, Object)} declared so far with + * the possibility to add, replace, or remove. * @param claimsConsumer the consumer * @return the {@link Builder} for further configurations */ @@ -137,7 +141,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Use this access token hash in the resulting {@link OidcIdToken} - * * @param accessTokenHash The access token hash to use * @return the {@link Builder} for further configurations */ @@ -147,7 +150,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Use this audience in the resulting {@link OidcIdToken} - * * @param audience The audience(s) to use * @return the {@link Builder} for further configurations */ @@ -157,7 +159,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Use this authentication {@link Instant} in the resulting {@link OidcIdToken} - * * @param authenticatedAt The authentication {@link Instant} to use * @return the {@link Builder} for further configurations */ @@ -166,9 +167,10 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce } /** - * Use this authentication context class reference in the resulting {@link OidcIdToken} - * - * @param authenticationContextClass The authentication context class reference to use + * Use this authentication context class reference in the resulting + * {@link OidcIdToken} + * @param authenticationContextClass The authentication context class reference to + * use * @return the {@link Builder} for further configurations */ public Builder authenticationContextClass(String authenticationContextClass) { @@ -177,7 +179,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Use these authentication methods in the resulting {@link OidcIdToken} - * * @param authenticationMethods The authentication methods to use * @return the {@link Builder} for further configurations */ @@ -187,7 +188,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Use this authorization code hash in the resulting {@link OidcIdToken} - * * @param authorizationCodeHash The authorization code hash to use * @return the {@link Builder} for further configurations */ @@ -197,7 +197,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Use this authorized party in the resulting {@link OidcIdToken} - * * @param authorizedParty The authorized party to use * @return the {@link Builder} for further configurations */ @@ -207,7 +206,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Use this expiration in the resulting {@link OidcIdToken} - * * @param expiresAt The expiration to use * @return the {@link Builder} for further configurations */ @@ -217,7 +215,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Use this issued-at timestamp in the resulting {@link OidcIdToken} - * * @param issuedAt The issued-at timestamp to use * @return the {@link Builder} for further configurations */ @@ -227,7 +224,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Use this issuer in the resulting {@link OidcIdToken} - * * @param issuer The issuer to use * @return the {@link Builder} for further configurations */ @@ -237,7 +233,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Use this nonce in the resulting {@link OidcIdToken} - * * @param nonce The nonce to use * @return the {@link Builder} for further configurations */ @@ -247,7 +242,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Use this subject in the resulting {@link OidcIdToken} - * * @param subject The subject to use * @return the {@link Builder} for further configurations */ @@ -257,7 +251,6 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce /** * Build the {@link OidcIdToken} - * * @return The constructed {@link OidcIdToken} */ public OidcIdToken build() { @@ -272,5 +265,7 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce } return (Instant) timestamp; } + } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/OidcScopes.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/OidcScopes.java index e8b70c757a..253db42356 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/OidcScopes.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/OidcScopes.java @@ -18,17 +18,19 @@ package org.springframework.security.oauth2.core.oidc; import org.springframework.security.oauth2.core.OAuth2AccessToken; /** - * The scope values defined by the OpenID Connect Core 1.0 specification - * that can be used to request {@link StandardClaimNames claims}. + * The scope values defined by the OpenID Connect Core 1.0 specification that can be used + * to request {@link StandardClaimNames claims}. *

        - * The scope(s) associated to an {@link OAuth2AccessToken} determine what claims (resources) - * will be available when they are used to access OAuth 2.0 Protected Endpoints, - * such as the UserInfo Endpoint. + * The scope(s) associated to an {@link OAuth2AccessToken} determine what claims + * (resources) will be available when they are used to access OAuth 2.0 Protected + * Endpoints, such as the UserInfo Endpoint. * * @author Joe Grandja * @since 5.0 * @see StandardClaimNames - * @see Requesting Claims using Scope Values + * @see Requesting Claims + * using Scope Values */ public interface OidcScopes { @@ -45,7 +47,8 @@ public interface OidcScopes { String PROFILE = "profile"; /** - * The {@code email} scope requests access to the {@code email} and {@code email_verified} claims. + * The {@code email} scope requests access to the {@code email} and + * {@code email_verified} claims. */ String EMAIL = "email"; @@ -55,7 +58,8 @@ public interface OidcScopes { String ADDRESS = "address"; /** - * The {@code phone} scope requests access to the {@code phone_number} and {@code phone_number_verified} claims. + * The {@code phone} scope requests access to the {@code phone_number} and + * {@code phone_number_verified} claims. */ String PHONE = "phone"; diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/OidcUserInfo.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/OidcUserInfo.java index 5de4899ff6..1269de2164 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/OidcUserInfo.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/OidcUserInfo.java @@ -47,26 +47,33 @@ import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.W import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.ZONEINFO; /** - * A representation of a UserInfo Response that is returned - * from the OAuth 2.0 Protected Resource UserInfo Endpoint. + * A representation of a UserInfo Response that is returned from the OAuth 2.0 Protected + * Resource UserInfo Endpoint. * *

        - * The {@code OidcUserInfo} contains a set of "Standard Claims" about the authentication of an End-User. + * The {@code OidcUserInfo} contains a set of "Standard Claims" about the + * authentication of an End-User. * * @author Joe Grandja * @since 5.0 * @see StandardClaimAccessor - * @see UserInfo Response - * @see UserInfo Endpoint - * @see Standard Claims + * @see UserInfo + * Response + * @see UserInfo Endpoint + * @see Standard + * Claims */ public class OidcUserInfo implements StandardClaimAccessor, Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private final Map claims; /** * Constructs a {@code OidcUserInfo} using the provided parameters. - * * @param claims the claims about the authentication of the End-User */ public OidcUserInfo(Map claims) { @@ -100,7 +107,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Create a {@link Builder} - * * @return the {@link Builder} for further configuration * @since 5.3 */ @@ -115,13 +121,14 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { * @since 5.3 */ public static final class Builder { + private final Map claims = new LinkedHashMap<>(); - private Builder() {} + private Builder() { + } /** * Use this claim in the resulting {@link OidcUserInfo} - * * @param name The claim name * @param value The claim value * @return the {@link Builder} for further configurations @@ -132,8 +139,8 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { } /** - * Provides access to every {@link #claim(String, Object)} - * declared so far with the possibility to add, replace, or remove. + * Provides access to every {@link #claim(String, Object)} declared so far with + * the possibility to add, replace, or remove. * @param claimsConsumer the consumer * @return the {@link Builder} for further configurations */ @@ -144,7 +151,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this address in the resulting {@link OidcUserInfo} - * * @param address The address to use * @return the {@link Builder} for further configurations */ @@ -154,7 +160,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this birthdate in the resulting {@link OidcUserInfo} - * * @param birthdate The birthdate to use * @return the {@link Builder} for further configurations */ @@ -164,7 +169,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this email in the resulting {@link OidcUserInfo} - * * @param email The email to use * @return the {@link Builder} for further configurations */ @@ -174,7 +178,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this verified-email indicator in the resulting {@link OidcUserInfo} - * * @param emailVerified The verified-email indicator to use * @return the {@link Builder} for further configurations */ @@ -184,7 +187,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this family name in the resulting {@link OidcUserInfo} - * * @param familyName The family name to use * @return the {@link Builder} for further configurations */ @@ -194,7 +196,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this gender in the resulting {@link OidcUserInfo} - * * @param gender The gender to use * @return the {@link Builder} for further configurations */ @@ -204,7 +205,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this given name in the resulting {@link OidcUserInfo} - * * @param givenName The given name to use * @return the {@link Builder} for further configurations */ @@ -214,7 +214,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this locale in the resulting {@link OidcUserInfo} - * * @param locale The locale to use * @return the {@link Builder} for further configurations */ @@ -224,7 +223,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this middle name in the resulting {@link OidcUserInfo} - * * @param middleName The middle name to use * @return the {@link Builder} for further configurations */ @@ -234,7 +232,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this name in the resulting {@link OidcUserInfo} - * * @param name The name to use * @return the {@link Builder} for further configurations */ @@ -244,7 +241,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this nickname in the resulting {@link OidcUserInfo} - * * @param nickname The nickname to use * @return the {@link Builder} for further configurations */ @@ -254,7 +250,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this picture in the resulting {@link OidcUserInfo} - * * @param picture The picture to use * @return the {@link Builder} for further configurations */ @@ -264,7 +259,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this phone number in the resulting {@link OidcUserInfo} - * * @param phoneNumber The phone number to use * @return the {@link Builder} for further configurations */ @@ -274,7 +268,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this verified-phone-number indicator in the resulting {@link OidcUserInfo} - * * @param phoneNumberVerified The verified-phone-number indicator to use * @return the {@link Builder} for further configurations */ @@ -284,7 +277,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this preferred username in the resulting {@link OidcUserInfo} - * * @param preferredUsername The preferred username to use * @return the {@link Builder} for further configurations */ @@ -294,7 +286,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this profile in the resulting {@link OidcUserInfo} - * * @param profile The profile to use * @return the {@link Builder} for further configurations */ @@ -304,7 +295,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this subject in the resulting {@link OidcUserInfo} - * * @param subject The subject to use * @return the {@link Builder} for further configurations */ @@ -314,7 +304,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this updated-at {@link Instant} in the resulting {@link OidcUserInfo} - * * @param updatedAt The updated-at {@link Instant} to use * @return the {@link Builder} for further configurations */ @@ -324,7 +313,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this website in the resulting {@link OidcUserInfo} - * * @param website The website to use * @return the {@link Builder} for further configurations */ @@ -334,7 +322,6 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Use this zoneinfo in the resulting {@link OidcUserInfo} - * * @param zoneinfo The zoneinfo to use * @return the {@link Builder} for further configurations */ @@ -344,11 +331,12 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable { /** * Build the {@link OidcUserInfo} - * * @return The constructed {@link OidcUserInfo} */ public OidcUserInfo build() { return new OidcUserInfo(this.claims); } + } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/StandardClaimAccessor.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/StandardClaimAccessor.java index 455e0f8f36..e99c53959c 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/StandardClaimAccessor.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/StandardClaimAccessor.java @@ -22,14 +22,18 @@ import java.time.Instant; import java.util.Map; /** - * A {@link ClaimAccessor} for the "Standard Claims" that can be returned - * either in the UserInfo Response or the ID Token. + * A {@link ClaimAccessor} for the "Standard Claims" that can be returned either + * in the UserInfo Response or the ID Token. * * @see ClaimAccessor * @see StandardClaimNames * @see OidcUserInfo - * @see UserInfo Response - * @see Standard Claims + * @see UserInfo + * Response + * @see Standard + * Claims * @author Joe Grandja * @since 5.0 */ @@ -37,7 +41,6 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the Subject identifier {@code (sub)}. - * * @return the Subject identifier */ default String getSubject() { @@ -46,7 +49,6 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the user's full name {@code (name)} in displayable form. - * * @return the user's full name */ default String getFullName() { @@ -55,7 +57,6 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the user's given name(s) or first name(s) {@code (given_name)}. - * * @return the user's given name(s) */ default String getGivenName() { @@ -64,7 +65,6 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the user's surname(s) or last name(s) {@code (family_name)}. - * * @return the user's family names(s) */ default String getFamilyName() { @@ -73,7 +73,6 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the user's middle name(s) {@code (middle_name)}. - * * @return the user's middle name(s) */ default String getMiddleName() { @@ -81,8 +80,8 @@ public interface StandardClaimAccessor extends ClaimAccessor { } /** - * Returns the user's nick name {@code (nickname)} that may or may not be the same as the {@code (given_name)}. - * + * Returns the user's nick name {@code (nickname)} that may or may not be the same as + * the {@code (given_name)}. * @return the user's nick name */ default String getNickName() { @@ -90,8 +89,8 @@ public interface StandardClaimAccessor extends ClaimAccessor { } /** - * Returns the preferred username {@code (preferred_username)} that the user wishes to be referred to. - * + * Returns the preferred username {@code (preferred_username)} that the user wishes to + * be referred to. * @return the user's preferred user name */ default String getPreferredUsername() { @@ -100,7 +99,6 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the URL of the user's profile page {@code (profile)}. - * * @return the URL of the user's profile page */ default String getProfile() { @@ -109,7 +107,6 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the URL of the user's profile picture {@code (picture)}. - * * @return the URL of the user's profile picture */ default String getPicture() { @@ -118,7 +115,6 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the URL of the user's web page or blog {@code (website)}. - * * @return the URL of the user's web page or blog */ default String getWebsite() { @@ -127,7 +123,6 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the user's preferred e-mail address {@code (email)}. - * * @return the user's preferred e-mail address */ default String getEmail() { @@ -135,9 +130,10 @@ public interface StandardClaimAccessor extends ClaimAccessor { } /** - * Returns {@code true} if the user's e-mail address has been verified {@code (email_verified)}, otherwise {@code false}. - * - * @return {@code true} if the user's e-mail address has been verified, otherwise {@code false} + * Returns {@code true} if the user's e-mail address has been verified + * {@code (email_verified)}, otherwise {@code false}. + * @return {@code true} if the user's e-mail address has been verified, otherwise + * {@code false} */ default Boolean getEmailVerified() { return this.getClaimAsBoolean(StandardClaimNames.EMAIL_VERIFIED); @@ -145,7 +141,6 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the user's gender {@code (gender)}. - * * @return the user's gender */ default String getGender() { @@ -154,7 +149,6 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the user's birth date {@code (birthdate)}. - * * @return the user's birth date */ default String getBirthdate() { @@ -163,7 +157,6 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the user's time zone {@code (zoneinfo)}. - * * @return the user's time zone */ default String getZoneInfo() { @@ -172,7 +165,6 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the user's locale {@code (locale)}. - * * @return the user's locale */ default String getLocale() { @@ -181,7 +173,6 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the user's preferred phone number {@code (phone_number)}. - * * @return the user's preferred phone number */ default String getPhoneNumber() { @@ -189,9 +180,10 @@ public interface StandardClaimAccessor extends ClaimAccessor { } /** - * Returns {@code true} if the user's phone number has been verified {@code (phone_number_verified)}, otherwise {@code false}. - * - * @return {@code true} if the user's phone number has been verified, otherwise {@code false} + * Returns {@code true} if the user's phone number has been verified + * {@code (phone_number_verified)}, otherwise {@code false}. + * @return {@code true} if the user's phone number has been verified, otherwise + * {@code false} */ default Boolean getPhoneNumberVerified() { return this.getClaimAsBoolean(StandardClaimNames.PHONE_NUMBER_VERIFIED); @@ -199,22 +191,20 @@ public interface StandardClaimAccessor extends ClaimAccessor { /** * Returns the user's preferred postal address {@code (address)}. - * * @return the user's preferred postal address */ default AddressStandardClaim getAddress() { Map addressFields = this.getClaimAsMap(StandardClaimNames.ADDRESS); - return (!CollectionUtils.isEmpty(addressFields) ? - new DefaultAddressStandardClaim.Builder(addressFields).build() : - new DefaultAddressStandardClaim.Builder().build()); + return (!CollectionUtils.isEmpty(addressFields) ? new DefaultAddressStandardClaim.Builder(addressFields).build() + : new DefaultAddressStandardClaim.Builder().build()); } /** * Returns the time the user's information was last updated {@code (updated_at)}. - * * @return the time the user's information was last updated */ default Instant getUpdatedAt() { return this.getClaimAsInstant(StandardClaimNames.UPDATED_AT); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/StandardClaimNames.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/StandardClaimNames.java index e57b4df7a0..0e465c1e23 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/StandardClaimNames.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/StandardClaimNames.java @@ -16,14 +16,19 @@ package org.springframework.security.oauth2.core.oidc; /** - * The names of the "Standard Claims" defined by the OpenID Connect Core 1.0 specification - * that can be returned either in the UserInfo Response or the ID Token. + * The names of the "Standard Claims" defined by the OpenID Connect Core 1.0 + * specification that can be returned either in the UserInfo Response or the ID Token. * * @author Joe Grandja * @since 5.0 - * @see Standard Claims - * @see UserInfo Response - * @see ID Token + * @see Standard + * Claims + * @see UserInfo + * Response + * @see ID Token */ public interface StandardClaimNames { @@ -53,12 +58,14 @@ public interface StandardClaimNames { String MIDDLE_NAME = "middle_name"; /** - * {@code nickname} - the user's nick name that may or may not be the same as the {@code given_name} + * {@code nickname} - the user's nick name that may or may not be the same as the + * {@code given_name} */ String NICKNAME = "nickname"; /** - * {@code preferred_username} - the preferred username that the user wishes to be referred to + * {@code preferred_username} - the preferred username that the user wishes to be + * referred to */ String PREFERRED_USERNAME = "preferred_username"; @@ -83,7 +90,8 @@ public interface StandardClaimNames { String EMAIL = "email"; /** - * {@code email_verified} - {@code true} if the user's e-mail address has been verified, otherwise {@code false} + * {@code email_verified} - {@code true} if the user's e-mail address has been + * verified, otherwise {@code false} */ String EMAIL_VERIFIED = "email_verified"; @@ -113,7 +121,8 @@ public interface StandardClaimNames { String PHONE_NUMBER = "phone_number"; /** - * {@code phone_number_verified} - {@code true} if the user's phone number has been verified, otherwise {@code false} + * {@code phone_number_verified} - {@code true} if the user's phone number has been + * verified, otherwise {@code false} */ String PHONE_NUMBER_VERIFIED = "phone_number_verified"; diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/endpoint/OidcParameterNames.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/endpoint/OidcParameterNames.java index 827c4557b2..b157408940 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/endpoint/OidcParameterNames.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/endpoint/OidcParameterNames.java @@ -16,13 +16,15 @@ package org.springframework.security.oauth2.core.oidc.endpoint; /** - * Standard parameter names defined in the OAuth Parameters Registry - * and used by the authorization endpoint and token endpoint. + * Standard parameter names defined in the OAuth Parameters Registry and used by the + * authorization endpoint and token endpoint. * * @author Joe Grandja * @author Mark Heckler * @since 5.0 - * @see 18.2 OAuth Parameters Registration + * @see 18.2 + * OAuth Parameters Registration */ public interface OidcParameterNames { diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/DefaultOidcUser.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/DefaultOidcUser.java index b162ba85ae..34ab430cf8 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/DefaultOidcUser.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/DefaultOidcUser.java @@ -29,8 +29,8 @@ import java.util.Map; * The default implementation of an {@link OidcUser}. * *

        - * The default claim used for accessing the "name" of the - * user {@code Principal} from {@link #getClaims()} is {@link IdTokenClaimNames#SUB}. + * The default claim used for accessing the "name" of the user {@code Principal} + * from {@link #getClaims()} is {@link IdTokenClaimNames#SUB}. * * @author Joe Grandja * @author Vedran Pavic @@ -41,12 +41,13 @@ import java.util.Map; * @see OidcUserInfo */ public class DefaultOidcUser extends DefaultOAuth2User implements OidcUser { + private final OidcIdToken idToken; + private final OidcUserInfo userInfo; /** * Constructs a {@code DefaultOidcUser} using the provided parameters. - * * @param authorities the authorities granted to the user * @param idToken the {@link OidcIdToken ID Token} containing claims about the user */ @@ -56,36 +57,39 @@ public class DefaultOidcUser extends DefaultOAuth2User implements OidcUser { /** * Constructs a {@code DefaultOidcUser} using the provided parameters. - * * @param authorities the authorities granted to the user * @param idToken the {@link OidcIdToken ID Token} containing claims about the user - * @param nameAttributeKey the key used to access the user's "name" from {@link #getAttributes()} + * @param nameAttributeKey the key used to access the user's "name" from + * {@link #getAttributes()} */ - public DefaultOidcUser(Collection authorities, OidcIdToken idToken, String nameAttributeKey) { + public DefaultOidcUser(Collection authorities, OidcIdToken idToken, + String nameAttributeKey) { this(authorities, idToken, null, nameAttributeKey); } /** * Constructs a {@code DefaultOidcUser} using the provided parameters. - * * @param authorities the authorities granted to the user * @param idToken the {@link OidcIdToken ID Token} containing claims about the user - * @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user, may be {@code null} + * @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user, + * may be {@code null} */ - public DefaultOidcUser(Collection authorities, OidcIdToken idToken, OidcUserInfo userInfo) { + public DefaultOidcUser(Collection authorities, OidcIdToken idToken, + OidcUserInfo userInfo) { this(authorities, idToken, userInfo, IdTokenClaimNames.SUB); } /** * Constructs a {@code DefaultOidcUser} using the provided parameters. - * * @param authorities the authorities granted to the user * @param idToken the {@link OidcIdToken ID Token} containing claims about the user - * @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user, may be {@code null} - * @param nameAttributeKey the key used to access the user's "name" from {@link #getAttributes()} + * @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user, + * may be {@code null} + * @param nameAttributeKey the key used to access the user's "name" from + * {@link #getAttributes()} */ public DefaultOidcUser(Collection authorities, OidcIdToken idToken, - OidcUserInfo userInfo, String nameAttributeKey) { + OidcUserInfo userInfo, String nameAttributeKey) { super(authorities, OidcUserAuthority.collectClaims(idToken, userInfo), nameAttributeKey); this.idToken = idToken; this.userInfo = userInfo; @@ -105,4 +109,5 @@ public class DefaultOidcUser extends DefaultOAuth2User implements OidcUser { public OidcUserInfo getUserInfo() { return this.userInfo; } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/OidcUser.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/OidcUser.java index 15b3014061..e975c06f1a 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/OidcUser.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/OidcUser.java @@ -26,17 +26,18 @@ import org.springframework.security.oauth2.core.user.OAuth2User; import java.util.Map; /** - * A representation of a user {@code Principal} - * that is registered with an OpenID Connect 1.0 Provider. + * A representation of a user {@code Principal} that is registered with an OpenID Connect + * 1.0 Provider. * *

        - * An {@code OidcUser} contains "claims" about the authentication of the End-User. - * The claims are aggregated from the {@link OidcIdToken} and the {@link OidcUserInfo} (if available). + * An {@code OidcUser} contains "claims" about the authentication of the + * End-User. The claims are aggregated from the {@link OidcIdToken} and the + * {@link OidcUserInfo} (if available). * *

        * Implementation instances of this interface represent an {@link AuthenticatedPrincipal} - * which is associated to an {@link Authentication} object - * and may be accessed via {@link Authentication#getPrincipal()}. + * which is associated to an {@link Authentication} object and may be accessed via + * {@link Authentication#getPrincipal()}. * * @author Joe Grandja * @since 5.0 @@ -46,30 +47,31 @@ import java.util.Map; * @see OidcUserInfo * @see IdTokenClaimAccessor * @see StandardClaimAccessor - * @see ID Token - * @see Standard Claims + * @see ID Token + * @see Standard + * Claims */ public interface OidcUser extends OAuth2User, IdTokenClaimAccessor { /** - * Returns the claims about the user. - * The claims are aggregated from {@link #getIdToken()} and {@link #getUserInfo()} (if available). - * + * Returns the claims about the user. The claims are aggregated from + * {@link #getIdToken()} and {@link #getUserInfo()} (if available). * @return a {@code Map} of claims about the user */ Map getClaims(); /** * Returns the {@link OidcUserInfo UserInfo} containing claims about the user. - * * @return the {@link OidcUserInfo} containing claims about the user. */ OidcUserInfo getUserInfo(); /** * Returns the {@link OidcIdToken ID Token} containing claims about the user. - * * @return the {@link OidcIdToken} containing claims about the user. */ OidcIdToken getIdToken(); + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/OidcUserAuthority.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/OidcUserAuthority.java index 2d215b1326..210c310b85 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/OidcUserAuthority.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/OidcUserAuthority.java @@ -32,12 +32,13 @@ import java.util.Map; * @see OidcUser */ public class OidcUserAuthority extends OAuth2UserAuthority { + private final OidcIdToken idToken; + private final OidcUserInfo userInfo; /** * Constructs a {@code OidcUserAuthority} using the provided parameters. - * * @param idToken the {@link OidcIdToken ID Token} containing claims about the user */ public OidcUserAuthority(OidcIdToken idToken) { @@ -45,11 +46,11 @@ public class OidcUserAuthority extends OAuth2UserAuthority { } /** - * Constructs a {@code OidcUserAuthority} using the provided parameters - * and defaults {@link #getAuthority()} to {@code ROLE_USER}. - * + * Constructs a {@code OidcUserAuthority} using the provided parameters and defaults + * {@link #getAuthority()} to {@code ROLE_USER}. * @param idToken the {@link OidcIdToken ID Token} containing claims about the user - * @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user, may be {@code null} + * @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user, + * may be {@code null} */ public OidcUserAuthority(OidcIdToken idToken, OidcUserInfo userInfo) { this("ROLE_USER", idToken, userInfo); @@ -57,10 +58,10 @@ public class OidcUserAuthority extends OAuth2UserAuthority { /** * Constructs a {@code OidcUserAuthority} using the provided parameters. - * * @param authority the authority granted to the user * @param idToken the {@link OidcIdToken ID Token} containing claims about the user - * @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user, may be {@code null} + * @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user, + * may be {@code null} */ public OidcUserAuthority(String authority, OidcIdToken idToken, OidcUserInfo userInfo) { super(authority, collectClaims(idToken, userInfo)); @@ -70,7 +71,6 @@ public class OidcUserAuthority extends OAuth2UserAuthority { /** * Returns the {@link OidcIdToken ID Token} containing claims about the user. - * * @return the {@link OidcIdToken} containing claims about the user. */ public OidcIdToken getIdToken() { @@ -78,8 +78,8 @@ public class OidcUserAuthority extends OAuth2UserAuthority { } /** - * Returns the {@link OidcUserInfo UserInfo} containing claims about the user, may be {@code null}. - * + * Returns the {@link OidcUserInfo UserInfo} containing claims about the user, may be + * {@code null}. * @return the {@link OidcUserInfo} containing claims about the user, or {@code null} */ public OidcUserInfo getUserInfo() { @@ -103,9 +103,7 @@ public class OidcUserAuthority extends OAuth2UserAuthority { if (!this.getIdToken().equals(that.getIdToken())) { return false; } - return this.getUserInfo() != null ? - this.getUserInfo().equals(that.getUserInfo()) : - that.getUserInfo() == null; + return this.getUserInfo() != null ? this.getUserInfo().equals(that.getUserInfo()) : that.getUserInfo() == null; } @Override @@ -125,4 +123,5 @@ public class OidcUserAuthority extends OAuth2UserAuthority { claims.putAll(idToken.getClaims()); return claims; } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/package-info.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/package-info.java index 3af0286c26..eaaf28ff6d 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/package-info.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/oidc/user/package-info.java @@ -14,6 +14,7 @@ * limitations under the License. */ /** - * Provides a model for an OpenID Connect Core 1.0 representation of a user {@code Principal}. + * Provides a model for an OpenID Connect Core 1.0 representation of a user + * {@code Principal}. */ package org.springframework.security.oauth2.core.oidc.user; diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/package-info.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/package-info.java index 77190dd447..e723882d6c 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/package-info.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/package-info.java @@ -14,6 +14,7 @@ * limitations under the License. */ /** - * Core classes and interfaces providing support for the OAuth 2.0 Authorization Framework. + * Core classes and interfaces providing support for the OAuth 2.0 Authorization + * Framework. */ package org.springframework.security.oauth2.core; diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/DefaultOAuth2User.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/DefaultOAuth2User.java index 7657d6b1b7..c31312a8ad 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/DefaultOAuth2User.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/DefaultOAuth2User.java @@ -34,12 +34,11 @@ import java.util.LinkedHashSet; * The default implementation of an {@link OAuth2User}. * *

        - * User attribute names are not standardized between providers - * and therefore it is required to supply the key - * for the user's "name" attribute to one of the constructors. - * The key will be used for accessing the "name" of the - * {@code Principal} (user) via {@link #getAttributes()} - * and returning it from {@link #getName()}. + * User attribute names are not standardized between providers and therefore it is + * required to supply the key for the user's "name" attribute to one of + * the constructors. The key will be used for accessing the "name" of the + * {@code Principal} (user) via {@link #getAttributes()} and returning it from + * {@link #getName()}. * * @author Joe Grandja * @author Eddú Meléndez @@ -47,19 +46,24 @@ import java.util.LinkedHashSet; * @since 5.0 */ public class DefaultOAuth2User implements OAuth2User, Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private final Set authorities; + private final Map attributes; + private final String nameAttributeKey; /** * Constructs a {@code DefaultOAuth2User} using the provided parameters. - * - * @param authorities the authorities granted to the user - * @param attributes the attributes about the user - * @param nameAttributeKey the key used to access the user's "name" from {@link #getAttributes()} + * @param authorities the authorities granted to the user + * @param attributes the attributes about the user + * @param nameAttributeKey the key used to access the user's "name" from + * {@link #getAttributes()} */ - public DefaultOAuth2User(Collection authorities, Map attributes, String nameAttributeKey) { + public DefaultOAuth2User(Collection authorities, Map attributes, + String nameAttributeKey) { Assert.notEmpty(authorities, "authorities cannot be empty"); Assert.notEmpty(attributes, "attributes cannot be empty"); Assert.hasText(nameAttributeKey, "nameAttributeKey cannot be empty"); @@ -87,8 +91,8 @@ public class DefaultOAuth2User implements OAuth2User, Serializable { } private Set sortAuthorities(Collection authorities) { - SortedSet sortedAuthorities = - new TreeSet<>(Comparator.comparing(GrantedAuthority::getAuthority)); + SortedSet sortedAuthorities = new TreeSet<>( + Comparator.comparing(GrantedAuthority::getAuthority)); sortedAuthorities.addAll(authorities); return sortedAuthorities; } @@ -133,4 +137,5 @@ public class DefaultOAuth2User implements OAuth2User, Serializable { sb.append("]"); return sb.toString(); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/OAuth2User.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/OAuth2User.java index f25db96c01..d361098ede 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/OAuth2User.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/OAuth2User.java @@ -19,23 +19,24 @@ import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; /** - * A representation of a user {@code Principal} - * that is registered with an OAuth 2.0 Provider. + * A representation of a user {@code Principal} that is registered with an OAuth 2.0 + * Provider. * *

        - * An OAuth 2.0 user is composed of one or more attributes, for example, - * first name, middle name, last name, email, phone number, address, etc. - * Each user attribute has a "name" and "value" and - * is keyed by the "name" in {@link #getAttributes()}. + * An OAuth 2.0 user is composed of one or more attributes, for example, first name, + * middle name, last name, email, phone number, address, etc. Each user attribute has a + * "name" and "value" and is keyed by the "name" in + * {@link #getAttributes()}. * *

        - * NOTE: Attribute names are not standardized between providers and therefore will vary. - * Please consult the provider's API documentation for the set of supported user attribute names. + * NOTE: Attribute names are not standardized between providers and + * therefore will vary. Please consult the provider's API documentation for the set of + * supported user attribute names. * *

        - * Implementation instances of this interface represent an {@link OAuth2AuthenticatedPrincipal} - * which is associated to an {@link Authentication} object - * and may be accessed via {@link Authentication#getPrincipal()}. + * Implementation instances of this interface represent an + * {@link OAuth2AuthenticatedPrincipal} which is associated to an {@link Authentication} + * object and may be accessed via {@link Authentication#getPrincipal()}. * * @author Joe Grandja * @author Eddú Meléndez diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/OAuth2UserAuthority.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/OAuth2UserAuthority.java index 161fc1f64c..d0e513bcd6 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/OAuth2UserAuthority.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/user/OAuth2UserAuthority.java @@ -31,14 +31,16 @@ import java.util.Map; * @see OAuth2User */ public class OAuth2UserAuthority implements GrantedAuthority { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + private final String authority; + private final Map attributes; /** - * Constructs a {@code OAuth2UserAuthority} using the provided parameters - * and defaults {@link #getAuthority()} to {@code ROLE_USER}. - * + * Constructs a {@code OAuth2UserAuthority} using the provided parameters and defaults + * {@link #getAuthority()} to {@code ROLE_USER}. * @param attributes the attributes about the user */ public OAuth2UserAuthority(Map attributes) { @@ -47,7 +49,6 @@ public class OAuth2UserAuthority implements GrantedAuthority { /** * Constructs a {@code OAuth2UserAuthority} using the provided parameters. - * * @param authority the authority granted to the user * @param attributes the attributes about the user */ @@ -65,7 +66,6 @@ public class OAuth2UserAuthority implements GrantedAuthority { /** * Returns the attributes about the user. - * * @return a {@code Map} of attributes about the user */ public Map getAttributes() { @@ -100,4 +100,5 @@ public class OAuth2UserAuthority implements GrantedAuthority { public String toString() { return this.getAuthority(); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2AccessTokenResponseBodyExtractor.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2AccessTokenResponseBodyExtractor.java index b6de896d32..fdd4407674 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2AccessTokenResponseBodyExtractor.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2AccessTokenResponseBodyExtractor.java @@ -41,7 +41,9 @@ import java.util.Map; import java.util.Set; /** - * Provides a way to create an {@link OAuth2AccessTokenResponse} from a {@link ReactiveHttpInputMessage} + * Provides a way to create an {@link OAuth2AccessTokenResponse} from a + * {@link ReactiveHttpInputMessage} + * * @author Rob Winch * @since 5.1 */ @@ -50,16 +52,18 @@ class OAuth2AccessTokenResponseBodyExtractor private static final String INVALID_TOKEN_RESPONSE_ERROR_CODE = "invalid_token_response"; - OAuth2AccessTokenResponseBodyExtractor() {} + OAuth2AccessTokenResponseBodyExtractor() { + } @Override - public Mono extract(ReactiveHttpInputMessage inputMessage, - Context context) { - ParameterizedTypeReference> type = new ParameterizedTypeReference>() {}; + public Mono extract(ReactiveHttpInputMessage inputMessage, Context context) { + ParameterizedTypeReference> type = new ParameterizedTypeReference>() { + }; BodyExtractor>, ReactiveHttpInputMessage> delegate = BodyExtractors.toMono(type); return delegate.extract(inputMessage, context) .onErrorMap(e -> new OAuth2AuthorizationException( - invalidTokenResponse("An error occurred parsing the Access Token response: " + e.getMessage()), e)) + invalidTokenResponse("An error occurred parsing the Access Token response: " + e.getMessage()), + e)) .switchIfEmpty(Mono.error(() -> new OAuth2AuthorizationException( invalidTokenResponse("Empty OAuth 2.0 Access Token Response")))) .map(OAuth2AccessTokenResponseBodyExtractor::parse) @@ -79,23 +83,20 @@ class OAuth2AccessTokenResponseBodyExtractor } private static OAuth2Error invalidTokenResponse(String message) { - return new OAuth2Error( - INVALID_TOKEN_RESPONSE_ERROR_CODE, - message, - null); + return new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE, message, null); } private static Mono oauth2AccessTokenResponse(TokenResponse tokenResponse) { if (tokenResponse.indicatesSuccess()) { - return Mono.just(tokenResponse) - .cast(AccessTokenResponse.class); + return Mono.just(tokenResponse).cast(AccessTokenResponse.class); } TokenErrorResponse tokenErrorResponse = (TokenErrorResponse) tokenResponse; ErrorObject errorObject = tokenErrorResponse.getErrorObject(); OAuth2Error oauth2Error; if (errorObject == null) { oauth2Error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR); - } else { + } + else { oauth2Error = new OAuth2Error( errorObject.getCode() != null ? errorObject.getCode() : OAuth2ErrorCodes.SERVER_ERROR, errorObject.getDescription(), @@ -107,14 +108,13 @@ class OAuth2AccessTokenResponseBodyExtractor private static OAuth2AccessTokenResponse oauth2AccessTokenResponse(AccessTokenResponse accessTokenResponse) { AccessToken accessToken = accessTokenResponse.getTokens().getAccessToken(); OAuth2AccessToken.TokenType accessTokenType = null; - if (OAuth2AccessToken.TokenType.BEARER.getValue() - .equalsIgnoreCase(accessToken.getType().getValue())) { + if (OAuth2AccessToken.TokenType.BEARER.getValue().equalsIgnoreCase(accessToken.getType().getValue())) { accessTokenType = OAuth2AccessToken.TokenType.BEARER; } long expiresIn = accessToken.getLifetime(); - Set scopes = accessToken.getScope() == null ? - Collections.emptySet() : new LinkedHashSet<>(accessToken.getScope().toStringList()); + Set scopes = accessToken.getScope() == null ? Collections.emptySet() + : new LinkedHashSet<>(accessToken.getScope().toStringList()); String refreshToken = null; if (accessTokenResponse.getTokens().getRefreshToken() != null) { @@ -123,12 +123,9 @@ class OAuth2AccessTokenResponseBodyExtractor Map additionalParameters = new LinkedHashMap<>(accessTokenResponse.getCustomParameters()); - return OAuth2AccessTokenResponse.withToken(accessToken.getValue()) - .tokenType(accessTokenType) - .expiresIn(expiresIn) - .scopes(scopes) - .refreshToken(refreshToken) - .additionalParameters(additionalParameters) - .build(); + return OAuth2AccessTokenResponse.withToken(accessToken.getValue()).tokenType(accessTokenType) + .expiresIn(expiresIn).scopes(scopes).refreshToken(refreshToken) + .additionalParameters(additionalParameters).build(); } + } diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2BodyExtractors.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2BodyExtractors.java index 4818f7a064..10625ce160 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2BodyExtractors.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2BodyExtractors.java @@ -23,6 +23,7 @@ import reactor.core.publisher.Mono; /** * Static factory methods for OAuth2 {@link BodyExtractor} implementations. + * * @author Rob Winch * @since 5.1 */ @@ -36,5 +37,7 @@ public abstract class OAuth2BodyExtractors { return new OAuth2AccessTokenResponseBodyExtractor(); } - private OAuth2BodyExtractors() {} + private OAuth2BodyExtractors() { + } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/AuthenticationMethodTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/AuthenticationMethodTests.java index 3a0f698659..ce937dea1a 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/AuthenticationMethodTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/AuthenticationMethodTests.java @@ -45,4 +45,5 @@ public class AuthenticationMethodTests { public void getValueWhenFormAuthenticationTypeThenReturnQuery() { assertThat(AuthenticationMethod.QUERY.getValue()).isEqualTo("query"); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/AuthorizationGrantTypeTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/AuthorizationGrantTypeTests.java index 8205e162ca..9142d08a9e 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/AuthorizationGrantTypeTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/AuthorizationGrantTypeTests.java @@ -50,4 +50,5 @@ public class AuthorizationGrantTypeTests { public void getValueWhenPasswordGrantTypeThenReturnPassword() { assertThat(AuthorizationGrantType.PASSWORD.getValue()).isEqualTo("password"); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/ClaimAccessorTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/ClaimAccessorTests.java index 29fa8154bd..4a5a8a2854 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/ClaimAccessorTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/ClaimAccessorTests.java @@ -34,7 +34,9 @@ import static org.assertj.core.api.Assertions.catchThrowable; * @author Joe Grandja */ public class ClaimAccessorTests { + private Map claims = new HashMap<>(); + private ClaimAccessor claimAccessor = (() -> this.claims); @Before @@ -49,8 +51,8 @@ public class ClaimAccessorTests { String claimName = "date"; this.claims.put(claimName, Date.from(expectedClaimValue)); - assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween( - expectedClaimValue.minusSeconds(1), expectedClaimValue.plusSeconds(1)); + assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween(expectedClaimValue.minusSeconds(1), + expectedClaimValue.plusSeconds(1)); } // gh-5191 @@ -60,8 +62,8 @@ public class ClaimAccessorTests { String claimName = "longSeconds"; this.claims.put(claimName, expectedClaimValue.getEpochSecond()); - assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween( - expectedClaimValue.minusSeconds(1), expectedClaimValue.plusSeconds(1)); + assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween(expectedClaimValue.minusSeconds(1), + expectedClaimValue.plusSeconds(1)); } @Test @@ -70,8 +72,8 @@ public class ClaimAccessorTests { String claimName = "instant"; this.claims.put(claimName, expectedClaimValue); - assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween( - expectedClaimValue.minusSeconds(1), expectedClaimValue.plusSeconds(1)); + assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween(expectedClaimValue.minusSeconds(1), + expectedClaimValue.plusSeconds(1)); } // gh-5250 @@ -81,8 +83,8 @@ public class ClaimAccessorTests { String claimName = "integerSeconds"; this.claims.put(claimName, Long.valueOf(expectedClaimValue.getEpochSecond()).intValue()); - assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween( - expectedClaimValue.minusSeconds(1), expectedClaimValue.plusSeconds(1)); + assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween(expectedClaimValue.minusSeconds(1), + expectedClaimValue.plusSeconds(1)); } // gh-5250 @@ -92,8 +94,8 @@ public class ClaimAccessorTests { String claimName = "doubleSeconds"; this.claims.put(claimName, Long.valueOf(expectedClaimValue.getEpochSecond()).doubleValue()); - assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween( - expectedClaimValue.minusSeconds(1), expectedClaimValue.plusSeconds(1)); + assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween(expectedClaimValue.minusSeconds(1), + expectedClaimValue.plusSeconds(1)); } // gh-5608 @@ -140,8 +142,11 @@ public class ClaimAccessorTests { String claimName = "boolean"; this.claims.put(claimName, expectedClaimValue); - Throwable thrown = catchThrowable(() -> { boolean actualClaimValue = this.claimAccessor.getClaim(claimName); }); + Throwable thrown = catchThrowable(() -> { + boolean actualClaimValue = this.claimAccessor.getClaim(claimName); + }); assertThat(thrown).isInstanceOf(ClassCastException.class); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/ClientAuthenticationMethodTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/ClientAuthenticationMethodTests.java index 174388b7ac..fcea86cdf2 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/ClientAuthenticationMethodTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/ClientAuthenticationMethodTests.java @@ -45,4 +45,5 @@ public class ClientAuthenticationMethodTests { public void getValueWhenAuthenticationMethodNoneThenReturnNone() { assertThat(ClientAuthenticationMethod.NONE.getValue()).isEqualTo("none"); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/DefaultOAuth2AuthenticatedPrincipalTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/DefaultOAuth2AuthenticatedPrincipalTests.java index 8d794e7a09..012fc99b46 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/DefaultOAuth2AuthenticatedPrincipalTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/DefaultOAuth2AuthenticatedPrincipalTests.java @@ -34,8 +34,11 @@ import static org.assertj.core.api.Assertions.assertThatCode; * @author Josh Cummings */ public class DefaultOAuth2AuthenticatedPrincipalTests { + String name = "test-subject"; + Map attributes = Collections.singletonMap("sub", this.name); + Collection authorities = AuthorityUtils.createAuthorityList("SCOPE_read"); @Test @@ -49,33 +52,34 @@ public class DefaultOAuth2AuthenticatedPrincipalTests { @Test public void constructorWhenAuthoritiesIsNullOrEmptyThenNoAuthorities() { - Collection authorities = - new DefaultOAuth2AuthenticatedPrincipal(this.attributes, null).getAuthorities(); + Collection authorities = new DefaultOAuth2AuthenticatedPrincipal(this.attributes, + null).getAuthorities(); assertThat(authorities).isEmpty(); - authorities = new DefaultOAuth2AuthenticatedPrincipal(this.attributes, - Collections.emptyList()).getAuthorities(); + authorities = new DefaultOAuth2AuthenticatedPrincipal(this.attributes, Collections.emptyList()) + .getAuthorities(); assertThat(authorities).isEmpty(); } @Test public void constructorWhenNameIsNullThenFallsbackToSubAttribute() { - OAuth2AuthenticatedPrincipal principal = - new DefaultOAuth2AuthenticatedPrincipal(null, this.attributes, this.authorities); + OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal(null, this.attributes, + this.authorities); assertThat(principal.getName()).isEqualTo(this.attributes.get("sub")); } @Test public void getNameWhenInConstructorThenReturns() { - OAuth2AuthenticatedPrincipal principal = - new DefaultOAuth2AuthenticatedPrincipal("other-subject", this.attributes, this.authorities); + OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal("other-subject", + this.attributes, this.authorities); assertThat(principal.getName()).isEqualTo("other-subject"); } @Test public void getAttributeWhenGivenKeyThenReturnsValue() { - OAuth2AuthenticatedPrincipal principal = - new DefaultOAuth2AuthenticatedPrincipal(this.attributes, this.authorities); + OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal(this.attributes, + this.authorities); assertThat((String) principal.getAttribute("sub")).isEqualTo("test-subject"); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/DelegatingOAuth2TokenValidatorTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/DelegatingOAuth2TokenValidatorTests.java index eb9bc26bbc..621318f6a6 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/DelegatingOAuth2TokenValidatorTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/DelegatingOAuth2TokenValidatorTests.java @@ -34,13 +34,12 @@ import static org.mockito.Mockito.when; * @author Josh Cummings */ public class DelegatingOAuth2TokenValidatorTests { - private static final OAuth2Error DETAIL = new OAuth2Error( - "error", "description", "uri"); + + private static final OAuth2Error DETAIL = new OAuth2Error("error", "description", "uri"); @Test public void validateWhenNoValidatorsConfiguredThenReturnsSuccessfulResult() { - DelegatingOAuth2TokenValidator tokenValidator = - new DelegatingOAuth2TokenValidator<>(); + DelegatingOAuth2TokenValidator tokenValidator = new DelegatingOAuth2TokenValidator<>(); AbstractOAuth2Token token = mock(AbstractOAuth2Token.class); assertThat(tokenValidator.validate(token).hasErrors()).isFalse(); @@ -51,17 +50,14 @@ public class DelegatingOAuth2TokenValidatorTests { OAuth2TokenValidator success = mock(OAuth2TokenValidator.class); OAuth2TokenValidator failure = mock(OAuth2TokenValidator.class); - when(success.validate(any(AbstractOAuth2Token.class))) - .thenReturn(OAuth2TokenValidatorResult.success()); - when(failure.validate(any(AbstractOAuth2Token.class))) - .thenReturn(OAuth2TokenValidatorResult.failure(DETAIL)); + when(success.validate(any(AbstractOAuth2Token.class))).thenReturn(OAuth2TokenValidatorResult.success()); + when(failure.validate(any(AbstractOAuth2Token.class))).thenReturn(OAuth2TokenValidatorResult.failure(DETAIL)); - DelegatingOAuth2TokenValidator tokenValidator = - new DelegatingOAuth2TokenValidator<>(Arrays.asList(success, failure)); + DelegatingOAuth2TokenValidator tokenValidator = new DelegatingOAuth2TokenValidator<>( + Arrays.asList(success, failure)); AbstractOAuth2Token token = mock(AbstractOAuth2Token.class); - OAuth2TokenValidatorResult result = - tokenValidator.validate(token); + OAuth2TokenValidatorResult result = tokenValidator.validate(token); assertThat(result.hasErrors()).isTrue(); assertThat(result.getErrors()).containsExactly(DETAIL); @@ -79,12 +75,11 @@ public class DelegatingOAuth2TokenValidatorTests { when(secondFailure.validate(any(AbstractOAuth2Token.class))) .thenReturn(OAuth2TokenValidatorResult.failure(otherDetail)); - DelegatingOAuth2TokenValidator tokenValidator = - new DelegatingOAuth2TokenValidator<>(firstFailure, secondFailure); + DelegatingOAuth2TokenValidator tokenValidator = new DelegatingOAuth2TokenValidator<>( + firstFailure, secondFailure); AbstractOAuth2Token token = mock(AbstractOAuth2Token.class); - OAuth2TokenValidatorResult result = - tokenValidator.validate(token); + OAuth2TokenValidatorResult result = tokenValidator.validate(token); assertThat(result.hasErrors()).isTrue(); assertThat(result.getErrors()).containsExactly(DETAIL, otherDetail); @@ -95,17 +90,14 @@ public class DelegatingOAuth2TokenValidatorTests { OAuth2TokenValidator firstSuccess = mock(OAuth2TokenValidator.class); OAuth2TokenValidator secondSuccess = mock(OAuth2TokenValidator.class); - when(firstSuccess.validate(any(AbstractOAuth2Token.class))) - .thenReturn(OAuth2TokenValidatorResult.success()); - when(secondSuccess.validate(any(AbstractOAuth2Token.class))) - .thenReturn(OAuth2TokenValidatorResult.success()); + when(firstSuccess.validate(any(AbstractOAuth2Token.class))).thenReturn(OAuth2TokenValidatorResult.success()); + when(secondSuccess.validate(any(AbstractOAuth2Token.class))).thenReturn(OAuth2TokenValidatorResult.success()); - DelegatingOAuth2TokenValidator tokenValidator = - new DelegatingOAuth2TokenValidator<>(Arrays.asList(firstSuccess, secondSuccess)); + DelegatingOAuth2TokenValidator tokenValidator = new DelegatingOAuth2TokenValidator<>( + Arrays.asList(firstSuccess, secondSuccess)); AbstractOAuth2Token token = mock(AbstractOAuth2Token.class); - OAuth2TokenValidatorResult result = - tokenValidator.validate(token); + OAuth2TokenValidatorResult result = tokenValidator.validate(token); assertThat(result.hasErrors()).isFalse(); assertThat(result.getErrors()).isEmpty(); @@ -113,9 +105,9 @@ public class DelegatingOAuth2TokenValidatorTests { @Test public void constructorWhenInvokedWithNullValidatorListThenThrowsIllegalArgumentException() { - assertThatCode(() -> new DelegatingOAuth2TokenValidator<> - ((Collection>) null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> new DelegatingOAuth2TokenValidator<>( + (Collection>) null)) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -123,15 +115,13 @@ public class DelegatingOAuth2TokenValidatorTests { OAuth2TokenValidator firstSuccess = mock(OAuth2TokenValidator.class); OAuth2TokenValidator secondSuccess = mock(OAuth2TokenValidator.class); - when(firstSuccess.validate(any(AbstractOAuth2Token.class))) - .thenReturn(OAuth2TokenValidatorResult.success()); - when(secondSuccess.validate(any(AbstractOAuth2Token.class))) - .thenReturn(OAuth2TokenValidatorResult.success()); + when(firstSuccess.validate(any(AbstractOAuth2Token.class))).thenReturn(OAuth2TokenValidatorResult.success()); + when(secondSuccess.validate(any(AbstractOAuth2Token.class))).thenReturn(OAuth2TokenValidatorResult.success()); - DelegatingOAuth2TokenValidator firstValidator = - new DelegatingOAuth2TokenValidator<>(Arrays.asList(firstSuccess, secondSuccess)); - DelegatingOAuth2TokenValidator secondValidator = - new DelegatingOAuth2TokenValidator<>(firstSuccess, secondSuccess); + DelegatingOAuth2TokenValidator firstValidator = new DelegatingOAuth2TokenValidator<>( + Arrays.asList(firstSuccess, secondSuccess)); + DelegatingOAuth2TokenValidator secondValidator = new DelegatingOAuth2TokenValidator<>( + firstSuccess, secondSuccess); AbstractOAuth2Token token = mock(AbstractOAuth2Token.class); @@ -141,4 +131,5 @@ public class DelegatingOAuth2TokenValidatorTests { verify(firstSuccess, times(2)).validate(token); verify(secondSuccess, times(2)).validate(token); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2AccessTokenTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2AccessTokenTests.java index ccede95337..4a63db8351 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2AccessTokenTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2AccessTokenTests.java @@ -31,10 +31,15 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Joe Grandja */ public class OAuth2AccessTokenTests { + private static final OAuth2AccessToken.TokenType TOKEN_TYPE = OAuth2AccessToken.TokenType.BEARER; + private static final String TOKEN_VALUE = "access-token"; + private static final Instant ISSUED_AT = Instant.now(); + private static final Instant EXPIRES_AT = Instant.from(ISSUED_AT).plusSeconds(60); + private static final Set SCOPES = new LinkedHashSet<>(Arrays.asList("scope1", "scope2")); @Test @@ -64,8 +69,7 @@ public class OAuth2AccessTokenTests { @Test public void constructorWhenAllParametersProvidedAndValidThenCreated() { - OAuth2AccessToken accessToken = new OAuth2AccessToken( - TOKEN_TYPE, TOKEN_VALUE, ISSUED_AT, EXPIRES_AT, SCOPES); + OAuth2AccessToken accessToken = new OAuth2AccessToken(TOKEN_TYPE, TOKEN_VALUE, ISSUED_AT, EXPIRES_AT, SCOPES); assertThat(accessToken.getTokenType()).isEqualTo(TOKEN_TYPE); assertThat(accessToken.getTokenValue()).isEqualTo(TOKEN_VALUE); @@ -77,8 +81,7 @@ public class OAuth2AccessTokenTests { // gh-5492 @Test public void constructorWhenCreatedThenIsSerializableAndDeserializable() { - OAuth2AccessToken accessToken = new OAuth2AccessToken( - TOKEN_TYPE, TOKEN_VALUE, ISSUED_AT, EXPIRES_AT, SCOPES); + OAuth2AccessToken accessToken = new OAuth2AccessToken(TOKEN_TYPE, TOKEN_VALUE, ISSUED_AT, EXPIRES_AT, SCOPES); byte[] serialized = SerializationUtils.serialize(accessToken); accessToken = (OAuth2AccessToken) SerializationUtils.deserialize(serialized); @@ -89,4 +92,5 @@ public class OAuth2AccessTokenTests { assertThat(accessToken.getExpiresAt()).isEqualTo(EXPIRES_AT); assertThat(accessToken.getScopes()).isEqualTo(SCOPES); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2ErrorTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2ErrorTests.java index 9cc9b12299..bacc7a3e0d 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2ErrorTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2ErrorTests.java @@ -25,8 +25,11 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Joe Grandja */ public class OAuth2ErrorTests { + private static final String ERROR_CODE = "error-code"; + private static final String ERROR_DESCRIPTION = "error-description"; + private static final String ERROR_URI = "error-uri"; @Test(expected = IllegalArgumentException.class) @@ -42,4 +45,5 @@ public class OAuth2ErrorTests { assertThat(error.getDescription()).isEqualTo(ERROR_DESCRIPTION); assertThat(error.getUri()).isEqualTo(ERROR_URI); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2TokenValidatorResultTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2TokenValidatorResultTests.java index 22c56c1576..940d485a9b 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2TokenValidatorResultTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2TokenValidatorResultTests.java @@ -28,8 +28,8 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Josh Cummings */ public class OAuth2TokenValidatorResultTests { - private static final OAuth2Error DETAIL = new OAuth2Error( - "error", "description", "uri"); + + private static final OAuth2Error DETAIL = new OAuth2Error("error", "description", "uri"); @Test public void successWhenInvokedThenReturnsSuccessfulResult() { @@ -52,4 +52,5 @@ public class OAuth2TokenValidatorResultTests { assertThat(failure.hasErrors()).isTrue(); assertThat(failure.getErrors()).containsExactly(DETAIL, DETAIL); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/TestOAuth2AccessTokens.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/TestOAuth2AccessTokens.java index 62ca87ff48..c4ba056f9f 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/TestOAuth2AccessTokens.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/TestOAuth2AccessTokens.java @@ -26,18 +26,15 @@ import java.util.HashSet; * @since 5.1 */ public class TestOAuth2AccessTokens { + public static OAuth2AccessToken noScopes() { - return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "no-scopes", - Instant.now(), + return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "no-scopes", Instant.now(), Instant.now().plus(Duration.ofDays(1))); } public static OAuth2AccessToken scopes(String... scopes) { - return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "scopes", - Instant.now(), - Instant.now().plus(Duration.ofDays(1)), - new HashSet<>(Arrays.asList(scopes))); + return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "scopes", Instant.now(), + Instant.now().plus(Duration.ofDays(1)), new HashSet<>(Arrays.asList(scopes))); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/TestOAuth2RefreshTokens.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/TestOAuth2RefreshTokens.java index 8face452f5..69d56d33bb 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/TestOAuth2RefreshTokens.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/TestOAuth2RefreshTokens.java @@ -23,7 +23,9 @@ import java.time.Instant; * @since 5.1 */ public class TestOAuth2RefreshTokens { + public static OAuth2RefreshToken refreshToken() { return new OAuth2RefreshToken("refresh-token", Instant.now()); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/converter/ClaimConversionServiceTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/converter/ClaimConversionServiceTests.java index c7b8cc3571..42cb3ffdb4 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/converter/ClaimConversionServiceTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/converter/ClaimConversionServiceTests.java @@ -38,6 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @since 5.2 */ public class ClaimConversionServiceTests { + private final ConversionService conversionService = ClaimConversionService.getSharedInstance(); @Test @@ -104,7 +105,8 @@ public class ClaimConversionServiceTests { Instant instant = Instant.now(); assertThat(this.conversionService.convert(String.valueOf(instant.getEpochSecond()), Instant.class)) .isEqualTo(instant.truncatedTo(ChronoUnit.SECONDS)); - assertThat(this.conversionService.convert(String.valueOf(instant.toString()), Instant.class)).isEqualTo(instant); + assertThat(this.conversionService.convert(String.valueOf(instant.toString()), Instant.class)) + .isEqualTo(instant); } @Test @@ -179,8 +181,7 @@ public class ClaimConversionServiceTests { @Test public void convertListStringWhenNotConvertibleThenReturnSingletonList() { String string = "not-convertible-list"; - assertThat(this.conversionService.convert(string, List.class)) - .isEqualTo(Collections.singletonList(string)); + assertThat(this.conversionService.convert(string, List.class)).isEqualTo(Collections.singletonList(string)); } @Test @@ -224,4 +225,5 @@ public class ClaimConversionServiceTests { List notConvertibleList = Lists.list("1", "2", "3", "4"); assertThat(this.conversionService.convert(notConvertibleList, Map.class)).isNull(); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverterTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverterTests.java index fee193f8e4..9996851324 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverterTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/converter/ClaimTypeConverterTests.java @@ -38,13 +38,21 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @since 5.2 */ public class ClaimTypeConverterTests { + private static final String STRING_CLAIM = "string-claim"; + private static final String BOOLEAN_CLAIM = "boolean-claim"; + private static final String INSTANT_CLAIM = "instant-claim"; + private static final String URL_CLAIM = "url-claim"; + private static final String COLLECTION_STRING_CLAIM = "collection-string-claim"; + private static final String LIST_STRING_CLAIM = "list-string-claim"; + private static final String MAP_STRING_OBJECT_CLAIM = "map-string-object-claim"; + private ClaimTypeConverter claimTypeConverter; @Before @@ -58,8 +66,8 @@ public class ClaimTypeConverterTests { TypeDescriptor.collection(Collection.class, TypeDescriptor.valueOf(String.class))); Converter listStringConverter = getConverter( TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class))); - Converter mapStringObjectConverter = getConverter( - TypeDescriptor.map(Map.class, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Object.class))); + Converter mapStringObjectConverter = getConverter(TypeDescriptor.map(Map.class, + TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Object.class))); Map> claimTypeConverters = new HashMap<>(); claimTypeConverters.put(STRING_CLAIM, stringConverter); @@ -79,8 +87,7 @@ public class ClaimTypeConverterTests { @Test public void constructorWhenConvertersNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new ClaimTypeConverter(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> new ClaimTypeConverter(null)).isInstanceOf(IllegalArgumentException.class); } @Test @@ -167,4 +174,5 @@ public class ClaimTypeConverterTests { assertThat(claims.get("claim1")).isSameAs("value1"); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/MapOAuth2AccessTokenResponseConverterTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/MapOAuth2AccessTokenResponseConverterTests.java index 6af7ed499d..e1bd4d0247 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/MapOAuth2AccessTokenResponseConverterTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/MapOAuth2AccessTokenResponseConverterTests.java @@ -41,7 +41,6 @@ public class MapOAuth2AccessTokenResponseConverterTests { this.messageConverter = new MapOAuth2AccessTokenResponseConverter(); } - @Test public void shouldConvertFull() { Map map = new HashMap<>(); @@ -123,4 +122,5 @@ public class MapOAuth2AccessTokenResponseConverterTests { Assert.assertNotNull(additionalParameters); Assert.assertEquals(0, additionalParameters.size()); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseMapConverterTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseMapConverterTests.java index 980155b6c9..0b6abc2dee 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseMapConverterTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseMapConverterTests.java @@ -40,7 +40,6 @@ public class OAuth2AccessTokenResponseMapConverterTests { this.messageConverter = new OAuth2AccessTokenResponseMapConverter(); } - @Test public void convertFull() { Map additionalParameters = new HashMap<>(); @@ -51,14 +50,9 @@ public class OAuth2AccessTokenResponseMapConverterTests { scopes.add("read"); scopes.add("write"); - OAuth2AccessTokenResponse build = OAuth2AccessTokenResponse - .withToken("access-token-value-1234") - .expiresIn(3699) - .additionalParameters(additionalParameters) - .refreshToken("refresh-token-value-1234") - .scopes(scopes) - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .build(); + OAuth2AccessTokenResponse build = OAuth2AccessTokenResponse.withToken("access-token-value-1234").expiresIn(3699) + .additionalParameters(additionalParameters).refreshToken("refresh-token-value-1234").scopes(scopes) + .tokenType(OAuth2AccessToken.TokenType.BEARER).build(); Map result = messageConverter.convert(build); Assert.assertEquals(7, result.size()); @@ -73,10 +67,8 @@ public class OAuth2AccessTokenResponseMapConverterTests { @Test public void convertMinimal() { - OAuth2AccessTokenResponse build = OAuth2AccessTokenResponse - .withToken("access-token-value-1234") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .build(); + OAuth2AccessTokenResponse build = OAuth2AccessTokenResponse.withToken("access-token-value-1234") + .tokenType(OAuth2AccessToken.TokenType.BEARER).build(); Map result = messageConverter.convert(build); Assert.assertEquals(3, result.size()); @@ -84,4 +76,5 @@ public class OAuth2AccessTokenResponseMapConverterTests { Assert.assertEquals("Bearer", result.get("token_type")); Assert.assertNotNull(result.get("expires_in")); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseTests.java index 8f2d3aa1cb..0e678aef39 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AccessTokenResponseTests.java @@ -34,46 +34,38 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Joe Grandja */ public class OAuth2AccessTokenResponseTests { + private static final String TOKEN_VALUE = "access-token"; + private static final String REFRESH_TOKEN_VALUE = "refresh-token"; + private static final long EXPIRES_IN = Instant.now().plusSeconds(5).toEpochMilli(); @Test(expected = IllegalArgumentException.class) public void buildWhenTokenValueIsNullThenThrowIllegalArgumentException() { - OAuth2AccessTokenResponse.withToken(null) - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(EXPIRES_IN) - .build(); + OAuth2AccessTokenResponse.withToken(null).tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(EXPIRES_IN) + .build(); } @Test(expected = IllegalArgumentException.class) public void buildWhenTokenTypeIsNullThenThrowIllegalArgumentException() { - OAuth2AccessTokenResponse.withToken(TOKEN_VALUE) - .tokenType(null) - .expiresIn(EXPIRES_IN) - .build(); + OAuth2AccessTokenResponse.withToken(TOKEN_VALUE).tokenType(null).expiresIn(EXPIRES_IN).build(); } @Test public void buildWhenExpiresInIsZeroThenExpiresAtOneSecondAfterIssueAt() { - OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse - .withToken(TOKEN_VALUE) - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(0) - .build(); - assertThat(tokenResponse.getAccessToken().getExpiresAt()).isEqualTo( - tokenResponse.getAccessToken().getIssuedAt().plusSeconds(1)); + OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse.withToken(TOKEN_VALUE) + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(0).build(); + assertThat(tokenResponse.getAccessToken().getExpiresAt()) + .isEqualTo(tokenResponse.getAccessToken().getIssuedAt().plusSeconds(1)); } @Test public void buildWhenExpiresInIsNegativeThenExpiresAtOneSecondAfterIssueAt() { - OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse - .withToken(TOKEN_VALUE) - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(-1L) - .build(); - assertThat(tokenResponse.getAccessToken().getExpiresAt()).isEqualTo( - tokenResponse.getAccessToken().getIssuedAt().plusSeconds(1)); + OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse.withToken(TOKEN_VALUE) + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(-1L).build(); + assertThat(tokenResponse.getAccessToken().getExpiresAt()) + .isEqualTo(tokenResponse.getAccessToken().getIssuedAt().plusSeconds(1)); } @Test @@ -84,14 +76,9 @@ public class OAuth2AccessTokenResponseTests { additionalParameters.put("param1", "value1"); additionalParameters.put("param2", "value2"); - OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse - .withToken(TOKEN_VALUE) - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(expiresAt.toEpochMilli()) - .scopes(scopes) - .refreshToken(REFRESH_TOKEN_VALUE) - .additionalParameters(additionalParameters) - .build(); + OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse.withToken(TOKEN_VALUE) + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(expiresAt.toEpochMilli()).scopes(scopes) + .refreshToken(REFRESH_TOKEN_VALUE).additionalParameters(additionalParameters).build(); assertThat(tokenResponse.getAccessToken()).isNotNull(); assertThat(tokenResponse.getAccessToken().getTokenValue()).isEqualTo(TOKEN_VALUE); @@ -111,24 +98,21 @@ public class OAuth2AccessTokenResponseTests { additionalParameters.put("param1", "value1"); additionalParameters.put("param2", "value2"); - OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse - .withToken(TOKEN_VALUE) - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(expiresAt.toEpochMilli()) - .scopes(scopes) - .refreshToken(REFRESH_TOKEN_VALUE) - .additionalParameters(additionalParameters) - .build(); + OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse.withToken(TOKEN_VALUE) + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(expiresAt.toEpochMilli()).scopes(scopes) + .refreshToken(REFRESH_TOKEN_VALUE).additionalParameters(additionalParameters).build(); - OAuth2AccessTokenResponse withResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse) - .build(); + OAuth2AccessTokenResponse withResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse).build(); - assertThat(withResponse.getAccessToken().getTokenValue()).isEqualTo(tokenResponse.getAccessToken().getTokenValue()); + assertThat(withResponse.getAccessToken().getTokenValue()) + .isEqualTo(tokenResponse.getAccessToken().getTokenValue()); assertThat(withResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER); assertThat(withResponse.getAccessToken().getIssuedAt()).isEqualTo(tokenResponse.getAccessToken().getIssuedAt()); - assertThat(withResponse.getAccessToken().getExpiresAt()).isEqualTo(tokenResponse.getAccessToken().getExpiresAt()); + assertThat(withResponse.getAccessToken().getExpiresAt()) + .isEqualTo(tokenResponse.getAccessToken().getExpiresAt()); assertThat(withResponse.getAccessToken().getScopes()).isEqualTo(tokenResponse.getAccessToken().getScopes()); - assertThat(withResponse.getRefreshToken().getTokenValue()).isEqualTo(tokenResponse.getRefreshToken().getTokenValue()); + assertThat(withResponse.getRefreshToken().getTokenValue()) + .isEqualTo(tokenResponse.getRefreshToken().getTokenValue()); assertThat(withResponse.getAdditionalParameters()).isEqualTo(tokenResponse.getAdditionalParameters()); } @@ -140,33 +124,26 @@ public class OAuth2AccessTokenResponseTests { additionalParameters.put("param1", "value1"); additionalParameters.put("param2", "value2"); - OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse - .withToken(TOKEN_VALUE) - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(expiresAt.toEpochMilli()) - .scopes(scopes) - .additionalParameters(additionalParameters) - .build(); + OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse.withToken(TOKEN_VALUE) + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(expiresAt.toEpochMilli()).scopes(scopes) + .additionalParameters(additionalParameters).build(); - OAuth2AccessTokenResponse withResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse) - .build(); + OAuth2AccessTokenResponse withResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse).build(); assertThat(withResponse.getRefreshToken()).isNull(); } @Test public void buildWhenResponseAndExpiresInThenExpiresAtEqualToIssuedAtPlusExpiresIn() { - OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse - .withToken(TOKEN_VALUE) - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .build(); + OAuth2AccessTokenResponse tokenResponse = OAuth2AccessTokenResponse.withToken(TOKEN_VALUE) + .tokenType(OAuth2AccessToken.TokenType.BEARER).build(); long expiresIn = 30; OAuth2AccessTokenResponse withResponse = OAuth2AccessTokenResponse.withResponse(tokenResponse) - .expiresIn(expiresIn) - .build(); + .expiresIn(expiresIn).build(); - assertThat(withResponse.getAccessToken().getExpiresAt()).isEqualTo( - withResponse.getAccessToken().getIssuedAt().plusSeconds(expiresIn)); + assertThat(withResponse.getAccessToken().getExpiresAt()) + .isEqualTo(withResponse.getAccessToken().getIssuedAt().plusSeconds(expiresIn)); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationExchangeTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationExchangeTests.java index 6986e19496..7c8cb0bc0e 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationExchangeTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationExchangeTests.java @@ -42,9 +42,10 @@ public class OAuth2AuthorizationExchangeTests { public void constructorWhenRequiredArgsProvidedThenCreated() { OAuth2AuthorizationRequest authorizationRequest = request().build(); OAuth2AuthorizationResponse authorizationResponse = success().build(); - OAuth2AuthorizationExchange authorizationExchange = - new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse); + OAuth2AuthorizationExchange authorizationExchange = new OAuth2AuthorizationExchange(authorizationRequest, + authorizationResponse); assertThat(authorizationExchange.getAuthorizationRequest()).isEqualTo(authorizationRequest); assertThat(authorizationExchange.getAuthorizationResponse()).isEqualTo(authorizationResponse); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequestTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequestTests.java index 8f0745d4f2..4805ed0770 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequestTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationRequestTests.java @@ -36,113 +36,70 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Joe Grandja */ public class OAuth2AuthorizationRequestTests { + private static final String AUTHORIZATION_URI = "https://provider.com/oauth2/authorize"; + private static final String CLIENT_ID = "client-id"; + private static final String REDIRECT_URI = "https://example.com"; + private static final Set SCOPES = new LinkedHashSet<>(Arrays.asList("scope1", "scope2")); + private static final String STATE = "state"; @Test public void buildWhenAuthorizationUriIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> - OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri(null) - .clientId(CLIENT_ID) - .redirectUri(REDIRECT_URI) - .scopes(SCOPES) - .state(STATE) - .build() - ).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> OAuth2AuthorizationRequest.authorizationCode().authorizationUri(null) + .clientId(CLIENT_ID).redirectUri(REDIRECT_URI).scopes(SCOPES).state(STATE).build()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void buildWhenClientIdIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> - OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri(AUTHORIZATION_URI) - .clientId(null) - .redirectUri(REDIRECT_URI) - .scopes(SCOPES) - .state(STATE) - .build() - ).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> OAuth2AuthorizationRequest.authorizationCode().authorizationUri(AUTHORIZATION_URI) + .clientId(null).redirectUri(REDIRECT_URI).scopes(SCOPES).state(STATE).build()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void buildWhenRedirectUriIsNullForImplicitThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> - OAuth2AuthorizationRequest.implicit() - .authorizationUri(AUTHORIZATION_URI) - .clientId(CLIENT_ID) - .redirectUri(null) - .scopes(SCOPES) - .state(STATE) - .build() - ).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> OAuth2AuthorizationRequest.implicit().authorizationUri(AUTHORIZATION_URI) + .clientId(CLIENT_ID).redirectUri(null).scopes(SCOPES).state(STATE).build()) + .isInstanceOf(IllegalArgumentException.class); } @Test public void buildWhenRedirectUriIsNullForAuthorizationCodeThenDoesNotThrowAnyException() { - assertThatCode(() -> - OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri(AUTHORIZATION_URI) - .clientId(CLIENT_ID) - .redirectUri(null) - .scopes(SCOPES) - .state(STATE) - .build()) - .doesNotThrowAnyException(); + assertThatCode(() -> OAuth2AuthorizationRequest.authorizationCode().authorizationUri(AUTHORIZATION_URI) + .clientId(CLIENT_ID).redirectUri(null).scopes(SCOPES).state(STATE).build()).doesNotThrowAnyException(); } @Test public void buildWhenScopesIsNullThenDoesNotThrowAnyException() { - assertThatCode(() -> - OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri(AUTHORIZATION_URI) - .clientId(CLIENT_ID) - .redirectUri(REDIRECT_URI) - .scopes(null) - .state(STATE) - .build()) - .doesNotThrowAnyException(); + assertThatCode(() -> OAuth2AuthorizationRequest.authorizationCode().authorizationUri(AUTHORIZATION_URI) + .clientId(CLIENT_ID).redirectUri(REDIRECT_URI).scopes(null).state(STATE).build()) + .doesNotThrowAnyException(); } @Test public void buildWhenStateIsNullThenDoesNotThrowAnyException() { - assertThatCode(() -> - OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri(AUTHORIZATION_URI) - .clientId(CLIENT_ID) - .redirectUri(REDIRECT_URI) - .scopes(SCOPES) - .state(null) - .build()) - .doesNotThrowAnyException(); + assertThatCode(() -> OAuth2AuthorizationRequest.authorizationCode().authorizationUri(AUTHORIZATION_URI) + .clientId(CLIENT_ID).redirectUri(REDIRECT_URI).scopes(SCOPES).state(null).build()) + .doesNotThrowAnyException(); } @Test public void buildWhenAdditionalParametersEmptyThenDoesNotThrowAnyException() { - assertThatCode(() -> - OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri(AUTHORIZATION_URI) - .clientId(CLIENT_ID) - .redirectUri(REDIRECT_URI) - .scopes(SCOPES) - .state(STATE) - .additionalParameters(Map::clear) - .build()) - .doesNotThrowAnyException(); + assertThatCode(() -> OAuth2AuthorizationRequest.authorizationCode().authorizationUri(AUTHORIZATION_URI) + .clientId(CLIENT_ID).redirectUri(REDIRECT_URI).scopes(SCOPES).state(STATE) + .additionalParameters(Map::clear).build()).doesNotThrowAnyException(); } @Test public void buildWhenImplicitThenGrantTypeResponseTypeIsSet() { OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.implicit() - .authorizationUri(AUTHORIZATION_URI) - .clientId(CLIENT_ID) - .redirectUri(REDIRECT_URI) - .scopes(SCOPES) - .state(STATE) - .build(); + .authorizationUri(AUTHORIZATION_URI).clientId(CLIENT_ID).redirectUri(REDIRECT_URI).scopes(SCOPES) + .state(STATE).build(); assertThat(authorizationRequest.getGrantType()).isEqualTo(AuthorizationGrantType.IMPLICIT); assertThat(authorizationRequest.getResponseType()).isEqualTo(OAuth2AuthorizationResponseType.TOKEN); } @@ -150,11 +107,7 @@ public class OAuth2AuthorizationRequestTests { @Test public void buildWhenAuthorizationCodeThenGrantTypeResponseTypeIsSet() { OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri(AUTHORIZATION_URI) - .clientId(CLIENT_ID) - .redirectUri(null) - .scopes(SCOPES) - .state(STATE) + .authorizationUri(AUTHORIZATION_URI).clientId(CLIENT_ID).redirectUri(null).scopes(SCOPES).state(STATE) .build(); assertThat(authorizationRequest.getGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); assertThat(authorizationRequest.getResponseType()).isEqualTo(OAuth2AuthorizationResponseType.CODE); @@ -171,15 +124,9 @@ public class OAuth2AuthorizationRequestTests { attributes.put("attribute2", "value2"); OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri(AUTHORIZATION_URI) - .clientId(CLIENT_ID) - .redirectUri(REDIRECT_URI) - .scopes(SCOPES) - .state(STATE) - .additionalParameters(additionalParameters) - .attributes(attributes) - .authorizationRequestUri(AUTHORIZATION_URI) - .build(); + .authorizationUri(AUTHORIZATION_URI).clientId(CLIENT_ID).redirectUri(REDIRECT_URI).scopes(SCOPES) + .state(STATE).additionalParameters(additionalParameters).attributes(attributes) + .authorizationRequestUri(AUTHORIZATION_URI).build(); assertThat(authorizationRequest.getAuthorizationUri()).isEqualTo(AUTHORIZATION_URI); assertThat(authorizationRequest.getGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); @@ -196,43 +143,27 @@ public class OAuth2AuthorizationRequestTests { @Test public void buildWhenScopesMultiThenSeparatedByEncodedSpace() { OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.implicit() - .authorizationUri(AUTHORIZATION_URI) - .clientId(CLIENT_ID) - .redirectUri(REDIRECT_URI) - .scopes(SCOPES) - .state(STATE) - .build(); + .authorizationUri(AUTHORIZATION_URI).clientId(CLIENT_ID).redirectUri(REDIRECT_URI).scopes(SCOPES) + .state(STATE).build(); assertThat(authorizationRequest.getAuthorizationRequestUri()) - .isEqualTo("https://provider.com/oauth2/authorize?" + - "response_type=token&client_id=client-id&" + - "scope=scope1%20scope2&state=state&" + - "redirect_uri=https://example.com"); + .isEqualTo("https://provider.com/oauth2/authorize?" + "response_type=token&client_id=client-id&" + + "scope=scope1%20scope2&state=state&" + "redirect_uri=https://example.com"); } @Test public void buildWhenAuthorizationRequestUriSetThenOverridesDefault() { OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri(AUTHORIZATION_URI) - .clientId(CLIENT_ID) - .redirectUri(REDIRECT_URI) - .scopes(SCOPES) - .state(STATE) - .authorizationRequestUri(AUTHORIZATION_URI) - .build(); + .authorizationUri(AUTHORIZATION_URI).clientId(CLIENT_ID).redirectUri(REDIRECT_URI).scopes(SCOPES) + .state(STATE).authorizationRequestUri(AUTHORIZATION_URI).build(); assertThat(authorizationRequest.getAuthorizationRequestUri()).isEqualTo(AUTHORIZATION_URI); } @Test public void buildWhenAuthorizationRequestUriFunctionSetThenOverridesDefault() { OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri(AUTHORIZATION_URI) - .clientId(CLIENT_ID) - .redirectUri(REDIRECT_URI) - .scopes(SCOPES) - .state(STATE) - .authorizationRequestUri(uriBuilder -> URI.create(AUTHORIZATION_URI)) - .build(); + .authorizationUri(AUTHORIZATION_URI).clientId(CLIENT_ID).redirectUri(REDIRECT_URI).scopes(SCOPES) + .state(STATE).authorizationRequestUri(uriBuilder -> URI.create(AUTHORIZATION_URI)).build(); assertThat(authorizationRequest.getAuthorizationRequestUri()).isEqualTo(AUTHORIZATION_URI); } @@ -243,30 +174,22 @@ public class OAuth2AuthorizationRequestTests { additionalParameters.put("param2", "value2"); OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri(AUTHORIZATION_URI) - .clientId(CLIENT_ID) - .redirectUri(REDIRECT_URI) - .scopes(SCOPES) - .state(STATE) - .additionalParameters(additionalParameters) - .build(); + .authorizationUri(AUTHORIZATION_URI).clientId(CLIENT_ID).redirectUri(REDIRECT_URI).scopes(SCOPES) + .state(STATE).additionalParameters(additionalParameters).build(); assertThat(authorizationRequest.getAuthorizationRequestUri()).isNotNull(); - assertThat(authorizationRequest.getAuthorizationRequestUri()) - .isEqualTo("https://provider.com/oauth2/authorize?" + - "response_type=code&client_id=client-id&" + - "scope=scope1%20scope2&state=state&" + - "redirect_uri=https://example.com¶m1=value1¶m2=value2"); + assertThat(authorizationRequest.getAuthorizationRequestUri()).isEqualTo("https://provider.com/oauth2/authorize?" + + "response_type=code&client_id=client-id&" + "scope=scope1%20scope2&state=state&" + + "redirect_uri=https://example.com¶m1=value1¶m2=value2"); } @Test public void buildWhenRequiredParametersSetThenAuthorizationRequestUriIncludesRequiredParametersOnly() { OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri(AUTHORIZATION_URI) - .clientId(CLIENT_ID) - .build(); + .authorizationUri(AUTHORIZATION_URI).clientId(CLIENT_ID).build(); - assertThat(authorizationRequest.getAuthorizationRequestUri()).isEqualTo("https://provider.com/oauth2/authorize?response_type=code&client_id=client-id"); + assertThat(authorizationRequest.getAuthorizationRequestUri()) + .isEqualTo("https://provider.com/oauth2/authorize?response_type=code&client_id=client-id"); } @Test @@ -285,58 +208,50 @@ public class OAuth2AuthorizationRequestTests { attributes.put("attribute2", "value2"); OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri(AUTHORIZATION_URI) - .clientId(CLIENT_ID) - .redirectUri(REDIRECT_URI) - .scopes(SCOPES) - .state(STATE) - .additionalParameters(additionalParameters) - .attributes(attributes) + .authorizationUri(AUTHORIZATION_URI).clientId(CLIENT_ID).redirectUri(REDIRECT_URI).scopes(SCOPES) + .state(STATE).additionalParameters(additionalParameters).attributes(attributes).build(); + + OAuth2AuthorizationRequest authorizationRequestCopy = OAuth2AuthorizationRequest.from(authorizationRequest) .build(); - OAuth2AuthorizationRequest authorizationRequestCopy = - OAuth2AuthorizationRequest.from(authorizationRequest).build(); - - assertThat(authorizationRequestCopy.getAuthorizationUri()).isEqualTo(authorizationRequest.getAuthorizationUri()); + assertThat(authorizationRequestCopy.getAuthorizationUri()) + .isEqualTo(authorizationRequest.getAuthorizationUri()); assertThat(authorizationRequestCopy.getGrantType()).isEqualTo(authorizationRequest.getGrantType()); assertThat(authorizationRequestCopy.getResponseType()).isEqualTo(authorizationRequest.getResponseType()); assertThat(authorizationRequestCopy.getClientId()).isEqualTo(authorizationRequest.getClientId()); assertThat(authorizationRequestCopy.getRedirectUri()).isEqualTo(authorizationRequest.getRedirectUri()); assertThat(authorizationRequestCopy.getScopes()).isEqualTo(authorizationRequest.getScopes()); assertThat(authorizationRequestCopy.getState()).isEqualTo(authorizationRequest.getState()); - assertThat(authorizationRequestCopy.getAdditionalParameters()).isEqualTo(authorizationRequest.getAdditionalParameters()); + assertThat(authorizationRequestCopy.getAdditionalParameters()) + .isEqualTo(authorizationRequest.getAdditionalParameters()); assertThat(authorizationRequestCopy.getAttributes()).isEqualTo(authorizationRequest.getAttributes()); - assertThat(authorizationRequestCopy.getAuthorizationRequestUri()).isEqualTo(authorizationRequest.getAuthorizationRequestUri()); + assertThat(authorizationRequestCopy.getAuthorizationRequestUri()) + .isEqualTo(authorizationRequest.getAuthorizationRequestUri()); } @Test public void buildWhenAuthorizationUriIncludesQueryParameterThenAuthorizationRequestUrlIncludesIt() { - OAuth2AuthorizationRequest authorizationRequest = - TestOAuth2AuthorizationRequests.request() - .authorizationUri(AUTHORIZATION_URI + - "?param1=value1¶m2=value2").build(); + OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.request() + .authorizationUri(AUTHORIZATION_URI + "?param1=value1¶m2=value2").build(); assertThat(authorizationRequest.getAuthorizationRequestUri()).isNotNull(); - assertThat(authorizationRequest.getAuthorizationRequestUri()) - .isEqualTo("https://provider.com/oauth2/authorize?" + - "param1=value1¶m2=value2&" + - "response_type=code&client_id=client-id&state=state&" + - "redirect_uri=https://example.com/authorize/oauth2/code/registration-id"); + assertThat(authorizationRequest.getAuthorizationRequestUri()).isEqualTo("https://provider.com/oauth2/authorize?" + + "param1=value1¶m2=value2&" + "response_type=code&client_id=client-id&state=state&" + + "redirect_uri=https://example.com/authorize/oauth2/code/registration-id"); } @Test public void buildWhenAuthorizationUriIncludesEscapedQueryParameterThenAuthorizationRequestUrlIncludesIt() { - OAuth2AuthorizationRequest authorizationRequest = - TestOAuth2AuthorizationRequests.request() - .authorizationUri(AUTHORIZATION_URI + - "?claims=%7B%22userinfo%22%3A%7B%22email_verified%22%3A%7B%22essential%22%3Atrue%7D%7D%7D").build(); + OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.request() + .authorizationUri(AUTHORIZATION_URI + + "?claims=%7B%22userinfo%22%3A%7B%22email_verified%22%3A%7B%22essential%22%3Atrue%7D%7D%7D") + .build(); assertThat(authorizationRequest.getAuthorizationRequestUri()).isNotNull(); - assertThat(authorizationRequest.getAuthorizationRequestUri()) - .isEqualTo("https://provider.com/oauth2/authorize?" + - "claims=%7B%22userinfo%22%3A%7B%22email_verified%22%3A%7B%22essential%22%3Atrue%7D%7D%7D&" + - "response_type=code&client_id=client-id&state=state&" + - "redirect_uri=https://example.com/authorize/oauth2/code/registration-id"); + assertThat(authorizationRequest.getAuthorizationRequestUri()).isEqualTo("https://provider.com/oauth2/authorize?" + + "claims=%7B%22userinfo%22%3A%7B%22email_verified%22%3A%7B%22essential%22%3Atrue%7D%7D%7D&" + + "response_type=code&client_id=client-id&state=state&" + + "redirect_uri=https://example.com/authorize/oauth2/code/registration-id"); } @Test @@ -345,16 +260,14 @@ public class OAuth2AuthorizationRequestTests { additionalParameters.put("item amount", "19.95" + '\u20ac'); additionalParameters.put("item name", "H" + '\u00c5' + "M" + '\u00d6'); additionalParameters.put('\u00e2' + "ge", "4" + '\u00bd'); - OAuth2AuthorizationRequest authorizationRequest = - TestOAuth2AuthorizationRequests.request() - .additionalParameters(additionalParameters) - .build(); + OAuth2AuthorizationRequest authorizationRequest = TestOAuth2AuthorizationRequests.request() + .additionalParameters(additionalParameters).build(); assertThat(authorizationRequest.getAuthorizationRequestUri()).isNotNull(); - assertThat(authorizationRequest.getAuthorizationRequestUri()) - .isEqualTo("https://example.com/login/oauth/authorize?" + - "response_type=code&client_id=client-id&state=state&" + - "redirect_uri=https://example.com/authorize/oauth2/code/registration-id&" + - "item%20amount=19.95%E2%82%AC&%C3%A2ge=4%C2%BD&item%20name=H%C3%85M%C3%96"); + assertThat(authorizationRequest.getAuthorizationRequestUri()).isEqualTo( + "https://example.com/login/oauth/authorize?" + "response_type=code&client_id=client-id&state=state&" + + "redirect_uri=https://example.com/authorize/oauth2/code/registration-id&" + + "item%20amount=19.95%E2%82%AC&%C3%A2ge=4%C2%BD&item%20name=H%C3%85M%C3%96"); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseTests.java index 00bd042b70..d3757fe5dd 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseTests.java @@ -26,43 +26,40 @@ import static org.assertj.core.api.Assertions.assertThatCode; * @author Joe Grandja */ public class OAuth2AuthorizationResponseTests { + private static final String AUTH_CODE = "auth-code"; + private static final String REDIRECT_URI = "https://example.com"; + private static final String STATE = "state"; + private static final String ERROR_CODE = "error-code"; + private static final String ERROR_DESCRIPTION = "error-description"; + private static final String ERROR_URI = "error-uri"; @Test(expected = IllegalArgumentException.class) public void buildSuccessResponseWhenAuthCodeIsNullThenThrowIllegalArgumentException() { - OAuth2AuthorizationResponse.success(null) - .redirectUri(REDIRECT_URI) - .state(STATE) - .build(); + OAuth2AuthorizationResponse.success(null).redirectUri(REDIRECT_URI).state(STATE).build(); } @Test(expected = IllegalArgumentException.class) public void buildSuccessResponseWhenRedirectUriIsNullThenThrowIllegalArgumentException() { - OAuth2AuthorizationResponse.success(AUTH_CODE) - .redirectUri(null) - .state(STATE) - .build(); + OAuth2AuthorizationResponse.success(AUTH_CODE).redirectUri(null).state(STATE).build(); } @Test public void buildSuccessResponseWhenStateIsNullThenDoesNotThrowAnyException() { - assertThatCode(() -> OAuth2AuthorizationResponse.success(AUTH_CODE) - .redirectUri(REDIRECT_URI) - .state(null) - .build()).doesNotThrowAnyException(); + assertThatCode( + () -> OAuth2AuthorizationResponse.success(AUTH_CODE).redirectUri(REDIRECT_URI).state(null).build()) + .doesNotThrowAnyException(); } @Test public void buildSuccessResponseWhenAllAttributesProvidedThenAllAttributesAreSet() { OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponse.success(AUTH_CODE) - .redirectUri(REDIRECT_URI) - .state(STATE) - .build(); + .redirectUri(REDIRECT_URI).state(STATE).build(); assertThat(authorizationResponse.getCode()).isEqualTo(AUTH_CODE); assertThat(authorizationResponse.getRedirectUri()).isEqualTo(REDIRECT_URI); assertThat(authorizationResponse.getState()).isEqualTo(STATE); @@ -70,45 +67,31 @@ public class OAuth2AuthorizationResponseTests { @Test(expected = IllegalArgumentException.class) public void buildSuccessResponseWhenErrorCodeIsSetThenThrowIllegalArgumentException() { - OAuth2AuthorizationResponse.success(AUTH_CODE) - .redirectUri(REDIRECT_URI) - .state(STATE) - .errorCode(ERROR_CODE) - .build(); + OAuth2AuthorizationResponse.success(AUTH_CODE).redirectUri(REDIRECT_URI).state(STATE).errorCode(ERROR_CODE) + .build(); } @Test(expected = IllegalArgumentException.class) public void buildErrorResponseWhenErrorCodeIsNullThenThrowIllegalArgumentException() { - OAuth2AuthorizationResponse.error(null) - .redirectUri(REDIRECT_URI) - .state(STATE) - .build(); + OAuth2AuthorizationResponse.error(null).redirectUri(REDIRECT_URI).state(STATE).build(); } @Test(expected = IllegalArgumentException.class) public void buildErrorResponseWhenRedirectUriIsNullThenThrowIllegalArgumentException() { - OAuth2AuthorizationResponse.error(ERROR_CODE) - .redirectUri(null) - .state(STATE) - .build(); + OAuth2AuthorizationResponse.error(ERROR_CODE).redirectUri(null).state(STATE).build(); } @Test public void buildErrorResponseWhenStateIsNullThenDoesNotThrowAnyException() { - assertThatCode(() -> OAuth2AuthorizationResponse.error(ERROR_CODE) - .redirectUri(REDIRECT_URI) - .state(null) - .build()).doesNotThrowAnyException(); + assertThatCode( + () -> OAuth2AuthorizationResponse.error(ERROR_CODE).redirectUri(REDIRECT_URI).state(null).build()) + .doesNotThrowAnyException(); } @Test public void buildErrorResponseWhenAllAttributesProvidedThenAllAttributesAreSet() { OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponse.error(ERROR_CODE) - .errorDescription(ERROR_DESCRIPTION) - .errorUri(ERROR_URI) - .redirectUri(REDIRECT_URI) - .state(STATE) - .build(); + .errorDescription(ERROR_DESCRIPTION).errorUri(ERROR_URI).redirectUri(REDIRECT_URI).state(STATE).build(); assertThat(authorizationResponse.getError().getErrorCode()).isEqualTo(ERROR_CODE); assertThat(authorizationResponse.getError().getDescription()).isEqualTo(ERROR_DESCRIPTION); assertThat(authorizationResponse.getError().getUri()).isEqualTo(ERROR_URI); @@ -118,10 +101,7 @@ public class OAuth2AuthorizationResponseTests { @Test(expected = IllegalArgumentException.class) public void buildErrorResponseWhenAuthCodeIsSetThenThrowIllegalArgumentException() { - OAuth2AuthorizationResponse.error(ERROR_CODE) - .redirectUri(REDIRECT_URI) - .state(STATE) - .code(AUTH_CODE) - .build(); + OAuth2AuthorizationResponse.error(ERROR_CODE).redirectUri(REDIRECT_URI).state(STATE).code(AUTH_CODE).build(); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseTypeTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseTypeTests.java index dd963fa0a1..f039a93683 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseTypeTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/OAuth2AuthorizationResponseTypeTests.java @@ -35,4 +35,5 @@ public class OAuth2AuthorizationResponseTypeTests { public void getValueWhenResponseTypeTokenThenReturnToken() { assertThat(OAuth2AuthorizationResponseType.TOKEN.getValue()).isEqualTo("token"); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AccessTokenResponses.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AccessTokenResponses.java index 3cee5f9ef1..7cc0bf27f5 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AccessTokenResponses.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AccessTokenResponses.java @@ -27,15 +27,15 @@ import java.util.Map; * @since 5.1 */ public class TestOAuth2AccessTokenResponses { + public static OAuth2AccessTokenResponse.Builder accessTokenResponse() { - return OAuth2AccessTokenResponse.withToken("token") - .tokenType(OAuth2AccessToken.TokenType.BEARER); + return OAuth2AccessTokenResponse.withToken("token").tokenType(OAuth2AccessToken.TokenType.BEARER); } public static OAuth2AccessTokenResponse.Builder oidcAccessTokenResponse() { Map additionalParameters = new HashMap<>(); additionalParameters.put(OidcParameterNames.ID_TOKEN, "id-token"); - return accessTokenResponse() - .additionalParameters(additionalParameters); + return accessTokenResponse().additionalParameters(additionalParameters); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AuthorizationExchanges.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AuthorizationExchanges.java index 98fdbec1dc..68cb45df48 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AuthorizationExchanges.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AuthorizationExchanges.java @@ -34,4 +34,5 @@ public class TestOAuth2AuthorizationExchanges { OAuth2AuthorizationResponse response = TestOAuth2AuthorizationResponses.error().build(); return new OAuth2AuthorizationExchange(request, response); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AuthorizationRequests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AuthorizationRequests.java index b160cdbf32..ccfa6679c0 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AuthorizationRequests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AuthorizationRequests.java @@ -24,20 +24,20 @@ import java.util.Map; * @since 5.1 */ public class TestOAuth2AuthorizationRequests { + public static OAuth2AuthorizationRequest.Builder request() { String registrationId = "registration-id"; String clientId = "client-id"; Map attributes = new HashMap<>(); attributes.put(OAuth2ParameterNames.REGISTRATION_ID, registrationId); return OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri("https://example.com/login/oauth/authorize") - .clientId(clientId) - .redirectUri("https://example.com/authorize/oauth2/code/registration-id") - .state("state") + .authorizationUri("https://example.com/login/oauth/authorize").clientId(clientId) + .redirectUri("https://example.com/authorize/oauth2/code/registration-id").state("state") .attributes(attributes); } public static OAuth2AuthorizationRequest.Builder oidcRequest() { return request().scope("openid"); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AuthorizationResponses.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AuthorizationResponses.java index 7ad7085c71..fbed4c0fef 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AuthorizationResponses.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/endpoint/TestOAuth2AuthorizationResponses.java @@ -23,8 +23,7 @@ package org.springframework.security.oauth2.core.endpoint; public class TestOAuth2AuthorizationResponses { public static OAuth2AuthorizationResponse.Builder success() { - return OAuth2AuthorizationResponse.success("authorization-code") - .state("state") + return OAuth2AuthorizationResponse.success("authorization-code").state("state") .redirectUri("https://example.com/authorize/oauth2/code/registration-id"); } @@ -33,4 +32,5 @@ public class TestOAuth2AuthorizationResponses { .redirectUri("https://example.com/authorize/oauth2/code/registration-id") .errorUri("https://example.com/error"); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverterTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverterTests.java index e3ef18ee84..798e32ec78 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverterTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverterTests.java @@ -44,6 +44,7 @@ import static org.mockito.Mockito.when; * @author Joe Grandja */ public class OAuth2AccessTokenResponseHttpMessageConverterTests { + private OAuth2AccessTokenResponseHttpMessageConverter messageConverter; @Before @@ -70,25 +71,21 @@ public class OAuth2AccessTokenResponseHttpMessageConverterTests { @Test public void readInternalWhenSuccessfulTokenResponseThenReadOAuth2AccessTokenResponse() throws Exception { - String tokenResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": \"3600\",\n" + - " \"scope\": \"read write\",\n" + - " \"refresh_token\": \"refresh-token-1234\",\n" + - " \"custom_parameter_1\": \"custom-value-1\",\n" + - " \"custom_parameter_2\": \"custom-value-2\"\n" + - "}\n"; + String tokenResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": \"3600\",\n" + + " \"scope\": \"read write\",\n" + " \"refresh_token\": \"refresh-token-1234\",\n" + + " \"custom_parameter_1\": \"custom-value-1\",\n" + " \"custom_parameter_2\": \"custom-value-2\"\n" + + "}\n"; - MockClientHttpResponse response = new MockClientHttpResponse( - tokenResponse.getBytes(), HttpStatus.OK); + MockClientHttpResponse response = new MockClientHttpResponse(tokenResponse.getBytes(), HttpStatus.OK); - OAuth2AccessTokenResponse accessTokenResponse = this.messageConverter.readInternal( - OAuth2AccessTokenResponse.class, response); + OAuth2AccessTokenResponse accessTokenResponse = this.messageConverter + .readInternal(OAuth2AccessTokenResponse.class, response); assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo("access-token-1234"); assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER); - assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBeforeOrEqualTo(Instant.now().plusSeconds(3600)); + assertThat(accessTokenResponse.getAccessToken().getExpiresAt()) + .isBeforeOrEqualTo(Instant.now().plusSeconds(3600)); assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("read", "write"); assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo("refresh-token-1234"); assertThat(accessTokenResponse.getAdditionalParameters()).containsExactly( @@ -99,56 +96,46 @@ public class OAuth2AccessTokenResponseHttpMessageConverterTests { // gh-6463 @Test public void readInternalWhenSuccessfulTokenResponseWithObjectThenReadOAuth2AccessTokenResponse() { - String tokenResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": 3600,\n" + - " \"scope\": \"read write\",\n" + - " \"refresh_token\": \"refresh-token-1234\",\n" + - " \"custom_object_1\": {\"name1\": \"value1\"},\n" + - " \"custom_object_2\": [\"value1\", \"value2\"],\n" + - " \"custom_parameter_1\": \"custom-value-1\",\n" + - " \"custom_parameter_2\": \"custom-value-2\"\n" + - "}\n"; + String tokenResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": 3600,\n" + " \"scope\": \"read write\",\n" + + " \"refresh_token\": \"refresh-token-1234\",\n" + + " \"custom_object_1\": {\"name1\": \"value1\"},\n" + + " \"custom_object_2\": [\"value1\", \"value2\"],\n" + + " \"custom_parameter_1\": \"custom-value-1\",\n" + " \"custom_parameter_2\": \"custom-value-2\"\n" + + "}\n"; - MockClientHttpResponse response = new MockClientHttpResponse( - tokenResponse.getBytes(), HttpStatus.OK); + MockClientHttpResponse response = new MockClientHttpResponse(tokenResponse.getBytes(), HttpStatus.OK); - OAuth2AccessTokenResponse accessTokenResponse = this.messageConverter.readInternal( - OAuth2AccessTokenResponse.class, response); + OAuth2AccessTokenResponse accessTokenResponse = this.messageConverter + .readInternal(OAuth2AccessTokenResponse.class, response); assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo("access-token-1234"); assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER); - assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBeforeOrEqualTo(Instant.now().plusSeconds(3600)); + assertThat(accessTokenResponse.getAccessToken().getExpiresAt()) + .isBeforeOrEqualTo(Instant.now().plusSeconds(3600)); assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("read", "write"); assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo("refresh-token-1234"); assertThat(accessTokenResponse.getAdditionalParameters()).containsExactly( - entry("custom_object_1", "{name1=value1}"), - entry("custom_object_2", "[value1, value2]"), - entry("custom_parameter_1", "custom-value-1"), - entry("custom_parameter_2", "custom-value-2")); + entry("custom_object_1", "{name1=value1}"), entry("custom_object_2", "[value1, value2]"), + entry("custom_parameter_1", "custom-value-1"), entry("custom_parameter_2", "custom-value-2")); } // gh-8108 @Test public void readInternalWhenSuccessfulTokenResponseWithNullValueThenReadOAuth2AccessTokenResponse() { - String tokenResponse = "{\n" + - " \"access_token\": \"access-token-1234\",\n" + - " \"token_type\": \"bearer\",\n" + - " \"expires_in\": 3600,\n" + - " \"scope\": null,\n" + - " \"refresh_token\": \"refresh-token-1234\"\n" + - "}\n"; + String tokenResponse = "{\n" + " \"access_token\": \"access-token-1234\",\n" + + " \"token_type\": \"bearer\",\n" + " \"expires_in\": 3600,\n" + " \"scope\": null,\n" + + " \"refresh_token\": \"refresh-token-1234\"\n" + "}\n"; - MockClientHttpResponse response = new MockClientHttpResponse( - tokenResponse.getBytes(), HttpStatus.OK); + MockClientHttpResponse response = new MockClientHttpResponse(tokenResponse.getBytes(), HttpStatus.OK); - OAuth2AccessTokenResponse accessTokenResponse = this.messageConverter.readInternal( - OAuth2AccessTokenResponse.class, response); + OAuth2AccessTokenResponse accessTokenResponse = this.messageConverter + .readInternal(OAuth2AccessTokenResponse.class, response); assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo("access-token-1234"); assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER); - assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBeforeOrEqualTo(Instant.now().plusSeconds(3600)); + assertThat(accessTokenResponse.getAccessToken().getExpiresAt()) + .isBeforeOrEqualTo(Instant.now().plusSeconds(3600)); assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("null"); assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo("refresh-token-1234"); } @@ -161,8 +148,7 @@ public class OAuth2AccessTokenResponseHttpMessageConverterTests { String tokenResponse = "{}"; - MockClientHttpResponse response = new MockClientHttpResponse( - tokenResponse.getBytes(), HttpStatus.OK); + MockClientHttpResponse response = new MockClientHttpResponse(tokenResponse.getBytes(), HttpStatus.OK); assertThatThrownBy(() -> this.messageConverter.readInternal(OAuth2AccessTokenResponse.class, response)) .isInstanceOf(HttpMessageNotReadableException.class) @@ -177,14 +163,9 @@ public class OAuth2AccessTokenResponseHttpMessageConverterTests { additionalParameters.put("custom_parameter_1", "custom-value-1"); additionalParameters.put("custom_parameter_2", "custom-value-2"); - OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse - .withToken("access-token-1234") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(expiresAt.toEpochMilli()) - .scopes(scopes) - .refreshToken("refresh-token-1234") - .additionalParameters(additionalParameters) - .build(); + OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("access-token-1234") + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(expiresAt.toEpochMilli()).scopes(scopes) + .refreshToken("refresh-token-1234").additionalParameters(additionalParameters).build(); MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); this.messageConverter.writeInternal(accessTokenResponse, outputMessage); @@ -205,10 +186,8 @@ public class OAuth2AccessTokenResponseHttpMessageConverterTests { when(tokenResponseParametersConverter.convert(any())).thenThrow(RuntimeException.class); this.messageConverter.setTokenResponseParametersConverter(tokenResponseParametersConverter); - OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse - .withToken("access-token-1234") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(Instant.now().plusSeconds(3600).toEpochMilli()) + OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("access-token-1234") + .tokenType(OAuth2AccessToken.TokenType.BEARER).expiresIn(Instant.now().plusSeconds(3600).toEpochMilli()) .build(); MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); @@ -217,4 +196,5 @@ public class OAuth2AccessTokenResponseHttpMessageConverterTests { .isInstanceOf(HttpMessageNotWritableException.class) .hasMessageContaining("An error occurred writing the OAuth 2.0 Access Token Response"); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverterTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverterTests.java index 11211aad56..ace827314c 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverterTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/http/converter/OAuth2ErrorHttpMessageConverterTests.java @@ -37,6 +37,7 @@ import static org.mockito.Mockito.when; * @author Joe Grandja */ public class OAuth2ErrorHttpMessageConverterTests { + private OAuth2ErrorHttpMessageConverter messageConverter; @Before @@ -63,14 +64,11 @@ public class OAuth2ErrorHttpMessageConverterTests { @Test public void readInternalWhenErrorResponseThenReadOAuth2Error() throws Exception { - String errorResponse = "{\n" + - " \"error\": \"unauthorized_client\",\n" + - " \"error_description\": \"The client is not authorized\",\n" + - " \"error_uri\": \"https://tools.ietf.org/html/rfc6749#section-5.2\"\n" + - "}\n"; + String errorResponse = "{\n" + " \"error\": \"unauthorized_client\",\n" + + " \"error_description\": \"The client is not authorized\",\n" + + " \"error_uri\": \"https://tools.ietf.org/html/rfc6749#section-5.2\"\n" + "}\n"; - MockClientHttpResponse response = new MockClientHttpResponse( - errorResponse.getBytes(), HttpStatus.BAD_REQUEST); + MockClientHttpResponse response = new MockClientHttpResponse(errorResponse.getBytes(), HttpStatus.BAD_REQUEST); OAuth2Error oauth2Error = this.messageConverter.readInternal(OAuth2Error.class, response); assertThat(oauth2Error.getErrorCode()).isEqualTo("unauthorized_client"); @@ -81,15 +79,11 @@ public class OAuth2ErrorHttpMessageConverterTests { // gh-8157 @Test public void readInternalWhenErrorResponseWithObjectThenReadOAuth2Error() throws Exception { - String errorResponse = "{\n" + - " \"error\": \"unauthorized_client\",\n" + - " \"error_description\": \"The client is not authorized\",\n" + - " \"error_codes\": [65001],\n" + - " \"error_uri\": \"https://tools.ietf.org/html/rfc6749#section-5.2\"\n" + - "}\n"; + String errorResponse = "{\n" + " \"error\": \"unauthorized_client\",\n" + + " \"error_description\": \"The client is not authorized\",\n" + " \"error_codes\": [65001],\n" + + " \"error_uri\": \"https://tools.ietf.org/html/rfc6749#section-5.2\"\n" + "}\n"; - MockClientHttpResponse response = new MockClientHttpResponse( - errorResponse.getBytes(), HttpStatus.BAD_REQUEST); + MockClientHttpResponse response = new MockClientHttpResponse(errorResponse.getBytes(), HttpStatus.BAD_REQUEST); OAuth2Error oauth2Error = this.messageConverter.readInternal(OAuth2Error.class, response); assertThat(oauth2Error.getErrorCode()).isEqualTo("unauthorized_client"); @@ -105,8 +99,7 @@ public class OAuth2ErrorHttpMessageConverterTests { String errorResponse = "{}"; - MockClientHttpResponse response = new MockClientHttpResponse( - errorResponse.getBytes(), HttpStatus.BAD_REQUEST); + MockClientHttpResponse response = new MockClientHttpResponse(errorResponse.getBytes(), HttpStatus.BAD_REQUEST); assertThatThrownBy(() -> this.messageConverter.readInternal(OAuth2Error.class, response)) .isInstanceOf(HttpMessageNotReadableException.class) @@ -115,8 +108,8 @@ public class OAuth2ErrorHttpMessageConverterTests { @Test public void writeInternalWhenOAuth2ErrorThenWriteErrorResponse() throws Exception { - OAuth2Error oauth2Error = new OAuth2Error("unauthorized_client", - "The client is not authorized", "https://tools.ietf.org/html/rfc6749#section-5.2"); + OAuth2Error oauth2Error = new OAuth2Error("unauthorized_client", "The client is not authorized", + "https://tools.ietf.org/html/rfc6749#section-5.2"); MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); this.messageConverter.writeInternal(oauth2Error, outputMessage); @@ -133,8 +126,8 @@ public class OAuth2ErrorHttpMessageConverterTests { when(errorParametersConverter.convert(any())).thenThrow(RuntimeException.class); this.messageConverter.setErrorParametersConverter(errorParametersConverter); - OAuth2Error oauth2Error = new OAuth2Error("unauthorized_client", - "The client is not authorized", "https://tools.ietf.org/html/rfc6749#section-5.2"); + OAuth2Error oauth2Error = new OAuth2Error("unauthorized_client", "The client is not authorized", + "https://tools.ietf.org/html/rfc6749#section-5.2"); MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); @@ -142,4 +135,5 @@ public class OAuth2ErrorHttpMessageConverterTests { .isInstanceOf(HttpMessageNotWritableException.class) .hasMessageContaining("An error occurred writing the OAuth 2.0 Error"); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/DefaultAddressStandardClaimTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/DefaultAddressStandardClaimTests.java index f22653985e..f9f3aa6312 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/DefaultAddressStandardClaimTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/DefaultAddressStandardClaimTests.java @@ -28,6 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Joe Grandja */ public class DefaultAddressStandardClaimTests { + static final String FORMATTED_FIELD_NAME = "formatted"; static final String STREET_ADDRESS_FIELD_NAME = "street_address"; static final String LOCALITY_FIELD_NAME = "locality"; @@ -43,15 +44,9 @@ public class DefaultAddressStandardClaimTests { @Test public void buildWhenAllAttributesProvidedThenAllAttributesAreSet() { - AddressStandardClaim addressStandardClaim = - new DefaultAddressStandardClaim.Builder() - .formatted(FORMATTED) - .streetAddress(STREET_ADDRESS) - .locality(LOCALITY) - .region(REGION) - .postalCode(POSTAL_CODE) - .country(COUNTRY) - .build(); + AddressStandardClaim addressStandardClaim = new DefaultAddressStandardClaim.Builder().formatted(FORMATTED) + .streetAddress(STREET_ADDRESS).locality(LOCALITY).region(REGION).postalCode(POSTAL_CODE) + .country(COUNTRY).build(); assertThat(addressStandardClaim.getFormatted()).isEqualTo(FORMATTED); assertThat(addressStandardClaim.getStreetAddress()).isEqualTo(STREET_ADDRESS); @@ -71,9 +66,7 @@ public class DefaultAddressStandardClaimTests { addressFields.put(POSTAL_CODE_FIELD_NAME, POSTAL_CODE); addressFields.put(COUNTRY_FIELD_NAME, COUNTRY); - AddressStandardClaim addressStandardClaim = - new DefaultAddressStandardClaim.Builder(addressFields) - .build(); + AddressStandardClaim addressStandardClaim = new DefaultAddressStandardClaim.Builder(addressFields).build(); assertThat(addressStandardClaim.getFormatted()).isEqualTo(FORMATTED); assertThat(addressStandardClaim.getStreetAddress()).isEqualTo(STREET_ADDRESS); @@ -82,4 +75,5 @@ public class DefaultAddressStandardClaimTests { assertThat(addressStandardClaim.getPostalCode()).isEqualTo(POSTAL_CODE); assertThat(addressStandardClaim.getCountry()).isEqualTo(COUNTRY); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcIdTokenBuilderTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcIdTokenBuilderTests.java index c3b049eb06..50d4bb5223 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcIdTokenBuilderTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcIdTokenBuilderTests.java @@ -30,19 +30,14 @@ import static org.springframework.security.oauth2.core.oidc.IdTokenClaimNames.SU * Tests for {@link OidcUserInfo} */ public class OidcIdTokenBuilderTests { + @Test public void buildWhenCalledTwiceThenGeneratesTwoOidcIdTokens() { OidcIdToken.Builder idTokenBuilder = OidcIdToken.withTokenValue("token"); - OidcIdToken first = idTokenBuilder - .tokenValue("V1") - .claim("TEST_CLAIM_1", "C1") - .build(); + OidcIdToken first = idTokenBuilder.tokenValue("V1").claim("TEST_CLAIM_1", "C1").build(); - OidcIdToken second = idTokenBuilder - .tokenValue("V2") - .claim("TEST_CLAIM_1", "C2") - .claim("TEST_CLAIM_2", "C3") + OidcIdToken second = idTokenBuilder.tokenValue("V2").claim("TEST_CLAIM_1", "C2").claim("TEST_CLAIM_2", "C3") .build(); assertThat(first.getClaims()).hasSize(1); @@ -61,16 +56,13 @@ public class OidcIdTokenBuilderTests { Instant now = Instant.now(); - OidcIdToken idToken = idTokenBuilder - .expiresAt(now).build(); + OidcIdToken idToken = idTokenBuilder.expiresAt(now).build(); assertThat(idToken.getExpiresAt()).isSameAs(now); - idToken = idTokenBuilder - .expiresAt(now).build(); + idToken = idTokenBuilder.expiresAt(now).build(); assertThat(idToken.getExpiresAt()).isSameAs(now); - assertThatCode(() -> idTokenBuilder - .claim(EXP, "not an instant").build()) + assertThatCode(() -> idTokenBuilder.claim(EXP, "not an instant").build()) .isInstanceOf(IllegalArgumentException.class); } @@ -80,16 +72,13 @@ public class OidcIdTokenBuilderTests { Instant now = Instant.now(); - OidcIdToken idToken = idTokenBuilder - .issuedAt(now).build(); + OidcIdToken idToken = idTokenBuilder.issuedAt(now).build(); assertThat(idToken.getIssuedAt()).isSameAs(now); - idToken = idTokenBuilder - .issuedAt(now).build(); + idToken = idTokenBuilder.issuedAt(now).build(); assertThat(idToken.getIssuedAt()).isSameAs(now); - assertThatCode(() -> idTokenBuilder - .claim(IAT, "not an instant").build()) + assertThatCode(() -> idTokenBuilder.claim(IAT, "not an instant").build()) .isInstanceOf(IllegalArgumentException.class); } @@ -100,26 +89,18 @@ public class OidcIdTokenBuilderTests { String generic = new String("sub"); String named = new String("sub"); - OidcIdToken idToken = idTokenBuilder - .subject(named) - .claim(SUB, generic).build(); + OidcIdToken idToken = idTokenBuilder.subject(named).claim(SUB, generic).build(); assertThat(idToken.getSubject()).isSameAs(generic); - idToken = idTokenBuilder - .claim(SUB, generic) - .subject(named).build(); + idToken = idTokenBuilder.claim(SUB, generic).subject(named).build(); assertThat(idToken.getSubject()).isSameAs(named); } @Test public void claimsWhenRemovingAClaimThenIsNotPresent() { - OidcIdToken.Builder idTokenBuilder = OidcIdToken.withTokenValue("token") - .claim("needs", "a claim"); + OidcIdToken.Builder idTokenBuilder = OidcIdToken.withTokenValue("token").claim("needs", "a claim"); - OidcIdToken idToken = idTokenBuilder - .subject("sub") - .claims(claims -> claims.remove(SUB)) - .build(); + OidcIdToken idToken = idTokenBuilder.subject("sub").claims(claims -> claims.remove(SUB)).build(); assertThat(idToken.getSubject()).isNull(); } @@ -129,11 +110,10 @@ public class OidcIdTokenBuilderTests { String name = new String("name"); String value = new String("value"); - OidcIdToken idToken = idTokenBuilder - .claims(claims -> claims.put(name, value)) - .build(); + OidcIdToken idToken = idTokenBuilder.claims(claims -> claims.put(name, value)).build(); assertThat(idToken.getClaims()).hasSize(1); assertThat(idToken.getClaims().get(name)).isSameAs(value); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcIdTokenTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcIdTokenTests.java index 15a04e6b0a..55e722a704 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcIdTokenTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcIdTokenTests.java @@ -32,33 +32,57 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Joe Grandja */ public class OidcIdTokenTests { + private static final String ISS_CLAIM = "iss"; + private static final String SUB_CLAIM = "sub"; + private static final String AUD_CLAIM = "aud"; + private static final String IAT_CLAIM = "iat"; + private static final String EXP_CLAIM = "exp"; + private static final String AUTH_TIME_CLAIM = "auth_time"; + private static final String NONCE_CLAIM = "nonce"; + private static final String ACR_CLAIM = "acr"; + private static final String AMR_CLAIM = "amr"; + private static final String AZP_CLAIM = "azp"; + private static final String AT_HASH_CLAIM = "at_hash"; + private static final String C_HASH_CLAIM = "c_hash"; private static final String ISS_VALUE = "https://provider.com"; + private static final String SUB_VALUE = "subject1"; + private static final List AUD_VALUE = Arrays.asList("aud1", "aud2"); + private static final long IAT_VALUE = Instant.now().toEpochMilli(); + private static final long EXP_VALUE = Instant.now().plusSeconds(60).toEpochMilli(); + private static final long AUTH_TIME_VALUE = Instant.now().minusSeconds(5).toEpochMilli(); + private static final String NONCE_VALUE = "nonce"; + private static final String ACR_VALUE = "acr"; + private static final List AMR_VALUE = Arrays.asList("amr1", "amr2"); + private static final String AZP_VALUE = "azp"; + private static final String AT_HASH_VALUE = "at_hash"; + private static final String C_HASH_VALUE = "c_hash"; private static final Map CLAIMS; + private static final String ID_TOKEN_VALUE = "id-token-value"; static { @@ -84,14 +108,14 @@ public class OidcIdTokenTests { @Test(expected = IllegalArgumentException.class) public void constructorWhenClaimsIsEmptyThenThrowIllegalArgumentException() { - new OidcIdToken(ID_TOKEN_VALUE, Instant.ofEpochMilli(IAT_VALUE), - Instant.ofEpochMilli(EXP_VALUE), Collections.emptyMap()); + new OidcIdToken(ID_TOKEN_VALUE, Instant.ofEpochMilli(IAT_VALUE), Instant.ofEpochMilli(EXP_VALUE), + Collections.emptyMap()); } @Test public void constructorWhenParametersProvidedAndValidThenCreated() { OidcIdToken idToken = new OidcIdToken(ID_TOKEN_VALUE, Instant.ofEpochMilli(IAT_VALUE), - Instant.ofEpochMilli(EXP_VALUE), CLAIMS); + Instant.ofEpochMilli(EXP_VALUE), CLAIMS); assertThat(idToken.getClaims()).isEqualTo(CLAIMS); assertThat(idToken.getTokenValue()).isEqualTo(ID_TOKEN_VALUE); @@ -108,4 +132,5 @@ public class OidcIdTokenTests { assertThat(idToken.getAccessTokenHash()).isEqualTo(AT_HASH_VALUE); assertThat(idToken.getAuthorizationCodeHash()).isEqualTo(C_HASH_VALUE); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcUserInfoBuilderTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcUserInfoBuilderTests.java index 9b1c057016..ce6fddf320 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcUserInfoBuilderTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcUserInfoBuilderTests.java @@ -25,18 +25,14 @@ import static org.springframework.security.oauth2.core.oidc.IdTokenClaimNames.SU * Tests for {@link OidcUserInfo} */ public class OidcUserInfoBuilderTests { + @Test public void buildWhenCalledTwiceThenGeneratesTwoOidcUserInfos() { OidcUserInfo.Builder userInfoBuilder = OidcUserInfo.builder(); - OidcUserInfo first = userInfoBuilder - .claim("TEST_CLAIM_1", "C1") - .build(); + OidcUserInfo first = userInfoBuilder.claim("TEST_CLAIM_1", "C1").build(); - OidcUserInfo second = userInfoBuilder - .claim("TEST_CLAIM_1", "C2") - .claim("TEST_CLAIM_2", "C3") - .build(); + OidcUserInfo second = userInfoBuilder.claim("TEST_CLAIM_1", "C2").claim("TEST_CLAIM_2", "C3").build(); assertThat(first.getClaims()).hasSize(1); assertThat(first.getClaims().get("TEST_CLAIM_1")).isEqualTo("C1"); @@ -53,26 +49,18 @@ public class OidcUserInfoBuilderTests { String generic = new String("sub"); String named = new String("sub"); - OidcUserInfo userInfo = userInfoBuilder - .subject(named) - .claim(SUB, generic).build(); + OidcUserInfo userInfo = userInfoBuilder.subject(named).claim(SUB, generic).build(); assertThat(userInfo.getSubject()).isSameAs(generic); - userInfo = userInfoBuilder - .claim(SUB, generic) - .subject(named).build(); + userInfo = userInfoBuilder.claim(SUB, generic).subject(named).build(); assertThat(userInfo.getSubject()).isSameAs(named); } @Test public void claimsWhenRemovingAClaimThenIsNotPresent() { - OidcUserInfo.Builder userInfoBuilder = OidcUserInfo.builder() - .claim("needs", "a claim"); + OidcUserInfo.Builder userInfoBuilder = OidcUserInfo.builder().claim("needs", "a claim"); - OidcUserInfo userInfo = userInfoBuilder - .subject("sub") - .claims(claims -> claims.remove(SUB)) - .build(); + OidcUserInfo userInfo = userInfoBuilder.subject("sub").claims(claims -> claims.remove(SUB)).build(); assertThat(userInfo.getSubject()).isNull(); } @@ -82,11 +70,10 @@ public class OidcUserInfoBuilderTests { String name = new String("name"); String value = new String("value"); - OidcUserInfo userInfo = userInfoBuilder - .claims(claims -> claims.put(name, value)) - .build(); + OidcUserInfo userInfo = userInfoBuilder.claims(claims -> claims.put(name, value)).build(); assertThat(userInfo.getClaims()).hasSize(1); assertThat(userInfo.getClaims().get(name)).isSameAs(value); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcUserInfoTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcUserInfoTests.java index c94e798d84..81827d0cb3 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcUserInfoTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcUserInfoTests.java @@ -31,46 +31,85 @@ import static org.springframework.security.oauth2.core.oidc.DefaultAddressStanda * @author Joe Grandja */ public class OidcUserInfoTests { + private static final String SUB_CLAIM = "sub"; + private static final String NAME_CLAIM = "name"; + private static final String GIVEN_NAME_CLAIM = "given_name"; + private static final String FAMILY_NAME_CLAIM = "family_name"; + private static final String MIDDLE_NAME_CLAIM = "middle_name"; + private static final String NICKNAME_CLAIM = "nickname"; + private static final String PREFERRED_USERNAME_CLAIM = "preferred_username"; + private static final String PROFILE_CLAIM = "profile"; + private static final String PICTURE_CLAIM = "picture"; + private static final String WEBSITE_CLAIM = "website"; + private static final String EMAIL_CLAIM = "email"; + private static final String EMAIL_VERIFIED_CLAIM = "email_verified"; + private static final String GENDER_CLAIM = "gender"; + private static final String BIRTHDATE_CLAIM = "birthdate"; + private static final String ZONEINFO_CLAIM = "zoneinfo"; + private static final String LOCALE_CLAIM = "locale"; + private static final String PHONE_NUMBER_CLAIM = "phone_number"; + private static final String PHONE_NUMBER_VERIFIED_CLAIM = "phone_number_verified"; + private static final String ADDRESS_CLAIM = "address"; + private static final String UPDATED_AT_CLAIM = "updated_at"; private static final String SUB_VALUE = "subject1"; + private static final String NAME_VALUE = "full_name"; + private static final String GIVEN_NAME_VALUE = "given_name"; + private static final String FAMILY_NAME_VALUE = "family_name"; + private static final String MIDDLE_NAME_VALUE = "middle_name"; + private static final String NICKNAME_VALUE = "nickname"; + private static final String PREFERRED_USERNAME_VALUE = "preferred_username"; + private static final String PROFILE_VALUE = "profile"; + private static final String PICTURE_VALUE = "picture"; + private static final String WEBSITE_VALUE = "website"; + private static final String EMAIL_VALUE = "email"; + private static final Boolean EMAIL_VERIFIED_VALUE = true; + private static final String GENDER_VALUE = "gender"; + private static final String BIRTHDATE_VALUE = "birthdate"; + private static final String ZONEINFO_VALUE = "zoneinfo"; + private static final String LOCALE_VALUE = "locale"; + private static final String PHONE_NUMBER_VALUE = "phone_number"; + private static final Boolean PHONE_NUMBER_VERIFIED_VALUE = true; + private static final Map ADDRESS_VALUE; + private static final long UPDATED_AT_VALUE = Instant.now().minusSeconds(60).toEpochMilli(); private static final Map CLAIMS; @@ -139,4 +178,5 @@ public class OidcUserInfoTests { assertThat(userInfo.getAddress()).isEqualTo(new DefaultAddressStandardClaim.Builder(ADDRESS_VALUE).build()); assertThat(userInfo.getUpdatedAt().getEpochSecond()).isEqualTo(UPDATED_AT_VALUE); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/TestOidcIdTokens.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/TestOidcIdTokens.java index a866554f54..a97d9c94b6 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/TestOidcIdTokens.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/TestOidcIdTokens.java @@ -26,12 +26,10 @@ import static org.springframework.security.oauth2.core.oidc.OidcIdToken.withToke * @author Josh Cummings */ public class TestOidcIdTokens { + public static OidcIdToken.Builder idToken() { - return withTokenValue("id-token") - .issuer("https://example.com") - .subject("subject") - .issuedAt(Instant.now()) - .expiresAt(Instant.now().plusSeconds(86400)) - .claim("id", "id"); + return withTokenValue("id-token").issuer("https://example.com").subject("subject").issuedAt(Instant.now()) + .expiresAt(Instant.now().plusSeconds(86400)).claim("id", "id"); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/DefaultOidcUserTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/DefaultOidcUserTests.java index 2fad69684f..edba3543bb 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/DefaultOidcUserTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/DefaultOidcUserTests.java @@ -39,12 +39,19 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Joe Grandja */ public class DefaultOidcUserTests { + private static final SimpleGrantedAuthority AUTHORITY = new SimpleGrantedAuthority("ROLE_USER"); + private static final Set AUTHORITIES = Collections.singleton(AUTHORITY); + private static final String SUBJECT = "test-subject"; + private static final String EMAIL = "test-subject@example.com"; + private static final String NAME = "test-name"; + private static final Map ID_TOKEN_CLAIMS = new HashMap<>(); + private static final Map USER_INFO_CLAIMS = new HashMap<>(); static { @@ -54,7 +61,9 @@ public class DefaultOidcUserTests { USER_INFO_CLAIMS.put(StandardClaimNames.EMAIL, EMAIL); } - private static final OidcIdToken ID_TOKEN = new OidcIdToken("id-token-value", Instant.EPOCH, Instant.MAX, ID_TOKEN_CLAIMS); + private static final OidcIdToken ID_TOKEN = new OidcIdToken("id-token-value", Instant.EPOCH, Instant.MAX, + ID_TOKEN_CLAIMS); + private static final OidcUserInfo USER_INFO = new OidcUserInfo(USER_INFO_CLAIMS); @Test(expected = IllegalArgumentException.class) @@ -100,29 +109,30 @@ public class DefaultOidcUserTests { public void constructorWhenAuthoritiesIdTokenUserInfoProvidedThenCreated() { DefaultOidcUser user = new DefaultOidcUser(AUTHORITIES, ID_TOKEN, USER_INFO); - assertThat(user.getClaims()).containsOnlyKeys( - IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, StandardClaimNames.NAME, StandardClaimNames.EMAIL); + assertThat(user.getClaims()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, + StandardClaimNames.NAME, StandardClaimNames.EMAIL); assertThat(user.getIdToken()).isEqualTo(ID_TOKEN); assertThat(user.getUserInfo()).isEqualTo(USER_INFO); assertThat(user.getName()).isEqualTo(SUBJECT); assertThat(user.getAuthorities()).hasSize(1); assertThat(user.getAuthorities().iterator().next()).isEqualTo(AUTHORITY); - assertThat(user.getAttributes()).containsOnlyKeys( - IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, StandardClaimNames.NAME, StandardClaimNames.EMAIL); + assertThat(user.getAttributes()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, + StandardClaimNames.NAME, StandardClaimNames.EMAIL); } @Test public void constructorWhenAllParametersProvidedAndValidThenCreated() { DefaultOidcUser user = new DefaultOidcUser(AUTHORITIES, ID_TOKEN, USER_INFO, StandardClaimNames.EMAIL); - assertThat(user.getClaims()).containsOnlyKeys( - IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, StandardClaimNames.NAME, StandardClaimNames.EMAIL); + assertThat(user.getClaims()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, + StandardClaimNames.NAME, StandardClaimNames.EMAIL); assertThat(user.getIdToken()).isEqualTo(ID_TOKEN); assertThat(user.getUserInfo()).isEqualTo(USER_INFO); assertThat(user.getName()).isEqualTo(EMAIL); assertThat(user.getAuthorities()).hasSize(1); assertThat(user.getAuthorities().iterator().next()).isEqualTo(AUTHORITY); - assertThat(user.getAttributes()).containsOnlyKeys( - IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, StandardClaimNames.NAME, StandardClaimNames.EMAIL); + assertThat(user.getAttributes()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, + StandardClaimNames.NAME, StandardClaimNames.EMAIL); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/OidcUserAuthorityTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/OidcUserAuthorityTests.java index d859b74d56..0331d1cf69 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/OidcUserAuthorityTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/OidcUserAuthorityTests.java @@ -34,11 +34,17 @@ import static org.assertj.core.api.Assertions.assertThatCode; * @author Joe Grandja */ public class OidcUserAuthorityTests { + private static final String AUTHORITY = "ROLE_USER"; + private static final String SUBJECT = "test-subject"; + private static final String EMAIL = "test-subject@example.com"; + private static final String NAME = "test-name"; + private static final Map ID_TOKEN_CLAIMS = new HashMap<>(); + private static final Map USER_INFO_CLAIMS = new HashMap<>(); static { @@ -48,7 +54,9 @@ public class OidcUserAuthorityTests { USER_INFO_CLAIMS.put(StandardClaimNames.EMAIL, EMAIL); } - private static final OidcIdToken ID_TOKEN = new OidcIdToken("id-token-value", Instant.EPOCH, Instant.MAX, ID_TOKEN_CLAIMS); + private static final OidcIdToken ID_TOKEN = new OidcIdToken("id-token-value", Instant.EPOCH, Instant.MAX, + ID_TOKEN_CLAIMS); + private static final OidcUserInfo USER_INFO = new OidcUserInfo(USER_INFO_CLAIMS); @Test(expected = IllegalArgumentException.class) @@ -73,7 +81,8 @@ public class OidcUserAuthorityTests { assertThat(userAuthority.getIdToken()).isEqualTo(ID_TOKEN); assertThat(userAuthority.getUserInfo()).isEqualTo(USER_INFO); assertThat(userAuthority.getAuthority()).isEqualTo(AUTHORITY); - assertThat(userAuthority.getAttributes()).containsOnlyKeys( - IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, StandardClaimNames.NAME, StandardClaimNames.EMAIL); + assertThat(userAuthority.getAttributes()).containsOnlyKeys(IdTokenClaimNames.ISS, IdTokenClaimNames.SUB, + StandardClaimNames.NAME, StandardClaimNames.EMAIL); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/TestOidcUsers.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/TestOidcUsers.java index d53cbf49f4..b71ef0aa80 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/TestOidcUsers.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/user/TestOidcUsers.java @@ -34,35 +34,25 @@ public class TestOidcUsers { public static DefaultOidcUser create() { OidcIdToken idToken = idToken(); OidcUserInfo userInfo = userInfo(); - return new DefaultOidcUser( - authorities(idToken, userInfo), idToken, userInfo); + return new DefaultOidcUser(authorities(idToken, userInfo), idToken, userInfo); } private static OidcIdToken idToken() { Instant issuedAt = Instant.now(); Instant expiresAt = issuedAt.plusSeconds(3600); - return OidcIdToken.withTokenValue("id-token") - .issuedAt(issuedAt) - .expiresAt(expiresAt) - .subject("subject") + return OidcIdToken.withTokenValue("id-token").issuedAt(issuedAt).expiresAt(expiresAt).subject("subject") .issuer("http://localhost/issuer") .audience(Collections.unmodifiableSet(new LinkedHashSet<>(Collections.singletonList("client")))) - .authorizedParty("client") - .build(); + .authorizedParty("client").build(); } private static OidcUserInfo userInfo() { - return OidcUserInfo.builder() - .subject("subject") - .name("full name") - .build(); + return OidcUserInfo.builder().subject("subject").name("full name").build(); } private static Collection authorities(OidcIdToken idToken, OidcUserInfo userInfo) { - return new LinkedHashSet<>( - Arrays.asList( - new OidcUserAuthority(idToken, userInfo), - new SimpleGrantedAuthority("SCOPE_read"), - new SimpleGrantedAuthority("SCOPE_write"))); + return new LinkedHashSet<>(Arrays.asList(new OidcUserAuthority(idToken, userInfo), + new SimpleGrantedAuthority("SCOPE_read"), new SimpleGrantedAuthority("SCOPE_write"))); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/DefaultOAuth2UserTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/DefaultOAuth2UserTests.java index 3642b54abb..ff82d711db 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/DefaultOAuth2UserTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/DefaultOAuth2UserTests.java @@ -34,12 +34,16 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Joe Grandja */ public class DefaultOAuth2UserTests { + private static final SimpleGrantedAuthority AUTHORITY = new SimpleGrantedAuthority("ROLE_USER"); + private static final Set AUTHORITIES = Collections.singleton(AUTHORITY); + private static final String ATTRIBUTE_NAME_KEY = "username"; + private static final String USERNAME = "test"; - private static final Map ATTRIBUTES = Collections.singletonMap( - ATTRIBUTE_NAME_KEY, USERNAME); + + private static final Map ATTRIBUTES = Collections.singletonMap(ATTRIBUTE_NAME_KEY, USERNAME); @Test(expected = IllegalArgumentException.class) public void constructorWhenAuthoritiesIsNullThenThrowIllegalArgumentException() { @@ -87,4 +91,5 @@ public class DefaultOAuth2UserTests { DefaultOAuth2User user = new DefaultOAuth2User(AUTHORITIES, ATTRIBUTES, ATTRIBUTE_NAME_KEY); SerializationUtils.serialize(user); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/OAuth2UserAuthorityTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/OAuth2UserAuthorityTests.java index ef37d2ab01..dca030c8e4 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/OAuth2UserAuthorityTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/OAuth2UserAuthorityTests.java @@ -28,7 +28,9 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Joe Grandja */ public class OAuth2UserAuthorityTests { + private static final String AUTHORITY = "ROLE_USER"; + private static final Map ATTRIBUTES = Collections.singletonMap("username", "test"); @Test(expected = IllegalArgumentException.class) @@ -53,4 +55,5 @@ public class OAuth2UserAuthorityTests { assertThat(userAuthority.getAuthority()).isEqualTo(AUTHORITY); assertThat(userAuthority.getAttributes()).isEqualTo(ATTRIBUTES); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/TestOAuth2Users.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/TestOAuth2Users.java index 456f6376aa..bdf2c155d5 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/TestOAuth2Users.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/user/TestOAuth2Users.java @@ -39,10 +39,8 @@ public class TestOAuth2Users { } private static Collection authorities(Map attributes) { - return new LinkedHashSet<>( - Arrays.asList( - new OAuth2UserAuthority(attributes), - new SimpleGrantedAuthority("SCOPE_read"), - new SimpleGrantedAuthority("SCOPE_write"))); + return new LinkedHashSet<>(Arrays.asList(new OAuth2UserAuthority(attributes), + new SimpleGrantedAuthority("SCOPE_read"), new SimpleGrantedAuthority("SCOPE_write"))); } + } diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2BodyExtractorsTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2BodyExtractorsTests.java index 48f7cd19da..61de352edd 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2BodyExtractorsTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2BodyExtractorsTests.java @@ -93,8 +93,7 @@ public class OAuth2BodyExtractorsTests { Mono result = extractor.extract(response, this.context); - assertThatCode(result::block) - .isInstanceOf(OAuth2AuthorizationException.class) + assertThatCode(result::block).isInstanceOf(OAuth2AuthorizationException.class) .hasMessageContaining("An error occurred parsing the Access Token response"); } @@ -107,8 +106,7 @@ public class OAuth2BodyExtractorsTests { Mono result = extractor.extract(response, this.context); - assertThatCode(result::block) - .isInstanceOf(OAuth2AuthorizationException.class) + assertThatCode(result::block).isInstanceOf(OAuth2AuthorizationException.class) .hasMessageContaining("Empty OAuth 2.0 Access Token Response"); } @@ -119,13 +117,10 @@ public class OAuth2BodyExtractorsTests { MockClientHttpResponse response = new MockClientHttpResponse(HttpStatus.OK); response.getHeaders().setContentType(MediaType.APPLICATION_JSON); - response.setBody("{\n" - + " \"access_token\":\"2YotnFZFEjr1zCsicMWpAA\",\n" - + " \"token_type\":\"Bearer\",\n" - + " \"expires_in\":3600,\n" - + " \"refresh_token\":\"tGzv3JOkF0XG5Qx2TlKWIA\",\n" - + " \"example_parameter\":\"example_value\"\n" - + " }"); + response.setBody( + "{\n" + " \"access_token\":\"2YotnFZFEjr1zCsicMWpAA\",\n" + " \"token_type\":\"Bearer\",\n" + + " \"expires_in\":3600,\n" + " \"refresh_token\":\"tGzv3JOkF0XG5Qx2TlKWIA\",\n" + + " \"example_parameter\":\"example_value\"\n" + " }"); Instant now = Instant.now(); OAuth2AccessTokenResponse result = extractor.extract(response, this.context).block(); @@ -137,7 +132,6 @@ public class OAuth2BodyExtractorsTests { assertThat(result.getAdditionalParameters()).containsEntry("example_parameter", "example_value"); } - @Test // gh-6087 public void oauth2AccessTokenResponseWhenMultipleAttributeTypesThenCreated() { @@ -146,14 +140,10 @@ public class OAuth2BodyExtractorsTests { MockClientHttpResponse response = new MockClientHttpResponse(HttpStatus.OK); response.getHeaders().setContentType(MediaType.APPLICATION_JSON); - response.setBody("{\n" - + " \"access_token\":\"2YotnFZFEjr1zCsicMWpAA\",\n" - + " \"token_type\":\"Bearer\",\n" - + " \"expires_in\":3600,\n" - + " \"refresh_token\":\"tGzv3JOkF0XG5Qx2TlKWIA\",\n" - + " \"subjson\":{}, \n" - + " \"list\":[] \n" - + " }"); + response.setBody( + "{\n" + " \"access_token\":\"2YotnFZFEjr1zCsicMWpAA\",\n" + " \"token_type\":\"Bearer\",\n" + + " \"expires_in\":3600,\n" + " \"refresh_token\":\"tGzv3JOkF0XG5Qx2TlKWIA\",\n" + + " \"subjson\":{}, \n" + " \"list\":[] \n" + " }"); Instant now = Instant.now(); OAuth2AccessTokenResponse result = extractor.extract(response, this.context).block(); @@ -165,4 +155,5 @@ public class OAuth2BodyExtractorsTests { assertThat(result.getAdditionalParameters().get("subjson")).isInstanceOfAny(Map.class); assertThat(result.getAdditionalParameters().get("list")).isInstanceOfAny(List.class); } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/JwsAlgorithm.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/JwsAlgorithm.java index d815208940..59f66b248a 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/JwsAlgorithm.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/JwsAlgorithm.java @@ -16,15 +16,19 @@ package org.springframework.security.oauth2.jose.jws; /** - * Super interface for cryptographic algorithms defined by the JSON Web Algorithms (JWA) specification - * and used by JSON Web Signature (JWS) to digitally sign or create a MAC - * of the contents of the JWS Protected Header and JWS Payload. + * Super interface for cryptographic algorithms defined by the JSON Web Algorithms (JWA) + * specification and used by JSON Web Signature (JWS) to digitally sign or create a MAC of + * the contents of the JWS Protected Header and JWS Payload. * * @author Joe Grandja * @since 5.2 - * @see JSON Web Algorithms (JWA) - * @see JSON Web Signature (JWS) - * @see Cryptographic Algorithms for Digital Signatures and MACs + * @see JSON Web Algorithms + * (JWA) + * @see JSON Web Signature + * (JWS) + * @see Cryptographic Algorithms for Digital + * Signatures and MACs */ public interface JwsAlgorithm { diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/JwsAlgorithms.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/JwsAlgorithms.java index b3ef013e6b..c4b26be816 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/JwsAlgorithms.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/JwsAlgorithms.java @@ -16,15 +16,19 @@ package org.springframework.security.oauth2.jose.jws; /** - * The cryptographic algorithms defined by the JSON Web Algorithms (JWA) specification - * and used by JSON Web Signature (JWS) to digitally sign or create a MAC - * of the contents of the JWS Protected Header and JWS Payload. + * The cryptographic algorithms defined by the JSON Web Algorithms (JWA) specification and + * used by JSON Web Signature (JWS) to digitally sign or create a MAC of the contents of + * the JWS Protected Header and JWS Payload. * * @author Joe Grandja * @since 5.0 - * @see JSON Web Algorithms (JWA) - * @see JSON Web Signature (JWS) - * @see Cryptographic Algorithms for Digital Signatures and MACs + * @see JSON Web Algorithms + * (JWA) + * @see JSON Web Signature + * (JWS) + * @see Cryptographic Algorithms for Digital + * Signatures and MACs */ public interface JwsAlgorithms { diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/MacAlgorithm.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/MacAlgorithm.java index 2f525b9a5c..6e0b02967c 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/MacAlgorithm.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/MacAlgorithm.java @@ -15,17 +15,21 @@ */ package org.springframework.security.oauth2.jose.jws; - /** - * An enumeration of the cryptographic algorithms defined by the JSON Web Algorithms (JWA) specification - * and used by JSON Web Signature (JWS) to create a MAC of the contents of the JWS Protected Header and JWS Payload. + * An enumeration of the cryptographic algorithms defined by the JSON Web Algorithms (JWA) + * specification and used by JSON Web Signature (JWS) to create a MAC of the contents of + * the JWS Protected Header and JWS Payload. * * @author Joe Grandja * @since 5.2 * @see JwsAlgorithm - * @see JSON Web Algorithms (JWA) - * @see JSON Web Signature (JWS) - * @see Cryptographic Algorithms for Digital Signatures and MACs + * @see JSON Web Algorithms + * (JWA) + * @see JSON Web Signature + * (JWS) + * @see Cryptographic Algorithms for Digital + * Signatures and MACs */ public enum MacAlgorithm implements JwsAlgorithm { @@ -44,7 +48,6 @@ public enum MacAlgorithm implements JwsAlgorithm { */ HS512(JwsAlgorithms.HS512); - private final String name; MacAlgorithm(String name) { @@ -53,7 +56,6 @@ public enum MacAlgorithm implements JwsAlgorithm { /** * Attempt to resolve the provided algorithm name to a {@code MacAlgorithm}. - * * @param name the algorithm name * @return the resolved {@code MacAlgorithm}, or {@code null} if not found */ @@ -68,11 +70,11 @@ public enum MacAlgorithm implements JwsAlgorithm { /** * Returns the algorithm name. - * * @return the algorithm name */ @Override public String getName() { return this.name; } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/SignatureAlgorithm.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/SignatureAlgorithm.java index 8ea0d884b7..6e572209f6 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/SignatureAlgorithm.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/SignatureAlgorithm.java @@ -16,15 +16,20 @@ package org.springframework.security.oauth2.jose.jws; /** - * An enumeration of the cryptographic algorithms defined by the JSON Web Algorithms (JWA) specification - * and used by JSON Web Signature (JWS) to digitally sign the contents of the JWS Protected Header and JWS Payload. + * An enumeration of the cryptographic algorithms defined by the JSON Web Algorithms (JWA) + * specification and used by JSON Web Signature (JWS) to digitally sign the contents of + * the JWS Protected Header and JWS Payload. * * @author Joe Grandja * @since 5.2 * @see JwsAlgorithm - * @see JSON Web Algorithms (JWA) - * @see JSON Web Signature (JWS) - * @see Cryptographic Algorithms for Digital Signatures and MACs + * @see JSON Web Algorithms + * (JWA) + * @see JSON Web Signature + * (JWS) + * @see Cryptographic Algorithms for Digital + * Signatures and MACs */ public enum SignatureAlgorithm implements JwsAlgorithm { @@ -73,7 +78,6 @@ public enum SignatureAlgorithm implements JwsAlgorithm { */ PS512(JwsAlgorithms.PS512); - private final String name; SignatureAlgorithm(String name) { @@ -82,7 +86,6 @@ public enum SignatureAlgorithm implements JwsAlgorithm { /** * Attempt to resolve the provided algorithm name to a {@code SignatureAlgorithm}. - * * @param name the algorithm name * @return the resolved {@code SignatureAlgorithm}, or {@code null} if not found */ @@ -97,11 +100,11 @@ public enum SignatureAlgorithm implements JwsAlgorithm { /** * Returns the algorithm name. - * * @return the algorithm name */ @Override public String getName() { return this.name; } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/BadJwtException.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/BadJwtException.java index 11aa05b9f9..3a30545179 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/BadJwtException.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/BadJwtException.java @@ -17,13 +17,15 @@ package org.springframework.security.oauth2.jwt; /** - * An exception similar to {@link org.springframework.security.authentication.BadCredentialsException} - * that indicates a {@link Jwt} that is invalid in some way. + * An exception similar to + * {@link org.springframework.security.authentication.BadCredentialsException} that + * indicates a {@link Jwt} that is invalid in some way. * * @author Josh Cummings * @since 5.3 */ public class BadJwtException extends JwtException { + public BadJwtException(String message) { super(message); } @@ -31,4 +33,5 @@ public class BadJwtException extends JwtException { public BadJwtException(String message, Throwable cause) { super(message, cause); } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/Jwt.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/Jwt.java index e5e09f0117..6e3b431e20 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/Jwt.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/Jwt.java @@ -34,29 +34,34 @@ import static org.springframework.security.oauth2.jwt.JwtClaimNames.NBF; import static org.springframework.security.oauth2.jwt.JwtClaimNames.SUB; /** - * An implementation of an {@link AbstractOAuth2Token} representing a JSON Web Token (JWT). + * An implementation of an {@link AbstractOAuth2Token} representing a JSON Web Token + * (JWT). * *

        * JWTs represent a set of "claims" as a JSON object that may be encoded in a - * JSON Web Signature (JWS) and/or JSON Web Encryption (JWE) structure. - * The JSON object, also known as the JWT Claims Set, consists of one or more claim name/value pairs. - * The claim name is a {@code String} and the claim value is an arbitrary JSON object. + * JSON Web Signature (JWS) and/or JSON Web Encryption (JWE) structure. The JSON object, + * also known as the JWT Claims Set, consists of one or more claim name/value pairs. The + * claim name is a {@code String} and the claim value is an arbitrary JSON object. * * @author Joe Grandja * @since 5.0 * @see AbstractOAuth2Token * @see JwtClaimAccessor - * @see JSON Web Token (JWT) - * @see JSON Web Signature (JWS) - * @see JSON Web Encryption (JWE) + * @see JSON Web Token + * (JWT) + * @see JSON Web Signature + * (JWS) + * @see JSON Web Encryption + * (JWE) */ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { + private final Map headers; + private final Map claims; /** * Constructs a {@code Jwt} using the provided parameters. - * * @param tokenValue the token value * @param issuedAt the time at which the JWT was issued * @param expiresAt the expiration time on or after which the JWT MUST NOT be accepted @@ -64,8 +69,8 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { * @param claims the JWT Claims Set * */ - public Jwt(String tokenValue, Instant issuedAt, Instant expiresAt, - Map headers, Map claims) { + public Jwt(String tokenValue, Instant issuedAt, Instant expiresAt, Map headers, + Map claims) { super(tokenValue, issuedAt, expiresAt); Assert.notEmpty(headers, "headers cannot be empty"); Assert.notEmpty(claims, "claims cannot be empty"); @@ -75,7 +80,6 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { /** * Returns the JOSE header(s). - * * @return a {@code Map} of the JOSE header(s) */ public Map getHeaders() { @@ -84,7 +88,6 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { /** * Returns the JWT Claims Set. - * * @return a {@code Map} of the JWT Claims Set */ @Override @@ -94,7 +97,6 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { /** * Return a {@link Jwt.Builder} - * * @return A {@link Jwt.Builder} */ public static Builder withTokenValue(String tokenValue) { @@ -109,8 +111,11 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { * @since 5.2 */ public final static class Builder { + private String tokenValue; + private final Map claims = new LinkedHashMap<>(); + private final Map headers = new LinkedHashMap<>(); private Builder(String tokenValue) { @@ -119,7 +124,6 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { /** * Use this token value in the resulting {@link Jwt} - * * @param tokenValue The token value to use * @return the {@link Builder} for further configurations */ @@ -130,7 +134,6 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { /** * Use this claim in the resulting {@link Jwt} - * * @param name The claim name * @param value The claim value * @return the {@link Builder} for further configurations @@ -141,8 +144,8 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { } /** - * Provides access to every {@link #claim(String, Object)} - * declared so far with the possibility to add, replace, or remove. + * Provides access to every {@link #claim(String, Object)} declared so far with + * the possibility to add, replace, or remove. * @param claimsConsumer the consumer * @return the {@link Builder} for further configurations */ @@ -153,7 +156,6 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { /** * Use this header in the resulting {@link Jwt} - * * @param name The header name * @param value The header value * @return the {@link Builder} for further configurations @@ -164,8 +166,8 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { } /** - * Provides access to every {@link #header(String, Object)} - * declared so far with the possibility to add, replace, or remove. + * Provides access to every {@link #header(String, Object)} declared so far with + * the possibility to add, replace, or remove. * @param headersConsumer the consumer * @return the {@link Builder} for further configurations */ @@ -176,7 +178,6 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { /** * Use this audience in the resulting {@link Jwt} - * * @param audience The audience(s) to use * @return the {@link Builder} for further configurations */ @@ -186,7 +187,6 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { /** * Use this expiration in the resulting {@link Jwt} - * * @param expiresAt The expiration to use * @return the {@link Builder} for further configurations */ @@ -197,7 +197,6 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { /** * Use this identifier in the resulting {@link Jwt} - * * @param jti The identifier to use * @return the {@link Builder} for further configurations */ @@ -208,7 +207,6 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { /** * Use this issued-at timestamp in the resulting {@link Jwt} - * * @param issuedAt The issued-at timestamp to use * @return the {@link Builder} for further configurations */ @@ -219,7 +217,6 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { /** * Use this issuer in the resulting {@link Jwt} - * * @param issuer The issuer to use * @return the {@link Builder} for further configurations */ @@ -230,7 +227,6 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { /** * Use this not-before timestamp in the resulting {@link Jwt} - * * @param notBefore The not-before timestamp to use * @return the {@link Builder} for further configurations */ @@ -241,7 +237,6 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { /** * Use this subject in the resulting {@link Jwt} - * * @param subject The subject to use * @return the {@link Builder} for further configurations */ @@ -252,7 +247,6 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { /** * Build the {@link Jwt} - * * @return The constructed {@link Jwt} */ public Jwt build() { @@ -267,5 +261,7 @@ public class Jwt extends AbstractOAuth2Token implements JwtClaimAccessor { } return (Instant) timestamp; } + } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtClaimAccessor.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtClaimAccessor.java index f7d5740201..8c9fc4bf4b 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtClaimAccessor.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtClaimAccessor.java @@ -22,21 +22,22 @@ import java.time.Instant; import java.util.List; /** - * A {@link ClaimAccessor} for the "claims" that may be contained - * in the JSON object JWT Claims Set of a JSON Web Token (JWT). + * A {@link ClaimAccessor} for the "claims" that may be contained in the JSON + * object JWT Claims Set of a JSON Web Token (JWT). * * @author Joe Grandja * @since 5.0 * @see ClaimAccessor * @see JwtClaimNames * @see Jwt - * @see Registered Claim Names + * @see Registered Claim Names */ public interface JwtClaimAccessor extends ClaimAccessor { /** - * Returns the Issuer {@code (iss)} claim which identifies the principal that issued the JWT. - * + * Returns the Issuer {@code (iss)} claim which identifies the principal that issued + * the JWT. * @return the Issuer identifier */ default URL getIssuer() { @@ -44,9 +45,8 @@ public interface JwtClaimAccessor extends ClaimAccessor { } /** - * Returns the Subject {@code (sub)} claim which identifies the principal - * that is the subject of the JWT. - * + * Returns the Subject {@code (sub)} claim which identifies the principal that is the + * subject of the JWT. * @return the Subject identifier */ default String getSubject() { @@ -54,9 +54,8 @@ public interface JwtClaimAccessor extends ClaimAccessor { } /** - * Returns the Audience {@code (aud)} claim which identifies the recipient(s) - * that the JWT is intended for. - * + * Returns the Audience {@code (aud)} claim which identifies the recipient(s) that the + * JWT is intended for. * @return the Audience(s) that this JWT intended for */ default List getAudience() { @@ -64,28 +63,28 @@ public interface JwtClaimAccessor extends ClaimAccessor { } /** - * Returns the Expiration time {@code (exp)} claim which identifies the expiration time - * on or after which the JWT MUST NOT be accepted for processing. - * - * @return the Expiration time on or after which the JWT MUST NOT be accepted for processing + * Returns the Expiration time {@code (exp)} claim which identifies the expiration + * time on or after which the JWT MUST NOT be accepted for processing. + * @return the Expiration time on or after which the JWT MUST NOT be accepted for + * processing */ default Instant getExpiresAt() { return this.getClaimAsInstant(JwtClaimNames.EXP); } /** - * Returns the Not Before {@code (nbf)} claim which identifies the time - * before which the JWT MUST NOT be accepted for processing. - * - * @return the Not Before time before which the JWT MUST NOT be accepted for processing + * Returns the Not Before {@code (nbf)} claim which identifies the time before which + * the JWT MUST NOT be accepted for processing. + * @return the Not Before time before which the JWT MUST NOT be accepted for + * processing */ default Instant getNotBefore() { return this.getClaimAsInstant(JwtClaimNames.NBF); } /** - * Returns the Issued at {@code (iat)} claim which identifies the time at which the JWT was issued. - * + * Returns the Issued at {@code (iat)} claim which identifies the time at which the + * JWT was issued. * @return the Issued at claim which identifies the time at which the JWT was issued */ default Instant getIssuedAt() { @@ -93,11 +92,12 @@ public interface JwtClaimAccessor extends ClaimAccessor { } /** - * Returns the JWT ID {@code (jti)} claim which provides a unique identifier for the JWT. - * + * Returns the JWT ID {@code (jti)} claim which provides a unique identifier for the + * JWT. * @return the JWT ID claim which provides a unique identifier for the JWT */ default String getId() { return this.getClaimAsString(JwtClaimNames.JTI); } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtClaimNames.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtClaimNames.java index aad5c0f452..247c3a8818 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtClaimNames.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtClaimNames.java @@ -16,13 +16,14 @@ package org.springframework.security.oauth2.jwt; /** - * The Registered Claim Names defined by the JSON Web Token (JWT) specification - * that may be contained in the JSON object JWT Claims Set. + * The Registered Claim Names defined by the JSON Web Token (JWT) specification that may + * be contained in the JSON object JWT Claims Set. * * @author Joe Grandja * @since 5.0 * @see JwtClaimAccessor - * @see JWT Claims + * @see JWT + * Claims */ public interface JwtClaimNames { @@ -32,22 +33,26 @@ public interface JwtClaimNames { String ISS = "iss"; /** - * {@code sub} - the Subject claim identifies the principal that is the subject of the JWT + * {@code sub} - the Subject claim identifies the principal that is the subject of the + * JWT */ String SUB = "sub"; /** - * {@code aud} - the Audience claim identifies the recipient(s) that the JWT is intended for + * {@code aud} - the Audience claim identifies the recipient(s) that the JWT is + * intended for */ String AUD = "aud"; /** - * {@code exp} - the Expiration time claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing + * {@code exp} - the Expiration time claim identifies the expiration time on or after + * which the JWT MUST NOT be accepted for processing */ String EXP = "exp"; /** - * {@code nbf} - the Not Before claim identifies the time before which the JWT MUST NOT be accepted for processing + * {@code nbf} - the Not Before claim identifies the time before which the JWT MUST + * NOT be accepted for processing */ String NBF = "nbf"; diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtClaimValidator.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtClaimValidator.java index c9b4a91d5b..fb0882a658 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtClaimValidator.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtClaimValidator.java @@ -15,32 +15,36 @@ */ package org.springframework.security.oauth2.jwt; +import java.util.function.Predicate; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.oauth2.core.OAuth2ErrorCodes; import org.springframework.security.oauth2.core.OAuth2TokenValidator; import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; import org.springframework.util.Assert; -import java.util.function.Predicate; - /** - * Validates a claim in a {@link Jwt} against a provided {@link java.util.function.Predicate} + * Validates a claim in a {@link Jwt} against a provided + * {@link java.util.function.Predicate} * * @author Zeeshan Adnan * @since 5.3 */ public final class JwtClaimValidator implements OAuth2TokenValidator { + private final Log logger = LogFactory.getLog(getClass()); private final String claim; + private final Predicate test; + private final OAuth2Error error; /** * Constructs a {@link JwtClaimValidator} using the provided parameters - * * @param claim - is the name of the claim in {@link Jwt} to validate. * @param test - is the predicate function for the claim to test against. */ @@ -49,8 +53,7 @@ public final class JwtClaimValidator implements OAuth2TokenValidator { Assert.notNull(test, "test can not be null"); this.claim = claim; this.test = test; - this.error = new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST, - "The " + this.claim + " claim is not valid", + this.error = new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST, "The " + this.claim + " claim is not valid", "https://tools.ietf.org/html/rfc6750#section-3.1"); } @@ -61,11 +64,13 @@ public final class JwtClaimValidator implements OAuth2TokenValidator { public OAuth2TokenValidatorResult validate(Jwt token) { Assert.notNull(token, "token cannot be null"); T claimValue = token.getClaim(this.claim); - if (test.test(claimValue)) { + if (this.test.test(claimValue)) { return OAuth2TokenValidatorResult.success(); - } else { - logger.debug(error.getDescription()); - return OAuth2TokenValidatorResult.failure(error); + } + else { + this.logger.debug(this.error.getDescription()); + return OAuth2TokenValidatorResult.failure(this.error); } } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoder.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoder.java index 020f6362eb..e1a47036f4 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoder.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoder.java @@ -16,33 +16,39 @@ package org.springframework.security.oauth2.jwt; /** - * Implementations of this interface are responsible for "decoding" - * a JSON Web Token (JWT) from it's compact claims representation format to a {@link Jwt}. + * Implementations of this interface are responsible for "decoding" a JSON Web + * Token (JWT) from it's compact claims representation format to a {@link Jwt}. * *

        - * JWTs may be represented using the JWS Compact Serialization format for a - * JSON Web Signature (JWS) structure or JWE Compact Serialization format for a - * JSON Web Encryption (JWE) structure. Therefore, implementors are responsible - * for verifying a JWS and/or decrypting a JWE. + * JWTs may be represented using the JWS Compact Serialization format for a JSON Web + * Signature (JWS) structure or JWE Compact Serialization format for a JSON Web Encryption + * (JWE) structure. Therefore, implementors are responsible for verifying a JWS and/or + * decrypting a JWE. * * @author Joe Grandja * @since 5.0 * @see Jwt - * @see JSON Web Token (JWT) - * @see JSON Web Signature (JWS) - * @see JSON Web Encryption (JWE) - * @see JWS Compact Serialization - * @see JWE Compact Serialization + * @see JSON Web Token + * (JWT) + * @see JSON Web Signature + * (JWS) + * @see JSON Web Encryption + * (JWE) + * @see JWS + * Compact Serialization + * @see JWE + * Compact Serialization */ @FunctionalInterface public interface JwtDecoder { /** - * Decodes the JWT from it's compact claims representation format and returns a {@link Jwt}. - * + * Decodes the JWT from it's compact claims representation format and returns a + * {@link Jwt}. * @param token the JWT value * @return a {@link Jwt} * @throws JwtException if an error occurs while attempting to decode the JWT */ Jwt decode(String token) throws JwtException; + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoderFactory.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoderFactory.java index 094cc96086..f8d4898238 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoderFactory.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoderFactory.java @@ -16,22 +16,20 @@ package org.springframework.security.oauth2.jwt; /** - * A factory for {@link JwtDecoder}(s). - * This factory should be supplied with a type that provides - * contextual information used to create a specific {@code JwtDecoder}. + * A factory for {@link JwtDecoder}(s). This factory should be supplied with a type that + * provides contextual information used to create a specific {@code JwtDecoder}. * * @author Joe Grandja * @since 5.2 * @see JwtDecoder - * - * @param The type that provides contextual information used to create a specific {@code JwtDecoder}. + * @param The type that provides contextual information used to create a specific + * {@code JwtDecoder}. */ @FunctionalInterface public interface JwtDecoderFactory { /** * Creates a {@code JwtDecoder} using the supplied "contextual" type. - * * @param context the type that provides contextual information * @return a {@link JwtDecoder} */ diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoderProviderConfigurationUtils.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoderProviderConfigurationUtils.java index 2496abb5b1..b730f48b53 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoderProviderConfigurationUtils.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoderProviderConfigurationUtils.java @@ -27,21 +27,26 @@ import java.util.Collections; import java.util.Map; /** - * Allows resolving configuration from an - * OpenID Provider Configuration or - * Authorization Server Metadata Request based on provided - * issuer and method invoked. + * Allows resolving configuration from an OpenID + * Provider Configuration or + * Authorization Server Metadata + * Request based on provided issuer and method invoked. * * @author Thomas Vitale * @author Rafiullah Hamedy * @since 5.2 */ class JwtDecoderProviderConfigurationUtils { + private static final String OIDC_METADATA_PATH = "/.well-known/openid-configuration"; + private static final String OAUTH_METADATA_PATH = "/.well-known/oauth-authorization-server"; + private static final RestTemplate rest = new RestTemplate(); - private static final ParameterizedTypeReference> typeReference = - new ParameterizedTypeReference>() {}; + + private static final ParameterizedTypeReference> typeReference = new ParameterizedTypeReference>() { + }; static Map getConfigurationForOidcIssuerLocation(String oidcIssuerLocation) { return getConfiguration(oidcIssuerLocation, oidc(URI.create(oidcIssuerLocation))); @@ -58,14 +63,13 @@ class JwtDecoderProviderConfigurationUtils { metadataIssuer = configuration.get("issuer").toString(); } if (!issuer.equals(metadataIssuer)) { - throw new IllegalStateException("The Issuer \"" + metadataIssuer + "\" provided in the configuration did not " - + "match the requested issuer \"" + issuer + "\""); + throw new IllegalStateException("The Issuer \"" + metadataIssuer + + "\" provided in the configuration did not " + "match the requested issuer \"" + issuer + "\""); } } private static Map getConfiguration(String issuer, URI... uris) { - String errorMessage = "Unable to resolve the Configuration with the provided Issuer of " + - "\"" + issuer + "\""; + String errorMessage = "Unable to resolve the Configuration with the provided Issuer of " + "\"" + issuer + "\""; for (URI uri : uris) { try { RequestEntity request = RequestEntity.get(uri).build(); @@ -77,11 +81,13 @@ class JwtDecoderProviderConfigurationUtils { } return configuration; - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { throw e; - } catch (RuntimeException e) { - if (!(e instanceof HttpClientErrorException && - ((HttpClientErrorException) e).getStatusCode().is4xxClientError())) { + } + catch (RuntimeException e) { + if (!(e instanceof HttpClientErrorException + && ((HttpClientErrorException) e).getStatusCode().is4xxClientError())) { throw new IllegalArgumentException(errorMessage, e); } // else try another endpoint @@ -91,20 +97,18 @@ class JwtDecoderProviderConfigurationUtils { } private static URI oidc(URI issuer) { - return UriComponentsBuilder.fromUri(issuer) - .replacePath(issuer.getPath() + OIDC_METADATA_PATH) + return UriComponentsBuilder.fromUri(issuer).replacePath(issuer.getPath() + OIDC_METADATA_PATH) .build(Collections.emptyMap()); } private static URI oidcRfc8414(URI issuer) { - return UriComponentsBuilder.fromUri(issuer) - .replacePath(OIDC_METADATA_PATH + issuer.getPath()) + return UriComponentsBuilder.fromUri(issuer).replacePath(OIDC_METADATA_PATH + issuer.getPath()) .build(Collections.emptyMap()); } private static URI oauth(URI issuer) { - return UriComponentsBuilder.fromUri(issuer) - .replacePath(OAUTH_METADATA_PATH + issuer.getPath()) + return UriComponentsBuilder.fromUri(issuer).replacePath(OAUTH_METADATA_PATH + issuer.getPath()) .build(Collections.emptyMap()); } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoders.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoders.java index 0d2f233198..b4acb42b9b 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoders.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtDecoders.java @@ -23,10 +23,11 @@ import org.springframework.util.Assert; import static org.springframework.security.oauth2.jwt.NimbusJwtDecoder.withJwkSetUri; /** - * Allows creating a {@link JwtDecoder} from an - * OpenID Provider Configuration or - * Authorization Server Metadata Request based on provided - * issuer and method invoked. + * Allows creating a {@link JwtDecoder} from an OpenID + * Provider Configuration or + * Authorization Server Metadata + * Request based on provided issuer and method invoked. * * @author Josh Cummings * @author Rafiullah Hamedy @@ -35,68 +36,69 @@ import static org.springframework.security.oauth2.jwt.NimbusJwtDecoder.withJwkSe public final class JwtDecoders { /** - * Creates a {@link JwtDecoder} using the provided - * Issuer by making an - * OpenID Provider - * Configuration Request and using the values in the - * OpenID + * Creates a {@link JwtDecoder} using the provided Issuer + * by making an OpenID + * Provider Configuration Request and using the values in the OpenID * Provider Configuration Response to initialize the {@link JwtDecoder}. - * - * @param oidcIssuerLocation the Issuer - * @return a {@link JwtDecoder} that was initialized by the OpenID Provider Configuration. + * @param oidcIssuerLocation the Issuer + * @return a {@link JwtDecoder} that was initialized by the OpenID Provider + * Configuration. */ public static JwtDecoder fromOidcIssuerLocation(String oidcIssuerLocation) { Assert.hasText(oidcIssuerLocation, "oidcIssuerLocation cannot be empty"); - Map configuration = JwtDecoderProviderConfigurationUtils.getConfigurationForOidcIssuerLocation(oidcIssuerLocation); + Map configuration = JwtDecoderProviderConfigurationUtils + .getConfigurationForOidcIssuerLocation(oidcIssuerLocation); return withProviderConfiguration(configuration, oidcIssuerLocation); } /** - * Creates a {@link JwtDecoder} using the provided - * Issuer by querying - * three different discovery endpoints serially, using the values in the first successful response to - * initialize. If an endpoint returns anything other than a 200 or a 4xx, the method will exit without - * attempting subsequent endpoints. + * Creates a {@link JwtDecoder} using the provided Issuer + * by querying three different discovery endpoints serially, using the values in the + * first successful response to initialize. If an endpoint returns anything other than + * a 200 or a 4xx, the method will exit without attempting subsequent endpoints. * - * The three endpoints are computed as follows, given that the {@code issuer} is composed of a {@code host} - * and a {@code path}: + * The three endpoints are computed as follows, given that the {@code issuer} is + * composed of a {@code host} and a {@code path}: * *

          - *
        1. - * {@code host/.well-known/openid-configuration/path}, as defined in - * RFC 8414's Compatibility Notes. - *
        2. - *
        3. - * {@code issuer/.well-known/openid-configuration}, as defined in - * - * OpenID Provider Configuration. - *
        4. - *
        5. - * {@code host/.well-known/oauth-authorization-server/path}, as defined in - * Authorization Server Metadata Request. - *
        6. + *
        7. {@code host/.well-known/openid-configuration/path}, as defined in + * RFC 8414's Compatibility + * Notes.
        8. + *
        9. {@code issuer/.well-known/openid-configuration}, as defined in + * OpenID Provider Configuration.
        10. + *
        11. {@code host/.well-known/oauth-authorization-server/path}, as defined in + * Authorization Server + * Metadata Request.
        12. *
        * * Note that the second endpoint is the equivalent of calling * {@link JwtDecoders#fromOidcIssuerLocation(String)} - * - * @param issuer the Issuer + * @param issuer the Issuer * @return a {@link JwtDecoder} that was initialized by one of the described endpoints */ public static JwtDecoder fromIssuerLocation(String issuer) { Assert.hasText(issuer, "issuer cannot be empty"); - Map configuration = JwtDecoderProviderConfigurationUtils.getConfigurationForIssuerLocation(issuer); + Map configuration = JwtDecoderProviderConfigurationUtils + .getConfigurationForIssuerLocation(issuer); return withProviderConfiguration(configuration, issuer); } /** - * Validate provided issuer and build {@link JwtDecoder} from - * OpenID Provider - * Configuration Response and Authorization Server Metadata - * Response. - * + * Validate provided issuer and build {@link JwtDecoder} from OpenID + * Provider Configuration Response and + * Authorization Server + * Metadata Response. * @param configuration the configuration values - * @param issuer the Issuer + * @param issuer the Issuer * @return {@link JwtDecoder} */ private static JwtDecoder withProviderConfiguration(Map configuration, String issuer) { @@ -108,5 +110,7 @@ public final class JwtDecoders { return jwtDecoder; } - private JwtDecoders() {} + private JwtDecoders() { + } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtException.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtException.java index fe3f58cadb..80f9c9d6f3 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtException.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtException.java @@ -25,7 +25,6 @@ public class JwtException extends RuntimeException { /** * Constructs a {@code JwtException} using the provided parameters. - * * @param message the detail message */ public JwtException(String message) { @@ -34,11 +33,11 @@ public class JwtException extends RuntimeException { /** * Constructs a {@code JwtException} using the provided parameters. - * * @param message the detail message * @param cause the root cause */ public JwtException(String message, Throwable cause) { super(message, cause); } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtIssuerValidator.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtIssuerValidator.java index da9beacce8..6f0c085621 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtIssuerValidator.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtIssuerValidator.java @@ -33,7 +33,6 @@ public final class JwtIssuerValidator implements OAuth2TokenValidator { /** * Constructs a {@link JwtIssuerValidator} using the provided parameters - * * @param issuer - The issuer that each {@link Jwt} should have. */ public JwtIssuerValidator(String issuer) { @@ -49,4 +48,5 @@ public final class JwtIssuerValidator implements OAuth2TokenValidator { Assert.notNull(token, "token cannot be null"); return this.validator.validate(token); } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtTimestampValidator.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtTimestampValidator.java index eef9dc8e8e..21ddb58aab 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtTimestampValidator.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtTimestampValidator.java @@ -30,20 +30,23 @@ import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; import org.springframework.util.Assert; /** - * An implementation of {@link OAuth2TokenValidator} for verifying claims in a Jwt-based access token + * An implementation of {@link OAuth2TokenValidator} for verifying claims in a Jwt-based + * access token * *

        - * Because clocks can differ between the Jwt source, say the Authorization Server, and its destination, say the - * Resource Server, there is a default clock leeway exercised when deciding if the current time is within the Jwt's - * specified operating window + * Because clocks can differ between the Jwt source, say the Authorization Server, and its + * destination, say the Resource Server, there is a default clock leeway exercised when + * deciding if the current time is within the Jwt's specified operating window * * @author Josh Cummings * @since 5.1 * @see Jwt * @see OAuth2TokenValidator - * @see JSON Web Token (JWT) + * @see JSON Web Token + * (JWT) */ public final class JwtTimestampValidator implements OAuth2TokenValidator { + private final Log logger = LogFactory.getLog(getClass()); private static final Duration DEFAULT_MAX_CLOCK_SKEW = Duration.of(60, ChronoUnit.SECONDS); @@ -94,21 +97,18 @@ public final class JwtTimestampValidator implements OAuth2TokenValidator { private OAuth2Error createOAuth2Error(String reason) { logger.debug(reason); - return new OAuth2Error( - OAuth2ErrorCodes.INVALID_REQUEST, - reason, + return new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST, reason, "https://tools.ietf.org/html/rfc6750#section-3.1"); } /** - * ' - * Use this {@link Clock} with {@link Instant#now()} for assessing - * timestamp validity - * + * ' Use this {@link Clock} with {@link Instant#now()} for assessing timestamp + * validity * @param clock */ public void setClock(Clock clock) { Assert.notNull(clock, "clock cannot be null"); this.clock = clock; } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtValidationException.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtValidationException.java index 3ea9e11050..cc028423e0 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtValidationException.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtValidationException.java @@ -23,13 +23,13 @@ import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; import org.springframework.util.Assert; /** - * An exception that results from an unsuccessful - * {@link OAuth2TokenValidatorResult} + * An exception that results from an unsuccessful {@link OAuth2TokenValidatorResult} * * @author Josh Cummings * @since 5.1 */ public class JwtValidationException extends BadJwtException { + private final Collection errors; /** @@ -47,9 +47,9 @@ public class JwtValidationException extends BadJwtException { * throw new JwtValidationException(errors.iterator().next().getDescription(), errors); * } * - * * @param message - the exception message - * @param errors - a list of {@link OAuth2Error}s with extra detail about the validation result + * @param errors - a list of {@link OAuth2Error}s with extra detail about the + * validation result */ public JwtValidationException(String message, Collection errors) { super(message); @@ -65,4 +65,5 @@ public class JwtValidationException extends BadJwtException { public Collection getErrors() { return this.errors; } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtValidators.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtValidators.java index 9630c944fd..ceb3738fa2 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtValidators.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/JwtValidators.java @@ -24,6 +24,7 @@ import org.springframework.security.oauth2.core.OAuth2TokenValidator; /** * Provides factory methods for creating {@code OAuth2TokenValidator} + * * @author Josh Cummings * @author Rob Winch * @since 5.1 @@ -32,14 +33,17 @@ public final class JwtValidators { /** *

        - * Create a {@link Jwt} Validator that contains all standard validators when an issuer is known. + * Create a {@link Jwt} Validator that contains all standard validators when an issuer + * is known. *

        *

        - * User's wanting to leverage the defaults plus additional validation can add the result of this - * method to {@code DelegatingOAuth2TokenValidator} along with the additional validators. + * User's wanting to leverage the defaults plus additional validation can add the + * result of this method to {@code DelegatingOAuth2TokenValidator} along with the + * additional validators. *

        * @param issuer the issuer - * @return - a delegating validator containing all standard validators as well as any supplied + * @return - a delegating validator containing all standard validators as well as any + * supplied */ public static OAuth2TokenValidator createDefaultWithIssuer(String issuer) { List> validators = new ArrayList<>(); @@ -53,14 +57,18 @@ public final class JwtValidators { * Create a {@link Jwt} Validator that contains all standard validators. *

        *

        - * User's wanting to leverage the defaults plus additional validation can add the result of this - * method to {@code DelegatingOAuth2TokenValidator} along with the additional validators. + * User's wanting to leverage the defaults plus additional validation can add the + * result of this method to {@code DelegatingOAuth2TokenValidator} along with the + * additional validators. *

        - * @return - a delegating validator containing all standard validators as well as any supplied + * @return - a delegating validator containing all standard validators as well as any + * supplied */ public static OAuth2TokenValidator createDefault() { return new DelegatingOAuth2TokenValidator<>(Arrays.asList(new JwtTimestampValidator())); } - private JwtValidators() {} + private JwtValidators() { + } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverter.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverter.java index 50a6d382dc..bb8d502446 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverter.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverter.java @@ -31,27 +31,33 @@ import java.util.HashMap; import java.util.Map; /** - * Converts a JWT claim set, claim by claim. Can be configured with custom converters - * by claim name. + * Converts a JWT claim set, claim by claim. Can be configured with custom converters by + * claim name. * * @author Josh Cummings * @since 5.1 * @see ClaimTypeConverter */ public final class MappedJwtClaimSetConverter implements Converter, Map> { + private final static ConversionService CONVERSION_SERVICE = ClaimConversionService.getSharedInstance(); + private final static TypeDescriptor OBJECT_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Object.class); + private final static TypeDescriptor STRING_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(String.class); + private final static TypeDescriptor INSTANT_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Instant.class); + private final static TypeDescriptor URL_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(URL.class); + private final Map> claimTypeConverters; + private final Converter, Map> delegate; /** * Constructs a {@link MappedJwtClaimSetConverter} with the provided arguments * * This will completely replace any set of default converters. - * * @param claimTypeConverters The {@link Map} of converters to use */ public MappedJwtClaimSetConverter(Map> claimTypeConverters) { @@ -64,26 +70,26 @@ public final class MappedJwtClaimSetConverter implements Converter * MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); * * - * Or, the following would supply a custom converter for the subject, leaving the other defaults - * in place: + * Or, the following would supply a custom converter for the subject, leaving the + * other defaults in place: * *
         	 * 	MappedJwtClaimsSetConverter.withDefaults(
         	 * 		Collections.singletonMap(JwtClaimNames.SUB, new UserDetailsServiceJwtSubjectConverter()));
         	 * 
        * - * To completely replace the underlying {@link Map} of converters, see {@link MappedJwtClaimSetConverter#MappedJwtClaimSetConverter(Map)}. - * + * To completely replace the underlying {@link Map} of converters, see + * {@link MappedJwtClaimSetConverter#MappedJwtClaimSetConverter(Map)}. * @param claimTypeConverters - * @return An instance of {@link MappedJwtClaimSetConverter} that contains the converters provided, - * plus any defaults that were not overridden. + * @return An instance of {@link MappedJwtClaimSetConverter} that contains the + * converters provided, plus any defaults that were not overridden. */ public static MappedJwtClaimSetConverter withDefaults(Map> claimTypeConverters) { Assert.notNull(claimTypeConverters, "claimTypeConverters cannot be null"); @@ -131,7 +137,8 @@ public final class MappedJwtClaimSetConverter implements Converter jwtProcessor; - private Converter, Map> claimSetConverter = - MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); + private Converter, Map> claimSetConverter = MappedJwtClaimSetConverter + .withDefaults(Collections.emptyMap()); + private OAuth2TokenValidator jwtValidator = JwtValidators.createDefault(); /** * Configures a {@link NimbusJwtDecoder} with the given parameters - * * @param jwtProcessor - the {@link JWTProcessor} to use */ public NimbusJwtDecoder(JWTProcessor jwtProcessor) { @@ -98,7 +99,6 @@ public final class NimbusJwtDecoder implements JwtDecoder { /** * Use this {@link Jwt} Validator - * * @param jwtValidator - the Jwt Validator to use */ public void setJwtValidator(OAuth2TokenValidator jwtValidator) { @@ -108,7 +108,6 @@ public final class NimbusJwtDecoder implements JwtDecoder { /** * Use the following {@link Converter} for manipulating the JWT's claim set - * * @param claimSetConverter the {@link Converter} to use */ public void setClaimSetConverter(Converter, Map> claimSetConverter) { @@ -118,7 +117,6 @@ public final class NimbusJwtDecoder implements JwtDecoder { /** * Decode and validate the JWT from its compact claims representation format - * * @param token the JWT value * @return a validated {@link Jwt} * @throws JwtException @@ -136,7 +134,8 @@ public final class NimbusJwtDecoder implements JwtDecoder { private JWT parse(String token) { try { return JWTParser.parse(token); - } catch (Exception ex) { + } + catch (Exception ex) { throw new BadJwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, ex.getMessage()), ex); } } @@ -149,51 +148,50 @@ public final class NimbusJwtDecoder implements JwtDecoder { Map headers = new LinkedHashMap<>(parsedJwt.getHeader().toJSONObject()); Map claims = this.claimSetConverter.convert(jwtClaimsSet.getClaims()); - return Jwt.withTokenValue(token) - .headers(h -> h.putAll(headers)) - .claims(c -> c.putAll(claims)) - .build(); - } catch (RemoteKeySourceException ex) { + return Jwt.withTokenValue(token).headers(h -> h.putAll(headers)).claims(c -> c.putAll(claims)).build(); + } + catch (RemoteKeySourceException ex) { if (ex.getCause() instanceof ParseException) { throw new JwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, "Malformed Jwk set")); - } else { + } + else { throw new JwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, ex.getMessage()), ex); } - } catch (JOSEException ex) { + } + catch (JOSEException ex) { throw new JwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, ex.getMessage()), ex); - } catch (Exception ex) { + } + catch (Exception ex) { if (ex.getCause() instanceof ParseException) { throw new BadJwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, "Malformed payload")); - } else { + } + else { throw new BadJwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, ex.getMessage()), ex); } } } - private Jwt validateJwt(Jwt jwt){ + private Jwt validateJwt(Jwt jwt) { OAuth2TokenValidatorResult result = this.jwtValidator.validate(jwt); if (result.hasErrors()) { Collection errors = result.getErrors(); String validationErrorString = "Unable to validate Jwt"; for (OAuth2Error oAuth2Error : errors) { if (!StringUtils.isEmpty(oAuth2Error.getDescription())) { - validationErrorString = String.format( - DECODING_ERROR_MESSAGE_TEMPLATE, oAuth2Error.getDescription()); + validationErrorString = String.format(DECODING_ERROR_MESSAGE_TEMPLATE, + oAuth2Error.getDescription()); break; } } - throw new JwtValidationException( - validationErrorString, - result.getErrors()); + throw new JwtValidationException(validationErrorString, result.getErrors()); } return jwt; } /** - * Use the given - * JWK Set uri. - * + * Use the given JWK Set + * uri. * @param jwkSetUri the JWK Set uri to use * @return a {@link JwkSetUriJwtDecoderBuilder} for further configurations */ @@ -203,7 +201,6 @@ public final class NimbusJwtDecoder implements JwtDecoder { /** * Use the given public key to validate JWTs - * * @param key the public key to use * @return a {@link PublicKeyJwtDecoderBuilder} for further configurations */ @@ -213,7 +210,6 @@ public final class NimbusJwtDecoder implements JwtDecoder { /** * Use the given {@code SecretKey} to validate the MAC on a JSON Web Signature (JWS). - * * @param secretKey the {@code SecretKey} used to validate the MAC * @return a {@link SecretKeyJwtDecoderBuilder} for further configurations */ @@ -223,26 +219,32 @@ public final class NimbusJwtDecoder implements JwtDecoder { /** * A builder for creating {@link NimbusJwtDecoder} instances based on a - * JWK Set uri. + * JWK Set + * uri. */ public static final class JwkSetUriJwtDecoderBuilder { + private String jwkSetUri; + private Set signatureAlgorithms = new HashSet<>(); + private RestOperations restOperations = new RestTemplate(); + private Cache cache; + private Consumer> jwtProcessorCustomizer; private JwkSetUriJwtDecoderBuilder(String jwkSetUri) { Assert.hasText(jwkSetUri, "jwkSetUri cannot be empty"); this.jwkSetUri = jwkSetUri; - this.jwtProcessorCustomizer = (processor) -> {}; + this.jwtProcessorCustomizer = (processor) -> { + }; } /** * Append the given signing - * algorithm - * to the set of algorithms to use. - * + * algorithm to the set of algorithms to use. * @param signatureAlgorithm the algorithm to use * @return a {@link JwkSetUriJwtDecoderBuilder} for further configurations */ @@ -254,10 +256,10 @@ public final class NimbusJwtDecoder implements JwtDecoder { /** * Configure the list of - * algorithms - * to use with the given {@link Consumer}. - * - * @param signatureAlgorithmsConsumer a {@link Consumer} for further configuring the algorithm list + * algorithms to use with the given {@link Consumer}. + * @param signatureAlgorithmsConsumer a {@link Consumer} for further configuring + * the algorithm list * @return a {@link JwkSetUriJwtDecoderBuilder} for further configurations */ public JwkSetUriJwtDecoderBuilder jwsAlgorithms(Consumer> signatureAlgorithmsConsumer) { @@ -267,11 +269,11 @@ public final class NimbusJwtDecoder implements JwtDecoder { } /** - * Use the given {@link RestOperations} to coordinate with the authorization servers indicated in the - * JWK Set uri - * as well as the - * Issuer. - * + * Use the given {@link RestOperations} to coordinate with the authorization + * servers indicated in the + * JWK Set uri as well + * as the Issuer. * @param restOperations * @return */ @@ -284,7 +286,6 @@ public final class NimbusJwtDecoder implements JwtDecoder { /** * Use the given {@link Cache} to store * JWK Set. - * * @param cache the {@link Cache} to be used to store JWK Set * @return a {@link JwkSetUriJwtDecoderBuilder} for further configurations * @since 5.4 @@ -296,14 +297,15 @@ public final class NimbusJwtDecoder implements JwtDecoder { } /** - * Use the given {@link Consumer} to customize the {@link JWTProcessor ConfigurableJWTProcessor} before - * passing it to the build {@link NimbusJwtDecoder}. - * + * Use the given {@link Consumer} to customize the {@link JWTProcessor + * ConfigurableJWTProcessor} before passing it to the build + * {@link NimbusJwtDecoder}. * @param jwtProcessorCustomizer the callback used to alter the processor * @return a {@link JwkSetUriJwtDecoderBuilder} for further configurations * @since 5.4 */ - public JwkSetUriJwtDecoderBuilder jwtProcessorCustomizer(Consumer> jwtProcessorCustomizer) { + public JwkSetUriJwtDecoderBuilder jwtProcessorCustomizer( + Consumer> jwtProcessorCustomizer) { Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null"); this.jwtProcessorCustomizer = jwtProcessorCustomizer; return this; @@ -312,7 +314,8 @@ public final class NimbusJwtDecoder implements JwtDecoder { JWSKeySelector jwsKeySelector(JWKSource jwkSource) { if (this.signatureAlgorithms.isEmpty()) { return new JWSVerificationKeySelector<>(JWSAlgorithm.RS256, jwkSource); - } else { + } + else { Set jwsAlgorithms = new HashSet<>(); for (SignatureAlgorithm signatureAlgorithm : this.signatureAlgorithms) { JWSAlgorithm jwsAlgorithm = JWSAlgorithm.parse(signatureAlgorithm.getName()); @@ -337,7 +340,8 @@ public final class NimbusJwtDecoder implements JwtDecoder { jwtProcessor.setJWSKeySelector(jwsKeySelector(jwkSource)); // Spring Security validates the claim set independent from Nimbus - jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { }); + jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { + }); this.jwtProcessorCustomizer.accept(jwtProcessor); @@ -346,7 +350,6 @@ public final class NimbusJwtDecoder implements JwtDecoder { /** * Build the configured {@link NimbusJwtDecoder}. - * * @return the configured {@link NimbusJwtDecoder} */ public NimbusJwtDecoder build() { @@ -356,12 +359,14 @@ public final class NimbusJwtDecoder implements JwtDecoder { private static URL toURL(String url) { try { return new URL(url); - } catch (MalformedURLException ex) { + } + catch (MalformedURLException ex) { throw new IllegalArgumentException("Invalid JWK Set URL \"" + url + "\" : " + ex.getMessage(), ex); } } private static class NoOpJwkSetCache implements JWKSetCache { + @Override public void put(JWKSet jwkSet) { } @@ -375,10 +380,13 @@ public final class NimbusJwtDecoder implements JwtDecoder { public boolean requiresRefresh() { return true; } + } private static class CachingResourceRetriever implements ResourceRetriever { + private final Cache cache; + private final ResourceRetriever resourceRetriever; CachingResourceRetriever(Cache cache, ResourceRetriever resourceRetriever) { @@ -392,22 +400,27 @@ public final class NimbusJwtDecoder implements JwtDecoder { try { jwkSet = this.cache.get(url.toString(), () -> this.resourceRetriever.retrieveResource(url).getContent()); - } catch (Cache.ValueRetrievalException ex) { + } + catch (Cache.ValueRetrievalException ex) { Throwable thrownByValueLoader = ex.getCause(); if (thrownByValueLoader instanceof IOException) { throw (IOException) thrownByValueLoader; } throw new IOException(thrownByValueLoader); - } catch (Exception ex) { + } + catch (Exception ex) { throw new IOException(ex); } return new Resource(jwkSet, "UTF-8"); } + } private static class RestOperationsResourceRetriever implements ResourceRetriever { + private static final MediaType APPLICATION_JWK_SET_JSON = new MediaType("application", "jwk-set+json"); + private final RestOperations restOperations; RestOperationsResourceRetriever(RestOperations restOperations) { @@ -424,7 +437,8 @@ public final class NimbusJwtDecoder implements JwtDecoder { try { RequestEntity request = new RequestEntity<>(headers, HttpMethod.GET, url.toURI()); response = this.restOperations.exchange(request, String.class); - } catch (Exception ex) { + } + catch (Exception ex) { throw new IOException(ex); } @@ -434,31 +448,38 @@ public final class NimbusJwtDecoder implements JwtDecoder { return new Resource(response.getBody(), "UTF-8"); } + } + } /** * A builder for creating {@link NimbusJwtDecoder} instances based on a public key. */ public static final class PublicKeyJwtDecoderBuilder { + private JWSAlgorithm jwsAlgorithm; + private RSAPublicKey key; + private Consumer> jwtProcessorCustomizer; private PublicKeyJwtDecoderBuilder(RSAPublicKey key) { Assert.notNull(key, "key cannot be null"); this.jwsAlgorithm = JWSAlgorithm.RS256; this.key = key; - this.jwtProcessorCustomizer = (processor) -> {}; + this.jwtProcessorCustomizer = (processor) -> { + }; } /** * Use the given signing - * algorithm. + * algorithm. * * The value should be one of - * RS256, RS384, or RS512. - * + * RS256, RS384, or RS512. * @param signatureAlgorithm the algorithm to use * @return a {@link PublicKeyJwtDecoderBuilder} for further configurations */ @@ -469,14 +490,15 @@ public final class NimbusJwtDecoder implements JwtDecoder { } /** - * Use the given {@link Consumer} to customize the {@link JWTProcessor ConfigurableJWTProcessor} before - * passing it to the build {@link NimbusJwtDecoder}. - * + * Use the given {@link Consumer} to customize the {@link JWTProcessor + * ConfigurableJWTProcessor} before passing it to the build + * {@link NimbusJwtDecoder}. * @param jwtProcessorCustomizer the callback used to alter the processor * @return a {@link PublicKeyJwtDecoderBuilder} for further configurations * @since 5.4 */ - public PublicKeyJwtDecoderBuilder jwtProcessorCustomizer(Consumer> jwtProcessorCustomizer) { + public PublicKeyJwtDecoderBuilder jwtProcessorCustomizer( + Consumer> jwtProcessorCustomizer) { Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null"); this.jwtProcessorCustomizer = jwtProcessorCustomizer; return this; @@ -484,18 +506,18 @@ public final class NimbusJwtDecoder implements JwtDecoder { JWTProcessor processor() { if (!JWSAlgorithm.Family.RSA.contains(this.jwsAlgorithm)) { - throw new IllegalStateException("The provided key is of type RSA; " + - "however the signature algorithm is of some other type: " + - this.jwsAlgorithm + ". Please indicate one of RS256, RS384, or RS512."); + throw new IllegalStateException( + "The provided key is of type RSA; " + "however the signature algorithm is of some other type: " + + this.jwsAlgorithm + ". Please indicate one of RS256, RS384, or RS512."); } - JWSKeySelector jwsKeySelector = - new SingleKeyJWSKeySelector<>(this.jwsAlgorithm, this.key); + JWSKeySelector jwsKeySelector = new SingleKeyJWSKeySelector<>(this.jwsAlgorithm, this.key); DefaultJWTProcessor jwtProcessor = new DefaultJWTProcessor<>(); jwtProcessor.setJWSKeySelector(jwsKeySelector); // Spring Security validates the claim set independent from Nimbus - jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { }); + jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { + }); this.jwtProcessorCustomizer.accept(jwtProcessor); @@ -504,36 +526,41 @@ public final class NimbusJwtDecoder implements JwtDecoder { /** * Build the configured {@link NimbusJwtDecoder}. - * * @return the configured {@link NimbusJwtDecoder} */ public NimbusJwtDecoder build() { return new NimbusJwtDecoder(processor()); } + } /** - * A builder for creating {@link NimbusJwtDecoder} instances based on a {@code SecretKey}. + * A builder for creating {@link NimbusJwtDecoder} instances based on a + * {@code SecretKey}. */ public static final class SecretKeyJwtDecoderBuilder { + private final SecretKey secretKey; + private JWSAlgorithm jwsAlgorithm = JWSAlgorithm.HS256; + private Consumer> jwtProcessorCustomizer; private SecretKeyJwtDecoderBuilder(SecretKey secretKey) { Assert.notNull(secretKey, "secretKey cannot be null"); this.secretKey = secretKey; - this.jwtProcessorCustomizer = (processor) -> {}; + this.jwtProcessorCustomizer = (processor) -> { + }; } /** * Use the given - * algorithm - * when generating the MAC. + * algorithm when generating the MAC. * * The value should be one of - * HS256, HS384 or HS512. - * + * HS256, HS384 or HS512. * @param macAlgorithm the MAC algorithm to use * @return a {@link SecretKeyJwtDecoderBuilder} for further configurations */ @@ -544,14 +571,15 @@ public final class NimbusJwtDecoder implements JwtDecoder { } /** - * Use the given {@link Consumer} to customize the {@link JWTProcessor ConfigurableJWTProcessor} before - * passing it to the build {@link NimbusJwtDecoder}. - * + * Use the given {@link Consumer} to customize the {@link JWTProcessor + * ConfigurableJWTProcessor} before passing it to the build + * {@link NimbusJwtDecoder}. * @param jwtProcessorCustomizer the callback used to alter the processor * @return a {@link SecretKeyJwtDecoderBuilder} for further configurations * @since 5.4 */ - public SecretKeyJwtDecoderBuilder jwtProcessorCustomizer(Consumer> jwtProcessorCustomizer) { + public SecretKeyJwtDecoderBuilder jwtProcessorCustomizer( + Consumer> jwtProcessorCustomizer) { Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null"); this.jwtProcessorCustomizer = jwtProcessorCustomizer; return this; @@ -559,7 +587,6 @@ public final class NimbusJwtDecoder implements JwtDecoder { /** * Build the configured {@link NimbusJwtDecoder}. - * * @return the configured {@link NimbusJwtDecoder} */ public NimbusJwtDecoder build() { @@ -567,17 +594,20 @@ public final class NimbusJwtDecoder implements JwtDecoder { } JWTProcessor processor() { - JWSKeySelector jwsKeySelector = - new SingleKeyJWSKeySelector<>(this.jwsAlgorithm, this.secretKey); + JWSKeySelector jwsKeySelector = new SingleKeyJWSKeySelector<>(this.jwsAlgorithm, + this.secretKey); DefaultJWTProcessor jwtProcessor = new DefaultJWTProcessor<>(); jwtProcessor.setJWSKeySelector(jwsKeySelector); // Spring Security validates the claim set independent from Nimbus - jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { }); + jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { + }); this.jwtProcessorCustomizer.accept(jwtProcessor); return jwtProcessor; } + } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoderJwkSupport.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoderJwkSupport.java index 8d698d01ae..c8b4f435a6 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoderJwkSupport.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoderJwkSupport.java @@ -28,38 +28,43 @@ import java.util.Map; import static org.springframework.security.oauth2.jwt.NimbusJwtDecoder.withJwkSetUri; /** - * An implementation of a {@link JwtDecoder} that "decodes" a - * JSON Web Token (JWT) and additionally verifies it's digital signature if the JWT is a - * JSON Web Signature (JWS). The public key used for verification is obtained from the - * JSON Web Key (JWK) Set {@code URL} supplied via the constructor. + * An implementation of a {@link JwtDecoder} that "decodes" a JSON Web Token (JWT) and + * additionally verifies it's digital signature if the JWT is a JSON Web Signature (JWS). + * The public key used for verification is obtained from the JSON Web Key (JWK) Set + * {@code URL} supplied via the constructor. * *

        * NOTE: This implementation uses the Nimbus JOSE + JWT SDK internally. * * @deprecated Use {@link NimbusJwtDecoder} or {@link JwtDecoders} instead - * * @author Joe Grandja * @author Josh Cummings * @since 5.0 * @see JwtDecoder * @see NimbusJwtDecoder - * @see JSON Web Token (JWT) - * @see JSON Web Signature (JWS) - * @see JSON Web Key (JWK) - * @see Nimbus JOSE + JWT SDK + * @see JSON Web Token + * (JWT) + * @see JSON Web Signature + * (JWS) + * @see JSON Web Key + * (JWK) + * @see Nimbus + * JOSE + JWT SDK */ @Deprecated public final class NimbusJwtDecoderJwkSupport implements JwtDecoder { + private NimbusJwtDecoder.JwkSetUriJwtDecoderBuilder jwtDecoderBuilder; + private OAuth2TokenValidator jwtValidator = JwtValidators.createDefault(); - private Converter, Map> claimSetConverter = - MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); + + private Converter, Map> claimSetConverter = MappedJwtClaimSetConverter + .withDefaults(Collections.emptyMap()); private NimbusJwtDecoder delegate; /** * Constructs a {@code NimbusJwtDecoderJwkSupport} using the provided parameters. - * * @param jwkSetUrl the JSON Web Key (JWK) Set {@code URL} */ public NimbusJwtDecoderJwkSupport(String jwkSetUrl) { @@ -68,9 +73,9 @@ public final class NimbusJwtDecoderJwkSupport implements JwtDecoder { /** * Constructs a {@code NimbusJwtDecoderJwkSupport} using the provided parameters. - * * @param jwkSetUrl the JSON Web Key (JWK) Set {@code URL} - * @param jwsAlgorithm the JSON Web Algorithm (JWA) used for verifying the digital signatures + * @param jwsAlgorithm the JSON Web Algorithm (JWA) used for verifying the digital + * signatures */ public NimbusJwtDecoderJwkSupport(String jwkSetUrl, String jwsAlgorithm) { Assert.hasText(jwkSetUrl, "jwkSetUrl cannot be empty"); @@ -94,7 +99,6 @@ public final class NimbusJwtDecoderJwkSupport implements JwtDecoder { /** * Use this {@link Jwt} Validator - * * @param jwtValidator - the Jwt Validator to use */ public void setJwtValidator(OAuth2TokenValidator jwtValidator) { @@ -105,7 +109,6 @@ public final class NimbusJwtDecoderJwkSupport implements JwtDecoder { /** * Use the following {@link Converter} for manipulating the JWT's claim set - * * @param claimSetConverter the {@link Converter} to use */ public void setClaimSetConverter(Converter, Map> claimSetConverter) { @@ -118,11 +121,13 @@ public final class NimbusJwtDecoderJwkSupport implements JwtDecoder { * Sets the {@link RestOperations} used when requesting the JSON Web Key (JWK) Set. * * @since 5.1 - * @param restOperations the {@link RestOperations} used when requesting the JSON Web Key (JWK) Set + * @param restOperations the {@link RestOperations} used when requesting the JSON Web + * Key (JWK) Set */ public void setRestOperations(RestOperations restOperations) { Assert.notNull(restOperations, "restOperations cannot be null"); this.jwtDecoderBuilder = this.jwtDecoderBuilder.restOperations(restOperations); this.delegate = makeDelegate(); } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java index 9bbedfd306..2cbfbaf8ce 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java @@ -62,9 +62,9 @@ import java.util.function.Consumer; import java.util.function.Function; /** - * An implementation of a {@link ReactiveJwtDecoder} that "decodes" a - * JSON Web Token (JWT) and additionally verifies it's digital signature if the JWT is a - * JSON Web Signature (JWS). + * An implementation of a {@link ReactiveJwtDecoder} that "decodes" a JSON Web + * Token (JWT) and additionally verifies it's digital signature if the JWT is a JSON Web + * Signature (JWS). * *

        * NOTE: This implementation uses the Nimbus JOSE + JWT SDK internally. @@ -73,21 +73,26 @@ import java.util.function.Function; * @author Joe Grandja * @since 5.1 * @see ReactiveJwtDecoder - * @see JSON Web Token (JWT) - * @see JSON Web Signature (JWS) - * @see JSON Web Key (JWK) - * @see Nimbus JOSE + JWT SDK + * @see JSON Web Token + * (JWT) + * @see JSON Web Signature + * (JWS) + * @see JSON Web Key + * (JWK) + * @see Nimbus + * JOSE + JWT SDK */ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { + private final Converter> jwtProcessor; private OAuth2TokenValidator jwtValidator = JwtValidators.createDefault(); - private Converter, Map> claimSetConverter = - MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); + + private Converter, Map> claimSetConverter = MappedJwtClaimSetConverter + .withDefaults(Collections.emptyMap()); /** * Constructs a {@code NimbusReactiveJwtDecoder} using the provided parameters. - * * @param jwkSetUrl the JSON Web Key (JWK) Set {@code URL} */ public NimbusReactiveJwtDecoder(String jwkSetUrl) { @@ -96,7 +101,6 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { /** * Constructs a {@code NimbusReactiveJwtDecoder} using the provided parameters. - * * @param publicKey the {@code RSAPublicKey} used to verify the signature * @since 5.2 */ @@ -106,8 +110,8 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { /** * Constructs a {@code NimbusReactiveJwtDecoder} using the provided parameters. - * - * @param jwtProcessor the {@link Converter} used to process and verify the signed Jwt and return the Jwt Claim Set + * @param jwtProcessor the {@link Converter} used to process and verify the signed Jwt + * and return the Jwt Claim Set * @since 5.2 */ public NimbusReactiveJwtDecoder(Converter> jwtProcessor) { @@ -116,7 +120,6 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { /** * Use the provided {@link OAuth2TokenValidator} to validate incoming {@link Jwt}s. - * * @param jwtValidator the {@link OAuth2TokenValidator} to use */ public void setJwtValidator(OAuth2TokenValidator jwtValidator) { @@ -126,7 +129,6 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { /** * Use the following {@link Converter} for manipulating the JWT's claim set - * * @param claimSetConverter the {@link Converter} to use */ public void setClaimSetConverter(Converter, Map> claimSetConverter) { @@ -146,20 +148,22 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { private JWT parse(String token) { try { return JWTParser.parse(token); - } catch (Exception ex) { + } + catch (Exception ex) { throw new BadJwtException("An error occurred while attempting to decode the Jwt: " + ex.getMessage(), ex); } } private Mono decode(JWT parsedToken) { try { - return this.jwtProcessor.convert(parsedToken) - .map(set -> createJwt(parsedToken, set)) - .map(this::validateJwt) - .onErrorMap(e -> !(e instanceof IllegalStateException) && !(e instanceof JwtException), e -> new JwtException("An error occurred while attempting to decode the Jwt: ", e)); - } catch (JwtException ex) { + return this.jwtProcessor.convert(parsedToken).map(set -> createJwt(parsedToken, set)).map(this::validateJwt) + .onErrorMap(e -> !(e instanceof IllegalStateException) && !(e instanceof JwtException), + e -> new JwtException("An error occurred while attempting to decode the Jwt: ", e)); + } + catch (JwtException ex) { throw ex; - } catch (RuntimeException ex) { + } + catch (RuntimeException ex) { throw new JwtException("An error occurred while attempting to decode the Jwt: " + ex.getMessage(), ex); } } @@ -169,11 +173,10 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { Map headers = new LinkedHashMap<>(parsedJwt.getHeader().toJSONObject()); Map claims = this.claimSetConverter.convert(jwtClaimsSet.getClaims()); - return Jwt.withTokenValue(parsedJwt.getParsedString()) - .headers(h -> h.putAll(headers)) - .claims(c -> c.putAll(claims)) - .build(); - } catch (Exception ex) { + return Jwt.withTokenValue(parsedJwt.getParsedString()).headers(h -> h.putAll(headers)) + .claims(c -> c.putAll(claims)).build(); + } + catch (Exception ex) { throw new BadJwtException("An error occurred while attempting to decode the Jwt: " + ex.getMessage(), ex); } } @@ -196,9 +199,8 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { } /** - * Use the given - * JWK Set uri to validate JWTs. - * + * Use the given JWK Set + * uri to validate JWTs. * @param jwkSetUri the JWK Set uri to use * @return a {@link JwkSetUriReactiveJwtDecoderBuilder} for further configurations * @@ -210,7 +212,6 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { /** * Use the given public key to validate JWTs - * * @param key the public key to use * @return a {@link PublicKeyReactiveJwtDecoderBuilder} for further configurations * @@ -222,7 +223,6 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { /** * Use the given {@code SecretKey} to validate the MAC on a JSON Web Signature (JWS). - * * @param secretKey the {@code SecretKey} used to validate the MAC * @return a {@link SecretKeyReactiveJwtDecoderBuilder} for further configurations * @@ -234,7 +234,6 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { /** * Use the given {@link Function} to validate JWTs - * * @param source the {@link Function} * @return a {@link JwkSourceReactiveJwtDecoderBuilder} for further configurations * @@ -246,27 +245,32 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { /** * A builder for creating {@link NimbusReactiveJwtDecoder} instances based on a - * JWK Set uri. + * JWK Set + * uri. * * @since 5.2 */ public static final class JwkSetUriReactiveJwtDecoderBuilder { + private final String jwkSetUri; + private Set signatureAlgorithms = new HashSet<>(); + private WebClient webClient = WebClient.create(); + private Consumer> jwtProcessorCustomizer; private JwkSetUriReactiveJwtDecoderBuilder(String jwkSetUri) { Assert.hasText(jwkSetUri, "jwkSetUri cannot be empty"); this.jwkSetUri = jwkSetUri; - this.jwtProcessorCustomizer = (processor) -> {}; + this.jwtProcessorCustomizer = (processor) -> { + }; } /** * Append the given signing - * algorithm - * to the set of algorithms to use. - * + * algorithm to the set of algorithms to use. * @param signatureAlgorithm the algorithm to use * @return a {@link JwkSetUriReactiveJwtDecoderBuilder} for further configurations */ @@ -278,24 +282,24 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { /** * Configure the list of - * algorithms - * to use with the given {@link Consumer}. - * - * @param signatureAlgorithmsConsumer a {@link Consumer} for further configuring the algorithm list + * algorithms to use with the given {@link Consumer}. + * @param signatureAlgorithmsConsumer a {@link Consumer} for further configuring + * the algorithm list * @return a {@link JwkSetUriReactiveJwtDecoderBuilder} for further configurations */ - public JwkSetUriReactiveJwtDecoderBuilder jwsAlgorithms(Consumer> signatureAlgorithmsConsumer) { + public JwkSetUriReactiveJwtDecoderBuilder jwsAlgorithms( + Consumer> signatureAlgorithmsConsumer) { Assert.notNull(signatureAlgorithmsConsumer, "signatureAlgorithmsConsumer cannot be null"); signatureAlgorithmsConsumer.accept(this.signatureAlgorithms); return this; } /** - * Use the given {@link WebClient} to coordinate with the authorization servers indicated in the - * JWK Set uri - * as well as the - * Issuer. - * + * Use the given {@link WebClient} to coordinate with the authorization servers + * indicated in the JWK + * Set uri as well as the Issuer. * @param webClient * @return a {@link JwkSetUriReactiveJwtDecoderBuilder} for further configurations */ @@ -306,14 +310,15 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { } /** - * Use the given {@link Consumer} to customize the {@link JWTProcessor ConfigurableJWTProcessor} before - * passing it to the build {@link NimbusReactiveJwtDecoder}. - * + * Use the given {@link Consumer} to customize the {@link JWTProcessor + * ConfigurableJWTProcessor} before passing it to the build + * {@link NimbusReactiveJwtDecoder}. * @param jwtProcessorCustomizer the callback used to alter the processor * @return a {@link JwkSetUriReactiveJwtDecoderBuilder} for further configurations * @since 5.4 */ - public JwkSetUriReactiveJwtDecoderBuilder jwtProcessorCustomizer(Consumer> jwtProcessorCustomizer) { + public JwkSetUriReactiveJwtDecoderBuilder jwtProcessorCustomizer( + Consumer> jwtProcessorCustomizer) { Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null"); this.jwtProcessorCustomizer = jwtProcessorCustomizer; return this; @@ -321,7 +326,6 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { /** * Build the configured {@link NimbusReactiveJwtDecoder}. - * * @return the configured {@link NimbusReactiveJwtDecoder} */ public NimbusReactiveJwtDecoder build() { @@ -331,7 +335,8 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { JWSKeySelector jwsKeySelector(JWKSource jwkSource) { if (this.signatureAlgorithms.isEmpty()) { return new JWSVerificationKeySelector<>(JWSAlgorithm.RS256, jwkSource); - } else { + } + else { Set jwsAlgorithms = new HashSet<>(); for (SignatureAlgorithm signatureAlgorithm : this.signatureAlgorithms) { JWSAlgorithm jwsAlgorithm = JWSAlgorithm.parse(signatureAlgorithm.getName()); @@ -346,7 +351,8 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { DefaultJWTProcessor jwtProcessor = new DefaultJWTProcessor<>(); JWSKeySelector jwsKeySelector = jwsKeySelector(jwkSource); jwtProcessor.setJWSKeySelector(jwsKeySelector); - jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> {}); + jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { + }); this.jwtProcessorCustomizer.accept(jwtProcessor); @@ -356,8 +362,7 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { Function expectedJwsAlgorithms = getExpectedJwsAlgorithms(jwsKeySelector); return jwt -> { JWKSelector selector = createSelector(expectedJwsAlgorithms, jwt.getHeader()); - return source.get(selector) - .onErrorMap(e -> new IllegalStateException("Could not obtain the keys", e)) + return source.get(selector).onErrorMap(e -> new IllegalStateException("Could not obtain the keys", e)) .map(jwkList -> createClaimsSet(jwtProcessor, jwt, new JWKSecurityContext(jwkList))); }; } @@ -377,31 +382,37 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { return new JWKSelector(JWKMatcher.forJWSHeader(jwsHeader)); } + } /** - * A builder for creating {@link NimbusReactiveJwtDecoder} instances based on a public key. + * A builder for creating {@link NimbusReactiveJwtDecoder} instances based on a public + * key. * * @since 5.2 */ public static final class PublicKeyReactiveJwtDecoderBuilder { + private final RSAPublicKey key; + private JWSAlgorithm jwsAlgorithm; + private Consumer> jwtProcessorCustomizer; private PublicKeyReactiveJwtDecoderBuilder(RSAPublicKey key) { Assert.notNull(key, "key cannot be null"); this.key = key; this.jwsAlgorithm = JWSAlgorithm.RS256; - this.jwtProcessorCustomizer = (processor) -> {}; + this.jwtProcessorCustomizer = (processor) -> { + }; } /** * Use the given signing - * algorithm. - * The value should be one of - * RS256, RS384, or RS512. - * + * algorithm. The value should be one of + * RS256, RS384, or RS512. * @param signatureAlgorithm the algorithm to use * @return a {@link PublicKeyReactiveJwtDecoderBuilder} for further configurations */ @@ -412,14 +423,15 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { } /** - * Use the given {@link Consumer} to customize the {@link JWTProcessor ConfigurableJWTProcessor} before - * passing it to the build {@link NimbusReactiveJwtDecoder}. - * + * Use the given {@link Consumer} to customize the {@link JWTProcessor + * ConfigurableJWTProcessor} before passing it to the build + * {@link NimbusReactiveJwtDecoder}. * @param jwtProcessorCustomizer the callback used to alter the processor * @return a {@link PublicKeyReactiveJwtDecoderBuilder} for further configurations * @since 5.4 */ - public PublicKeyReactiveJwtDecoderBuilder jwtProcessorCustomizer(Consumer> jwtProcessorCustomizer) { + public PublicKeyReactiveJwtDecoderBuilder jwtProcessorCustomizer( + Consumer> jwtProcessorCustomizer) { Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null"); this.jwtProcessorCustomizer = jwtProcessorCustomizer; return this; @@ -427,7 +439,6 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { /** * Build the configured {@link NimbusReactiveJwtDecoder}. - * * @return the configured {@link NimbusReactiveJwtDecoder} */ public NimbusReactiveJwtDecoder build() { @@ -436,49 +447,55 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { Converter> processor() { if (!JWSAlgorithm.Family.RSA.contains(this.jwsAlgorithm)) { - throw new IllegalStateException("The provided key is of type RSA; " + - "however the signature algorithm is of some other type: " + - this.jwsAlgorithm + ". Please indicate one of RS256, RS384, or RS512."); + throw new IllegalStateException( + "The provided key is of type RSA; " + "however the signature algorithm is of some other type: " + + this.jwsAlgorithm + ". Please indicate one of RS256, RS384, or RS512."); } - JWSKeySelector jwsKeySelector = - new SingleKeyJWSKeySelector<>(this.jwsAlgorithm, this.key); + JWSKeySelector jwsKeySelector = new SingleKeyJWSKeySelector<>(this.jwsAlgorithm, this.key); DefaultJWTProcessor jwtProcessor = new DefaultJWTProcessor<>(); jwtProcessor.setJWSKeySelector(jwsKeySelector); // Spring Security validates the claim set independent from Nimbus - jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { }); + jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { + }); this.jwtProcessorCustomizer.accept(jwtProcessor); return jwt -> Mono.just(createClaimsSet(jwtProcessor, jwt, null)); } + } /** - * A builder for creating {@link NimbusReactiveJwtDecoder} instances based on a {@code SecretKey}. + * A builder for creating {@link NimbusReactiveJwtDecoder} instances based on a + * {@code SecretKey}. * * @since 5.2 */ public static final class SecretKeyReactiveJwtDecoderBuilder { + private final SecretKey secretKey; + private JWSAlgorithm jwsAlgorithm = JWSAlgorithm.HS256; + private Consumer> jwtProcessorCustomizer; private SecretKeyReactiveJwtDecoderBuilder(SecretKey secretKey) { Assert.notNull(secretKey, "secretKey cannot be null"); this.secretKey = secretKey; - this.jwtProcessorCustomizer = (processor) -> {}; + this.jwtProcessorCustomizer = (processor) -> { + }; } /** * Use the given - * algorithm - * when generating the MAC. + * algorithm when generating the MAC. * * The value should be one of - * HS256, HS384 or HS512. - * + * HS256, HS384 or HS512. * @param macAlgorithm the MAC algorithm to use * @return a {@link SecretKeyReactiveJwtDecoderBuilder} for further configurations */ @@ -489,14 +506,15 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { } /** - * Use the given {@link Consumer} to customize the {@link JWTProcessor ConfigurableJWTProcessor} before - * passing it to the build {@link NimbusReactiveJwtDecoder}. - * + * Use the given {@link Consumer} to customize the {@link JWTProcessor + * ConfigurableJWTProcessor} before passing it to the build + * {@link NimbusReactiveJwtDecoder}. * @param jwtProcessorCustomizer the callback used to alter the processor * @return a {@link SecretKeyReactiveJwtDecoderBuilder} for further configurations * @since 5.4 */ - public SecretKeyReactiveJwtDecoderBuilder jwtProcessorCustomizer(Consumer> jwtProcessorCustomizer) { + public SecretKeyReactiveJwtDecoderBuilder jwtProcessorCustomizer( + Consumer> jwtProcessorCustomizer) { Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null"); this.jwtProcessorCustomizer = jwtProcessorCustomizer; return this; @@ -504,7 +522,6 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { /** * Build the configured {@link NimbusReactiveJwtDecoder}. - * * @return the configured {@link NimbusReactiveJwtDecoder} */ public NimbusReactiveJwtDecoder build() { @@ -512,18 +529,20 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { } Converter> processor() { - JWSKeySelector jwsKeySelector = - new SingleKeyJWSKeySelector<>(this.jwsAlgorithm, this.secretKey); + JWSKeySelector jwsKeySelector = new SingleKeyJWSKeySelector<>(this.jwsAlgorithm, + this.secretKey); DefaultJWTProcessor jwtProcessor = new DefaultJWTProcessor<>(); jwtProcessor.setJWSKeySelector(jwsKeySelector); // Spring Security validates the claim set independent from Nimbus - jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { }); + jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { + }); this.jwtProcessorCustomizer.accept(jwtProcessor); return jwt -> Mono.just(createClaimsSet(jwtProcessor, jwt, null)); } + } /** @@ -532,20 +551,24 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { * @since 5.2 */ public static final class JwkSourceReactiveJwtDecoderBuilder { + private final Function> jwkSource; + private JWSAlgorithm jwsAlgorithm = JWSAlgorithm.RS256; + private Consumer> jwtProcessorCustomizer; private JwkSourceReactiveJwtDecoderBuilder(Function> jwkSource) { Assert.notNull(jwkSource, "jwkSource cannot be null"); this.jwkSource = jwkSource; - this.jwtProcessorCustomizer = (processor) -> {}; + this.jwtProcessorCustomizer = (processor) -> { + }; } /** * Use the given signing - * algorithm. - * + * algorithm. * @param jwsAlgorithm the algorithm to use * @return a {@link JwkSourceReactiveJwtDecoderBuilder} for further configurations */ @@ -556,14 +579,15 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { } /** - * Use the given {@link Consumer} to customize the {@link JWTProcessor ConfigurableJWTProcessor} before - * passing it to the build {@link NimbusReactiveJwtDecoder}. - * + * Use the given {@link Consumer} to customize the {@link JWTProcessor + * ConfigurableJWTProcessor} before passing it to the build + * {@link NimbusReactiveJwtDecoder}. * @param jwtProcessorCustomizer the callback used to alter the processor * @return a {@link JwkSourceReactiveJwtDecoderBuilder} for further configurations * @since 5.4 */ - public JwkSourceReactiveJwtDecoderBuilder jwtProcessorCustomizer(Consumer> jwtProcessorCustomizer) { + public JwkSourceReactiveJwtDecoderBuilder jwtProcessorCustomizer( + Consumer> jwtProcessorCustomizer) { Assert.notNull(jwtProcessorCustomizer, "jwtProcessorCustomizer cannot be null"); this.jwtProcessorCustomizer = jwtProcessorCustomizer; return this; @@ -571,7 +595,6 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { /** * Build the configured {@link NimbusReactiveJwtDecoder}. - * * @return the configured {@link NimbusReactiveJwtDecoder} */ public NimbusReactiveJwtDecoder build() { @@ -580,28 +603,29 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { Converter> processor() { JWKSecurityContextJWKSet jwkSource = new JWKSecurityContextJWKSet(); - JWSKeySelector jwsKeySelector = - new JWSVerificationKeySelector<>(this.jwsAlgorithm, jwkSource); + JWSKeySelector jwsKeySelector = new JWSVerificationKeySelector<>(this.jwsAlgorithm, + jwkSource); DefaultJWTProcessor jwtProcessor = new DefaultJWTProcessor<>(); jwtProcessor.setJWSKeySelector(jwsKeySelector); - jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> {}); + jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> { + }); this.jwtProcessorCustomizer.accept(jwtProcessor); return jwt -> { if (jwt instanceof SignedJWT) { return this.jwkSource.apply((SignedJWT) jwt) - .onErrorMap(e -> new IllegalStateException("Could not obtain the keys", e)) - .collectList() + .onErrorMap(e -> new IllegalStateException("Could not obtain the keys", e)).collectList() .map(jwks -> createClaimsSet(jwtProcessor, jwt, new JWKSecurityContext(jwks))); } throw new BadJwtException("Unsupported algorithm of " + jwt.getHeader().getAlgorithm()); }; } + } private static JWTClaimsSet createClaimsSet(JWTProcessor jwtProcessor, - JWT parsedToken, C context) { + JWT parsedToken, C context) { try { return jwtProcessor.process(parsedToken, context); } @@ -612,4 +636,5 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { throw new JwtException("Failed to validate the token", e); } } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJWKSource.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJWKSource.java index 7ffbbc7a82..a13866f122 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJWKSource.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJWKSource.java @@ -24,9 +24,12 @@ import java.util.List; /** * A reactive version of {@link com.nimbusds.jose.jwk.source.JWKSource} + * * @author Rob Winch * @since 5.1 */ interface ReactiveJWKSource { + Mono> get(JWKSelector jwkSelector); + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJWKSourceAdapter.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJWKSourceAdapter.java index 784688e05d..24da1b0984 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJWKSourceAdapter.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJWKSourceAdapter.java @@ -26,10 +26,12 @@ import java.util.List; /** * Adapts a {@link JWKSource} to a {@link ReactiveJWKSource} which must be non-blocking. + * * @author Rob Winch * @since 5.1 */ class ReactiveJWKSourceAdapter implements ReactiveJWKSource { + private final JWKSource source; /** @@ -44,4 +46,5 @@ class ReactiveJWKSourceAdapter implements ReactiveJWKSource { public Mono> get(JWKSelector jwkSelector) { return Mono.fromCallable(() -> this.source.get(jwkSelector, null)); } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecoder.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecoder.java index 7f7431e49c..7f94e310e6 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecoder.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecoder.java @@ -18,30 +18,35 @@ package org.springframework.security.oauth2.jwt; import reactor.core.publisher.Mono; /** - * Implementations of this interface are responsible for "decoding" - * a JSON Web Token (JWT) from it's compact claims representation format to a {@link Jwt}. + * Implementations of this interface are responsible for "decoding" a JSON Web + * Token (JWT) from it's compact claims representation format to a {@link Jwt}. * *

        - * JWTs may be represented using the JWS Compact Serialization format for a - * JSON Web Signature (JWS) structure or JWE Compact Serialization format for a - * JSON Web Encryption (JWE) structure. Therefore, implementors are responsible - * for verifying a JWS and/or decrypting a JWE. + * JWTs may be represented using the JWS Compact Serialization format for a JSON Web + * Signature (JWS) structure or JWE Compact Serialization format for a JSON Web Encryption + * (JWE) structure. Therefore, implementors are responsible for verifying a JWS and/or + * decrypting a JWE. * * @author Rob Winch * @since 5.1 * @see Jwt - * @see JSON Web Token (JWT) - * @see JSON Web Signature (JWS) - * @see JSON Web Encryption (JWE) - * @see JWS Compact Serialization - * @see JWE Compact Serialization + * @see JSON Web Token + * (JWT) + * @see JSON Web Signature + * (JWS) + * @see JSON Web Encryption + * (JWE) + * @see JWS + * Compact Serialization + * @see JWE + * Compact Serialization */ @FunctionalInterface public interface ReactiveJwtDecoder { /** - * Decodes the JWT from it's compact claims representation format and returns a {@link Jwt}. - * + * Decodes the JWT from it's compact claims representation format and returns a + * {@link Jwt}. * @param token the JWT value * @return a {@link Jwt} * @throws JwtException if an error occurs while attempting to decode the JWT diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecoderFactory.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecoderFactory.java index cc93890fc5..61b1ce0ac2 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecoderFactory.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecoderFactory.java @@ -16,22 +16,21 @@ package org.springframework.security.oauth2.jwt; /** - * A factory for {@link ReactiveJwtDecoder}(s). - * This factory should be supplied with a type that provides - * contextual information used to create a specific {@code ReactiveJwtDecoder}. + * A factory for {@link ReactiveJwtDecoder}(s). This factory should be supplied with a + * type that provides contextual information used to create a specific + * {@code ReactiveJwtDecoder}. * * @author Joe Grandja * @since 5.2 * @see ReactiveJwtDecoder - * - * @param The type that provides contextual information used to create a specific {@code ReactiveJwtDecoder}. + * @param The type that provides contextual information used to create a specific + * {@code ReactiveJwtDecoder}. */ @FunctionalInterface public interface ReactiveJwtDecoderFactory { /** * Creates a {@code ReactiveJwtDecoder} using the supplied "contextual" type. - * * @param context the type that provides contextual information * @return a {@link ReactiveJwtDecoder} */ diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecoders.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecoders.java index d062b515cf..702ca0eaef 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecoders.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecoders.java @@ -23,10 +23,11 @@ import org.springframework.util.Assert; import static org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder.withJwkSetUri; /** - * Allows creating a {@link ReactiveJwtDecoder} from an - * OpenID Provider Configuration or - * Authorization Server Metadata Request based on provided - * issuer and method invoked. + * Allows creating a {@link ReactiveJwtDecoder} from an OpenID + * Provider Configuration or + * Authorization Server Metadata + * Request based on provided issuer and method invoked. * * @author Josh Cummings * @since 5.1 @@ -34,68 +35,70 @@ import static org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder.w public final class ReactiveJwtDecoders { /** - * Creates a {@link ReactiveJwtDecoder} using the provided - * Issuer by making an - * OpenID Provider - * Configuration Request and using the values in the - * OpenID + * Creates a {@link ReactiveJwtDecoder} using the provided Issuer + * by making an OpenID + * Provider Configuration Request and using the values in the OpenID * Provider Configuration Response to initialize the {@link ReactiveJwtDecoder}. - * - * @param oidcIssuerLocation the Issuer - * @return a {@link ReactiveJwtDecoder} that was initialized by the OpenID Provider Configuration. + * @param oidcIssuerLocation the Issuer + * @return a {@link ReactiveJwtDecoder} that was initialized by the OpenID Provider + * Configuration. */ public static ReactiveJwtDecoder fromOidcIssuerLocation(String oidcIssuerLocation) { Assert.hasText(oidcIssuerLocation, "oidcIssuerLocation cannot be empty"); - Map configuration = JwtDecoderProviderConfigurationUtils.getConfigurationForOidcIssuerLocation(oidcIssuerLocation); + Map configuration = JwtDecoderProviderConfigurationUtils + .getConfigurationForOidcIssuerLocation(oidcIssuerLocation); return withProviderConfiguration(configuration, oidcIssuerLocation); } /** - * Creates a {@link ReactiveJwtDecoder} using the provided - * Issuer by querying - * three different discovery endpoints serially, using the values in the first successful response to - * initialize. If an endpoint returns anything other than a 200 or a 4xx, the method will exit without - * attempting subsequent endpoints. + * Creates a {@link ReactiveJwtDecoder} using the provided Issuer + * by querying three different discovery endpoints serially, using the values in the + * first successful response to initialize. If an endpoint returns anything other than + * a 200 or a 4xx, the method will exit without attempting subsequent endpoints. * - * The three endpoints are computed as follows, given that the {@code issuer} is composed of a {@code host} - * and a {@code path}: + * The three endpoints are computed as follows, given that the {@code issuer} is + * composed of a {@code host} and a {@code path}: * *

          - *
        1. - * {@code host/.well-known/openid-configuration/path}, as defined in - * RFC 8414's Compatibility Notes. - *
        2. - *
        3. - * {@code issuer/.well-known/openid-configuration}, as defined in - * - * OpenID Provider Configuration. - *
        4. - *
        5. - * {@code host/.well-known/oauth-authorization-server/path}, as defined in - * Authorization Server Metadata Request. - *
        6. + *
        7. {@code host/.well-known/openid-configuration/path}, as defined in + * RFC 8414's Compatibility + * Notes.
        8. + *
        9. {@code issuer/.well-known/openid-configuration}, as defined in + * OpenID Provider Configuration.
        10. + *
        11. {@code host/.well-known/oauth-authorization-server/path}, as defined in + * Authorization Server + * Metadata Request.
        12. *
        * * Note that the second endpoint is the equivalent of calling * {@link ReactiveJwtDecoders#fromOidcIssuerLocation(String)} - * - * @param issuer the Issuer - * @return a {@link ReactiveJwtDecoder} that was initialized by one of the described endpoints + * @param issuer the Issuer + * @return a {@link ReactiveJwtDecoder} that was initialized by one of the described + * endpoints */ public static ReactiveJwtDecoder fromIssuerLocation(String issuer) { Assert.hasText(issuer, "issuer cannot be empty"); - Map configuration = JwtDecoderProviderConfigurationUtils.getConfigurationForIssuerLocation(issuer); + Map configuration = JwtDecoderProviderConfigurationUtils + .getConfigurationForIssuerLocation(issuer); return withProviderConfiguration(configuration, issuer); } /** - * Build {@link ReactiveJwtDecoder} from - * OpenID Provider - * Configuration Response and Authorization Server Metadata - * Response. - * + * Build {@link ReactiveJwtDecoder} from OpenID + * Provider Configuration Response and + * Authorization Server + * Metadata Response. * @param configuration the configuration values - * @param issuer the Issuer + * @param issuer the Issuer * @return {@link ReactiveJwtDecoder} */ private static ReactiveJwtDecoder withProviderConfiguration(Map configuration, String issuer) { @@ -107,5 +110,7 @@ public final class ReactiveJwtDecoders { return jwtDecoder; } - private ReactiveJwtDecoders() {} + private ReactiveJwtDecoders() { + } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveRemoteJWKSource.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveRemoteJWKSource.java index 36c4e47703..922a279ee2 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveRemoteJWKSource.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/ReactiveRemoteJWKSource.java @@ -37,6 +37,7 @@ import org.springframework.web.reactive.function.client.WebClient; * @since 5.1 */ class ReactiveRemoteJWKSource implements ReactiveJWKSource { + /** * The cached JWK set. */ @@ -52,8 +53,7 @@ class ReactiveRemoteJWKSource implements ReactiveJWKSource { } public Mono> get(JWKSelector jwkSelector) { - return this.cachedJWKSet.get() - .switchIfEmpty(Mono.defer(() -> getJWKSet())) + return this.cachedJWKSet.get().switchIfEmpty(Mono.defer(() -> getJWKSet())) .flatMap(jwkSet -> get(jwkSelector, jwkSet)) .switchIfEmpty(Mono.defer(() -> getJWKSet().map(jwkSet -> jwkSelector.select(jwkSet)))); } @@ -90,19 +90,12 @@ class ReactiveRemoteJWKSource implements ReactiveJWKSource { /** * Updates the cached JWK set from the configured URL. - * * @return The updated JWK set. - * * @throws RemoteKeySourceException If JWK retrieval failed. */ private Mono getJWKSet() { - return this.webClient.get() - .uri(this.jwkSetURL) - .retrieve() - .bodyToMono(String.class) - .map(this::parse) - .doOnNext(jwkSet -> this.cachedJWKSet.set(Mono.just(jwkSet))) - .cache(); + return this.webClient.get().uri(this.jwkSetURL).retrieve().bodyToMono(String.class).map(this::parse) + .doOnNext(jwkSet -> this.cachedJWKSet.set(Mono.just(jwkSet))).cache(); } private JWKSet parse(String body) { @@ -116,9 +109,7 @@ class ReactiveRemoteJWKSource implements ReactiveJWKSource { /** * Returns the first specified key ID (kid) for a JWK matcher. - * * @param jwkMatcher The JWK matcher. Must not be {@code null}. - * * @return The first key ID, {@code null} if none. */ protected static String getFirstSpecifiedKeyID(final JWKMatcher jwkMatcher) { @@ -129,7 +120,7 @@ class ReactiveRemoteJWKSource implements ReactiveJWKSource { return null; } - for (String id: keyIDs) { + for (String id : keyIDs) { if (id != null) { return id; } @@ -140,4 +131,5 @@ class ReactiveRemoteJWKSource implements ReactiveJWKSource { public void setWebClient(WebClient webClient) { this.webClient = webClient; } + } diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/SingleKeyJWSKeySelector.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/SingleKeyJWSKeySelector.java index 4111a2866e..677e06ed60 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/SingleKeyJWSKeySelector.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/SingleKeyJWSKeySelector.java @@ -34,7 +34,9 @@ import org.springframework.util.Assert; * @since 5.2 */ final class SingleKeyJWSKeySelector implements JWSKeySelector { + private final List keySet; + private final JWSAlgorithm expectedJwsAlgorithm; SingleKeyJWSKeySelector(JWSAlgorithm expectedJwsAlgorithm, Key key) { @@ -51,4 +53,5 @@ final class SingleKeyJWSKeySelector implements JWSKey } return this.keySet; } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jose/TestKeys.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jose/TestKeys.java index 555d92b347..4871860b55 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jose/TestKeys.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jose/TestKeys.java @@ -31,29 +31,29 @@ import javax.crypto.spec.SecretKeySpec; * @since 5.2 */ public class TestKeys { + public static final KeyFactory kf; static { try { kf = KeyFactory.getInstance("RSA"); - } catch (NoSuchAlgorithmException e) { + } + catch (NoSuchAlgorithmException e) { throw new IllegalStateException(e); } } public static final String DEFAULT_ENCODED_SECRET_KEY = "bCzY/M48bbkwBEWjmNSIEPfwApcvXOnkCxORBEbPr+4="; - public static final SecretKey DEFAULT_SECRET_KEY = - new SecretKeySpec(Base64.getDecoder().decode(DEFAULT_ENCODED_SECRET_KEY), "AES"); + public static final SecretKey DEFAULT_SECRET_KEY = new SecretKeySpec( + Base64.getDecoder().decode(DEFAULT_ENCODED_SECRET_KEY), "AES"); - public static final String DEFAULT_RSA_PUBLIC_KEY = - "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3FlqJr5TRskIQIgdE3Dd" + - "7D9lboWdcTUT8a+fJR7MAvQm7XXNoYkm3v7MQL1NYtDvL2l8CAnc0WdSTINU6IRv" + - "c5Kqo2Q4csNX9SHOmEfzoROjQqahEcve1jBXluoCXdYuYpx4/1tfRgG6ii4Uhxh6" + - "iI8qNMJQX+fLfqhbfYfxBQVRPywBkAbIP4x1EAsbC6FSNmkhCxiMNqEgxaIpY8C2" + - "kJdJ/ZIV+WW4noDdzpKqHcwmB8FsrumlVY/DNVvUSDIipiq9PbP4H99TXN1o746o" + - "RaNa07rq1hoCgMSSy+85SagCoxlmyE+D+of9SsMY8Ol9t0rdzpobBuhyJ/o5dfvj" + - "KwIDAQAB"; + public static final String DEFAULT_RSA_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3FlqJr5TRskIQIgdE3Dd" + + "7D9lboWdcTUT8a+fJR7MAvQm7XXNoYkm3v7MQL1NYtDvL2l8CAnc0WdSTINU6IRv" + + "c5Kqo2Q4csNX9SHOmEfzoROjQqahEcve1jBXluoCXdYuYpx4/1tfRgG6ii4Uhxh6" + + "iI8qNMJQX+fLfqhbfYfxBQVRPywBkAbIP4x1EAsbC6FSNmkhCxiMNqEgxaIpY8C2" + + "kJdJ/ZIV+WW4noDdzpKqHcwmB8FsrumlVY/DNVvUSDIipiq9PbP4H99TXN1o746o" + + "RaNa07rq1hoCgMSSy+85SagCoxlmyE+D+of9SsMY8Ol9t0rdzpobBuhyJ/o5dfvj" + "KwIDAQAB"; public static final RSAPublicKey DEFAULT_PUBLIC_KEY = publicKey(); @@ -61,38 +61,37 @@ public class TestKeys { X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.getDecoder().decode(DEFAULT_RSA_PUBLIC_KEY)); try { return (RSAPublicKey) kf.generatePublic(spec); - } catch (InvalidKeySpecException e) { + } + catch (InvalidKeySpecException e) { throw new IllegalArgumentException(e); } } - public static final String DEFAULT_RSA_PRIVATE_KEY = - "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDcWWomvlNGyQhA" + - "iB0TcN3sP2VuhZ1xNRPxr58lHswC9Cbtdc2hiSbe/sxAvU1i0O8vaXwICdzRZ1JM" + - "g1TohG9zkqqjZDhyw1f1Ic6YR/OhE6NCpqERy97WMFeW6gJd1i5inHj/W19GAbqK" + - "LhSHGHqIjyo0wlBf58t+qFt9h/EFBVE/LAGQBsg/jHUQCxsLoVI2aSELGIw2oSDF" + - "oiljwLaQl0n9khX5ZbiegN3OkqodzCYHwWyu6aVVj8M1W9RIMiKmKr09s/gf31Nc" + - "3WjvjqhFo1rTuurWGgKAxJLL7zlJqAKjGWbIT4P6h/1Kwxjw6X23St3OmhsG6HIn" + - "+jl1++MrAgMBAAECggEBAMf820wop3pyUOwI3aLcaH7YFx5VZMzvqJdNlvpg1jbE" + - "E2Sn66b1zPLNfOIxLcBG8x8r9Ody1Bi2Vsqc0/5o3KKfdgHvnxAB3Z3dPh2WCDek" + - "lCOVClEVoLzziTuuTdGO5/CWJXdWHcVzIjPxmK34eJXioiLaTYqN3XKqKMdpD0ZG" + - "mtNTGvGf+9fQ4i94t0WqIxpMpGt7NM4RHy3+Onggev0zLiDANC23mWrTsUgect/7" + - "62TYg8g1bKwLAb9wCBT+BiOuCc2wrArRLOJgUkj/F4/gtrR9ima34SvWUyoUaKA0" + - "bi4YBX9l8oJwFGHbU9uFGEMnH0T/V0KtIB7qetReywkCgYEA9cFyfBIQrYISV/OA" + - "+Z0bo3vh2aL0QgKrSXZ924cLt7itQAHNZ2ya+e3JRlTczi5mnWfjPWZ6eJB/8MlH" + - "Gpn12o/POEkU+XjZZSPe1RWGt5g0S3lWqyx9toCS9ACXcN9tGbaqcFSVI73zVTRA" + - "8J9grR0fbGn7jaTlTX2tnlOTQ60CgYEA5YjYpEq4L8UUMFkuj+BsS3u0oEBnzuHd" + - "I9LEHmN+CMPosvabQu5wkJXLuqo2TxRnAznsA8R3pCLkdPGoWMCiWRAsCn979TdY" + - "QbqO2qvBAD2Q19GtY7lIu6C35/enQWzJUMQE3WW0OvjLzZ0l/9mA2FBRR+3F9A1d" + - "rBdnmv0c3TcCgYEAi2i+ggVZcqPbtgrLOk5WVGo9F1GqUBvlgNn30WWNTx4zIaEk" + - "HSxtyaOLTxtq2odV7Kr3LGiKxwPpn/T+Ief+oIp92YcTn+VfJVGw4Z3BezqbR8lA" + - "Uf/+HF5ZfpMrVXtZD4Igs3I33Duv4sCuqhEvLWTc44pHifVloozNxYfRfU0CgYBN" + - "HXa7a6cJ1Yp829l62QlJKtx6Ymj95oAnQu5Ez2ROiZMqXRO4nucOjGUP55Orac1a" + - "FiGm+mC/skFS0MWgW8evaHGDbWU180wheQ35hW6oKAb7myRHtr4q20ouEtQMdQIF" + - "snV39G1iyqeeAsf7dxWElydXpRi2b68i3BIgzhzebQKBgQCdUQuTsqV9y/JFpu6H" + - "c5TVvhG/ubfBspI5DhQqIGijnVBzFT//UfIYMSKJo75qqBEyP2EJSmCsunWsAFsM" + - "TszuiGTkrKcZy9G0wJqPztZZl2F2+bJgnA6nBEV7g5PA4Af+QSmaIhRwqGDAuROR" + - "47jndeyIaMTNETEmOnms+as17g=="; + public static final String DEFAULT_RSA_PRIVATE_KEY = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDcWWomvlNGyQhA" + + "iB0TcN3sP2VuhZ1xNRPxr58lHswC9Cbtdc2hiSbe/sxAvU1i0O8vaXwICdzRZ1JM" + + "g1TohG9zkqqjZDhyw1f1Ic6YR/OhE6NCpqERy97WMFeW6gJd1i5inHj/W19GAbqK" + + "LhSHGHqIjyo0wlBf58t+qFt9h/EFBVE/LAGQBsg/jHUQCxsLoVI2aSELGIw2oSDF" + + "oiljwLaQl0n9khX5ZbiegN3OkqodzCYHwWyu6aVVj8M1W9RIMiKmKr09s/gf31Nc" + + "3WjvjqhFo1rTuurWGgKAxJLL7zlJqAKjGWbIT4P6h/1Kwxjw6X23St3OmhsG6HIn" + + "+jl1++MrAgMBAAECggEBAMf820wop3pyUOwI3aLcaH7YFx5VZMzvqJdNlvpg1jbE" + + "E2Sn66b1zPLNfOIxLcBG8x8r9Ody1Bi2Vsqc0/5o3KKfdgHvnxAB3Z3dPh2WCDek" + + "lCOVClEVoLzziTuuTdGO5/CWJXdWHcVzIjPxmK34eJXioiLaTYqN3XKqKMdpD0ZG" + + "mtNTGvGf+9fQ4i94t0WqIxpMpGt7NM4RHy3+Onggev0zLiDANC23mWrTsUgect/7" + + "62TYg8g1bKwLAb9wCBT+BiOuCc2wrArRLOJgUkj/F4/gtrR9ima34SvWUyoUaKA0" + + "bi4YBX9l8oJwFGHbU9uFGEMnH0T/V0KtIB7qetReywkCgYEA9cFyfBIQrYISV/OA" + + "+Z0bo3vh2aL0QgKrSXZ924cLt7itQAHNZ2ya+e3JRlTczi5mnWfjPWZ6eJB/8MlH" + + "Gpn12o/POEkU+XjZZSPe1RWGt5g0S3lWqyx9toCS9ACXcN9tGbaqcFSVI73zVTRA" + + "8J9grR0fbGn7jaTlTX2tnlOTQ60CgYEA5YjYpEq4L8UUMFkuj+BsS3u0oEBnzuHd" + + "I9LEHmN+CMPosvabQu5wkJXLuqo2TxRnAznsA8R3pCLkdPGoWMCiWRAsCn979TdY" + + "QbqO2qvBAD2Q19GtY7lIu6C35/enQWzJUMQE3WW0OvjLzZ0l/9mA2FBRR+3F9A1d" + + "rBdnmv0c3TcCgYEAi2i+ggVZcqPbtgrLOk5WVGo9F1GqUBvlgNn30WWNTx4zIaEk" + + "HSxtyaOLTxtq2odV7Kr3LGiKxwPpn/T+Ief+oIp92YcTn+VfJVGw4Z3BezqbR8lA" + + "Uf/+HF5ZfpMrVXtZD4Igs3I33Duv4sCuqhEvLWTc44pHifVloozNxYfRfU0CgYBN" + + "HXa7a6cJ1Yp829l62QlJKtx6Ymj95oAnQu5Ez2ROiZMqXRO4nucOjGUP55Orac1a" + + "FiGm+mC/skFS0MWgW8evaHGDbWU180wheQ35hW6oKAb7myRHtr4q20ouEtQMdQIF" + + "snV39G1iyqeeAsf7dxWElydXpRi2b68i3BIgzhzebQKBgQCdUQuTsqV9y/JFpu6H" + + "c5TVvhG/ubfBspI5DhQqIGijnVBzFT//UfIYMSKJo75qqBEyP2EJSmCsunWsAFsM" + + "TszuiGTkrKcZy9G0wJqPztZZl2F2+bJgnA6nBEV7g5PA4Af+QSmaIhRwqGDAuROR" + "47jndeyIaMTNETEmOnms+as17g=="; public static final RSAPrivateKey DEFAULT_PRIVATE_KEY = privateKey(); @@ -100,8 +99,10 @@ public class TestKeys { PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(DEFAULT_RSA_PRIVATE_KEY)); try { return (RSAPrivateKey) kf.generatePrivate(spec); - } catch (InvalidKeySpecException e) { + } + catch (InvalidKeySpecException e) { throw new IllegalArgumentException(e); } } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jose/jws/MacAlgorithmTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jose/jws/MacAlgorithmTests.java index cea7ef5054..085b53d0fb 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jose/jws/MacAlgorithmTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jose/jws/MacAlgorithmTests.java @@ -38,4 +38,5 @@ public class MacAlgorithmTests { public void fromWhenAlgorithmInvalidThenDoesNotResolve() { assertThat(MacAlgorithm.from("invalid")).isNull(); } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jose/jws/SignatureAlgorithmTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jose/jws/SignatureAlgorithmTests.java index 4b2c19f018..5942491975 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jose/jws/SignatureAlgorithmTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jose/jws/SignatureAlgorithmTests.java @@ -44,4 +44,5 @@ public class SignatureAlgorithmTests { public void fromWhenAlgorithmInvalidThenDoesNotResolve() { assertThat(SignatureAlgorithm.from("invalid")).isNull(); } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtBuilderTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtBuilderTests.java index 4004ef9400..c0941bb83e 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtBuilderTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtBuilderTests.java @@ -37,19 +37,10 @@ public class JwtBuilderTests { public void buildWhenCalledTwiceThenGeneratesTwoJwts() { Jwt.Builder jwtBuilder = Jwt.withTokenValue("token"); - Jwt first = jwtBuilder - .tokenValue("V1") - .header("TEST_HEADER_1", "H1") - .claim("TEST_CLAIM_1", "C1") - .build(); + Jwt first = jwtBuilder.tokenValue("V1").header("TEST_HEADER_1", "H1").claim("TEST_CLAIM_1", "C1").build(); - Jwt second = jwtBuilder - .tokenValue("V2") - .header("TEST_HEADER_1", "H2") - .header("TEST_HEADER_2", "H3") - .claim("TEST_CLAIM_1", "C2") - .claim("TEST_CLAIM_2", "C3") - .build(); + Jwt second = jwtBuilder.tokenValue("V2").header("TEST_HEADER_1", "H2").header("TEST_HEADER_2", "H3") + .claim("TEST_CLAIM_1", "C2").claim("TEST_CLAIM_2", "C3").build(); assertThat(first.getHeaders()).hasSize(1); assertThat(first.getHeaders().get("TEST_HEADER_1")).isEqualTo("H1"); @@ -68,86 +59,65 @@ public class JwtBuilderTests { @Test public void expiresAtWhenUsingGenericOrNamedClaimMethodRequiresInstant() { - Jwt.Builder jwtBuilder = Jwt.withTokenValue("token") - .header("needs", "a header"); + Jwt.Builder jwtBuilder = Jwt.withTokenValue("token").header("needs", "a header"); Instant now = Instant.now(); - Jwt jwt = jwtBuilder - .expiresAt(now).build(); + Jwt jwt = jwtBuilder.expiresAt(now).build(); assertThat(jwt.getExpiresAt()).isSameAs(now); - jwt = jwtBuilder - .expiresAt(now).build(); + jwt = jwtBuilder.expiresAt(now).build(); assertThat(jwt.getExpiresAt()).isSameAs(now); - assertThatCode(() -> jwtBuilder - .claim(EXP, "not an instant").build()) + assertThatCode(() -> jwtBuilder.claim(EXP, "not an instant").build()) .isInstanceOf(IllegalArgumentException.class); } @Test public void issuedAtWhenUsingGenericOrNamedClaimMethodRequiresInstant() { - Jwt.Builder jwtBuilder = Jwt.withTokenValue("token") - .header("needs", "a header"); + Jwt.Builder jwtBuilder = Jwt.withTokenValue("token").header("needs", "a header"); Instant now = Instant.now(); - Jwt jwt = jwtBuilder - .issuedAt(now).build(); + Jwt jwt = jwtBuilder.issuedAt(now).build(); assertThat(jwt.getIssuedAt()).isSameAs(now); - jwt = jwtBuilder - .issuedAt(now).build(); + jwt = jwtBuilder.issuedAt(now).build(); assertThat(jwt.getIssuedAt()).isSameAs(now); - assertThatCode(() -> jwtBuilder - .claim(IAT, "not an instant").build()) + assertThatCode(() -> jwtBuilder.claim(IAT, "not an instant").build()) .isInstanceOf(IllegalArgumentException.class); } @Test public void subjectWhenUsingGenericOrNamedClaimMethodThenLastOneWins() { - Jwt.Builder jwtBuilder = Jwt.withTokenValue("token") - .header("needs", "a header"); + Jwt.Builder jwtBuilder = Jwt.withTokenValue("token").header("needs", "a header"); String generic = new String("sub"); String named = new String("sub"); - Jwt jwt = jwtBuilder - .subject(named) - .claim(SUB, generic).build(); + Jwt jwt = jwtBuilder.subject(named).claim(SUB, generic).build(); assertThat(jwt.getSubject()).isSameAs(generic); - jwt = jwtBuilder - .claim(SUB, generic) - .subject(named).build(); + jwt = jwtBuilder.claim(SUB, generic).subject(named).build(); assertThat(jwt.getSubject()).isSameAs(named); } @Test public void claimsWhenRemovingAClaimThenIsNotPresent() { - Jwt.Builder jwtBuilder = Jwt.withTokenValue("token") - .claim("needs", "a claim") - .header("needs", "a header"); + Jwt.Builder jwtBuilder = Jwt.withTokenValue("token").claim("needs", "a claim").header("needs", "a header"); - Jwt jwt = jwtBuilder - .subject("sub") - .claims(claims -> claims.remove(SUB)) - .build(); + Jwt jwt = jwtBuilder.subject("sub").claims(claims -> claims.remove(SUB)).build(); assertThat(jwt.getSubject()).isNull(); } @Test public void claimsWhenAddingAClaimThenIsPresent() { - Jwt.Builder jwtBuilder = Jwt.withTokenValue("token") - .header("needs", "a header"); + Jwt.Builder jwtBuilder = Jwt.withTokenValue("token").header("needs", "a header"); String name = new String("name"); String value = new String("value"); - Jwt jwt = jwtBuilder - .claims(claims -> claims.put(name, value)) - .build(); + Jwt jwt = jwtBuilder.claims(claims -> claims.put(name, value)).build(); assertThat(jwt.getClaims()).hasSize(1); assertThat(jwt.getClaims().get(name)).isSameAs(value); @@ -155,27 +125,19 @@ public class JwtBuilderTests { @Test public void headersWhenRemovingAClaimThenIsNotPresent() { - Jwt.Builder jwtBuilder = Jwt.withTokenValue("token") - .claim("needs", "a claim") - .header("needs", "a header"); + Jwt.Builder jwtBuilder = Jwt.withTokenValue("token").claim("needs", "a claim").header("needs", "a header"); - Jwt jwt = jwtBuilder - .header("alg", "none") - .headers(headers -> headers.remove("alg")) - .build(); + Jwt jwt = jwtBuilder.header("alg", "none").headers(headers -> headers.remove("alg")).build(); assertThat(jwt.getHeaders().get("alg")).isNull(); } @Test public void headersWhenAddingAClaimThenIsPresent() { - Jwt.Builder jwtBuilder = Jwt.withTokenValue("token") - .claim("needs", "a claim"); + Jwt.Builder jwtBuilder = Jwt.withTokenValue("token").claim("needs", "a claim"); String name = new String("name"); String value = new String("value"); - Jwt jwt = jwtBuilder - .headers(headers -> headers.put(name, value)) - .build(); + Jwt jwt = jwtBuilder.headers(headers -> headers.put(name, value)).build(); assertThat(jwt.getHeaders()).hasSize(1); assertThat(jwt.getHeaders().get(name)).isSameAs(value); diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtClaimValidatorTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtClaimValidatorTests.java index 968af2a8ab..de223c8d76 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtClaimValidatorTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtClaimValidatorTests.java @@ -33,20 +33,19 @@ import static org.springframework.security.oauth2.jwt.TestJwts.jwt; public class JwtClaimValidatorTests { private static final Predicate test = claim -> claim.equals("http://test"); + private final JwtClaimValidator validator = new JwtClaimValidator<>(ISS, test); @Test public void validateWhenClaimPassesTheTestThenReturnsSuccess() { Jwt jwt = jwt().claim(ISS, "http://test").build(); - assertThat(validator.validate(jwt)) - .isEqualTo(OAuth2TokenValidatorResult.success()); + assertThat(validator.validate(jwt)).isEqualTo(OAuth2TokenValidatorResult.success()); } @Test public void validateWhenClaimFailsTheTestThenReturnsFailure() { Jwt jwt = jwt().claim(ISS, "http://abc").build(); - assertThat(validator.validate(jwt).getErrors().isEmpty()) - .isFalse(); + assertThat(validator.validate(jwt).getErrors().isEmpty()).isFalse(); } @Test @@ -56,14 +55,13 @@ public class JwtClaimValidatorTests { } @Test - public void validateWhenTestIsNullThenThrowsIllegalArgumentException(){ - assertThatThrownBy(() -> new JwtClaimValidator<>(ISS, null)) - .isInstanceOf(IllegalArgumentException.class); + public void validateWhenTestIsNullThenThrowsIllegalArgumentException() { + assertThatThrownBy(() -> new JwtClaimValidator<>(ISS, null)).isInstanceOf(IllegalArgumentException.class); } @Test public void validateWhenJwtIsNullThenThrowsIllegalArgumentException() { - assertThatThrownBy(() -> validator.validate(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> validator.validate(null)).isInstanceOf(IllegalArgumentException.class); } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtDecodersTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtDecodersTests.java index 8fa7ee5869..618e9f081e 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtDecodersTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtDecodersTests.java @@ -47,40 +47,31 @@ import static org.assertj.core.api.Assertions.assertThatCode; * @author Rafiullah Hamedy */ public class JwtDecodersTests { + /** - * Contains those parameters required to construct a JwtDecoder as well as any required parameters + * Contains those parameters required to construct a JwtDecoder as well as any + * required parameters */ - private static final String DEFAULT_RESPONSE_TEMPLATE = - "{\n" - + " \"authorization_endpoint\": \"https://example.com/o/oauth2/v2/auth\", \n" - + " \"id_token_signing_alg_values_supported\": [\n" - + " \"RS256\"\n" - + " ], \n" - + " \"issuer\": \"%s\", \n" - + " \"jwks_uri\": \"%s/.well-known/jwks.json\", \n" - + " \"response_types_supported\": [\n" - + " \"code\", \n" - + " \"token\", \n" - + " \"id_token\", \n" - + " \"code token\", \n" - + " \"code id_token\", \n" - + " \"token id_token\", \n" - + " \"code token id_token\", \n" - + " \"none\"\n" - + " ], \n" - + " \"subject_types_supported\": [\n" - + " \"public\"\n" - + " ], \n" - + " \"token_endpoint\": \"https://example.com/oauth2/v4/token\"\n" - + "}"; + private static final String DEFAULT_RESPONSE_TEMPLATE = "{\n" + + " \"authorization_endpoint\": \"https://example.com/o/oauth2/v2/auth\", \n" + + " \"id_token_signing_alg_values_supported\": [\n" + " \"RS256\"\n" + " ], \n" + + " \"issuer\": \"%s\", \n" + " \"jwks_uri\": \"%s/.well-known/jwks.json\", \n" + + " \"response_types_supported\": [\n" + " \"code\", \n" + " \"token\", \n" + + " \"id_token\", \n" + " \"code token\", \n" + " \"code id_token\", \n" + + " \"token id_token\", \n" + " \"code token id_token\", \n" + " \"none\"\n" + + " ], \n" + " \"subject_types_supported\": [\n" + " \"public\"\n" + " ], \n" + + " \"token_endpoint\": \"https://example.com/oauth2/v4/token\"\n" + "}"; private static final String JWK_SET = "{\"keys\":[{\"p\":\"49neceJFs8R6n7WamRGy45F5Tv0YM-R2ODK3eSBUSLOSH2tAqjEVKOkLE5fiNA3ygqq15NcKRadB2pTVf-Yb5ZIBuKzko8bzYIkIqYhSh_FAdEEr0vHF5fq_yWSvc6swsOJGqvBEtuqtJY027u-G2gAQasCQdhyejer68zsTn8M\",\"kty\":\"RSA\",\"q\":\"tWR-ysspjZ73B6p2vVRVyHwP3KQWL5KEQcdgcmMOE_P_cPs98vZJfLhxobXVmvzuEWBpRSiqiuyKlQnpstKt94Cy77iO8m8ISfF3C9VyLWXi9HUGAJb99irWABFl3sNDff5K2ODQ8CmuXLYM25OwN3ikbrhEJozlXg_NJFSGD4E\",\"d\":\"FkZHYZlw5KSoqQ1i2RA2kCUygSUOf1OqMt3uomtXuUmqKBm_bY7PCOhmwbvbn4xZYEeHuTR8Xix-0KpHe3NKyWrtRjkq1T_un49_1LLVUhJ0dL-9_x0xRquVjhl_XrsRXaGMEHs8G9pLTvXQ1uST585gxIfmCe0sxPZLvwoic-bXf64UZ9BGRV3lFexWJQqCZp2S21HfoU7wiz6kfLRNi-K4xiVNB1gswm_8o5lRuY7zB9bRARQ3TS2G4eW7p5sxT3CgsGiQD3_wPugU8iDplqAjgJ5ofNJXZezoj0t6JMB_qOpbrmAM1EnomIPebSLW7Ky9SugEd6KMdL5lW6AuAQ\",\"e\":\"AQAB\",\"use\":\"sig\",\"kid\":\"one\",\"qi\":\"wdkFu_tV2V1l_PWUUimG516Zvhqk2SWDw1F7uNDD-Lvrv_WNRIJVzuffZ8WYiPy8VvYQPJUrT2EXL8P0ocqwlaSTuXctrORcbjwgxDQDLsiZE0C23HYzgi0cofbScsJdhcBg7d07LAf7cdJWG0YVl1FkMCsxUlZ2wTwHfKWf-v4\",\"dp\":\"uwnPxqC-IxG4r33-SIT02kZC1IqC4aY7PWq0nePiDEQMQWpjjNH50rlq9EyLzbtdRdIouo-jyQXB01K15-XXJJ60dwrGLYNVqfsTd0eGqD1scYJGHUWG9IDgCsxyEnuG3s0AwbW2UolWVSsU2xMZGb9PurIUZECeD1XDZwMp2s0\",\"dq\":\"hra786AunB8TF35h8PpROzPoE9VJJMuLrc6Esm8eZXMwopf0yhxfN2FEAvUoTpLJu93-UH6DKenCgi16gnQ0_zt1qNNIVoRfg4rw_rjmsxCYHTVL3-RDeC8X_7TsEySxW0EgFTHh-nr6I6CQrAJjPM88T35KHtdFATZ7BCBB8AE\",\"n\":\"oXJ8OyOv_eRnce4akdanR4KYRfnC2zLV4uYNQpcFn6oHL0dj7D6kxQmsXoYgJV8ZVDn71KGmuLvolxsDncc2UrhyMBY6DVQVgMSVYaPCTgW76iYEKGgzTEw5IBRQL9w3SRJWd3VJTZZQjkXef48Ocz06PGF3lhbz4t5UEZtdF4rIe7u-977QwHuh7yRPBQ3sII-cVoOUMgaXB9SHcGF2iZCtPzL_IffDUcfhLQteGebhW8A6eUHgpD5A1PQ-JCw_G7UOzZAjjDjtNM2eqm8j-Ms_gqnm4MiCZ4E-9pDN77CAAPVN7kuX6ejs9KBXpk01z48i9fORYk9u7rAkh1HuQw\"}]}"; + private static final String ISSUER_MISMATCH = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczpcL1wvd3Jvbmdpc3N1ZXIiLCJleHAiOjQ2ODcyNTYwNDl9.Ax8LMI6rhB9Pv_CE3kFi1JPuLj9gZycifWrLeDpkObWEEVAsIls9zAhNFyJlG-Oo7up6_mDhZgeRfyKnpSF5GhKJtXJDCzwg0ZDVUE6rS0QadSxsMMGbl7c4y0lG_7TfLX2iWeNJukJj_oSW9KzW4FsBp1BoocWjrreesqQU3fZHbikH-c_Fs2TsAIpHnxflyEzfOFWpJ8D4DtzHXqfvieMwpy42xsPZK3LR84zlasf0Ne1tC_hLHvyHRdAXwn0CMoKxc7-8j0r9Mq8kAzUsPn9If7bMLqGkxUcTPdk5x7opAUajDZx95SXHLmtztNtBa2S6EfPJXuPKG6tM5Wq5Ug"; private static final String OIDC_METADATA_PATH = "/.well-known/openid-configuration"; + private static final String OAUTH_METADATA_PATH = "/.well-known/oauth-authorization-server"; private MockWebServer server; + private String issuer; @Before @@ -99,8 +90,7 @@ public class JwtDecodersTests { public void issuerWhenResponseIsTypicalThenReturnedDecoderValidatesIssuer() { prepareConfigurationResponse(); JwtDecoder decoder = JwtDecoders.fromOidcIssuerLocation(this.issuer); - assertThatCode(() -> decoder.decode(ISSUER_MISMATCH)) - .isInstanceOf(JwtValidationException.class) + assertThatCode(() -> decoder.decode(ISSUER_MISMATCH)).isInstanceOf(JwtValidationException.class) .hasMessageContaining("The iss claim is not valid"); } @@ -108,8 +98,7 @@ public class JwtDecodersTests { public void issuerWhenOidcFallbackResponseIsTypicalThenReturnedDecoderValidatesIssuer() { prepareConfigurationResponseOidc(); JwtDecoder decoder = JwtDecoders.fromIssuerLocation(this.issuer); - assertThatCode(() -> decoder.decode(ISSUER_MISMATCH)) - .isInstanceOf(JwtValidationException.class) + assertThatCode(() -> decoder.decode(ISSUER_MISMATCH)).isInstanceOf(JwtValidationException.class) .hasMessageContaining("The iss claim is not valid"); } @@ -117,8 +106,7 @@ public class JwtDecodersTests { public void issuerWhenOAuth2ResponseIsTypicalThenReturnedDecoderValidatesIssuer() { prepareConfigurationResponseOAuth2(); JwtDecoder decoder = JwtDecoders.fromIssuerLocation(this.issuer); - assertThatCode(() -> decoder.decode(ISSUER_MISMATCH)) - .isInstanceOf(JwtValidationException.class) + assertThatCode(() -> decoder.decode(ISSUER_MISMATCH)).isInstanceOf(JwtValidationException.class) .hasMessageContaining("The iss claim is not valid"); } @@ -149,22 +137,19 @@ public class JwtDecodersTests { @Test public void issuerWhenResponseIsNonCompliantThenThrowsRuntimeException() { prepareConfigurationResponse("{ \"missing_required_keys\" : \"and_values\" }"); - assertThatCode(() -> JwtDecoders.fromOidcIssuerLocation(this.issuer)) - .isInstanceOf(RuntimeException.class); + assertThatCode(() -> JwtDecoders.fromOidcIssuerLocation(this.issuer)).isInstanceOf(RuntimeException.class); } @Test public void issuerWhenOidcFallbackResponseIsNonCompliantThenThrowsRuntimeException() { prepareConfigurationResponseOidc("{ \"missing_required_keys\" : \"and_values\" }"); - assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)) - .isInstanceOf(RuntimeException.class); + assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)).isInstanceOf(RuntimeException.class); } @Test public void issuerWhenOAuth2ResponseIsNonCompliantThenThrowsRuntimeException() { prepareConfigurationResponseOAuth2("{ \"missing_required_keys\" : \"and_values\" }"); - assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)) - .isInstanceOf(RuntimeException.class); + assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)).isInstanceOf(RuntimeException.class); } // gh-7512 @@ -173,8 +158,7 @@ public class JwtDecodersTests { throws JsonMappingException, JsonProcessingException { prepareConfigurationResponse(this.buildResponseWithMissingJwksUri()); assertThatCode(() -> JwtDecoders.fromOidcIssuerLocation(this.issuer)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("The public JWK set URI must not be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("The public JWK set URI must not be null"); } // gh-7512 @@ -182,8 +166,7 @@ public class JwtDecodersTests { public void issuerWhenOidcFallbackResponseDoesNotContainJwksUriThenThrowsIllegalArgumentException() throws JsonMappingException, JsonProcessingException { prepareConfigurationResponseOidc(this.buildResponseWithMissingJwksUri()); - assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)) - .isInstanceOf(IllegalArgumentException.class) + assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)).isInstanceOf(IllegalArgumentException.class) .hasMessage("The public JWK set URI must not be null"); } @@ -192,56 +175,49 @@ public class JwtDecodersTests { public void issuerWhenOAuth2ResponseDoesNotContainJwksUriThenThrowsIllegalArgumentException() throws JsonMappingException, JsonProcessingException { prepareConfigurationResponseOAuth2(this.buildResponseWithMissingJwksUri()); - assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)) - .isInstanceOf(IllegalArgumentException.class) + assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)).isInstanceOf(IllegalArgumentException.class) .hasMessage("The public JWK set URI must not be null"); } @Test public void issuerWhenResponseIsMalformedThenThrowsRuntimeException() { prepareConfigurationResponse("malformed"); - assertThatCode(() -> JwtDecoders.fromOidcIssuerLocation(this.issuer)) - .isInstanceOf(RuntimeException.class); + assertThatCode(() -> JwtDecoders.fromOidcIssuerLocation(this.issuer)).isInstanceOf(RuntimeException.class); } @Test public void issuerWhenOidcFallbackResponseIsMalformedThenThrowsRuntimeException() { prepareConfigurationResponseOidc("malformed"); - assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)) - .isInstanceOf(RuntimeException.class); + assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)).isInstanceOf(RuntimeException.class); } @Test public void issuerWhenOAuth2ResponseIsMalformedThenThrowsRuntimeException() { prepareConfigurationResponseOAuth2("malformed"); - assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)) - .isInstanceOf(RuntimeException.class); + assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)).isInstanceOf(RuntimeException.class); } @Test public void issuerWhenRespondingIssuerMismatchesRequestedIssuerThenThrowsIllegalStateException() { prepareConfigurationResponse(String.format(DEFAULT_RESPONSE_TEMPLATE, this.issuer + "/wrong", this.issuer)); - assertThatCode(() -> JwtDecoders.fromOidcIssuerLocation(this.issuer)) - .isInstanceOf(IllegalStateException.class); + assertThatCode(() -> JwtDecoders.fromOidcIssuerLocation(this.issuer)).isInstanceOf(IllegalStateException.class); } @Test public void issuerWhenOidcFallbackRespondingIssuerMismatchesRequestedIssuerThenThrowsIllegalStateException() { prepareConfigurationResponseOidc(String.format(DEFAULT_RESPONSE_TEMPLATE, this.issuer + "/wrong", this.issuer)); - assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)) - .isInstanceOf(IllegalStateException.class); + assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)).isInstanceOf(IllegalStateException.class); } @Test public void issuerWhenOAuth2RespondingIssuerMismatchesRequestedIssuerThenThrowsIllegalStateException() { - prepareConfigurationResponseOAuth2(String.format(DEFAULT_RESPONSE_TEMPLATE, this.issuer + "/wrong", this.issuer)); - assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)) - .isInstanceOf(IllegalStateException.class); + prepareConfigurationResponseOAuth2( + String.format(DEFAULT_RESPONSE_TEMPLATE, this.issuer + "/wrong", this.issuer)); + assertThatCode(() -> JwtDecoders.fromIssuerLocation(this.issuer)).isInstanceOf(IllegalStateException.class); } @Test - public void issuerWhenRequestedIssuerIsUnresponsiveThenThrowsIllegalArgumentException() - throws Exception { + public void issuerWhenRequestedIssuerIsUnresponsiveThenThrowsIllegalArgumentException() throws Exception { this.server.shutdown(); assertThatCode(() -> JwtDecoders.fromOidcIssuerLocation("https://issuer")) @@ -296,8 +272,7 @@ public class JwtDecodersTests { @Override public MockResponse dispatch(RecordedRequest request) { return Optional.of(request).map(RecordedRequest::getRequestUrl).map(HttpUrl::toString) - .map(responses::get) - .orElse(new MockResponse().setResponseCode(404)); + .map(responses::get).orElse(new MockResponse().setResponseCode(404)); } }; this.server.setDispatcher(dispatcher); @@ -309,14 +284,12 @@ public class JwtDecodersTests { private String oidc() { URI uri = URI.create(this.issuer); - return UriComponentsBuilder.fromUri(uri) - .replacePath(uri.getPath() + OIDC_METADATA_PATH).toUriString(); + return UriComponentsBuilder.fromUri(uri).replacePath(uri.getPath() + OIDC_METADATA_PATH).toUriString(); } private String oauth() { URI uri = URI.create(this.issuer); - return UriComponentsBuilder.fromUri(uri) - .replacePath(OAUTH_METADATA_PATH + uri.getPath()).toUriString(); + return UriComponentsBuilder.fromUri(uri).replacePath(OAUTH_METADATA_PATH + uri.getPath()).toUriString(); } private String jwks() { @@ -324,16 +297,16 @@ public class JwtDecodersTests { } private MockResponse response(String body) { - return new MockResponse() - .setBody(body) - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + return new MockResponse().setBody(body).setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); } public String buildResponseWithMissingJwksUri() throws JsonMappingException, JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); Map response = mapper.readValue(DEFAULT_RESPONSE_TEMPLATE, - new TypeReference>(){}); + new TypeReference>() { + }); response.remove("jwks_uri"); return mapper.writeValueAsString(response); } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtIssuerValidatorTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtIssuerValidatorTests.java index ba0a42c0ca..688ef5ef65 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtIssuerValidatorTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtIssuerValidatorTests.java @@ -28,6 +28,7 @@ import static org.springframework.security.oauth2.jwt.TestJwts.jwt; * @since 5.1 */ public class JwtIssuerValidatorTests { + private static final String ISSUER = "https://issuer"; private final JwtIssuerValidator validator = new JwtIssuerValidator(ISSUER); @@ -36,8 +37,7 @@ public class JwtIssuerValidatorTests { public void validateWhenIssuerMatchesThenReturnsSuccess() { Jwt jwt = jwt().claim("iss", ISSUER).build(); - assertThat(this.validator.validate(jwt)) - .isEqualTo(OAuth2TokenValidatorResult.success()); + assertThat(this.validator.validate(jwt)).isEqualTo(OAuth2TokenValidatorResult.success()); } @Test @@ -63,19 +63,17 @@ public class JwtIssuerValidatorTests { Jwt jwt = jwt().claim(JwtClaimNames.ISS, "issuer").build(); JwtIssuerValidator validator = new JwtIssuerValidator("issuer"); - assertThat(validator.validate(jwt)) - .isEqualTo(OAuth2TokenValidatorResult.success()); + assertThat(validator.validate(jwt)).isEqualTo(OAuth2TokenValidatorResult.success()); } @Test public void validateWhenJwtIsNullThenThrowsIllegalArgumentException() { - assertThatCode(() -> this.validator.validate(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> this.validator.validate(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void constructorWhenNullIssuerIsGivenThenThrowsIllegalArgumentException() { - assertThatCode(() -> new JwtIssuerValidator(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> new JwtIssuerValidator(null)).isInstanceOf(IllegalArgumentException.class); } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtTests.java index e59716da74..ba686bf90e 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtTests.java @@ -33,24 +33,39 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Joe Grandja */ public class JwtTests { + private static final String ISS_CLAIM = "iss"; + private static final String SUB_CLAIM = "sub"; + private static final String AUD_CLAIM = "aud"; + private static final String EXP_CLAIM = "exp"; + private static final String NBF_CLAIM = "nbf"; + private static final String IAT_CLAIM = "iat"; + private static final String JTI_CLAIM = "jti"; private static final String ISS_VALUE = "https://provider.com"; + private static final String SUB_VALUE = "subject1"; + private static final List AUD_VALUE = Arrays.asList("aud1", "aud2"); + private static final long EXP_VALUE = Instant.now().plusSeconds(60).toEpochMilli(); + private static final long NBF_VALUE = Instant.now().plusSeconds(5).toEpochMilli(); + private static final long IAT_VALUE = Instant.now().toEpochMilli(); + private static final String JTI_VALUE = "jwt-id-1"; private static final Map HEADERS; + private static final Map CLAIMS; + private static final String JWT_TOKEN_VALUE = "jwt-token-value"; static { @@ -74,20 +89,20 @@ public class JwtTests { @Test(expected = IllegalArgumentException.class) public void constructorWhenHeadersIsEmptyThenThrowIllegalArgumentException() { - new Jwt(JWT_TOKEN_VALUE, Instant.ofEpochMilli(IAT_VALUE), - Instant.ofEpochMilli(EXP_VALUE), Collections.emptyMap(), CLAIMS); + new Jwt(JWT_TOKEN_VALUE, Instant.ofEpochMilli(IAT_VALUE), Instant.ofEpochMilli(EXP_VALUE), + Collections.emptyMap(), CLAIMS); } @Test(expected = IllegalArgumentException.class) public void constructorWhenClaimsIsEmptyThenThrowIllegalArgumentException() { - new Jwt(JWT_TOKEN_VALUE, Instant.ofEpochMilli(IAT_VALUE), - Instant.ofEpochMilli(EXP_VALUE), HEADERS, Collections.emptyMap()); + new Jwt(JWT_TOKEN_VALUE, Instant.ofEpochMilli(IAT_VALUE), Instant.ofEpochMilli(EXP_VALUE), HEADERS, + Collections.emptyMap()); } @Test public void constructorWhenParametersProvidedAndValidThenCreated() { - Jwt jwt = new Jwt(JWT_TOKEN_VALUE, Instant.ofEpochMilli(IAT_VALUE), - Instant.ofEpochMilli(EXP_VALUE), HEADERS, CLAIMS); + Jwt jwt = new Jwt(JWT_TOKEN_VALUE, Instant.ofEpochMilli(IAT_VALUE), Instant.ofEpochMilli(EXP_VALUE), HEADERS, + CLAIMS); assertThat(jwt.getTokenValue()).isEqualTo(JWT_TOKEN_VALUE); assertThat(jwt.getHeaders()).isEqualTo(HEADERS); @@ -100,4 +115,5 @@ public class JwtTests { assertThat(jwt.getIssuedAt().toEpochMilli()).isEqualTo(IAT_VALUE); assertThat(jwt.getId()).isEqualTo(JTI_VALUE); } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtTimestampValidatorTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtTimestampValidatorTests.java index ee2f85825f..34b7bf0915 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtTimestampValidatorTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtTimestampValidatorTests.java @@ -41,10 +41,15 @@ import static org.springframework.security.oauth2.jwt.TestJwts.jwt; * @author Josh Cummings */ public class JwtTimestampValidatorTests { + private static final Clock MOCK_NOW = Clock.fixed(Instant.ofEpochMilli(0), ZoneId.systemDefault()); + private static final String MOCK_TOKEN_VALUE = "token"; + private static final Instant MOCK_ISSUED_AT = Instant.MIN; + private static final Map MOCK_HEADER = Collections.singletonMap("alg", JwsAlgorithms.RS256); + private static final Map MOCK_CLAIM_SET = Collections.singletonMap("some", "claim"); @Test @@ -86,18 +91,15 @@ public class JwtTimestampValidatorTests { Instant justOverOneDayAgo = now.minus(oneDayOff).minusSeconds(10); Instant justOverOneDayFromNow = now.plus(oneDayOff).plusSeconds(10); - Jwt jwt = jwt() - .expiresAt(almostOneDayAgo) - .notBefore(almostOneDayFromNow) - .build(); + Jwt jwt = jwt().expiresAt(almostOneDayAgo).notBefore(almostOneDayFromNow).build(); assertThat(jwtValidator.validate(jwt).hasErrors()).isFalse(); jwt = jwt().expiresAt(justOverOneDayAgo).build(); OAuth2TokenValidatorResult result = jwtValidator.validate(jwt); - Collection messages = - result.getErrors().stream().map(OAuth2Error::getDescription).collect(Collectors.toList()); + Collection messages = result.getErrors().stream().map(OAuth2Error::getDescription) + .collect(Collectors.toList()); assertThat(result.hasErrors()).isTrue(); assertThat(messages).contains("Jwt expired at " + justOverOneDayAgo); @@ -105,8 +107,7 @@ public class JwtTimestampValidatorTests { jwt = jwt().notBefore(justOverOneDayFromNow).build(); result = jwtValidator.validate(jwt); - messages = - result.getErrors().stream().map(OAuth2Error::getDescription).collect(Collectors.toList()); + messages = result.getErrors().stream().map(OAuth2Error::getDescription).collect(Collectors.toList()); assertThat(result.hasErrors()).isTrue(); assertThat(messages).contains("Jwt used before " + justOverOneDayFromNow); @@ -137,10 +138,7 @@ public class JwtTimestampValidatorTests { @Test public void validateWhenNotBeforeIsValidAndExpiryIsNotSpecifiedThenReturnsSuccessfulResult() { - Jwt jwt = jwt() - .claims(c -> c.remove(EXP)) - .notBefore(Instant.MIN) - .build(); + Jwt jwt = jwt().claims(c -> c.remove(EXP)).notBefore(Instant.MIN).build(); JwtTimestampValidator jwtValidator = new JwtTimestampValidator(); assertThat(jwtValidator.validate(jwt).hasErrors()).isFalse(); @@ -156,10 +154,7 @@ public class JwtTimestampValidatorTests { @Test public void validateWhenBothExpiryAndNotBeforeAreValidThenReturnsSuccessfulResult() { - Jwt jwt = jwt() - .expiresAt(Instant.now(MOCK_NOW)) - .notBefore(Instant.now(MOCK_NOW)) - .build(); + Jwt jwt = jwt().expiresAt(Instant.now(MOCK_NOW)).notBefore(Instant.now(MOCK_NOW)).build(); JwtTimestampValidator jwtValidator = new JwtTimestampValidator(Duration.ofNanos(0)); jwtValidator.setClock(MOCK_NOW); @@ -171,13 +166,12 @@ public class JwtTimestampValidatorTests { public void setClockWhenInvokedWithNullThenThrowsIllegalArgumentException() { JwtTimestampValidator jwtValidator = new JwtTimestampValidator(); - assertThatCode(() -> jwtValidator.setClock(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> jwtValidator.setClock(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void constructorWhenInvokedWithNullDurationThenThrowsIllegalArgumentException() { - assertThatCode(() -> new JwtTimestampValidator(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> new JwtTimestampValidator(null)).isInstanceOf(IllegalArgumentException.class); } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverterTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverterTests.java index 322890449d..49bf8f04ee 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverterTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/MappedJwtClaimSetConverterTests.java @@ -42,6 +42,7 @@ import static org.mockito.Mockito.when; * @author Josh Cummings */ public class MappedJwtClaimSetConverterTests { + @Test public void convertWhenUsingCustomExpiresAtConverterThenIssuedAtConverterStillConsultsIt() { Instant at = Instant.ofEpochMilli(1000000000000L); @@ -54,14 +55,12 @@ public class MappedJwtClaimSetConverterTests { Map source = new HashMap<>(); Map target = converter.convert(source); - assertThat(target.get(JwtClaimNames.IAT)). - isEqualTo(Instant.ofEpochMilli(at.toEpochMilli()).minusSeconds(1)); + assertThat(target.get(JwtClaimNames.IAT)).isEqualTo(Instant.ofEpochMilli(at.toEpochMilli()).minusSeconds(1)); } @Test public void convertWhenUsingDefaultsThenBasesIssuedAtOffOfExpiration() { - MappedJwtClaimSetConverter converter = - MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); + MappedJwtClaimSetConverter converter = MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); Map source = Collections.singletonMap(JwtClaimNames.EXP, 1000000000L); Map target = converter.convert(source); @@ -72,8 +71,7 @@ public class MappedJwtClaimSetConverterTests { @Test public void convertWhenUsingDefaultsThenCoercesAudienceAccordingToJwtSpec() { - MappedJwtClaimSetConverter converter = - MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); + MappedJwtClaimSetConverter converter = MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); Map source = Collections.singletonMap(JwtClaimNames.AUD, "audience"); Map target = converter.convert(source); @@ -90,8 +88,7 @@ public class MappedJwtClaimSetConverterTests { @Test public void convertWhenUsingDefaultsThenCoercesAllAttributesInJwtSpec() { - MappedJwtClaimSetConverter converter = - MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); + MappedJwtClaimSetConverter converter = MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); Map source = new HashMap<>(); source.put(JwtClaimNames.JTI, 1); @@ -142,8 +139,7 @@ public class MappedJwtClaimSetConverterTests { @Test public void convertWhenConverterReturnsNullThenClaimIsRemoved() { - MappedJwtClaimSetConverter converter = MappedJwtClaimSetConverter - .withDefaults(Collections.emptyMap()); + MappedJwtClaimSetConverter converter = MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); Map source = Collections.singletonMap(JwtClaimNames.ISS, null); Map target = converter.convert(source); @@ -193,8 +189,7 @@ public class MappedJwtClaimSetConverterTests { @Test public void convertWhenUsingDefaultsThenFailedConversionThrowsIllegalStateException() { - MappedJwtClaimSetConverter converter = MappedJwtClaimSetConverter - .withDefaults(Collections.emptyMap()); + MappedJwtClaimSetConverter converter = MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); Map badIssuer = Collections.singletonMap(JwtClaimNames.ISS, "https://badly formed iss"); assertThatCode(() -> converter.convert(badIssuer)).isInstanceOf(IllegalStateException.class); @@ -212,8 +207,7 @@ public class MappedJwtClaimSetConverterTests { // gh-6073 @Test public void convertWhenIssuerIsNotAUriThenConvertsToString() { - MappedJwtClaimSetConverter converter = MappedJwtClaimSetConverter - .withDefaults(Collections.emptyMap()); + MappedJwtClaimSetConverter converter = MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); Map nonUriIssuer = Collections.singletonMap(JwtClaimNames.ISS, "issuer"); Map target = converter.convert(nonUriIssuer); @@ -223,8 +217,7 @@ public class MappedJwtClaimSetConverterTests { // gh-6073 @Test public void convertWhenIssuerIsOfTypeURLThenConvertsToString() throws Exception { - MappedJwtClaimSetConverter converter = MappedJwtClaimSetConverter - .withDefaults(Collections.emptyMap()); + MappedJwtClaimSetConverter converter = MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); Map issuer = Collections.singletonMap(JwtClaimNames.ISS, new URL("https://issuer")); Map target = converter.convert(issuer); @@ -233,8 +226,7 @@ public class MappedJwtClaimSetConverterTests { @Test public void constructWhenAnyParameterIsNullThenIllegalArgumentException() { - assertThatCode(() -> new MappedJwtClaimSetConverter(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> new MappedJwtClaimSetConverter(null)).isInstanceOf(IllegalArgumentException.class); } @Test @@ -242,4 +234,5 @@ public class MappedJwtClaimSetConverterTests { assertThatCode(() -> MappedJwtClaimSetConverter.withDefaults(null)) .isInstanceOf(IllegalArgumentException.class); } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoderJwkSupportTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoderJwkSupportTests.java index 2597dd2638..937d0bdd41 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoderJwkSupportTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoderJwkSupportTests.java @@ -53,22 +53,26 @@ import static org.mockito.Mockito.when; * @author Josh Cummings */ public class NimbusJwtDecoderJwkSupportTests { + private static final String JWK_SET_URL = "https://provider.com/oauth2/keys"; + private static final String JWS_ALGORITHM = JwsAlgorithms.RS256; private static final String JWK_SET = "{\"keys\":[{\"p\":\"49neceJFs8R6n7WamRGy45F5Tv0YM-R2ODK3eSBUSLOSH2tAqjEVKOkLE5fiNA3ygqq15NcKRadB2pTVf-Yb5ZIBuKzko8bzYIkIqYhSh_FAdEEr0vHF5fq_yWSvc6swsOJGqvBEtuqtJY027u-G2gAQasCQdhyejer68zsTn8M\",\"kty\":\"RSA\",\"q\":\"tWR-ysspjZ73B6p2vVRVyHwP3KQWL5KEQcdgcmMOE_P_cPs98vZJfLhxobXVmvzuEWBpRSiqiuyKlQnpstKt94Cy77iO8m8ISfF3C9VyLWXi9HUGAJb99irWABFl3sNDff5K2ODQ8CmuXLYM25OwN3ikbrhEJozlXg_NJFSGD4E\",\"d\":\"FkZHYZlw5KSoqQ1i2RA2kCUygSUOf1OqMt3uomtXuUmqKBm_bY7PCOhmwbvbn4xZYEeHuTR8Xix-0KpHe3NKyWrtRjkq1T_un49_1LLVUhJ0dL-9_x0xRquVjhl_XrsRXaGMEHs8G9pLTvXQ1uST585gxIfmCe0sxPZLvwoic-bXf64UZ9BGRV3lFexWJQqCZp2S21HfoU7wiz6kfLRNi-K4xiVNB1gswm_8o5lRuY7zB9bRARQ3TS2G4eW7p5sxT3CgsGiQD3_wPugU8iDplqAjgJ5ofNJXZezoj0t6JMB_qOpbrmAM1EnomIPebSLW7Ky9SugEd6KMdL5lW6AuAQ\",\"e\":\"AQAB\",\"use\":\"sig\",\"kid\":\"one\",\"qi\":\"wdkFu_tV2V1l_PWUUimG516Zvhqk2SWDw1F7uNDD-Lvrv_WNRIJVzuffZ8WYiPy8VvYQPJUrT2EXL8P0ocqwlaSTuXctrORcbjwgxDQDLsiZE0C23HYzgi0cofbScsJdhcBg7d07LAf7cdJWG0YVl1FkMCsxUlZ2wTwHfKWf-v4\",\"dp\":\"uwnPxqC-IxG4r33-SIT02kZC1IqC4aY7PWq0nePiDEQMQWpjjNH50rlq9EyLzbtdRdIouo-jyQXB01K15-XXJJ60dwrGLYNVqfsTd0eGqD1scYJGHUWG9IDgCsxyEnuG3s0AwbW2UolWVSsU2xMZGb9PurIUZECeD1XDZwMp2s0\",\"dq\":\"hra786AunB8TF35h8PpROzPoE9VJJMuLrc6Esm8eZXMwopf0yhxfN2FEAvUoTpLJu93-UH6DKenCgi16gnQ0_zt1qNNIVoRfg4rw_rjmsxCYHTVL3-RDeC8X_7TsEySxW0EgFTHh-nr6I6CQrAJjPM88T35KHtdFATZ7BCBB8AE\",\"n\":\"oXJ8OyOv_eRnce4akdanR4KYRfnC2zLV4uYNQpcFn6oHL0dj7D6kxQmsXoYgJV8ZVDn71KGmuLvolxsDncc2UrhyMBY6DVQVgMSVYaPCTgW76iYEKGgzTEw5IBRQL9w3SRJWd3VJTZZQjkXef48Ocz06PGF3lhbz4t5UEZtdF4rIe7u-977QwHuh7yRPBQ3sII-cVoOUMgaXB9SHcGF2iZCtPzL_IffDUcfhLQteGebhW8A6eUHgpD5A1PQ-JCw_G7UOzZAjjDjtNM2eqm8j-Ms_gqnm4MiCZ4E-9pDN77CAAPVN7kuX6ejs9KBXpk01z48i9fORYk9u7rAkh1HuQw\"}]}"; + private static final String MALFORMED_JWK_SET = "malformed"; private static final String SIGNED_JWT = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ0ZXN0LXN1YmplY3QiLCJzY3AiOlsibWVzc2FnZTpyZWFkIl0sImV4cCI6NDY4Mzg5Nzc3Nn0.LtMVtIiRIwSyc3aX35Zl0JVwLTcQZAB3dyBOMHNaHCKUljwMrf20a_gT79LfhjDzE_fUVUmFiAO32W1vFnYpZSVaMDUgeIOIOpxfoe9shj_uYenAwIS-_UxqGVIJiJoXNZh_MK80ShNpvsQwamxWEEOAMBtpWNiVYNDMdfgho9n3o5_Z7Gjy8RLBo1tbDREbO9kTFwGIxm_EYpezmRCRq4w1DdS6UDW321hkwMxPnCMSWOvp-hRpmgY2yjzLgPJ6Aucmg9TJ8jloAP1DjJoF1gRR7NTAk8LOGkSjTzVYDYMbCF51YdpojhItSk80YzXiEsv1mTz4oMM49jXBmfXFMA"; + private static final String MALFORMED_JWT = "eyJhbGciOiJSUzI1NiJ9.eyJuYmYiOnt9LCJleHAiOjQ2ODQyMjUwODd9.guoQvujdWvd3xw7FYQEn4D6-gzM_WqFvXdmvAUNSLbxG7fv2_LLCNujPdrBHJoYPbOwS1BGNxIKQWS1tylvqzmr1RohQ-RZ2iAM1HYQzboUlkoMkcd8ENM__ELqho8aNYBfqwkNdUOyBFoy7Syu_w2SoJADw2RTjnesKO6CVVa05bW118pDS4xWxqC4s7fnBjmZoTn4uQ-Kt9YSQZQk8YQxkJSiyanozzgyfgXULA6mPu1pTNU3FVFaK1i1av_xtH_zAPgb647ZeaNe4nahgqC5h8nhOlm8W2dndXbwAt29nd2ZWBsru_QwZz83XSKLhTPFz-mPBByZZDsyBbIHf9A"; + private static final String UNSIGNED_JWT = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJleHAiOi0yMDMzMjI0OTcsImp0aSI6IjEyMyIsInR5cCI6IkpXVCJ9."; private NimbusJwtDecoderJwkSupport jwtDecoder = new NimbusJwtDecoderJwkSupport(JWK_SET_URL, JWS_ALGORITHM); @Test public void constructorWhenJwkSetUrlIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new NimbusJwtDecoderJwkSupport(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> new NimbusJwtDecoderJwkSupport(null)).isInstanceOf(IllegalArgumentException.class); } @Test @@ -91,8 +95,7 @@ public class NimbusJwtDecoderJwkSupportTests { @Test public void decodeWhenJwtInvalidThenThrowJwtException() { - assertThatThrownBy(() -> this.jwtDecoder.decode("invalid")) - .isInstanceOf(JwtException.class); + assertThatThrownBy(() -> this.jwtDecoder.decode("invalid")).isInstanceOf(JwtException.class); } // gh-5168 @@ -111,19 +114,17 @@ public class NimbusJwtDecoderJwkSupportTests { // gh-5457 @Test public void decodeWhenPlainJwtThenExceptionDoesNotMentionClass() { - assertThatCode(() -> this.jwtDecoder.decode(UNSIGNED_JWT)) - .isInstanceOf(JwtException.class) + assertThatCode(() -> this.jwtDecoder.decode(UNSIGNED_JWT)).isInstanceOf(JwtException.class) .hasMessageContaining("Unsupported algorithm of none"); } @Test public void decodeWhenJwtIsMalformedThenReturnsStockException() throws Exception { - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { server.enqueue(new MockResponse().setBody(JWK_SET)); String jwkSetUrl = server.url("/.well-known/jwks.json").toString(); NimbusJwtDecoderJwkSupport jwtDecoder = new NimbusJwtDecoderJwkSupport(jwkSetUrl); - assertThatCode(() -> jwtDecoder.decode(MALFORMED_JWT)) - .isInstanceOf(JwtException.class) + assertThatCode(() -> jwtDecoder.decode(MALFORMED_JWT)).isInstanceOf(JwtException.class) .hasMessage("An error occurred while attempting to decode the Jwt: Malformed payload"); server.shutdown(); } @@ -131,12 +132,11 @@ public class NimbusJwtDecoderJwkSupportTests { @Test public void decodeWhenJwkResponseIsMalformedThenReturnsStockException() throws Exception { - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { server.enqueue(new MockResponse().setBody(MALFORMED_JWK_SET)); String jwkSetUrl = server.url("/.well-known/jwks.json").toString(); NimbusJwtDecoderJwkSupport jwtDecoder = new NimbusJwtDecoderJwkSupport(jwkSetUrl); - assertThatCode(() -> jwtDecoder.decode(SIGNED_JWT)) - .isInstanceOf(JwtException.class) + assertThatCode(() -> jwtDecoder.decode(SIGNED_JWT)).isInstanceOf(JwtException.class) .hasMessage("An error occurred while attempting to decode the Jwt: Malformed Jwk set"); server.shutdown(); } @@ -144,12 +144,11 @@ public class NimbusJwtDecoderJwkSupportTests { @Test public void decodeWhenJwkEndpointIsUnresponsiveThenReturnsJwtException() throws Exception { - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { server.enqueue(new MockResponse().setBody(MALFORMED_JWK_SET)); String jwkSetUrl = server.url("/.well-known/jwks.json").toString(); NimbusJwtDecoderJwkSupport jwtDecoder = new NimbusJwtDecoderJwkSupport(jwkSetUrl); - assertThatCode(() -> jwtDecoder.decode(SIGNED_JWT)) - .isInstanceOf(JwtException.class) + assertThatCode(() -> jwtDecoder.decode(SIGNED_JWT)).isInstanceOf(JwtException.class) .hasMessageContaining("An error occurred while attempting to decode the Jwt"); server.shutdown(); } @@ -158,7 +157,7 @@ public class NimbusJwtDecoderJwkSupportTests { // gh-5603 @Test public void decodeWhenCustomRestOperationsSetThenUsed() throws Exception { - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { server.enqueue(new MockResponse().setBody(JWK_SET)); String jwkSetUrl = server.url("/.well-known/jwks.json").toString(); NimbusJwtDecoderJwkSupport jwtDecoder = new NimbusJwtDecoderJwkSupport(jwkSetUrl); @@ -172,7 +171,7 @@ public class NimbusJwtDecoderJwkSupportTests { @Test public void decodeWhenJwtFailsValidationThenReturnsCorrespondingErrorMessage() throws Exception { - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { server.enqueue(new MockResponse().setBody(JWK_SET)); String jwkSetUrl = server.url("/.well-known/jwks.json").toString(); @@ -184,15 +183,14 @@ public class NimbusJwtDecoderJwkSupportTests { when(jwtValidator.validate(any(Jwt.class))).thenReturn(OAuth2TokenValidatorResult.failure(failure)); decoder.setJwtValidator(jwtValidator); - assertThatCode(() -> decoder.decode(SIGNED_JWT)) - .isInstanceOf(JwtValidationException.class) + assertThatCode(() -> decoder.decode(SIGNED_JWT)).isInstanceOf(JwtValidationException.class) .hasMessageContaining("mock-description"); } } @Test public void decodeWhenJwtValidationHasTwoErrorsThenJwtExceptionMessageShowsFirstError() throws Exception { - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { server.enqueue(new MockResponse().setBody(JWK_SET)); String jwkSetUrl = server.url("/.well-known/jwks.json").toString(); @@ -206,8 +204,7 @@ public class NimbusJwtDecoderJwkSupportTests { when(jwtValidator.validate(any(Jwt.class))).thenReturn(result); decoder.setJwtValidator(jwtValidator); - assertThatCode(() -> decoder.decode(SIGNED_JWT)) - .isInstanceOf(JwtValidationException.class) + assertThatCode(() -> decoder.decode(SIGNED_JWT)).isInstanceOf(JwtValidationException.class) .hasMessageContaining("mock-description") .hasFieldOrPropertyWithValue("errors", Arrays.asList(firstFailure, secondFailure)); } @@ -215,7 +212,7 @@ public class NimbusJwtDecoderJwkSupportTests { @Test public void decodeWhenUsingSignedJwtThenReturnsClaimsGivenByClaimSetConverter() throws Exception { - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { server.enqueue(new MockResponse().setBody(JWK_SET)); String jwkSetUrl = server.url("/.well-known/jwks.json").toString(); @@ -233,8 +230,7 @@ public class NimbusJwtDecoderJwkSupportTests { @Test public void setClaimSetConverterWhenIsNullThenThrowsIllegalArgumentException() { - assertThatCode(() -> jwtDecoder.setClaimSetConverter(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> jwtDecoder.setClaimSetConverter(null)).isInstanceOf(IllegalArgumentException.class); } private static RestOperations mockJwkSetResponse(String response) { @@ -243,4 +239,5 @@ public class NimbusJwtDecoderJwkSupportTests { .thenReturn(new ResponseEntity<>(response, HttpStatus.OK)); return restOperations; } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoderTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoderTests.java index 9e1e8e95b3..82cb1e729c 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoderTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoderTests.java @@ -96,17 +96,25 @@ import static org.springframework.security.oauth2.jwt.NimbusJwtDecoder.withSecre * @author Mykyta Bezverkhyi */ public class NimbusJwtDecoderTests { + private static final String JWK_SET = "{\"keys\":[{\"p\":\"49neceJFs8R6n7WamRGy45F5Tv0YM-R2ODK3eSBUSLOSH2tAqjEVKOkLE5fiNA3ygqq15NcKRadB2pTVf-Yb5ZIBuKzko8bzYIkIqYhSh_FAdEEr0vHF5fq_yWSvc6swsOJGqvBEtuqtJY027u-G2gAQasCQdhyejer68zsTn8M\",\"kty\":\"RSA\",\"q\":\"tWR-ysspjZ73B6p2vVRVyHwP3KQWL5KEQcdgcmMOE_P_cPs98vZJfLhxobXVmvzuEWBpRSiqiuyKlQnpstKt94Cy77iO8m8ISfF3C9VyLWXi9HUGAJb99irWABFl3sNDff5K2ODQ8CmuXLYM25OwN3ikbrhEJozlXg_NJFSGD4E\",\"d\":\"FkZHYZlw5KSoqQ1i2RA2kCUygSUOf1OqMt3uomtXuUmqKBm_bY7PCOhmwbvbn4xZYEeHuTR8Xix-0KpHe3NKyWrtRjkq1T_un49_1LLVUhJ0dL-9_x0xRquVjhl_XrsRXaGMEHs8G9pLTvXQ1uST585gxIfmCe0sxPZLvwoic-bXf64UZ9BGRV3lFexWJQqCZp2S21HfoU7wiz6kfLRNi-K4xiVNB1gswm_8o5lRuY7zB9bRARQ3TS2G4eW7p5sxT3CgsGiQD3_wPugU8iDplqAjgJ5ofNJXZezoj0t6JMB_qOpbrmAM1EnomIPebSLW7Ky9SugEd6KMdL5lW6AuAQ\",\"e\":\"AQAB\",\"use\":\"sig\",\"kid\":\"one\",\"qi\":\"wdkFu_tV2V1l_PWUUimG516Zvhqk2SWDw1F7uNDD-Lvrv_WNRIJVzuffZ8WYiPy8VvYQPJUrT2EXL8P0ocqwlaSTuXctrORcbjwgxDQDLsiZE0C23HYzgi0cofbScsJdhcBg7d07LAf7cdJWG0YVl1FkMCsxUlZ2wTwHfKWf-v4\",\"dp\":\"uwnPxqC-IxG4r33-SIT02kZC1IqC4aY7PWq0nePiDEQMQWpjjNH50rlq9EyLzbtdRdIouo-jyQXB01K15-XXJJ60dwrGLYNVqfsTd0eGqD1scYJGHUWG9IDgCsxyEnuG3s0AwbW2UolWVSsU2xMZGb9PurIUZECeD1XDZwMp2s0\",\"dq\":\"hra786AunB8TF35h8PpROzPoE9VJJMuLrc6Esm8eZXMwopf0yhxfN2FEAvUoTpLJu93-UH6DKenCgi16gnQ0_zt1qNNIVoRfg4rw_rjmsxCYHTVL3-RDeC8X_7TsEySxW0EgFTHh-nr6I6CQrAJjPM88T35KHtdFATZ7BCBB8AE\",\"n\":\"oXJ8OyOv_eRnce4akdanR4KYRfnC2zLV4uYNQpcFn6oHL0dj7D6kxQmsXoYgJV8ZVDn71KGmuLvolxsDncc2UrhyMBY6DVQVgMSVYaPCTgW76iYEKGgzTEw5IBRQL9w3SRJWd3VJTZZQjkXef48Ocz06PGF3lhbz4t5UEZtdF4rIe7u-977QwHuh7yRPBQ3sII-cVoOUMgaXB9SHcGF2iZCtPzL_IffDUcfhLQteGebhW8A6eUHgpD5A1PQ-JCw_G7UOzZAjjDjtNM2eqm8j-Ms_gqnm4MiCZ4E-9pDN77CAAPVN7kuX6ejs9KBXpk01z48i9fORYk9u7rAkh1HuQw\"}]}"; + private static final String MALFORMED_JWK_SET = "malformed"; private static final String SIGNED_JWT = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ0ZXN0LXN1YmplY3QiLCJzY3AiOlsibWVzc2FnZTpyZWFkIl0sImV4cCI6NDY4Mzg5Nzc3Nn0.LtMVtIiRIwSyc3aX35Zl0JVwLTcQZAB3dyBOMHNaHCKUljwMrf20a_gT79LfhjDzE_fUVUmFiAO32W1vFnYpZSVaMDUgeIOIOpxfoe9shj_uYenAwIS-_UxqGVIJiJoXNZh_MK80ShNpvsQwamxWEEOAMBtpWNiVYNDMdfgho9n3o5_Z7Gjy8RLBo1tbDREbO9kTFwGIxm_EYpezmRCRq4w1DdS6UDW321hkwMxPnCMSWOvp-hRpmgY2yjzLgPJ6Aucmg9TJ8jloAP1DjJoF1gRR7NTAk8LOGkSjTzVYDYMbCF51YdpojhItSk80YzXiEsv1mTz4oMM49jXBmfXFMA"; + private static final String MALFORMED_JWT = "eyJhbGciOiJSUzI1NiJ9.eyJuYmYiOnt9LCJleHAiOjQ2ODQyMjUwODd9.guoQvujdWvd3xw7FYQEn4D6-gzM_WqFvXdmvAUNSLbxG7fv2_LLCNujPdrBHJoYPbOwS1BGNxIKQWS1tylvqzmr1RohQ-RZ2iAM1HYQzboUlkoMkcd8ENM__ELqho8aNYBfqwkNdUOyBFoy7Syu_w2SoJADw2RTjnesKO6CVVa05bW118pDS4xWxqC4s7fnBjmZoTn4uQ-Kt9YSQZQk8YQxkJSiyanozzgyfgXULA6mPu1pTNU3FVFaK1i1av_xtH_zAPgb647ZeaNe4nahgqC5h8nhOlm8W2dndXbwAt29nd2ZWBsru_QwZz83XSKLhTPFz-mPBByZZDsyBbIHf9A"; + private static final String UNSIGNED_JWT = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJleHAiOi0yMDMzMjI0OTcsImp0aSI6IjEyMyIsInR5cCI6IkpXVCJ9."; + private static final String EMPTY_EXP_CLAIM_JWT = "eyJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJhdWRpZW5jZSJ9.D1eT0jpBEpuh74p-YT-uF81Z7rkVqIpUtJ5hWWFiVShZ9s8NIntK4Q1GlvlziiySSaVYaXtpTmDB3c8r-Z5Mj4ibihiueCSq7jaPD3sA8IMQKL-L6Uol8MSD_lSFE2n3fVBTxFeaejBKfZsDxnhzgpy8g7PncR47w8NHs-7tKO4qw7G_SV3hkNpDNoqZTfMImxyWEebgKM2pJAhN4das2CO1KAjYMfEByLcgYncE8fzdYPJhMFo2XRRSQABoeUBuKSAwIntBaOGvcb-qII_Hefc5U0cmpNItG75F2XfX803plKI4FFpAxJsbPKWSQmhs6bZOrhx0x74pY5LS3ghmJw"; private static final String JWK_SET_URI = "https://issuer/.well-known/jwks.json"; + private static final String RS512_SIGNED_JWT = "eyJhbGciOiJSUzUxMiJ9.eyJzdWIiOiJ0ZXN0LXN1YmplY3QiLCJleHAiOjE5NzQzMjYxMTl9.LKAx-60EBfD7jC1jb1eKcjO4uLvf3ssISV-8tN-qp7gAjSvKvj4YA9-V2mIb6jcS1X_xGmNy6EIimZXpWaBR3nJmeu-jpe85u4WaW2Ztr8ecAi-dTO7ZozwdtljKuBKKvj4u1nF70zyCNl15AozSG0W1ASrjUuWrJtfyDG6WoZ8VfNMuhtU-xUYUFvscmeZKUYQcJ1KS-oV5tHeF8aNiwQoiPC_9KXCOZtNEJFdq6-uzFdHxvOP2yex5Gbmg5hXonauIFXG2ZPPGdXzm-5xkhBpgM8U7A_6wb3So8wBvLYYm2245QUump63AJRAy8tQpwt4n9MvQxQgS3z9R-NK92A"; + private static final String RS256_SIGNED_JWT = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ0ZXN0LXN1YmplY3QiLCJleHAiOjE5NzQzMjYzMzl9.CT-H2OWEqmSs1NWmnta5ealLFvM8OlbQTjGhfRcKLNxrTrzsOkqBJl-AN3k16BQU7mS32o744TiiZ29NcDlxPsr1MqTlN86-dobPiuNIDLp3A1bOVdXMcVFuMYkrNv0yW0tGS9OjEqsCCuZDkZ1by6AhsHLbGwRY-6AQdcRouZygGpOQu1hNun5j8q5DpSTY4AXKARIFlF-O3OpVbPJ0ebr3Ki-i3U9p_55H0e4-wx2bqcApWlqgofl1I8NKWacbhZgn81iibup2W7E0CzCzh71u1Mcy3xk1sYePx-dwcxJnHmxJReBBWjJZEAeCrkbnn_OCuo2fA-EQyNJtlN5F2w"; + private static final String VERIFY_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq4yKxb6SNePdDmQi9xFCrP6QvHosErQzryknQTTTffs0t3cy3Er3lIceuhZ7yQNSCDfPFqG8GoyoKhuChRiA5D+J2ab7bqTa1QJKfnCyERoscftgN2fXPHjHoiKbpGV2tMVw8mXl//tePOAiKbMJaBUnlAvJgkk1rVm08dSwpLC1sr2M19euf9jwnRGkMRZuhp9iCPgECRke5T8Ixpv0uQjSmGHnWUKTFlbj8sM83suROR1Ue64JSGScANc5vk3huJ/J97qTC+K2oKj6L8d9O8dpc4obijEOJwpydNvTYDgbiivYeSB00KS9jlBkQ5B2QqLvLVEygDl3dp59nGx6YQIDAQAB"; private static final MediaType APPLICATION_JWK_SET_JSON = new MediaType("application", "jwk-set+json"); @@ -122,14 +130,12 @@ public class NimbusJwtDecoderTests { @Test public void constructorWhenJwtProcessorIsNullThenThrowIllegalArgumentException() { - assertThatThrownBy(() -> new NimbusJwtDecoder(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> new NimbusJwtDecoder(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void setClaimSetConverterWhenIsNullThenThrowsIllegalArgumentException() { - assertThatCode(() -> this.jwtDecoder.setClaimSetConverter(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> this.jwtDecoder.setClaimSetConverter(null)).isInstanceOf(IllegalArgumentException.class); } @Test @@ -140,35 +146,30 @@ public class NimbusJwtDecoderTests { @Test public void decodeWhenJwtInvalidThenThrowJwtException() { - assertThatThrownBy(() -> this.jwtDecoder.decode("invalid")) - .isInstanceOf(BadJwtException.class); + assertThatThrownBy(() -> this.jwtDecoder.decode("invalid")).isInstanceOf(BadJwtException.class); } // gh-5168 @Test public void decodeWhenExpClaimNullThenDoesNotThrowException() { - assertThatCode(() -> this.jwtDecoder.decode(EMPTY_EXP_CLAIM_JWT)) - .doesNotThrowAnyException(); + assertThatCode(() -> this.jwtDecoder.decode(EMPTY_EXP_CLAIM_JWT)).doesNotThrowAnyException(); } @Test public void decodeWhenIatClaimNullThenDoesNotThrowException() { - assertThatCode(() -> this.jwtDecoder.decode(SIGNED_JWT)) - .doesNotThrowAnyException(); + assertThatCode(() -> this.jwtDecoder.decode(SIGNED_JWT)).doesNotThrowAnyException(); } // gh-5457 @Test public void decodeWhenPlainJwtThenExceptionDoesNotMentionClass() { - assertThatCode(() -> this.jwtDecoder.decode(UNSIGNED_JWT)) - .isInstanceOf(BadJwtException.class) + assertThatCode(() -> this.jwtDecoder.decode(UNSIGNED_JWT)).isInstanceOf(BadJwtException.class) .hasMessageContaining("Unsupported algorithm of none"); } @Test public void decodeWhenJwtIsMalformedThenReturnsStockException() { - assertThatCode(() -> this.jwtDecoder.decode(MALFORMED_JWT)) - .isInstanceOf(BadJwtException.class) + assertThatCode(() -> this.jwtDecoder.decode(MALFORMED_JWT)).isInstanceOf(BadJwtException.class) .hasMessage("An error occurred while attempting to decode the Jwt: Malformed payload"); } @@ -177,12 +178,10 @@ public class NimbusJwtDecoderTests { OAuth2Error failure = new OAuth2Error("mock-error", "mock-description", "mock-uri"); OAuth2TokenValidator jwtValidator = mock(OAuth2TokenValidator.class); - when(jwtValidator.validate(any(Jwt.class))) - .thenReturn(OAuth2TokenValidatorResult.failure(failure)); + when(jwtValidator.validate(any(Jwt.class))).thenReturn(OAuth2TokenValidatorResult.failure(failure)); this.jwtDecoder.setJwtValidator(jwtValidator); - assertThatCode(() -> this.jwtDecoder.decode(SIGNED_JWT)) - .isInstanceOf(JwtValidationException.class) + assertThatCode(() -> this.jwtDecoder.decode(SIGNED_JWT)).isInstanceOf(JwtValidationException.class) .hasMessageContaining("mock-description"); } @@ -196,8 +195,7 @@ public class NimbusJwtDecoderTests { when(jwtValidator.validate(any(Jwt.class))).thenReturn(result); this.jwtDecoder.setJwtValidator(jwtValidator); - assertThatCode(() -> this.jwtDecoder.decode(SIGNED_JWT)) - .isInstanceOf(JwtValidationException.class) + assertThatCode(() -> this.jwtDecoder.decode(SIGNED_JWT)).isInstanceOf(JwtValidationException.class) .hasMessageContaining("mock-description") .hasFieldOrPropertyWithValue("errors", Arrays.asList(firstFailure, secondFailure)); } @@ -213,16 +211,14 @@ public class NimbusJwtDecoderTests { OAuth2TokenValidatorResult result = OAuth2TokenValidatorResult.failure(errorEmpty, error, error2); when(jwtValidator.validate(any(Jwt.class))).thenReturn(result); - Assertions.assertThatCode(() -> this.jwtDecoder.decode(SIGNED_JWT)) - .isInstanceOf(JwtValidationException.class) + Assertions.assertThatCode(() -> this.jwtDecoder.decode(SIGNED_JWT)).isInstanceOf(JwtValidationException.class) .hasMessageContaining("mock-description"); } @Test public void decodeWhenUsingSignedJwtThenReturnsClaimsGivenByClaimSetConverter() { Converter, Map> claimSetConverter = mock(Converter.class); - when(claimSetConverter.convert(any(Map.class))) - .thenReturn(Collections.singletonMap("custom", "value")); + when(claimSetConverter.convert(any(Map.class))).thenReturn(Collections.singletonMap("custom", "value")); this.jwtDecoder.setClaimSetConverter(claimSetConverter); Jwt jwt = this.jwtDecoder.decode(SIGNED_JWT); @@ -238,8 +234,7 @@ public class NimbusJwtDecoderTests { when(claimSetConverter.convert(any(Map.class))).thenThrow(new IllegalArgumentException("bad conversion")); - assertThatCode(() -> this.jwtDecoder.decode(SIGNED_JWT)) - .isInstanceOf(BadJwtException.class); + assertThatCode(() -> this.jwtDecoder.decode(SIGNED_JWT)).isInstanceOf(BadJwtException.class); } @Test @@ -252,21 +247,19 @@ public class NimbusJwtDecoderTests { @Test public void decodeWhenJwkResponseIsMalformedThenReturnsStockException() { NimbusJwtDecoder jwtDecoder = new NimbusJwtDecoder(withSigning(MALFORMED_JWK_SET)); - assertThatCode(() -> jwtDecoder.decode(SIGNED_JWT)) - .isInstanceOf(JwtException.class) + assertThatCode(() -> jwtDecoder.decode(SIGNED_JWT)).isInstanceOf(JwtException.class) .isNotInstanceOf(BadJwtException.class) .hasMessage("An error occurred while attempting to decode the Jwt: Malformed Jwk set"); } @Test public void decodeWhenJwkEndpointIsUnresponsiveThenReturnsJwtException() throws Exception { - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { String jwkSetUri = server.url("/.well-known/jwks.json").toString(); NimbusJwtDecoder jwtDecoder = withJwkSetUri(jwkSetUri).build(); server.shutdown(); - assertThatCode(() -> jwtDecoder.decode(SIGNED_JWT)) - .isInstanceOf(JwtException.class) + assertThatCode(() -> jwtDecoder.decode(SIGNED_JWT)).isInstanceOf(JwtException.class) .isNotInstanceOf(BadJwtException.class) .hasMessageContaining("An error occurred while attempting to decode the Jwt"); } @@ -274,14 +267,13 @@ public class NimbusJwtDecoderTests { @Test public void decodeWhenJwkEndpointIsUnresponsiveAndCacheIsConfiguredThenReturnsJwtException() throws Exception { - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { Cache cache = new ConcurrentMapCache("test-jwk-set-cache"); String jwkSetUri = server.url("/.well-known/jwks.json").toString(); NimbusJwtDecoder jwtDecoder = withJwkSetUri(jwkSetUri).cache(cache).build(); server.shutdown(); - assertThatCode(() -> jwtDecoder.decode(SIGNED_JWT)) - .isInstanceOf(JwtException.class) + assertThatCode(() -> jwtDecoder.decode(SIGNED_JWT)).isInstanceOf(JwtException.class) .isNotInstanceOf(BadJwtException.class) .hasMessageContaining("An error occurred while attempting to decode the Jwt"); } @@ -312,32 +304,25 @@ public class NimbusJwtDecoderTests { @Test public void withPublicKeyWhenNullThenThrowsException() { - assertThatThrownBy(() -> withPublicKey(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> withPublicKey(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void buildWhenSignatureAlgorithmMismatchesKeyTypeThenThrowsException() { - Assertions.assertThatCode(() -> withPublicKey(key()) - .signatureAlgorithm(SignatureAlgorithm.ES256) - .build()) + Assertions.assertThatCode(() -> withPublicKey(key()).signatureAlgorithm(SignatureAlgorithm.ES256).build()) .isInstanceOf(IllegalStateException.class); } @Test public void decodeWhenUsingPublicKeyThenSuccessfullyDecodes() throws Exception { NimbusJwtDecoder decoder = withPublicKey(key()).build(); - assertThat(decoder.decode(RS256_SIGNED_JWT)) - .extracting(Jwt::getSubject) - .isEqualTo("test-subject"); + assertThat(decoder.decode(RS256_SIGNED_JWT)).extracting(Jwt::getSubject).isEqualTo("test-subject"); } @Test public void decodeWhenUsingPublicKeyWithRs512ThenSuccessfullyDecodes() throws Exception { NimbusJwtDecoder decoder = withPublicKey(key()).signatureAlgorithm(SignatureAlgorithm.RS512).build(); - assertThat(decoder.decode(RS512_SIGNED_JWT)) - .extracting(Jwt::getSubject) - .isEqualTo("test-subject"); + assertThat(decoder.decode(RS512_SIGNED_JWT)).extracting(Jwt::getSubject).isEqualTo("test-subject"); } // gh-7049 @@ -346,22 +331,17 @@ public class NimbusJwtDecoderTests { RSAPublicKey publicKey = TestKeys.DEFAULT_PUBLIC_KEY; RSAPrivateKey privateKey = TestKeys.DEFAULT_PRIVATE_KEY; JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS256).keyID("one").build(); - JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() - .subject("test-subject") - .expirationTime(Date.from(Instant.now().plusSeconds(60))) - .build(); + JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().subject("test-subject") + .expirationTime(Date.from(Instant.now().plusSeconds(60))).build(); SignedJWT signedJwt = signedJwt(privateKey, header, claimsSet); NimbusJwtDecoder decoder = withPublicKey(publicKey).signatureAlgorithm(SignatureAlgorithm.RS256).build(); - assertThat(decoder.decode(signedJwt.serialize())) - .extracting(Jwt::getSubject) - .isEqualTo("test-subject"); + assertThat(decoder.decode(signedJwt.serialize())).extracting(Jwt::getSubject).isEqualTo("test-subject"); } @Test public void decodeWhenSignatureMismatchesAlgorithmThenThrowsException() throws Exception { NimbusJwtDecoder decoder = withPublicKey(key()).signatureAlgorithm(SignatureAlgorithm.RS512).build(); - Assertions.assertThatCode(() -> decoder.decode(RS256_SIGNED_JWT)) - .isInstanceOf(BadJwtException.class); + Assertions.assertThatCode(() -> decoder.decode(RS256_SIGNED_JWT)).isInstanceOf(BadJwtException.class); } // gh-8730 @@ -370,13 +350,12 @@ public class NimbusJwtDecoderTests { RSAPublicKey publicKey = TestKeys.DEFAULT_PUBLIC_KEY; RSAPrivateKey privateKey = TestKeys.DEFAULT_PRIVATE_KEY; JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS256).type(new JOSEObjectType("JWS")).build(); - JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() - .expirationTime(Date.from(Instant.now().plusSeconds(60))) + JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().expirationTime(Date.from(Instant.now().plusSeconds(60))) .build(); SignedJWT signedJwt = signedJwt(privateKey, header, claimsSet); - NimbusJwtDecoder decoder = withPublicKey(publicKey) - .signatureAlgorithm(SignatureAlgorithm.RS256) - .jwtProcessorCustomizer(p -> p.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("JWS")))) + NimbusJwtDecoder decoder = withPublicKey(publicKey).signatureAlgorithm(SignatureAlgorithm.RS256) + .jwtProcessorCustomizer( + p -> p.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("JWS")))) .build(); assertThat(decoder.decode(signedJwt.serialize()).containsClaim(JwtClaimNames.EXP)).isNotNull(); } @@ -384,14 +363,12 @@ public class NimbusJwtDecoderTests { @Test public void withPublicKeyWhenJwtProcessorCustomizerNullThenThrowsIllegalArgumentException() { assertThatThrownBy(() -> withPublicKey(key()).jwtProcessorCustomizer(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("jwtProcessorCustomizer cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("jwtProcessorCustomizer cannot be null"); } @Test public void withSecretKeyWhenNullThenThrowsIllegalArgumentException() { - assertThatThrownBy(() -> withSecretKey(null)) - .isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> withSecretKey(null)).isInstanceOf(IllegalArgumentException.class) .hasMessage("secretKey cannot be null"); } @@ -399,37 +376,29 @@ public class NimbusJwtDecoderTests { public void withSecretKeyWhenMacAlgorithmNullThenThrowsIllegalArgumentException() { SecretKey secretKey = TestKeys.DEFAULT_SECRET_KEY; assertThatThrownBy(() -> withSecretKey(secretKey).macAlgorithm(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("macAlgorithm cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("macAlgorithm cannot be null"); } @Test public void decodeWhenUsingSecretKeyThenSuccessfullyDecodes() throws Exception { SecretKey secretKey = TestKeys.DEFAULT_SECRET_KEY; MacAlgorithm macAlgorithm = MacAlgorithm.HS256; - JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() - .subject("test-subject") - .expirationTime(Date.from(Instant.now().plusSeconds(60))) - .build(); + JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().subject("test-subject") + .expirationTime(Date.from(Instant.now().plusSeconds(60))).build(); SignedJWT signedJWT = signedJwt(secretKey, macAlgorithm, claimsSet); NimbusJwtDecoder decoder = withSecretKey(secretKey).macAlgorithm(macAlgorithm).build(); - assertThat(decoder.decode(signedJWT.serialize())) - .extracting(Jwt::getSubject) - .isEqualTo("test-subject"); + assertThat(decoder.decode(signedJWT.serialize())).extracting(Jwt::getSubject).isEqualTo("test-subject"); } @Test public void decodeWhenUsingSecretKeyAndIncorrectAlgorithmThenThrowsJwtException() throws Exception { SecretKey secretKey = TestKeys.DEFAULT_SECRET_KEY; MacAlgorithm macAlgorithm = MacAlgorithm.HS256; - JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() - .subject("test-subject") - .expirationTime(Date.from(Instant.now().plusSeconds(60))) - .build(); + JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().subject("test-subject") + .expirationTime(Date.from(Instant.now().plusSeconds(60))).build(); SignedJWT signedJWT = signedJwt(secretKey, macAlgorithm, claimsSet); NimbusJwtDecoder decoder = withSecretKey(secretKey).macAlgorithm(MacAlgorithm.HS512).build(); - assertThatThrownBy(() -> decoder.decode(signedJWT.serialize())) - .isInstanceOf(BadJwtException.class) + assertThatThrownBy(() -> decoder.decode(signedJWT.serialize())).isInstanceOf(BadJwtException.class) .hasMessageContaining("Unsupported algorithm of HS256"); } @@ -438,15 +407,11 @@ public class NimbusJwtDecoderTests { public void decodeWhenUsingSecertKeyWithKidThenStillUsesKey() throws Exception { SecretKey secretKey = TestKeys.DEFAULT_SECRET_KEY; JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.HS256).keyID("one").build(); - JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() - .subject("test-subject") - .expirationTime(Date.from(Instant.now().plusSeconds(60))) - .build(); + JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().subject("test-subject") + .expirationTime(Date.from(Instant.now().plusSeconds(60))).build(); SignedJWT signedJwt = signedJwt(secretKey, header, claimsSet); NimbusJwtDecoder decoder = withSecretKey(secretKey).macAlgorithm(MacAlgorithm.HS256).build(); - assertThat(decoder.decode(signedJwt.serialize())) - .extracting(Jwt::getSubject) - .isEqualTo("test-subject"); + assertThat(decoder.decode(signedJwt.serialize())).extracting(Jwt::getSubject).isEqualTo("test-subject"); } // gh-8730 @@ -454,13 +419,12 @@ public class NimbusJwtDecoderTests { public void withSecretKeyWhenUsingCustomTypeHeaderThenSuccessfullyDecodes() throws Exception { SecretKey secretKey = TestKeys.DEFAULT_SECRET_KEY; JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.HS256).type(new JOSEObjectType("JWS")).build(); - JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() - .expirationTime(Date.from(Instant.now().plusSeconds(60))) + JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().expirationTime(Date.from(Instant.now().plusSeconds(60))) .build(); SignedJWT signedJwt = signedJwt(secretKey, header, claimsSet); - NimbusJwtDecoder decoder = withSecretKey(secretKey) - .macAlgorithm(MacAlgorithm.HS256) - .jwtProcessorCustomizer(p -> p.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("JWS")))) + NimbusJwtDecoder decoder = withSecretKey(secretKey).macAlgorithm(MacAlgorithm.HS256) + .jwtProcessorCustomizer( + p -> p.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("JWS")))) .build(); assertThat(decoder.decode(signedJwt.serialize()).containsClaim(JwtClaimNames.EXP)).isNotNull(); } @@ -469,50 +433,38 @@ public class NimbusJwtDecoderTests { public void withSecretKeyWhenJwtProcessorCustomizerNullThenThrowsIllegalArgumentException() { SecretKey secretKey = TestKeys.DEFAULT_SECRET_KEY; assertThatThrownBy(() -> withSecretKey(secretKey).jwtProcessorCustomizer(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("jwtProcessorCustomizer cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("jwtProcessorCustomizer cannot be null"); } @Test public void jwsKeySelectorWhenNoAlgorithmThenReturnsRS256Selector() { JWKSource jwkSource = mock(JWKSource.class); - JWSKeySelector jwsKeySelector = - withJwkSetUri(JWK_SET_URI).jwsKeySelector(jwkSource); + JWSKeySelector jwsKeySelector = withJwkSetUri(JWK_SET_URI).jwsKeySelector(jwkSource); assertThat(jwsKeySelector instanceof JWSVerificationKeySelector); - JWSVerificationKeySelector jwsVerificationKeySelector = - (JWSVerificationKeySelector) jwsKeySelector; - assertThat(jwsVerificationKeySelector.isAllowed(JWSAlgorithm.RS256)) - .isTrue(); + JWSVerificationKeySelector jwsVerificationKeySelector = (JWSVerificationKeySelector) jwsKeySelector; + assertThat(jwsVerificationKeySelector.isAllowed(JWSAlgorithm.RS256)).isTrue(); } @Test public void jwsKeySelectorWhenOneAlgorithmThenReturnsSingleSelector() { JWKSource jwkSource = mock(JWKSource.class); - JWSKeySelector jwsKeySelector = - withJwkSetUri(JWK_SET_URI).jwsAlgorithm(SignatureAlgorithm.RS512) - .jwsKeySelector(jwkSource); + JWSKeySelector jwsKeySelector = withJwkSetUri(JWK_SET_URI) + .jwsAlgorithm(SignatureAlgorithm.RS512).jwsKeySelector(jwkSource); assertThat(jwsKeySelector instanceof JWSVerificationKeySelector); - JWSVerificationKeySelector jwsVerificationKeySelector = - (JWSVerificationKeySelector) jwsKeySelector; - assertThat(jwsVerificationKeySelector.isAllowed(JWSAlgorithm.RS512)) - .isTrue(); + JWSVerificationKeySelector jwsVerificationKeySelector = (JWSVerificationKeySelector) jwsKeySelector; + assertThat(jwsVerificationKeySelector.isAllowed(JWSAlgorithm.RS512)).isTrue(); } @Test public void jwsKeySelectorWhenMultipleAlgorithmThenReturnsCompositeSelector() { JWKSource jwkSource = mock(JWKSource.class); - JWSKeySelector jwsKeySelector = - withJwkSetUri(JWK_SET_URI) - .jwsAlgorithm(SignatureAlgorithm.RS256) - .jwsAlgorithm(SignatureAlgorithm.RS512) - .jwsKeySelector(jwkSource); + JWSKeySelector jwsKeySelector = withJwkSetUri(JWK_SET_URI) + .jwsAlgorithm(SignatureAlgorithm.RS256).jwsAlgorithm(SignatureAlgorithm.RS512) + .jwsKeySelector(jwkSource); assertThat(jwsKeySelector instanceof JWSVerificationKeySelector); - JWSVerificationKeySelector jwsAlgorithmMapKeySelector = - (JWSVerificationKeySelector) jwsKeySelector; - assertThat(jwsAlgorithmMapKeySelector.isAllowed(JWSAlgorithm.RS256)) - .isTrue(); - assertThat(jwsAlgorithmMapKeySelector.isAllowed(JWSAlgorithm.RS512)) - .isTrue(); + JWSVerificationKeySelector jwsAlgorithmMapKeySelector = (JWSVerificationKeySelector) jwsKeySelector; + assertThat(jwsAlgorithmMapKeySelector.isAllowed(JWSAlgorithm.RS256)).isTrue(); + assertThat(jwsAlgorithmMapKeySelector.isAllowed(JWSAlgorithm.RS512)).isTrue(); } // gh-7290 @@ -521,9 +473,7 @@ public class NimbusJwtDecoderTests { RestOperations restOperations = mock(RestOperations.class); when(restOperations.exchange(any(RequestEntity.class), eq(String.class))) .thenReturn(new ResponseEntity<>(JWK_SET, HttpStatus.OK)); - JWTProcessor processor = withJwkSetUri(JWK_SET_URI) - .restOperations(restOperations) - .processor(); + JWTProcessor processor = withJwkSetUri(JWK_SET_URI).restOperations(restOperations).processor(); NimbusJwtDecoder jwtDecoder = new NimbusJwtDecoder(processor); jwtDecoder.decode(SIGNED_JWT); ArgumentCaptor requestEntityCaptor = ArgumentCaptor.forClass(RequestEntity.class); @@ -539,10 +489,7 @@ public class NimbusJwtDecoderTests { RestOperations restOperations = mock(RestOperations.class); when(restOperations.exchange(any(RequestEntity.class), eq(String.class))) .thenReturn(new ResponseEntity<>(JWK_SET, HttpStatus.OK)); - NimbusJwtDecoder jwtDecoder = withJwkSetUri(JWK_SET_URI) - .restOperations(restOperations) - .cache(cache) - .build(); + NimbusJwtDecoder jwtDecoder = withJwkSetUri(JWK_SET_URI).restOperations(restOperations).cache(cache).build(); // when jwtDecoder.decode(SIGNED_JWT); // then @@ -560,10 +507,7 @@ public class NimbusJwtDecoderTests { RestOperations restOperations = mock(RestOperations.class); Cache cache = mock(Cache.class); when(cache.get(eq(JWK_SET_URI), any(Callable.class))).thenReturn(JWK_SET); - NimbusJwtDecoder jwtDecoder = withJwkSetUri(JWK_SET_URI) - .cache(cache) - .restOperations(restOperations) - .build(); + NimbusJwtDecoder jwtDecoder = withJwkSetUri(JWK_SET_URI).cache(cache).restOperations(restOperations).build(); // when jwtDecoder.decode(SIGNED_JWT); // then @@ -579,13 +523,9 @@ public class NimbusJwtDecoderTests { RestOperations restOperations = mock(RestOperations.class); when(restOperations.exchange(any(RequestEntity.class), eq(String.class))) .thenThrow(new RestClientException("Cannot retrieve JWK Set")); - NimbusJwtDecoder jwtDecoder = withJwkSetUri(JWK_SET_URI) - .restOperations(restOperations) - .cache(cache) - .build(); + NimbusJwtDecoder jwtDecoder = withJwkSetUri(JWK_SET_URI).restOperations(restOperations).cache(cache).build(); // then - assertThatCode(() -> jwtDecoder.decode(SIGNED_JWT)) - .isInstanceOf(JwtException.class) + assertThatCode(() -> jwtDecoder.decode(SIGNED_JWT)).isInstanceOf(JwtException.class) .isNotInstanceOf(BadJwtException.class) .hasMessageContaining("An error occurred while attempting to decode the Jwt"); } @@ -596,20 +536,18 @@ public class NimbusJwtDecoderTests { RestOperations restOperations = mock(RestOperations.class); when(restOperations.exchange(any(RequestEntity.class), eq(String.class))) .thenReturn(new ResponseEntity<>(JWK_SET, HttpStatus.OK)); - NimbusJwtDecoder jwtDecoder = withJwkSetUri(JWK_SET_URI) - .restOperations(restOperations) - .jwtProcessorCustomizer(p -> p.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("JWS")))) + NimbusJwtDecoder jwtDecoder = withJwkSetUri(JWK_SET_URI).restOperations(restOperations) + .jwtProcessorCustomizer( + p -> p.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("JWS")))) .build(); - assertThatCode(() -> jwtDecoder.decode(SIGNED_JWT)) - .isInstanceOf(BadJwtException.class) - .hasMessageContaining("An error occurred while attempting to decode the Jwt: Required JOSE header \"typ\" (type) parameter is missing"); + assertThatCode(() -> jwtDecoder.decode(SIGNED_JWT)).isInstanceOf(BadJwtException.class).hasMessageContaining( + "An error occurred while attempting to decode the Jwt: Required JOSE header \"typ\" (type) parameter is missing"); } @Test public void withJwkSetUriWhenJwtProcessorCustomizerNullThenThrowsIllegalArgumentException() { assertThatThrownBy(() -> withJwkSetUri(JWK_SET_URI).jwtProcessorCustomizer(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("jwtProcessorCustomizer cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("jwtProcessorCustomizer cannot be null"); } private RSAPublicKey key() throws InvalidKeySpecException { @@ -618,7 +556,8 @@ public class NimbusJwtDecoderTests { return (RSAPublicKey) kf.generatePublic(spec); } - private SignedJWT signedJwt(SecretKey secretKey, MacAlgorithm jwsAlgorithm, JWTClaimsSet claimsSet) throws Exception { + private SignedJWT signedJwt(SecretKey secretKey, MacAlgorithm jwsAlgorithm, JWTClaimsSet claimsSet) + throws Exception { return signedJwt(secretKey, new JWSHeader(JWSAlgorithm.parse(jwsAlgorithm.getName())), claimsSet); } @@ -642,9 +581,7 @@ public class NimbusJwtDecoderTests { RestOperations restOperations = mock(RestOperations.class); when(restOperations.exchange(any(RequestEntity.class), eq(String.class))) .thenReturn(new ResponseEntity<>(jwkResponse, HttpStatus.OK)); - return withJwkSetUri(JWK_SET_URI) - .restOperations(restOperations) - .processor(); + return withJwkSetUri(JWK_SET_URI).restOperations(restOperations).processor(); } private static JWTProcessor withoutSigning() { @@ -652,16 +589,19 @@ public class NimbusJwtDecoderTests { } private static class MockJwtProcessor extends DefaultJWTProcessor { + @Override - public JWTClaimsSet process(SignedJWT signedJWT, SecurityContext context) - throws BadJOSEException { + public JWTClaimsSet process(SignedJWT signedJWT, SecurityContext context) throws BadJOSEException { try { return signedJWT.getJWTClaimsSet(); - } catch (ParseException e) { + } + catch (ParseException e) { // Payload not a JSON object throw new BadJWTException(e.getMessage(), e); } } + } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoderTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoderTests.java index 8c884dc8ab..2927e89441 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoderTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoderTests.java @@ -84,27 +84,26 @@ import static org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder.w public class NimbusReactiveJwtDecoderTests { private String expired = "eyJraWQiOiJrZXktaWQtMSIsImFsZyI6IlJTMjU2In0.eyJzY29wZSI6Im1lc3NhZ2U6cmVhZCIsImV4cCI6MTUyOTkzNzYzMX0.Dt5jFOKkB8zAmjciwvlGkj4LNStXWH0HNIfr8YYajIthBIpVgY5Hg_JL8GBmUFzKDgyusT0q60OOg8_Pdi4Lu-VTWyYutLSlNUNayMlyBaVEWfyZJnh2_OwMZr1vRys6HF-o1qZldhwcfvczHg61LwPa1ISoqaAltDTzBu9cGISz2iBUCuR0x71QhbuRNyJdjsyS96NqiM_TspyiOSxmlNch2oAef1MssOQ23CrKilIvEDsz_zk5H94q7rH0giWGdEHCENESsTJS0zvzH6r2xIWjd5WnihFpCPkwznEayxaEhrdvJqT_ceyXCIfY4m3vujPQHNDG0UshpwvDuEbPUg"; + private String messageReadToken = "eyJraWQiOiJrZXktaWQtMSIsImFsZyI6IlJTMjU2In0.eyJzY29wZSI6Im1lc3NhZ2U6cmVhZCIsImV4cCI6OTIyMzM3MjAwNjA5NjM3NX0.bnQ8IJDXmQbmIXWku0YT1HOyV_3d0iQSA_0W2CmPyELhsxFETzBEEcZ0v0xCBiswDT51rwD83wbX3YXxb84fM64AhpU8wWOxLjha4J6HJX2JnlG47ydaAVD7eWGSYTavyyQ-CwUjQWrfMVcObFZLYG11ydzRYOR9-aiHcK3AobcTcS8jZFeI8EGQV_Cd3IJ018uFCf6VnXLv7eV2kRt08Go2RiPLW47ExvD7Dzzz_wDBKfb4pNem7fDvuzB3UPcp5m9QvLZicnbS_6AvDi6P1y_DFJf-1T5gkGmX5piDH1L1jg2Yl6tjmXbk5B3VhsyjJuXE6gzq1d-xie0Z1NVOxw"; + private String unsignedToken = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJleHAiOi0yMDMzMjI0OTcsImp0aSI6IjEyMyIsInR5cCI6IkpXVCJ9."; - private String jwkSet = - "{\n" - + " \"keys\":[\n" - + " {\n" - + " \"kty\":\"RSA\",\n" - + " \"e\":\"AQAB\",\n" - + " \"use\":\"sig\",\n" - + " \"kid\":\"key-id-1\",\n" - + " \"n\":\"qL48v1clgFw-Evm145pmh8nRYiNt72Gupsshn7Qs8dxEydCRp1DPOV_PahPk1y2nvldBNIhfNL13JOAiJ6BTiF-2ICuICAhDArLMnTH61oL1Hepq8W1xpa9gxsnL1P51thvfmiiT4RTW57koy4xIWmIp8ZXXfYgdH2uHJ9R0CQBuYKe7nEOObjxCFWC8S30huOfW2cYtv0iB23h6w5z2fDLjddX6v_FXM7ktcokgpm3_XmvT_-bL6_GGwz9k6kJOyMTubecr-WT__le8ikY66zlplYXRQh6roFfFCL21Pt8xN5zrk-0AMZUnmi8F2S2ztSBmAVJ7H71ELXsURBVZpw\"\n" - + " }\n" - + " ]\n" - + "}"; + + private String jwkSet = "{\n" + " \"keys\":[\n" + " {\n" + " \"kty\":\"RSA\",\n" + + " \"e\":\"AQAB\",\n" + " \"use\":\"sig\",\n" + " \"kid\":\"key-id-1\",\n" + + " \"n\":\"qL48v1clgFw-Evm145pmh8nRYiNt72Gupsshn7Qs8dxEydCRp1DPOV_PahPk1y2nvldBNIhfNL13JOAiJ6BTiF-2ICuICAhDArLMnTH61oL1Hepq8W1xpa9gxsnL1P51thvfmiiT4RTW57koy4xIWmIp8ZXXfYgdH2uHJ9R0CQBuYKe7nEOObjxCFWC8S30huOfW2cYtv0iB23h6w5z2fDLjddX6v_FXM7ktcokgpm3_XmvT_-bL6_GGwz9k6kJOyMTubecr-WT__le8ikY66zlplYXRQh6roFfFCL21Pt8xN5zrk-0AMZUnmi8F2S2ztSBmAVJ7H71ELXsURBVZpw\"\n" + + " }\n" + " ]\n" + "}"; + private String jwkSetUri = "https://issuer/certs"; private String rsa512 = "eyJhbGciOiJSUzUxMiJ9.eyJzdWIiOiJ0ZXN0LXN1YmplY3QiLCJleHAiOjE5NzQzMjYxMTl9.LKAx-60EBfD7jC1jb1eKcjO4uLvf3ssISV-8tN-qp7gAjSvKvj4YA9-V2mIb6jcS1X_xGmNy6EIimZXpWaBR3nJmeu-jpe85u4WaW2Ztr8ecAi-dTO7ZozwdtljKuBKKvj4u1nF70zyCNl15AozSG0W1ASrjUuWrJtfyDG6WoZ8VfNMuhtU-xUYUFvscmeZKUYQcJ1KS-oV5tHeF8aNiwQoiPC_9KXCOZtNEJFdq6-uzFdHxvOP2yex5Gbmg5hXonauIFXG2ZPPGdXzm-5xkhBpgM8U7A_6wb3So8wBvLYYm2245QUump63AJRAy8tQpwt4n9MvQxQgS3z9R-NK92A"; + private String rsa256 = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ0ZXN0LXN1YmplY3QiLCJleHAiOjE5NzQzMjYzMzl9.CT-H2OWEqmSs1NWmnta5ealLFvM8OlbQTjGhfRcKLNxrTrzsOkqBJl-AN3k16BQU7mS32o744TiiZ29NcDlxPsr1MqTlN86-dobPiuNIDLp3A1bOVdXMcVFuMYkrNv0yW0tGS9OjEqsCCuZDkZ1by6AhsHLbGwRY-6AQdcRouZygGpOQu1hNun5j8q5DpSTY4AXKARIFlF-O3OpVbPJ0ebr3Ki-i3U9p_55H0e4-wx2bqcApWlqgofl1I8NKWacbhZgn81iibup2W7E0CzCzh71u1Mcy3xk1sYePx-dwcxJnHmxJReBBWjJZEAeCrkbnn_OCuo2fA-EQyNJtlN5F2w"; + private String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq4yKxb6SNePdDmQi9xFCrP6QvHosErQzryknQTTTffs0t3cy3Er3lIceuhZ7yQNSCDfPFqG8GoyoKhuChRiA5D+J2ab7bqTa1QJKfnCyERoscftgN2fXPHjHoiKbpGV2tMVw8mXl//tePOAiKbMJaBUnlAvJgkk1rVm08dSwpLC1sr2M19euf9jwnRGkMRZuhp9iCPgECRke5T8Ixpv0uQjSmGHnWUKTFlbj8sM83suROR1Ue64JSGScANc5vk3huJ/J97qTC+K2oKj6L8d9O8dpc4obijEOJwpydNvTYDgbiivYeSB00KS9jlBkQ5B2QqLvLVEygDl3dp59nGx6YQIDAQAB"; private MockWebServer server; + private NimbusReactiveJwtDecoder decoder; private static KeyFactory kf; @@ -132,8 +131,7 @@ public class NimbusReactiveJwtDecoderTests { this.decoder = new NimbusReactiveJwtDecoder("https://s"); assertThatCode(() -> this.decoder.decode(this.messageReadToken).block()) - .isInstanceOf(IllegalStateException.class) - .hasCauseInstanceOf(UnknownHostException.class); + .isInstanceOf(IllegalStateException.class).hasCauseInstanceOf(UnknownHostException.class); } @@ -146,14 +144,14 @@ public class NimbusReactiveJwtDecoderTests { @Test public void decodeWhenRSAPublicKeyThenSuccess() throws Exception { - byte[] bytes = Base64.getDecoder().decode("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqL48v1clgFw+Evm145pmh8nRYiNt72Gupsshn7Qs8dxEydCRp1DPOV/PahPk1y2nvldBNIhfNL13JOAiJ6BTiF+2ICuICAhDArLMnTH61oL1Hepq8W1xpa9gxsnL1P51thvfmiiT4RTW57koy4xIWmIp8ZXXfYgdH2uHJ9R0CQBuYKe7nEOObjxCFWC8S30huOfW2cYtv0iB23h6w5z2fDLjddX6v/FXM7ktcokgpm3/XmvT/+bL6/GGwz9k6kJOyMTubecr+WT//le8ikY66zlplYXRQh6roFfFCL21Pt8xN5zrk+0AMZUnmi8F2S2ztSBmAVJ7H71ELXsURBVZpwIDAQAB"); + byte[] bytes = Base64.getDecoder().decode( + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqL48v1clgFw+Evm145pmh8nRYiNt72Gupsshn7Qs8dxEydCRp1DPOV/PahPk1y2nvldBNIhfNL13JOAiJ6BTiF+2ICuICAhDArLMnTH61oL1Hepq8W1xpa9gxsnL1P51thvfmiiT4RTW57koy4xIWmIp8ZXXfYgdH2uHJ9R0CQBuYKe7nEOObjxCFWC8S30huOfW2cYtv0iB23h6w5z2fDLjddX6v/FXM7ktcokgpm3/XmvT/+bL6/GGwz9k6kJOyMTubecr+WT//le8ikY66zlplYXRQh6roFfFCL21Pt8xN5zrk+0AMZUnmi8F2S2ztSBmAVJ7H71ELXsURBVZpwIDAQAB"); RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA") .generatePublic(new X509EncodedKeySpec(bytes)); this.decoder = new NimbusReactiveJwtDecoder(publicKey); String noKeyId = "eyJhbGciOiJSUzI1NiJ9.eyJzY29wZSI6IiIsImV4cCI6OTIyMzM3MjAwNjA5NjM3NX0.hNVuHSUkxdLZrDfqdmKcOi0ggmNaDuB4ZPxPtJl1gwBiXzIGN6Hwl24O2BfBZiHFKUTQDs4_RvzD71mEG3DvUrcKmdYWqIB1l8KNmxQLUDG-cAPIpJmRJgCh50tf8OhOE_Cb9E1HcsOUb47kT9iz-VayNBcmo6BmyZLdEGhsdGBrc3Mkz2dd_0PF38I2Hf_cuSjn9gBjFGtiPEXJvob3PEjVTSx_zvodT8D9p3An1R3YBZf5JSd1cQisrXgDX2k1Jmf7UKKWzgfyCgnEtRWWbsUdPqo3rSEY9GDC1iSQXsFTTC1FT_JJDkwzGf011fsU5O_Ko28TARibmKTCxAKNRQ"; - assertThatCode(() -> this.decoder.decode(noKeyId).block()) - .doesNotThrowAnyException(); + assertThatCode(() -> this.decoder.decode(noKeyId).block()).doesNotThrowAnyException(); } @Test @@ -167,14 +165,12 @@ public class NimbusReactiveJwtDecoderTests { @Test public void decodeWhenExpiredThenFail() { - assertThatCode(() -> this.decoder.decode(this.expired).block()) - .isInstanceOf(JwtValidationException.class); + assertThatCode(() -> this.decoder.decode(this.expired).block()).isInstanceOf(JwtValidationException.class); } @Test public void decodeWhenNoPeriodThenFail() { - assertThatCode(() -> this.decoder.decode("").block()) - .isInstanceOf(BadJwtException.class); + assertThatCode(() -> this.decoder.decode("").block()).isInstanceOf(BadJwtException.class); } @Test @@ -186,27 +182,27 @@ public class NimbusReactiveJwtDecoderTests { @Test public void decodeWhenInvalidSignatureThenFail() { - assertThatCode(() -> this.decoder.decode(this.messageReadToken.substring(0, this.messageReadToken.length() - 2)).block()) - .isInstanceOf(BadJwtException.class); + assertThatCode(() -> this.decoder.decode(this.messageReadToken.substring(0, this.messageReadToken.length() - 2)) + .block()).isInstanceOf(BadJwtException.class); } @Test public void decodeWhenAlgNoneThenFail() { - assertThatCode(() -> this.decoder.decode("ew0KICAiYWxnIjogIm5vbmUiLA0KICAidHlwIjogIkpXVCINCn0.ew0KICAic3ViIjogIjEyMzQ1Njc4OTAiLA0KICAibmFtZSI6ICJKb2huIERvZSIsDQogICJpYXQiOiAxNTE2MjM5MDIyDQp9.").block()) - .isInstanceOf(BadJwtException.class) - .hasMessage("Unsupported algorithm of none"); + assertThatCode(() -> this.decoder.decode( + "ew0KICAiYWxnIjogIm5vbmUiLA0KICAidHlwIjogIkpXVCINCn0.ew0KICAic3ViIjogIjEyMzQ1Njc4OTAiLA0KICAibmFtZSI6ICJKb2huIERvZSIsDQogICJpYXQiOiAxNTE2MjM5MDIyDQp9.") + .block()).isInstanceOf(BadJwtException.class).hasMessage("Unsupported algorithm of none"); } @Test public void decodeWhenInvalidAlgMismatchThenFail() { - assertThatCode(() -> this.decoder.decode("ew0KICAiYWxnIjogIkVTMjU2IiwNCiAgInR5cCI6ICJKV1QiDQp9.ew0KICAic3ViIjogIjEyMzQ1Njc4OTAiLA0KICAibmFtZSI6ICJKb2huIERvZSIsDQogICJpYXQiOiAxNTE2MjM5MDIyDQp9.").block()) - .isInstanceOf(BadJwtException.class); + assertThatCode(() -> this.decoder.decode( + "ew0KICAiYWxnIjogIkVTMjU2IiwNCiAgInR5cCI6ICJKV1QiDQp9.ew0KICAic3ViIjogIjEyMzQ1Njc4OTAiLA0KICAibmFtZSI6ICJKb2huIERvZSIsDQogICJpYXQiOiAxNTE2MjM5MDIyDQp9.") + .block()).isInstanceOf(BadJwtException.class); } @Test public void decodeWhenUnsignedTokenThenMessageDoesNotMentionClass() { - assertThatCode(() -> this.decoder.decode(this.unsignedToken).block()) - .isInstanceOf(BadJwtException.class) + assertThatCode(() -> this.decoder.decode(this.unsignedToken).block()).isInstanceOf(BadJwtException.class) .hasMessage("Unsupported algorithm of none"); } @@ -220,8 +216,7 @@ public class NimbusReactiveJwtDecoderTests { when(jwtValidator.validate(any(Jwt.class))).thenReturn(result); assertThatCode(() -> this.decoder.decode(this.messageReadToken).block()) - .isInstanceOf(JwtValidationException.class) - .hasMessageContaining("mock-description"); + .isInstanceOf(JwtValidationException.class).hasMessageContaining("mock-description"); } @Test @@ -236,8 +231,7 @@ public class NimbusReactiveJwtDecoderTests { when(jwtValidator.validate(any(Jwt.class))).thenReturn(result); assertThatCode(() -> this.decoder.decode(this.messageReadToken).block()) - .isInstanceOf(JwtValidationException.class) - .hasMessageContaining("mock-description"); + .isInstanceOf(JwtValidationException.class).hasMessageContaining("mock-description"); } @Test @@ -261,20 +255,17 @@ public class NimbusReactiveJwtDecoderTests { when(claimSetConverter.convert(any(Map.class))).thenThrow(new IllegalArgumentException("bad conversion")); - assertThatCode(() -> this.decoder.decode(this.messageReadToken).block()) - .isInstanceOf(BadJwtException.class); + assertThatCode(() -> this.decoder.decode(this.messageReadToken).block()).isInstanceOf(BadJwtException.class); } @Test public void setJwtValidatorWhenGivenNullThrowsIllegalArgumentException() { - assertThatCode(() -> this.decoder.setJwtValidator(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> this.decoder.setJwtValidator(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void setClaimSetConverterWhenNullThrowsIllegalArgumentException() { - assertThatCode(() -> this.decoder.setClaimSetConverter(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> this.decoder.setClaimSetConverter(null)).isInstanceOf(IllegalArgumentException.class); } @Test @@ -291,8 +282,7 @@ public class NimbusReactiveJwtDecoderTests { @Test public void withJwkSetUriWhenJwtProcessorCustomizerNullThenThrowsIllegalArgumentException() { assertThatCode(() -> withJwkSetUri(jwkSetUri).jwtProcessorCustomizer(null).build()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("jwtProcessorCustomizer cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("jwtProcessorCustomizer cannot be null"); } @Test @@ -306,9 +296,7 @@ public class NimbusReactiveJwtDecoderTests { public void decodeWhenSignedThenOk() { WebClient webClient = mockJwkSetResponse(this.jwkSet); NimbusReactiveJwtDecoder decoder = withJwkSetUri(this.jwkSetUri).webClient(webClient).build(); - assertThat(decoder.decode(messageReadToken).block()) - .extracting(Jwt::getExpiresAt) - .isNotNull(); + assertThat(decoder.decode(messageReadToken).block()).extracting(Jwt::getExpiresAt).isNotNull(); verify(webClient).get(); } @@ -316,66 +304,55 @@ public class NimbusReactiveJwtDecoderTests { @Test public void withJwkSetUriWhenUsingCustomTypeHeaderThenRefuseOmittedType() { WebClient webClient = mockJwkSetResponse(this.jwkSet); - NimbusReactiveJwtDecoder decoder = withJwkSetUri(this.jwkSetUri) - .webClient(webClient) - .jwtProcessorCustomizer(p -> p.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("JWS")))) + NimbusReactiveJwtDecoder decoder = withJwkSetUri(this.jwkSetUri).webClient(webClient) + .jwtProcessorCustomizer( + p -> p.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("JWS")))) .build(); - assertThatCode(() -> decoder.decode(messageReadToken).block()) - .isInstanceOf(BadJwtException.class) + assertThatCode(() -> decoder.decode(messageReadToken).block()).isInstanceOf(BadJwtException.class) .hasRootCauseMessage("Required JOSE header \"typ\" (type) parameter is missing"); } @Test public void withPublicKeyWhenNullThenThrowsException() { - assertThatThrownBy(() -> withPublicKey(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> withPublicKey(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void buildWhenSignatureAlgorithmMismatchesKeyTypeThenThrowsException() { - assertThatCode(() -> withPublicKey(key()) - .signatureAlgorithm(SignatureAlgorithm.ES256) - .build()) + assertThatCode(() -> withPublicKey(key()).signatureAlgorithm(SignatureAlgorithm.ES256).build()) .isInstanceOf(IllegalStateException.class); } @Test public void buildWhenJwtProcessorCustomizerNullThenThrowsIllegalArgumentException() { assertThatCode(() -> withPublicKey(key()).jwtProcessorCustomizer(null).build()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("jwtProcessorCustomizer cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("jwtProcessorCustomizer cannot be null"); } @Test public void decodeWhenUsingPublicKeyThenSuccessfullyDecodes() throws Exception { NimbusReactiveJwtDecoder decoder = withPublicKey(key()).build(); - assertThat(decoder.decode(this.rsa256).block()) - .extracting(Jwt::getSubject) - .isEqualTo("test-subject"); + assertThat(decoder.decode(this.rsa256).block()).extracting(Jwt::getSubject).isEqualTo("test-subject"); } @Test public void decodeWhenUsingPublicKeyWithRs512ThenSuccessfullyDecodes() throws Exception { - NimbusReactiveJwtDecoder decoder = - withPublicKey(key()).signatureAlgorithm(SignatureAlgorithm.RS512).build(); - assertThat(decoder.decode(this.rsa512).block()) - .extracting(Jwt::getSubject) - .isEqualTo("test-subject"); + NimbusReactiveJwtDecoder decoder = withPublicKey(key()).signatureAlgorithm(SignatureAlgorithm.RS512).build(); + assertThat(decoder.decode(this.rsa512).block()).extracting(Jwt::getSubject).isEqualTo("test-subject"); } @Test public void decodeWhenSignatureMismatchesAlgorithmThenThrowsException() throws Exception { - NimbusReactiveJwtDecoder decoder = - withPublicKey(key()).signatureAlgorithm(SignatureAlgorithm.RS512).build(); - assertThatCode(() -> decoder.decode(this.rsa256).block()) - .isInstanceOf(BadJwtException.class); + NimbusReactiveJwtDecoder decoder = withPublicKey(key()).signatureAlgorithm(SignatureAlgorithm.RS512).build(); + assertThatCode(() -> decoder.decode(this.rsa256).block()).isInstanceOf(BadJwtException.class); } // gh-8730 @Test public void withPublicKeyWhenUsingCustomTypeHeaderThenRefuseOmittedType() throws Exception { NimbusReactiveJwtDecoder decoder = withPublicKey(key()) - .jwtProcessorCustomizer(p -> p.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("JWS")))) + .jwtProcessorCustomizer( + p -> p.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("JWS")))) .build(); AssertionsForClassTypes.assertThatCode(() -> decoder.decode(this.rsa256).block()) @@ -385,44 +362,38 @@ public class NimbusReactiveJwtDecoderTests { @Test public void withJwkSourceWhenNullThenThrowsException() { - assertThatCode(() -> withJwkSource(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> withJwkSource(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void withJwkSourceWhenJwtProcessorCustomizerNullThenThrowsIllegalArgumentException() { assertThatCode(() -> withJwkSource(jwt -> Flux.empty()).jwtProcessorCustomizer(null).build()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("jwtProcessorCustomizer cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("jwtProcessorCustomizer cannot be null"); } @Test public void decodeWhenCustomJwkSourceResolutionThenDecodes() { - NimbusReactiveJwtDecoder decoder = - withJwkSource(jwt -> Flux.fromIterable(parseJWKSet(this.jwkSet).getKeys())) - .build(); + NimbusReactiveJwtDecoder decoder = withJwkSource(jwt -> Flux.fromIterable(parseJWKSet(this.jwkSet).getKeys())) + .build(); - assertThat(decoder.decode(this.messageReadToken).block()) - .extracting(Jwt::getExpiresAt) - .isNotNull(); + assertThat(decoder.decode(this.messageReadToken).block()).extracting(Jwt::getExpiresAt).isNotNull(); } // gh-8730 @Test public void withJwkSourceWhenUsingCustomTypeHeaderThenRefuseOmittedType() { NimbusReactiveJwtDecoder decoder = withJwkSource(jwt -> Flux.empty()) - .jwtProcessorCustomizer(p -> p.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("JWS")))) + .jwtProcessorCustomizer( + p -> p.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("JWS")))) .build(); - assertThatCode(() -> decoder.decode(this.messageReadToken).block()) - .isInstanceOf(BadJwtException.class) + assertThatCode(() -> decoder.decode(this.messageReadToken).block()).isInstanceOf(BadJwtException.class) .hasRootCauseMessage("Required JOSE header \"typ\" (type) parameter is missing"); } @Test public void withSecretKeyWhenSecretKeyNullThenThrowsIllegalArgumentException() { - assertThatThrownBy(() -> withSecretKey(null)) - .isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> withSecretKey(null)).isInstanceOf(IllegalArgumentException.class) .hasMessage("secretKey cannot be null"); } @@ -430,26 +401,22 @@ public class NimbusReactiveJwtDecoderTests { public void withSecretKeyWhenJwtProcessorCustomizerNullThenThrowsIllegalArgumentException() { SecretKey secretKey = TestKeys.DEFAULT_SECRET_KEY; assertThatThrownBy(() -> withSecretKey(secretKey).jwtProcessorCustomizer(null).build()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("jwtProcessorCustomizer cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("jwtProcessorCustomizer cannot be null"); } @Test public void withSecretKeyWhenMacAlgorithmNullThenThrowsIllegalArgumentException() { SecretKey secretKey = TestKeys.DEFAULT_SECRET_KEY; assertThatThrownBy(() -> withSecretKey(secretKey).macAlgorithm(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("macAlgorithm cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("macAlgorithm cannot be null"); } @Test public void decodeWhenSecretKeyThenSuccess() throws Exception { SecretKey secretKey = TestKeys.DEFAULT_SECRET_KEY; MacAlgorithm macAlgorithm = MacAlgorithm.HS256; - JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() - .subject("test-subject") - .expirationTime(Date.from(Instant.now().plusSeconds(60))) - .build(); + JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().subject("test-subject") + .expirationTime(Date.from(Instant.now().plusSeconds(60))).build(); SignedJWT signedJWT = signedJwt(secretKey, macAlgorithm, claimsSet); this.decoder = withSecretKey(secretKey).macAlgorithm(macAlgorithm).build(); @@ -462,10 +429,10 @@ public class NimbusReactiveJwtDecoderTests { public void withSecretKeyWhenUsingCustomTypeHeaderThenRefuseOmittedType() { SecretKey secretKey = TestKeys.DEFAULT_SECRET_KEY; NimbusReactiveJwtDecoder decoder = withSecretKey(secretKey) - .jwtProcessorCustomizer(p -> p.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("JWS")))) + .jwtProcessorCustomizer( + p -> p.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("JWS")))) .build(); - assertThatCode(() -> decoder.decode(messageReadToken).block()) - .isInstanceOf(BadJwtException.class) + assertThatCode(() -> decoder.decode(messageReadToken).block()).isInstanceOf(BadJwtException.class) .hasRootCauseMessage("Required JOSE header \"typ\" (type) parameter is missing"); } @@ -473,10 +440,8 @@ public class NimbusReactiveJwtDecoderTests { public void decodeWhenSecretKeyAndAlgorithmMismatchThenThrowsJwtException() throws Exception { SecretKey secretKey = TestKeys.DEFAULT_SECRET_KEY; MacAlgorithm macAlgorithm = MacAlgorithm.HS256; - JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() - .subject("test-subject") - .expirationTime(Date.from(Instant.now().plusSeconds(60))) - .build(); + JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().subject("test-subject") + .expirationTime(Date.from(Instant.now().plusSeconds(60))).build(); SignedJWT signedJWT = signedJwt(secretKey, macAlgorithm, claimsSet); this.decoder = withSecretKey(secretKey).macAlgorithm(MacAlgorithm.HS512).build(); @@ -487,46 +452,36 @@ public class NimbusReactiveJwtDecoderTests { @Test public void jwsKeySelectorWhenNoAlgorithmThenReturnsRS256Selector() { JWKSource jwkSource = mock(JWKSource.class); - JWSKeySelector jwsKeySelector = - withJwkSetUri(this.jwkSetUri).jwsKeySelector(jwkSource); + JWSKeySelector jwsKeySelector = withJwkSetUri(this.jwkSetUri).jwsKeySelector(jwkSource); assertThat(jwsKeySelector instanceof JWSVerificationKeySelector); - JWSVerificationKeySelector jwsVerificationKeySelector = - (JWSVerificationKeySelector) jwsKeySelector; - assertThat(jwsVerificationKeySelector.isAllowed(JWSAlgorithm.RS256)) - .isTrue(); + JWSVerificationKeySelector jwsVerificationKeySelector = (JWSVerificationKeySelector) jwsKeySelector; + assertThat(jwsVerificationKeySelector.isAllowed(JWSAlgorithm.RS256)).isTrue(); } @Test public void jwsKeySelectorWhenOneAlgorithmThenReturnsSingleSelector() { JWKSource jwkSource = mock(JWKSource.class); - JWSKeySelector jwsKeySelector = - withJwkSetUri(this.jwkSetUri).jwsAlgorithm(SignatureAlgorithm.RS512) - .jwsKeySelector(jwkSource); + JWSKeySelector jwsKeySelector = withJwkSetUri(this.jwkSetUri) + .jwsAlgorithm(SignatureAlgorithm.RS512).jwsKeySelector(jwkSource); assertThat(jwsKeySelector instanceof JWSVerificationKeySelector); - JWSVerificationKeySelector jwsVerificationKeySelector = - (JWSVerificationKeySelector) jwsKeySelector; - assertThat(jwsVerificationKeySelector.isAllowed(JWSAlgorithm.RS512)) - .isTrue(); + JWSVerificationKeySelector jwsVerificationKeySelector = (JWSVerificationKeySelector) jwsKeySelector; + assertThat(jwsVerificationKeySelector.isAllowed(JWSAlgorithm.RS512)).isTrue(); } @Test public void jwsKeySelectorWhenMultipleAlgorithmThenReturnsCompositeSelector() { JWKSource jwkSource = mock(JWKSource.class); - JWSKeySelector jwsKeySelector = - withJwkSetUri(this.jwkSetUri) - .jwsAlgorithm(SignatureAlgorithm.RS256) - .jwsAlgorithm(SignatureAlgorithm.RS512) - .jwsKeySelector(jwkSource); + JWSKeySelector jwsKeySelector = withJwkSetUri(this.jwkSetUri) + .jwsAlgorithm(SignatureAlgorithm.RS256).jwsAlgorithm(SignatureAlgorithm.RS512) + .jwsKeySelector(jwkSource); assertThat(jwsKeySelector instanceof JWSVerificationKeySelector); - JWSVerificationKeySelector jwsAlgorithmMapKeySelector = - (JWSVerificationKeySelector) jwsKeySelector; - assertThat(jwsAlgorithmMapKeySelector.isAllowed(JWSAlgorithm.RS256)) - .isTrue(); - assertThat(jwsAlgorithmMapKeySelector.isAllowed(JWSAlgorithm.RS512)) - .isTrue(); + JWSVerificationKeySelector jwsAlgorithmMapKeySelector = (JWSVerificationKeySelector) jwsKeySelector; + assertThat(jwsAlgorithmMapKeySelector.isAllowed(JWSAlgorithm.RS256)).isTrue(); + assertThat(jwsAlgorithmMapKeySelector.isAllowed(JWSAlgorithm.RS512)).isTrue(); } - private SignedJWT signedJwt(SecretKey secretKey, MacAlgorithm jwsAlgorithm, JWTClaimsSet claimsSet) throws Exception { + private SignedJWT signedJwt(SecretKey secretKey, MacAlgorithm jwsAlgorithm, JWTClaimsSet claimsSet) + throws Exception { SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.parse(jwsAlgorithm.getName())), claimsSet); JWSSigner signer = new MACSigner(secretKey); signedJWT.sign(signer); @@ -536,7 +491,8 @@ public class NimbusReactiveJwtDecoderTests { private JWKSet parseJWKSet(String jwkSet) { try { return JWKSet.parse(jwkSet); - } catch (ParseException e) { + } + catch (ParseException e) { throw new IllegalArgumentException(e); } } @@ -557,4 +513,5 @@ public class NimbusReactiveJwtDecoderTests { when(spec.retrieve()).thenReturn(responseSpec); return webClient; } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecodersTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecodersTests.java index 3e6b411fc5..4cb9b91789 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecodersTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/ReactiveJwtDecodersTests.java @@ -46,40 +46,31 @@ import static org.assertj.core.api.Assertions.assertThatCode; * @author Rafiullah Hamedy */ public class ReactiveJwtDecodersTests { + /** - * Contains those parameters required to construct a ReactiveJwtDecoder as well as any required parameters + * Contains those parameters required to construct a ReactiveJwtDecoder as well as any + * required parameters */ - private static final String DEFAULT_RESPONSE_TEMPLATE = - "{\n" - + " \"authorization_endpoint\": \"https://example.com/o/oauth2/v2/auth\", \n" - + " \"id_token_signing_alg_values_supported\": [\n" - + " \"RS256\"\n" - + " ], \n" - + " \"issuer\": \"%s\", \n" - + " \"jwks_uri\": \"%s/.well-known/jwks.json\", \n" - + " \"response_types_supported\": [\n" - + " \"code\", \n" - + " \"token\", \n" - + " \"id_token\", \n" - + " \"code token\", \n" - + " \"code id_token\", \n" - + " \"token id_token\", \n" - + " \"code token id_token\", \n" - + " \"none\"\n" - + " ], \n" - + " \"subject_types_supported\": [\n" - + " \"public\"\n" - + " ], \n" - + " \"token_endpoint\": \"https://example.com/oauth2/v4/token\"\n" - + "}"; + private static final String DEFAULT_RESPONSE_TEMPLATE = "{\n" + + " \"authorization_endpoint\": \"https://example.com/o/oauth2/v2/auth\", \n" + + " \"id_token_signing_alg_values_supported\": [\n" + " \"RS256\"\n" + " ], \n" + + " \"issuer\": \"%s\", \n" + " \"jwks_uri\": \"%s/.well-known/jwks.json\", \n" + + " \"response_types_supported\": [\n" + " \"code\", \n" + " \"token\", \n" + + " \"id_token\", \n" + " \"code token\", \n" + " \"code id_token\", \n" + + " \"token id_token\", \n" + " \"code token id_token\", \n" + " \"none\"\n" + + " ], \n" + " \"subject_types_supported\": [\n" + " \"public\"\n" + " ], \n" + + " \"token_endpoint\": \"https://example.com/oauth2/v4/token\"\n" + "}"; private static final String JWK_SET = "{\"keys\":[{\"p\":\"49neceJFs8R6n7WamRGy45F5Tv0YM-R2ODK3eSBUSLOSH2tAqjEVKOkLE5fiNA3ygqq15NcKRadB2pTVf-Yb5ZIBuKzko8bzYIkIqYhSh_FAdEEr0vHF5fq_yWSvc6swsOJGqvBEtuqtJY027u-G2gAQasCQdhyejer68zsTn8M\",\"kty\":\"RSA\",\"q\":\"tWR-ysspjZ73B6p2vVRVyHwP3KQWL5KEQcdgcmMOE_P_cPs98vZJfLhxobXVmvzuEWBpRSiqiuyKlQnpstKt94Cy77iO8m8ISfF3C9VyLWXi9HUGAJb99irWABFl3sNDff5K2ODQ8CmuXLYM25OwN3ikbrhEJozlXg_NJFSGD4E\",\"d\":\"FkZHYZlw5KSoqQ1i2RA2kCUygSUOf1OqMt3uomtXuUmqKBm_bY7PCOhmwbvbn4xZYEeHuTR8Xix-0KpHe3NKyWrtRjkq1T_un49_1LLVUhJ0dL-9_x0xRquVjhl_XrsRXaGMEHs8G9pLTvXQ1uST585gxIfmCe0sxPZLvwoic-bXf64UZ9BGRV3lFexWJQqCZp2S21HfoU7wiz6kfLRNi-K4xiVNB1gswm_8o5lRuY7zB9bRARQ3TS2G4eW7p5sxT3CgsGiQD3_wPugU8iDplqAjgJ5ofNJXZezoj0t6JMB_qOpbrmAM1EnomIPebSLW7Ky9SugEd6KMdL5lW6AuAQ\",\"e\":\"AQAB\",\"use\":\"sig\",\"kid\":\"one\",\"qi\":\"wdkFu_tV2V1l_PWUUimG516Zvhqk2SWDw1F7uNDD-Lvrv_WNRIJVzuffZ8WYiPy8VvYQPJUrT2EXL8P0ocqwlaSTuXctrORcbjwgxDQDLsiZE0C23HYzgi0cofbScsJdhcBg7d07LAf7cdJWG0YVl1FkMCsxUlZ2wTwHfKWf-v4\",\"dp\":\"uwnPxqC-IxG4r33-SIT02kZC1IqC4aY7PWq0nePiDEQMQWpjjNH50rlq9EyLzbtdRdIouo-jyQXB01K15-XXJJ60dwrGLYNVqfsTd0eGqD1scYJGHUWG9IDgCsxyEnuG3s0AwbW2UolWVSsU2xMZGb9PurIUZECeD1XDZwMp2s0\",\"dq\":\"hra786AunB8TF35h8PpROzPoE9VJJMuLrc6Esm8eZXMwopf0yhxfN2FEAvUoTpLJu93-UH6DKenCgi16gnQ0_zt1qNNIVoRfg4rw_rjmsxCYHTVL3-RDeC8X_7TsEySxW0EgFTHh-nr6I6CQrAJjPM88T35KHtdFATZ7BCBB8AE\",\"n\":\"oXJ8OyOv_eRnce4akdanR4KYRfnC2zLV4uYNQpcFn6oHL0dj7D6kxQmsXoYgJV8ZVDn71KGmuLvolxsDncc2UrhyMBY6DVQVgMSVYaPCTgW76iYEKGgzTEw5IBRQL9w3SRJWd3VJTZZQjkXef48Ocz06PGF3lhbz4t5UEZtdF4rIe7u-977QwHuh7yRPBQ3sII-cVoOUMgaXB9SHcGF2iZCtPzL_IffDUcfhLQteGebhW8A6eUHgpD5A1PQ-JCw_G7UOzZAjjDjtNM2eqm8j-Ms_gqnm4MiCZ4E-9pDN77CAAPVN7kuX6ejs9KBXpk01z48i9fORYk9u7rAkh1HuQw\"}]}"; + private static final String ISSUER_MISMATCH = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczpcL1wvd3Jvbmdpc3N1ZXIiLCJleHAiOjQ2ODcyNTYwNDl9.Ax8LMI6rhB9Pv_CE3kFi1JPuLj9gZycifWrLeDpkObWEEVAsIls9zAhNFyJlG-Oo7up6_mDhZgeRfyKnpSF5GhKJtXJDCzwg0ZDVUE6rS0QadSxsMMGbl7c4y0lG_7TfLX2iWeNJukJj_oSW9KzW4FsBp1BoocWjrreesqQU3fZHbikH-c_Fs2TsAIpHnxflyEzfOFWpJ8D4DtzHXqfvieMwpy42xsPZK3LR84zlasf0Ne1tC_hLHvyHRdAXwn0CMoKxc7-8j0r9Mq8kAzUsPn9If7bMLqGkxUcTPdk5x7opAUajDZx95SXHLmtztNtBa2S6EfPJXuPKG6tM5Wq5Ug"; private static final String OIDC_METADATA_PATH = "/.well-known/openid-configuration"; + private static final String OAUTH_METADATA_PATH = "/.well-known/oauth-authorization-server"; private MockWebServer server; + private String issuer; @Before @@ -101,8 +92,7 @@ public class ReactiveJwtDecodersTests { ReactiveJwtDecoder decoder = ReactiveJwtDecoders.fromOidcIssuerLocation(this.issuer); - assertThatCode(() -> decoder.decode(ISSUER_MISMATCH).block()) - .isInstanceOf(JwtValidationException.class) + assertThatCode(() -> decoder.decode(ISSUER_MISMATCH).block()).isInstanceOf(JwtValidationException.class) .hasMessageContaining("The iss claim is not valid"); } @@ -112,8 +102,7 @@ public class ReactiveJwtDecodersTests { ReactiveJwtDecoder decoder = ReactiveJwtDecoders.fromIssuerLocation(this.issuer); - assertThatCode(() -> decoder.decode(ISSUER_MISMATCH).block()) - .isInstanceOf(JwtValidationException.class) + assertThatCode(() -> decoder.decode(ISSUER_MISMATCH).block()).isInstanceOf(JwtValidationException.class) .hasMessageContaining("The iss claim is not valid"); } @@ -123,8 +112,7 @@ public class ReactiveJwtDecodersTests { ReactiveJwtDecoder decoder = ReactiveJwtDecoders.fromIssuerLocation(this.issuer); - assertThatCode(() -> decoder.decode(ISSUER_MISMATCH).block()) - .isInstanceOf(JwtValidationException.class) + assertThatCode(() -> decoder.decode(ISSUER_MISMATCH).block()).isInstanceOf(JwtValidationException.class) .hasMessageContaining("The iss claim is not valid"); } @@ -139,15 +127,13 @@ public class ReactiveJwtDecodersTests { @Test public void issuerWhenOidcFallbackResponseIsNonCompliantThenThrowsRuntimeException() { prepareConfigurationResponseOidc("{ \"missing_required_keys\" : \"and_values\" }"); - assertThatCode(() -> ReactiveJwtDecoders.fromIssuerLocation(this.issuer)) - .isInstanceOf(RuntimeException.class); + assertThatCode(() -> ReactiveJwtDecoders.fromIssuerLocation(this.issuer)).isInstanceOf(RuntimeException.class); } @Test public void issuerWhenOAuth2ResponseIsNonCompliantThenThrowsRuntimeException() { prepareConfigurationResponseOAuth2("{ \"missing_required_keys\" : \"and_values\" }"); - assertThatCode(() -> ReactiveJwtDecoders.fromIssuerLocation(this.issuer)) - .isInstanceOf(RuntimeException.class); + assertThatCode(() -> ReactiveJwtDecoders.fromIssuerLocation(this.issuer)).isInstanceOf(RuntimeException.class); } // gh-7512 @@ -156,8 +142,7 @@ public class ReactiveJwtDecodersTests { throws JsonMappingException, JsonProcessingException { prepareConfigurationResponse(this.buildResponseWithMissingJwksUri()); assertThatCode(() -> ReactiveJwtDecoders.fromOidcIssuerLocation(this.issuer)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("The public JWK set URI must not be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("The public JWK set URI must not be null"); } // gh-7512 @@ -166,8 +151,7 @@ public class ReactiveJwtDecodersTests { throws JsonMappingException, JsonProcessingException { prepareConfigurationResponseOidc(this.buildResponseWithMissingJwksUri()); assertThatCode(() -> ReactiveJwtDecoders.fromIssuerLocation(this.issuer)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("The public JWK set URI must not be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("The public JWK set URI must not be null"); } // gh-7512 @@ -176,8 +160,7 @@ public class ReactiveJwtDecodersTests { throws JsonMappingException, JsonProcessingException { prepareConfigurationResponseOAuth2(this.buildResponseWithMissingJwksUri()); assertThatCode(() -> ReactiveJwtDecoders.fromIssuerLocation(this.issuer)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("The public JWK set URI must not be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessage("The public JWK set URI must not be null"); } @Test @@ -191,15 +174,13 @@ public class ReactiveJwtDecodersTests { @Test public void issuerWhenOidcFallbackResponseIsMalformedThenThrowsRuntimeException() { prepareConfigurationResponseOidc("malformed"); - assertThatCode(() -> ReactiveJwtDecoders.fromIssuerLocation(this.issuer)) - .isInstanceOf(RuntimeException.class); + assertThatCode(() -> ReactiveJwtDecoders.fromIssuerLocation(this.issuer)).isInstanceOf(RuntimeException.class); } @Test public void issuerWhenOAuth2ResponseIsMalformedThenThrowsRuntimeException() { prepareConfigurationResponseOAuth2("malformed"); - assertThatCode(() -> ReactiveJwtDecoders.fromIssuerLocation(this.issuer)) - .isInstanceOf(RuntimeException.class); + assertThatCode(() -> ReactiveJwtDecoders.fromIssuerLocation(this.issuer)).isInstanceOf(RuntimeException.class); } @Test @@ -219,14 +200,14 @@ public class ReactiveJwtDecodersTests { @Test public void issuerWhenOAuth2RespondingIssuerMismatchesRequestedIssuerThenThrowsIllegalStateException() { - prepareConfigurationResponseOAuth2(String.format(DEFAULT_RESPONSE_TEMPLATE, this.issuer + "/wrong", this.issuer)); + prepareConfigurationResponseOAuth2( + String.format(DEFAULT_RESPONSE_TEMPLATE, this.issuer + "/wrong", this.issuer)); assertThatCode(() -> ReactiveJwtDecoders.fromIssuerLocation(this.issuer)) .isInstanceOf(IllegalStateException.class); } @Test - public void issuerWhenRequestedIssuerIsUnresponsiveThenThrowsIllegalArgumentException() - throws Exception { + public void issuerWhenRequestedIssuerIsUnresponsiveThenThrowsIllegalArgumentException() throws Exception { this.server.shutdown(); @@ -282,8 +263,7 @@ public class ReactiveJwtDecodersTests { @Override public MockResponse dispatch(RecordedRequest request) { return Optional.of(request).map(RecordedRequest::getRequestUrl).map(HttpUrl::toString) - .map(responses::get) - .orElse(new MockResponse().setResponseCode(404)); + .map(responses::get).orElse(new MockResponse().setResponseCode(404)); } }; this.server.setDispatcher(dispatcher); @@ -295,14 +275,12 @@ public class ReactiveJwtDecodersTests { private String oidc() { URI uri = URI.create(this.issuer); - return UriComponentsBuilder.fromUri(uri) - .replacePath(uri.getPath() + OIDC_METADATA_PATH).toUriString(); + return UriComponentsBuilder.fromUri(uri).replacePath(uri.getPath() + OIDC_METADATA_PATH).toUriString(); } private String oauth() { URI uri = URI.create(this.issuer); - return UriComponentsBuilder.fromUri(uri) - .replacePath(OAUTH_METADATA_PATH + uri.getPath()).toUriString(); + return UriComponentsBuilder.fromUri(uri).replacePath(OAUTH_METADATA_PATH + uri.getPath()).toUriString(); } private String jwks() { @@ -310,16 +288,16 @@ public class ReactiveJwtDecodersTests { } private MockResponse response(String body) { - return new MockResponse() - .setBody(body) - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + return new MockResponse().setBody(body).setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); } public String buildResponseWithMissingJwksUri() throws JsonMappingException, JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); Map response = mapper.readValue(DEFAULT_RESPONSE_TEMPLATE, - new TypeReference>(){}); + new TypeReference>() { + }); response.remove("jwks_uri"); return mapper.writeValueAsString(response); } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/ReactiveRemoteJWKSourceTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/ReactiveRemoteJWKSourceTests.java index d5551e1d68..15d952ed10 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/ReactiveRemoteJWKSourceTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/ReactiveRemoteJWKSourceTests.java @@ -42,6 +42,7 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class ReactiveRemoteJWKSourceTests { + @Mock private JWKMatcher matcher; @@ -51,40 +52,23 @@ public class ReactiveRemoteJWKSourceTests { private MockWebServer server; - private String keys = "{\n" - + " \"keys\": [\n" - + " {\n" - + " \"alg\": \"RS256\", \n" + private String keys = "{\n" + " \"keys\": [\n" + " {\n" + " \"alg\": \"RS256\", \n" + " \"e\": \"AQAB\", \n" + " \"kid\": \"1923397381d9574bb873202a90c32b7ceeaed027\", \n" + " \"kty\": \"RSA\", \n" + " \"n\": \"m4I5Dk5GnbzzUtqaljDVbpMONi1JLNJ8ZuXE8VvjCAVebDg5vTYhQ33jUwGgbn1wFmytUMgMmvK8A8Gpshl0sO2GBIZoh6_pwLrk657ZEtv-hx9fYKnzwyrfHqxtSswMAyr7XtKl8Ha1I03uFMSaYaaBTwVXCHByhzr4PVXfKAYJNbbcteUZfE8ODlBQkjQLI0IB78Nu8XIRrdzTF_5LCuM6rLUNtX6_KdzPpeX9KEtB7OBAfkdZEtBzGI-aYNLtIaL4qO6cVxBeVDLMoj9kVsRPylrwhEFQcGOjtJhwJwXFzTMZVhkiLFCHxZkkjoMrK5osSRlhduuGI9ot8XTUKQ\", \n" - + " \"use\": \"sig\"\n" - + " }, \n" - + " {\n" - + " \"alg\": \"RS256\", \n" + + " \"use\": \"sig\"\n" + " }, \n" + " {\n" + " \"alg\": \"RS256\", \n" + " \"e\": \"AQAB\", \n" + " \"kid\": \"7ddf54d3032d1f0d48c3618892ca74c1ac30ad77\", \n" + " \"kty\": \"RSA\", \n" + " \"n\": \"yLlYyux949b7qS-DdqTNjdZb4NtqiNH-Jt7DtRxmfW9XZLOQ6Q2NYgmPe9hyy5GHG7W3zsd6Q-rzq5eGRNEUx1767K1dS5PtkVWPiPG_M7rDqCu3HsLmKQKhRjHYaCWl5NuiMB5mXoPhSwrHd2yeGE7QHIV7_CiQFc1xQsXeiC-nTeJohJO3HI97w0GXE8pHspLYq9oG87f5IHxFr89abmwRug-D7QWQyW5b4doe4ZL-52J-8WHd52kGrGfu4QyV83oAad3I_9Q-yiWOXUr_0GIrzz4_-u5HgqYexnodFhZZSaKuRSg_b5qCnPhW8gBDLAHkmQzQMaWsN14L0pokbQ\", \n" - + " \"use\": \"sig\"\n" - + " }\n" - + " ]\n" - + "}\n"; + + " \"use\": \"sig\"\n" + " }\n" + " ]\n" + "}\n"; - - private String keys2 = "{\n" - + " \"keys\": [\n" - + " {\n" - + " \"alg\": \"RS256\", \n" - + " \"e\": \"AQAB\", \n" - + " \"kid\": \"rotated\", \n" + private String keys2 = "{\n" + " \"keys\": [\n" + " {\n" + " \"alg\": \"RS256\", \n" + + " \"e\": \"AQAB\", \n" + " \"kid\": \"rotated\", \n" + " \"kty\": \"RSA\", \n" + " \"n\": \"m4I5Dk5GnbzzUtqaljDVbpMONi1JLNJ8ZuXE8VvjCAVebDg5vTYhQ33jUwGgbn1wFmytUMgMmvK8A8Gpshl0sO2GBIZoh6_pwLrk657ZEtv-hx9fYKnzwyrfHqxtSswMAyr7XtKl8Ha1I03uFMSaYaaBTwVXCHByhzr4PVXfKAYJNbbcteUZfE8ODlBQkjQLI0IB78Nu8XIRrdzTF_5LCuM6rLUNtX6_KdzPpeX9KEtB7OBAfkdZEtBzGI-aYNLtIaL4qO6cVxBeVDLMoj9kVsRPylrwhEFQcGOjtJhwJwXFzTMZVhkiLFCHxZkkjoMrK5osSRlhduuGI9ot8XTUKQ\", \n" - + " \"use\": \"sig\"\n" - + " }\n" - + " ]\n" - + "}\n"; + + " \"use\": \"sig\"\n" + " }\n" + " ]\n" + "}\n"; @Before public void setup() { @@ -162,4 +146,5 @@ public class ReactiveRemoteJWKSourceTests { assertThat(this.source.get(this.selector).block()).isEmpty(); } + } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/TestJwts.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/TestJwts.java index b253a79616..8cb46904ca 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/TestJwts.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/TestJwts.java @@ -20,21 +20,15 @@ import java.time.Instant; import java.util.Arrays; public class TestJwts { + public static Jwt.Builder jwt() { - return Jwt.withTokenValue("token") - .header("alg", "none") - .audience(Arrays.asList("https://audience.example.org")) - .expiresAt(Instant.MAX) - .issuedAt(Instant.MIN) - .issuer("https://issuer.example.org") - .jti("jti") - .notBefore(Instant.MIN) - .subject("mock-test-subject"); + return Jwt.withTokenValue("token").header("alg", "none").audience(Arrays.asList("https://audience.example.org")) + .expiresAt(Instant.MAX).issuedAt(Instant.MIN).issuer("https://issuer.example.org").jti("jti") + .notBefore(Instant.MIN).subject("mock-test-subject"); } public static Jwt user() { - return jwt() - .claim("sub", "mock-test-subject") - .build(); + return jwt().claim("sub", "mock-test-subject").build(); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenAuthenticationToken.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenAuthenticationToken.java index 6f12be55db..a1b6ecc0e7 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenAuthenticationToken.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenAuthenticationToken.java @@ -27,22 +27,23 @@ import org.springframework.util.Assert; /** * An {@link Authentication} that contains a - * Bearer Token. + * Bearer + * Token. * - * Used by {@link BearerTokenAuthenticationFilter} to prepare an authentication attempt and supported - * by {@link JwtAuthenticationProvider}. + * Used by {@link BearerTokenAuthenticationFilter} to prepare an authentication attempt + * and supported by {@link JwtAuthenticationProvider}. * * @author Josh Cummings * @since 5.1 */ public class BearerTokenAuthenticationToken extends AbstractAuthenticationToken { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private String token; /** * Create a {@code BearerTokenAuthenticationToken} using the provided parameter(s) - * * @param token - the bearer token */ public BearerTokenAuthenticationToken(String token) { @@ -54,8 +55,11 @@ public class BearerTokenAuthenticationToken extends AbstractAuthenticationToken } /** - * Get the Bearer Token - * @return the token that proves the caller's authority to perform the {@link javax.servlet.http.HttpServletRequest} + * Get the + * Bearer + * Token + * @return the token that proves the caller's authority to perform the + * {@link javax.servlet.http.HttpServletRequest} */ public String getToken() { return this.token; @@ -76,4 +80,5 @@ public class BearerTokenAuthenticationToken extends AbstractAuthenticationToken public Object getPrincipal() { return this.getToken(); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenError.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenError.java index 26f0db3e78..59fe9f399c 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenError.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenError.java @@ -21,14 +21,16 @@ import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.util.Assert; /** - * A representation of a Bearer Token Error. + * A representation of a + * Bearer Token + * Error. * * @author Vedran Pavic * @author Josh Cummings * @since 5.1 * @see BearerTokenErrorCodes - * @see RFC 6750 Section 3: The WWW-Authenticate - * Response Header Field + * @see RFC 6750 + * Section 3: The WWW-Authenticate Response Header Field */ public final class BearerTokenError extends OAuth2Error { @@ -38,7 +40,6 @@ public final class BearerTokenError extends OAuth2Error { /** * Create a {@code BearerTokenError} using the provided parameters - * * @param errorCode the error code * @param httpStatus the HTTP status */ @@ -48,14 +49,14 @@ public final class BearerTokenError extends OAuth2Error { /** * Create a {@code BearerTokenError} using the provided parameters - * * @param errorCode the error code * @param httpStatus the HTTP status * @param description the description * @param errorUri the URI * @param scope the scope */ - public BearerTokenError(String errorCode, HttpStatus httpStatus, String description, String errorUri, String scope) { + public BearerTokenError(String errorCode, HttpStatus httpStatus, String description, String errorUri, + String scope) { super(errorCode, description, errorUri); Assert.notNull(httpStatus, "httpStatus cannot be null"); @@ -65,8 +66,7 @@ public final class BearerTokenError extends OAuth2Error { "errorCode contains invalid ASCII characters, it must conform to RFC 6750"); Assert.isTrue(isErrorUriValid(errorUri), "errorUri contains invalid ASCII characters, it must conform to RFC 6750"); - Assert.isTrue(isScopeValid(scope), - "scope contains invalid ASCII characters, it must conform to RFC 6750"); + Assert.isTrue(isScopeValid(scope), "scope contains invalid ASCII characters, it must conform to RFC 6750"); this.httpStatus = httpStatus; this.scope = scope; @@ -89,37 +89,27 @@ public final class BearerTokenError extends OAuth2Error { } private static boolean isDescriptionValid(String description) { - return description == null || - description.chars().allMatch(c -> - withinTheRangeOf(c, 0x20, 0x21) || - withinTheRangeOf(c, 0x23, 0x5B) || - withinTheRangeOf(c, 0x5D, 0x7E)); + return description == null || description.chars().allMatch(c -> withinTheRangeOf(c, 0x20, 0x21) + || withinTheRangeOf(c, 0x23, 0x5B) || withinTheRangeOf(c, 0x5D, 0x7E)); } private static boolean isErrorCodeValid(String errorCode) { - return errorCode.chars().allMatch(c -> - withinTheRangeOf(c, 0x20, 0x21) || - withinTheRangeOf(c, 0x23, 0x5B) || - withinTheRangeOf(c, 0x5D, 0x7E)); + return errorCode.chars().allMatch(c -> withinTheRangeOf(c, 0x20, 0x21) || withinTheRangeOf(c, 0x23, 0x5B) + || withinTheRangeOf(c, 0x5D, 0x7E)); } private static boolean isErrorUriValid(String errorUri) { - return errorUri == null || - errorUri.chars().allMatch(c -> - c == 0x21 || - withinTheRangeOf(c, 0x23, 0x5B) || - withinTheRangeOf(c, 0x5D, 0x7E)); + return errorUri == null || errorUri.chars() + .allMatch(c -> c == 0x21 || withinTheRangeOf(c, 0x23, 0x5B) || withinTheRangeOf(c, 0x5D, 0x7E)); } private static boolean isScopeValid(String scope) { - return scope == null || - scope.chars().allMatch(c -> - withinTheRangeOf(c, 0x20, 0x21) || - withinTheRangeOf(c, 0x23, 0x5B) || - withinTheRangeOf(c, 0x5D, 0x7E)); + return scope == null || scope.chars().allMatch(c -> withinTheRangeOf(c, 0x20, 0x21) + || withinTheRangeOf(c, 0x23, 0x5B) || withinTheRangeOf(c, 0x5D, 0x7E)); } private static boolean withinTheRangeOf(int c, int min, int max) { return c >= min && c <= max; } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenErrorCodes.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenErrorCodes.java index 0e74b2d6f1..84457dc674 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenErrorCodes.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenErrorCodes.java @@ -17,29 +17,32 @@ package org.springframework.security.oauth2.server.resource; /** - * Standard error codes defined by the OAuth 2.0 Authorization Framework: Bearer Token Usage. + * Standard error codes defined by the OAuth 2.0 Authorization Framework: Bearer Token + * Usage. * * @author Vedran Pavic * @since 5.1 - * @see RFC 6750 Section 3.1: Error Codes + * @see RFC 6750 + * Section 3.1: Error Codes */ public interface BearerTokenErrorCodes { /** - * {@code invalid_request} - The request is missing a required parameter, includes an unsupported parameter or - * parameter value, repeats the same parameter, uses more than one method for including an access token, or is - * otherwise malformed. + * {@code invalid_request} - The request is missing a required parameter, includes an + * unsupported parameter or parameter value, repeats the same parameter, uses more + * than one method for including an access token, or is otherwise malformed. */ String INVALID_REQUEST = "invalid_request"; /** - * {@code invalid_token} - The access token provided is expired, revoked, malformed, or invalid for other - * reasons. + * {@code invalid_token} - The access token provided is expired, revoked, malformed, + * or invalid for other reasons. */ String INVALID_TOKEN = "invalid_token"; /** - * {@code insufficient_scope} - The request requires higher privileges than provided by the access token. + * {@code insufficient_scope} - The request requires higher privileges than provided + * by the access token. */ String INSUFFICIENT_SCOPE = "insufficient_scope"; diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenErrors.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenErrors.java index 7bbd5387d4..5a2b50cfbb 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenErrors.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/BearerTokenErrors.java @@ -23,73 +23,72 @@ import static org.springframework.security.oauth2.server.resource.BearerTokenErr import static org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes.INVALID_TOKEN; /** - * A factory for creating {@link BearerTokenError} instances that correspond to the registered - * Bearer Token Error Codes. + * A factory for creating {@link BearerTokenError} instances that correspond to the + * registered Bearer Token Error + * Codes. * * @author Josh Cummings * @since 5.3 */ public final class BearerTokenErrors { + private static final BearerTokenError DEFAULT_INVALID_REQUEST = invalidRequest("Invalid request"); + private static final BearerTokenError DEFAULT_INVALID_TOKEN = invalidToken("Invalid token"); + private static final BearerTokenError DEFAULT_INSUFFICIENT_SCOPE = insufficientScope("Insufficient scope", null); private static final String DEFAULT_URI = "https://tools.ietf.org/html/rfc6750#section-3.1"; /** * Create a {@link BearerTokenError} caused by an invalid request - * * @param message a description of the error * @return a {@link BearerTokenError} */ public static BearerTokenError invalidRequest(String message) { try { - return new BearerTokenError(INVALID_REQUEST, - HttpStatus.BAD_REQUEST, - message, - DEFAULT_URI); - } catch (IllegalArgumentException malformed) { - // some third-party library error messages are not suitable for RFC 6750's error message charset + return new BearerTokenError(INVALID_REQUEST, HttpStatus.BAD_REQUEST, message, DEFAULT_URI); + } + catch (IllegalArgumentException malformed) { + // some third-party library error messages are not suitable for RFC 6750's + // error message charset return DEFAULT_INVALID_REQUEST; } } /** * Create a {@link BearerTokenError} caused by an invalid token - * * @param message a description of the error * @return a {@link BearerTokenError} */ public static BearerTokenError invalidToken(String message) { try { - return new BearerTokenError(INVALID_TOKEN, - HttpStatus.UNAUTHORIZED, - message, - DEFAULT_URI); - } catch (IllegalArgumentException malformed) { - // some third-party library error messages are not suitable for RFC 6750's error message charset + return new BearerTokenError(INVALID_TOKEN, HttpStatus.UNAUTHORIZED, message, DEFAULT_URI); + } + catch (IllegalArgumentException malformed) { + // some third-party library error messages are not suitable for RFC 6750's + // error message charset return DEFAULT_INVALID_TOKEN; } } /** * Create a {@link BearerTokenError} caused by an invalid token - * * @param scope the scope attribute to use in the error * @return a {@link BearerTokenError} */ public static BearerTokenError insufficientScope(String message, String scope) { try { - return new BearerTokenError(INSUFFICIENT_SCOPE, - HttpStatus.FORBIDDEN, - message, - DEFAULT_URI, - scope); - } catch (IllegalArgumentException malformed) { - // some third-party library error messages are not suitable for RFC 6750's error message charset + return new BearerTokenError(INSUFFICIENT_SCOPE, HttpStatus.FORBIDDEN, message, DEFAULT_URI, scope); + } + catch (IllegalArgumentException malformed) { + // some third-party library error messages are not suitable for RFC 6750's + // error message charset return DEFAULT_INSUFFICIENT_SCOPE; } } - private BearerTokenErrors() {} + private BearerTokenErrors() { + } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/InvalidBearerTokenException.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/InvalidBearerTokenException.java index 47ac1c72be..e3ba596dab 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/InvalidBearerTokenException.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/InvalidBearerTokenException.java @@ -32,9 +32,9 @@ public class InvalidBearerTokenException extends OAuth2AuthenticationException { * Construct an instance of {@link InvalidBearerTokenException} given the provided * description. * - * The description will be wrapped into an {@link org.springframework.security.oauth2.core.OAuth2Error} - * instance as the {@code error_description}. - * + * The description will be wrapped into an + * {@link org.springframework.security.oauth2.core.OAuth2Error} instance as the + * {@code error_description}. * @param description the description */ public InvalidBearerTokenException(String description) { @@ -45,13 +45,14 @@ public class InvalidBearerTokenException extends OAuth2AuthenticationException { * Construct an instance of {@link InvalidBearerTokenException} given the provided * description and cause * - * The description will be wrapped into an {@link org.springframework.security.oauth2.core.OAuth2Error} - * instance as the {@code error_description}. - * + * The description will be wrapped into an + * {@link org.springframework.security.oauth2.core.OAuth2Error} instance as the + * {@code error_description}. * @param description the description * @param cause the causing exception */ public InvalidBearerTokenException(String description, Throwable cause) { super(invalidToken(description), cause); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/AbstractOAuth2TokenAuthenticationToken.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/AbstractOAuth2TokenAuthenticationToken.java index d6d63b6b92..4a9b3edf39 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/AbstractOAuth2TokenAuthenticationToken.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/AbstractOAuth2TokenAuthenticationToken.java @@ -28,25 +28,31 @@ import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.util.Assert; /** - * Base class for {@link AbstractAuthenticationToken} implementations - * that expose common attributes between different OAuth 2.0 Access Token Formats. + * Base class for {@link AbstractAuthenticationToken} implementations that expose common + * attributes between different OAuth 2.0 Access Token Formats. * *

        * For example, a {@link Jwt} could expose its {@link Jwt#getClaims() claims} via * {@link #getTokenAttributes()} or an "Introspected" OAuth 2.0 Access Token - * could expose the attributes of the Introspection Response via {@link #getTokenAttributes()}. + * could expose the attributes of the Introspection Response via + * {@link #getTokenAttributes()}. * * @author Joe Grandja * @since 5.1 * @see OAuth2AccessToken * @see Jwt - * @see 2.2 Introspection Response + * @see 2.2 + * Introspection Response */ -public abstract class AbstractOAuth2TokenAuthenticationToken extends AbstractAuthenticationToken { +public abstract class AbstractOAuth2TokenAuthenticationToken + extends AbstractAuthenticationToken { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private Object principal; + private Object credentials; + private T token; /** @@ -59,20 +65,14 @@ public abstract class AbstractOAuth2TokenAuthenticationToken authorities) { + protected AbstractOAuth2TokenAuthenticationToken(T token, Collection authorities) { this(token, token, token, authorities); } - protected AbstractOAuth2TokenAuthenticationToken( - T token, - Object principal, - Object credentials, + protected AbstractOAuth2TokenAuthenticationToken(T token, Object principal, Object credentials, Collection authorities) { super(authorities); @@ -108,8 +108,8 @@ public abstract class AbstractOAuth2TokenAuthenticationToken getTokenAttributes(); + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthentication.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthentication.java index ca0f1ee334..18d2325e2d 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthentication.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthentication.java @@ -28,8 +28,8 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; import org.springframework.util.Assert; /** - * An {@link org.springframework.security.core.Authentication} token that represents a successful authentication as - * obtained through a bearer token. + * An {@link org.springframework.security.core.Authentication} token that represents a + * successful authentication as obtained through a bearer token. * * @author Josh Cummings * @since 5.2 @@ -43,7 +43,6 @@ public class BearerTokenAuthentication extends AbstractOAuth2TokenAuthentication /** * Constructs a {@link BearerTokenAuthentication} with the provided arguments - * * @param principal The OAuth 2.0 attributes * @param credentials The verified token * @param authorities The authorities associated with the given token @@ -52,7 +51,8 @@ public class BearerTokenAuthentication extends AbstractOAuth2TokenAuthentication Collection authorities) { super(credentials, principal, credentials, authorities); - Assert.isTrue(credentials.getTokenType() == OAuth2AccessToken.TokenType.BEARER, "credentials must be a bearer token"); + Assert.isTrue(credentials.getTokenType() == OAuth2AccessToken.TokenType.BEARER, + "credentials must be a bearer token"); this.attributes = Collections.unmodifiableMap(new LinkedHashMap<>(principal.getAttributes())); setAuthenticated(true); } @@ -64,4 +64,5 @@ public class BearerTokenAuthentication extends AbstractOAuth2TokenAuthentication public Map getTokenAttributes() { return this.attributes; } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationConverter.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationConverter.java index 4b8171e8cb..9cd153f925 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationConverter.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationConverter.java @@ -32,8 +32,8 @@ import org.springframework.util.Assert; * @since 5.1 */ public class JwtAuthenticationConverter implements Converter { - private Converter> jwtGrantedAuthoritiesConverter - = new JwtGrantedAuthoritiesConverter(); + + private Converter> jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); private String principalClaimName; @@ -49,8 +49,8 @@ public class JwtAuthenticationConverter implements Converter> jwtGrantedAuthoritiesConverter) { + public void setJwtGrantedAuthoritiesConverter( + Converter> jwtGrantedAuthoritiesConverter) { Assert.notNull(jwtGrantedAuthoritiesConverter, "jwtGrantedAuthoritiesConverter cannot be null"); this.jwtGrantedAuthoritiesConverter = jwtGrantedAuthoritiesConverter; } /** - * Sets the principal claim name. - * Defaults to {@link JwtClaimNames#SUB}. - * + * Sets the principal claim name. Defaults to {@link JwtClaimNames#SUB}. * @param principalClaimName The principal claim name * @since 5.4 */ @@ -86,4 +84,5 @@ public class JwtAuthenticationConverter implements ConverterBearer Tokens - * for protecting OAuth 2.0 Resource Servers. + * Bearer + * Tokens for protecting OAuth 2.0 Resource Servers. *

        *

        - * This {@link AuthenticationProvider} is responsible for decoding and verifying a {@link Jwt}-encoded access token, - * returning its claims set as part of the {@link Authentication} statement. + * This {@link AuthenticationProvider} is responsible for decoding and verifying a + * {@link Jwt}-encoded access token, returning its claims set as part of the + * {@link Authentication} statement. *

        *

        - * Scopes are translated into {@link GrantedAuthority}s according to the following algorithm: + * Scopes are translated into {@link GrantedAuthority}s according to the following + * algorithm: * - * 1. If there is a "scope" or "scp" attribute, then - * if a {@link String}, then split by spaces and return, or - * if a {@link Collection}, then simply return - * 2. Take the resulting {@link Collection} of {@link String}s and prepend the "SCOPE_" keyword, adding - * as {@link GrantedAuthority}s. + * 1. If there is a "scope" or "scp" attribute, then if a {@link String}, then split by + * spaces and return, or if a {@link Collection}, then simply return 2. Take the resulting + * {@link Collection} of {@link String}s and prepend the "SCOPE_" keyword, adding as + * {@link GrantedAuthority}s. * * @author Josh Cummings * @author Joe Grandja @@ -57,6 +58,7 @@ import org.springframework.util.Assert; * @see JwtDecoder */ public final class JwtAuthenticationProvider implements AuthenticationProvider { + private final JwtDecoder jwtDecoder; private Converter jwtAuthenticationConverter = new JwtAuthenticationConverter(); @@ -68,10 +70,9 @@ public final class JwtAuthenticationProvider implements AuthenticationProvider { /** * Decode and validate the - * Bearer Token. - * + * Bearer + * Token. * @param authentication the authentication request object. - * * @return A successful authentication * @throws AuthenticationException if authentication failed for some reason */ @@ -82,9 +83,11 @@ public final class JwtAuthenticationProvider implements AuthenticationProvider { Jwt jwt; try { jwt = this.jwtDecoder.decode(bearer.getToken()); - } catch (BadJwtException failed) { + } + catch (BadJwtException failed) { throw new InvalidBearerTokenException(failed.getMessage(), failed); - } catch (JwtException failed) { + } + catch (JwtException failed) { throw new AuthenticationServiceException(failed.getMessage(), failed); } @@ -108,4 +111,5 @@ public final class JwtAuthenticationProvider implements AuthenticationProvider { Assert.notNull(jwtAuthenticationConverter, "jwtAuthenticationConverter cannot be null"); this.jwtAuthenticationConverter = jwtAuthenticationConverter; } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationToken.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationToken.java index 44edd9bb55..323880c335 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationToken.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationToken.java @@ -24,8 +24,8 @@ import org.springframework.security.core.Transient; import org.springframework.security.oauth2.jwt.Jwt; /** - * An implementation of an {@link AbstractOAuth2TokenAuthenticationToken} - * representing a {@link Jwt} {@code Authentication}. + * An implementation of an {@link AbstractOAuth2TokenAuthenticationToken} representing a + * {@link Jwt} {@code Authentication}. * * @author Joe Grandja * @since 5.1 @@ -34,13 +34,13 @@ import org.springframework.security.oauth2.jwt.Jwt; */ @Transient public class JwtAuthenticationToken extends AbstractOAuth2TokenAuthenticationToken { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private final String name; /** * Constructs a {@code JwtAuthenticationToken} using the provided parameters. - * * @param jwt the JWT */ public JwtAuthenticationToken(Jwt jwt) { @@ -50,7 +50,6 @@ public class JwtAuthenticationToken extends AbstractOAuth2TokenAuthenticationTok /** * Constructs a {@code JwtAuthenticationToken} using the provided parameters. - * * @param jwt the JWT * @param authorities the authorities assigned to the JWT */ @@ -62,7 +61,6 @@ public class JwtAuthenticationToken extends AbstractOAuth2TokenAuthenticationTok /** * Constructs a {@code JwtAuthenticationToken} using the provided parameters. - * * @param jwt the JWT * @param authorities the authorities assigned to the JWT * @param name the principal name @@ -88,4 +86,5 @@ public class JwtAuthenticationToken extends AbstractOAuth2TokenAuthenticationTok public String getName() { return this.name; } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtBearerTokenAuthenticationConverter.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtBearerTokenAuthenticationConverter.java index 7cd7fd518a..726c98a61a 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtBearerTokenAuthenticationConverter.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtBearerTokenAuthenticationConverter.java @@ -28,25 +28,29 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; import org.springframework.security.oauth2.jwt.Jwt; /** - * A {@link Converter} that takes a {@link Jwt} and converts it into a {@link BearerTokenAuthentication}. + * A {@link Converter} that takes a {@link Jwt} and converts it into a + * {@link BearerTokenAuthentication}. * - * In the process, it will attempt to parse either the "scope" or "scp" attribute, whichever it finds first. + * In the process, it will attempt to parse either the "scope" or "scp" attribute, + * whichever it finds first. * - * It's not intended that this implementation be configured since it is simply an adapter. If you are using, - * for example, a custom {@link JwtGrantedAuthoritiesConverter}, then it's recommended that you simply - * create your own {@link Converter} that delegates to your custom {@link JwtGrantedAuthoritiesConverter} - * and instantiates the appropriate {@link BearerTokenAuthentication}. + * It's not intended that this implementation be configured since it is simply an adapter. + * If you are using, for example, a custom {@link JwtGrantedAuthoritiesConverter}, then + * it's recommended that you simply create your own {@link Converter} that delegates to + * your custom {@link JwtGrantedAuthoritiesConverter} and instantiates the appropriate + * {@link BearerTokenAuthentication}. * * @author Josh Cummings * @since 5.2 */ public final class JwtBearerTokenAuthenticationConverter implements Converter { + private final JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); @Override public AbstractAuthenticationToken convert(Jwt jwt) { - OAuth2AccessToken accessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt()); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, jwt.getTokenValue(), + jwt.getIssuedAt(), jwt.getExpiresAt()); Map attributes = jwt.getClaims(); AbstractAuthenticationToken token = this.jwtAuthenticationConverter.convert(jwt); @@ -55,4 +59,5 @@ public final class JwtBearerTokenAuthenticationConverter implements Converter> { + private static final String DEFAULT_AUTHORITY_PREFIX = "SCOPE_"; - private static final Collection WELL_KNOWN_AUTHORITIES_CLAIM_NAMES = - Arrays.asList("scope", "scp"); + private static final Collection WELL_KNOWN_AUTHORITIES_CLAIM_NAMES = Arrays.asList("scope", "scp"); private String authorityPrefix = DEFAULT_AUTHORITY_PREFIX; @@ -47,7 +47,6 @@ public final class JwtGrantedAuthoritiesConverter implements Converter) authorities; } return Collections.emptyList(); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java index 97cc3d3fe9..86db91c361 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolver.java @@ -39,27 +39,33 @@ import org.springframework.security.oauth2.server.resource.web.DefaultBearerToke import org.springframework.util.Assert; /** - * An implementation of {@link AuthenticationManagerResolver} that resolves a JWT-based {@link AuthenticationManager} - * based on the Issuer in a - * signed JWT (JWS). + * An implementation of {@link AuthenticationManagerResolver} that resolves a JWT-based + * {@link AuthenticationManager} based on the Issuer in + * a signed JWT (JWS). * - * To use, this class must be able to determine whether or not the `iss` claim is trusted. Recall that - * anyone can stand up an authorization server and issue valid tokens to a resource server. The simplest way - * to achieve this is to supply a list of trusted issuers in the constructor. + * To use, this class must be able to determine whether or not the `iss` claim is trusted. + * Recall that anyone can stand up an authorization server and issue valid tokens to a + * resource server. The simplest way to achieve this is to supply a list of trusted + * issuers in the constructor. * - * This class derives the Issuer from the `iss` claim found in the {@link HttpServletRequest}'s - * Bearer Token. + * This class derives the Issuer from the `iss` claim found in the + * {@link HttpServletRequest}'s + * Bearer + * Token. * * @author Josh Cummings * @since 5.3 */ public final class JwtIssuerAuthenticationManagerResolver implements AuthenticationManagerResolver { + private final AuthenticationManagerResolver issuerAuthenticationManagerResolver; + private final Converter issuerConverter = new JwtClaimIssuerConverter(); /** - * Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided parameters - * + * Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided + * parameters * @param trustedIssuers a list of trusted issuers */ public JwtIssuerAuthenticationManagerResolver(String... trustedIssuers) { @@ -67,22 +73,23 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat } /** - * Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided parameters - * + * Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided + * parameters * @param trustedIssuers a list of trusted issuers */ public JwtIssuerAuthenticationManagerResolver(Collection trustedIssuers) { Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty"); - this.issuerAuthenticationManagerResolver = - new TrustedIssuerJwtAuthenticationManagerResolver - (Collections.unmodifiableCollection(trustedIssuers)::contains); + this.issuerAuthenticationManagerResolver = new TrustedIssuerJwtAuthenticationManagerResolver( + Collections.unmodifiableCollection(trustedIssuers)::contains); } /** - * Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided parameters + * Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided + * parameters * - * Note that the {@link AuthenticationManagerResolver} provided in this constructor will need to - * verify that the issuer is trusted. This should be done via an allowlist. + * Note that the {@link AuthenticationManagerResolver} provided in this constructor + * will need to verify that the issuer is trusted. This should be done via an + * allowlist. * * One way to achieve this is with a {@link Map} where the keys are the known issuers: *

        @@ -94,19 +101,20 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat
         	 * 
        * * The keys in the {@link Map} are the allowed issuers. - * - * @param issuerAuthenticationManagerResolver a strategy for resolving the {@link AuthenticationManager} by the issuer + * @param issuerAuthenticationManagerResolver a strategy for resolving the + * {@link AuthenticationManager} by the issuer */ - public JwtIssuerAuthenticationManagerResolver(AuthenticationManagerResolver issuerAuthenticationManagerResolver) { + public JwtIssuerAuthenticationManagerResolver( + AuthenticationManagerResolver issuerAuthenticationManagerResolver) { Assert.notNull(issuerAuthenticationManagerResolver, "issuerAuthenticationManagerResolver cannot be null"); this.issuerAuthenticationManagerResolver = issuerAuthenticationManagerResolver; } /** - * Return an {@link AuthenticationManager} based off of the `iss` claim found in the request's bearer token - * - * @throws OAuth2AuthenticationException if the bearer token is malformed or an {@link AuthenticationManager} - * can't be derived from the issuer + * Return an {@link AuthenticationManager} based off of the `iss` claim found in the + * request's bearer token + * @throws OAuth2AuthenticationException if the bearer token is malformed or an + * {@link AuthenticationManager} can't be derived from the issuer */ @Override public AuthenticationManager resolve(HttpServletRequest request) { @@ -118,8 +126,7 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat return authenticationManager; } - private static class JwtClaimIssuerConverter - implements Converter { + private static class JwtClaimIssuerConverter implements Converter { private final BearerTokenResolver resolver = new DefaultBearerTokenResolver(); @@ -131,17 +138,20 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat if (issuer != null) { return issuer; } - } catch (Exception e) { + } + catch (Exception e) { throw new InvalidBearerTokenException(e.getMessage(), e); } throw new InvalidBearerTokenException("Missing issuer"); } + } private static class TrustedIssuerJwtAuthenticationManagerResolver implements AuthenticationManagerResolver { private final Map authenticationManagers = new ConcurrentHashMap<>(); + private final Predicate trustedIssuer; TrustedIssuerJwtAuthenticationManagerResolver(Predicate trustedIssuer) { @@ -158,5 +168,7 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat } return null; } + } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java index 0328d5ae3b..aa72fcd8c5 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java @@ -41,17 +41,20 @@ import org.springframework.util.Assert; import org.springframework.web.server.ServerWebExchange; /** - * An implementation of {@link ReactiveAuthenticationManagerResolver} that resolves a JWT-based - * {@link ReactiveAuthenticationManager} based on the - * Issuer in a - * signed JWT (JWS). + * An implementation of {@link ReactiveAuthenticationManagerResolver} that resolves a + * JWT-based {@link ReactiveAuthenticationManager} based on the Issuer in + * a signed JWT (JWS). * - * To use, this class must be able to determine whether or not the `iss` claim is trusted. Recall that - * anyone can stand up an authorization server and issue valid tokens to a resource server. The simplest way - * to achieve this is to supply a list of trusted issuers in the constructor. + * To use, this class must be able to determine whether or not the `iss` claim is trusted. + * Recall that anyone can stand up an authorization server and issue valid tokens to a + * resource server. The simplest way to achieve this is to supply a list of trusted + * issuers in the constructor. * - * This class derives the Issuer from the `iss` claim found in the {@link ServerWebExchange}'s - * Bearer Token. + * This class derives the Issuer from the `iss` claim found in the + * {@link ServerWebExchange}'s + * Bearer + * Token. * * @author Josh Cummings * @author Roman Matiushchenko @@ -61,11 +64,12 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver implements ReactiveAuthenticationManagerResolver { private final ReactiveAuthenticationManagerResolver issuerAuthenticationManagerResolver; + private final Converter> issuerConverter = new JwtClaimIssuerConverter(); /** - * Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the provided parameters - * + * Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the + * provided parameters * @param trustedIssuers a list of trusted issuers */ public JwtIssuerReactiveAuthenticationManagerResolver(String... trustedIssuers) { @@ -73,21 +77,23 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver } /** - * Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the provided parameters - * + * Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the + * provided parameters * @param trustedIssuers a collection of trusted issuers */ public JwtIssuerReactiveAuthenticationManagerResolver(Collection trustedIssuers) { Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty"); - this.issuerAuthenticationManagerResolver = - new TrustedIssuerJwtAuthenticationManagerResolver(new ArrayList<>(trustedIssuers)::contains); + this.issuerAuthenticationManagerResolver = new TrustedIssuerJwtAuthenticationManagerResolver( + new ArrayList<>(trustedIssuers)::contains); } /** - * Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the provided parameters + * Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the + * provided parameters * - * Note that the {@link ReactiveAuthenticationManagerResolver} provided in this constructor will need to - * verify that the issuer is trusted. This should be done via an allowed list of issuers. + * Note that the {@link ReactiveAuthenticationManagerResolver} provided in this + * constructor will need to verify that the issuer is trusted. This should be done via + * an allowed list of issuers. * * One way to achieve this is with a {@link Map} where the keys are the known issuers: *
        @@ -99,37 +105,32 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver
         	 * 
        * * The keys in the {@link Map} are the trusted issuers. - * - * @param issuerAuthenticationManagerResolver a strategy for resolving the {@link ReactiveAuthenticationManager} - * by the issuer + * @param issuerAuthenticationManagerResolver a strategy for resolving the + * {@link ReactiveAuthenticationManager} by the issuer */ - public JwtIssuerReactiveAuthenticationManagerResolver - (ReactiveAuthenticationManagerResolver issuerAuthenticationManagerResolver) { + public JwtIssuerReactiveAuthenticationManagerResolver( + ReactiveAuthenticationManagerResolver issuerAuthenticationManagerResolver) { Assert.notNull(issuerAuthenticationManagerResolver, "issuerAuthenticationManagerResolver cannot be null"); this.issuerAuthenticationManagerResolver = issuerAuthenticationManagerResolver; } /** - * Return an {@link AuthenticationManager} based off of the `iss` claim found in the request's bearer token - * - * @throws OAuth2AuthenticationException if the bearer token is malformed or an {@link ReactiveAuthenticationManager} - * can't be derived from the issuer + * Return an {@link AuthenticationManager} based off of the `iss` claim found in the + * request's bearer token + * @throws OAuth2AuthenticationException if the bearer token is malformed or an + * {@link ReactiveAuthenticationManager} can't be derived from the issuer */ @Override public Mono resolve(ServerWebExchange exchange) { return this.issuerConverter.convert(exchange) - .flatMap(issuer -> - this.issuerAuthenticationManagerResolver.resolve(issuer).switchIfEmpty( - Mono.error(() -> new InvalidBearerTokenException("Invalid issuer " + issuer))) - ); + .flatMap(issuer -> this.issuerAuthenticationManagerResolver.resolve(issuer) + .switchIfEmpty(Mono.error(() -> new InvalidBearerTokenException("Invalid issuer " + issuer)))); } - private static class JwtClaimIssuerConverter - implements Converter> { + private static class JwtClaimIssuerConverter implements Converter> { - private final ServerBearerTokenAuthenticationConverter converter = - new ServerBearerTokenAuthenticationConverter(); + private final ServerBearerTokenAuthenticationConverter converter = new ServerBearerTokenAuthenticationConverter(); @Override public Mono convert(@NonNull ServerWebExchange exchange) { @@ -139,21 +140,24 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver String issuer = JWTParser.parse(token.getToken()).getJWTClaimsSet().getIssuer(); if (issuer == null) { throw new InvalidBearerTokenException("Missing issuer"); - } else { + } + else { return issuer; } - } catch (Exception e) { - throw new InvalidBearerTokenException(e.getMessage(), e); + } + catch (Exception e) { + throw new InvalidBearerTokenException(e.getMessage(), e); } }); } + } private static class TrustedIssuerJwtAuthenticationManagerResolver implements ReactiveAuthenticationManagerResolver { - private final Map> authenticationManagers = - new ConcurrentHashMap<>(); + private final Map> authenticationManagers = new ConcurrentHashMap<>(); + private final Predicate trustedIssuer; TrustedIssuerJwtAuthenticationManagerResolver(Predicate trustedIssuer) { @@ -165,12 +169,12 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver if (!this.trustedIssuer.test(issuer)) { return Mono.empty(); } - return this.authenticationManagers.computeIfAbsent(issuer, k -> - Mono.fromCallable(() -> - new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation(k)) - ) - .subscribeOn(Schedulers.boundedElastic()) - .cache()); + return this.authenticationManagers.computeIfAbsent(issuer, + k -> Mono.fromCallable( + () -> new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation(k))) + .subscribeOn(Schedulers.boundedElastic()).cache()); } + } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtReactiveAuthenticationManager.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtReactiveAuthenticationManager.java index ab877b2181..a246841a66 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtReactiveAuthenticationManager.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtReactiveAuthenticationManager.java @@ -39,10 +39,11 @@ import org.springframework.util.Assert; * @since 5.1 */ public final class JwtReactiveAuthenticationManager implements ReactiveAuthenticationManager { + private final ReactiveJwtDecoder jwtDecoder; - private Converter> jwtAuthenticationConverter - = new ReactiveJwtAuthenticationConverterAdapter(new JwtAuthenticationConverter()); + private Converter> jwtAuthenticationConverter = new ReactiveJwtAuthenticationConverterAdapter( + new JwtAuthenticationConverter()); public JwtReactiveAuthenticationManager(ReactiveJwtDecoder jwtDecoder) { Assert.notNull(jwtDecoder, "jwtDecoder cannot be null"); @@ -51,19 +52,15 @@ public final class JwtReactiveAuthenticationManager implements ReactiveAuthentic @Override public Mono authenticate(Authentication authentication) { - return Mono.justOrEmpty(authentication) - .filter(a -> a instanceof BearerTokenAuthenticationToken) - .cast(BearerTokenAuthenticationToken.class) - .map(BearerTokenAuthenticationToken::getToken) - .flatMap(this.jwtDecoder::decode) - .flatMap(this.jwtAuthenticationConverter::convert) - .cast(Authentication.class) - .onErrorMap(JwtException.class, this::onError); + return Mono.justOrEmpty(authentication).filter(a -> a instanceof BearerTokenAuthenticationToken) + .cast(BearerTokenAuthenticationToken.class).map(BearerTokenAuthenticationToken::getToken) + .flatMap(this.jwtDecoder::decode).flatMap(this.jwtAuthenticationConverter::convert) + .cast(Authentication.class).onErrorMap(JwtException.class, this::onError); } /** - * Use the given {@link Converter} for converting a {@link Jwt} into an {@link AbstractAuthenticationToken}. - * + * Use the given {@link Converter} for converting a {@link Jwt} into an + * {@link AbstractAuthenticationToken}. * @param jwtAuthenticationConverter the {@link Converter} to use */ public void setJwtAuthenticationConverter( @@ -76,8 +73,10 @@ public final class JwtReactiveAuthenticationManager implements ReactiveAuthentic private AuthenticationException onError(JwtException e) { if (e instanceof BadJwtException) { return new InvalidBearerTokenException(e.getMessage(), e); - } else { + } + else { return new AuthenticationServiceException(e.getMessage(), e); } } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProvider.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProvider.java index f1818b73ac..698062b743 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProvider.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProvider.java @@ -38,20 +38,22 @@ import static org.springframework.security.oauth2.server.resource.introspection. /** * An {@link AuthenticationProvider} implementation for opaque - * Bearer Tokens, - * using an - * OAuth 2.0 Introspection Endpoint - * to check the token's validity and reveal its attributes. + * Bearer + * Tokens, using an + * OAuth 2.0 Introspection + * Endpoint to check the token's validity and reveal its attributes. *

        - * This {@link AuthenticationProvider} is responsible for introspecting and verifying an opaque access token, - * returning its attributes set as part of the {@link Authentication} statement. + * This {@link AuthenticationProvider} is responsible for introspecting and verifying an + * opaque access token, returning its attributes set as part of the {@link Authentication} + * statement. *

        - * Scopes are translated into {@link GrantedAuthority}s according to the following algorithm: + * Scopes are translated into {@link GrantedAuthority}s according to the following + * algorithm: *

          - *
        1. - * If there is a "scope" attribute, then convert to a {@link Collection} of {@link String}s. - *
        2. - * Take the resulting {@link Collection} and prepend the "SCOPE_" keyword to each element, adding as {@link GrantedAuthority}s. + *
        3. If there is a "scope" attribute, then convert to a {@link Collection} of + * {@link String}s. + *
        4. Take the resulting {@link Collection} and prepend the "SCOPE_" keyword to each + * element, adding as {@link GrantedAuthority}s. *
        * * @author Josh Cummings @@ -59,11 +61,11 @@ import static org.springframework.security.oauth2.server.resource.introspection. * @see AuthenticationProvider */ public final class OpaqueTokenAuthenticationProvider implements AuthenticationProvider { + private OpaqueTokenIntrospector introspector; /** * Creates a {@code OpaqueTokenAuthenticationProvider} with the provided parameters - * * @param introspector The {@link OpaqueTokenIntrospector} to use */ public OpaqueTokenAuthenticationProvider(OpaqueTokenIntrospector introspector) { @@ -73,10 +75,9 @@ public final class OpaqueTokenAuthenticationProvider implements AuthenticationPr /** * Introspect and validate the opaque - * Bearer Token. - * + * Bearer + * Token. * @param authentication the authentication request object. - * * @return A successful authentication * @throws AuthenticationException if authentication failed for some reason */ @@ -90,9 +91,11 @@ public final class OpaqueTokenAuthenticationProvider implements AuthenticationPr OAuth2AuthenticatedPrincipal principal; try { principal = this.introspector.introspect(bearer.getToken()); - } catch (BadOpaqueTokenException failed) { + } + catch (BadOpaqueTokenException failed) { throw new InvalidBearerTokenException(failed.getMessage()); - } catch (OAuth2IntrospectionException failed) { + } + catch (OAuth2IntrospectionException failed) { throw new AuthenticationServiceException(failed.getMessage()); } @@ -112,8 +115,8 @@ public final class OpaqueTokenAuthenticationProvider implements AuthenticationPr private AbstractAuthenticationToken convert(OAuth2AuthenticatedPrincipal principal, String token) { Instant iat = principal.getAttribute(ISSUED_AT); Instant exp = principal.getAttribute(EXPIRES_AT); - OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - token, iat, exp); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, token, iat, exp); return new BearerTokenAuthentication(principal, accessToken, principal.getAuthorities()); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManager.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManager.java index 30a918a4da..95e763bd9a 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManager.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManager.java @@ -39,20 +39,22 @@ import static org.springframework.security.oauth2.server.resource.introspection. /** * An {@link ReactiveAuthenticationManager} implementation for opaque - * Bearer Tokens, - * using an - * OAuth 2.0 Introspection Endpoint - * to check the token's validity and reveal its attributes. + * Bearer + * Tokens, using an + * OAuth 2.0 Introspection + * Endpoint to check the token's validity and reveal its attributes. *

        - * This {@link ReactiveAuthenticationManager} is responsible for introspecting and verifying an opaque access token, - * returning its attributes set as part of the {@link Authentication} statement. + * This {@link ReactiveAuthenticationManager} is responsible for introspecting and + * verifying an opaque access token, returning its attributes set as part of the + * {@link Authentication} statement. *

        - * Scopes are translated into {@link GrantedAuthority}s according to the following algorithm: + * Scopes are translated into {@link GrantedAuthority}s according to the following + * algorithm: *

          - *
        1. - * If there is a "scope" attribute, then convert to a {@link Collection} of {@link String}s. - *
        2. - * Take the resulting {@link Collection} and prepend the "SCOPE_" keyword to each element, adding as {@link GrantedAuthority}s. + *
        3. If there is a "scope" attribute, then convert to a {@link Collection} of + * {@link String}s. + *
        4. Take the resulting {@link Collection} and prepend the "SCOPE_" keyword to each + * element, adding as {@link GrantedAuthority}s. *
        * * @author Josh Cummings @@ -60,11 +62,12 @@ import static org.springframework.security.oauth2.server.resource.introspection. * @see ReactiveAuthenticationManager */ public class OpaqueTokenReactiveAuthenticationManager implements ReactiveAuthenticationManager { + private ReactiveOpaqueTokenIntrospector introspector; /** - * Creates a {@code OpaqueTokenReactiveAuthenticationManager} with the provided parameters - * + * Creates a {@code OpaqueTokenReactiveAuthenticationManager} with the provided + * parameters * @param introspector The {@link ReactiveOpaqueTokenIntrospector} to use */ public OpaqueTokenReactiveAuthenticationManager(ReactiveOpaqueTokenIntrospector introspector) { @@ -74,33 +77,29 @@ public class OpaqueTokenReactiveAuthenticationManager implements ReactiveAuthent @Override public Mono authenticate(Authentication authentication) { - return Mono.justOrEmpty(authentication) - .filter(BearerTokenAuthenticationToken.class::isInstance) - .cast(BearerTokenAuthenticationToken.class) - .map(BearerTokenAuthenticationToken::getToken) - .flatMap(this::authenticate) - .cast(Authentication.class); + return Mono.justOrEmpty(authentication).filter(BearerTokenAuthenticationToken.class::isInstance) + .cast(BearerTokenAuthenticationToken.class).map(BearerTokenAuthenticationToken::getToken) + .flatMap(this::authenticate).cast(Authentication.class); } private Mono authenticate(String token) { - return this.introspector.introspect(token) - .map(principal -> { - Instant iat = principal.getAttribute(ISSUED_AT); - Instant exp = principal.getAttribute(EXPIRES_AT); + return this.introspector.introspect(token).map(principal -> { + Instant iat = principal.getAttribute(ISSUED_AT); + Instant exp = principal.getAttribute(EXPIRES_AT); - // construct token - OAuth2AccessToken accessToken = - new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, token, iat, exp); - return new BearerTokenAuthentication(principal, accessToken, principal.getAuthorities()); - }) - .onErrorMap(OAuth2IntrospectionException.class, this::onError); + // construct token + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, token, iat, exp); + return new BearerTokenAuthentication(principal, accessToken, principal.getAuthorities()); + }).onErrorMap(OAuth2IntrospectionException.class, this::onError); } private AuthenticationException onError(OAuth2IntrospectionException e) { if (e instanceof BadOpaqueTokenException) { return new InvalidBearerTokenException(e.getMessage(), e); - } else { + } + else { return new AuthenticationServiceException(e.getMessage(), e); } } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverter.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverter.java index 4bd8ba0d58..51e80f776b 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverter.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverter.java @@ -26,32 +26,33 @@ import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.util.Assert; /** - * Reactive version of {@link JwtAuthenticationConverter} for converting a {@link Jwt} - * to a {@link AbstractAuthenticationToken Mono<AbstractAuthenticationToken>}. + * Reactive version of {@link JwtAuthenticationConverter} for converting a {@link Jwt} to + * a {@link AbstractAuthenticationToken Mono<AbstractAuthenticationToken>}. * * @author Eric Deandrea * @since 5.2 */ public final class ReactiveJwtAuthenticationConverter implements Converter> { - private Converter> jwtGrantedAuthoritiesConverter - = new ReactiveJwtGrantedAuthoritiesConverterAdapter(new JwtGrantedAuthoritiesConverter()); + + private Converter> jwtGrantedAuthoritiesConverter = new ReactiveJwtGrantedAuthoritiesConverterAdapter( + new JwtGrantedAuthoritiesConverter()); @Override public Mono convert(Jwt jwt) { - return this.jwtGrantedAuthoritiesConverter.convert(jwt) - .collectList() + return this.jwtGrantedAuthoritiesConverter.convert(jwt).collectList() .map(authorities -> new JwtAuthenticationToken(jwt, authorities)); } /** - * Sets the {@link Converter Converter<Jwt, Flux<GrantedAuthority>>} to use. - * Defaults to a reactive {@link JwtGrantedAuthoritiesConverter}. - * + * Sets the {@link Converter Converter<Jwt, Flux<GrantedAuthority>>} to + * use. Defaults to a reactive {@link JwtGrantedAuthoritiesConverter}. * @param jwtGrantedAuthoritiesConverter The converter * @see JwtGrantedAuthoritiesConverter */ - public void setJwtGrantedAuthoritiesConverter(Converter> jwtGrantedAuthoritiesConverter) { + public void setJwtGrantedAuthoritiesConverter( + Converter> jwtGrantedAuthoritiesConverter) { Assert.notNull(jwtGrantedAuthoritiesConverter, "jwtGrantedAuthoritiesConverter cannot be null"); this.jwtGrantedAuthoritiesConverter = jwtGrantedAuthoritiesConverter; } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverterAdapter.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverterAdapter.java index 1727b67086..c868cacfdb 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverterAdapter.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverterAdapter.java @@ -30,6 +30,7 @@ import org.springframework.util.Assert; * @since 5.1.1 */ public class ReactiveJwtAuthenticationConverterAdapter implements Converter> { + private final Converter delegate; public ReactiveJwtAuthenticationConverterAdapter(Converter delegate) { @@ -40,4 +41,5 @@ public class ReactiveJwtAuthenticationConverterAdapter implements Converter convert(Jwt jwt) { return Mono.just(jwt).map(this.delegate::convert); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtGrantedAuthoritiesConverterAdapter.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtGrantedAuthoritiesConverterAdapter.java index cf98c33706..5dc1b81df2 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtGrantedAuthoritiesConverterAdapter.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtGrantedAuthoritiesConverterAdapter.java @@ -26,11 +26,11 @@ import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.util.Assert; /** - * Adapts a {@link Converter Converter<Jwt, Collection<GrantedAuthority>>} to a - * {@link Converter Converter<Jwt, Flux<GrantedAuthority>>}. + * Adapts a {@link Converter Converter<Jwt, Collection<GrantedAuthority>>} to + * a {@link Converter Converter<Jwt, Flux<GrantedAuthority>>}. *

        - * Make sure the {@link Converter Converter<Jwt, Collection<GrantedAuthority>>} - * being adapted is non-blocking. + * Make sure the {@link Converter Converter<Jwt, + * Collection<GrantedAuthority>>} being adapted is non-blocking. *

        * * @author Eric Deandrea @@ -38,9 +38,11 @@ import org.springframework.util.Assert; * @see JwtGrantedAuthoritiesConverter */ public final class ReactiveJwtGrantedAuthoritiesConverterAdapter implements Converter> { + private final Converter> grantedAuthoritiesConverter; - public ReactiveJwtGrantedAuthoritiesConverterAdapter(Converter> grantedAuthoritiesConverter) { + public ReactiveJwtGrantedAuthoritiesConverterAdapter( + Converter> grantedAuthoritiesConverter) { Assert.notNull(grantedAuthoritiesConverter, "grantedAuthoritiesConverter cannot be null"); this.grantedAuthoritiesConverter = grantedAuthoritiesConverter; } @@ -49,4 +51,5 @@ public final class ReactiveJwtGrantedAuthoritiesConverterAdapter implements Conv public Flux convert(Jwt jwt) { return Flux.fromIterable(this.grantedAuthoritiesConverter.convert(jwt)); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/package-info.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/package-info.java index 2ee786b68e..3b022e8675 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/package-info.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/package-info.java @@ -15,6 +15,7 @@ */ /** - * OAuth 2.0 Resource Server {@code Authentication}s and supporting classes and interfaces. + * OAuth 2.0 Resource Server {@code Authentication}s and supporting classes and + * interfaces. */ package org.springframework.security.oauth2.server.resource.authentication; diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/BadOpaqueTokenException.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/BadOpaqueTokenException.java index b190400cae..5e155c8bce 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/BadOpaqueTokenException.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/BadOpaqueTokenException.java @@ -17,13 +17,15 @@ package org.springframework.security.oauth2.server.resource.introspection; /** - * An exception similar to {@link org.springframework.security.authentication.BadCredentialsException} - * that indicates an opaque token that is invalid in some way. + * An exception similar to + * {@link org.springframework.security.authentication.BadCredentialsException} that + * indicates an opaque token that is invalid in some way. * * @author Josh Cummings * @since 5.3 */ public class BadOpaqueTokenException extends OAuth2IntrospectionException { + public BadOpaqueTokenException(String message) { super(message); } @@ -31,4 +33,5 @@ public class BadOpaqueTokenException extends OAuth2IntrospectionException { public BadOpaqueTokenException(String message, Throwable cause) { super(message, cause); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospector.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospector.java index 440ba8b9c4..a6b1ff2521 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospector.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospector.java @@ -55,23 +55,25 @@ import static org.springframework.security.oauth2.server.resource.introspection. import static org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames.SCOPE; /** - * A Nimbus implementation of {@link OpaqueTokenIntrospector} that verifies and introspects - * a token using the configured - * OAuth 2.0 Introspection Endpoint. + * A Nimbus implementation of {@link OpaqueTokenIntrospector} that verifies and + * introspects a token using the configured + * OAuth 2.0 Introspection + * Endpoint. * * @author Josh Cummings * @author MD Sayem Ahmed * @since 5.2 */ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector { + private Converter> requestEntityConverter; + private RestOperations restOperations; private final String authorityPrefix = "SCOPE_"; /** * Creates a {@code OpaqueTokenAuthenticationProvider} with the provided parameters - * * @param introspectionUri The introspection endpoint uri * @param clientId The client id authorized to introspect * @param clientSecret The client's secret @@ -90,9 +92,8 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector { /** * Creates a {@code OpaqueTokenAuthenticationProvider} with the provided parameters * - * The given {@link RestOperations} should perform its own client authentication against the - * introspection endpoint. - * + * The given {@link RestOperations} should perform its own client authentication + * against the introspection endpoint. * @param introspectionUri The introspection endpoint uri * @param restOperations The client for performing the introspection request */ @@ -139,7 +140,8 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector { TokenIntrospectionResponse introspectionResponse = parseNimbusResponse(httpResponse); TokenIntrospectionSuccessResponse introspectionSuccessResponse = castToNimbusSuccess(introspectionResponse); - // relying solely on the authorization server to validate this token (not checking 'exp', for example) + // relying solely on the authorization server to validate this token (not checking + // 'exp', for example) if (!introspectionSuccessResponse.isActive()) { throw new BadOpaqueTokenException("Provided token isn't active"); } @@ -148,11 +150,10 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector { } /** - * Sets the {@link Converter} used for converting the OAuth 2.0 access token to a {@link RequestEntity} - * representation of the OAuth 2.0 token introspection request. - * - * @param requestEntityConverter the {@link Converter} used for converting to a {@link RequestEntity} representation - * of the token introspection request + * Sets the {@link Converter} used for converting the OAuth 2.0 access token to a + * {@link RequestEntity} representation of the OAuth 2.0 token introspection request. + * @param requestEntityConverter the {@link Converter} used for converting to a + * {@link RequestEntity} representation of the token introspection request */ public void setRequestEntityConverter(Converter> requestEntityConverter) { Assert.notNull(requestEntityConverter, "requestEntityConverter cannot be null"); @@ -163,7 +164,8 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector { private ResponseEntity makeRequest(RequestEntity requestEntity) { try { return this.restOperations.exchange(requestEntity, String.class); - } catch (Exception ex) { + } + catch (Exception ex) { throw new OAuth2IntrospectionException(ex.getMessage(), ex); } } @@ -174,8 +176,7 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector { response.setContent(responseEntity.getBody()); if (response.getStatusCode() != HTTPResponse.SC_OK) { - throw new OAuth2IntrospectionException( - "Introspection endpoint responded with " + response.getStatusCode()); + throw new OAuth2IntrospectionException("Introspection endpoint responded with " + response.getStatusCode()); } return response; } @@ -183,7 +184,8 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector { private TokenIntrospectionResponse parseNimbusResponse(HTTPResponse response) { try { return TokenIntrospectionResponse.parse(response); - } catch (Exception ex) { + } + catch (Exception ex) { throw new OAuth2IntrospectionException(ex.getMessage(), ex); } } @@ -237,8 +239,10 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector { private URL issuer(String uri) { try { return new URL(uri); - } catch (Exception ex) { + } + catch (Exception ex) { throw new OAuth2IntrospectionException("Invalid " + ISSUER + " value: " + uri); } } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospector.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospector.java index 05c1e9c4c3..81b27931ca 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospector.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospector.java @@ -52,22 +52,25 @@ import static org.springframework.security.oauth2.server.resource.introspection. import static org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames.SCOPE; /** - * A Nimbus implementation of {@link ReactiveOpaqueTokenIntrospector} that verifies and introspects - * a token using the configured - * OAuth 2.0 Introspection Endpoint. + * A Nimbus implementation of {@link ReactiveOpaqueTokenIntrospector} that verifies and + * introspects a token using the configured + * OAuth 2.0 Introspection + * Endpoint. * * @author Josh Cummings * @since 5.2 */ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueTokenIntrospector { + private URI introspectionUri; + private WebClient webClient; private String authorityPrefix = "SCOPE_"; /** - * Creates a {@code OpaqueTokenReactiveAuthenticationManager} with the provided parameters - * + * Creates a {@code OpaqueTokenReactiveAuthenticationManager} with the provided + * parameters * @param introspectionUri The introspection endpoint uri * @param clientId The client id authorized to introspect * @param clientSecret The client secret for the authorized client @@ -78,14 +81,12 @@ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke Assert.notNull(clientSecret, "clientSecret cannot be null"); this.introspectionUri = URI.create(introspectionUri); - this.webClient = WebClient.builder() - .defaultHeaders(h -> h.setBasicAuth(clientId, clientSecret)) - .build(); + this.webClient = WebClient.builder().defaultHeaders(h -> h.setBasicAuth(clientId, clientSecret)).build(); } /** - * Creates a {@code OpaqueTokenReactiveAuthenticationManager} with the provided parameters - * + * Creates a {@code OpaqueTokenReactiveAuthenticationManager} with the provided + * parameters * @param introspectionUri The introspection endpoint uri * @param webClient The client for performing the introspection request */ @@ -102,42 +103,34 @@ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke */ @Override public Mono introspect(String token) { - return Mono.just(token) - .flatMap(this::makeRequest) - .flatMap(this::adaptToNimbusResponse) - .map(this::parseNimbusResponse) - .map(this::castToNimbusSuccess) - .doOnNext(response -> validate(token, response)) - .map(this::convertClaimsSet) + return Mono.just(token).flatMap(this::makeRequest).flatMap(this::adaptToNimbusResponse) + .map(this::parseNimbusResponse).map(this::castToNimbusSuccess) + .doOnNext(response -> validate(token, response)).map(this::convertClaimsSet) .onErrorMap(e -> !(e instanceof OAuth2IntrospectionException), this::onError); } private Mono makeRequest(String token) { - return this.webClient.post() - .uri(this.introspectionUri) + return this.webClient.post().uri(this.introspectionUri) .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_UTF8_VALUE) - .body(BodyInserters.fromFormData("token", token)) - .exchange(); + .body(BodyInserters.fromFormData("token", token)).exchange(); } private Mono adaptToNimbusResponse(ClientResponse responseEntity) { HTTPResponse response = new HTTPResponse(responseEntity.rawStatusCode()); response.setHeader(HttpHeaders.CONTENT_TYPE, responseEntity.headers().contentType().get().toString()); if (response.getStatusCode() != HTTPResponse.SC_OK) { - return responseEntity.bodyToFlux(DataBuffer.class) - .map(DataBufferUtils::release) - .then(Mono.error(new OAuth2IntrospectionException( - "Introspection endpoint responded with " + response.getStatusCode()))); + return responseEntity.bodyToFlux(DataBuffer.class).map(DataBufferUtils::release) + .then(Mono.error(new OAuth2IntrospectionException( + "Introspection endpoint responded with " + response.getStatusCode()))); } - return responseEntity.bodyToMono(String.class) - .doOnNext(response::setContent) - .map(body -> response); + return responseEntity.bodyToMono(String.class).doOnNext(response::setContent).map(body -> response); } private TokenIntrospectionResponse parseNimbusResponse(HTTPResponse response) { try { return TokenIntrospectionResponse.parse(response); - } catch (Exception ex) { + } + catch (Exception ex) { throw new OAuth2IntrospectionException(ex.getMessage(), ex); } } @@ -150,7 +143,8 @@ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke } private void validate(String token, TokenIntrospectionSuccessResponse response) { - // relying solely on the authorization server to validate this token (not checking 'exp', for example) + // relying solely on the authorization server to validate this token (not checking + // 'exp', for example) if (!response.isActive()) { throw new BadOpaqueTokenException("Provided token isn't active"); } @@ -198,7 +192,8 @@ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke private URL issuer(String uri) { try { return new URL(uri); - } catch (Exception ex) { + } + catch (Exception ex) { throw new OAuth2IntrospectionException("Invalid " + ISSUER + " value: " + uri); } } @@ -206,4 +201,5 @@ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke private OAuth2IntrospectionException onError(Throwable e) { return new OAuth2IntrospectionException(e.getMessage(), e); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionAuthenticatedPrincipal.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionAuthenticatedPrincipal.java index 8e9427831e..338ff3ec56 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionAuthenticatedPrincipal.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionAuthenticatedPrincipal.java @@ -29,16 +29,18 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; * * @author David Kovac * @since 5.4 - * @see Introspection Response + * @see Introspection Response */ -public final class OAuth2IntrospectionAuthenticatedPrincipal implements OAuth2IntrospectionClaimAccessor, - OAuth2AuthenticatedPrincipal, Serializable { +public final class OAuth2IntrospectionAuthenticatedPrincipal + implements OAuth2IntrospectionClaimAccessor, OAuth2AuthenticatedPrincipal, Serializable { + private final OAuth2AuthenticatedPrincipal delegate; /** - * Constructs an {@code OAuth2IntrospectionAuthenticatedPrincipal} using the provided parameters. - * - * @param attributes the attributes of the OAuth 2.0 Token Introspection + * Constructs an {@code OAuth2IntrospectionAuthenticatedPrincipal} using the provided + * parameters. + * @param attributes the attributes of the OAuth 2.0 Token Introspection * @param authorities the authorities of the OAuth 2.0 Token Introspection */ public OAuth2IntrospectionAuthenticatedPrincipal(Map attributes, @@ -48,10 +50,10 @@ public final class OAuth2IntrospectionAuthenticatedPrincipal implements OAuth2In } /** - * Constructs an {@code OAuth2IntrospectionAuthenticatedPrincipal} using the provided parameters. - * - * @param name the name attached to the OAuth 2.0 Token Introspection - * @param attributes the attributes of the OAuth 2.0 Token Introspection + * Constructs an {@code OAuth2IntrospectionAuthenticatedPrincipal} using the provided + * parameters. + * @param name the name attached to the OAuth 2.0 Token Introspection + * @param attributes the attributes of the OAuth 2.0 Token Introspection * @param authorities the authorities of the OAuth 2.0 Token Introspection */ public OAuth2IntrospectionAuthenticatedPrincipal(String name, Map attributes, @@ -62,7 +64,6 @@ public final class OAuth2IntrospectionAuthenticatedPrincipal implements OAuth2In /** * Gets the attributes of the OAuth 2.0 Token Introspection in map form. - * * @return a {@link Map} of the attribute's objects keyed by the attribute's names */ @Override @@ -71,9 +72,8 @@ public final class OAuth2IntrospectionAuthenticatedPrincipal implements OAuth2In } /** - * Get the {@link Collection} of {@link GrantedAuthority}s associated - * with this OAuth 2.0 Token Introspection - * + * Get the {@link Collection} of {@link GrantedAuthority}s associated with this OAuth + * 2.0 Token Introspection * @return the OAuth 2.0 Token Introspection authorities */ @Override @@ -96,4 +96,5 @@ public final class OAuth2IntrospectionAuthenticatedPrincipal implements OAuth2In public Map getClaims() { return getAttributes(); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimAccessor.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimAccessor.java index 18c3c30e78..b95109d670 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimAccessor.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimAccessor.java @@ -23,20 +23,21 @@ import java.util.List; import org.springframework.security.oauth2.core.ClaimAccessor; /** - * A {@link ClaimAccessor} for the "claims" that may be contained - * in the Introspection Response. + * A {@link ClaimAccessor} for the "claims" that may be contained in the + * Introspection Response. * * @author David Kovac * @since 5.4 * @see ClaimAccessor * @see OAuth2IntrospectionClaimNames * @see OAuth2IntrospectionAuthenticatedPrincipal - * @see Introspection Response + * @see Introspection Response */ public interface OAuth2IntrospectionClaimAccessor extends ClaimAccessor { + /** * Returns the indicator {@code (active)} whether or not the token is currently active - * * @return the indicator whether or not the token is currently active */ default boolean isActive() { @@ -45,7 +46,6 @@ public interface OAuth2IntrospectionClaimAccessor extends ClaimAccessor { /** * Returns the scopes {@code (scope)} associated with the token - * * @return the scopes associated with the token */ default String getScope() { @@ -54,7 +54,6 @@ public interface OAuth2IntrospectionClaimAccessor extends ClaimAccessor { /** * Returns the client identifier {@code (client_id)} for the token - * * @return the client identifier for the token */ default String getClientId() { @@ -62,9 +61,10 @@ public interface OAuth2IntrospectionClaimAccessor extends ClaimAccessor { } /** - * Returns a human-readable identifier {@code (username)} for the resource owner that authorized the token - * - * @return a human-readable identifier for the resource owner that authorized the token + * Returns a human-readable identifier {@code (username)} for the resource owner that + * authorized the token + * @return a human-readable identifier for the resource owner that authorized the + * token */ default String getUsername() { return this.getClaimAsString(OAuth2IntrospectionClaimNames.USERNAME); @@ -72,7 +72,6 @@ public interface OAuth2IntrospectionClaimAccessor extends ClaimAccessor { /** * Returns the type of the token {@code (token_type)}, for example {@code bearer}. - * * @return the type of the token, for example {@code bearer}. */ default String getTokenType() { @@ -81,7 +80,6 @@ public interface OAuth2IntrospectionClaimAccessor extends ClaimAccessor { /** * Returns a timestamp {@code (exp)} indicating when the token expires - * * @return a timestamp indicating when the token expires */ default Instant getExpiresAt() { @@ -90,7 +88,6 @@ public interface OAuth2IntrospectionClaimAccessor extends ClaimAccessor { /** * Returns a timestamp {@code (iat)} indicating when the token was issued - * * @return a timestamp indicating when the token was issued */ default Instant getIssuedAt() { @@ -98,8 +95,8 @@ public interface OAuth2IntrospectionClaimAccessor extends ClaimAccessor { } /** - * Returns a timestamp {@code (nbf)} indicating when the token is not to be used before - * + * Returns a timestamp {@code (nbf)} indicating when the token is not to be used + * before * @return a timestamp indicating when the token is not to be used before */ default Instant getNotBefore() { @@ -107,9 +104,10 @@ public interface OAuth2IntrospectionClaimAccessor extends ClaimAccessor { } /** - * Returns usually a machine-readable identifier {@code (sub)} of the resource owner who authorized the token - * - * @return usually a machine-readable identifier of the resource owner who authorized the token + * Returns usually a machine-readable identifier {@code (sub)} of the resource owner + * who authorized the token + * @return usually a machine-readable identifier of the resource owner who authorized + * the token */ default String getSubject() { return this.getClaimAsString(OAuth2IntrospectionClaimNames.SUBJECT); @@ -117,7 +115,6 @@ public interface OAuth2IntrospectionClaimAccessor extends ClaimAccessor { /** * Returns the intended audience {@code (aud)} for the token - * * @return the intended audience for the token */ default List getAudience() { @@ -126,7 +123,6 @@ public interface OAuth2IntrospectionClaimAccessor extends ClaimAccessor { /** * Returns the issuer {@code (iss)} of the token - * * @return the issuer of the token */ default URL getIssuer() { @@ -135,10 +131,10 @@ public interface OAuth2IntrospectionClaimAccessor extends ClaimAccessor { /** * Returns the identifier {@code (jti)} for the token - * * @return the identifier for the token */ default String getId() { return this.getClaimAsString(OAuth2IntrospectionClaimNames.JTI); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimNames.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimNames.java index d2f011d18a..2fdb15043f 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimNames.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimNames.java @@ -17,7 +17,8 @@ package org.springframework.security.oauth2.server.resource.introspection; /** * The names of the "Introspection Claims" defined by an - * Introspection Response. + * Introspection + * Response. * * @author Josh Cummings * @since 5.2 @@ -40,7 +41,8 @@ public interface OAuth2IntrospectionClaimNames { String CLIENT_ID = "client_id"; /** - * {@code username} - A human-readable identifier for the resource owner that authorized the token + * {@code username} - A human-readable identifier for the resource owner that + * authorized the token */ String USERNAME = "username"; @@ -65,7 +67,8 @@ public interface OAuth2IntrospectionClaimNames { String NOT_BEFORE = "nbf"; /** - * {@code sub} - Usually a machine-readable identifier of the resource owner who authorized the token + * {@code sub} - Usually a machine-readable identifier of the resource owner who + * authorized the token */ String SUBJECT = "sub"; @@ -83,4 +86,5 @@ public interface OAuth2IntrospectionClaimNames { * {@code jti} - The identifier for the token */ String JTI = "jti"; + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionException.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionException.java index ffd468fc54..e2649ba975 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionException.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionException.java @@ -23,6 +23,7 @@ package org.springframework.security.oauth2.server.resource.introspection; * @since 5.2 */ public class OAuth2IntrospectionException extends RuntimeException { + public OAuth2IntrospectionException(String message) { super(message); } @@ -30,4 +31,5 @@ public class OAuth2IntrospectionException extends RuntimeException { public OAuth2IntrospectionException(String message, Throwable cause) { super(message, cause); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OpaqueTokenIntrospector.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OpaqueTokenIntrospector.java index 672647d0fb..056a7766b2 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OpaqueTokenIntrospector.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OpaqueTokenIntrospector.java @@ -24,11 +24,12 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; * A contract for introspecting and verifying an OAuth 2.0 token. * * A typical implementation of this interface will make a request to an - * OAuth 2.0 Introspection Endpoint - * to verify the token and return its attributes, indicating a successful verification. + * OAuth 2.0 Introspection + * Endpoint to verify the token and return its attributes, indicating a successful + * verification. * - * Another sensible implementation of this interface would be to query a backing store - * of tokens, for example a distributed cache. + * Another sensible implementation of this interface would be to query a backing store of + * tokens, for example a distributed cache. * * @author Josh Cummings * @since 5.2 @@ -40,9 +41,9 @@ public interface OpaqueTokenIntrospector { * Introspect and verify the given token, returning its attributes. * * Returning a {@link Map} is indicative that the token is valid. - * * @param token the token to introspect * @return the token's attributes */ OAuth2AuthenticatedPrincipal introspect(String token); + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/ReactiveOpaqueTokenIntrospector.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/ReactiveOpaqueTokenIntrospector.java index 60d1078571..2d91da5ff4 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/ReactiveOpaqueTokenIntrospector.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/ReactiveOpaqueTokenIntrospector.java @@ -26,11 +26,12 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; * A contract for introspecting and verifying an OAuth 2.0 token. * * A typical implementation of this interface will make a request to an - * OAuth 2.0 Introspection Endpoint - * to verify the token and return its attributes, indicating a successful verification. + * OAuth 2.0 Introspection + * Endpoint to verify the token and return its attributes, indicating a successful + * verification. * - * Another sensible implementation of this interface would be to query a backing store - * of tokens, for example a distributed cache. + * Another sensible implementation of this interface would be to query a backing store of + * tokens, for example a distributed cache. * * @author Josh Cummings * @since 5.2 @@ -42,9 +43,9 @@ public interface ReactiveOpaqueTokenIntrospector { * Introspect and verify the given token, returning its attributes. * * Returning a {@link Map} is indicative that the token is valid. - * * @param token the token to introspect * @return the token's attributes */ Mono introspect(String token); + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationEntryPoint.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationEntryPoint.java index b6861448be..6a9ae1f38b 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationEntryPoint.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationEntryPoint.java @@ -31,16 +31,16 @@ import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.util.StringUtils; /** - * An {@link AuthenticationEntryPoint} implementation used to commence authentication of protected resource requests - * using {@link BearerTokenAuthenticationFilter}. + * An {@link AuthenticationEntryPoint} implementation used to commence authentication of + * protected resource requests using {@link BearerTokenAuthenticationFilter}. *

        - * Uses information provided by {@link BearerTokenError} to set HTTP response status code and populate - * {@code WWW-Authenticate} HTTP header. + * Uses information provided by {@link BearerTokenError} to set HTTP response status code + * and populate {@code WWW-Authenticate} HTTP header. * * @author Vedran Pavic * @see BearerTokenError - * @see RFC 6750 Section 3: The WWW-Authenticate - * Response Header Field + * @see RFC 6750 + * Section 3: The WWW-Authenticate Response Header Field * @since 5.1 */ public final class BearerTokenAuthenticationEntryPoint implements AuthenticationEntryPoint { @@ -48,16 +48,15 @@ public final class BearerTokenAuthenticationEntryPoint implements Authentication private String realmName; /** - * Collect error details from the provided parameters and format according to - * RFC 6750, specifically {@code error}, {@code error_description}, {@code error_uri}, and {@code scope}. - * - * @param request that resulted in an AuthenticationException - * @param response so that the user agent can begin authentication + * Collect error details from the provided parameters and format according to RFC + * 6750, specifically {@code error}, {@code error_description}, {@code error_uri}, and + * {@code scope}. + * @param request that resulted in an AuthenticationException + * @param response so that the user agent can begin authentication * @param authException that caused the invocation */ @Override - public void commence( - HttpServletRequest request, HttpServletResponse response, + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) { HttpStatus status = HttpStatus.UNAUTHORIZED; @@ -100,7 +99,6 @@ public final class BearerTokenAuthenticationEntryPoint implements Authentication /** * Set the default realm name to use in the bearer token error response - * * @param realmName */ public void setRealmName(String realmName) { @@ -126,4 +124,5 @@ public final class BearerTokenAuthenticationEntryPoint implements Authentication return wwwAuthenticate.toString(); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilter.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilter.java index c96ab90fd5..5ffaab7f2e 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilter.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilter.java @@ -40,37 +40,39 @@ import org.springframework.web.filter.OncePerRequestFilter; /** * Authenticates requests that contain an OAuth 2.0 - * Bearer Token. + * Bearer + * Token. * - * This filter should be wired with an {@link AuthenticationManager} that can authenticate a - * {@link BearerTokenAuthenticationToken}. + * This filter should be wired with an {@link AuthenticationManager} that can authenticate + * a {@link BearerTokenAuthenticationToken}. * * @author Josh Cummings * @author Vedran Pavic * @author Joe Grandja * @since 5.1 - * @see The OAuth 2.0 Authorization Framework: Bearer Token Usage + * @see The OAuth 2.0 + * Authorization Framework: Bearer Token Usage * @see JwtAuthenticationProvider */ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter { + private final AuthenticationManagerResolver authenticationManagerResolver; - private final AuthenticationDetailsSource authenticationDetailsSource = - new WebAuthenticationDetailsSource(); + private final AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); private BearerTokenResolver bearerTokenResolver = new DefaultBearerTokenResolver(); private AuthenticationEntryPoint authenticationEntryPoint = new BearerTokenAuthenticationEntryPoint(); - private AuthenticationFailureHandler authenticationFailureHandler = (request, response, exception) -> - authenticationEntryPoint.commence(request, response, exception); + private AuthenticationFailureHandler authenticationFailureHandler = (request, response, + exception) -> authenticationEntryPoint.commence(request, response, exception); /** * Construct a {@code BearerTokenAuthenticationFilter} using the provided parameter(s) * @param authenticationManagerResolver */ - public BearerTokenAuthenticationFilter - (AuthenticationManagerResolver authenticationManagerResolver) { + public BearerTokenAuthenticationFilter( + AuthenticationManagerResolver authenticationManagerResolver) { Assert.notNull(authenticationManagerResolver, "authenticationManagerResolver cannot be null"); this.authenticationManagerResolver = authenticationManagerResolver; @@ -86,9 +88,9 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter } /** - * Extract any Bearer Token from - * the request and attempt an authentication. - * + * Extract any + * Bearer + * Token from the request and attempt an authentication. * @param request * @param response * @param filterChain @@ -105,7 +107,8 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter try { token = this.bearerTokenResolver.resolve(request); - } catch ( OAuth2AuthenticationException invalid ) { + } + catch (OAuth2AuthenticationException invalid) { this.authenticationEntryPoint.commence(request, response, invalid); return; } @@ -128,7 +131,8 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter SecurityContextHolder.setContext(context); filterChain.doFilter(request, response); - } catch (AuthenticationException failed) { + } + catch (AuthenticationException failed) { SecurityContextHolder.clearContext(); if (debug) { @@ -140,7 +144,8 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter } /** - * Set the {@link BearerTokenResolver} to use. Defaults to {@link DefaultBearerTokenResolver}. + * Set the {@link BearerTokenResolver} to use. Defaults to + * {@link DefaultBearerTokenResolver}. * @param bearerTokenResolver the {@code BearerTokenResolver} to use */ public void setBearerTokenResolver(BearerTokenResolver bearerTokenResolver) { @@ -149,7 +154,8 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter } /** - * Set the {@link AuthenticationEntryPoint} to use. Defaults to {@link BearerTokenAuthenticationEntryPoint}. + * Set the {@link AuthenticationEntryPoint} to use. Defaults to + * {@link BearerTokenAuthenticationEntryPoint}. * @param authenticationEntryPoint the {@code AuthenticationEntryPoint} to use */ public void setAuthenticationEntryPoint(final AuthenticationEntryPoint authenticationEntryPoint) { @@ -158,7 +164,8 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter } /** - * Set the {@link AuthenticationFailureHandler} to use. Default implementation invokes {@link AuthenticationEntryPoint}. + * Set the {@link AuthenticationFailureHandler} to use. Default implementation invokes + * {@link AuthenticationEntryPoint}. * @param authenticationFailureHandler the {@code AuthenticationFailureHandler} to use * @since 5.2 */ @@ -166,4 +173,5 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter Assert.notNull(authenticationFailureHandler, "authenticationFailureHandler cannot be null"); this.authenticationFailureHandler = authenticationFailureHandler; } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenResolver.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenResolver.java index bebd4fc0f7..f7bd2efd3f 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenResolver.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/BearerTokenResolver.java @@ -21,20 +21,22 @@ import javax.servlet.http.HttpServletRequest; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; /** - * A strategy for resolving Bearer Tokens - * from the {@link HttpServletRequest}. + * A strategy for resolving + * Bearer + * Tokens from the {@link HttpServletRequest}. * * @author Vedran Pavic * @since 5.1 - * @see RFC 6750 Section 2: Authenticated Requests + * @see RFC 6750 + * Section 2: Authenticated Requests */ @FunctionalInterface public interface BearerTokenResolver { /** - * Resolve any Bearer Token - * value from the request. - * + * Resolve any + * Bearer + * Token value from the request. * @param request the request * @return the Bearer Token value or {@code null} if none found * @throws OAuth2AuthenticationException if the found token is invalid diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolver.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolver.java index 248d3d9606..25419df655 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolver.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolver.java @@ -33,13 +33,13 @@ import static org.springframework.security.oauth2.server.resource.BearerTokenErr * * @author Vedran Pavic * @since 5.1 - * @see RFC 6750 Section 2: Authenticated Requests + * @see RFC 6750 + * Section 2: Authenticated Requests */ public final class DefaultBearerTokenResolver implements BearerTokenResolver { - private static final Pattern authorizationPattern = Pattern.compile( - "^Bearer (?[a-zA-Z0-9-._~+/]+=*)$", - Pattern.CASE_INSENSITIVE); + private static final Pattern authorizationPattern = Pattern.compile("^Bearer (?[a-zA-Z0-9-._~+/]+=*)$", + Pattern.CASE_INSENSITIVE); private boolean allowFormEncodedBodyParameter = false; @@ -68,19 +68,21 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver { } /** - * Set if transport of access token using form-encoded body parameter is supported. Defaults to {@code false}. - * @param allowFormEncodedBodyParameter if the form-encoded body parameter is supported + * Set if transport of access token using form-encoded body parameter is supported. + * Defaults to {@code false}. + * @param allowFormEncodedBodyParameter if the form-encoded body parameter is + * supported */ public void setAllowFormEncodedBodyParameter(boolean allowFormEncodedBodyParameter) { this.allowFormEncodedBodyParameter = allowFormEncodedBodyParameter; } /** - * Set if transport of access token using URI query parameter is supported. Defaults to {@code false}. - * - * The spec recommends against using this mechanism for sending bearer tokens, and even goes as far as - * stating that it was only included for completeness. + * Set if transport of access token using URI query parameter is supported. Defaults + * to {@code false}. * + * The spec recommends against using this mechanism for sending bearer tokens, and + * even goes as far as stating that it was only included for completeness. * @param allowUriQueryParameter if the URI query parameter is supported */ public void setAllowUriQueryParameter(boolean allowUriQueryParameter) { @@ -91,8 +93,8 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver { * Set this value to configure what header is checked when resolving a Bearer Token. * This value is defaulted to {@link HttpHeaders#AUTHORIZATION}. * - * This allows other headers to be used as the Bearer Token source such as {@link HttpHeaders#PROXY_AUTHORIZATION} - * + * This allows other headers to be used as the Bearer Token source such as + * {@link HttpHeaders#PROXY_AUTHORIZATION} * @param bearerTokenHeaderName the header to check when retrieving the Bearer Token. * @since 5.4 */ @@ -117,7 +119,7 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver { private static String resolveFromRequestParameters(HttpServletRequest request) { String[] values = request.getParameterValues("access_token"); - if (values == null || values.length == 0) { + if (values == null || values.length == 0) { return null; } @@ -133,4 +135,5 @@ public final class DefaultBearerTokenResolver implements BearerTokenResolver { return ((this.allowFormEncodedBodyParameter && "POST".equals(request.getMethod())) || (this.allowUriQueryParameter && "GET".equals(request.getMethod()))); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/HeaderBearerTokenResolver.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/HeaderBearerTokenResolver.java index 77593895e9..ff5c9a7ae2 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/HeaderBearerTokenResolver.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/HeaderBearerTokenResolver.java @@ -38,4 +38,5 @@ public class HeaderBearerTokenResolver implements BearerTokenResolver { public String resolve(HttpServletRequest request) { return request.getHeader(this.header); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/access/BearerTokenAccessDeniedHandler.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/access/BearerTokenAccessDeniedHandler.java index d535f95601..ab81fa900c 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/access/BearerTokenAccessDeniedHandler.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/access/BearerTokenAccessDeniedHandler.java @@ -31,11 +31,14 @@ import java.util.Map; /** * Translates any {@link AccessDeniedException} into an HTTP response in accordance with - * RFC 6750 Section 3: The WWW-Authenticate. + * RFC 6750 + * Section 3: The WWW-Authenticate. *

        - * So long as the class can prove that the request has a valid OAuth 2.0 {@link Authentication}, then will return an - * insufficient scope error; otherwise, - * it will simply indicate the scheme (Bearer) and any configured realm. + * So long as the class can prove that the request has a valid OAuth 2.0 + * {@link Authentication}, then will return an + * insufficient + * scope error; otherwise, it will simply indicate the scheme (Bearer) and any + * configured realm. * * @author Josh Cummings * @since 5.1 @@ -45,16 +48,15 @@ public final class BearerTokenAccessDeniedHandler implements AccessDeniedHandler private String realmName; /** - * Collect error details from the provided parameters and format according to - * RFC 6750, specifically {@code error}, {@code error_description}, {@code error_uri}, and {@code scope}. - * - * @param request that resulted in an AccessDeniedException - * @param response so that the user agent can be advised of the failure + * Collect error details from the provided parameters and format according to RFC + * 6750, specifically {@code error}, {@code error_description}, {@code error_uri}, and + * {@code scope}. + * @param request that resulted in an AccessDeniedException + * @param response so that the user agent can be advised of the failure * @param accessDeniedException that caused the invocation */ @Override - public void handle( - HttpServletRequest request, HttpServletResponse response, + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) { Map parameters = new LinkedHashMap<>(); @@ -65,7 +67,8 @@ public final class BearerTokenAccessDeniedHandler implements AccessDeniedHandler if (request.getUserPrincipal() instanceof AbstractOAuth2TokenAuthenticationToken) { parameters.put("error", BearerTokenErrorCodes.INSUFFICIENT_SCOPE); - parameters.put("error_description", "The request requires higher privileges than provided by the access token."); + parameters.put("error_description", + "The request requires higher privileges than provided by the access token."); parameters.put("error_uri", "https://tools.ietf.org/html/rfc6750#section-3.1"); } @@ -77,7 +80,6 @@ public final class BearerTokenAccessDeniedHandler implements AccessDeniedHandler /** * Set the default realm name to use in the bearer token error response - * * @param realmName */ public void setRealmName(String realmName) { @@ -103,4 +105,5 @@ public final class BearerTokenAccessDeniedHandler implements AccessDeniedHandler return wwwAuthenticate.toString(); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/access/server/BearerTokenServerAccessDeniedHandler.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/access/server/BearerTokenServerAccessDeniedHandler.java index c4e74650c4..2a397afb9e 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/access/server/BearerTokenServerAccessDeniedHandler.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/access/server/BearerTokenServerAccessDeniedHandler.java @@ -33,19 +33,22 @@ import java.util.Map; /** * Translates any {@link AccessDeniedException} into an HTTP response in accordance with - * RFC 6750 Section 3: The WWW-Authenticate. + * RFC 6750 + * Section 3: The WWW-Authenticate. * - * So long as the class can prove that the request has a valid OAuth 2.0 {@link Authentication}, then will return an - * insufficient scope error; otherwise, - * it will simply indicate the scheme (Bearer) and any configured realm. + * So long as the class can prove that the request has a valid OAuth 2.0 + * {@link Authentication}, then will return an + * insufficient + * scope error; otherwise, it will simply indicate the scheme (Bearer) and any + * configured realm. * * @author Josh Cummings * @since 5.1 * */ public class BearerTokenServerAccessDeniedHandler implements ServerAccessDeniedHandler { - private static final Collection WELL_KNOWN_SCOPE_ATTRIBUTE_NAMES = - Arrays.asList("scope", "scp"); + + private static final Collection WELL_KNOWN_SCOPE_ATTRIBUTE_NAMES = Arrays.asList("scope", "scp"); private String realmName; @@ -58,16 +61,13 @@ public class BearerTokenServerAccessDeniedHandler implements ServerAccessDeniedH parameters.put("realm", this.realmName); } - return exchange.getPrincipal() - .filter(AbstractOAuth2TokenAuthenticationToken.class::isInstance) - .map(token -> errorMessageParameters(parameters)) - .switchIfEmpty(Mono.just(parameters)) + return exchange.getPrincipal().filter(AbstractOAuth2TokenAuthenticationToken.class::isInstance) + .map(token -> errorMessageParameters(parameters)).switchIfEmpty(Mono.just(parameters)) .flatMap(params -> respond(exchange, params)); } /** * Set the default realm name to use in the bearer token error response - * * @param realmName */ public final void setRealmName(String realmName) { @@ -76,7 +76,8 @@ public class BearerTokenServerAccessDeniedHandler implements ServerAccessDeniedH private static Map errorMessageParameters(Map parameters) { parameters.put("error", BearerTokenErrorCodes.INSUFFICIENT_SCOPE); - parameters.put("error_description", "The request requires higher privileges than provided by the access token."); + parameters.put("error_description", + "The request requires higher privileges than provided by the access token."); parameters.put("error_uri", "https://tools.ietf.org/html/rfc6750#section-3.1"); return parameters; @@ -106,4 +107,5 @@ public class BearerTokenServerAccessDeniedHandler implements ServerAccessDeniedH return wwwAuthenticate.toString(); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServerBearerExchangeFilterFunction.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServerBearerExchangeFilterFunction.java index 700531d588..ccf4a8c1f5 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServerBearerExchangeFilterFunction.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServerBearerExchangeFilterFunction.java @@ -29,14 +29,16 @@ import org.springframework.web.reactive.function.client.ExchangeFunction; /** * An {@link ExchangeFilterFunction} that adds the - * Bearer Token - * from an existing {@link AbstractOAuth2Token} tied to the current {@link Authentication}. + * Bearer + * Token from an existing {@link AbstractOAuth2Token} tied to the current + * {@link Authentication}. * - * Suitable for Reactive applications, applying it to a typical {@link org.springframework.web.reactive.function.client.WebClient} - * configuration: + * Suitable for Reactive applications, applying it to a typical + * {@link org.springframework.web.reactive.function.client.WebClient} configuration: * *

        - *  @Bean
        +
        + *  @Bean
          *  WebClient webClient() {
          *      ServerBearerExchangeFilterFunction bearer = new ServerBearerExchangeFilterFunction();
          *      return WebClient.builder()
        @@ -47,35 +49,28 @@ import org.springframework.web.reactive.function.client.ExchangeFunction;
          * @author Josh Cummings
          * @since 5.2
          */
        -public final class ServerBearerExchangeFilterFunction
        -		implements ExchangeFilterFunction {
        +public final class ServerBearerExchangeFilterFunction implements ExchangeFilterFunction {
         
         	/**
         	 * {@inheritDoc}
         	 */
         	@Override
         	public Mono filter(ClientRequest request, ExchangeFunction next) {
        -		return oauth2Token()
        -				.map(token -> bearer(request, token))
        -				.defaultIfEmpty(request)
        -				.flatMap(next::exchange);
        +		return oauth2Token().map(token -> bearer(request, token)).defaultIfEmpty(request).flatMap(next::exchange);
         	}
         
         	private Mono oauth2Token() {
         		return currentAuthentication()
         				.filter(authentication -> authentication.getCredentials() instanceof AbstractOAuth2Token)
        -				.map(Authentication::getCredentials)
        -				.cast(AbstractOAuth2Token.class);
        +				.map(Authentication::getCredentials).cast(AbstractOAuth2Token.class);
         	}
         
         	private Mono currentAuthentication() {
        -		return ReactiveSecurityContextHolder.getContext()
        -				.map(SecurityContext::getAuthentication);
        +		return ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication);
         	}
         
         	private ClientRequest bearer(ClientRequest request, AbstractOAuth2Token token) {
        -		return ClientRequest.from(request)
        -				.headers(headers -> headers.setBearerAuth(token.getTokenValue()))
        -				.build();
        +		return ClientRequest.from(request).headers(headers -> headers.setBearerAuth(token.getTokenValue())).build();
         	}
        +
         }
        diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServletBearerExchangeFilterFunction.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServletBearerExchangeFilterFunction.java
        index f59af70f02..3e9d377678 100644
        --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServletBearerExchangeFilterFunction.java
        +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServletBearerExchangeFilterFunction.java
        @@ -30,14 +30,16 @@ import org.springframework.web.reactive.function.client.ExchangeFunction;
         
         /**
          * An {@link ExchangeFilterFunction} that adds the
        - * Bearer Token
        - * from an existing {@link AbstractOAuth2Token} tied to the current {@link Authentication}.
        + * Bearer
        + * Token from an existing {@link AbstractOAuth2Token} tied to the current
        + * {@link Authentication}.
          *
        - * Suitable for Servlet applications, applying it to a typical {@link org.springframework.web.reactive.function.client.WebClient}
        - * configuration:
        + * Suitable for Servlet applications, applying it to a typical
        + * {@link org.springframework.web.reactive.function.client.WebClient} configuration:
          *
          * 
        - *  @Bean
        +
        + *  @Bean
          *  WebClient webClient() {
          *      ServletBearerExchangeFilterFunction bearer = new ServletBearerExchangeFilterFunction();
          *      return WebClient.builder()
        @@ -45,39 +47,33 @@ import org.springframework.web.reactive.function.client.ExchangeFunction;
          *  }
          * 
        * - * To locate the bearer token, this looks in the Reactor {@link Context} for a key of type {@link Authentication}. + * To locate the bearer token, this looks in the Reactor {@link Context} for a key of type + * {@link Authentication}. * * Registering * {@see org.springframework.security.config.annotation.web.configuration.OAuth2ResourceServerConfiguration.OAuth2ResourceServerWebFluxSecurityConfiguration.BearerRequestContextSubscriberRegistrar}, - * as a {@code @Bean} will take care of this automatically, - * but certainly an application can supply a {@link Context} of its own to override. + * as a {@code @Bean} will take care of this automatically, but certainly an application + * can supply a {@link Context} of its own to override. * * @author Josh Cummings * @since 5.2 */ -public final class ServletBearerExchangeFilterFunction - implements ExchangeFilterFunction { +public final class ServletBearerExchangeFilterFunction implements ExchangeFilterFunction { - static final String SECURITY_REACTOR_CONTEXT_ATTRIBUTES_KEY = - "org.springframework.security.SECURITY_CONTEXT_ATTRIBUTES"; + static final String SECURITY_REACTOR_CONTEXT_ATTRIBUTES_KEY = "org.springframework.security.SECURITY_CONTEXT_ATTRIBUTES"; /** * {@inheritDoc} */ @Override public Mono filter(ClientRequest request, ExchangeFunction next) { - return oauth2Token() - .map(token -> bearer(request, token)) - .defaultIfEmpty(request) - .flatMap(next::exchange); + return oauth2Token().map(token -> bearer(request, token)).defaultIfEmpty(request).flatMap(next::exchange); } private Mono oauth2Token() { - return Mono.subscriberContext() - .flatMap(this::currentAuthentication) + return Mono.subscriberContext().flatMap(this::currentAuthentication) .filter(authentication -> authentication.getCredentials() instanceof AbstractOAuth2Token) - .map(Authentication::getCredentials) - .cast(AbstractOAuth2Token.class); + .map(Authentication::getCredentials).cast(AbstractOAuth2Token.class); } private Mono currentAuthentication(Context ctx) { @@ -85,7 +81,8 @@ public final class ServletBearerExchangeFilterFunction } private T getAttribute(Context ctx, Class clazz) { - // NOTE: SecurityReactorContextConfiguration.SecurityReactorContextSubscriber adds this key + // NOTE: SecurityReactorContextConfiguration.SecurityReactorContextSubscriber adds + // this key if (!ctx.hasKey(SECURITY_REACTOR_CONTEXT_ATTRIBUTES_KEY)) { return null; } @@ -94,8 +91,7 @@ public final class ServletBearerExchangeFilterFunction } private ClientRequest bearer(ClientRequest request, AbstractOAuth2Token token) { - return ClientRequest.from(request) - .headers(headers -> headers.setBearerAuth(token.getTokenValue())) - .build(); + return ClientRequest.from(request).headers(headers -> headers.setBearerAuth(token.getTokenValue())).build(); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/BearerTokenServerAuthenticationEntryPoint.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/BearerTokenServerAuthenticationEntryPoint.java index 3a050f30cb..e5f027e5e1 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/BearerTokenServerAuthenticationEntryPoint.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/BearerTokenServerAuthenticationEntryPoint.java @@ -34,20 +34,19 @@ import java.util.LinkedHashMap; import java.util.Map; /** - * An {@link AuthenticationEntryPoint} implementation used to commence authentication of protected resource requests - * using {@link BearerTokenAuthenticationFilter}. + * An {@link AuthenticationEntryPoint} implementation used to commence authentication of + * protected resource requests using {@link BearerTokenAuthenticationFilter}. *

        - * Uses information provided by {@link BearerTokenError} to set HTTP response status code and populate - * {@code WWW-Authenticate} HTTP header. + * Uses information provided by {@link BearerTokenError} to set HTTP response status code + * and populate {@code WWW-Authenticate} HTTP header. * * @author Rob Winch * @see BearerTokenError - * @see RFC 6750 Section 3: The WWW-Authenticate - * Response Header Field + * @see RFC 6750 + * Section 3: The WWW-Authenticate Response Header Field * @since 5.1 */ -public final class BearerTokenServerAuthenticationEntryPoint implements - ServerAuthenticationEntryPoint { +public final class BearerTokenServerAuthenticationEntryPoint implements ServerAuthenticationEntryPoint { private String realmName; @@ -127,4 +126,5 @@ public final class BearerTokenServerAuthenticationEntryPoint implements return wwwAuthenticate.toString(); } + } diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverter.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverter.java index d59c943e6c..d2885fcb4f 100644 --- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverter.java +++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverter.java @@ -36,31 +36,32 @@ import static org.springframework.security.oauth2.server.resource.BearerTokenErr import static org.springframework.security.oauth2.server.resource.BearerTokenErrors.invalidToken; /** - * A strategy for resolving Bearer Tokens - * from the {@link ServerWebExchange}. + * A strategy for resolving + * Bearer + * Tokens from the {@link ServerWebExchange}. * * @author Rob Winch * @since 5.1 - * @see RFC 6750 Section 2: Authenticated Requests + * @see RFC 6750 + * Section 2: Authenticated Requests */ -public class ServerBearerTokenAuthenticationConverter - implements ServerAuthenticationConverter { - private static final Pattern authorizationPattern = Pattern.compile( - "^Bearer (?[a-zA-Z0-9-._~+/]+=*)$", - Pattern.CASE_INSENSITIVE); +public class ServerBearerTokenAuthenticationConverter implements ServerAuthenticationConverter { + + private static final Pattern authorizationPattern = Pattern.compile("^Bearer (?[a-zA-Z0-9-._~+/]+=*)$", + Pattern.CASE_INSENSITIVE); private boolean allowUriQueryParameter = false; + private String bearerTokenHeaderName = HttpHeaders.AUTHORIZATION; public Mono convert(ServerWebExchange exchange) { - return Mono.fromCallable(() -> token(exchange.getRequest())) - .map(token -> { - if (token.isEmpty()) { - BearerTokenError error = invalidTokenError(); - throw new OAuth2AuthenticationException(error); - } - return new BearerTokenAuthenticationToken(token); - }); + return Mono.fromCallable(() -> token(exchange.getRequest())).map(token -> { + if (token.isEmpty()) { + BearerTokenError error = invalidTokenError(); + throw new OAuth2AuthenticationException(error); + } + return new BearerTokenAuthenticationToken(token); + }); } private String token(ServerHttpRequest request) { @@ -80,11 +81,11 @@ public class ServerBearerTokenAuthenticationConverter } /** - * Set if transport of access token using URI query parameter is supported. Defaults to {@code false}. - * - * The spec recommends against using this mechanism for sending bearer tokens, and even goes as far as - * stating that it was only included for completeness. + * Set if transport of access token using URI query parameter is supported. Defaults + * to {@code false}. * + * The spec recommends against using this mechanism for sending bearer tokens, and + * even goes as far as stating that it was only included for completeness. * @param allowUriQueryParameter if the URI query parameter is supported */ public void setAllowUriQueryParameter(boolean allowUriQueryParameter) { @@ -95,8 +96,8 @@ public class ServerBearerTokenAuthenticationConverter * Set this value to configure what header is checked when resolving a Bearer Token. * This value is defaulted to {@link HttpHeaders#AUTHORIZATION}. * - * This allows other headers to be used as the Bearer Token source such as {@link HttpHeaders#PROXY_AUTHORIZATION} - * + * This allows other headers to be used as the Bearer Token source such as + * {@link HttpHeaders#PROXY_AUTHORIZATION} * @param bearerTokenHeaderName the header to check when retrieving the Bearer Token. * @since 5.4 */ @@ -109,7 +110,7 @@ public class ServerBearerTokenAuthenticationConverter if (StringUtils.startsWithIgnoreCase(authorization, "bearer")) { Matcher matcher = authorizationPattern.matcher(authorization); - if (!matcher.matches() ) { + if (!matcher.matches()) { BearerTokenError error = invalidTokenError(); throw new OAuth2AuthenticationException(error); } @@ -126,4 +127,5 @@ public class ServerBearerTokenAuthenticationConverter private boolean isParameterTokenSupportedForRequest(ServerHttpRequest request) { return this.allowUriQueryParameter && HttpMethod.GET.equals(request.getMethod()); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/core/TestOAuth2AuthenticatedPrincipals.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/core/TestOAuth2AuthenticatedPrincipals.java index 92c9437a34..dd548a22b4 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/core/TestOAuth2AuthenticatedPrincipals.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/core/TestOAuth2AuthenticatedPrincipals.java @@ -37,8 +37,10 @@ import org.springframework.security.oauth2.server.resource.introspection.OAuth2I * @author Josh Cummings */ public class TestOAuth2AuthenticatedPrincipals { + public static OAuth2AuthenticatedPrincipal active() { - return active(attributes -> {}); + return active(attributes -> { + }); } public static OAuth2AuthenticatedPrincipal active(Consumer> attributesConsumer) { @@ -54,17 +56,18 @@ public class TestOAuth2AuthenticatedPrincipals { attributes.put(OAuth2IntrospectionClaimNames.USERNAME, "jdoe"); attributesConsumer.accept(attributes); - Collection authorities = - Arrays.asList(new SimpleGrantedAuthority("SCOPE_read"), - new SimpleGrantedAuthority("SCOPE_write"), new SimpleGrantedAuthority("SCOPE_dolphin")); + Collection authorities = Arrays.asList(new SimpleGrantedAuthority("SCOPE_read"), + new SimpleGrantedAuthority("SCOPE_write"), new SimpleGrantedAuthority("SCOPE_dolphin")); return new OAuth2IntrospectionAuthenticatedPrincipal(attributes, authorities); } private static URL url(String url) { try { return new URL(url); - } catch (IOException e) { + } + catch (IOException e) { throw new UncheckedIOException(e); } } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/BearerTokenAuthenticationTokenTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/BearerTokenAuthenticationTokenTests.java index ff9b361048..a85e43d25b 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/BearerTokenAuthenticationTokenTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/BearerTokenAuthenticationTokenTests.java @@ -27,17 +27,16 @@ import static org.assertj.core.api.Assertions.assertThatCode; * @author Josh Cummings */ public class BearerTokenAuthenticationTokenTests { + @Test public void constructorWhenTokenIsNullThenThrowsException() { - assertThatCode(() -> new BearerTokenAuthenticationToken(null)) - .isInstanceOf(IllegalArgumentException.class) + assertThatCode(() -> new BearerTokenAuthenticationToken(null)).isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("token cannot be empty"); } @Test public void constructorWhenTokenIsEmptyThenThrowsException() { - assertThatCode(() -> new BearerTokenAuthenticationToken("")) - .isInstanceOf(IllegalArgumentException.class) + assertThatCode(() -> new BearerTokenAuthenticationToken("")).isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("token cannot be empty"); } @@ -49,4 +48,5 @@ public class BearerTokenAuthenticationTokenTests { assertThat(token.getPrincipal()).isEqualTo("token"); assertThat(token.getCredentials()).isEqualTo("token"); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/BearerTokenErrorTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/BearerTokenErrorTests.java index b8d78569e0..ca7c70e5b3 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/BearerTokenErrorTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/BearerTokenErrorTests.java @@ -102,37 +102,30 @@ public class BearerTokenErrorTests { @Test public void constructorWithAllParametersWhenErrorCodeIsInvalidThenThrowIllegalArgumentException() { - assertThatCode(() -> new BearerTokenError(TEST_ERROR_CODE + "\"", TEST_HTTP_STATUS, TEST_DESCRIPTION, - TEST_URI, TEST_SCOPE)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("errorCode") - .hasMessageContaining("RFC 6750"); + assertThatCode(() -> new BearerTokenError(TEST_ERROR_CODE + "\"", TEST_HTTP_STATUS, TEST_DESCRIPTION, TEST_URI, + TEST_SCOPE)).isInstanceOf(IllegalArgumentException.class).hasMessageContaining("errorCode") + .hasMessageContaining("RFC 6750"); } @Test public void constructorWithAllParametersWhenDescriptionIsInvalidThenThrowIllegalArgumentException() { - assertThatCode(() -> new BearerTokenError(TEST_ERROR_CODE, TEST_HTTP_STATUS, TEST_DESCRIPTION + "\"", - TEST_URI, TEST_SCOPE)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("description") - .hasMessageContaining("RFC 6750"); + assertThatCode(() -> new BearerTokenError(TEST_ERROR_CODE, TEST_HTTP_STATUS, TEST_DESCRIPTION + "\"", TEST_URI, + TEST_SCOPE)).isInstanceOf(IllegalArgumentException.class).hasMessageContaining("description") + .hasMessageContaining("RFC 6750"); } @Test public void constructorWithAllParametersWhenErrorUriIsInvalidThenThrowIllegalArgumentException() { - assertThatCode(() -> new BearerTokenError(TEST_ERROR_CODE, TEST_HTTP_STATUS, TEST_DESCRIPTION, - TEST_URI + "\"", TEST_SCOPE)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("errorUri") - .hasMessageContaining("RFC 6750"); + assertThatCode(() -> new BearerTokenError(TEST_ERROR_CODE, TEST_HTTP_STATUS, TEST_DESCRIPTION, TEST_URI + "\"", + TEST_SCOPE)).isInstanceOf(IllegalArgumentException.class).hasMessageContaining("errorUri") + .hasMessageContaining("RFC 6750"); } @Test public void constructorWithAllParametersWhenScopeIsInvalidThenThrowIllegalArgumentException() { - assertThatCode(() -> new BearerTokenError(TEST_ERROR_CODE, TEST_HTTP_STATUS, TEST_DESCRIPTION, - TEST_URI, TEST_SCOPE + "\"")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("scope") - .hasMessageContaining("RFC 6750"); + assertThatCode(() -> new BearerTokenError(TEST_ERROR_CODE, TEST_HTTP_STATUS, TEST_DESCRIPTION, TEST_URI, + TEST_SCOPE + "\"")).isInstanceOf(IllegalArgumentException.class).hasMessageContaining("scope") + .hasMessageContaining("RFC 6750"); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/BearerTokenErrorsTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/BearerTokenErrorsTests.java index c244e68ba4..f84778f545 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/BearerTokenErrorsTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/BearerTokenErrorsTests.java @@ -27,6 +27,7 @@ import static org.springframework.security.oauth2.server.resource.BearerTokenErr import static org.springframework.security.oauth2.server.resource.BearerTokenErrorCodes.INVALID_TOKEN; public class BearerTokenErrorsTests { + @Test public void invalidRequestWhenMessageGivenThenBearerTokenErrorReturned() { String message = "message"; @@ -89,4 +90,5 @@ public class BearerTokenErrorsTests { assertThat(error.getScope()).isNull(); assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1"); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/DefaultAuthenticationEventPublisherBearerTokenTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/DefaultAuthenticationEventPublisherBearerTokenTests.java index d87c0d8acf..84456f738b 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/DefaultAuthenticationEventPublisherBearerTokenTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/DefaultAuthenticationEventPublisherBearerTokenTests.java @@ -36,6 +36,7 @@ import static org.springframework.security.oauth2.jwt.TestJwts.jwt; * {@see DefaultAuthenticationEventPublisher} */ public class DefaultAuthenticationEventPublisherBearerTokenTests { + DefaultAuthenticationEventPublisher publisher; @Test @@ -46,7 +47,7 @@ public class DefaultAuthenticationEventPublisherBearerTokenTests { this.publisher = new DefaultAuthenticationEventPublisher(appPublisher); this.publisher.publishAuthenticationFailure(new InvalidBearerTokenException("invalid"), authentication); this.publisher.publishAuthenticationFailure(new InvalidBearerTokenException("invalid", cause), authentication); - verify(appPublisher, times(2)).publishEvent( - isA(AuthenticationFailureBadCredentialsEvent.class)); + verify(appPublisher, times(2)).publishEvent(isA(AuthenticationFailureBadCredentialsEvent.class)); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationTests.java index 8aa7fefc7f..e8c7b3eb44 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationTests.java @@ -46,12 +46,16 @@ import static org.springframework.security.oauth2.server.resource.introspection. * @author Josh Cummings */ public class BearerTokenAuthenticationTests { - private final OAuth2AccessToken token = - new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "token", Instant.now(), Instant.now().plusSeconds(3600)); + + private final OAuth2AccessToken token = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token", + Instant.now(), Instant.now().plusSeconds(3600)); + private final String name = "sub"; + private Map attributesMap = new HashMap<>(); + private DefaultOAuth2AuthenticatedPrincipal principal; + private final Collection authorities = AuthorityUtils.createAuthorityList("USER"); @Before @@ -64,15 +68,17 @@ public class BearerTokenAuthenticationTests { @Test public void getNameWhenConfiguredInConstructorThenReturnsName() { - OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal(this.name, this.attributesMap, this.authorities); - BearerTokenAuthentication authenticated = new BearerTokenAuthentication(principal, this.token, this.authorities); + OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal(this.name, this.attributesMap, + this.authorities); + BearerTokenAuthentication authenticated = new BearerTokenAuthentication(principal, this.token, + this.authorities); assertThat(authenticated.getName()).isEqualTo(this.name); } @Test public void getNameWhenHasNoSubjectThenReturnsNull() { - OAuth2AuthenticatedPrincipal principal = - new DefaultOAuth2AuthenticatedPrincipal(Collections.singletonMap("claim", "value"), null); + OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal( + Collections.singletonMap("claim", "value"), null); BearerTokenAuthentication authenticated = new BearerTokenAuthentication(principal, this.token, null); assertThat(authenticated.getName()).isNull(); } @@ -86,37 +92,35 @@ public class BearerTokenAuthenticationTests { @Test public void constructorWhenTokenIsNullThenThrowsException() { assertThatCode(() -> new BearerTokenAuthentication(this.principal, null, null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("token cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessageContaining("token cannot be null"); } @Test public void constructorWhenCredentialIsNullThenThrowsException() { assertThatCode(() -> new BearerTokenAuthentication(null, this.token, null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("principal cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessageContaining("principal cannot be null"); } @Test public void constructorWhenPassingAllAttributesThenTokenIsAuthenticated() { - OAuth2AuthenticatedPrincipal principal = - new DefaultOAuth2AuthenticatedPrincipal("harris", Collections.singletonMap("claim", "value"), null); + OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal("harris", + Collections.singletonMap("claim", "value"), null); BearerTokenAuthentication authenticated = new BearerTokenAuthentication(principal, this.token, null); assertThat(authenticated.isAuthenticated()).isTrue(); } @Test public void getTokenAttributesWhenHasTokenThenReturnsThem() { - BearerTokenAuthentication authenticated = - new BearerTokenAuthentication(this.principal, this.token, Collections.emptyList()); + BearerTokenAuthentication authenticated = new BearerTokenAuthentication(this.principal, this.token, + Collections.emptyList()); assertThat(authenticated.getTokenAttributes()).isEqualTo(this.principal.getAttributes()); } @Test public void getAuthoritiesWhenHasAuthoritiesThenReturnsThem() { List authorities = AuthorityUtils.createAuthorityList("USER"); - BearerTokenAuthentication authenticated = - new BearerTokenAuthentication(this.principal, this.token, authorities); + BearerTokenAuthentication authenticated = new BearerTokenAuthentication(this.principal, this.token, + authorities); assertThat(authenticated.getAuthorities()).isEqualTo(authorities); } @@ -137,7 +141,7 @@ public class BearerTokenAuthenticationTests { JSONObject attributes = new JSONObject(Collections.singletonMap("iss", new URL("https://idp.example.com"))); OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal(attributes, null); BearerTokenAuthentication token = new BearerTokenAuthentication(principal, this.token, null); - assertThatCode(token::toString) - .doesNotThrowAnyException(); + assertThatCode(token::toString).doesNotThrowAnyException(); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationConverterTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationConverterTests.java index 6ade846fbc..ad14ba287a 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationConverterTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationConverterTests.java @@ -38,6 +38,7 @@ import static org.springframework.security.oauth2.jwt.TestJwts.jwt; * @author Evgeniy Cheban */ public class JwtAuthenticationConverterTests { + JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); @Test @@ -47,8 +48,7 @@ public class JwtAuthenticationConverterTests { AbstractAuthenticationToken authentication = this.jwtAuthenticationConverter.convert(jwt); Collection authorities = authentication.getAuthorities(); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("SCOPE_message:read"), + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("SCOPE_message:read"), new SimpleGrantedAuthority("SCOPE_message:write")); } @@ -63,16 +63,15 @@ public class JwtAuthenticationConverterTests { public void convertWithOverriddenGrantedAuthoritiesConverter() { Jwt jwt = jwt().claim("scope", "message:read message:write").build(); - Converter> grantedAuthoritiesConverter = - token -> Arrays.asList(new SimpleGrantedAuthority("blah")); + Converter> grantedAuthoritiesConverter = token -> Arrays + .asList(new SimpleGrantedAuthority("blah")); this.jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter); AbstractAuthenticationToken authentication = this.jwtAuthenticationConverter.convert(jwt); Collection authorities = authentication.getAuthorities(); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("blah")); + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("blah")); } @Test @@ -84,8 +83,7 @@ public class JwtAuthenticationConverterTests { @Test public void whenSettingEmptyPrincipalClaimName() { - assertThatIllegalArgumentException() - .isThrownBy(() -> this.jwtAuthenticationConverter.setPrincipalClaimName("")) + assertThatIllegalArgumentException().isThrownBy(() -> this.jwtAuthenticationConverter.setPrincipalClaimName("")) .withMessage("principalClaimName cannot be empty"); } @@ -105,4 +103,5 @@ public class JwtAuthenticationConverterTests { assertThat(authentication.getName()).isEqualTo("100"); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationProviderTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationProviderTests.java index 50db5d9187..fe8c173d54 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationProviderTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationProviderTests.java @@ -46,6 +46,7 @@ import static org.springframework.security.oauth2.jwt.TestJwts.jwt; */ @RunWith(MockitoJUnitRunner.class) public class JwtAuthenticationProviderTests { + @Mock Converter jwtAuthenticationConverter; @@ -56,8 +57,7 @@ public class JwtAuthenticationProviderTests { @Before public void setup() { - this.provider = - new JwtAuthenticationProvider(this.jwtDecoder); + this.provider = new JwtAuthenticationProvider(this.jwtDecoder); this.provider.setJwtAuthenticationConverter(jwtAuthenticationConverter); } @@ -70,8 +70,7 @@ public class JwtAuthenticationProviderTests { when(this.jwtDecoder.decode("token")).thenReturn(jwt); when(this.jwtAuthenticationConverter.convert(jwt)).thenReturn(new JwtAuthenticationToken(jwt)); - JwtAuthenticationToken authentication = - (JwtAuthenticationToken) this.provider.authenticate(token); + JwtAuthenticationToken authentication = (JwtAuthenticationToken) this.provider.authenticate(token); assertThat(authentication.getTokenAttributes()).containsEntry("name", "value"); } @@ -93,11 +92,8 @@ public class JwtAuthenticationProviderTests { when(this.jwtDecoder.decode(token.getToken())).thenThrow(new BadJwtException("with \"invalid\" chars")); - assertThatCode(() -> this.provider.authenticate(token)) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasFieldOrPropertyWithValue( - "error.description", - "Invalid token"); + assertThatCode(() -> this.provider.authenticate(token)).isInstanceOf(OAuth2AuthenticationException.class) + .hasFieldOrPropertyWithValue("error.description", "Invalid token"); } // gh-7785 @@ -107,8 +103,7 @@ public class JwtAuthenticationProviderTests { when(this.jwtDecoder.decode(token.getToken())).thenThrow(new JwtException("no jwk set")); - assertThatCode(() -> this.provider.authenticate(token)) - .isInstanceOf(AuthenticationException.class) + assertThatCode(() -> this.provider.authenticate(token)).isInstanceOf(AuthenticationException.class) .isNotInstanceOf(OAuth2AuthenticationException.class); } @@ -124,9 +119,8 @@ public class JwtAuthenticationProviderTests { when(this.jwtDecoder.decode(token.getToken())).thenReturn(jwt); when(this.jwtAuthenticationConverter.convert(jwt)).thenReturn(authentication); - assertThat(this.provider.authenticate(token)) - .isEqualTo(authentication) - .hasFieldOrPropertyWithValue("details", details); + assertThat(this.provider.authenticate(token)).isEqualTo(authentication).hasFieldOrPropertyWithValue("details", + details); } @Test @@ -139,7 +133,7 @@ public class JwtAuthenticationProviderTests { } private Predicate errorCode(String errorCode) { - return failed -> - ((OAuth2AuthenticationException) failed).getError().getErrorCode() == errorCode; + return failed -> ((OAuth2AuthenticationException) failed).getError().getErrorCode() == errorCode; } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationTokenTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationTokenTests.java index f439abf7d2..5fc65eb8bf 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationTokenTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationTokenTests.java @@ -56,8 +56,7 @@ public class JwtAuthenticationTokenTests { @Test public void constructorWhenJwtIsNullThenThrowsException() { - assertThatCode(() -> new JwtAuthenticationToken(null)) - .isInstanceOf(IllegalArgumentException.class) + assertThatCode(() -> new JwtAuthenticationToken(null)).isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("token cannot be null"); } @@ -127,4 +126,5 @@ public class JwtAuthenticationTokenTests { private Jwt.Builder builder() { return Jwt.withTokenValue("token").header("alg", RS256); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtBearerTokenAuthenticationConverterTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtBearerTokenAuthenticationConverterTests.java index f96073aeb7..db485936f7 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtBearerTokenAuthenticationConverterTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtBearerTokenAuthenticationConverterTests.java @@ -32,15 +32,12 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Josh Cummings */ public class JwtBearerTokenAuthenticationConverterTests { - private final JwtBearerTokenAuthenticationConverter converter = - new JwtBearerTokenAuthenticationConverter(); + + private final JwtBearerTokenAuthenticationConverter converter = new JwtBearerTokenAuthenticationConverter(); @Test public void convertWhenJwtThenBearerTokenAuthentication() { - Jwt jwt = Jwt.withTokenValue("token-value") - .claim("claim", "value") - .header("header", "value") - .build(); + Jwt jwt = Jwt.withTokenValue("token-value").claim("claim", "value").header("header", "value").build(); AbstractAuthenticationToken token = this.converter.convert(jwt); @@ -53,33 +50,28 @@ public class JwtBearerTokenAuthenticationConverterTests { @Test public void convertWhenJwtWithScopeAttributeThenBearerTokenAuthentication() { - Jwt jwt = Jwt.withTokenValue("token-value") - .claim("scope", "message:read message:write") - .header("header", "value") - .build(); + Jwt jwt = Jwt.withTokenValue("token-value").claim("scope", "message:read message:write") + .header("header", "value").build(); AbstractAuthenticationToken token = this.converter.convert(jwt); assertThat(token).isInstanceOf(BearerTokenAuthentication.class); BearerTokenAuthentication bearerToken = (BearerTokenAuthentication) token; - assertThat(bearerToken.getAuthorities()) - .containsExactly(new SimpleGrantedAuthority("SCOPE_message:read"), - new SimpleGrantedAuthority("SCOPE_message:write")); + assertThat(bearerToken.getAuthorities()).containsExactly(new SimpleGrantedAuthority("SCOPE_message:read"), + new SimpleGrantedAuthority("SCOPE_message:write")); } @Test public void convertWhenJwtWithScpAttributeThenBearerTokenAuthentication() { - Jwt jwt = Jwt.withTokenValue("token-value") - .claim("scp", Arrays.asList("message:read", "message:write")) - .header("header", "value") - .build(); + Jwt jwt = Jwt.withTokenValue("token-value").claim("scp", Arrays.asList("message:read", "message:write")) + .header("header", "value").build(); AbstractAuthenticationToken token = this.converter.convert(jwt); assertThat(token).isInstanceOf(BearerTokenAuthentication.class); BearerTokenAuthentication bearerToken = (BearerTokenAuthentication) token; - assertThat(bearerToken.getAuthorities()) - .containsExactly(new SimpleGrantedAuthority("SCOPE_message:read"), - new SimpleGrantedAuthority("SCOPE_message:write")); + assertThat(bearerToken.getAuthorities()).containsExactly(new SimpleGrantedAuthority("SCOPE_message:read"), + new SimpleGrantedAuthority("SCOPE_message:write")); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverterTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverterTests.java index 70ecf618e7..32d1ef773a 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverterTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverterTests.java @@ -50,8 +50,7 @@ public class JwtGrantedAuthoritiesConverterTests { JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); Collection authorities = jwtGrantedAuthoritiesConverter.convert(jwt); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("SCOPE_message:read"), + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("SCOPE_message:read"), new SimpleGrantedAuthority("SCOPE_message:write")); } @@ -63,8 +62,7 @@ public class JwtGrantedAuthoritiesConverterTests { jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_"); Collection authorities = jwtGrantedAuthoritiesConverter.convert(jwt); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("ROLE_message:read"), + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("ROLE_message:read"), new SimpleGrantedAuthority("ROLE_message:write")); } @@ -76,8 +74,7 @@ public class JwtGrantedAuthoritiesConverterTests { jwtGrantedAuthoritiesConverter.setAuthorityPrefix(""); Collection authorities = jwtGrantedAuthoritiesConverter.convert(jwt); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("message:read"), + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("message:read"), new SimpleGrantedAuthority("message:write")); } @@ -98,8 +95,7 @@ public class JwtGrantedAuthoritiesConverterTests { JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); Collection authorities = jwtGrantedAuthoritiesConverter.convert(jwt); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("SCOPE_message:read"), + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("SCOPE_message:read"), new SimpleGrantedAuthority("SCOPE_message:write")); } @@ -111,8 +107,7 @@ public class JwtGrantedAuthoritiesConverterTests { jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_"); Collection authorities = jwtGrantedAuthoritiesConverter.convert(jwt); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("ROLE_message:read"), + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("ROLE_message:read"), new SimpleGrantedAuthority("ROLE_message:write")); } @@ -124,8 +119,7 @@ public class JwtGrantedAuthoritiesConverterTests { jwtGrantedAuthoritiesConverter.setAuthorityPrefix(""); Collection authorities = jwtGrantedAuthoritiesConverter.convert(jwt); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("message:read"), + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("message:read"), new SimpleGrantedAuthority("message:write")); } @@ -141,25 +135,19 @@ public class JwtGrantedAuthoritiesConverterTests { @Test public void convertWhenTokenHasBothScopeAndScpThenScopeAttributeIsTranslatedToAuthorities() { - Jwt jwt = jwt() - .claim("scp", Arrays.asList("message:read", "message:write")) - .claim("scope", "missive:read missive:write") - .build(); + Jwt jwt = jwt().claim("scp", Arrays.asList("message:read", "message:write")) + .claim("scope", "missive:read missive:write").build(); JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); Collection authorities = jwtGrantedAuthoritiesConverter.convert(jwt); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("SCOPE_missive:read"), + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("SCOPE_missive:read"), new SimpleGrantedAuthority("SCOPE_missive:write")); } @Test public void convertWhenTokenHasEmptyScopeAndNonEmptyScpThenScopeAttributeIsTranslatedToNoAuthorities() { - Jwt jwt = jwt() - .claim("scp", Arrays.asList("message:read", "message:write")) - .claim("scope", "") - .build(); + Jwt jwt = jwt().claim("scp", Arrays.asList("message:read", "message:write")).claim("scope", "").build(); JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); Collection authorities = jwtGrantedAuthoritiesConverter.convert(jwt); @@ -169,10 +157,7 @@ public class JwtGrantedAuthoritiesConverterTests { @Test public void convertWhenTokenHasEmptyScopeAndEmptyScpAttributeThenTranslatesToNoAuthorities() { - Jwt jwt = jwt() - .claim("scp", Collections.emptyList()) - .claim("scope", Collections.emptyList()) - .build(); + Jwt jwt = jwt().claim("scp", Collections.emptyList()).claim("scope", Collections.emptyList()).build(); JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); Collection authorities = jwtGrantedAuthoritiesConverter.convert(jwt); @@ -192,7 +177,7 @@ public class JwtGrantedAuthoritiesConverterTests { @Test public void convertWhenTokenHasUnsupportedTypeForScopeThenTranslatesToNoAuthorities() { - Jwt jwt = jwt().claim("scope", new String[] {"message:read", "message:write"}).build(); + Jwt jwt = jwt().claim("scope", new String[] { "message:read", "message:write" }).build(); JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); Collection authorities = jwtGrantedAuthoritiesConverter.convert(jwt); @@ -202,26 +187,20 @@ public class JwtGrantedAuthoritiesConverterTests { @Test public void convertWhenTokenHasCustomClaimNameThenCustomClaimNameAttributeIsTranslatedToAuthorities() { - Jwt jwt = jwt() - .claim("roles", Arrays.asList("message:read", "message:write")) - .claim("scope", "missive:read missive:write") - .build(); + Jwt jwt = jwt().claim("roles", Arrays.asList("message:read", "message:write")) + .claim("scope", "missive:read missive:write").build(); JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("roles"); Collection authorities = jwtGrantedAuthoritiesConverter.convert(jwt); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("SCOPE_message:read"), + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("SCOPE_message:read"), new SimpleGrantedAuthority("SCOPE_message:write")); } @Test public void convertWhenTokenHasEmptyCustomClaimNameThenCustomClaimNameAttributeIsTranslatedToNoAuthorities() { - Jwt jwt = jwt() - .claim("roles", Collections.emptyList()) - .claim("scope", "missive:read missive:write") - .build(); + Jwt jwt = jwt().claim("roles", Collections.emptyList()).claim("scope", "missive:read missive:write").build(); JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("roles"); @@ -240,4 +219,5 @@ public class JwtGrantedAuthoritiesConverterTests { assertThat(authorities).isEmpty(); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java index 21df5189fe..1cab4a21c5 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java @@ -48,13 +48,14 @@ import static org.springframework.security.oauth2.jwt.JwtClaimNames.ISS; * Tests for {@link JwtIssuerAuthenticationManagerResolver} */ public class JwtIssuerAuthenticationManagerResolverTests { - private static final String DEFAULT_RESPONSE_TEMPLATE = "{\n" - + " \"issuer\": \"%s\", \n" - + " \"jwks_uri\": \"%s/.well-known/jwks.json\" \n" - + "}"; + + private static final String DEFAULT_RESPONSE_TEMPLATE = "{\n" + " \"issuer\": \"%s\", \n" + + " \"jwks_uri\": \"%s/.well-known/jwks.json\" \n" + "}"; private String jwt = jwt("iss", "trusted"); + private String evil = jwt("iss", "\""); + private String noIssuer = jwt("sub", "sub"); @Test @@ -62,51 +63,45 @@ public class JwtIssuerAuthenticationManagerResolverTests { try (MockWebServer server = new MockWebServer()) { server.start(); String issuer = server.url("").toString(); - server.enqueue(new MockResponse() - .setResponseCode(200) - .setHeader("Content-Type", "application/json") + server.enqueue(new MockResponse().setResponseCode(200).setHeader("Content-Type", "application/json") .setBody(String.format(DEFAULT_RESPONSE_TEMPLATE, issuer, issuer))); JWSObject jws = new JWSObject(new JWSHeader(JWSAlgorithm.RS256), new Payload(new JSONObject(Collections.singletonMap(ISS, issuer)))); jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY)); - JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerAuthenticationManagerResolver(issuer); + JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( + issuer); MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Authorization", "Bearer " + jws.serialize()); - AuthenticationManager authenticationManager = - authenticationManagerResolver.resolve(request); + AuthenticationManager authenticationManager = authenticationManagerResolver.resolve(request); assertThat(authenticationManager).isNotNull(); - AuthenticationManager cachedAuthenticationManager = - authenticationManagerResolver.resolve(request); + AuthenticationManager cachedAuthenticationManager = authenticationManagerResolver.resolve(request); assertThat(authenticationManager).isSameAs(cachedAuthenticationManager); } } @Test public void resolveWhenUsingUntrustedIssuerThenException() { - JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerAuthenticationManagerResolver("other", "issuers"); + JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( + "other", "issuers"); MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Authorization", "Bearer " + this.jwt); assertThatCode(() -> authenticationManagerResolver.resolve(request)) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageContaining("Invalid issuer"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageContaining("Invalid issuer"); } @Test public void resolveWhenUsingCustomIssuerAuthenticationManagerResolverThenUses() { AuthenticationManager authenticationManager = mock(AuthenticationManager.class); - JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerAuthenticationManagerResolver(issuer -> authenticationManager); + JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( + issuer -> authenticationManager); MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Authorization", "Bearer " + this.jwt); - assertThat(authenticationManagerResolver.resolve(request)) - .isSameAs(authenticationManager); + assertThat(authenticationManagerResolver.resolve(request)).isSameAs(authenticationManager); } @Test @@ -115,54 +110,48 @@ public class JwtIssuerAuthenticationManagerResolverTests { request.addHeader("Authorization", "Bearer " + this.jwt); Map authenticationManagers = new HashMap<>(); - JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerAuthenticationManagerResolver(authenticationManagers::get); + JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( + authenticationManagers::get); assertThatCode(() -> authenticationManagerResolver.resolve(request)) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageContaining("Invalid issuer"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageContaining("Invalid issuer"); AuthenticationManager authenticationManager = mock(AuthenticationManager.class); authenticationManagers.put("trusted", authenticationManager); - assertThat(authenticationManagerResolver.resolve(request)) - .isSameAs(authenticationManager); + assertThat(authenticationManagerResolver.resolve(request)).isSameAs(authenticationManager); authenticationManagers.clear(); assertThatCode(() -> authenticationManagerResolver.resolve(request)) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageContaining("Invalid issuer"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageContaining("Invalid issuer"); } @Test public void resolveWhenBearerTokenMalformedThenException() { - JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerAuthenticationManagerResolver("trusted"); + JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( + "trusted"); MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Authorization", "Bearer jwt"); assertThatCode(() -> authenticationManagerResolver.resolve(request)) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageNotContaining("Invalid issuer"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageNotContaining("Invalid issuer"); } @Test public void resolveWhenBearerTokenNoIssuerThenException() { - JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerAuthenticationManagerResolver("trusted"); + JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( + "trusted"); MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Authorization", "Bearer " + this.noIssuer); assertThatCode(() -> authenticationManagerResolver.resolve(request)) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageContaining("Missing issuer"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageContaining("Missing issuer"); } @Test public void resolveWhenBearerTokenEvilThenGenericException() { - JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerAuthenticationManagerResolver("trusted"); + JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver( + "trusted"); MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Authorization", "Bearer " + this.evil); assertThatCode(() -> authenticationManagerResolver.resolve(request)) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessage("Invalid issuer"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessage("Invalid issuer"); } @Test @@ -183,4 +172,5 @@ public class JwtIssuerAuthenticationManagerResolverTests { PlainJWT jwt = new PlainJWT(new JWTClaimsSet.Builder().claim(claim, value).build()); return jwt.serialize(); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java index d694707096..58e545ff03 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java @@ -50,61 +50,58 @@ import static org.springframework.security.oauth2.jwt.JwtClaimNames.ISS; * Tests for {@link JwtIssuerReactiveAuthenticationManagerResolver} */ public class JwtIssuerReactiveAuthenticationManagerResolverTests { - private static final String DEFAULT_RESPONSE_TEMPLATE = "{\n" - + " \"issuer\": \"%s\", \n" - + " \"jwks_uri\": \"%s/.well-known/jwks.json\" \n" - + "}"; + + private static final String DEFAULT_RESPONSE_TEMPLATE = "{\n" + " \"issuer\": \"%s\", \n" + + " \"jwks_uri\": \"%s/.well-known/jwks.json\" \n" + "}"; private String jwt = jwt("iss", "trusted"); + private String evil = jwt("iss", "\""); + private String noIssuer = jwt("sub", "sub"); @Test public void resolveWhenUsingTrustedIssuerThenReturnsAuthenticationManager() throws Exception { try (MockWebServer server = new MockWebServer()) { String issuer = server.url("").toString(); - server.enqueue(new MockResponse() - .setResponseCode(200) - .setHeader("Content-Type", "application/json") + server.enqueue(new MockResponse().setResponseCode(200).setHeader("Content-Type", "application/json") .setBody(String.format(DEFAULT_RESPONSE_TEMPLATE, issuer, issuer))); JWSObject jws = new JWSObject(new JWSHeader(JWSAlgorithm.RS256), new Payload(new JSONObject(Collections.singletonMap(ISS, issuer)))); jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY)); - JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerReactiveAuthenticationManagerResolver(issuer); + JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver( + issuer); MockServerWebExchange exchange = withBearerToken(jws.serialize()); - ReactiveAuthenticationManager authenticationManager = - authenticationManagerResolver.resolve(exchange).block(); + ReactiveAuthenticationManager authenticationManager = authenticationManagerResolver.resolve(exchange) + .block(); assertThat(authenticationManager).isNotNull(); - ReactiveAuthenticationManager cachedAuthenticationManager = - authenticationManagerResolver.resolve(exchange).block(); + ReactiveAuthenticationManager cachedAuthenticationManager = authenticationManagerResolver.resolve(exchange) + .block(); assertThat(authenticationManager).isSameAs(cachedAuthenticationManager); } } @Test public void resolveWhenUsingUntrustedIssuerThenException() { - JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerReactiveAuthenticationManagerResolver("other", "issuers"); + JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver( + "other", "issuers"); MockServerWebExchange exchange = withBearerToken(this.jwt); assertThatCode(() -> authenticationManagerResolver.resolve(exchange).block()) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageContaining("Invalid issuer"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageContaining("Invalid issuer"); } @Test public void resolveWhenUsingCustomIssuerAuthenticationManagerResolverThenUses() { ReactiveAuthenticationManager authenticationManager = mock(ReactiveAuthenticationManager.class); - JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerReactiveAuthenticationManagerResolver(issuer -> Mono.just(authenticationManager)); + JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver( + issuer -> Mono.just(authenticationManager)); MockServerWebExchange exchange = withBearerToken(this.jwt); - assertThat(authenticationManagerResolver.resolve(exchange).block()) - .isSameAs(authenticationManager); + assertThat(authenticationManagerResolver.resolve(exchange).block()).isSameAs(authenticationManager); } @Test @@ -112,51 +109,45 @@ public class JwtIssuerReactiveAuthenticationManagerResolverTests { MockServerWebExchange exchange = withBearerToken(this.jwt); Map authenticationManagers = new HashMap<>(); - JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerReactiveAuthenticationManagerResolver(issuer -> Mono.justOrEmpty(authenticationManagers.get(issuer))); + JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver( + issuer -> Mono.justOrEmpty(authenticationManagers.get(issuer))); assertThatCode(() -> authenticationManagerResolver.resolve(exchange).block()) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageContaining("Invalid issuer"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageContaining("Invalid issuer"); ReactiveAuthenticationManager authenticationManager = mock(ReactiveAuthenticationManager.class); authenticationManagers.put("trusted", authenticationManager); - assertThat(authenticationManagerResolver.resolve(exchange).block()) - .isSameAs(authenticationManager); + assertThat(authenticationManagerResolver.resolve(exchange).block()).isSameAs(authenticationManager); authenticationManagers.clear(); assertThatCode(() -> authenticationManagerResolver.resolve(exchange).block()) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageContaining("Invalid issuer"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageContaining("Invalid issuer"); } @Test public void resolveWhenBearerTokenMalformedThenException() { - JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerReactiveAuthenticationManagerResolver("trusted"); + JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver( + "trusted"); MockServerWebExchange exchange = withBearerToken("jwt"); assertThatCode(() -> authenticationManagerResolver.resolve(exchange).block()) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageNotContaining("Invalid issuer"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageNotContaining("Invalid issuer"); } @Test public void resolveWhenBearerTokenNoIssuerThenException() { - JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerReactiveAuthenticationManagerResolver("trusted"); + JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver( + "trusted"); MockServerWebExchange exchange = withBearerToken(this.noIssuer); assertThatCode(() -> authenticationManagerResolver.resolve(exchange).block()) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessageContaining("Missing issuer"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessageContaining("Missing issuer"); } @Test public void resolveWhenBearerTokenEvilThenGenericException() { - JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = - new JwtIssuerReactiveAuthenticationManagerResolver("trusted"); + JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver( + "trusted"); MockServerWebExchange exchange = withBearerToken(this.evil); assertThatCode(() -> authenticationManagerResolver.resolve(exchange).block()) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasMessage("Invalid token"); + .isInstanceOf(OAuth2AuthenticationException.class).hasMessage("Invalid token"); } @Test @@ -169,8 +160,9 @@ public class JwtIssuerReactiveAuthenticationManagerResolverTests { @Test public void constructorWhenNullAuthenticationManagerResolverThenException() { - assertThatCode(() -> new JwtIssuerReactiveAuthenticationManagerResolver((ReactiveAuthenticationManagerResolver) null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode( + () -> new JwtIssuerReactiveAuthenticationManagerResolver((ReactiveAuthenticationManagerResolver) null)) + .isInstanceOf(IllegalArgumentException.class); } private String jwt(String claim, String value) { @@ -179,8 +171,9 @@ public class JwtIssuerReactiveAuthenticationManagerResolverTests { } private MockServerWebExchange withBearerToken(String token) { - MockServerHttpRequest request = MockServerHttpRequest.get("/") - .header("Authorization", "Bearer " + token).build(); + MockServerHttpRequest request = MockServerHttpRequest.get("/").header("Authorization", "Bearer " + token) + .build(); return MockServerWebExchange.from(request); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtReactiveAuthenticationManagerTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtReactiveAuthenticationManagerTests.java index 8317aaba58..5764da170f 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtReactiveAuthenticationManagerTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtReactiveAuthenticationManagerTests.java @@ -46,6 +46,7 @@ import static org.springframework.security.oauth2.jwt.TestJwts.jwt; */ @RunWith(MockitoJUnitRunner.class) public class JwtReactiveAuthenticationManagerTests { + @Mock private ReactiveJwtDecoder jwtDecoder; @@ -96,11 +97,8 @@ public class JwtReactiveAuthenticationManagerTests { BearerTokenAuthenticationToken token = new BearerTokenAuthenticationToken("token-1"); when(this.jwtDecoder.decode(token.getToken())).thenThrow(new BadJwtException("with \"invalid\" chars")); - assertThatCode(() -> this.manager.authenticate(token).block()) - .isInstanceOf(OAuth2AuthenticationException.class) - .hasFieldOrPropertyWithValue( - "error.description", - "Invalid token"); + assertThatCode(() -> this.manager.authenticate(token).block()).isInstanceOf(OAuth2AuthenticationException.class) + .hasFieldOrPropertyWithValue("error.description", "Invalid token"); } // gh-7785 @@ -109,8 +107,7 @@ public class JwtReactiveAuthenticationManagerTests { BearerTokenAuthenticationToken token = new BearerTokenAuthenticationToken("token-1"); when(this.jwtDecoder.decode(token.getToken())).thenThrow(new JwtException("no jwk set")); - assertThatCode(() -> this.manager.authenticate(token).block()) - .isInstanceOf(AuthenticationException.class) + assertThatCode(() -> this.manager.authenticate(token).block()).isInstanceOf(AuthenticationException.class) .isNotInstanceOf(OAuth2AuthenticationException.class); } @@ -119,8 +116,7 @@ public class JwtReactiveAuthenticationManagerTests { BearerTokenAuthenticationToken token = new BearerTokenAuthenticationToken("token-1"); when(this.jwtDecoder.decode(any())).thenReturn(Mono.error(new RuntimeException("Oops"))); - assertThatCode(() -> this.manager.authenticate(token).block()) - .isInstanceOf(RuntimeException.class); + assertThatCode(() -> this.manager.authenticate(token).block()).isInstanceOf(RuntimeException.class); } @Test @@ -132,6 +128,8 @@ public class JwtReactiveAuthenticationManagerTests { assertThat(authentication).isNotNull(); assertThat(authentication.isAuthenticated()).isTrue(); - assertThat(authentication.getAuthorities()).extracting(GrantedAuthority::getAuthority).containsOnly("SCOPE_message:read", "SCOPE_message:write"); + assertThat(authentication.getAuthorities()).extracting(GrantedAuthority::getAuthority) + .containsOnly("SCOPE_message:read", "SCOPE_message:write"); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProviderTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProviderTests.java index 61496ff77d..0609e5bba3 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProviderTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProviderTests.java @@ -53,51 +53,47 @@ import static org.springframework.security.oauth2.server.resource.introspection. * @author Josh Cummings */ public class OpaqueTokenAuthenticationProviderTests { + @Test public void authenticateWhenActiveTokenThenOk() throws Exception { - OAuth2AuthenticatedPrincipal principal = active(attributes -> attributes.put("extension_field", "twenty-seven")); + OAuth2AuthenticatedPrincipal principal = active( + attributes -> attributes.put("extension_field", "twenty-seven")); OpaqueTokenIntrospector introspector = mock(OpaqueTokenIntrospector.class); when(introspector.introspect(any())).thenReturn(principal); OpaqueTokenAuthenticationProvider provider = new OpaqueTokenAuthenticationProvider(introspector); - Authentication result = - provider.authenticate(new BearerTokenAuthenticationToken("token")); + Authentication result = provider.authenticate(new BearerTokenAuthenticationToken("token")); assertThat(result.getPrincipal()).isInstanceOf(OAuth2IntrospectionAuthenticatedPrincipal.class); Map attributes = ((OAuth2AuthenticatedPrincipal) result.getPrincipal()).getAttributes(); - assertThat(attributes) - .isNotNull() - .containsEntry(ACTIVE, true) + assertThat(attributes).isNotNull().containsEntry(ACTIVE, true) .containsEntry(AUDIENCE, Arrays.asList("https://protected.example.net/resource")) .containsEntry(OAuth2IntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4") .containsEntry(EXPIRES_AT, Instant.ofEpochSecond(1419356238)) .containsEntry(ISSUER, new URL("https://server.example.com/")) .containsEntry(NOT_BEFORE, Instant.ofEpochSecond(29348723984L)) .containsEntry(SCOPE, Arrays.asList("read", "write", "dolphin")) - .containsEntry(SUBJECT, "Z5O3upPC88QrAjx00dis") - .containsEntry(USERNAME, "jdoe") + .containsEntry(SUBJECT, "Z5O3upPC88QrAjx00dis").containsEntry(USERNAME, "jdoe") .containsEntry("extension_field", "twenty-seven"); - assertThat(result.getAuthorities()).extracting("authority") - .containsExactly("SCOPE_read", "SCOPE_write", "SCOPE_dolphin"); + assertThat(result.getAuthorities()).extracting("authority").containsExactly("SCOPE_read", "SCOPE_write", + "SCOPE_dolphin"); } @Test public void authenticateWhenMissingScopeAttributeThenNoAuthorities() { - OAuth2AuthenticatedPrincipal principal = new OAuth2IntrospectionAuthenticatedPrincipal(Collections.singletonMap("claim", "value"), null); + OAuth2AuthenticatedPrincipal principal = new OAuth2IntrospectionAuthenticatedPrincipal( + Collections.singletonMap("claim", "value"), null); OpaqueTokenIntrospector introspector = mock(OpaqueTokenIntrospector.class); when(introspector.introspect(any())).thenReturn(principal); OpaqueTokenAuthenticationProvider provider = new OpaqueTokenAuthenticationProvider(introspector); - Authentication result = - provider.authenticate(new BearerTokenAuthenticationToken("token")); + Authentication result = provider.authenticate(new BearerTokenAuthenticationToken("token")); assertThat(result.getPrincipal()).isInstanceOf(OAuth2AuthenticatedPrincipal.class); Map attributes = ((OAuth2AuthenticatedPrincipal) result.getPrincipal()).getAttributes(); - assertThat(attributes) - .isNotNull() - .doesNotContainKey(SCOPE); + assertThat(attributes).isNotNull().doesNotContainKey(SCOPE); assertThat(result.getAuthorities()).isEmpty(); } @@ -114,7 +110,7 @@ public class OpaqueTokenAuthenticationProviderTests { @Test public void constructorWhenIntrospectionClientIsNullThenIllegalArgumentException() { - assertThatCode(() -> new OpaqueTokenAuthenticationProvider(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> new OpaqueTokenAuthenticationProvider(null)).isInstanceOf(IllegalArgumentException.class); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManagerTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManagerTests.java index e7b92f8a45..c6d6297c72 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManagerTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManagerTests.java @@ -55,53 +55,47 @@ import static org.springframework.security.oauth2.server.resource.introspection. * @author Josh Cummings */ public class OpaqueTokenReactiveAuthenticationManagerTests { + @Test public void authenticateWhenActiveTokenThenOk() throws Exception { - OAuth2AuthenticatedPrincipal authority = active(attributes -> attributes.put("extension_field", "twenty-seven")); + OAuth2AuthenticatedPrincipal authority = active( + attributes -> attributes.put("extension_field", "twenty-seven")); ReactiveOpaqueTokenIntrospector introspector = mock(ReactiveOpaqueTokenIntrospector.class); when(introspector.introspect(any())).thenReturn(Mono.just(authority)); - OpaqueTokenReactiveAuthenticationManager provider = - new OpaqueTokenReactiveAuthenticationManager(introspector); + OpaqueTokenReactiveAuthenticationManager provider = new OpaqueTokenReactiveAuthenticationManager(introspector); - Authentication result = - provider.authenticate(new BearerTokenAuthenticationToken("token")).block(); + Authentication result = provider.authenticate(new BearerTokenAuthenticationToken("token")).block(); assertThat(result.getPrincipal()).isInstanceOf(OAuth2IntrospectionAuthenticatedPrincipal.class); Map attributes = ((OAuth2AuthenticatedPrincipal) result.getPrincipal()).getAttributes(); - assertThat(attributes) - .isNotNull() - .containsEntry(ACTIVE, true) + assertThat(attributes).isNotNull().containsEntry(ACTIVE, true) .containsEntry(AUDIENCE, Arrays.asList("https://protected.example.net/resource")) .containsEntry(OAuth2IntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4") .containsEntry(EXPIRES_AT, Instant.ofEpochSecond(1419356238)) .containsEntry(ISSUER, new URL("https://server.example.com/")) .containsEntry(NOT_BEFORE, Instant.ofEpochSecond(29348723984L)) .containsEntry(SCOPE, Arrays.asList("read", "write", "dolphin")) - .containsEntry(SUBJECT, "Z5O3upPC88QrAjx00dis") - .containsEntry(USERNAME, "jdoe") + .containsEntry(SUBJECT, "Z5O3upPC88QrAjx00dis").containsEntry(USERNAME, "jdoe") .containsEntry("extension_field", "twenty-seven"); - assertThat(result.getAuthorities()).extracting("authority") - .containsExactly("SCOPE_read", "SCOPE_write", "SCOPE_dolphin"); + assertThat(result.getAuthorities()).extracting("authority").containsExactly("SCOPE_read", "SCOPE_write", + "SCOPE_dolphin"); } @Test public void authenticateWhenMissingScopeAttributeThenNoAuthorities() { - OAuth2AuthenticatedPrincipal authority = new OAuth2IntrospectionAuthenticatedPrincipal(Collections.singletonMap("claim", "value"), null); + OAuth2AuthenticatedPrincipal authority = new OAuth2IntrospectionAuthenticatedPrincipal( + Collections.singletonMap("claim", "value"), null); ReactiveOpaqueTokenIntrospector introspector = mock(ReactiveOpaqueTokenIntrospector.class); when(introspector.introspect(any())).thenReturn(Mono.just(authority)); - OpaqueTokenReactiveAuthenticationManager provider = - new OpaqueTokenReactiveAuthenticationManager(introspector); + OpaqueTokenReactiveAuthenticationManager provider = new OpaqueTokenReactiveAuthenticationManager(introspector); - Authentication result = - provider.authenticate(new BearerTokenAuthenticationToken("token")).block(); + Authentication result = provider.authenticate(new BearerTokenAuthenticationToken("token")).block(); assertThat(result.getPrincipal()).isInstanceOf(OAuth2IntrospectionAuthenticatedPrincipal.class); Map attributes = ((OAuth2AuthenticatedPrincipal) result.getPrincipal()).getAttributes(); - assertThat(attributes) - .isNotNull() - .doesNotContainKey(SCOPE); + assertThat(attributes).isNotNull().doesNotContainKey(SCOPE); assertThat(result.getAuthorities()).isEmpty(); } @@ -111,8 +105,7 @@ public class OpaqueTokenReactiveAuthenticationManagerTests { ReactiveOpaqueTokenIntrospector introspector = mock(ReactiveOpaqueTokenIntrospector.class); when(introspector.introspect(any())) .thenReturn(Mono.error(new OAuth2IntrospectionException("with \"invalid\" chars"))); - OpaqueTokenReactiveAuthenticationManager provider = - new OpaqueTokenReactiveAuthenticationManager(introspector); + OpaqueTokenReactiveAuthenticationManager provider = new OpaqueTokenReactiveAuthenticationManager(introspector); assertThatCode(() -> provider.authenticate(new BearerTokenAuthenticationToken("token")).block()) .isInstanceOf(AuthenticationServiceException.class); @@ -123,4 +116,5 @@ public class OpaqueTokenReactiveAuthenticationManagerTests { assertThatCode(() -> new OpaqueTokenReactiveAuthenticationManager(null)) .isInstanceOf(IllegalArgumentException.class); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverterAdapterTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverterAdapterTests.java index 6e076f0677..f9bfc8bc7d 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverterAdapterTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverterAdapterTests.java @@ -36,9 +36,11 @@ import static org.springframework.security.oauth2.jwt.TestJwts.jwt; * @author Josh Cummings */ public class ReactiveJwtAuthenticationConverterAdapterTests { + Converter converter = new JwtAuthenticationConverter(); - ReactiveJwtAuthenticationConverterAdapter jwtAuthenticationConverter = - new ReactiveJwtAuthenticationConverterAdapter(converter); + + ReactiveJwtAuthenticationConverterAdapter jwtAuthenticationConverter = new ReactiveJwtAuthenticationConverterAdapter( + converter); @Test public void convertWhenTokenHasScopeAttributeThenTranslatedToAuthorities() { @@ -47,8 +49,7 @@ public class ReactiveJwtAuthenticationConverterAdapterTests { AbstractAuthenticationToken authentication = this.jwtAuthenticationConverter.convert(jwt).block(); Collection authorities = authentication.getAuthorities(); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("SCOPE_message:read"), + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("SCOPE_message:read"), new SimpleGrantedAuthority("SCOPE_message:write")); } @@ -71,8 +72,7 @@ public class ReactiveJwtAuthenticationConverterAdapterTests { Collection authorities = authentication.getAuthorities(); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("SCOPE_message:read"), + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("SCOPE_message:read"), new SimpleGrantedAuthority("SCOPE_message:write")); } @@ -89,26 +89,20 @@ public class ReactiveJwtAuthenticationConverterAdapterTests { @Test public void convertWhenTokenHasBothScopeAndScpThenScopeAttributeIsTranslatedToAuthorities() { - Jwt jwt = jwt() - .claim("scp", Arrays.asList("message:read", "message:write")) - .claim("scope", "missive:read missive:write") - .build(); + Jwt jwt = jwt().claim("scp", Arrays.asList("message:read", "message:write")) + .claim("scope", "missive:read missive:write").build(); AbstractAuthenticationToken authentication = this.jwtAuthenticationConverter.convert(jwt).block(); Collection authorities = authentication.getAuthorities(); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("SCOPE_missive:read"), + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("SCOPE_missive:read"), new SimpleGrantedAuthority("SCOPE_missive:write")); } @Test public void convertWhenTokenHasEmptyScopeAndNonEmptyScpThenScopeAttributeIsTranslatedToNoAuthorities() { - Jwt jwt = jwt() - .claim("scp", Arrays.asList("message:read", "message:write")) - .claim("scope", "") - .build(); + Jwt jwt = jwt().claim("scp", Arrays.asList("message:read", "message:write")).claim("scope", "").build(); AbstractAuthenticationToken authentication = this.jwtAuthenticationConverter.convert(jwt).block(); @@ -116,4 +110,5 @@ public class ReactiveJwtAuthenticationConverterAdapterTests { assertThat(authorities).containsExactly(); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverterTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverterTests.java index 809c76be1d..2eb01d4dfd 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverterTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtAuthenticationConverterTests.java @@ -38,6 +38,7 @@ import static org.springframework.security.oauth2.jwt.TestJwts.jwt; * @since 5.2 */ public class ReactiveJwtAuthenticationConverterTests { + ReactiveJwtAuthenticationConverter jwtAuthenticationConverter = new ReactiveJwtAuthenticationConverter(); @Test @@ -47,8 +48,7 @@ public class ReactiveJwtAuthenticationConverterTests { AbstractAuthenticationToken authentication = this.jwtAuthenticationConverter.convert(jwt).block(); Collection authorities = authentication.getAuthorities(); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("SCOPE_message:read"), + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("SCOPE_message:read"), new SimpleGrantedAuthority("SCOPE_message:write")); } @@ -63,15 +63,15 @@ public class ReactiveJwtAuthenticationConverterTests { public void convertWithOverriddenGrantedAuthoritiesConverter() { Jwt jwt = jwt().claim("scope", "message:read message:write").build(); - Converter> grantedAuthoritiesConverter = - token -> Flux.just(new SimpleGrantedAuthority("blah")); + Converter> grantedAuthoritiesConverter = token -> Flux + .just(new SimpleGrantedAuthority("blah")); this.jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter); AbstractAuthenticationToken authentication = this.jwtAuthenticationConverter.convert(jwt).block(); Collection authorities = authentication.getAuthorities(); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("blah")); + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("blah")); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtGrantedAuthoritiesConverterAdapterTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtGrantedAuthoritiesConverterAdapterTests.java index e7ff494522..3966b0b4f0 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtGrantedAuthoritiesConverterAdapterTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/ReactiveJwtGrantedAuthoritiesConverterAdapterTests.java @@ -38,27 +38,24 @@ import static org.springframework.security.oauth2.jwt.TestJwts.jwt; * @since 5.2 */ public class ReactiveJwtGrantedAuthoritiesConverterAdapterTests { + @Test public void convertWithGrantedAuthoritiesConverter() { Jwt jwt = jwt().claim("scope", "message:read message:write").build(); - Converter> grantedAuthoritiesConverter = - token -> Arrays.asList(new SimpleGrantedAuthority("blah")); + Converter> grantedAuthoritiesConverter = token -> Arrays + .asList(new SimpleGrantedAuthority("blah")); - Collection authorities = - new ReactiveJwtGrantedAuthoritiesConverterAdapter(grantedAuthoritiesConverter) - .convert(jwt) - .toStream() - .collect(Collectors.toList()); + Collection authorities = new ReactiveJwtGrantedAuthoritiesConverterAdapter( + grantedAuthoritiesConverter).convert(jwt).toStream().collect(Collectors.toList()); - assertThat(authorities).containsExactly( - new SimpleGrantedAuthority("blah")); + assertThat(authorities).containsExactly(new SimpleGrantedAuthority("blah")); } @Test public void whenConstructingWithInvalidConverter() { - assertThatIllegalArgumentException() - .isThrownBy(() -> new ReactiveJwtGrantedAuthoritiesConverterAdapter(null)) + assertThatIllegalArgumentException().isThrownBy(() -> new ReactiveJwtGrantedAuthoritiesConverterAdapter(null)) .withMessage("grantedAuthoritiesConverter cannot be null"); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/TestBearerTokenAuthentications.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/TestBearerTokenAuthentications.java index 72a2584005..d02af90c84 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/TestBearerTokenAuthentications.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/TestBearerTokenAuthentications.java @@ -34,18 +34,15 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; * @author Josh Cummings */ public class TestBearerTokenAuthentications { + public static BearerTokenAuthentication bearer() { - Collection authorities = - AuthorityUtils.createAuthorityList("SCOPE_USER"); - OAuth2AuthenticatedPrincipal principal = - new DefaultOAuth2AuthenticatedPrincipal( - Collections.singletonMap("sub", "user"), - authorities); - OAuth2AccessToken token = - new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "token", Instant.now(), Instant.now().plusSeconds(86400), - new HashSet<>(Arrays.asList("USER"))); + Collection authorities = AuthorityUtils.createAuthorityList("SCOPE_USER"); + OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal( + Collections.singletonMap("sub", "user"), authorities); + OAuth2AccessToken token = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token", Instant.now(), + Instant.now().plusSeconds(86400), new HashSet<>(Arrays.asList("USER"))); return new BearerTokenAuthentication(principal, token, authorities); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospectorTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospectorTests.java index 8b49fb98e4..b2791a83cc 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospectorTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospectorTests.java @@ -64,94 +64,76 @@ import static org.springframework.security.oauth2.server.resource.introspection. public class NimbusOpaqueTokenIntrospectorTests { private static final String INTROSPECTION_URL = "https://server.example.com"; + private static final String CLIENT_ID = "client"; + private static final String CLIENT_SECRET = "secret"; - private static final String ACTIVE_RESPONSE = "{\n" + - " \"active\": true,\n" + - " \"client_id\": \"l238j323ds-23ij4\",\n" + - " \"username\": \"jdoe\",\n" + - " \"scope\": \"read write dolphin\",\n" + - " \"sub\": \"Z5O3upPC88QrAjx00dis\",\n" + - " \"aud\": \"https://protected.example.net/resource\",\n" + - " \"iss\": \"https://server.example.com/\",\n" + - " \"exp\": 1419356238,\n" + - " \"iat\": 1419350238,\n" + - " \"extension_field\": \"twenty-seven\"\n" + - " }"; + private static final String ACTIVE_RESPONSE = "{\n" + " \"active\": true,\n" + + " \"client_id\": \"l238j323ds-23ij4\",\n" + " \"username\": \"jdoe\",\n" + + " \"scope\": \"read write dolphin\",\n" + " \"sub\": \"Z5O3upPC88QrAjx00dis\",\n" + + " \"aud\": \"https://protected.example.net/resource\",\n" + + " \"iss\": \"https://server.example.com/\",\n" + " \"exp\": 1419356238,\n" + + " \"iat\": 1419350238,\n" + " \"extension_field\": \"twenty-seven\"\n" + " }"; - private static final String INACTIVE_RESPONSE = "{\n" + - " \"active\": false\n" + - " }"; + private static final String INACTIVE_RESPONSE = "{\n" + " \"active\": false\n" + " }"; - private static final String INVALID_RESPONSE = "{\n" + - " \"client_id\": \"l238j323ds-23ij4\",\n" + - " \"username\": \"jdoe\",\n" + - " \"scope\": \"read write dolphin\",\n" + - " \"sub\": \"Z5O3upPC88QrAjx00dis\",\n" + - " \"aud\": \"https://protected.example.net/resource\",\n" + - " \"iss\": \"https://server.example.com/\",\n" + - " \"exp\": 1419356238,\n" + - " \"iat\": 1419350238,\n" + - " \"extension_field\": \"twenty-seven\"\n" + - " }"; + private static final String INVALID_RESPONSE = "{\n" + " \"client_id\": \"l238j323ds-23ij4\",\n" + + " \"username\": \"jdoe\",\n" + " \"scope\": \"read write dolphin\",\n" + + " \"sub\": \"Z5O3upPC88QrAjx00dis\",\n" + + " \"aud\": \"https://protected.example.net/resource\",\n" + + " \"iss\": \"https://server.example.com/\",\n" + " \"exp\": 1419356238,\n" + + " \"iat\": 1419350238,\n" + " \"extension_field\": \"twenty-seven\"\n" + " }"; - private static final String MALFORMED_ISSUER_RESPONSE = "{\n" + - " \"active\" : \"true\",\n" + - " \"iss\" : \"badissuer\"\n" + - " }"; + private static final String MALFORMED_ISSUER_RESPONSE = "{\n" + " \"active\" : \"true\",\n" + + " \"iss\" : \"badissuer\"\n" + " }"; - private static final String MALFORMED_SCOPE_RESPONSE = "{\n" + - " \"active\": true,\n" + - " \"client_id\": \"l238j323ds-23ij4\",\n" + - " \"username\": \"jdoe\",\n" + - " \"scope\": [ \"read\", \"write\", \"dolphin\" ],\n" + - " \"sub\": \"Z5O3upPC88QrAjx00dis\",\n" + - " \"aud\": \"https://protected.example.net/resource\",\n" + - " \"iss\": \"https://server.example.com/\",\n" + - " \"exp\": 1419356238,\n" + - " \"iat\": 1419350238,\n" + - " \"extension_field\": \"twenty-seven\"\n" + - " }"; + private static final String MALFORMED_SCOPE_RESPONSE = "{\n" + " \"active\": true,\n" + + " \"client_id\": \"l238j323ds-23ij4\",\n" + " \"username\": \"jdoe\",\n" + + " \"scope\": [ \"read\", \"write\", \"dolphin\" ],\n" + " \"sub\": \"Z5O3upPC88QrAjx00dis\",\n" + + " \"aud\": \"https://protected.example.net/resource\",\n" + + " \"iss\": \"https://server.example.com/\",\n" + " \"exp\": 1419356238,\n" + + " \"iat\": 1419350238,\n" + " \"extension_field\": \"twenty-seven\"\n" + " }"; private static final ResponseEntity ACTIVE = response(ACTIVE_RESPONSE); + private static final ResponseEntity INACTIVE = response(INACTIVE_RESPONSE); + private static final ResponseEntity INVALID = response(INVALID_RESPONSE); + private static final ResponseEntity MALFORMED_ISSUER = response(MALFORMED_ISSUER_RESPONSE); + private static final ResponseEntity MALFORMED_SCOPE = response(MALFORMED_SCOPE_RESPONSE); @Test public void introspectWhenActiveTokenThenOk() throws Exception { - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { server.setDispatcher(requiresAuth(CLIENT_ID, CLIENT_SECRET, ACTIVE_RESPONSE)); String introspectUri = server.url("/introspect").toString(); - OpaqueTokenIntrospector introspectionClient = - new NimbusOpaqueTokenIntrospector(introspectUri, CLIENT_ID, CLIENT_SECRET); + OpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector(introspectUri, CLIENT_ID, + CLIENT_SECRET); OAuth2AuthenticatedPrincipal authority = introspectionClient.introspect("token"); - assertThat(authority.getAttributes()) - .isNotNull() - .containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true) + assertThat(authority.getAttributes()).isNotNull().containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true) .containsEntry(AUDIENCE, Arrays.asList("https://protected.example.net/resource")) .containsEntry(OAuth2IntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4") .containsEntry(EXPIRES_AT, Instant.ofEpochSecond(1419356238)) .containsEntry(ISSUER, new URL("https://server.example.com/")) .containsEntry(SCOPE, Arrays.asList("read", "write", "dolphin")) - .containsEntry(SUBJECT, "Z5O3upPC88QrAjx00dis") - .containsEntry(USERNAME, "jdoe") + .containsEntry(SUBJECT, "Z5O3upPC88QrAjx00dis").containsEntry(USERNAME, "jdoe") .containsEntry("extension_field", "twenty-seven"); } } @Test public void introspectWhenBadClientCredentialsThenError() throws IOException { - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { server.setDispatcher(requiresAuth(CLIENT_ID, CLIENT_SECRET, ACTIVE_RESPONSE)); String introspectUri = server.url("/introspect").toString(); - OpaqueTokenIntrospector introspectionClient = - new NimbusOpaqueTokenIntrospector(introspectUri, CLIENT_ID, "wrong"); + OpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector(introspectUri, CLIENT_ID, + "wrong"); assertThatCode(() -> introspectionClient.introspect("token")) .isInstanceOf(OAuth2IntrospectionException.class); @@ -161,14 +143,12 @@ public class NimbusOpaqueTokenIntrospectorTests { @Test public void introspectWhenInactiveTokenThenInvalidToken() { RestOperations restOperations = mock(RestOperations.class); - OpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, restOperations); - when(restOperations.exchange(any(RequestEntity.class), eq(String.class))) - .thenReturn(INACTIVE); + OpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, + restOperations); + when(restOperations.exchange(any(RequestEntity.class), eq(String.class))).thenReturn(INACTIVE); - assertThatCode(() -> introspectionClient.introspect("token")) - .isInstanceOf(OAuth2IntrospectionException.class) - .extracting("message") - .isEqualTo("Provided token isn't active"); + assertThatCode(() -> introspectionClient.introspect("token")).isInstanceOf(OAuth2IntrospectionException.class) + .extracting("message").isEqualTo("Provided token isn't active"); } @Test @@ -179,86 +159,71 @@ public class NimbusOpaqueTokenIntrospectorTests { introspectedValues.put(NOT_BEFORE, 29348723984L); RestOperations restOperations = mock(RestOperations.class); - OpaqueTokenIntrospector introspectionClient = - new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, restOperations); + OpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, + restOperations); when(restOperations.exchange(any(RequestEntity.class), eq(String.class))) .thenReturn(response(new JSONObject(introspectedValues).toJSONString())); OAuth2AuthenticatedPrincipal authority = introspectionClient.introspect("token"); - assertThat(authority.getAttributes()) - .isNotNull() - .containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true) + assertThat(authority.getAttributes()).isNotNull().containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true) .containsEntry(AUDIENCE, Arrays.asList("aud")) .containsEntry(NOT_BEFORE, Instant.ofEpochSecond(29348723984L)) - .doesNotContainKey(OAuth2IntrospectionClaimNames.CLIENT_ID) - .doesNotContainKey(SCOPE); + .doesNotContainKey(OAuth2IntrospectionClaimNames.CLIENT_ID).doesNotContainKey(SCOPE); } @Test public void introspectWhenIntrospectionEndpointThrowsExceptionThenInvalidToken() { RestOperations restOperations = mock(RestOperations.class); - OpaqueTokenIntrospector introspectionClient = - new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, restOperations); + OpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, + restOperations); when(restOperations.exchange(any(RequestEntity.class), eq(String.class))) .thenThrow(new IllegalStateException("server was unresponsive")); - assertThatCode(() -> introspectionClient.introspect("token")) - .isInstanceOf(OAuth2IntrospectionException.class) - .extracting("message") - .isEqualTo("server was unresponsive"); + assertThatCode(() -> introspectionClient.introspect("token")).isInstanceOf(OAuth2IntrospectionException.class) + .extracting("message").isEqualTo("server was unresponsive"); } - @Test public void introspectWhenIntrospectionEndpointReturnsMalformedResponseThenInvalidToken() { RestOperations restOperations = mock(RestOperations.class); - OpaqueTokenIntrospector introspectionClient = - new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, restOperations); - when(restOperations.exchange(any(RequestEntity.class), eq(String.class))) - .thenReturn(response("malformed")); + OpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, + restOperations); + when(restOperations.exchange(any(RequestEntity.class), eq(String.class))).thenReturn(response("malformed")); - assertThatCode(() -> introspectionClient.introspect("token")) - .isInstanceOf(OAuth2IntrospectionException.class); + assertThatCode(() -> introspectionClient.introspect("token")).isInstanceOf(OAuth2IntrospectionException.class); } @Test public void introspectWhenIntrospectionTokenReturnsInvalidResponseThenInvalidToken() { RestOperations restOperations = mock(RestOperations.class); - OpaqueTokenIntrospector introspectionClient = - new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, restOperations); - when(restOperations.exchange(any(RequestEntity.class), eq(String.class))) - .thenReturn(INVALID); + OpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, + restOperations); + when(restOperations.exchange(any(RequestEntity.class), eq(String.class))).thenReturn(INVALID); - assertThatCode(() -> introspectionClient.introspect("token")) - .isInstanceOf(OAuth2IntrospectionException.class); + assertThatCode(() -> introspectionClient.introspect("token")).isInstanceOf(OAuth2IntrospectionException.class); } @Test public void introspectWhenIntrospectionTokenReturnsMalformedIssuerResponseThenInvalidToken() { RestOperations restOperations = mock(RestOperations.class); - OpaqueTokenIntrospector introspectionClient = - new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, restOperations); - when(restOperations.exchange(any(RequestEntity.class), eq(String.class))) - .thenReturn(MALFORMED_ISSUER); + OpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, + restOperations); + when(restOperations.exchange(any(RequestEntity.class), eq(String.class))).thenReturn(MALFORMED_ISSUER); - assertThatCode(() -> introspectionClient.introspect("token")) - .isInstanceOf(OAuth2IntrospectionException.class); + assertThatCode(() -> introspectionClient.introspect("token")).isInstanceOf(OAuth2IntrospectionException.class); } // gh-7563 @Test public void introspectWhenIntrospectionTokenReturnsMalformedScopeThenEmptyAuthorities() { RestOperations restOperations = mock(RestOperations.class); - OpaqueTokenIntrospector introspectionClient = - new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, restOperations); - when(restOperations.exchange(any(RequestEntity.class), eq(String.class))) - .thenReturn(MALFORMED_SCOPE); + OpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, + restOperations); + when(restOperations.exchange(any(RequestEntity.class), eq(String.class))).thenReturn(MALFORMED_SCOPE); OAuth2AuthenticatedPrincipal principal = introspectionClient.introspect("token"); assertThat(principal.getAuthorities()).isEmpty(); - assertThat((Object) principal.getAttribute("scope")) - .isNotNull() - .isInstanceOf(JSONArray.class); + assertThat((Object) principal.getAttribute("scope")).isNotNull().isInstanceOf(JSONArray.class); JSONArray scope = principal.getAttribute("scope"); assertThat(scope).containsExactly("read", "write", "dolphin"); } @@ -291,9 +256,8 @@ public class NimbusOpaqueTokenIntrospectorTests { public void setRequestEntityConverterWhenConverterIsNullThenExceptionIsThrown() { RestOperations restOperations = mock(RestOperations.class); - NimbusOpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector( - INTROSPECTION_URL, restOperations - ); + NimbusOpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, + restOperations); assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> introspectionClient.setRequestEntityConverter(null)); @@ -308,9 +272,8 @@ public class NimbusOpaqueTokenIntrospectorTests { String tokenToIntrospect = "some token"; when(requestEntityConverter.convert(tokenToIntrospect)).thenReturn(requestEntity); when(restOperations.exchange(requestEntity, String.class)).thenReturn(ACTIVE); - NimbusOpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector( - INTROSPECTION_URL, restOperations - ); + NimbusOpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL, + restOperations); introspectionClient.setRequestEntityConverter(requestEntityConverter); introspectionClient.introspect(tokenToIntrospect); @@ -329,10 +292,8 @@ public class NimbusOpaqueTokenIntrospectorTests { @Override public MockResponse dispatch(RecordedRequest request) { String authorization = request.getHeader(HttpHeaders.AUTHORIZATION); - return Optional.ofNullable(authorization) - .filter(a -> isAuthorized(authorization, username, password)) - .map(a -> ok(response)) - .orElse(unauthorized()); + return Optional.ofNullable(authorization).filter(a -> isAuthorized(authorization, username, password)) + .map(a -> ok(response)).orElse(unauthorized()); } }; } @@ -343,11 +304,12 @@ public class NimbusOpaqueTokenIntrospectorTests { } private static MockResponse ok(String response) { - return new MockResponse().setBody(response) - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + return new MockResponse().setBody(response).setHeader(HttpHeaders.CONTENT_TYPE, + MediaType.APPLICATION_JSON_VALUE); } private static MockResponse unauthorized() { return new MockResponse().setResponseCode(401); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospectorTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospectorTests.java index cc7f50d3f9..691d25454b 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospectorTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospectorTests.java @@ -57,76 +57,61 @@ import static org.springframework.security.oauth2.server.resource.introspection. * Tests for {@link NimbusReactiveOpaqueTokenIntrospector} */ public class NimbusReactiveOpaqueTokenIntrospectorTests { + private static final String INTROSPECTION_URL = "https://server.example.com"; + private static final String CLIENT_ID = "client"; + private static final String CLIENT_SECRET = "secret"; - private static final String ACTIVE_RESPONSE = "{\n" + - " \"active\": true,\n" + - " \"client_id\": \"l238j323ds-23ij4\",\n" + - " \"username\": \"jdoe\",\n" + - " \"scope\": \"read write dolphin\",\n" + - " \"sub\": \"Z5O3upPC88QrAjx00dis\",\n" + - " \"aud\": \"https://protected.example.net/resource\",\n" + - " \"iss\": \"https://server.example.com/\",\n" + - " \"exp\": 1419356238,\n" + - " \"iat\": 1419350238,\n" + - " \"extension_field\": \"twenty-seven\"\n" + - " }"; + private static final String ACTIVE_RESPONSE = "{\n" + " \"active\": true,\n" + + " \"client_id\": \"l238j323ds-23ij4\",\n" + " \"username\": \"jdoe\",\n" + + " \"scope\": \"read write dolphin\",\n" + " \"sub\": \"Z5O3upPC88QrAjx00dis\",\n" + + " \"aud\": \"https://protected.example.net/resource\",\n" + + " \"iss\": \"https://server.example.com/\",\n" + " \"exp\": 1419356238,\n" + + " \"iat\": 1419350238,\n" + " \"extension_field\": \"twenty-seven\"\n" + " }"; - private static final String INACTIVE_RESPONSE = "{\n" + - " \"active\": false\n" + - " }"; + private static final String INACTIVE_RESPONSE = "{\n" + " \"active\": false\n" + " }"; - private static final String INVALID_RESPONSE = "{\n" + - " \"client_id\": \"l238j323ds-23ij4\",\n" + - " \"username\": \"jdoe\",\n" + - " \"scope\": \"read write dolphin\",\n" + - " \"sub\": \"Z5O3upPC88QrAjx00dis\",\n" + - " \"aud\": \"https://protected.example.net/resource\",\n" + - " \"iss\": \"https://server.example.com/\",\n" + - " \"exp\": 1419356238,\n" + - " \"iat\": 1419350238,\n" + - " \"extension_field\": \"twenty-seven\"\n" + - " }"; + private static final String INVALID_RESPONSE = "{\n" + " \"client_id\": \"l238j323ds-23ij4\",\n" + + " \"username\": \"jdoe\",\n" + " \"scope\": \"read write dolphin\",\n" + + " \"sub\": \"Z5O3upPC88QrAjx00dis\",\n" + + " \"aud\": \"https://protected.example.net/resource\",\n" + + " \"iss\": \"https://server.example.com/\",\n" + " \"exp\": 1419356238,\n" + + " \"iat\": 1419350238,\n" + " \"extension_field\": \"twenty-seven\"\n" + " }"; - private static final String MALFORMED_ISSUER_RESPONSE = "{\n" + - " \"active\" : \"true\",\n" + - " \"iss\" : \"badissuer\"\n" + - " }"; + private static final String MALFORMED_ISSUER_RESPONSE = "{\n" + " \"active\" : \"true\",\n" + + " \"iss\" : \"badissuer\"\n" + " }"; @Test public void authenticateWhenActiveTokenThenOk() throws Exception { - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { server.setDispatcher(requiresAuth(CLIENT_ID, CLIENT_SECRET, ACTIVE_RESPONSE)); String introspectUri = server.url("/introspect").toString(); - NimbusReactiveOpaqueTokenIntrospector introspectionClient = - new NimbusReactiveOpaqueTokenIntrospector(introspectUri, CLIENT_ID, CLIENT_SECRET); + NimbusReactiveOpaqueTokenIntrospector introspectionClient = new NimbusReactiveOpaqueTokenIntrospector( + introspectUri, CLIENT_ID, CLIENT_SECRET); OAuth2AuthenticatedPrincipal authority = introspectionClient.introspect("token").block(); - assertThat(authority.getAttributes()) - .isNotNull() - .containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true) + assertThat(authority.getAttributes()).isNotNull().containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true) .containsEntry(AUDIENCE, Arrays.asList("https://protected.example.net/resource")) .containsEntry(OAuth2IntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4") .containsEntry(EXPIRES_AT, Instant.ofEpochSecond(1419356238)) .containsEntry(ISSUER, new URL("https://server.example.com/")) .containsEntry(SCOPE, Arrays.asList("read", "write", "dolphin")) - .containsEntry(SUBJECT, "Z5O3upPC88QrAjx00dis") - .containsEntry(USERNAME, "jdoe") + .containsEntry(SUBJECT, "Z5O3upPC88QrAjx00dis").containsEntry(USERNAME, "jdoe") .containsEntry("extension_field", "twenty-seven"); } } @Test public void authenticateWhenBadClientCredentialsThenAuthenticationException() throws IOException { - try ( MockWebServer server = new MockWebServer() ) { + try (MockWebServer server = new MockWebServer()) { server.setDispatcher(requiresAuth(CLIENT_ID, CLIENT_SECRET, ACTIVE_RESPONSE)); String introspectUri = server.url("/introspect").toString(); - NimbusReactiveOpaqueTokenIntrospector introspectionClient = - new NimbusReactiveOpaqueTokenIntrospector(introspectUri, CLIENT_ID, "wrong"); + NimbusReactiveOpaqueTokenIntrospector introspectionClient = new NimbusReactiveOpaqueTokenIntrospector( + introspectUri, CLIENT_ID, "wrong"); assertThatCode(() -> introspectionClient.introspect("token").block()) .isInstanceOf(OAuth2IntrospectionException.class); @@ -136,12 +121,11 @@ public class NimbusReactiveOpaqueTokenIntrospectorTests { @Test public void authenticateWhenInactiveTokenThenInvalidToken() { WebClient webClient = mockResponse(INACTIVE_RESPONSE); - NimbusReactiveOpaqueTokenIntrospector introspectionClient = - new NimbusReactiveOpaqueTokenIntrospector(INTROSPECTION_URL, webClient); + NimbusReactiveOpaqueTokenIntrospector introspectionClient = new NimbusReactiveOpaqueTokenIntrospector( + INTROSPECTION_URL, webClient); assertThatCode(() -> introspectionClient.introspect("token").block()) - .isInstanceOf(BadOpaqueTokenException.class) - .extracting("message") + .isInstanceOf(BadOpaqueTokenException.class).extracting("message") .isEqualTo("Provided token isn't active"); } @@ -153,36 +137,32 @@ public class NimbusReactiveOpaqueTokenIntrospectorTests { introspectedValues.put(NOT_BEFORE, 29348723984L); WebClient webClient = mockResponse(new JSONObject(introspectedValues).toJSONString()); - NimbusReactiveOpaqueTokenIntrospector introspectionClient = - new NimbusReactiveOpaqueTokenIntrospector(INTROSPECTION_URL, webClient); + NimbusReactiveOpaqueTokenIntrospector introspectionClient = new NimbusReactiveOpaqueTokenIntrospector( + INTROSPECTION_URL, webClient); OAuth2AuthenticatedPrincipal authority = introspectionClient.introspect("token").block(); - assertThat(authority.getAttributes()) - .isNotNull() - .containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true) + assertThat(authority.getAttributes()).isNotNull().containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true) .containsEntry(AUDIENCE, Arrays.asList("aud")) .containsEntry(NOT_BEFORE, Instant.ofEpochSecond(29348723984L)) - .doesNotContainKey(OAuth2IntrospectionClaimNames.CLIENT_ID) - .doesNotContainKey(SCOPE); + .doesNotContainKey(OAuth2IntrospectionClaimNames.CLIENT_ID).doesNotContainKey(SCOPE); } @Test public void authenticateWhenIntrospectionEndpointThrowsExceptionThenInvalidToken() { WebClient webClient = mockResponse(new IllegalStateException("server was unresponsive")); - NimbusReactiveOpaqueTokenIntrospector introspectionClient = - new NimbusReactiveOpaqueTokenIntrospector(INTROSPECTION_URL, webClient); + NimbusReactiveOpaqueTokenIntrospector introspectionClient = new NimbusReactiveOpaqueTokenIntrospector( + INTROSPECTION_URL, webClient); assertThatCode(() -> introspectionClient.introspect("token").block()) - .isInstanceOf(OAuth2IntrospectionException.class) - .extracting("message") + .isInstanceOf(OAuth2IntrospectionException.class).extracting("message") .isEqualTo("server was unresponsive"); } @Test public void authenticateWhenIntrospectionEndpointReturnsMalformedResponseThenInvalidToken() { WebClient webClient = mockResponse("malformed"); - NimbusReactiveOpaqueTokenIntrospector introspectionClient = - new NimbusReactiveOpaqueTokenIntrospector(INTROSPECTION_URL, webClient); + NimbusReactiveOpaqueTokenIntrospector introspectionClient = new NimbusReactiveOpaqueTokenIntrospector( + INTROSPECTION_URL, webClient); assertThatCode(() -> introspectionClient.introspect("token").block()) .isInstanceOf(OAuth2IntrospectionException.class); @@ -191,8 +171,8 @@ public class NimbusReactiveOpaqueTokenIntrospectorTests { @Test public void authenticateWhenIntrospectionTokenReturnsInvalidResponseThenInvalidToken() { WebClient webClient = mockResponse(INVALID_RESPONSE); - NimbusReactiveOpaqueTokenIntrospector introspectionClient = - new NimbusReactiveOpaqueTokenIntrospector(INTROSPECTION_URL, webClient); + NimbusReactiveOpaqueTokenIntrospector introspectionClient = new NimbusReactiveOpaqueTokenIntrospector( + INTROSPECTION_URL, webClient); assertThatCode(() -> introspectionClient.introspect("token").block()) .isInstanceOf(OAuth2IntrospectionException.class); @@ -201,8 +181,8 @@ public class NimbusReactiveOpaqueTokenIntrospectorTests { @Test public void authenticateWhenIntrospectionTokenReturnsMalformedIssuerResponseThenInvalidToken() { WebClient webClient = mockResponse(MALFORMED_ISSUER_RESPONSE); - NimbusReactiveOpaqueTokenIntrospector introspectionClient = - new NimbusReactiveOpaqueTokenIntrospector(INTROSPECTION_URL, webClient); + NimbusReactiveOpaqueTokenIntrospector introspectionClient = new NimbusReactiveOpaqueTokenIntrospector( + INTROSPECTION_URL, webClient); assertThatCode(() -> introspectionClient.introspect("token").block()) .isInstanceOf(OAuth2IntrospectionException.class); @@ -262,10 +242,8 @@ public class NimbusReactiveOpaqueTokenIntrospectorTests { @Override public MockResponse dispatch(RecordedRequest request) { String authorization = request.getHeader(HttpHeaders.AUTHORIZATION); - return Optional.ofNullable(authorization) - .filter(a -> isAuthorized(authorization, username, password)) - .map(a -> ok(response)) - .orElse(unauthorized()); + return Optional.ofNullable(authorization).filter(a -> isAuthorized(authorization, username, password)) + .map(a -> ok(response)).orElse(unauthorized()); } }; } @@ -276,11 +254,12 @@ public class NimbusReactiveOpaqueTokenIntrospectorTests { } private static MockResponse ok(String response) { - return new MockResponse().setBody(response) - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + return new MockResponse().setBody(response).setHeader(HttpHeaders.CONTENT_TYPE, + MediaType.APPLICATION_JSON_VALUE); } private static MockResponse unauthorized() { return new MockResponse().setResponseCode(401); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionAuthenticatedPrincipalTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionAuthenticatedPrincipalTests.java index 83b6f318f4..b0cff1801f 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionAuthenticatedPrincipalTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionAuthenticatedPrincipalTests.java @@ -38,33 +38,55 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; * @author David Kovac */ public class OAuth2IntrospectionAuthenticatedPrincipalTests { + private static final String AUTHORITY = "SCOPE_read"; + private static final Collection AUTHORITIES = AuthorityUtils.createAuthorityList(AUTHORITY); private static final String SUBJECT = "test-subject"; private static final String ACTIVE_CLAIM = "active"; + private static final String CLIENT_ID_CLAIM = "client_id"; + private static final String USERNAME_CLAIM = "username"; + private static final String TOKEN_TYPE_CLAIM = "token_type"; + private static final String EXP_CLAIM = "exp"; + private static final String IAT_CLAIM = "iat"; + private static final String NBF_CLAIM = "nbf"; + private static final String SUB_CLAIM = "sub"; + private static final String AUD_CLAIM = "aud"; + private static final String ISS_CLAIM = "iss"; + private static final String JTI_CLAIM = "jti"; private static final boolean ACTIVE_VALUE = true; + private static final String CLIENT_ID_VALUE = "client-id-1"; + private static final String USERNAME_VALUE = "username-1"; + private static final String TOKEN_TYPE_VALUE = "token-type-1"; + private static final long EXP_VALUE = Instant.now().plusSeconds(60).getEpochSecond(); + private static final long IAT_VALUE = Instant.now().getEpochSecond(); + private static final long NBF_VALUE = Instant.now().plusSeconds(5).getEpochSecond(); + private static final String SUB_VALUE = "subject1"; + private static final List AUD_VALUE = Arrays.asList("aud1", "aud2"); + private static final String ISS_VALUE = "https://provider.com"; + private static final String JTI_VALUE = "jwt-id-1"; private static final Map CLAIMS; @@ -95,26 +117,25 @@ public class OAuth2IntrospectionAuthenticatedPrincipalTests { @Test public void constructorWhenAuthoritiesIsNullOrEmptyThenNoAuthorities() { - Collection authorities = - new OAuth2IntrospectionAuthenticatedPrincipal(CLAIMS, null).getAuthorities(); + Collection authorities = new OAuth2IntrospectionAuthenticatedPrincipal(CLAIMS, null) + .getAuthorities(); assertThat(authorities).isEmpty(); - authorities = new OAuth2IntrospectionAuthenticatedPrincipal(CLAIMS, - Collections.emptyList()).getAuthorities(); + authorities = new OAuth2IntrospectionAuthenticatedPrincipal(CLAIMS, Collections.emptyList()).getAuthorities(); assertThat(authorities).isEmpty(); } @Test public void constructorWhenNameIsNullThenFallsbackToSubAttribute() { - OAuth2AuthenticatedPrincipal principal = - new OAuth2IntrospectionAuthenticatedPrincipal(null, CLAIMS, AUTHORITIES); + OAuth2AuthenticatedPrincipal principal = new OAuth2IntrospectionAuthenticatedPrincipal(null, CLAIMS, + AUTHORITIES); assertThat(principal.getName()).isEqualTo(CLAIMS.get(SUB_CLAIM)); } @Test public void constructorWhenAttributesAuthoritiesProvidedThenCreated() { - OAuth2IntrospectionAuthenticatedPrincipal principal = - new OAuth2IntrospectionAuthenticatedPrincipal(CLAIMS, AUTHORITIES); + OAuth2IntrospectionAuthenticatedPrincipal principal = new OAuth2IntrospectionAuthenticatedPrincipal(CLAIMS, + AUTHORITIES); assertThat(principal.getName()).isEqualTo(CLAIMS.get(SUB_CLAIM)); assertThat(principal.getAttributes()).isEqualTo(CLAIMS); @@ -136,8 +157,8 @@ public class OAuth2IntrospectionAuthenticatedPrincipalTests { @Test public void constructorWhenAllParametersProvidedAndValidThenCreated() { - OAuth2IntrospectionAuthenticatedPrincipal principal = - new OAuth2IntrospectionAuthenticatedPrincipal(SUBJECT, CLAIMS, AUTHORITIES); + OAuth2IntrospectionAuthenticatedPrincipal principal = new OAuth2IntrospectionAuthenticatedPrincipal(SUBJECT, + CLAIMS, AUTHORITIES); assertThat(principal.getName()).isEqualTo(SUBJECT); assertThat(principal.getAttributes()).isEqualTo(CLAIMS); @@ -159,15 +180,14 @@ public class OAuth2IntrospectionAuthenticatedPrincipalTests { @Test public void getNameWhenInConstructorThenReturns() { - OAuth2AuthenticatedPrincipal principal = - new OAuth2IntrospectionAuthenticatedPrincipal(SUB_VALUE, CLAIMS, AUTHORITIES); + OAuth2AuthenticatedPrincipal principal = new OAuth2IntrospectionAuthenticatedPrincipal(SUB_VALUE, CLAIMS, + AUTHORITIES); assertThat(principal.getName()).isEqualTo(SUB_VALUE); } @Test public void getAttributeWhenGivenKeyThenReturnsValue() { - OAuth2AuthenticatedPrincipal principal = - new OAuth2IntrospectionAuthenticatedPrincipal(CLAIMS, AUTHORITIES); + OAuth2AuthenticatedPrincipal principal = new OAuth2IntrospectionAuthenticatedPrincipal(CLAIMS, AUTHORITIES); assertThat((Object) principal.getAttribute(ACTIVE_CLAIM)).isEqualTo(ACTIVE_VALUE); assertThat((Object) principal.getAttribute(CLIENT_ID_CLAIM)).isEqualTo(CLIENT_ID_VALUE); @@ -181,4 +201,5 @@ public class OAuth2IntrospectionAuthenticatedPrincipalTests { assertThat((Object) principal.getAttribute(ISS_CLAIM)).isEqualTo(ISS_VALUE); assertThat((Object) principal.getAttribute(JTI_CLAIM)).isEqualTo(JTI_VALUE); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationEntryPointTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationEntryPointTests.java index fc5bca4482..1dbe257e5e 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationEntryPointTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationEntryPointTests.java @@ -46,8 +46,7 @@ public class BearerTokenAuthenticationEntryPointTests { } @Test - public void commenceWhenNoBearerTokenErrorThenStatus401AndAuthHeader() - throws Exception { + public void commenceWhenNoBearerTokenErrorThenStatus401AndAuthHeader() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -59,8 +58,7 @@ public class BearerTokenAuthenticationEntryPointTests { } @Test - public void commenceWhenNoBearerTokenErrorAndRealmSetThenStatus401AndAuthHeaderWithRealm() - throws Exception { + public void commenceWhenNoBearerTokenErrorAndRealmSetThenStatus401AndAuthHeaderWithRealm() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -73,35 +71,28 @@ public class BearerTokenAuthenticationEntryPointTests { } @Test - public void commenceWhenInvalidRequestErrorThenStatus400AndHeaderWithError() - throws Exception { + public void commenceWhenInvalidRequestErrorThenStatus400AndHeaderWithError() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); - BearerTokenError error = new BearerTokenError( - BearerTokenErrorCodes.INVALID_REQUEST, - HttpStatus.BAD_REQUEST, - null, - null); + BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_REQUEST, HttpStatus.BAD_REQUEST, + null, null); - this.authenticationEntryPoint.commence(request, response, - new OAuth2AuthenticationException(error)); + this.authenticationEntryPoint.commence(request, response, new OAuth2AuthenticationException(error)); assertThat(response.getStatus()).isEqualTo(400); assertThat(response.getHeader("WWW-Authenticate")).isEqualTo("Bearer error=\"invalid_request\""); } @Test - public void commenceWhenInvalidRequestErrorThenStatus400AndHeaderWithErrorDetails() - throws Exception { + public void commenceWhenInvalidRequestErrorThenStatus400AndHeaderWithErrorDetails() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_REQUEST, HttpStatus.BAD_REQUEST, "The access token expired", null, null); - this.authenticationEntryPoint.commence(request, response, - new OAuth2AuthenticationException(error)); + this.authenticationEntryPoint.commence(request, response, new OAuth2AuthenticationException(error)); assertThat(response.getStatus()).isEqualTo(400); assertThat(response.getHeader("WWW-Authenticate")) @@ -109,16 +100,14 @@ public class BearerTokenAuthenticationEntryPointTests { } @Test - public void commenceWhenInvalidRequestErrorThenStatus400AndHeaderWithErrorUri() - throws Exception { + public void commenceWhenInvalidRequestErrorThenStatus400AndHeaderWithErrorUri() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_REQUEST, HttpStatus.BAD_REQUEST, null, "https://example.com", null); - this.authenticationEntryPoint.commence(request, response, - new OAuth2AuthenticationException(error)); + this.authenticationEntryPoint.commence(request, response, new OAuth2AuthenticationException(error)); assertThat(response.getStatus()).isEqualTo(400); assertThat(response.getHeader("WWW-Authenticate")) @@ -126,48 +115,42 @@ public class BearerTokenAuthenticationEntryPointTests { } @Test - public void commenceWhenInvalidTokenErrorThenStatus401AndHeaderWithError() - throws Exception { + public void commenceWhenInvalidTokenErrorThenStatus401AndHeaderWithError() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_TOKEN, HttpStatus.UNAUTHORIZED, null, null); - this.authenticationEntryPoint.commence(request, response, - new OAuth2AuthenticationException(error)); + this.authenticationEntryPoint.commence(request, response, new OAuth2AuthenticationException(error)); assertThat(response.getStatus()).isEqualTo(401); assertThat(response.getHeader("WWW-Authenticate")).isEqualTo("Bearer error=\"invalid_token\""); } @Test - public void commenceWhenInsufficientScopeErrorThenStatus403AndHeaderWithError() - throws Exception { + public void commenceWhenInsufficientScopeErrorThenStatus403AndHeaderWithError() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INSUFFICIENT_SCOPE, HttpStatus.FORBIDDEN, null, null); - this.authenticationEntryPoint.commence(request, response, - new OAuth2AuthenticationException(error)); + this.authenticationEntryPoint.commence(request, response, new OAuth2AuthenticationException(error)); assertThat(response.getStatus()).isEqualTo(403); assertThat(response.getHeader("WWW-Authenticate")).isEqualTo("Bearer error=\"insufficient_scope\""); } @Test - public void commenceWhenInsufficientScopeErrorThenStatus403AndHeaderWithErrorAndScope() - throws Exception { + public void commenceWhenInsufficientScopeErrorThenStatus403AndHeaderWithErrorAndScope() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INSUFFICIENT_SCOPE, HttpStatus.FORBIDDEN, null, null, "test.read test.write"); - this.authenticationEntryPoint.commence(request, response, - new OAuth2AuthenticationException(error)); + this.authenticationEntryPoint.commence(request, response, new OAuth2AuthenticationException(error)); assertThat(response.getStatus()).isEqualTo(403); assertThat(response.getHeader("WWW-Authenticate")) @@ -184,8 +167,7 @@ public class BearerTokenAuthenticationEntryPointTests { "Insufficient scope", "https://example.com", "test.read test.write"); this.authenticationEntryPoint.setRealmName("test"); - this.authenticationEntryPoint.commence(request, response, - new OAuth2AuthenticationException(error)); + this.authenticationEntryPoint.commence(request, response, new OAuth2AuthenticationException(error)); assertThat(response.getStatus()).isEqualTo(403); assertThat(response.getHeader("WWW-Authenticate")).isEqualTo( @@ -195,8 +177,7 @@ public class BearerTokenAuthenticationEntryPointTests { @Test public void setRealmNameWhenNullRealmNameThenNoExceptionThrown() { - assertThatCode(() -> this.authenticationEntryPoint.setRealmName(null)) - .doesNotThrowAnyException(); + assertThatCode(() -> this.authenticationEntryPoint.setRealmName(null)).doesNotThrowAnyException(); } } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilterTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilterTests.java index 25339f031b..065e41ed08 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilterTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/BearerTokenAuthenticationFilterTests.java @@ -53,6 +53,7 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class BearerTokenAuthenticationFilterTests { + @Mock AuthenticationEntryPoint authenticationEntryPoint; @@ -85,12 +86,12 @@ public class BearerTokenAuthenticationFilterTests { public void doFilterWhenBearerTokenPresentThenAuthenticates() throws ServletException, IOException { when(this.bearerTokenResolver.resolve(this.request)).thenReturn("token"); - BearerTokenAuthenticationFilter filter = - addMocks(new BearerTokenAuthenticationFilter(this.authenticationManager)); + BearerTokenAuthenticationFilter filter = addMocks( + new BearerTokenAuthenticationFilter(this.authenticationManager)); filter.doFilter(this.request, this.response, this.filterChain); - ArgumentCaptor captor = - ArgumentCaptor.forClass(BearerTokenAuthenticationToken.class); + ArgumentCaptor captor = ArgumentCaptor + .forClass(BearerTokenAuthenticationToken.class); verify(this.authenticationManager).authenticate(captor.capture()); @@ -99,16 +100,16 @@ public class BearerTokenAuthenticationFilterTests { @Test public void doFilterWhenUsingAuthenticationManagerResolverThenAuthenticates() throws Exception { - BearerTokenAuthenticationFilter filter = - addMocks(new BearerTokenAuthenticationFilter(this.authenticationManagerResolver)); + BearerTokenAuthenticationFilter filter = addMocks( + new BearerTokenAuthenticationFilter(this.authenticationManagerResolver)); when(this.bearerTokenResolver.resolve(this.request)).thenReturn("token"); when(this.authenticationManagerResolver.resolve(any())).thenReturn(this.authenticationManager); filter.doFilter(this.request, this.response, this.filterChain); - ArgumentCaptor captor = - ArgumentCaptor.forClass(BearerTokenAuthenticationToken.class); + ArgumentCaptor captor = ArgumentCaptor + .forClass(BearerTokenAuthenticationToken.class); verify(this.authenticationManager).authenticate(captor.capture()); @@ -116,8 +117,7 @@ public class BearerTokenAuthenticationFilterTests { } @Test - public void doFilterWhenNoBearerTokenPresentThenDoesNotAuthenticate() - throws ServletException, IOException { + public void doFilterWhenNoBearerTokenPresentThenDoesNotAuthenticate() throws ServletException, IOException { when(this.bearerTokenResolver.resolve(this.request)).thenReturn(null); @@ -126,11 +126,8 @@ public class BearerTokenAuthenticationFilterTests { @Test public void doFilterWhenMalformedBearerTokenThenPropagatesError() throws ServletException, IOException { - BearerTokenError error = new BearerTokenError( - BearerTokenErrorCodes.INVALID_REQUEST, - HttpStatus.BAD_REQUEST, - "description", - "uri"); + BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_REQUEST, HttpStatus.BAD_REQUEST, + "description", "uri"); OAuth2AuthenticationException exception = new OAuth2AuthenticationException(error); @@ -142,44 +139,36 @@ public class BearerTokenAuthenticationFilterTests { } @Test - public void doFilterWhenAuthenticationFailsWithDefaultHandlerThenPropagatesError() throws ServletException, IOException { - BearerTokenError error = new BearerTokenError( - BearerTokenErrorCodes.INVALID_TOKEN, - HttpStatus.UNAUTHORIZED, - "description", - "uri" - ); + public void doFilterWhenAuthenticationFailsWithDefaultHandlerThenPropagatesError() + throws ServletException, IOException { + BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_TOKEN, HttpStatus.UNAUTHORIZED, + "description", "uri"); OAuth2AuthenticationException exception = new OAuth2AuthenticationException(error); when(this.bearerTokenResolver.resolve(this.request)).thenReturn("token"); - when(this.authenticationManager.authenticate(any(BearerTokenAuthenticationToken.class))) - .thenThrow(exception); + when(this.authenticationManager.authenticate(any(BearerTokenAuthenticationToken.class))).thenThrow(exception); - BearerTokenAuthenticationFilter filter = - addMocks(new BearerTokenAuthenticationFilter(this.authenticationManager)); + BearerTokenAuthenticationFilter filter = addMocks( + new BearerTokenAuthenticationFilter(this.authenticationManager)); filter.doFilter(this.request, this.response, this.filterChain); verify(this.authenticationEntryPoint).commence(this.request, this.response, exception); } @Test - public void doFilterWhenAuthenticationFailsWithCustomHandlerThenPropagatesError() throws ServletException, IOException { - BearerTokenError error = new BearerTokenError( - BearerTokenErrorCodes.INVALID_TOKEN, - HttpStatus.UNAUTHORIZED, - "description", - "uri" - ); + public void doFilterWhenAuthenticationFailsWithCustomHandlerThenPropagatesError() + throws ServletException, IOException { + BearerTokenError error = new BearerTokenError(BearerTokenErrorCodes.INVALID_TOKEN, HttpStatus.UNAUTHORIZED, + "description", "uri"); OAuth2AuthenticationException exception = new OAuth2AuthenticationException(error); when(this.bearerTokenResolver.resolve(this.request)).thenReturn("token"); - when(this.authenticationManager.authenticate(any(BearerTokenAuthenticationToken.class))) - .thenThrow(exception); + when(this.authenticationManager.authenticate(any(BearerTokenAuthenticationToken.class))).thenThrow(exception); - BearerTokenAuthenticationFilter filter = - addMocks(new BearerTokenAuthenticationFilter(this.authenticationManager)); + BearerTokenAuthenticationFilter filter = addMocks( + new BearerTokenAuthenticationFilter(this.authenticationManager)); filter.setAuthenticationFailureHandler(this.authenticationFailureHandler); filter.doFilter(this.request, this.response, this.filterChain); @@ -189,16 +178,14 @@ public class BearerTokenAuthenticationFilterTests { @Test public void setAuthenticationEntryPointWhenNullThenThrowsException() { BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(this.authenticationManager); - assertThatCode(() -> filter.setAuthenticationEntryPoint(null)) - .isInstanceOf(IllegalArgumentException.class) + assertThatCode(() -> filter.setAuthenticationEntryPoint(null)).isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("authenticationEntryPoint cannot be null"); } @Test public void setBearerTokenResolverWhenNullThenThrowsException() { BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(this.authenticationManager); - assertThatCode(() -> filter.setBearerTokenResolver(null)) - .isInstanceOf(IllegalArgumentException.class) + assertThatCode(() -> filter.setBearerTokenResolver(null)).isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("bearerTokenResolver cannot be null"); } @@ -211,10 +198,10 @@ public class BearerTokenAuthenticationFilterTests { @Test public void constructorWhenNullAuthenticationManagerResolverThenThrowsException() { - assertThatCode(() -> - new BearerTokenAuthenticationFilter((AuthenticationManagerResolver) null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("authenticationManagerResolver cannot be null"); + assertThatCode( + () -> new BearerTokenAuthenticationFilter((AuthenticationManagerResolver) null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("authenticationManagerResolver cannot be null"); } private BearerTokenAuthenticationFilter addMocks(BearerTokenAuthenticationFilter filter) { @@ -223,13 +210,13 @@ public class BearerTokenAuthenticationFilterTests { return filter; } - private void dontAuthenticate() - throws ServletException, IOException { + private void dontAuthenticate() throws ServletException, IOException { - BearerTokenAuthenticationFilter filter = - addMocks(new BearerTokenAuthenticationFilter(this.authenticationManager)); + BearerTokenAuthenticationFilter filter = addMocks( + new BearerTokenAuthenticationFilter(this.authenticationManager)); filter.doFilter(this.request, this.response, this.filterChain); verifyNoMoreInteractions(this.authenticationManager); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolverTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolverTests.java index d8584c3f88..568df3dd14 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolverTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/DefaultBearerTokenResolverTests.java @@ -33,7 +33,9 @@ import static org.assertj.core.api.Assertions.assertThatCode; * @author Vedran Pavic */ public class DefaultBearerTokenResolverTests { + private static final String CUSTOM_HEADER = "custom-header"; + private static final String TEST_TOKEN = "test-token"; private DefaultBearerTokenResolver resolver; @@ -184,4 +186,5 @@ public class DefaultBearerTokenResolverTests { assertThat(this.resolver.resolve(request)).isNull(); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/HeaderBearerTokenResolverTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/HeaderBearerTokenResolverTests.java index ca8d047873..20121017c0 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/HeaderBearerTokenResolverTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/HeaderBearerTokenResolverTests.java @@ -38,16 +38,16 @@ public class HeaderBearerTokenResolverTests { @Test public void constructorWhenHeaderNullThenThrowIllegalArgumentException() { - assertThatCode(() -> { new HeaderBearerTokenResolver(null); }) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("header cannot be empty"); + assertThatCode(() -> { + new HeaderBearerTokenResolver(null); + }).isInstanceOf(IllegalArgumentException.class).hasMessage("header cannot be empty"); } @Test public void constructorWhenHeaderEmptyThenThrowIllegalArgumentException() { - assertThatCode(() -> { new HeaderBearerTokenResolver(""); }) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("header cannot be empty"); + assertThatCode(() -> { + new HeaderBearerTokenResolver(""); + }).isInstanceOf(IllegalArgumentException.class).hasMessage("header cannot be empty"); } @Test @@ -64,4 +64,5 @@ public class HeaderBearerTokenResolverTests { assertThat(this.resolver.resolve(request)).isNull(); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/MockExchangeFunction.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/MockExchangeFunction.java index a4da50ea00..0aa0aaf600 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/MockExchangeFunction.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/MockExchangeFunction.java @@ -32,6 +32,7 @@ import static org.mockito.Mockito.mock; * @since 5.1 */ public class MockExchangeFunction implements ExchangeFunction { + private List requests = new ArrayList<>(); private ClientResponse response = mock(ClientResponse.class); @@ -55,4 +56,5 @@ public class MockExchangeFunction implements ExchangeFunction { return Mono.just(this.response); }); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/access/BearerTokenAccessDeniedHandlerTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/access/BearerTokenAccessDeniedHandlerTests.java index 3799e77c4d..7961b5a1f3 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/access/BearerTokenAccessDeniedHandlerTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/access/BearerTokenAccessDeniedHandlerTests.java @@ -37,6 +37,7 @@ import static org.assertj.core.api.Assertions.assertThatCode; * @author Josh Cummings */ public class BearerTokenAccessDeniedHandlerTests { + private BearerTokenAccessDeniedHandler accessDeniedHandler; @Before @@ -45,8 +46,7 @@ public class BearerTokenAccessDeniedHandlerTests { } @Test - public void handleWhenNotOAuth2AuthenticatedThenStatus403() - throws Exception { + public void handleWhenNotOAuth2AuthenticatedThenStatus403() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -61,8 +61,7 @@ public class BearerTokenAccessDeniedHandlerTests { } @Test - public void handleWhenNotOAuth2AuthenticatedAndRealmSetThenStatus403AndAuthHeaderWithRealm() - throws Exception { + public void handleWhenNotOAuth2AuthenticatedAndRealmSetThenStatus403AndAuthHeaderWithRealm() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -90,15 +89,14 @@ public class BearerTokenAccessDeniedHandlerTests { this.accessDeniedHandler.handle(request, response, null); assertThat(response.getStatus()).isEqualTo(403); - assertThat(response.getHeader("WWW-Authenticate")).isEqualTo("Bearer error=\"insufficient_scope\", " + - "error_description=\"The request requires higher privileges than provided by the access token.\", " + - "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\""); + assertThat(response.getHeader("WWW-Authenticate")).isEqualTo("Bearer error=\"insufficient_scope\", " + + "error_description=\"The request requires higher privileges than provided by the access token.\", " + + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\""); } @Test public void setRealmNameWhenNullRealmNameThenNoExceptionThrown() { - assertThatCode(() -> this.accessDeniedHandler.setRealmName(null)) - .doesNotThrowAnyException(); + assertThatCode(() -> this.accessDeniedHandler.setRealmName(null)).doesNotThrowAnyException(); } static class TestingOAuth2TokenAuthenticationToken @@ -117,9 +115,13 @@ public class BearerTokenAccessDeniedHandlerTests { } static class TestingOAuth2Token extends AbstractOAuth2Token { + TestingOAuth2Token(String tokenValue) { super(tokenValue); } + } + } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/access/server/BearerTokenServerAccessDeniedHandlerTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/access/server/BearerTokenServerAccessDeniedHandlerTests.java index c4fb17ee65..5edb11aebf 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/access/server/BearerTokenServerAccessDeniedHandlerTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/access/server/BearerTokenServerAccessDeniedHandlerTests.java @@ -37,6 +37,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class BearerTokenServerAccessDeniedHandlerTests { + private BearerTokenServerAccessDeniedHandler accessDeniedHandler; @Before @@ -55,8 +56,7 @@ public class BearerTokenServerAccessDeniedHandlerTests { this.accessDeniedHandler.handle(exchange, null).block(); assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); - assertThat(exchange.getResponse().getHeaders().get("WWW-Authenticate")).isEqualTo( - Arrays.asList("Bearer")); + assertThat(exchange.getResponse().getHeaders().get("WWW-Authenticate")).isEqualTo(Arrays.asList("Bearer")); } @Test @@ -71,8 +71,8 @@ public class BearerTokenServerAccessDeniedHandlerTests { this.accessDeniedHandler.handle(exchange, null).block(); assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); - assertThat(exchange.getResponse().getHeaders().get("WWW-Authenticate")).isEqualTo( - Arrays.asList("Bearer realm=\"test\"")); + assertThat(exchange.getResponse().getHeaders().get("WWW-Authenticate")) + .isEqualTo(Arrays.asList("Bearer realm=\"test\"")); } @Test @@ -86,16 +86,15 @@ public class BearerTokenServerAccessDeniedHandlerTests { this.accessDeniedHandler.handle(exchange, null).block(); assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); - assertThat(exchange.getResponse().getHeaders().get("WWW-Authenticate")).isEqualTo( - Arrays.asList("Bearer error=\"insufficient_scope\", " + - "error_description=\"The request requires higher privileges than provided by the access token.\", " + - "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"")); + assertThat(exchange.getResponse().getHeaders().get("WWW-Authenticate")) + .isEqualTo(Arrays.asList("Bearer error=\"insufficient_scope\", " + + "error_description=\"The request requires higher privileges than provided by the access token.\", " + + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"")); } @Test public void setRealmNameWhenNullRealmNameThenNoExceptionThrown() { - assertThatCode(() -> this.accessDeniedHandler.setRealmName(null)) - .doesNotThrowAnyException(); + assertThatCode(() -> this.accessDeniedHandler.setRealmName(null)).doesNotThrowAnyException(); } static class TestingOAuth2TokenAuthenticationToken @@ -114,9 +113,13 @@ public class BearerTokenServerAccessDeniedHandlerTests { } static class TestingOAuth2Token extends AbstractOAuth2Token { + TestingOAuth2Token(String tokenValue) { super(tokenValue); } + } + } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServerBearerExchangeFilterFunctionTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServerBearerExchangeFilterFunctionTests.java index 22bdb72bcd..52517b788d 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServerBearerExchangeFilterFunctionTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServerBearerExchangeFilterFunctionTests.java @@ -42,14 +42,14 @@ import static org.springframework.http.HttpMethod.GET; * @author Josh Cummings */ public class ServerBearerExchangeFilterFunctionTests { + private ServerBearerExchangeFilterFunction function = new ServerBearerExchangeFilterFunction(); private MockExchangeFunction exchange = new MockExchangeFunction(); - private OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "token-0", - Instant.now(), - Instant.now().plus(Duration.ofDays(1))); + private OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token-0", + Instant.now(), Instant.now().plus(Duration.ofDays(1))); + private Authentication authentication = new AbstractOAuth2TokenAuthenticationToken(accessToken) { @Override public Map getTokenAttributes() { @@ -59,8 +59,7 @@ public class ServerBearerExchangeFilterFunctionTests { @Test public void filterWhenUnauthenticatedThenAuthorizationHeaderNull() { - ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .build(); + ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")).build(); this.function.filter(request, this.exchange).block(); @@ -69,12 +68,10 @@ public class ServerBearerExchangeFilterFunctionTests { @Test public void filterWhenAuthenticatedThenAuthorizationHeaderNull() throws Exception { - ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .build(); + ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")).build(); this.function.filter(request, this.exchange) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(this.authentication)) - .block(); + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(this.authentication)).block(); assertThat(this.exchange.getRequest().headers().getFirst(HttpHeaders.AUTHORIZATION)) .isEqualTo("Bearer " + this.accessToken.getTokenValue()); @@ -83,29 +80,25 @@ public class ServerBearerExchangeFilterFunctionTests { // gh-7353 @Test public void filterWhenAuthenticatedWithOtherTokenThenAuthorizationHeaderNull() throws Exception { - ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .build(); + ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")).build(); TestingAuthenticationToken token = new TestingAuthenticationToken("user", "pass"); this.function.filter(request, this.exchange) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(token)) - .block(); + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(token)).block(); - assertThat(this.exchange.getRequest().headers().getFirst(HttpHeaders.AUTHORIZATION)) - .isNull(); + assertThat(this.exchange.getRequest().headers().getFirst(HttpHeaders.AUTHORIZATION)).isNull(); } @Test public void filterWhenExistingAuthorizationThenSingleAuthorizationHeader() { ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .header(HttpHeaders.AUTHORIZATION, "Existing") - .build(); + .header(HttpHeaders.AUTHORIZATION, "Existing").build(); this.function.filter(request, this.exchange) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(this.authentication)) - .block(); + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(this.authentication)).block(); HttpHeaders headers = this.exchange.getRequest().headers(); assertThat(headers.get(HttpHeaders.AUTHORIZATION)).containsOnly("Bearer " + this.accessToken.getTokenValue()); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServletBearerExchangeFilterFunctionTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServletBearerExchangeFilterFunctionTests.java index e5fd79b339..c4999fb545 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServletBearerExchangeFilterFunctionTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServletBearerExchangeFilterFunctionTests.java @@ -47,14 +47,13 @@ import static org.springframework.security.oauth2.server.resource.web.reactive.f */ @RunWith(MockitoJUnitRunner.class) public class ServletBearerExchangeFilterFunctionTests { + private ServletBearerExchangeFilterFunction function = new ServletBearerExchangeFilterFunction(); private MockExchangeFunction exchange = new MockExchangeFunction(); - private OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "token-0", - Instant.now(), - Instant.now().plus(Duration.ofDays(1))); + private OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token-0", + Instant.now(), Instant.now().plus(Duration.ofDays(1))); private Authentication authentication = new AbstractOAuth2TokenAuthenticationToken(accessToken) { @Override @@ -65,38 +64,29 @@ public class ServletBearerExchangeFilterFunctionTests { @Test public void filterWhenUnauthenticatedThenAuthorizationHeaderNull() { - ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .build(); + ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")).build(); this.function.filter(request, this.exchange).block(); - assertThat(this.exchange.getRequest().headers().getFirst(HttpHeaders.AUTHORIZATION)) - .isNull(); + assertThat(this.exchange.getRequest().headers().getFirst(HttpHeaders.AUTHORIZATION)).isNull(); } // gh-7353 @Test public void filterWhenAuthenticatedWithOtherTokenThenAuthorizationHeaderNull() { TestingAuthenticationToken token = new TestingAuthenticationToken("user", "pass"); - ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .build(); + ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")).build(); - this.function.filter(request, this.exchange) - .subscriberContext(context(token)) - .block(); + this.function.filter(request, this.exchange).subscriberContext(context(token)).block(); - assertThat(this.exchange.getRequest().headers().getFirst(HttpHeaders.AUTHORIZATION)) - .isNull(); + assertThat(this.exchange.getRequest().headers().getFirst(HttpHeaders.AUTHORIZATION)).isNull(); } @Test public void filterWhenAuthenticatedThenAuthorizationHeader() { - ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .build(); + ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")).build(); - this.function.filter(request, this.exchange) - .subscriberContext(context(this.authentication)) - .block(); + this.function.filter(request, this.exchange).subscriberContext(context(this.authentication)).block(); assertThat(this.exchange.getRequest().headers().getFirst(HttpHeaders.AUTHORIZATION)) .isEqualTo("Bearer " + this.accessToken.getTokenValue()); @@ -105,12 +95,9 @@ public class ServletBearerExchangeFilterFunctionTests { @Test public void filterWhenExistingAuthorizationThenSingleAuthorizationHeader() { ClientRequest request = ClientRequest.create(GET, URI.create("https://example.com")) - .header(HttpHeaders.AUTHORIZATION, "Existing") - .build(); + .header(HttpHeaders.AUTHORIZATION, "Existing").build(); - this.function.filter(request, this.exchange) - .subscriberContext(context(this.authentication)) - .block(); + this.function.filter(request, this.exchange).subscriberContext(context(this.authentication)).block(); HttpHeaders headers = this.exchange.getRequest().headers(); assertThat(headers.get(HttpHeaders.AUTHORIZATION)).containsOnly("Bearer " + this.accessToken.getTokenValue()); @@ -121,4 +108,5 @@ public class ServletBearerExchangeFilterFunctionTests { contextAttributes.put(Authentication.class, authentication); return Context.of(SECURITY_REACTOR_CONTEXT_ATTRIBUTES_KEY, contextAttributes); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/BearerTokenServerAuthenticationEntryPointTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/BearerTokenServerAuthenticationEntryPointTests.java index 722ff98608..a5e044252a 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/BearerTokenServerAuthenticationEntryPointTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/BearerTokenServerAuthenticationEntryPointTests.java @@ -35,6 +35,7 @@ import static org.assertj.core.api.Assertions.*; * @since 5.1 */ public class BearerTokenServerAuthenticationEntryPointTests { + private BearerTokenServerAuthenticationEntryPoint entryPoint = new BearerTokenServerAuthenticationEntryPoint(); private MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/")); @@ -53,7 +54,8 @@ public class BearerTokenServerAuthenticationEntryPointTests { this.entryPoint.commence(this.exchange, new BadCredentialsException("")).block(); - assertThat(getResponse().getHeaders().getFirst(HttpHeaders.WWW_AUTHENTICATE)).isEqualTo("Bearer realm=\"Realm\""); + assertThat(getResponse().getHeaders().getFirst(HttpHeaders.WWW_AUTHENTICATE)) + .isEqualTo("Bearer realm=\"Realm\""); assertThat(getResponse().getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } @@ -64,7 +66,8 @@ public class BearerTokenServerAuthenticationEntryPointTests { this.entryPoint.commence(this.exchange, exception).block(); - assertThat(getResponse().getHeaders().getFirst(HttpHeaders.WWW_AUTHENTICATE)).isEqualTo("Bearer error=\"invalid_request\""); + assertThat(getResponse().getHeaders().getFirst(HttpHeaders.WWW_AUTHENTICATE)) + .isEqualTo("Bearer error=\"invalid_request\""); assertThat(getResponse().getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } @@ -75,19 +78,21 @@ public class BearerTokenServerAuthenticationEntryPointTests { this.entryPoint.commence(this.exchange, exception).block(); - assertThat(getResponse().getHeaders().getFirst(HttpHeaders.WWW_AUTHENTICATE)).isEqualTo("Bearer error=\"invalid_request\", error_description=\"Oops\", error_uri=\"https://example.com\""); + assertThat(getResponse().getHeaders().getFirst(HttpHeaders.WWW_AUTHENTICATE)).isEqualTo( + "Bearer error=\"invalid_request\", error_description=\"Oops\", error_uri=\"https://example.com\""); assertThat(getResponse().getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } @Test public void commenceWhenBearerTokenThenErrorInformation() { - OAuth2Error oauthError = new BearerTokenError(OAuth2ErrorCodes.INVALID_REQUEST, - HttpStatus.BAD_REQUEST, "Oops", "https://example.com"); + OAuth2Error oauthError = new BearerTokenError(OAuth2ErrorCodes.INVALID_REQUEST, HttpStatus.BAD_REQUEST, "Oops", + "https://example.com"); OAuth2AuthenticationException exception = new OAuth2AuthenticationException(oauthError); this.entryPoint.commence(this.exchange, exception).block(); - assertThat(getResponse().getHeaders().getFirst(HttpHeaders.WWW_AUTHENTICATE)).isEqualTo("Bearer error=\"invalid_request\", error_description=\"Oops\", error_uri=\"https://example.com\""); + assertThat(getResponse().getHeaders().getFirst(HttpHeaders.WWW_AUTHENTICATE)).isEqualTo( + "Bearer error=\"invalid_request\", error_description=\"Oops\", error_uri=\"https://example.com\""); assertThat(getResponse().getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); } @@ -102,4 +107,5 @@ public class BearerTokenServerAuthenticationEntryPointTests { private MockServerHttpResponse getResponse() { return this.exchange.getResponse(); } + } diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverterTests.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverterTests.java index e7932d6f66..939c418daa 100644 --- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverterTests.java +++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverterTests.java @@ -39,7 +39,9 @@ import static org.assertj.core.api.Assertions.catchThrowableOfType; * @since 5.1 */ public class ServerBearerTokenAuthenticationConverterTests { + private static final String CUSTOM_HEADER = "custom-header"; + private static final String TEST_TOKEN = "test-token"; private ServerBearerTokenAuthenticationConverter converter; @@ -51,9 +53,8 @@ public class ServerBearerTokenAuthenticationConverterTests { @Test public void resolveWhenValidHeaderIsPresentThenTokenIsResolved() { - MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest - .get("/") - .header(HttpHeaders.AUTHORIZATION, "Bearer " + TEST_TOKEN); + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/").header(HttpHeaders.AUTHORIZATION, + "Bearer " + TEST_TOKEN); assertThat(convertToToken(request).getToken()).isEqualTo(TEST_TOKEN); } @@ -62,9 +63,8 @@ public class ServerBearerTokenAuthenticationConverterTests { @Test public void resolveWhenHeaderEndsWithPaddingIndicatorThenTokenIsResolved() { String token = TEST_TOKEN + "=="; - MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest - .get("/") - .header(HttpHeaders.AUTHORIZATION, "Bearer " + token); + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/").header(HttpHeaders.AUTHORIZATION, + "Bearer " + token); assertThat(convertToToken(request).getToken()).isEqualTo(token); } @@ -72,9 +72,8 @@ public class ServerBearerTokenAuthenticationConverterTests { @Test public void resolveWhenCustomDefinedHeaderIsValidAndPresentThenTokenIsResolved() { this.converter.setBearerTokenHeaderName(CUSTOM_HEADER); - MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest - .get("/") - .header(CUSTOM_HEADER, "Bearer " + TEST_TOKEN); + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/").header(CUSTOM_HEADER, + "Bearer " + TEST_TOKEN); assertThat(convertToToken(request).getToken()).isEqualTo(TEST_TOKEN); } @@ -82,9 +81,8 @@ public class ServerBearerTokenAuthenticationConverterTests { // gh-7011 @Test public void resolveWhenValidHeaderIsEmptyStringThenTokenIsResolved() { - MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest - .get("/") - .header(HttpHeaders.AUTHORIZATION, "Bearer "); + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/").header(HttpHeaders.AUTHORIZATION, + "Bearer "); OAuth2AuthenticationException expected = catchThrowableOfType(() -> convertToToken(request), OAuth2AuthenticationException.class); @@ -96,72 +94,60 @@ public class ServerBearerTokenAuthenticationConverterTests { @Test public void resolveWhenLowercaseHeaderIsPresentThenTokenIsResolved() { - MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest - .get("/") - .header(HttpHeaders.AUTHORIZATION, "bearer " + TEST_TOKEN); + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/").header(HttpHeaders.AUTHORIZATION, + "bearer " + TEST_TOKEN); assertThat(convertToToken(request).getToken()).isEqualTo(TEST_TOKEN); } @Test public void resolveWhenNoHeaderIsPresentThenTokenIsNotResolved() { - MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest - .get("/"); + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/"); assertThat(convertToToken(request)).isNull(); } @Test public void resolveWhenHeaderWithWrongSchemeIsPresentThenTokenIsNotResolved() { - MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest - .get("/") - .header(HttpHeaders.AUTHORIZATION, "Basic " + Base64.getEncoder().encodeToString("test:test".getBytes())); + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/").header(HttpHeaders.AUTHORIZATION, + "Basic " + Base64.getEncoder().encodeToString("test:test".getBytes())); assertThat(convertToToken(request)).isNull(); } @Test public void resolveWhenHeaderWithMissingTokenIsPresentThenAuthenticationExceptionIsThrown() { - MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest - .get("/") - .header(HttpHeaders.AUTHORIZATION, "Bearer "); + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/").header(HttpHeaders.AUTHORIZATION, + "Bearer "); - assertThatCode(() -> convertToToken(request)) - .isInstanceOf(OAuth2AuthenticationException.class) + assertThatCode(() -> convertToToken(request)).isInstanceOf(OAuth2AuthenticationException.class) .hasMessageContaining(("Bearer token is malformed")); } @Test public void resolveWhenHeaderWithInvalidCharactersIsPresentThenAuthenticationExceptionIsThrown() { - MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest - .get("/") - .header(HttpHeaders.AUTHORIZATION, "Bearer an\"invalid\"token"); + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/").header(HttpHeaders.AUTHORIZATION, + "Bearer an\"invalid\"token"); - assertThatCode(() -> convertToToken(request)) - .isInstanceOf(OAuth2AuthenticationException.class) + assertThatCode(() -> convertToToken(request)).isInstanceOf(OAuth2AuthenticationException.class) .hasMessageContaining(("Bearer token is malformed")); } // gh-8865 @Test public void resolveWhenHeaderWithInvalidCharactersIsPresentAndNotSubscribedThenNoneExceptionIsThrown() { - MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest - .get("/") - .header(HttpHeaders.AUTHORIZATION, "Bearer an\"invalid\"token"); + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/").header(HttpHeaders.AUTHORIZATION, + "Bearer an\"invalid\"token"); - assertThatCode(() -> this.converter.convert(MockServerWebExchange.from(request))) - .doesNotThrowAnyException(); + assertThatCode(() -> this.converter.convert(MockServerWebExchange.from(request))).doesNotThrowAnyException(); } @Test public void resolveWhenValidHeaderIsPresentTogetherWithQueryParameterThenAuthenticationExceptionIsThrown() { - MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest - .get("/") - .queryParam("access_token", TEST_TOKEN) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + TEST_TOKEN); + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/") + .queryParam("access_token", TEST_TOKEN).header(HttpHeaders.AUTHORIZATION, "Bearer " + TEST_TOKEN); - assertThatCode(() -> convertToToken(request)) - .isInstanceOf(OAuth2AuthenticationException.class) + assertThatCode(() -> convertToToken(request)).isInstanceOf(OAuth2AuthenticationException.class) .hasMessageContaining("Found multiple bearer tokens in the request"); } @@ -169,9 +155,8 @@ public class ServerBearerTokenAuthenticationConverterTests { public void resolveWhenQueryParameterIsPresentAndSupportedThenTokenIsResolved() { this.converter.setAllowUriQueryParameter(true); - MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest - .get("/") - .queryParam("access_token", TEST_TOKEN); + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/").queryParam("access_token", + TEST_TOKEN); assertThat(convertToToken(request).getToken()).isEqualTo(TEST_TOKEN); } @@ -181,12 +166,10 @@ public class ServerBearerTokenAuthenticationConverterTests { public void resolveWhenQueryParameterIsEmptyAndSupportedThenOAuth2AuthenticationException() { this.converter.setAllowUriQueryParameter(true); - MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest - .get("/") - .queryParam("access_token", ""); + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/").queryParam("access_token", ""); OAuth2AuthenticationException expected = catchThrowableOfType(() -> convertToToken(request), - OAuth2AuthenticationException.class); + OAuth2AuthenticationException.class); BearerTokenError error = (BearerTokenError) expected.getError(); assertThat(error.getErrorCode()).isEqualTo(BearerTokenErrorCodes.INVALID_TOKEN); assertThat(error.getUri()).isEqualTo("https://tools.ietf.org/html/rfc6750#section-3.1"); @@ -195,9 +178,8 @@ public class ServerBearerTokenAuthenticationConverterTests { @Test public void resolveWhenQueryParameterIsPresentAndNotSupportedThenTokenIsNotResolved() { - MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest - .get("/") - .queryParam("access_token", TEST_TOKEN); + MockServerHttpRequest.BaseBuilder request = MockServerHttpRequest.get("/").queryParam("access_token", + TEST_TOKEN); assertThat(convertToToken(request)).isNull(); } @@ -210,4 +192,5 @@ public class ServerBearerTokenAuthenticationConverterTests { MockServerWebExchange exchange = MockServerWebExchange.from(request); return this.converter.convert(exchange).cast(BearerTokenAuthenticationToken.class).block(); } + } diff --git a/openid/src/main/java/org/springframework/security/openid/AuthenticationCancelledException.java b/openid/src/main/java/org/springframework/security/openid/AuthenticationCancelledException.java index e5e89d5e38..acfe840916 100644 --- a/openid/src/main/java/org/springframework/security/openid/AuthenticationCancelledException.java +++ b/openid/src/main/java/org/springframework/security/openid/AuthenticationCancelledException.java @@ -21,11 +21,13 @@ import org.springframework.security.core.AuthenticationException; * Indicates that OpenID authentication was cancelled * * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author Robin Bramley, Opsera Ltd */ public class AuthenticationCancelledException extends AuthenticationException { + // ~ Constructors // =================================================================================================== @@ -36,4 +38,5 @@ public class AuthenticationCancelledException extends AuthenticationException { public AuthenticationCancelledException(String msg, Throwable t) { super(msg, t); } + } diff --git a/openid/src/main/java/org/springframework/security/openid/AxFetchListFactory.java b/openid/src/main/java/org/springframework/security/openid/AxFetchListFactory.java index 3c99c94626..d279f333d5 100644 --- a/openid/src/main/java/org/springframework/security/openid/AxFetchListFactory.java +++ b/openid/src/main/java/org/springframework/security/openid/AxFetchListFactory.java @@ -25,8 +25,9 @@ import java.util.List; * OpenID providers, since they do not all support the same attributes. * * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author Luke Taylor * @since 3.1 */ @@ -35,9 +36,9 @@ public interface AxFetchListFactory { /** * Builds the list of attributes which should be added to the fetch request for the * supplied OpenID identifier. - * * @param identifier the claimed_identity * @return the attributes to fetch for this identifier */ List createAttributeList(String identifier); + } diff --git a/openid/src/main/java/org/springframework/security/openid/NullAxFetchListFactory.java b/openid/src/main/java/org/springframework/security/openid/NullAxFetchListFactory.java index 75df033bac..5cea1bba77 100644 --- a/openid/src/main/java/org/springframework/security/openid/NullAxFetchListFactory.java +++ b/openid/src/main/java/org/springframework/security/openid/NullAxFetchListFactory.java @@ -20,13 +20,16 @@ import java.util.List; /** * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author Luke Taylor * @since 3.1 */ public class NullAxFetchListFactory implements AxFetchListFactory { + public List createAttributeList(String identifier) { return Collections.emptyList(); } + } diff --git a/openid/src/main/java/org/springframework/security/openid/OpenID4JavaConsumer.java b/openid/src/main/java/org/springframework/security/openid/OpenID4JavaConsumer.java index 7ab6f47615..ad110c9342 100644 --- a/openid/src/main/java/org/springframework/security/openid/OpenID4JavaConsumer.java +++ b/openid/src/main/java/org/springframework/security/openid/OpenID4JavaConsumer.java @@ -42,14 +42,17 @@ import org.springframework.util.StringUtils; /** * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author Ray Krueger * @author Luke Taylor */ @SuppressWarnings("unchecked") public class OpenID4JavaConsumer implements OpenIDConsumer { + private static final String DISCOVERY_INFO_KEY = DiscoveryInformation.class.getName(); + private static final String ATTRIBUTE_LIST_KEY = "SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST"; // ~ Instance fields @@ -58,6 +61,7 @@ public class OpenID4JavaConsumer implements OpenIDConsumer { protected final Log logger = LogFactory.getLog(getClass()); private final ConsumerManager consumerManager; + private final AxFetchListFactory attributesToFetchFactory; // ~ Constructors @@ -67,13 +71,11 @@ public class OpenID4JavaConsumer implements OpenIDConsumer { this(new ConsumerManager(), new NullAxFetchListFactory()); } - public OpenID4JavaConsumer(AxFetchListFactory attributesToFetchFactory) - throws ConsumerException { + public OpenID4JavaConsumer(AxFetchListFactory attributesToFetchFactory) throws ConsumerException { this(new ConsumerManager(), attributesToFetchFactory); } - public OpenID4JavaConsumer(ConsumerManager consumerManager, - AxFetchListFactory attributesToFetchFactory) { + public OpenID4JavaConsumer(ConsumerManager consumerManager, AxFetchListFactory attributesToFetchFactory) { this.consumerManager = consumerManager; this.attributesToFetchFactory = attributesToFetchFactory; } @@ -81,8 +83,8 @@ public class OpenID4JavaConsumer implements OpenIDConsumer { // ~ Methods // ======================================================================================================== - public String beginConsumption(HttpServletRequest req, String identityUrl, - String returnToUrl, String realm) throws OpenIDConsumerException { + public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl, String realm) + throws OpenIDConsumerException { List discoveries; try { @@ -102,48 +104,42 @@ public class OpenID4JavaConsumer implements OpenIDConsumer { logger.debug("Looking up attribute fetch list for identifier: " + identityUrl); - List attributesToFetch = attributesToFetchFactory - .createAttributeList(identityUrl); + List attributesToFetch = attributesToFetchFactory.createAttributeList(identityUrl); if (!attributesToFetch.isEmpty()) { req.getSession().setAttribute(ATTRIBUTE_LIST_KEY, attributesToFetch); FetchRequest fetchRequest = FetchRequest.createFetchRequest(); for (OpenIDAttribute attr : attributesToFetch) { if (logger.isDebugEnabled()) { - logger.debug("Adding attribute " + attr.getType() - + " to fetch request"); + logger.debug("Adding attribute " + attr.getType() + " to fetch request"); } - fetchRequest.addAttribute(attr.getName(), attr.getType(), - attr.isRequired(), attr.getCount()); + fetchRequest.addAttribute(attr.getName(), attr.getType(), attr.isRequired(), attr.getCount()); } authReq.addExtension(fetchRequest); } } catch (MessageException | ConsumerException e) { - throw new OpenIDConsumerException( - "Error processing ConsumerManager authentication", e); + throw new OpenIDConsumerException("Error processing ConsumerManager authentication", e); } return authReq.getDestinationUrl(true); } - public OpenIDAuthenticationToken endConsumption(HttpServletRequest request) - throws OpenIDConsumerException { + public OpenIDAuthenticationToken endConsumption(HttpServletRequest request) throws OpenIDConsumerException { // extract the parameters from the authentication response // (which comes in as a HTTP request from the OpenID provider) ParameterList openidResp = new ParameterList(request.getParameterMap()); // retrieve the previously stored discovery information - DiscoveryInformation discovered = (DiscoveryInformation) request.getSession() - .getAttribute(DISCOVERY_INFO_KEY); + DiscoveryInformation discovered = (DiscoveryInformation) request.getSession().getAttribute(DISCOVERY_INFO_KEY); if (discovered == null) { throw new OpenIDConsumerException( "DiscoveryInformation is not available. Possible causes are lost session or replay attack"); } - List attributesToFetch = (List) request - .getSession().getAttribute(ATTRIBUTE_LIST_KEY); + List attributesToFetch = (List) request.getSession() + .getAttribute(ATTRIBUTE_LIST_KEY); request.getSession().removeAttribute(DISCOVERY_INFO_KEY); request.getSession().removeAttribute(ATTRIBUTE_LIST_KEY); @@ -160,8 +156,7 @@ public class OpenID4JavaConsumer implements OpenIDConsumer { VerificationResult verification; try { - verification = consumerManager.verify(receivingURL.toString(), openidResp, - discovered); + verification = consumerManager.verify(receivingURL.toString(), openidResp, discovered); } catch (MessageException | AssociationException | DiscoveryException e) { throw new OpenIDConsumerException("Error verifying openid response", e); @@ -175,21 +170,19 @@ public class OpenID4JavaConsumer implements OpenIDConsumer { return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE, id == null ? "Unknown" : id.getIdentifier(), "Verification status message: [" + verification.getStatusMsg() + "]", - Collections. emptyList()); + Collections.emptyList()); } - List attributes = fetchAxAttributes( - verification.getAuthResponse(), attributesToFetch); + List attributes = fetchAxAttributes(verification.getAuthResponse(), attributesToFetch); - return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, - verified.getIdentifier(), "some message", attributes); + return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, verified.getIdentifier(), + "some message", attributes); } - List fetchAxAttributes(Message authSuccess, - List attributesToFetch) throws OpenIDConsumerException { + List fetchAxAttributes(Message authSuccess, List attributesToFetch) + throws OpenIDConsumerException { - if (attributesToFetch == null - || !authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) { + if (attributesToFetch == null || !authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) { return Collections.emptyList(); } @@ -206,8 +199,7 @@ public class OpenID4JavaConsumer implements OpenIDConsumer { for (OpenIDAttribute attr : attributesToFetch) { List values = fetchResp.getAttributeValues(attr.getName()); if (!values.isEmpty()) { - OpenIDAttribute fetched = new OpenIDAttribute(attr.getName(), - attr.getType(), values); + OpenIDAttribute fetched = new OpenIDAttribute(attr.getName(), attr.getType(), values); fetched.setRequired(attr.isRequired()); attributes.add(fetched); } @@ -224,4 +216,5 @@ public class OpenID4JavaConsumer implements OpenIDConsumer { return attributes; } + } diff --git a/openid/src/main/java/org/springframework/security/openid/OpenIDAttribute.java b/openid/src/main/java/org/springframework/security/openid/OpenIDAttribute.java index c15d45856d..1f82bb8ea1 100644 --- a/openid/src/main/java/org/springframework/security/openid/OpenIDAttribute.java +++ b/openid/src/main/java/org/springframework/security/openid/OpenIDAttribute.java @@ -28,15 +28,20 @@ import org.springframework.util.Assert; * are returned during the authentication process. * * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author Luke Taylor * @since 3.0 */ public class OpenIDAttribute implements Serializable { + private final String name; + private final String typeIdentifier; + private boolean required = false; + private int count = 1; private final List values; @@ -96,8 +101,7 @@ public class OpenIDAttribute implements Serializable { * The values obtained from an attribute exchange. */ public List getValues() { - Assert.notNull(values, - "Cannot read values from an authentication request attribute"); + Assert.notNull(values, "Cannot read values from an authentication request attribute"); return values; } @@ -112,4 +116,5 @@ public class OpenIDAttribute implements Serializable { result.append("]"); return result.toString(); } + } diff --git a/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationFilter.java b/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationFilter.java index 9c3999d704..6c76689397 100644 --- a/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationFilter.java +++ b/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationFilter.java @@ -60,8 +60,9 @@ import java.util.*; * order to load the authorities for the user. * * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author Robin Bramley * @author Ray Krueger * @author Luke Taylor @@ -69,6 +70,7 @@ import java.util.*; * @see OpenIDAuthenticationProvider */ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessingFilter { + // ~ Static fields/initializers // ===================================================================================== @@ -78,8 +80,11 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing // ================================================================================================ private OpenIDConsumer consumer; + private String claimedIdentityFieldName = DEFAULT_CLAIMED_IDENTITY_FIELD; + private Map realmMapping = Collections.emptyMap(); + private Set returnToUrlParameters = Collections.emptySet(); // ~ Constructors @@ -105,12 +110,9 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing } } - if (returnToUrlParameters.isEmpty() - && getRememberMeServices() instanceof AbstractRememberMeServices) { + if (returnToUrlParameters.isEmpty() && getRememberMeServices() instanceof AbstractRememberMeServices) { returnToUrlParameters = new HashSet<>(); - returnToUrlParameters - .add(((AbstractRememberMeServices) getRememberMeServices()) - .getParameter()); + returnToUrlParameters.add(((AbstractRememberMeServices) getRememberMeServices()).getParameter()); } } @@ -124,8 +126,8 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing * */ @Override - public Authentication attemptAuthentication(HttpServletRequest request, - HttpServletResponse response) throws AuthenticationException, IOException { + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) + throws AuthenticationException, IOException { OpenIDAuthenticationToken token; String identity = request.getParameter("openid.identity"); @@ -136,11 +138,9 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing try { String returnToUrl = buildReturnToUrl(request); String realm = lookupRealm(returnToUrl); - String openIdUrl = consumer.beginConsumption(request, claimedIdentity, - returnToUrl, realm); + String openIdUrl = consumer.beginConsumption(request, claimedIdentity, returnToUrl, realm); if (logger.isDebugEnabled()) { - logger.debug("return_to is '" + returnToUrl + "', realm is '" + realm - + "'"); + logger.debug("return_to is '" + returnToUrl + "', realm is '" + realm + "'"); logger.debug("Redirecting to " + openIdUrl); } response.sendRedirect(openIdUrl); @@ -169,8 +169,7 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing token.setDetails(authenticationDetailsSource.buildDetails(request)); // delegate to the authentication provider - Authentication authentication = this.getAuthenticationManager().authenticate( - token); + Authentication authentication = this.getAuthenticationManager().authenticate(token); return authentication; } @@ -183,8 +182,8 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing URL url = new URL(returnToUrl); int port = url.getPort(); - StringBuilder realmBuffer = new StringBuilder(returnToUrl.length()) - .append(url.getProtocol()).append("://").append(url.getHost()); + StringBuilder realmBuffer = new StringBuilder(returnToUrl.length()).append(url.getProtocol()) + .append("://").append(url.getHost()); if (port > 0) { realmBuffer.append(":").append(port); } @@ -202,7 +201,6 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing /** * Builds the return_to URL that will be sent to the OpenID service provider. * By default returns the URL of the current request. - * * @param request the current request which is being processed by this filter * @return The return_to URL. */ @@ -259,7 +257,6 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing * protocol, hostname and port followed by a trailing slash. This means that * https://foo.example.com/login/openid will automatically become * http://foo.example.com:80/ - * * @param realmMapping containing returnToUrl -> realm mappings */ public void setRealmMapping(Map realmMapping) { @@ -269,7 +266,6 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing /** * The name of the request parameter containing the OpenID identity, as submitted from * the initial login form. - * * @param claimedIdentityFieldName defaults to "openid_identifier" */ public void setClaimedIdentityFieldName(String claimedIdentityFieldName) { @@ -284,7 +280,6 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing * Specifies any extra parameters submitted along with the identity field which should * be appended to the {@code return_to} URL which is assembled by * {@link #buildReturnToUrl}. - * * @param returnToUrlParameters the set of parameter names. If not set, it will * default to the parameter name used by the {@code RememberMeServices} obtained from * the parent class (if one is set). @@ -296,7 +291,6 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing /** * Performs URL encoding with UTF-8 - * * @param value the value to URL encode * @return the encoded value */ @@ -311,4 +305,5 @@ public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessing throw err; } } + } diff --git a/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationProvider.java b/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationProvider.java index e42baa6d1f..7a94db22a2 100644 --- a/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationProvider.java +++ b/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationProvider.java @@ -45,17 +45,19 @@ import org.springframework.util.Assert; * telephone numbers etc can easily be stored. * * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author Robin Bramley, Opsera Ltd. * @author Luke Taylor */ -public class OpenIDAuthenticationProvider - implements AuthenticationProvider, InitializingBean { +public class OpenIDAuthenticationProvider implements AuthenticationProvider, InitializingBean { + // ~ Instance fields // ================================================================================================ private AuthenticationUserDetailsService userDetailsService; + private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper(); // ~ Methods @@ -72,8 +74,7 @@ public class OpenIDAuthenticationProvider * org.springframework.security.authentication.AuthenticationProvider#authenticate * (org.springframework.security.Authentication) */ - public Authentication authenticate(final Authentication authentication) - throws AuthenticationException { + public Authentication authenticate(final Authentication authentication) throws AuthenticationException { if (!supports(authentication.getClass())) { return null; @@ -86,8 +87,7 @@ public class OpenIDAuthenticationProvider // handle the various possibilities if (status == OpenIDAuthenticationStatus.SUCCESS) { // Lookup user details - UserDetails userDetails = this.userDetailsService - .loadUserDetails(response); + UserDetails userDetails = this.userDetailsService.loadUserDetails(response); return createSuccessfulAuthentication(userDetails, response); @@ -96,20 +96,17 @@ public class OpenIDAuthenticationProvider throw new AuthenticationCancelledException("Log in cancelled"); } else if (status == OpenIDAuthenticationStatus.ERROR) { - throw new AuthenticationServiceException( - "Error message from server: " + response.getMessage()); + throw new AuthenticationServiceException("Error message from server: " + response.getMessage()); } else if (status == OpenIDAuthenticationStatus.FAILURE) { - throw new BadCredentialsException( - "Log in failed - identity could not be verified"); + throw new BadCredentialsException("Log in failed - identity could not be verified"); } else if (status == OpenIDAuthenticationStatus.SETUP_NEEDED) { throw new AuthenticationServiceException( "The server responded setup was needed, which shouldn't happen"); } else { - throw new AuthenticationServiceException( - "Unrecognized return value " + status.toString()); + throw new AuthenticationServiceException("Unrecognized return value " + status.toString()); } } @@ -123,24 +120,21 @@ public class OpenIDAuthenticationProvider * The default implementation just creates a new OpenIDAuthenticationToken from the * original, but with the UserDetails as the principal and including the authorities * loaded by the UserDetailsService. - * * @param userDetails the loaded UserDetails object * @param auth the token passed to the authenticate method, containing * @return the token which will represent the authenticated user. */ - protected Authentication createSuccessfulAuthentication(UserDetails userDetails, - OpenIDAuthenticationToken auth) { + protected Authentication createSuccessfulAuthentication(UserDetails userDetails, OpenIDAuthenticationToken auth) { return new OpenIDAuthenticationToken(userDetails, - this.authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), - auth.getIdentityUrl(), auth.getAttributes()); + this.authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), auth.getIdentityUrl(), + auth.getAttributes()); } /** * Used to load the {@code UserDetails} for the authenticated OpenID user. */ public void setUserDetailsService(UserDetailsService userDetailsService) { - this.userDetailsService = new UserDetailsByNameServiceWrapper<>( - userDetailsService); + this.userDetailsService = new UserDetailsByNameServiceWrapper<>(userDetailsService); } /** @@ -165,4 +159,5 @@ public class OpenIDAuthenticationProvider public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) { this.authoritiesMapper = authoritiesMapper; } + } diff --git a/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationStatus.java b/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationStatus.java index db2eee832b..16586b7b10 100644 --- a/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationStatus.java +++ b/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationStatus.java @@ -17,10 +17,10 @@ package org.springframework.security.openid; /** * Authentication status codes, based on JanRain status codes - * * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author JanRain Inc. * @author Robin Bramley, Opsera Ltd * @author Luke Taylor @@ -58,4 +58,5 @@ public enum OpenIDAuthenticationStatus { public String toString() { return name; } + } diff --git a/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationToken.java b/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationToken.java index 0625e07727..659cbf53a5 100644 --- a/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationToken.java +++ b/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationToken.java @@ -27,8 +27,9 @@ import org.springframework.security.core.SpringSecurityCoreVersion; * OpenID Authentication Token * * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author Robin Bramley */ public class OpenIDAuthenticationToken extends AbstractAuthenticationToken { @@ -39,16 +40,20 @@ public class OpenIDAuthenticationToken extends AbstractAuthenticationToken { // ================================================================================================ private final OpenIDAuthenticationStatus status; + private final Object principal; + private final String identityUrl; + private final String message; + private final List attributes; // ~ Constructors // =================================================================================================== - public OpenIDAuthenticationToken(OpenIDAuthenticationStatus status, - String identityUrl, String message, List attributes) { + public OpenIDAuthenticationToken(OpenIDAuthenticationStatus status, String identityUrl, String message, + List attributes) { super(new ArrayList<>(0)); this.principal = identityUrl; this.status = status; @@ -60,14 +65,12 @@ public class OpenIDAuthenticationToken extends AbstractAuthenticationToken { /** * Created by the OpenIDAuthenticationProvider on successful authentication. - * * @param principal usually the UserDetails returned by the configured * UserDetailsService used by the OpenIDAuthenticationProvider. * */ - public OpenIDAuthenticationToken(Object principal, - Collection authorities, String identityUrl, - List attributes) { + public OpenIDAuthenticationToken(Object principal, Collection authorities, + String identityUrl, List attributes) { super(authorities); this.principal = principal; this.status = OpenIDAuthenticationStatus.SUCCESS; @@ -118,4 +121,5 @@ public class OpenIDAuthenticationToken extends AbstractAuthenticationToken { public String toString() { return "[" + super.toString() + ", attributes : " + attributes + "]"; } + } diff --git a/openid/src/main/java/org/springframework/security/openid/OpenIDConsumer.java b/openid/src/main/java/org/springframework/security/openid/OpenIDConsumer.java index 303b143a9a..540e661df8 100644 --- a/openid/src/main/java/org/springframework/security/openid/OpenIDConsumer.java +++ b/openid/src/main/java/org/springframework/security/openid/OpenIDConsumer.java @@ -21,8 +21,9 @@ import javax.servlet.http.HttpServletRequest; * An interface for OpenID library implementations * * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author Ray Krueger * @author Robin Bramley, Opsera Ltd */ @@ -31,7 +32,6 @@ public interface OpenIDConsumer { /** * Given the request, the claimedIdentity, the return to url, and a realm, lookup the * openId authentication page the user should be redirected to. - * * @param req HttpServletRequest * @param claimedIdentity String URI the user presented during authentication * @param returnToUrl String URI of the URL we want the user sent back to by the OP @@ -39,10 +39,9 @@ public interface OpenIDConsumer { * @return String URI to redirect user to for authentication * @throws OpenIDConsumerException if anything bad happens */ - String beginConsumption(HttpServletRequest req, String claimedIdentity, - String returnToUrl, String realm) throws OpenIDConsumerException; - - OpenIDAuthenticationToken endConsumption(HttpServletRequest req) + String beginConsumption(HttpServletRequest req, String claimedIdentity, String returnToUrl, String realm) throws OpenIDConsumerException; + OpenIDAuthenticationToken endConsumption(HttpServletRequest req) throws OpenIDConsumerException; + } diff --git a/openid/src/main/java/org/springframework/security/openid/OpenIDConsumerException.java b/openid/src/main/java/org/springframework/security/openid/OpenIDConsumerException.java index f184032c15..9092f6ad5e 100644 --- a/openid/src/main/java/org/springframework/security/openid/OpenIDConsumerException.java +++ b/openid/src/main/java/org/springframework/security/openid/OpenIDConsumerException.java @@ -19,11 +19,13 @@ package org.springframework.security.openid; * Thrown by an OpenIDConsumer if it cannot process a request * * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author Robin Bramley, Opsera Ltd */ public class OpenIDConsumerException extends Exception { + // ~ Constructors // =================================================================================================== @@ -34,4 +36,5 @@ public class OpenIDConsumerException extends Exception { public OpenIDConsumerException(String message, Throwable t) { super(message, t); } + } diff --git a/openid/src/main/java/org/springframework/security/openid/RegexBasedAxFetchListFactory.java b/openid/src/main/java/org/springframework/security/openid/RegexBasedAxFetchListFactory.java index b59481bb38..3f5b413662 100644 --- a/openid/src/main/java/org/springframework/security/openid/RegexBasedAxFetchListFactory.java +++ b/openid/src/main/java/org/springframework/security/openid/RegexBasedAxFetchListFactory.java @@ -23,12 +23,14 @@ import java.util.regex.Pattern; /** * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author Luke Taylor * @since 3.1 */ public class RegexBasedAxFetchListFactory implements AxFetchListFactory { + private final Map> idToAttributes; /** diff --git a/openid/src/main/java/org/springframework/security/openid/package-info.java b/openid/src/main/java/org/springframework/security/openid/package-info.java index 3abaa47aa6..78ce088c0e 100644 --- a/openid/src/main/java/org/springframework/security/openid/package-info.java +++ b/openid/src/main/java/org/springframework/security/openid/package-info.java @@ -14,4 +14,3 @@ * limitations under the License. */ package org.springframework.security.openid; - diff --git a/openid/src/test/java/org/springframework/security/openid/MockOpenIDConsumer.java b/openid/src/test/java/org/springframework/security/openid/MockOpenIDConsumer.java index ce8f1a2382..cb4f7576d4 100644 --- a/openid/src/test/java/org/springframework/security/openid/MockOpenIDConsumer.java +++ b/openid/src/test/java/org/springframework/security/openid/MockOpenIDConsumer.java @@ -19,15 +19,18 @@ import javax.servlet.http.HttpServletRequest; /** * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author Robin Bramley, Opsera Ltd */ public class MockOpenIDConsumer implements OpenIDConsumer { + // ~ Instance fields // ================================================================================================ private OpenIDAuthenticationToken token; + private String redirectUrl; public MockOpenIDConsumer() { @@ -49,8 +52,7 @@ public class MockOpenIDConsumer implements OpenIDConsumer { // ~ Methods // ======================================================================================================== - public String beginConsumption(HttpServletRequest req, String claimedIdentity, - String returnToUrl, String realm) { + public String beginConsumption(HttpServletRequest req, String claimedIdentity, String returnToUrl, String realm) { return redirectUrl; } @@ -60,7 +62,6 @@ public class MockOpenIDConsumer implements OpenIDConsumer { /** * Set the redirectUrl to be returned by beginConsumption - * * @param redirectUrl */ public void setRedirectUrl(String redirectUrl) { @@ -73,10 +74,10 @@ public class MockOpenIDConsumer implements OpenIDConsumer { /** * Set the token to be returned by endConsumption - * * @param token */ public void setToken(OpenIDAuthenticationToken token) { this.token = token; } + } diff --git a/openid/src/test/java/org/springframework/security/openid/OpenID4JavaConsumerTests.java b/openid/src/test/java/org/springframework/security/openid/OpenID4JavaConsumerTests.java index 971c19a15f..f185a46066 100644 --- a/openid/src/test/java/org/springframework/security/openid/OpenID4JavaConsumerTests.java +++ b/openid/src/test/java/org/springframework/security/openid/OpenID4JavaConsumerTests.java @@ -41,11 +41,13 @@ import java.util.*; /** * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author Luke Taylor */ public class OpenID4JavaConsumerTests { + List attributes = Arrays.asList(new OpenIDAttribute("a", "b"), new OpenIDAttribute("b", "b", Arrays.asList("c"))); @@ -56,20 +58,17 @@ public class OpenID4JavaConsumerTests { AuthRequest authReq = mock(AuthRequest.class); DiscoveryInformation di = mock(DiscoveryInformation.class); - when(mgr.authenticate(any(DiscoveryInformation.class), any(), any())) - .thenReturn(authReq); + when(mgr.authenticate(any(DiscoveryInformation.class), any(), any())).thenReturn(authReq); when(mgr.associate(any())).thenReturn(di); - OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, - new MockAttributesFactory()); + OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, new MockAttributesFactory()); MockHttpServletRequest request = new MockHttpServletRequest(); consumer.beginConsumption(request, "", "", ""); - assertThat(request.getSession().getAttribute( - "SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST")).isEqualTo(attributes); - assertThat( - request.getSession().getAttribute(DiscoveryInformation.class.getName())).isEqualTo(di); + assertThat(request.getSession().getAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST")) + .isEqualTo(attributes); + assertThat(request.getSession().getAttribute(DiscoveryInformation.class.getName())).isEqualTo(di); // Check with empty attribute fetch list consumer = new OpenID4JavaConsumer(mgr, new NullAxFetchListFactory()); @@ -81,18 +80,15 @@ public class OpenID4JavaConsumerTests { @Test(expected = OpenIDConsumerException.class) public void discoveryExceptionRaisesOpenIDException() throws Exception { ConsumerManager mgr = mock(ConsumerManager.class); - OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, - new NullAxFetchListFactory()); + OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, new NullAxFetchListFactory()); when(mgr.discover(any())).thenThrow(new DiscoveryException("msg")); consumer.beginConsumption(new MockHttpServletRequest(), "", "", ""); } @Test - public void messageOrConsumerAuthenticationExceptionRaisesOpenIDException() - throws Exception { + public void messageOrConsumerAuthenticationExceptionRaisesOpenIDException() throws Exception { ConsumerManager mgr = mock(ConsumerManager.class); - OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, - new NullAxFetchListFactory()); + OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, new NullAxFetchListFactory()); when(mgr.authenticate(ArgumentMatchers.any(), any(), any())) .thenThrow(new MessageException("msg"), new ConsumerException("msg")); @@ -114,14 +110,11 @@ public class OpenID4JavaConsumerTests { @Test public void failedVerificationReturnsFailedAuthenticationStatus() throws Exception { ConsumerManager mgr = mock(ConsumerManager.class); - OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, - new NullAxFetchListFactory()); + OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, new NullAxFetchListFactory()); VerificationResult vr = mock(VerificationResult.class); DiscoveryInformation di = mock(DiscoveryInformation.class); - when( - mgr.verify(any(), any(ParameterList.class), - any(DiscoveryInformation.class))).thenReturn(vr); + when(mgr.verify(any(), any(ParameterList.class), any(DiscoveryInformation.class))).thenReturn(vr); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -135,14 +128,10 @@ public class OpenID4JavaConsumerTests { @Test public void verificationExceptionsRaiseOpenIDException() throws Exception { ConsumerManager mgr = mock(ConsumerManager.class); - OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, - new NullAxFetchListFactory()); + OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, new NullAxFetchListFactory()); - when( - mgr.verify(any(), any(ParameterList.class), - any(DiscoveryInformation.class))) - .thenThrow(new MessageException("")) - .thenThrow(new AssociationException("")) + when(mgr.verify(any(), any(ParameterList.class), any(DiscoveryInformation.class))) + .thenThrow(new MessageException("")).thenThrow(new AssociationException("")) .thenThrow(new DiscoveryException("")); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -175,24 +164,20 @@ public class OpenID4JavaConsumerTests { @Test public void successfulVerificationReturnsExpectedAuthentication() throws Exception { ConsumerManager mgr = mock(ConsumerManager.class); - OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, - new NullAxFetchListFactory()); + OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, new NullAxFetchListFactory()); VerificationResult vr = mock(VerificationResult.class); DiscoveryInformation di = mock(DiscoveryInformation.class); Identifier id = (Identifier) () -> "id"; Message msg = mock(Message.class); - when( - mgr.verify(any(), any(ParameterList.class), - any(DiscoveryInformation.class))).thenReturn(vr); + when(mgr.verify(any(), any(ParameterList.class), any(DiscoveryInformation.class))).thenReturn(vr); when(vr.getVerifiedId()).thenReturn(id); when(vr.getAuthResponse()).thenReturn(msg); MockHttpServletRequest request = new MockHttpServletRequest(); request.getSession().setAttribute(DiscoveryInformation.class.getName(), di); - request.getSession().setAttribute( - "SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST", attributes); + request.getSession().setAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST", attributes); OpenIDAuthenticationToken auth = consumer.endConsumption(request); @@ -201,8 +186,7 @@ public class OpenID4JavaConsumerTests { @Test public void fetchAttributesReturnsExpectedValues() throws Exception { - OpenID4JavaConsumer consumer = new OpenID4JavaConsumer( - new NullAxFetchListFactory()); + OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(new NullAxFetchListFactory()); Message msg = mock(Message.class); FetchResponse fr = mock(FetchResponse.class); when(msg.hasExtension(AxMessage.OPENID_NS_AX)).thenReturn(true); @@ -216,15 +200,12 @@ public class OpenID4JavaConsumerTests { } @Test(expected = OpenIDConsumerException.class) - public void messageExceptionFetchingAttributesRaisesOpenIDException() - throws Exception { - OpenID4JavaConsumer consumer = new OpenID4JavaConsumer( - new NullAxFetchListFactory()); + public void messageExceptionFetchingAttributesRaisesOpenIDException() throws Exception { + OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(new NullAxFetchListFactory()); Message msg = mock(Message.class); FetchResponse fr = mock(FetchResponse.class); when(msg.hasExtension(AxMessage.OPENID_NS_AX)).thenReturn(true); - when(msg.getExtension(AxMessage.OPENID_NS_AX)) - .thenThrow(new MessageException("")); + when(msg.getExtension(AxMessage.OPENID_NS_AX)).thenThrow(new MessageException("")); when(fr.getAttributeValues("a")).thenReturn(Arrays.asList("x", "y")); consumer.fetchAxAttributes(msg, attributes); @@ -232,8 +213,7 @@ public class OpenID4JavaConsumerTests { @Test(expected = OpenIDConsumerException.class) public void missingDiscoveryInformationThrowsException() throws Exception { - OpenID4JavaConsumer consumer = new OpenID4JavaConsumer( - new NullAxFetchListFactory()); + OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(new NullAxFetchListFactory()); consumer.endConsumption(new MockHttpServletRequest()); } @@ -248,5 +228,7 @@ public class OpenID4JavaConsumerTests { public List createAttributeList(String identifier) { return attributes; } + } + } diff --git a/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationFilterTests.java b/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationFilterTests.java index dbaf2eeb68..f01c669bd6 100644 --- a/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationFilterTests.java +++ b/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationFilterTests.java @@ -33,17 +33,22 @@ import org.springframework.security.web.authentication.SavedRequestAwareAuthenti /** * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. */ public class OpenIDAuthenticationFilterTests { OpenIDAuthenticationFilter filter; + private static final String REDIRECT_URL = "https://www.example.com/redirect"; + private static final String CLAIMED_IDENTITY_URL = "https://www.example.com/identity"; + private static final String REQUEST_PATH = "/login/openid"; - private static final String FILTER_PROCESS_URL = "http://localhost:8080" - + REQUEST_PATH; + + private static final String FILTER_PROCESS_URL = "http://localhost:8080" + REQUEST_PATH; + private static final String DEFAULT_TARGET_URL = FILTER_PROCESS_URL; @Before @@ -69,8 +74,8 @@ public class OpenIDAuthenticationFilterTests { req.setRemoteHost("www.example.com"); filter.setConsumer(new MockOpenIDConsumer() { - public String beginConsumption(HttpServletRequest req, - String claimedIdentity, String returnToUrl, String realm) { + public String beginConsumption(HttpServletRequest req, String claimedIdentity, String returnToUrl, + String realm) { assertThat(claimedIdentity).isEqualTo(CLAIMED_IDENTITY_URL); assertThat(returnToUrl).isEqualTo(DEFAULT_TARGET_URL); assertThat(realm).isEqualTo("http://localhost:8080/"); @@ -82,8 +87,7 @@ public class OpenIDAuthenticationFilterTests { filter.doFilter(req, response, fc); assertThat(response.getRedirectedUrl()).isEqualTo(REDIRECT_URL); // Filter chain shouldn't proceed - verify(fc, never()).doFilter(any(HttpServletRequest.class), - any(HttpServletResponse.class)); + verify(fc, never()).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class)); } /** @@ -116,4 +120,5 @@ public class OpenIDAuthenticationFilterTests { } return count; } + } diff --git a/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationProviderTests.java b/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationProviderTests.java index 902ca9b8fe..2ba7d99a50 100644 --- a/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationProviderTests.java +++ b/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationProviderTests.java @@ -36,11 +36,13 @@ import org.springframework.security.core.userdetails.UserDetailsService; * Tests {@link OpenIDAuthenticationProvider} * * @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are - * encouraged to migrate - * to OpenID Connect, which is supported by spring-security-oauth2. + * encouraged to + * migrate to OpenID Connect, which is + * supported by spring-security-oauth2. * @author Robin Bramley, Opsera Ltd */ public class OpenIDAuthenticationProviderTests { + // ~ Static fields/initializers // ===================================================================================== @@ -60,8 +62,8 @@ public class OpenIDAuthenticationProviderTests { provider.setUserDetailsService(new MockUserDetailsService()); provider.setAuthoritiesMapper(new NullAuthoritiesMapper()); - Authentication preAuth = new OpenIDAuthenticationToken( - OpenIDAuthenticationStatus.CANCELLED, USERNAME, "", null); + Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.CANCELLED, USERNAME, "", + null); assertThat(preAuth.isAuthenticated()).isFalse(); @@ -84,8 +86,7 @@ public class OpenIDAuthenticationProviderTests { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsService()); - Authentication preAuth = new OpenIDAuthenticationToken( - OpenIDAuthenticationStatus.ERROR, USERNAME, "", null); + Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.ERROR, USERNAME, "", null); assertThat(preAuth.isAuthenticated()).isFalse(); @@ -107,11 +108,9 @@ public class OpenIDAuthenticationProviderTests { public void testAuthenticateFailure() { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setAuthenticationUserDetailsService( - new UserDetailsByNameServiceWrapper<>( - new MockUserDetailsService())); + new UserDetailsByNameServiceWrapper<>(new MockUserDetailsService())); - Authentication preAuth = new OpenIDAuthenticationToken( - OpenIDAuthenticationStatus.FAILURE, USERNAME, "", null); + Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE, USERNAME, "", null); assertThat(preAuth.isAuthenticated()).isFalse(); @@ -120,8 +119,7 @@ public class OpenIDAuthenticationProviderTests { fail("Should throw an AuthenticationException"); } catch (BadCredentialsException expected) { - assertThat("Log in failed - identity could not be verified").isEqualTo( - expected.getMessage()); + assertThat("Log in failed - identity could not be verified").isEqualTo(expected.getMessage()); } } @@ -135,8 +133,8 @@ public class OpenIDAuthenticationProviderTests { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsService()); - Authentication preAuth = new OpenIDAuthenticationToken( - OpenIDAuthenticationStatus.SETUP_NEEDED, USERNAME, "", null); + Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SETUP_NEEDED, USERNAME, "", + null); assertThat(preAuth.isAuthenticated()).isFalse(); @@ -145,9 +143,8 @@ public class OpenIDAuthenticationProviderTests { fail("Should throw an AuthenticationException"); } catch (AuthenticationServiceException expected) { - assertThat( - "The server responded setup was needed, which shouldn't happen").isEqualTo( - expected.getMessage()); + assertThat("The server responded setup was needed, which shouldn't happen") + .isEqualTo(expected.getMessage()); } } @@ -161,8 +158,7 @@ public class OpenIDAuthenticationProviderTests { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsService()); - Authentication preAuth = new OpenIDAuthenticationToken( - OpenIDAuthenticationStatus.SUCCESS, USERNAME, "", null); + Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, USERNAME, "", null); assertThat(preAuth.isAuthenticated()).isFalse(); @@ -175,8 +171,7 @@ public class OpenIDAuthenticationProviderTests { assertThat(postAuth.getPrincipal() instanceof UserDetails).isTrue(); assertThat(postAuth.getAuthorities()).isNotNull(); assertThat(postAuth.getAuthorities().size() > 0).isTrue(); - assertThat( - ((OpenIDAuthenticationToken) postAuth).getStatus() == OpenIDAuthenticationStatus.SUCCESS).isTrue(); + assertThat(((OpenIDAuthenticationToken) postAuth).getStatus() == OpenIDAuthenticationStatus.SUCCESS).isTrue(); assertThat(((OpenIDAuthenticationToken) postAuth).getMessage() == null).isTrue(); } @@ -203,8 +198,7 @@ public class OpenIDAuthenticationProviderTests { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsService()); - assertThat( - provider.supports(UsernamePasswordAuthenticationToken.class)).isFalse(); + assertThat(provider.supports(UsernamePasswordAuthenticationToken.class)).isFalse(); } /* @@ -217,8 +211,7 @@ public class OpenIDAuthenticationProviderTests { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsService()); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( - USERNAME, "password"); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(USERNAME, "password"); assertThat(provider.authenticate(token)).isNull(); } @@ -253,10 +246,11 @@ public class OpenIDAuthenticationProviderTests { static class MockUserDetailsService implements UserDetailsService { - public UserDetails loadUserByUsername(String ssoUserId) - throws AuthenticationException { + public UserDetails loadUserByUsername(String ssoUserId) throws AuthenticationException { return new User(ssoUserId, "password", true, true, true, true, AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B")); } + } + } diff --git a/remoting/src/main/java/org/springframework/security/remoting/dns/DnsResolver.java b/remoting/src/main/java/org/springframework/security/remoting/dns/DnsResolver.java index 1bed997ea0..990fdeb6fe 100644 --- a/remoting/src/main/java/org/springframework/security/remoting/dns/DnsResolver.java +++ b/remoting/src/main/java/org/springframework/security/remoting/dns/DnsResolver.java @@ -27,14 +27,12 @@ public interface DnsResolver { /** * Resolves the IP Address (A record) to the specified host name. Throws * DnsEntryNotFoundException if there is no record. - * * @param hostname The hostname for which you need the IP Address * @return IP Address as a String * @throws DnsEntryNotFoundException No record found * @throws DnsLookupException Unknown DNS error */ - String resolveIpAddress(String hostname) throws DnsEntryNotFoundException, - DnsLookupException; + String resolveIpAddress(String hostname) throws DnsEntryNotFoundException, DnsLookupException; /** *

        @@ -56,22 +54,19 @@ public interface DnsResolver { * The method will return the record with highest priority (which means the lowest * number in the DNS record) and if there are more than one records with the same * priority, it will return the one with the highest weight. You will find more - * informatione about DNS service records at Wikipedia. - * + * informatione about DNS service records at + * Wikipedia. * @param serviceType The service type you are searching for, e.g. ldap, kerberos, ... * @param domain The domain, in which you are searching for the service * @return The hostname of the service * @throws DnsEntryNotFoundException No record found * @throws DnsLookupException Unknown DNS error */ - String resolveServiceEntry(String serviceType, String domain) - throws DnsEntryNotFoundException, DnsLookupException; + String resolveServiceEntry(String serviceType, String domain) throws DnsEntryNotFoundException, DnsLookupException; /** * Resolves the host name for the specified service and then the IP Address for this * host in one call. - * * @param serviceType The service type you are searching for, e.g. ldap, kerberos, ... * @param domain The domain, in which you are searching for the service * @return IP Address of the service diff --git a/remoting/src/main/java/org/springframework/security/remoting/dns/JndiDnsResolver.java b/remoting/src/main/java/org/springframework/security/remoting/dns/JndiDnsResolver.java index cc699e15df..ef2c63858c 100644 --- a/remoting/src/main/java/org/springframework/security/remoting/dns/JndiDnsResolver.java +++ b/remoting/src/main/java/org/springframework/security/remoting/dns/JndiDnsResolver.java @@ -46,7 +46,6 @@ public class JndiDnsResolver implements DnsResolver { /** * Allows to inject an own JNDI context factory. - * * @param ctxFactory factory to use, when a DirContext is needed * @see InitialDirContext * @see DirContext @@ -107,12 +106,10 @@ public class JndiDnsResolver implements DnsResolver { // This method is needed, so that we can use only one DirContext for // resolveServiceIpAddress(). - private String resolveServiceEntry(String serviceType, String domain, - DirContext ctx) { + private String resolveServiceEntry(String serviceType, String domain, DirContext ctx) { String result = null; try { - String query = new StringBuilder("_").append(serviceType).append("._tcp.") - .append(domain).toString(); + String query = new StringBuilder("_").append(serviceType).append("._tcp.").append(domain).toString(); Attribute dnsRecord = lookup(query, ctx, "SRV"); // There are maybe more records defined, we will return the one // with the highest priority (lowest number) and the highest weight @@ -120,12 +117,11 @@ public class JndiDnsResolver implements DnsResolver { int highestPriority = -1; int highestWeight = -1; - for (NamingEnumeration recordEnum = dnsRecord.getAll(); recordEnum - .hasMoreElements();) { + for (NamingEnumeration recordEnum = dnsRecord.getAll(); recordEnum.hasMoreElements();) { String[] record = recordEnum.next().toString().split(" "); if (record.length != 4) { - throw new DnsLookupException("Wrong service record for query " + query - + ": [" + Arrays.toString(record) + "]"); + throw new DnsLookupException( + "Wrong service record for query " + query + ": [" + Arrays.toString(record) + "]"); } int priority = Integer.parseInt(record[0]); int weight = Integer.parseInt(record[1]); @@ -143,8 +139,7 @@ public class JndiDnsResolver implements DnsResolver { } } catch (NamingException e) { - throw new DnsLookupException( - "DNS lookup failed for service " + serviceType + " at " + domain, e); + throw new DnsLookupException("DNS lookup failed for service " + serviceType + " at " + domain, e); } // remove the "." at the end @@ -162,8 +157,7 @@ public class JndiDnsResolver implements DnsResolver { } catch (NamingException e) { if (e instanceof NameNotFoundException) { - throw new DnsEntryNotFoundException("DNS entry not found for:" + query, - e); + throw new DnsEntryNotFoundException("DNS entry not found for:" + query, e); } throw new DnsLookupException("DNS lookup failed for: " + query, e); } @@ -173,18 +167,18 @@ public class JndiDnsResolver implements DnsResolver { public DirContext getCtx() { Hashtable env = new Hashtable<>(); - env.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.dns.DnsContextFactory"); + env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory"); env.put(Context.PROVIDER_URL, "dns:"); // This is needed for IBM JDK/JRE InitialDirContext ictx; try { ictx = new InitialDirContext(env); } catch (NamingException e) { - throw new DnsLookupException( - "Cannot create InitialDirContext for DNS lookup", e); + throw new DnsLookupException("Cannot create InitialDirContext for DNS lookup", e); } return ictx; } + } + } diff --git a/remoting/src/main/java/org/springframework/security/remoting/dns/package-info.java b/remoting/src/main/java/org/springframework/security/remoting/dns/package-info.java index 69ba68a47b..92c58d3e1e 100644 --- a/remoting/src/main/java/org/springframework/security/remoting/dns/package-info.java +++ b/remoting/src/main/java/org/springframework/security/remoting/dns/package-info.java @@ -17,4 +17,3 @@ * DNS resolution. */ package org.springframework.security.remoting.dns; - diff --git a/remoting/src/main/java/org/springframework/security/remoting/httpinvoker/AuthenticationSimpleHttpInvokerRequestExecutor.java b/remoting/src/main/java/org/springframework/security/remoting/httpinvoker/AuthenticationSimpleHttpInvokerRequestExecutor.java index 59e61d31b6..d706fa0dad 100644 --- a/remoting/src/main/java/org/springframework/security/remoting/httpinvoker/AuthenticationSimpleHttpInvokerRequestExecutor.java +++ b/remoting/src/main/java/org/springframework/security/remoting/httpinvoker/AuthenticationSimpleHttpInvokerRequestExecutor.java @@ -34,13 +34,12 @@ import org.springframework.security.core.context.SecurityContextHolder; * @author Ben Alex * @author Rob Winch */ -public class AuthenticationSimpleHttpInvokerRequestExecutor extends - SimpleHttpInvokerRequestExecutor { +public class AuthenticationSimpleHttpInvokerRequestExecutor extends SimpleHttpInvokerRequestExecutor { + // ~ Static fields/initializers // ===================================================================================== - private static final Log logger = LogFactory - .getLog(AuthenticationSimpleHttpInvokerRequestExecutor.class); + private static final Log logger = LogFactory.getLog(AuthenticationSimpleHttpInvokerRequestExecutor.class); // ~ Instance fields // ================================================================================================ @@ -53,13 +52,11 @@ public class AuthenticationSimpleHttpInvokerRequestExecutor extends /** * Provided so subclasses can perform additional configuration if required (eg set * additional request headers for non-security related information etc). - * * @param con the HTTP connection to prepare * @param contentLength the length of the content to send * */ - protected void doPrepareConnection(HttpURLConnection con, int contentLength) - throws IOException { + protected void doPrepareConnection(HttpURLConnection con, int contentLength) throws IOException { } /** @@ -73,14 +70,11 @@ public class AuthenticationSimpleHttpInvokerRequestExecutor extends * The SecurityContextHolder is used to obtain the relevant principal and * credentials. *

        - * * @param con the HTTP connection to prepare * @param contentLength the length of the content to send - * * @throws IOException if thrown by HttpURLConnection methods */ - protected void prepareConnection(HttpURLConnection con, int contentLength) - throws IOException { + protected void prepareConnection(HttpURLConnection con, int contentLength) throws IOException { super.prepareConnection(con, contentLength); Authentication auth = SecurityContextHolder.getContext().getAuthentication(); @@ -105,4 +99,5 @@ public class AuthenticationSimpleHttpInvokerRequestExecutor extends doPrepareConnection(con, contentLength); } + } diff --git a/remoting/src/main/java/org/springframework/security/remoting/httpinvoker/package-info.java b/remoting/src/main/java/org/springframework/security/remoting/httpinvoker/package-info.java index fcf9e723b4..5546bef57d 100644 --- a/remoting/src/main/java/org/springframework/security/remoting/httpinvoker/package-info.java +++ b/remoting/src/main/java/org/springframework/security/remoting/httpinvoker/package-info.java @@ -14,9 +14,9 @@ * limitations under the License. */ /** - * Enables use of Spring's HttpInvoker extension points to - * present the principal and credentials located - * in the ContextHolder via BASIC authentication. + * Enables use of Spring's HttpInvoker extension points to present the + * principal and credentials located in the + * ContextHolder via BASIC authentication. *

        * The beans are wired as follows: * @@ -32,4 +32,3 @@ *

        */ package org.springframework.security.remoting.httpinvoker; - diff --git a/remoting/src/main/java/org/springframework/security/remoting/package-info.java b/remoting/src/main/java/org/springframework/security/remoting/package-info.java index 8346f9098a..eb42cf2ed7 100644 --- a/remoting/src/main/java/org/springframework/security/remoting/package-info.java +++ b/remoting/src/main/java/org/springframework/security/remoting/package-info.java @@ -17,4 +17,3 @@ * Remote client related functionality. */ package org.springframework.security.remoting; - diff --git a/remoting/src/main/java/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocation.java b/remoting/src/main/java/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocation.java index dae5befd63..a2d125af3a 100644 --- a/remoting/src/main/java/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocation.java +++ b/remoting/src/main/java/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocation.java @@ -46,13 +46,13 @@ public class ContextPropagatingRemoteInvocation extends RemoteInvocation { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; - private static final Log logger = LogFactory - .getLog(ContextPropagatingRemoteInvocation.class); + private static final Log logger = LogFactory.getLog(ContextPropagatingRemoteInvocation.class); // ~ Instance fields // ================================================================================================ private final String principal; + private final String credentials; // ~ Constructors @@ -61,13 +61,11 @@ public class ContextPropagatingRemoteInvocation extends RemoteInvocation { /** * Constructs the object, storing the principal and credentials extracted from the * client-side security context. - * * @param methodInvocation the method to invoke */ public ContextPropagatingRemoteInvocation(MethodInvocation methodInvocation) { super(methodInvocation); - Authentication currentUser = SecurityContextHolder.getContext() - .getAuthentication(); + Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); if (currentUser != null) { principal = currentUser.getName(); @@ -93,18 +91,16 @@ public class ContextPropagatingRemoteInvocation extends RemoteInvocation { * Invoked on the server-side. *

        * The transmitted principal and credentials will be used to create an unauthenticated - * {@code Authentication} instance for processing by the {@code AuthenticationManager}. - * + * {@code Authentication} instance for processing by the + * {@code AuthenticationManager}. * @param targetObject the target object to apply the invocation to - * * @return the invocation result - * * @throws NoSuchMethodException if the method name could not be resolved * @throws IllegalAccessException if the method could not be accessed * @throws InvocationTargetException if the method invocation resulted in an exception */ - public Object invoke(Object targetObject) throws NoSuchMethodException, - IllegalAccessException, InvocationTargetException { + public Object invoke(Object targetObject) + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (principal != null) { Authentication request = createAuthenticationRequest(principal, credentials); @@ -131,8 +127,8 @@ public class ContextPropagatingRemoteInvocation extends RemoteInvocation { /** * Creates the server-side authentication request object. */ - protected Authentication createAuthenticationRequest(String principal, - String credentials) { + protected Authentication createAuthenticationRequest(String principal, String credentials) { return new UsernamePasswordAuthenticationToken(principal, credentials); } + } diff --git a/remoting/src/main/java/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocationFactory.java b/remoting/src/main/java/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocationFactory.java index 47dc7985ac..e01895feda 100644 --- a/remoting/src/main/java/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocationFactory.java +++ b/remoting/src/main/java/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocationFactory.java @@ -34,10 +34,12 @@ import org.springframework.remoting.support.RemoteInvocationFactory; * @author Ben Alex */ public class ContextPropagatingRemoteInvocationFactory implements RemoteInvocationFactory { + // ~ Methods // ======================================================================================================== public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) { return new ContextPropagatingRemoteInvocation(methodInvocation); } + } diff --git a/remoting/src/main/java/org/springframework/security/remoting/rmi/package-info.java b/remoting/src/main/java/org/springframework/security/remoting/rmi/package-info.java index 605b65ac59..3817405f8f 100644 --- a/remoting/src/main/java/org/springframework/security/remoting/rmi/package-info.java +++ b/remoting/src/main/java/org/springframework/security/remoting/rmi/package-info.java @@ -14,11 +14,11 @@ * limitations under the License. */ /** - * Enables use of Spring's RMI remoting extension points to propagate the SecurityContextHolder (which - * should contain an Authentication request token) from one JVM to the remote JVM. + * Enables use of Spring's RMI remoting extension points to propagate the + * SecurityContextHolder (which should contain an Authentication + * request token) from one JVM to the remote JVM. *

        - * The beans are wired as follows: - *

        + * The beans are wired as follows: 
          * <bean id="test" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
          *   <property name="serviceUrl"><value>rmi://localhost/Test</value></property>
          *   <property name="serviceInterface"><value>test.TargetInterface</value></property>
        @@ -31,4 +31,3 @@
          * 
        */ package org.springframework.security.remoting.rmi; - diff --git a/remoting/src/test/java/org/springframework/security/remoting/dns/JndiDnsResolverTests.java b/remoting/src/test/java/org/springframework/security/remoting/dns/JndiDnsResolverTests.java index 4f2aee1959..497daccdb0 100644 --- a/remoting/src/test/java/org/springframework/security/remoting/dns/JndiDnsResolverTests.java +++ b/remoting/src/test/java/org/springframework/security/remoting/dns/JndiDnsResolverTests.java @@ -30,14 +30,15 @@ import org.junit.Before; import org.junit.Test; /** - * * @author Mike Wiesner * @since 3.0 */ public class JndiDnsResolverTests { private JndiDnsResolver dnsResolver; + private InitialContextFactory contextFactory; + private DirContext context; @Before @@ -53,8 +54,7 @@ public class JndiDnsResolverTests { public void testResolveIpAddress() throws Exception { Attributes records = new BasicAttributes("A", "63.246.7.80"); - when(context.getAttributes("www.springsource.com", new String[] { "A" })) - .thenReturn(records); + when(context.getAttributes("www.springsource.com", new String[] { "A" })).thenReturn(records); String ipAddress = dnsResolver.resolveIpAddress("www.springsource.com"); assertThat(ipAddress).isEqualTo("63.246.7.80"); @@ -62,8 +62,8 @@ public class JndiDnsResolverTests { @Test(expected = DnsEntryNotFoundException.class) public void testResolveIpAddressNotExisting() throws Exception { - when(context.getAttributes(any(String.class), any(String[].class))).thenThrow( - new NameNotFoundException("not found")); + when(context.getAttributes(any(String.class), any(String[].class))) + .thenThrow(new NameNotFoundException("not found")); dnsResolver.resolveIpAddress("notexisting.ansdansdugiuzgguzgioansdiandwq.foo"); } @@ -72,8 +72,7 @@ public class JndiDnsResolverTests { public void testResolveServiceEntry() throws Exception { BasicAttributes records = createSrvRecords(); - when(context.getAttributes("_ldap._tcp.springsource.com", new String[] { "SRV" })) - .thenReturn(records); + when(context.getAttributes("_ldap._tcp.springsource.com", new String[] { "SRV" })).thenReturn(records); String hostname = dnsResolver.resolveServiceEntry("ldap", "springsource.com"); assertThat(hostname).isEqualTo("kdc.springsource.com"); @@ -81,8 +80,8 @@ public class JndiDnsResolverTests { @Test(expected = DnsEntryNotFoundException.class) public void testResolveServiceEntryNotExisting() throws Exception { - when(context.getAttributes(any(String.class), any(String[].class))).thenThrow( - new NameNotFoundException("not found")); + when(context.getAttributes(any(String.class), any(String[].class))) + .thenThrow(new NameNotFoundException("not found")); dnsResolver.resolveServiceEntry("wrong", "secpod.de"); } @@ -91,20 +90,16 @@ public class JndiDnsResolverTests { public void testResolveServiceIpAddress() throws Exception { BasicAttributes srvRecords = createSrvRecords(); BasicAttributes aRecords = new BasicAttributes("A", "63.246.7.80"); - when(context.getAttributes("_ldap._tcp.springsource.com", new String[] { "SRV" })) - .thenReturn(srvRecords); - when(context.getAttributes("kdc.springsource.com", new String[] { "A" })) - .thenReturn(aRecords); + when(context.getAttributes("_ldap._tcp.springsource.com", new String[] { "SRV" })).thenReturn(srvRecords); + when(context.getAttributes("kdc.springsource.com", new String[] { "A" })).thenReturn(aRecords); - String ipAddress = dnsResolver - .resolveServiceIpAddress("ldap", "springsource.com"); + String ipAddress = dnsResolver.resolveServiceIpAddress("ldap", "springsource.com"); assertThat(ipAddress).isEqualTo("63.246.7.80"); } @Test(expected = DnsLookupException.class) public void testUnknowError() throws Exception { - when(context.getAttributes(any(String.class), any(String[].class))).thenThrow( - new NamingException("error")); + when(context.getAttributes(any(String.class), any(String[].class))).thenThrow(new NamingException("error")); dnsResolver.resolveIpAddress(""); } @@ -121,4 +116,5 @@ public class JndiDnsResolverTests { records.put(record); return records; } + } diff --git a/remoting/src/test/java/org/springframework/security/remoting/httpinvoker/AuthenticationSimpleHttpInvokerRequestExecutorTests.java b/remoting/src/test/java/org/springframework/security/remoting/httpinvoker/AuthenticationSimpleHttpInvokerRequestExecutorTests.java index 4bc83c05d5..093f43bac4 100644 --- a/remoting/src/test/java/org/springframework/security/remoting/httpinvoker/AuthenticationSimpleHttpInvokerRequestExecutorTests.java +++ b/remoting/src/test/java/org/springframework/security/remoting/httpinvoker/AuthenticationSimpleHttpInvokerRequestExecutorTests.java @@ -49,8 +49,7 @@ public class AuthenticationSimpleHttpInvokerRequestExecutorTests { @Test public void testNormalOperation() throws Exception { // Setup client-side context - Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken( - "Aladdin", "open sesame"); + Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken("Aladdin", "open sesame"); SecurityContextHolder.getContext().setAuthentication(clientSideAuthentication); // Create a connection and ensure our executor sets its @@ -62,8 +61,7 @@ public class AuthenticationSimpleHttpInvokerRequestExecutorTests { // Check connection properties // See https://tools.ietf.org/html/rfc1945 section 11.1 for example // we are comparing against - assertThat(conn.getRequestProperty("Authorization")).isEqualTo( - "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); + assertThat(conn.getRequestProperty("Authorization")).isEqualTo("Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); } @Test @@ -83,8 +81,8 @@ public class AuthenticationSimpleHttpInvokerRequestExecutorTests { // SEC-1975 @Test public void testNullContextHolderWhenAnonymous() throws Exception { - AnonymousAuthenticationToken anonymous = new AnonymousAuthenticationToken("key", - "principal", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); + AnonymousAuthenticationToken anonymous = new AnonymousAuthenticationToken("key", "principal", + AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")); SecurityContextHolder.getContext().setAuthentication(anonymous); // Create a connection and ensure our executor sets its @@ -127,5 +125,7 @@ public class AuthenticationSimpleHttpInvokerRequestExecutorTests { public boolean usingProxy() { throw new UnsupportedOperationException("mock not implemented"); } + } + } diff --git a/remoting/src/test/java/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocationTests.java b/remoting/src/test/java/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocationTests.java index c5877fd021..580ef9f5fa 100644 --- a/remoting/src/test/java/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocationTests.java +++ b/remoting/src/test/java/org/springframework/security/remoting/rmi/ContextPropagatingRemoteInvocationTests.java @@ -49,8 +49,7 @@ public class ContextPropagatingRemoteInvocationTests { private ContextPropagatingRemoteInvocation getRemoteInvocation() throws Exception { Class clazz = TargetObject.class; Method method = clazz.getMethod("makeLowerCase", new Class[] { String.class }); - MethodInvocation mi = new SimpleMethodInvocation(new TargetObject(), method, - "SOME_STRING"); + MethodInvocation mi = new SimpleMethodInvocation(new TargetObject(), method, "SOME_STRING"); ContextPropagatingRemoteInvocationFactory factory = new ContextPropagatingRemoteInvocationFactory(); @@ -60,8 +59,7 @@ public class ContextPropagatingRemoteInvocationTests { @Test public void testContextIsResetEvenIfExceptionOccurs() throws Exception { // Setup client-side context - Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken( - "rod", "koala"); + Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken("rod", "koala"); SecurityContextHolder.getContext().setAuthentication(clientSideAuthentication); ContextPropagatingRemoteInvocation remoteInvocation = getRemoteInvocation(); @@ -76,16 +74,14 @@ public class ContextPropagatingRemoteInvocationTests { // expected } - assertThat( - SecurityContextHolder.getContext().getAuthentication()).withFailMessage( - "Authentication must be null").isNull(); + assertThat(SecurityContextHolder.getContext().getAuthentication()) + .withFailMessage("Authentication must be null").isNull(); } @Test public void testNormalOperation() throws Exception { // Setup client-side context - Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken( - "rod", "koala"); + Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken("rod", "koala"); SecurityContextHolder.getContext().setAuthentication(clientSideAuthentication); ContextPropagatingRemoteInvocation remoteInvocation = getRemoteInvocation(); @@ -109,19 +105,17 @@ public class ContextPropagatingRemoteInvocationTests { SecurityContextHolder.clearContext(); // unnecessary, but for // explicitness - assertThat(remoteInvocation.invoke(new TargetObject())).isEqualTo( - "some_string Authentication empty"); + assertThat(remoteInvocation.invoke(new TargetObject())).isEqualTo("some_string Authentication empty"); } // SEC-1867 @Test public void testNullCredentials() throws Exception { - Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken( - "rod", null); + Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken("rod", null); SecurityContextHolder.getContext().setAuthentication(clientSideAuthentication); ContextPropagatingRemoteInvocation remoteInvocation = getRemoteInvocation(); - assertThat( - ReflectionTestUtils.getField(remoteInvocation, "credentials")).isNull(); + assertThat(ReflectionTestUtils.getField(remoteInvocation, "credentials")).isNull(); } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadExchange.java b/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadExchange.java index 1979d5e263..4caa557536 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadExchange.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadExchange.java @@ -26,6 +26,7 @@ import org.springframework.util.MimeType; * @since 5.2 */ public interface PayloadExchange { + PayloadExchangeType getType(); Payload getPayload(); @@ -33,4 +34,5 @@ public interface PayloadExchange { MimeType getDataMimeType(); MimeType getMetadataMimeType(); + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadExchangeType.java b/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadExchangeType.java index e31d84b50e..9daa62532c 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadExchangeType.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadExchangeType.java @@ -23,14 +23,16 @@ package org.springframework.security.rsocket.api; * @since 5.2 */ public enum PayloadExchangeType { + /** - * The Setup. Can - * be used to determine if a Payload is part of the connection + * The Setup. Can be + * used to determine if a Payload is part of the connection */ SETUP(false), /** - * A Fire and Forget exchange. + * A Fire and Forget + * exchange. */ FIRE_AND_FORGET(true), @@ -41,9 +43,9 @@ public enum PayloadExchangeType { REQUEST_RESPONSE(true), /** - * A Request Stream - * exchange. This is only represents the request portion. The {@link #PAYLOAD} type - * represents the data that submitted. + * A Request + * Stream exchange. This is only represents the request portion. The + * {@link #PAYLOAD} type represents the data that submitted. */ REQUEST_STREAM(true), @@ -77,4 +79,5 @@ public enum PayloadExchangeType { public boolean isRequest() { return this.isRequest; } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadInterceptor.java b/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadInterceptor.java index 2f6f36c02b..692cfa72cf 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadInterceptor.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadInterceptor.java @@ -19,14 +19,15 @@ package org.springframework.security.rsocket.api; import reactor.core.publisher.Mono; /** - * Contract for interception-style, chained processing of Payloads that may - * be used to implement cross-cutting, application-agnostic requirements such - * as security, timeouts, and others. + * Contract for interception-style, chained processing of Payloads that may be used to + * implement cross-cutting, application-agnostic requirements such as security, timeouts, + * and others. * * @author Rob Winch * @since 5.2 */ public interface PayloadInterceptor { + /** * Process the Web request and (optionally) delegate to the next * {@code PayloadInterceptor} through the given {@link PayloadInterceptorChain}. @@ -35,4 +36,5 @@ public interface PayloadInterceptor { * @return {@code Mono} to indicate when payload processing is complete */ Mono intercept(PayloadExchange exchange, PayloadInterceptorChain chain); + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadInterceptorChain.java b/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadInterceptorChain.java index 30307ffc05..edfe567d75 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadInterceptorChain.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/api/PayloadInterceptorChain.java @@ -19,16 +19,18 @@ package org.springframework.security.rsocket.api; import reactor.core.publisher.Mono; /** - * Contract to allow a {@link PayloadInterceptor} to delegate to the next in the chain. - * * + * Contract to allow a {@link PayloadInterceptor} to delegate to the next in the chain. * + * * @author Rob Winch * @since 5.2 */ public interface PayloadInterceptorChain { + /** * Process the payload exchange. * @param exchange the current server exchange * @return {@code Mono} to indicate when request processing is complete */ Mono next(PayloadExchange exchange); + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/authentication/AnonymousPayloadInterceptor.java b/rsocket/src/main/java/org/springframework/security/rsocket/authentication/AnonymousPayloadInterceptor.java index 69fc5f6015..292ac8a8ca 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/authentication/AnonymousPayloadInterceptor.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/authentication/AnonymousPayloadInterceptor.java @@ -39,7 +39,9 @@ import java.util.List; public class AnonymousPayloadInterceptor implements PayloadInterceptor, Ordered { private String key; + private Object principal; + private List authorities; private int order; @@ -47,7 +49,6 @@ public class AnonymousPayloadInterceptor implements PayloadInterceptor, Ordered /** * Creates a filter with a principal named "anonymousUser" and the single authority * "ROLE_ANONYMOUS". - * * @param key the key to identify tokens created by this filter */ public AnonymousPayloadInterceptor(String key) { @@ -55,12 +56,11 @@ public class AnonymousPayloadInterceptor implements PayloadInterceptor, Ordered } /** - * @param key key the key to identify tokens created by this filter - * @param principal the principal which will be used to represent anonymous users + * @param key key the key to identify tokens created by this filter + * @param principal the principal which will be used to represent anonymous users * @param authorities the authority list for anonymous users */ - public AnonymousPayloadInterceptor(String key, Object principal, - List authorities) { + public AnonymousPayloadInterceptor(String key, Object principal, List authorities) { Assert.hasLength(key, "key cannot be null or empty"); Assert.notNull(principal, "Anonymous authentication principal must be set"); Assert.notNull(authorities, "Anonymous authorities must be set"); @@ -80,14 +80,13 @@ public class AnonymousPayloadInterceptor implements PayloadInterceptor, Ordered @Override public Mono intercept(PayloadExchange exchange, PayloadInterceptorChain chain) { - return ReactiveSecurityContextHolder.getContext() - .switchIfEmpty(Mono.defer(() -> { - AnonymousAuthenticationToken authentication = new AnonymousAuthenticationToken( - this.key, this.principal, this.authorities); - return chain.next(exchange) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) - .then(Mono.empty()); - })) - .flatMap(securityContext -> chain.next(exchange)); + return ReactiveSecurityContextHolder.getContext().switchIfEmpty(Mono.defer(() -> { + AnonymousAuthenticationToken authentication = new AnonymousAuthenticationToken(this.key, this.principal, + this.authorities); + return chain.next(exchange) + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) + .then(Mono.empty()); + })).flatMap(securityContext -> chain.next(exchange)); } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadExchangeConverter.java b/rsocket/src/main/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadExchangeConverter.java index 9b7e1ddae0..fcd709b65b 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadExchangeConverter.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadExchangeConverter.java @@ -36,29 +36,32 @@ import java.nio.charset.StandardCharsets; import java.util.Map; /** - * Converts from the {@link PayloadExchange} for - * Authentication Extension. - * For - * Simple - * a {@link UsernamePasswordAuthenticationToken} is returned. For - * Bearer + * Converts from the {@link PayloadExchange} for Authentication + * Extension. For Simple + * a {@link UsernamePasswordAuthenticationToken} is returned. For Bearer * a {@link BearerTokenAuthenticationToken} is returned. * * @author Rob Winch * @since 5.3 */ public class AuthenticationPayloadExchangeConverter implements PayloadExchangeAuthenticationConverter { - private static final MimeType COMPOSITE_METADATA_MIME_TYPE = MimeTypeUtils.parseMimeType( - WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); - private static final MimeType AUTHENTICATION_MIME_TYPE = MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString()); + private static final MimeType COMPOSITE_METADATA_MIME_TYPE = MimeTypeUtils + .parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); + + private static final MimeType AUTHENTICATION_MIME_TYPE = MimeTypeUtils + .parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString()); private MetadataExtractor metadataExtractor = createDefaultExtractor(); @Override public Mono convert(PayloadExchange exchange) { - return Mono.fromCallable(() -> this.metadataExtractor - .extract(exchange.getPayload(), this.COMPOSITE_METADATA_MIME_TYPE)) + return Mono + .fromCallable( + () -> this.metadataExtractor.extract(exchange.getPayload(), this.COMPOSITE_METADATA_MIME_TYPE)) .flatMap(metadata -> Mono.justOrEmpty(authentication(metadata))); } @@ -74,7 +77,8 @@ public class AuthenticationPayloadExchangeConverter implements PayloadExchangeAu WellKnownAuthType wellKnownAuthType = AuthMetadataCodec.readWellKnownAuthType(rawAuthentication); if (WellKnownAuthType.SIMPLE.equals(wellKnownAuthType)) { return simple(rawAuthentication); - } else if (WellKnownAuthType.BEARER.equals(wellKnownAuthType)) { + } + else if (WellKnownAuthType.BEARER.equals(wellKnownAuthType)) { return bearer(rawAuthentication); } throw new IllegalArgumentException("Unknown Mime Type " + wellKnownAuthType); @@ -99,4 +103,5 @@ public class AuthenticationPayloadExchangeConverter implements PayloadExchangeAu result.metadataToExtract(AUTHENTICATION_MIME_TYPE, byte[].class, "authentication"); return result; } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadInterceptor.java b/rsocket/src/main/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadInterceptor.java index 2765f1e7b7..0ec051a213 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadInterceptor.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadInterceptor.java @@ -40,8 +40,7 @@ public class AuthenticationPayloadInterceptor implements PayloadInterceptor, Ord private int order; - private PayloadExchangeAuthenticationConverter authenticationConverter = - new BasicAuthenticationPayloadExchangeConverter(); + private PayloadExchangeAuthenticationConverter authenticationConverter = new BasicAuthenticationPayloadExchangeConverter(); /** * Creates a new instance @@ -65,22 +64,19 @@ public class AuthenticationPayloadInterceptor implements PayloadInterceptor, Ord * Sets the convert to be used * @param authenticationConverter */ - public void setAuthenticationConverter( - PayloadExchangeAuthenticationConverter authenticationConverter) { + public void setAuthenticationConverter(PayloadExchangeAuthenticationConverter authenticationConverter) { Assert.notNull(authenticationConverter, "authenticationConverter cannot be null"); this.authenticationConverter = authenticationConverter; } public Mono intercept(PayloadExchange exchange, PayloadInterceptorChain chain) { - return this.authenticationConverter.convert(exchange) - .switchIfEmpty(chain.next(exchange).then(Mono.empty())) - .flatMap(a -> this.authenticationManager.authenticate(a)) - .flatMap(a -> onAuthenticationSuccess(chain.next(exchange), a)); + return this.authenticationConverter.convert(exchange).switchIfEmpty(chain.next(exchange).then(Mono.empty())) + .flatMap(a -> this.authenticationManager.authenticate(a)) + .flatMap(a -> onAuthenticationSuccess(chain.next(exchange), a)); } private Mono onAuthenticationSuccess(Mono payload, Authentication authentication) { - return payload - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)); + return payload.subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)); } } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/authentication/BasicAuthenticationPayloadExchangeConverter.java b/rsocket/src/main/java/org/springframework/security/rsocket/authentication/BasicAuthenticationPayloadExchangeConverter.java index dac42d0ba4..eefb071a03 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/authentication/BasicAuthenticationPayloadExchangeConverter.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/authentication/BasicAuthenticationPayloadExchangeConverter.java @@ -38,23 +38,26 @@ import reactor.core.publisher.Mono; */ public class BasicAuthenticationPayloadExchangeConverter implements PayloadExchangeAuthenticationConverter { - private MimeType metadataMimetype = MimeTypeUtils.parseMimeType( - WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); + private MimeType metadataMimetype = MimeTypeUtils + .parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); private MetadataExtractor metadataExtractor = createDefaultExtractor(); @Override public Mono convert(PayloadExchange exchange) { - return Mono.fromCallable(() -> this.metadataExtractor - .extract(exchange.getPayload(), this.metadataMimetype)) - .flatMap(metadata -> Mono.justOrEmpty(metadata.get(UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE.toString()))) + return Mono.fromCallable(() -> this.metadataExtractor.extract(exchange.getPayload(), this.metadataMimetype)) + .flatMap(metadata -> Mono + .justOrEmpty(metadata.get(UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE.toString()))) .cast(UsernamePasswordMetadata.class) - .map(credentials -> new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword())); + .map(credentials -> new UsernamePasswordAuthenticationToken(credentials.getUsername(), + credentials.getPassword())); } private static MetadataExtractor createDefaultExtractor() { DefaultMetadataExtractor result = new DefaultMetadataExtractor(new BasicAuthenticationDecoder()); - result.metadataToExtract(UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE, UsernamePasswordMetadata.class, (String) null); + result.metadataToExtract(UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE, + UsernamePasswordMetadata.class, (String) null); return result; } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/authentication/BearerPayloadExchangeConverter.java b/rsocket/src/main/java/org/springframework/security/rsocket/authentication/BearerPayloadExchangeConverter.java index 9b1d92a58d..de0ffe5bc8 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/authentication/BearerPayloadExchangeConverter.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/authentication/BearerPayloadExchangeConverter.java @@ -27,16 +27,16 @@ import reactor.core.publisher.Mono; import java.nio.charset.StandardCharsets; /** - * Converts from the {@link PayloadExchange} to a - * {@link BearerTokenAuthenticationToken} by extracting - * {@link BearerTokenMetadata#BEARER_AUTHENTICATION_MIME_TYPE} from the metadata. - * @author Rob Winch + * Converts from the {@link PayloadExchange} to a {@link BearerTokenAuthenticationToken} + * by extracting {@link BearerTokenMetadata#BEARER_AUTHENTICATION_MIME_TYPE} from the + * metadata. + * + * @author Rob Winch * @since 5.2 */ public class BearerPayloadExchangeConverter implements PayloadExchangeAuthenticationConverter { - private static final String BEARER_MIME_TYPE_VALUE = - BearerTokenMetadata.BEARER_AUTHENTICATION_MIME_TYPE.toString(); + private static final String BEARER_MIME_TYPE_VALUE = BearerTokenMetadata.BEARER_AUTHENTICATION_MIME_TYPE.toString(); @Override public Mono convert(PayloadExchange exchange) { @@ -51,4 +51,5 @@ public class BearerPayloadExchangeConverter implements PayloadExchangeAuthentica } return Mono.empty(); } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/authentication/PayloadExchangeAuthenticationConverter.java b/rsocket/src/main/java/org/springframework/security/rsocket/authentication/PayloadExchangeAuthenticationConverter.java index dbb247246e..25123f7aca 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/authentication/PayloadExchangeAuthenticationConverter.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/authentication/PayloadExchangeAuthenticationConverter.java @@ -22,9 +22,12 @@ import reactor.core.publisher.Mono; /** * Converts from a {@link PayloadExchange} to an {@link Authentication} + * * @author Rob Winch * @since 5.2 */ public interface PayloadExchangeAuthenticationConverter { + Mono convert(PayloadExchange exchange); + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/authorization/AuthorizationPayloadInterceptor.java b/rsocket/src/main/java/org/springframework/security/rsocket/authorization/AuthorizationPayloadInterceptor.java index c439f98a88..3f323f8b69 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/authorization/AuthorizationPayloadInterceptor.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/authorization/AuthorizationPayloadInterceptor.java @@ -34,12 +34,12 @@ import org.springframework.security.rsocket.api.PayloadInterceptor; * @since 5.2 */ public class AuthorizationPayloadInterceptor implements PayloadInterceptor, Ordered { + private final ReactiveAuthorizationManager authorizationManager; private int order; - public AuthorizationPayloadInterceptor( - ReactiveAuthorizationManager authorizationManager) { + public AuthorizationPayloadInterceptor(ReactiveAuthorizationManager authorizationManager) { Assert.notNull(authorizationManager, "authorizationManager cannot be null"); this.authorizationManager = authorizationManager; } @@ -55,11 +55,12 @@ public class AuthorizationPayloadInterceptor implements PayloadInterceptor, Orde @Override public Mono intercept(PayloadExchange exchange, PayloadInterceptorChain chain) { - return ReactiveSecurityContextHolder.getContext() - .filter(c -> c.getAuthentication() != null) + return ReactiveSecurityContextHolder.getContext().filter(c -> c.getAuthentication() != null) .map(SecurityContext::getAuthentication) - .switchIfEmpty(Mono.error(() -> new AuthenticationCredentialsNotFoundException("An Authentication (possibly AnonymousAuthenticationToken) is required."))) + .switchIfEmpty(Mono.error(() -> new AuthenticationCredentialsNotFoundException( + "An Authentication (possibly AnonymousAuthenticationToken) is required."))) .as(authentication -> this.authorizationManager.verify(authentication, exchange)) .then(chain.next(exchange)); } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/authorization/PayloadExchangeMatcherReactiveAuthorizationManager.java b/rsocket/src/main/java/org/springframework/security/rsocket/authorization/PayloadExchangeMatcherReactiveAuthorizationManager.java index 0382491137..604efe22d5 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/authorization/PayloadExchangeMatcherReactiveAuthorizationManager.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/authorization/PayloadExchangeMatcherReactiveAuthorizationManager.java @@ -32,15 +32,18 @@ import java.util.List; /** * Maps a @{code List} of {@link PayloadExchangeMatcher} instances to - * @{code ReactiveAuthorizationManager} instances. * + * @{code ReactiveAuthorizationManager} instances. * @author Rob Winch * @since 5.2 */ -public class PayloadExchangeMatcherReactiveAuthorizationManager implements ReactiveAuthorizationManager { +public class PayloadExchangeMatcherReactiveAuthorizationManager + implements ReactiveAuthorizationManager { + private final List>> mappings; - private PayloadExchangeMatcherReactiveAuthorizationManager(List>> mappings) { + private PayloadExchangeMatcherReactiveAuthorizationManager( + List>> mappings) { Assert.notEmpty(mappings, "mappings cannot be null"); this.mappings = mappings; } @@ -49,14 +52,10 @@ public class PayloadExchangeMatcherReactiveAuthorizationManager implements React public Mono check(Mono authentication, PayloadExchange exchange) { return Flux.fromIterable(this.mappings) .concatMap(mapping -> mapping.getMatcher().matches(exchange) - .filter(PayloadExchangeMatcher.MatchResult::isMatch) - .map(r -> r.getVariables()) - .flatMap(variables -> mapping.getEntry() - .check(authentication, new PayloadExchangeAuthorizationContext(exchange, variables)) - ) - ) - .next() - .switchIfEmpty(Mono.fromCallable(() -> new AuthorizationDecision(false))); + .filter(PayloadExchangeMatcher.MatchResult::isMatch).map(r -> r.getVariables()) + .flatMap(variables -> mapping.getEntry().check(authentication, + new PayloadExchangeAuthorizationContext(exchange, variables)))) + .next().switchIfEmpty(Mono.fromCallable(() -> new AuthorizationDecision(false))); } public static PayloadExchangeMatcherReactiveAuthorizationManager.Builder builder() { @@ -64,6 +63,7 @@ public class PayloadExchangeMatcherReactiveAuthorizationManager implements React } public static class Builder { + private final List>> mappings = new ArrayList<>(); private Builder() { @@ -78,5 +78,7 @@ public class PayloadExchangeMatcherReactiveAuthorizationManager implements React public PayloadExchangeMatcherReactiveAuthorizationManager build() { return new PayloadExchangeMatcherReactiveAuthorizationManager(this.mappings); } + } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/core/ContextPayloadInterceptorChain.java b/rsocket/src/main/java/org/springframework/security/rsocket/core/ContextPayloadInterceptorChain.java index c92785b7d0..7efcc28239 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/core/ContextPayloadInterceptorChain.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/core/ContextPayloadInterceptorChain.java @@ -26,8 +26,9 @@ import java.util.List; import java.util.ListIterator; /** - * A {@link PayloadInterceptorChain} which exposes the Reactor {@link Context} via a member variable. - * This class is not Thread safe, so a new instance must be created for each Thread. + * A {@link PayloadInterceptorChain} which exposes the Reactor {@link Context} via a + * member variable. This class is not Thread safe, so a new instance must be created for + * each Thread. * * Internally {@code ContextPayloadInterceptorChain} is used to ensure that the Reactor * {@code Context} is captured so it can be transferred to subscribers outside of this @@ -72,13 +73,8 @@ class ContextPayloadInterceptorChain implements PayloadInterceptorChain { } public Mono next(PayloadExchange exchange) { - return Mono.defer(() -> - shouldIntercept() ? - this.currentInterceptor.intercept(exchange, this.next) : - Mono.subscriberContext() - .doOnNext(c -> this.context = c) - .then() - ); + return Mono.defer(() -> shouldIntercept() ? this.currentInterceptor.intercept(exchange, this.next) + : Mono.subscriberContext().doOnNext(c -> this.context = c).then()); } Context getContext() { @@ -96,4 +92,5 @@ class ContextPayloadInterceptorChain implements PayloadInterceptorChain { public String toString() { return getClass().getSimpleName() + "[currentInterceptor=" + this.currentInterceptor + "]"; } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/core/DefaultPayloadExchange.java b/rsocket/src/main/java/org/springframework/security/rsocket/core/DefaultPayloadExchange.java index e49ccb5154..7deba38628 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/core/DefaultPayloadExchange.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/core/DefaultPayloadExchange.java @@ -69,4 +69,5 @@ public class DefaultPayloadExchange implements PayloadExchange { public MimeType getDataMimeType() { return this.dataMimeType; } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/core/PayloadInterceptorRSocket.java b/rsocket/src/main/java/org/springframework/security/rsocket/core/PayloadInterceptorRSocket.java index b1c7271ed9..ac122c3208 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/core/PayloadInterceptorRSocket.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/core/PayloadInterceptorRSocket.java @@ -31,10 +31,12 @@ import java.util.List; /** * Combines the {@link PayloadInterceptor} with an {@link RSocketProxy} + * * @author Rob Winch * @since 5.2 */ class PayloadInterceptorRSocket extends RSocketProxy { + private final List interceptors; private final MimeType metadataMimeType; @@ -43,14 +45,12 @@ class PayloadInterceptorRSocket extends RSocketProxy { private final Context context; - PayloadInterceptorRSocket(RSocket delegate, - List interceptors, MimeType metadataMimeType, + PayloadInterceptorRSocket(RSocket delegate, List interceptors, MimeType metadataMimeType, MimeType dataMimeType) { this(delegate, interceptors, metadataMimeType, dataMimeType, Context.empty()); } - PayloadInterceptorRSocket(RSocket delegate, - List interceptors, MimeType metadataMimeType, + PayloadInterceptorRSocket(RSocket delegate, List interceptors, MimeType metadataMimeType, MimeType dataMimeType, Context context) { super(delegate); this.metadataMimeType = metadataMimeType; @@ -71,71 +71,52 @@ class PayloadInterceptorRSocket extends RSocketProxy { @Override public Mono fireAndForget(Payload payload) { return intercept(PayloadExchangeType.FIRE_AND_FORGET, payload) - .flatMap(context -> - this.source.fireAndForget(payload) - .subscriberContext(context) - ); + .flatMap(context -> this.source.fireAndForget(payload).subscriberContext(context)); } @Override public Mono requestResponse(Payload payload) { return intercept(PayloadExchangeType.REQUEST_RESPONSE, payload) - .flatMap(context -> - this.source.requestResponse(payload) - .subscriberContext(context) - ); + .flatMap(context -> this.source.requestResponse(payload).subscriberContext(context)); } @Override public Flux requestStream(Payload payload) { return intercept(PayloadExchangeType.REQUEST_STREAM, payload) - .flatMapMany(context -> - this.source.requestStream(payload) - .subscriberContext(context) - ); + .flatMapMany(context -> this.source.requestStream(payload).subscriberContext(context)); } @Override public Flux requestChannel(Publisher payloads) { - return Flux.from(payloads) - .switchOnFirst((signal, innerFlux) -> { - Payload firstPayload = signal.get(); - return intercept(PayloadExchangeType.REQUEST_CHANNEL, firstPayload) - .flatMapMany(context -> - innerFlux - .skip(1) - .flatMap(p -> intercept(PayloadExchangeType.PAYLOAD, p).thenReturn(p)) + return Flux.from(payloads).switchOnFirst((signal, innerFlux) -> { + Payload firstPayload = signal.get(); + return intercept(PayloadExchangeType.REQUEST_CHANNEL, firstPayload).flatMapMany( + context -> innerFlux.skip(1).flatMap(p -> intercept(PayloadExchangeType.PAYLOAD, p).thenReturn(p)) .transform(securedPayloads -> Flux.concat(Flux.just(firstPayload), securedPayloads)) .transform(securedPayloads -> this.source.requestChannel(securedPayloads)) - .subscriberContext(context) - ); - }); + .subscriberContext(context)); + }); } @Override public Mono metadataPush(Payload payload) { return intercept(PayloadExchangeType.METADATA_PUSH, payload) - .flatMap(c -> this.source - .metadataPush(payload) - .subscriberContext(c) - ); + .flatMap(c -> this.source.metadataPush(payload).subscriberContext(c)); } private Mono intercept(PayloadExchangeType type, Payload payload) { return Mono.defer(() -> { ContextPayloadInterceptorChain chain = new ContextPayloadInterceptorChain(this.interceptors); - DefaultPayloadExchange exchange = new DefaultPayloadExchange(type, payload, - this.metadataMimeType, this.dataMimeType); - return chain.next(exchange) - .then(Mono.fromCallable(() -> chain.getContext())) - .defaultIfEmpty(Context.empty()) - .subscriberContext(this.context); + DefaultPayloadExchange exchange = new DefaultPayloadExchange(type, payload, this.metadataMimeType, + this.dataMimeType); + return chain.next(exchange).then(Mono.fromCallable(() -> chain.getContext())) + .defaultIfEmpty(Context.empty()).subscriberContext(this.context); }); } @Override public String toString() { - return getClass().getSimpleName() + "[source=" + this.source + ",interceptors=" - + this.interceptors + "]"; + return getClass().getSimpleName() + "[source=" + this.source + ",interceptors=" + this.interceptors + "]"; } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/core/PayloadSocketAcceptor.java b/rsocket/src/main/java/org/springframework/security/rsocket/core/PayloadSocketAcceptor.java index a5a849096b..fb07b9c1a5 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/core/PayloadSocketAcceptor.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/core/PayloadSocketAcceptor.java @@ -38,6 +38,7 @@ import java.util.List; * @since 5.2 */ class PayloadSocketAcceptor implements SocketAcceptor { + private final SocketAcceptor delegate; private final List interceptors; @@ -45,8 +46,8 @@ class PayloadSocketAcceptor implements SocketAcceptor { @Nullable private MimeType defaultDataMimeType; - private MimeType defaultMetadataMimeType = - MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); + private MimeType defaultMetadataMimeType = MimeTypeUtils + .parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); PayloadSocketAcceptor(SocketAcceptor delegate, List interceptors) { Assert.notNull(delegate, "delegate cannot be null"); @@ -70,10 +71,11 @@ class PayloadSocketAcceptor implements SocketAcceptor { // FIXME do we want to make the sendingSocket available in the PayloadExchange return intercept(setup, dataMimeType, metadataMimeType) - .flatMap(ctx -> this.delegate.accept(setup, sendingSocket) - .map(acceptingSocket -> new PayloadInterceptorRSocket(acceptingSocket, this.interceptors, metadataMimeType, dataMimeType, ctx)) - .subscriberContext(ctx) - ); + .flatMap( + ctx -> this.delegate.accept(setup, sendingSocket) + .map(acceptingSocket -> new PayloadInterceptorRSocket(acceptingSocket, + this.interceptors, metadataMimeType, dataMimeType, ctx)) + .subscriberContext(ctx)); } private Mono intercept(Payload payload, MimeType dataMimeType, MimeType metadataMimeType) { @@ -81,8 +83,7 @@ class PayloadSocketAcceptor implements SocketAcceptor { ContextPayloadInterceptorChain chain = new ContextPayloadInterceptorChain(this.interceptors); DefaultPayloadExchange exchange = new DefaultPayloadExchange(PayloadExchangeType.SETUP, payload, metadataMimeType, dataMimeType); - return chain.next(exchange) - .then(Mono.fromCallable(() -> chain.getContext())) + return chain.next(exchange).then(Mono.fromCallable(() -> chain.getContext())) .defaultIfEmpty(Context.empty()); }); } @@ -99,4 +100,5 @@ class PayloadSocketAcceptor implements SocketAcceptor { Assert.notNull(defaultMetadataMimeType, "defaultMetadataMimeType cannot be null"); this.defaultMetadataMimeType = defaultMetadataMimeType; } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/core/PayloadSocketAcceptorInterceptor.java b/rsocket/src/main/java/org/springframework/security/rsocket/core/PayloadSocketAcceptorInterceptor.java index 52cba75c45..02402a6fe8 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/core/PayloadSocketAcceptorInterceptor.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/core/PayloadSocketAcceptorInterceptor.java @@ -40,8 +40,8 @@ public class PayloadSocketAcceptorInterceptor implements SocketAcceptorIntercept @Nullable private MimeType defaultDataMimeType; - private MimeType defaultMetadataMimeType = - MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); + private MimeType defaultMetadataMimeType = MimeTypeUtils + .parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); public PayloadSocketAcceptorInterceptor(List interceptors) { this.interceptors = interceptors; @@ -49,8 +49,7 @@ public class PayloadSocketAcceptorInterceptor implements SocketAcceptorIntercept @Override public SocketAcceptor apply(SocketAcceptor socketAcceptor) { - PayloadSocketAcceptor acceptor = new PayloadSocketAcceptor( - socketAcceptor, this.interceptors); + PayloadSocketAcceptor acceptor = new PayloadSocketAcceptor(socketAcceptor, this.interceptors); acceptor.setDefaultDataMimeType(this.defaultDataMimeType); acceptor.setDefaultMetadataMimeType(this.defaultMetadataMimeType); return acceptor; @@ -64,4 +63,5 @@ public class PayloadSocketAcceptorInterceptor implements SocketAcceptorIntercept Assert.notNull(defaultMetadataMimeType, "defaultMetadataMimeType cannot be null"); this.defaultMetadataMimeType = defaultMetadataMimeType; } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/core/SecuritySocketAcceptorInterceptor.java b/rsocket/src/main/java/org/springframework/security/rsocket/core/SecuritySocketAcceptorInterceptor.java index f8f9cbaf81..73470acc74 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/core/SecuritySocketAcceptorInterceptor.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/core/SecuritySocketAcceptorInterceptor.java @@ -21,13 +21,15 @@ import io.rsocket.plugins.SocketAcceptorInterceptor; import org.springframework.util.Assert; /** - * A SocketAcceptorInterceptor that applies Security through a delegate {@link SocketAcceptorInterceptor}. This allows - * security to be applied lazily to an application. + * A SocketAcceptorInterceptor that applies Security through a delegate + * {@link SocketAcceptorInterceptor}. This allows security to be applied lazily to an + * application. * * @author Rob Winch * @since 5.2 */ public class SecuritySocketAcceptorInterceptor implements SocketAcceptorInterceptor { + private final SocketAcceptorInterceptor acceptorInterceptor; public SecuritySocketAcceptorInterceptor(SocketAcceptorInterceptor acceptorInterceptor) { @@ -39,4 +41,5 @@ public class SecuritySocketAcceptorInterceptor implements SocketAcceptorIntercep public SocketAcceptor apply(SocketAcceptor socketAcceptor) { return this.acceptorInterceptor.apply(socketAcceptor); } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BasicAuthenticationDecoder.java b/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BasicAuthenticationDecoder.java index 6b8a45fe41..ca673d6be9 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BasicAuthenticationDecoder.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BasicAuthenticationDecoder.java @@ -31,48 +31,47 @@ import java.util.Map; * * @author Rob Winch * @since 5.2 - * @deprecated Basic Authentication did not evolve into a standard. Use Simple Authentication instead. + * @deprecated Basic Authentication did not evolve into a standard. Use Simple + * Authentication instead. */ @Deprecated public class BasicAuthenticationDecoder extends AbstractDecoder { + public BasicAuthenticationDecoder() { super(UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE); } @Override - public Flux decode(Publisher input, - ResolvableType elementType, MimeType mimeType, Map hints) { - return Flux.from(input) - .map(DataBuffer::asByteBuffer) - .map(byteBuffer -> { - byte[] sizeBytes = new byte[4]; - byteBuffer.get(sizeBytes); + public Flux decode(Publisher input, ResolvableType elementType, + MimeType mimeType, Map hints) { + return Flux.from(input).map(DataBuffer::asByteBuffer).map(byteBuffer -> { + byte[] sizeBytes = new byte[4]; + byteBuffer.get(sizeBytes); - int usernameSize = 4; - byte[] usernameBytes = new byte[usernameSize]; - byteBuffer.get(usernameBytes); - byte[] passwordBytes = new byte[byteBuffer.remaining()]; - byteBuffer.get(passwordBytes); - String username = new String(usernameBytes); - String password = new String(passwordBytes); - return new UsernamePasswordMetadata(username, password); - }); + int usernameSize = 4; + byte[] usernameBytes = new byte[usernameSize]; + byteBuffer.get(usernameBytes); + byte[] passwordBytes = new byte[byteBuffer.remaining()]; + byteBuffer.get(passwordBytes); + String username = new String(usernameBytes); + String password = new String(passwordBytes); + return new UsernamePasswordMetadata(username, password); + }); } @Override - public Mono decodeToMono(Publisher input, - ResolvableType elementType, MimeType mimeType, Map hints) { - return Mono.from(input) - .map(DataBuffer::asByteBuffer) - .map(byteBuffer -> { - int usernameSize = byteBuffer.getInt(); - byte[] usernameBytes = new byte[usernameSize]; - byteBuffer.get(usernameBytes); - byte[] passwordBytes = new byte[byteBuffer.remaining()]; - byteBuffer.get(passwordBytes); - String username = new String(usernameBytes); - String password = new String(passwordBytes); - return new UsernamePasswordMetadata(username, password); - }); + public Mono decodeToMono(Publisher input, ResolvableType elementType, + MimeType mimeType, Map hints) { + return Mono.from(input).map(DataBuffer::asByteBuffer).map(byteBuffer -> { + int usernameSize = byteBuffer.getInt(); + byte[] usernameBytes = new byte[usernameSize]; + byteBuffer.get(usernameBytes); + byte[] passwordBytes = new byte[byteBuffer.remaining()]; + byteBuffer.get(passwordBytes); + String username = new String(usernameBytes); + String password = new String(passwordBytes); + return new UsernamePasswordMetadata(username, password); + }); } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BasicAuthenticationEncoder.java b/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BasicAuthenticationEncoder.java index 75e3f909ac..596e4d11d0 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BasicAuthenticationEncoder.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BasicAuthenticationEncoder.java @@ -34,29 +34,26 @@ import java.util.Map; * * @author Rob Winch * @since 5.2 - * @deprecated Basic Authentication did not evolve into a standard. use {@link SimpleAuthenticationEncoder} + * @deprecated Basic Authentication did not evolve into a standard. use + * {@link SimpleAuthenticationEncoder} */ @Deprecated -public class BasicAuthenticationEncoder extends - AbstractEncoder { +public class BasicAuthenticationEncoder extends AbstractEncoder { public BasicAuthenticationEncoder() { super(UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE); } @Override - public Flux encode( - Publisher inputStream, - DataBufferFactory bufferFactory, ResolvableType elementType, - MimeType mimeType, Map hints) { - return Flux.from(inputStream).map(credentials -> - encodeValue(credentials, bufferFactory, elementType, mimeType, hints)); + public Flux encode(Publisher inputStream, + DataBufferFactory bufferFactory, ResolvableType elementType, MimeType mimeType, Map hints) { + return Flux.from(inputStream) + .map(credentials -> encodeValue(credentials, bufferFactory, elementType, mimeType, hints)); } @Override - public DataBuffer encodeValue(UsernamePasswordMetadata credentials, - DataBufferFactory bufferFactory, ResolvableType valueType, MimeType mimeType, - Map hints) { + public DataBuffer encodeValue(UsernamePasswordMetadata credentials, DataBufferFactory bufferFactory, + ResolvableType valueType, MimeType mimeType, Map hints) { String username = credentials.getUsername(); String password = credentials.getPassword(); byte[] usernameBytes = username.getBytes(StandardCharsets.UTF_8); @@ -69,10 +66,12 @@ public class BasicAuthenticationEncoder extends metadata.write(password.getBytes(StandardCharsets.UTF_8)); release = false; return metadata; - } finally { + } + finally { if (release) { DataBufferUtils.release(metadata); } } } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BearerTokenAuthenticationEncoder.java b/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BearerTokenAuthenticationEncoder.java index ead8f960fa..2f5f51c451 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BearerTokenAuthenticationEncoder.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BearerTokenAuthenticationEncoder.java @@ -32,15 +32,17 @@ import reactor.core.publisher.Flux; import java.util.Map; /** - * Encodes Bearer Authentication. + * Encodes Bearer + * Authentication. * * @author Rob Winch * @since 5.3 */ -public class BearerTokenAuthenticationEncoder extends - AbstractEncoder { +public class BearerTokenAuthenticationEncoder extends AbstractEncoder { - private static final MimeType AUTHENTICATION_MIME_TYPE = MimeTypeUtils.parseMimeType("message/x.rsocket.authentication.v0"); + private static final MimeType AUTHENTICATION_MIME_TYPE = MimeTypeUtils + .parseMimeType("message/x.rsocket.authentication.v0"); private NettyDataBufferFactory defaultBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT); @@ -49,23 +51,19 @@ public class BearerTokenAuthenticationEncoder extends } @Override - public Flux encode( - Publisher inputStream, - DataBufferFactory bufferFactory, ResolvableType elementType, - MimeType mimeType, Map hints) { - return Flux.from(inputStream).map(credentials -> - encodeValue(credentials, bufferFactory, elementType, mimeType, hints)); + public Flux encode(Publisher inputStream, + DataBufferFactory bufferFactory, ResolvableType elementType, MimeType mimeType, Map hints) { + return Flux.from(inputStream) + .map(credentials -> encodeValue(credentials, bufferFactory, elementType, mimeType, hints)); } @Override - public DataBuffer encodeValue(BearerTokenMetadata credentials, - DataBufferFactory bufferFactory, ResolvableType valueType, MimeType mimeType, - Map hints) { + public DataBuffer encodeValue(BearerTokenMetadata credentials, DataBufferFactory bufferFactory, + ResolvableType valueType, MimeType mimeType, Map hints) { String token = credentials.getToken(); NettyDataBufferFactory factory = nettyFactory(bufferFactory); ByteBufAllocator allocator = factory.getByteBufAllocator(); - ByteBuf simpleAuthentication = AuthMetadataCodec - .encodeBearerMetadata(allocator, token.toCharArray()); + ByteBuf simpleAuthentication = AuthMetadataCodec.encodeBearerMetadata(allocator, token.toCharArray()); return factory.wrap(simpleAuthentication); } @@ -75,4 +73,5 @@ public class BearerTokenAuthenticationEncoder extends } return this.defaultBufferFactory; } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BearerTokenMetadata.java b/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BearerTokenMetadata.java index 5998b07cdd..364c4e4209 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BearerTokenMetadata.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/metadata/BearerTokenMetadata.java @@ -14,28 +14,30 @@ * limitations under the License. */ - package org.springframework.security.rsocket.metadata; import org.springframework.http.MediaType; import org.springframework.util.MimeType; /** - * Represents a bearer token that has been encoded into a - * {@link Payload#metadata()}. + * Represents a bearer token that has been encoded into a {@link Payload#metadata()}. * * @author Rob Winch * @since 5.2 */ public class BearerTokenMetadata { + /** * Represents a bearer token which is encoded as a String. * * See rsocket/rsocket#272 - * @deprecated Basic did not evolve into the standard. Instead use Simple Authentication MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString()) + * @deprecated Basic did not evolve into the standard. Instead use Simple + * Authentication + * MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString()) */ @Deprecated - public static final MimeType BEARER_AUTHENTICATION_MIME_TYPE = new MediaType("message", "x.rsocket.authentication.bearer.v0"); + public static final MimeType BEARER_AUTHENTICATION_MIME_TYPE = new MediaType("message", + "x.rsocket.authentication.bearer.v0"); private final String token; @@ -46,4 +48,5 @@ public class BearerTokenMetadata { public String getToken() { return this.token; } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/metadata/SimpleAuthenticationEncoder.java b/rsocket/src/main/java/org/springframework/security/rsocket/metadata/SimpleAuthenticationEncoder.java index eb4b0c737e..01f31b172d 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/metadata/SimpleAuthenticationEncoder.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/metadata/SimpleAuthenticationEncoder.java @@ -32,17 +32,17 @@ import reactor.core.publisher.Flux; import java.util.Map; /** - * Encodes - * Simple + * Encodes Simple * Authentication. * * @author Rob Winch * @since 5.3 */ -public class SimpleAuthenticationEncoder extends - AbstractEncoder { +public class SimpleAuthenticationEncoder extends AbstractEncoder { - private static final MimeType AUTHENTICATION_MIME_TYPE = MimeTypeUtils.parseMimeType("message/x.rsocket.authentication.v0"); + private static final MimeType AUTHENTICATION_MIME_TYPE = MimeTypeUtils + .parseMimeType("message/x.rsocket.authentication.v0"); private NettyDataBufferFactory defaultBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT); @@ -51,24 +51,21 @@ public class SimpleAuthenticationEncoder extends } @Override - public Flux encode( - Publisher inputStream, - DataBufferFactory bufferFactory, ResolvableType elementType, - MimeType mimeType, Map hints) { - return Flux.from(inputStream).map(credentials -> - encodeValue(credentials, bufferFactory, elementType, mimeType, hints)); + public Flux encode(Publisher inputStream, + DataBufferFactory bufferFactory, ResolvableType elementType, MimeType mimeType, Map hints) { + return Flux.from(inputStream) + .map(credentials -> encodeValue(credentials, bufferFactory, elementType, mimeType, hints)); } @Override - public DataBuffer encodeValue(UsernamePasswordMetadata credentials, - DataBufferFactory bufferFactory, ResolvableType valueType, MimeType mimeType, - Map hints) { + public DataBuffer encodeValue(UsernamePasswordMetadata credentials, DataBufferFactory bufferFactory, + ResolvableType valueType, MimeType mimeType, Map hints) { String username = credentials.getUsername(); String password = credentials.getPassword(); NettyDataBufferFactory factory = nettyFactory(bufferFactory); ByteBufAllocator allocator = factory.getByteBufAllocator(); - ByteBuf simpleAuthentication = AuthMetadataCodec - .encodeSimpleMetadata(allocator, username.toCharArray(), password.toCharArray()); + ByteBuf simpleAuthentication = AuthMetadataCodec.encodeSimpleMetadata(allocator, username.toCharArray(), + password.toCharArray()); return factory.wrap(simpleAuthentication); } @@ -78,4 +75,5 @@ public class SimpleAuthenticationEncoder extends } return this.defaultBufferFactory; } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/metadata/UsernamePasswordMetadata.java b/rsocket/src/main/java/org/springframework/security/rsocket/metadata/UsernamePasswordMetadata.java index dab4ad6ea5..946e5227a7 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/metadata/UsernamePasswordMetadata.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/metadata/UsernamePasswordMetadata.java @@ -28,15 +28,19 @@ import org.springframework.util.MimeType; * @since 5.2 */ public final class UsernamePasswordMetadata { + /** * Represents a username password which is encoded as * {@code ${username-bytes-length}${username-bytes}${password-bytes}}. * * See rsocket/rsocket#272 - * @deprecated Basic did not evolve into the standard. Instead use Simple Authentication MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString()) + * @deprecated Basic did not evolve into the standard. Instead use Simple + * Authentication + * MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString()) */ @Deprecated - public static final MimeType BASIC_AUTHENTICATION_MIME_TYPE = new MediaType("message", "x.rsocket.authentication.basic.v0"); + public static final MimeType BASIC_AUTHENTICATION_MIME_TYPE = new MediaType("message", + "x.rsocket.authentication.basic.v0"); private final String username; @@ -54,4 +58,5 @@ public final class UsernamePasswordMetadata { public String getPassword() { return this.password; } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeAuthorizationContext.java b/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeAuthorizationContext.java index 7312dbb4d0..4f0882905d 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeAuthorizationContext.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeAuthorizationContext.java @@ -26,7 +26,9 @@ import java.util.Map; * @since 5.2 */ public class PayloadExchangeAuthorizationContext { + private final PayloadExchange exchange; + private final Map variables; public PayloadExchangeAuthorizationContext(PayloadExchange exchange) { @@ -45,4 +47,5 @@ public class PayloadExchangeAuthorizationContext { public Map getVariables() { return Collections.unmodifiableMap(this.variables); } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeMatcher.java b/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeMatcher.java index cf8f00bc98..d1310eb15b 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeMatcher.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeMatcher.java @@ -24,6 +24,7 @@ import java.util.Map; /** * An interface for determining if a {@link PayloadExchangeMatcher} matches. + * * @author Rob Winch * @since 5.2 */ @@ -40,7 +41,9 @@ public interface PayloadExchangeMatcher { * The result of matching */ class MatchResult { + private final boolean match; + private final Map variables; private MatchResult(boolean match, Map variables) { @@ -70,7 +73,8 @@ public interface PayloadExchangeMatcher { /** * - * Creates an instance of {@link MatchResult} that is a match with the specified variables + * Creates an instance of {@link MatchResult} that is a match with the specified + * variables * @param variables * @return */ @@ -85,5 +89,7 @@ public interface PayloadExchangeMatcher { public static Mono notMatch() { return Mono.just(new MatchResult(false, Collections.emptyMap())); } + } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeMatcherEntry.java b/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeMatcherEntry.java index 6f7aa6ae28..2431fc8bf4 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeMatcherEntry.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeMatcherEntry.java @@ -20,7 +20,9 @@ package org.springframework.security.rsocket.util.matcher; * @author Rob Winch */ public class PayloadExchangeMatcherEntry { + private final PayloadExchangeMatcher matcher; + private final T entry; public PayloadExchangeMatcherEntry(PayloadExchangeMatcher matcher, T entry) { @@ -35,4 +37,5 @@ public class PayloadExchangeMatcherEntry { public T getEntry() { return this.entry; } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeMatchers.java b/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeMatchers.java index a6e110ebeb..ac1558fcf4 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeMatchers.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/PayloadExchangeMatchers.java @@ -28,9 +28,8 @@ public abstract class PayloadExchangeMatchers { public static PayloadExchangeMatcher setup() { return new PayloadExchangeMatcher() { public Mono matches(PayloadExchange exchange) { - return PayloadExchangeType.SETUP.equals(exchange.getType()) ? - MatchResult.match() : - MatchResult.notMatch(); + return PayloadExchangeType.SETUP.equals(exchange.getType()) ? MatchResult.match() + : MatchResult.notMatch(); } }; } @@ -38,9 +37,7 @@ public abstract class PayloadExchangeMatchers { public static PayloadExchangeMatcher anyRequest() { return new PayloadExchangeMatcher() { public Mono matches(PayloadExchange exchange) { - return exchange.getType().isRequest() ? - MatchResult.match() : - MatchResult.notMatch(); + return exchange.getType().isRequest() ? MatchResult.match() : MatchResult.notMatch(); } }; } @@ -53,5 +50,7 @@ public abstract class PayloadExchangeMatchers { }; } - private PayloadExchangeMatchers() {} + private PayloadExchangeMatchers() { + } + } diff --git a/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/RoutePayloadExchangeMatcher.java b/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/RoutePayloadExchangeMatcher.java index ce5bf542d7..27d63d7091 100644 --- a/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/RoutePayloadExchangeMatcher.java +++ b/rsocket/src/main/java/org/springframework/security/rsocket/util/matcher/RoutePayloadExchangeMatcher.java @@ -27,7 +27,7 @@ import java.util.Optional; /** * FIXME: Pay attention to the package this goes into. It requires spring-messaging for - * the MetadataExtractor. + * the MetadataExtractor. * * @author Rob Winch * @since 5.2 @@ -40,8 +40,7 @@ public class RoutePayloadExchangeMatcher implements PayloadExchangeMatcher { private final RouteMatcher routeMatcher; - public RoutePayloadExchangeMatcher(MetadataExtractor metadataExtractor, - RouteMatcher routeMatcher, String pattern) { + public RoutePayloadExchangeMatcher(MetadataExtractor metadataExtractor, RouteMatcher routeMatcher, String pattern) { Assert.notNull(pattern, "pattern cannot be null"); this.metadataExtractor = metadataExtractor; this.routeMatcher = routeMatcher; @@ -50,12 +49,12 @@ public class RoutePayloadExchangeMatcher implements PayloadExchangeMatcher { @Override public Mono matches(PayloadExchange exchange) { - Map metadata = this.metadataExtractor - .extract(exchange.getPayload(), exchange.getMetadataMimeType()); + Map metadata = this.metadataExtractor.extract(exchange.getPayload(), + exchange.getMetadataMimeType()); return Optional.ofNullable((String) metadata.get(MetadataExtractor.ROUTE_KEY)) - .map(routeValue -> this.routeMatcher.parseRoute(routeValue)) - .map(route -> this.routeMatcher.matchAndExtract(this.pattern, route)) - .map(v -> MatchResult.match(v)) - .orElse(MatchResult.notMatch()); + .map(routeValue -> this.routeMatcher.parseRoute(routeValue)) + .map(route -> this.routeMatcher.matchAndExtract(this.pattern, route)).map(v -> MatchResult.match(v)) + .orElse(MatchResult.notMatch()); } + } diff --git a/rsocket/src/test/java/org/springframework/security/rsocket/authentication/AnonymousPayloadInterceptorTests.java b/rsocket/src/test/java/org/springframework/security/rsocket/authentication/AnonymousPayloadInterceptorTests.java index 5aa69706fe..87c354e0c9 100644 --- a/rsocket/src/test/java/org/springframework/security/rsocket/authentication/AnonymousPayloadInterceptorTests.java +++ b/rsocket/src/test/java/org/springframework/security/rsocket/authentication/AnonymousPayloadInterceptorTests.java @@ -38,6 +38,7 @@ import static org.assertj.core.api.Assertions.*; */ @RunWith(MockitoJUnitRunner.class) public class AnonymousPayloadInterceptorTests { + @Mock private PayloadExchange exchange; @@ -51,31 +52,27 @@ public class AnonymousPayloadInterceptorTests { @Test public void constructorKeyWhenKeyNullThenException() { String key = null; - assertThatCode(() -> new AnonymousPayloadInterceptor(key)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> new AnonymousPayloadInterceptor(key)).isInstanceOf(IllegalArgumentException.class); } @Test public void constructorKeyPrincipalAuthoritiesWhenKeyNullThenException() { String key = null; assertThatCode(() -> new AnonymousPayloadInterceptor(key, "principal", - AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))) - .isInstanceOf(IllegalArgumentException.class); + AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))).isInstanceOf(IllegalArgumentException.class); } @Test public void constructorKeyPrincipalAuthoritiesWhenPrincipalNullThenException() { Object principal = null; assertThatCode(() -> new AnonymousPayloadInterceptor("key", principal, - AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))) - .isInstanceOf(IllegalArgumentException.class); + AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))).isInstanceOf(IllegalArgumentException.class); } @Test public void constructorKeyPrincipalAuthoritiesWhenAuthoritiesNullThenException() { List authorities = null; - assertThatCode(() -> new AnonymousPayloadInterceptor("key", "principal", - authorities)) + assertThatCode(() -> new AnonymousPayloadInterceptor("key", "principal", authorities)) .isInstanceOf(IllegalArgumentException.class); } @@ -93,15 +90,14 @@ public class AnonymousPayloadInterceptorTests { @Test public void interceptWhenAuthenticationThenOriginalAuthentication() { AuthenticationPayloadInterceptorChain chain = new AuthenticationPayloadInterceptorChain(); - TestingAuthenticationToken expected = - new TestingAuthenticationToken("test", "password"); + TestingAuthenticationToken expected = new TestingAuthenticationToken("test", "password"); this.interceptor.intercept(this.exchange, chain) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(expected)) - .block(); + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(expected)).block(); Authentication authentication = chain.getAuthentication(); assertThat(authentication).isEqualTo(expected); } + } diff --git a/rsocket/src/test/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadInterceptorChain.java b/rsocket/src/test/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadInterceptorChain.java index 30693d6b45..68b3505aa4 100644 --- a/rsocket/src/test/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadInterceptorChain.java +++ b/rsocket/src/test/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadInterceptorChain.java @@ -27,6 +27,7 @@ import org.springframework.security.rsocket.api.PayloadExchange; * @author Rob Winch */ class AuthenticationPayloadInterceptorChain implements PayloadInterceptorChain { + private Authentication authentication; @Override @@ -42,4 +43,5 @@ class AuthenticationPayloadInterceptorChain implements PayloadInterceptorChain { public void setAuthentication(Authentication authentication) { this.authentication = authentication; } + } diff --git a/rsocket/src/test/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadInterceptorTests.java b/rsocket/src/test/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadInterceptorTests.java index 7da8b63bcf..0cf10b8ecd 100644 --- a/rsocket/src/test/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadInterceptorTests.java +++ b/rsocket/src/test/java/org/springframework/security/rsocket/authentication/AuthenticationPayloadInterceptorTests.java @@ -62,8 +62,10 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class AuthenticationPayloadInterceptorTests { - static final MimeType COMPOSITE_METADATA = MimeTypeUtils.parseMimeType( - WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); + + static final MimeType COMPOSITE_METADATA = MimeTypeUtils + .parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); + @Mock ReactiveAuthenticationManager authenticationManager; @@ -72,50 +74,41 @@ public class AuthenticationPayloadInterceptorTests { @Test public void constructorWhenAuthenticationManagerNullThenException() { - assertThatCode(() -> new AuthenticationPayloadInterceptor(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> new AuthenticationPayloadInterceptor(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void interceptWhenBasicCredentialsThenAuthenticates() { - AuthenticationPayloadInterceptor interceptor = new AuthenticationPayloadInterceptor( - this.authenticationManager); + AuthenticationPayloadInterceptor interceptor = new AuthenticationPayloadInterceptor(this.authenticationManager); PayloadExchange exchange = createExchange(); - TestingAuthenticationToken expectedAuthentication = - new TestingAuthenticationToken("user", "password"); - when(this.authenticationManager.authenticate(any())).thenReturn(Mono.just( - expectedAuthentication)); + TestingAuthenticationToken expectedAuthentication = new TestingAuthenticationToken("user", "password"); + when(this.authenticationManager.authenticate(any())).thenReturn(Mono.just(expectedAuthentication)); AuthenticationPayloadInterceptorChain authenticationPayloadChain = new AuthenticationPayloadInterceptorChain(); - interceptor.intercept(exchange, authenticationPayloadChain) - .block(); + interceptor.intercept(exchange, authenticationPayloadChain).block(); Authentication authentication = authenticationPayloadChain.getAuthentication(); verify(this.authenticationManager).authenticate(this.authenticationArg.capture()); - assertThat(this.authenticationArg.getValue()).isEqualToComparingFieldByField(new UsernamePasswordAuthenticationToken("user", "password")); + assertThat(this.authenticationArg.getValue()) + .isEqualToComparingFieldByField(new UsernamePasswordAuthenticationToken("user", "password")); assertThat(authentication).isEqualTo(expectedAuthentication); } @Test public void interceptWhenAuthenticationSuccessThenChainSubscribedOnce() { - AuthenticationPayloadInterceptor interceptor = new AuthenticationPayloadInterceptor( - this.authenticationManager); + AuthenticationPayloadInterceptor interceptor = new AuthenticationPayloadInterceptor(this.authenticationManager); PayloadExchange exchange = createExchange(); - TestingAuthenticationToken expectedAuthentication = - new TestingAuthenticationToken("user", "password"); - when(this.authenticationManager.authenticate(any())).thenReturn(Mono.just( - expectedAuthentication)); + TestingAuthenticationToken expectedAuthentication = new TestingAuthenticationToken("user", "password"); + when(this.authenticationManager.authenticate(any())).thenReturn(Mono.just(expectedAuthentication)); PublisherProbe voidResult = PublisherProbe.empty(); PayloadInterceptorChain chain = mock(PayloadInterceptorChain.class); when(chain.next(any())).thenReturn(voidResult.mono()); - StepVerifier.create(interceptor.intercept(exchange, chain)) - .then(() -> assertThat(voidResult.subscribeCount()).isEqualTo(1)) - .verifyComplete(); + .then(() -> assertThat(voidResult.subscribeCount()).isEqualTo(1)).verifyComplete(); } private Payload createRequestPayload() { @@ -123,25 +116,22 @@ public class AuthenticationPayloadInterceptorTests { UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password"); BasicAuthenticationEncoder encoder = new BasicAuthenticationEncoder(); DefaultDataBufferFactory factory = new DefaultDataBufferFactory(); - ResolvableType elementType = ResolvableType - .forClass(UsernamePasswordMetadata.class); + ResolvableType elementType = ResolvableType.forClass(UsernamePasswordMetadata.class); MimeType mimeType = UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE; Map hints = null; - DataBuffer dataBuffer = encoder.encodeValue(credentials, factory, - elementType, mimeType, hints); + DataBuffer dataBuffer = encoder.encodeValue(credentials, factory, elementType, mimeType, hints); ByteBufAllocator allocator = ByteBufAllocator.DEFAULT; CompositeByteBuf metadata = allocator.compositeBuffer(); - CompositeMetadataCodec.encodeAndAddMetadata( - metadata, allocator, mimeType.toString(), NettyDataBufferFactory.toByteBuf(dataBuffer)); + CompositeMetadataCodec.encodeAndAddMetadata(metadata, allocator, mimeType.toString(), + NettyDataBufferFactory.toByteBuf(dataBuffer)); - return DefaultPayload.create(allocator.buffer(), - metadata); + return DefaultPayload.create(allocator.buffer(), metadata); } private PayloadExchange createExchange() { - return new DefaultPayloadExchange(PayloadExchangeType.REQUEST_RESPONSE, createRequestPayload(), COMPOSITE_METADATA, - MediaType.APPLICATION_JSON); + return new DefaultPayloadExchange(PayloadExchangeType.REQUEST_RESPONSE, createRequestPayload(), + COMPOSITE_METADATA, MediaType.APPLICATION_JSON); } } diff --git a/rsocket/src/test/java/org/springframework/security/rsocket/authorization/AuthorizationPayloadInterceptorTests.java b/rsocket/src/test/java/org/springframework/security/rsocket/authorization/AuthorizationPayloadInterceptorTests.java index 5e5178a46d..e47494e886 100644 --- a/rsocket/src/test/java/org/springframework/security/rsocket/authorization/AuthorizationPayloadInterceptorTests.java +++ b/rsocket/src/test/java/org/springframework/security/rsocket/authorization/AuthorizationPayloadInterceptorTests.java @@ -42,6 +42,7 @@ import static org.springframework.security.authorization.AuthorityReactiveAuthor */ @RunWith(MockitoJUnitRunner.class) public class AuthorizationPayloadInterceptorTests { + @Mock private ReactiveAuthorizationManager authorizationManager; @@ -59,42 +60,35 @@ public class AuthorizationPayloadInterceptorTests { public void interceptWhenAuthenticationEmptyAndSubscribedThenException() { when(this.chain.next(any())).thenReturn(this.chainResult.mono()); - AuthorizationPayloadInterceptor interceptor = - new AuthorizationPayloadInterceptor(authenticated()); + AuthorizationPayloadInterceptor interceptor = new AuthorizationPayloadInterceptor(authenticated()); StepVerifier.create(interceptor.intercept(this.exchange, this.chain)) - .then(() -> this.chainResult.assertWasNotSubscribed()) - .verifyError(AuthenticationCredentialsNotFoundException.class); + .then(() -> this.chainResult.assertWasNotSubscribed()) + .verifyError(AuthenticationCredentialsNotFoundException.class); } @Test public void interceptWhenAuthenticationNotSubscribedAndEmptyThenCompletes() { when(this.chain.next(any())).thenReturn(this.chainResult.mono()); - when(this.authorizationManager.verify(any(), any())) - .thenReturn(this.managerResult.mono()); + when(this.authorizationManager.verify(any(), any())).thenReturn(this.managerResult.mono()); - AuthorizationPayloadInterceptor interceptor = - new AuthorizationPayloadInterceptor(this.authorizationManager); + AuthorizationPayloadInterceptor interceptor = new AuthorizationPayloadInterceptor(this.authorizationManager); StepVerifier.create(interceptor.intercept(this.exchange, this.chain)) - .then(() -> this.chainResult.assertWasSubscribed()) - .verifyComplete(); + .then(() -> this.chainResult.assertWasSubscribed()).verifyComplete(); } @Test public void interceptWhenNotAuthorizedThenException() { when(this.chain.next(any())).thenReturn(this.chainResult.mono()); - AuthorizationPayloadInterceptor interceptor = - new AuthorizationPayloadInterceptor(hasRole("USER")); + AuthorizationPayloadInterceptor interceptor = new AuthorizationPayloadInterceptor(hasRole("USER")); Context userContext = ReactiveSecurityContextHolder .withAuthentication(new TestingAuthenticationToken("user", "password")); - Mono intercept = interceptor.intercept(this.exchange, this.chain) - .subscriberContext(userContext); + Mono intercept = interceptor.intercept(this.exchange, this.chain).subscriberContext(userContext); - StepVerifier.create(intercept) - .then(() -> this.chainResult.assertWasNotSubscribed()) + StepVerifier.create(intercept).then(() -> this.chainResult.assertWasNotSubscribed()) .verifyError(AccessDeniedException.class); } @@ -102,16 +96,13 @@ public class AuthorizationPayloadInterceptorTests { public void interceptWhenAuthorizedThenContinues() { when(this.chain.next(any())).thenReturn(this.chainResult.mono()); - AuthorizationPayloadInterceptor interceptor = - new AuthorizationPayloadInterceptor(authenticated()); + AuthorizationPayloadInterceptor interceptor = new AuthorizationPayloadInterceptor(authenticated()); Context userContext = ReactiveSecurityContextHolder .withAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")); - Mono intercept = interceptor.intercept(this.exchange, this.chain) - .subscriberContext(userContext); + Mono intercept = interceptor.intercept(this.exchange, this.chain).subscriberContext(userContext); - StepVerifier.create(intercept) - .then(() -> this.chainResult.assertWasSubscribed()) - .verifyComplete(); + StepVerifier.create(intercept).then(() -> this.chainResult.assertWasSubscribed()).verifyComplete(); } + } diff --git a/rsocket/src/test/java/org/springframework/security/rsocket/authorization/PayloadExchangeMatcherReactiveAuthorizationManagerTests.java b/rsocket/src/test/java/org/springframework/security/rsocket/authorization/PayloadExchangeMatcherReactiveAuthorizationManagerTests.java index 2a0fceafe3..f33546ac29 100644 --- a/rsocket/src/test/java/org/springframework/security/rsocket/authorization/PayloadExchangeMatcherReactiveAuthorizationManagerTests.java +++ b/rsocket/src/test/java/org/springframework/security/rsocket/authorization/PayloadExchangeMatcherReactiveAuthorizationManagerTests.java @@ -51,58 +51,47 @@ public class PayloadExchangeMatcherReactiveAuthorizationManagerTests { @Test public void checkWhenGrantedThenGranted() { AuthorizationDecision expected = new AuthorizationDecision(true); - when(this.authz.check(any(), any())).thenReturn(Mono.just( - expected)); - PayloadExchangeMatcherReactiveAuthorizationManager manager = - PayloadExchangeMatcherReactiveAuthorizationManager.builder() - .add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz)) - .build(); + when(this.authz.check(any(), any())).thenReturn(Mono.just(expected)); + PayloadExchangeMatcherReactiveAuthorizationManager manager = PayloadExchangeMatcherReactiveAuthorizationManager + .builder().add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz)) + .build(); - assertThat(manager.check(Mono.empty(), this.exchange).block()) - .isEqualTo(expected); + assertThat(manager.check(Mono.empty(), this.exchange).block()).isEqualTo(expected); } @Test public void checkWhenDeniedThenDenied() { AuthorizationDecision expected = new AuthorizationDecision(false); - when(this.authz.check(any(), any())).thenReturn(Mono.just( - expected)); - PayloadExchangeMatcherReactiveAuthorizationManager manager = - PayloadExchangeMatcherReactiveAuthorizationManager.builder() - .add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz)) - .build(); + when(this.authz.check(any(), any())).thenReturn(Mono.just(expected)); + PayloadExchangeMatcherReactiveAuthorizationManager manager = PayloadExchangeMatcherReactiveAuthorizationManager + .builder().add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz)) + .build(); - assertThat(manager.check(Mono.empty(), this.exchange).block()) - .isEqualTo(expected); + assertThat(manager.check(Mono.empty(), this.exchange).block()).isEqualTo(expected); } @Test public void checkWhenFirstMatchThenSecondUsed() { AuthorizationDecision expected = new AuthorizationDecision(true); - when(this.authz.check(any(), any())).thenReturn(Mono.just( - expected)); - PayloadExchangeMatcherReactiveAuthorizationManager manager = - PayloadExchangeMatcherReactiveAuthorizationManager.builder() - .add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz)) - .add(new PayloadExchangeMatcherEntry<>(e -> PayloadExchangeMatcher.MatchResult.notMatch(), this.authz2)) - .build(); + when(this.authz.check(any(), any())).thenReturn(Mono.just(expected)); + PayloadExchangeMatcherReactiveAuthorizationManager manager = PayloadExchangeMatcherReactiveAuthorizationManager + .builder().add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz)) + .add(new PayloadExchangeMatcherEntry<>(e -> PayloadExchangeMatcher.MatchResult.notMatch(), this.authz2)) + .build(); - assertThat(manager.check(Mono.empty(), this.exchange).block()) - .isEqualTo(expected); + assertThat(manager.check(Mono.empty(), this.exchange).block()).isEqualTo(expected); } @Test public void checkWhenSecondMatchThenSecondUsed() { AuthorizationDecision expected = new AuthorizationDecision(true); - when(this.authz2.check(any(), any())).thenReturn(Mono.just( - expected)); - PayloadExchangeMatcherReactiveAuthorizationManager manager = - PayloadExchangeMatcherReactiveAuthorizationManager.builder() - .add(new PayloadExchangeMatcherEntry<>(e -> PayloadExchangeMatcher.MatchResult.notMatch(), this.authz)) - .add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz2)) - .build(); + when(this.authz2.check(any(), any())).thenReturn(Mono.just(expected)); + PayloadExchangeMatcherReactiveAuthorizationManager manager = PayloadExchangeMatcherReactiveAuthorizationManager + .builder() + .add(new PayloadExchangeMatcherEntry<>(e -> PayloadExchangeMatcher.MatchResult.notMatch(), this.authz)) + .add(new PayloadExchangeMatcherEntry<>(PayloadExchangeMatchers.anyExchange(), this.authz2)).build(); - assertThat(manager.check(Mono.empty(), this.exchange).block()) - .isEqualTo(expected); + assertThat(manager.check(Mono.empty(), this.exchange).block()).isEqualTo(expected); } + } diff --git a/rsocket/src/test/java/org/springframework/security/rsocket/core/CaptureSecurityContextSocketAcceptor.java b/rsocket/src/test/java/org/springframework/security/rsocket/core/CaptureSecurityContextSocketAcceptor.java index f434ed4c70..0146455715 100644 --- a/rsocket/src/test/java/org/springframework/security/rsocket/core/CaptureSecurityContextSocketAcceptor.java +++ b/rsocket/src/test/java/org/springframework/security/rsocket/core/CaptureSecurityContextSocketAcceptor.java @@ -25,10 +25,13 @@ import org.springframework.security.core.context.ReactiveSecurityContextHolder; import org.springframework.security.core.context.SecurityContext; /** - * A {@link SocketAcceptor} that captures the {@link SecurityContext} and then continues with the {@link RSocket} + * A {@link SocketAcceptor} that captures the {@link SecurityContext} and then continues + * with the {@link RSocket} + * * @author Rob Winch */ class CaptureSecurityContextSocketAcceptor implements SocketAcceptor { + private final RSocket accept; private SecurityContext securityContext; @@ -40,11 +43,11 @@ class CaptureSecurityContextSocketAcceptor implements SocketAcceptor { @Override public Mono accept(ConnectionSetupPayload setup, RSocket sendingSocket) { return ReactiveSecurityContextHolder.getContext() - .doOnNext(securityContext -> this.securityContext = securityContext) - .thenReturn(this.accept); + .doOnNext(securityContext -> this.securityContext = securityContext).thenReturn(this.accept); } public SecurityContext getSecurityContext() { return this.securityContext; } + } diff --git a/rsocket/src/test/java/org/springframework/security/rsocket/core/PayloadInterceptorRSocketTests.java b/rsocket/src/test/java/org/springframework/security/rsocket/core/PayloadInterceptorRSocketTests.java index a925ac676e..c5c259de8f 100644 --- a/rsocket/src/test/java/org/springframework/security/rsocket/core/PayloadInterceptorRSocketTests.java +++ b/rsocket/src/test/java/org/springframework/security/rsocket/core/PayloadInterceptorRSocketTests.java @@ -64,8 +64,8 @@ import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class PayloadInterceptorRSocketTests { - static final MimeType COMPOSITE_METADATA = MimeTypeUtils.parseMimeType( - WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); + static final MimeType COMPOSITE_METADATA = MimeTypeUtils + .parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); @Mock RSocket delegate; @@ -95,26 +95,22 @@ public class PayloadInterceptorRSocketTests { this.delegate = null; List interceptors = Arrays.asList(this.interceptor); assertThatCode(() -> { - new PayloadInterceptorRSocket(this.delegate, interceptors, - metadataMimeType, dataMimeType); - }) - .isInstanceOf(IllegalArgumentException.class); + new PayloadInterceptorRSocket(this.delegate, interceptors, metadataMimeType, dataMimeType); + }).isInstanceOf(IllegalArgumentException.class); } @Test public void constructorWhenNullInterceptorsThenException() { List interceptors = null; - assertThatCode(() -> new PayloadInterceptorRSocket(this.delegate, interceptors, - metadataMimeType, dataMimeType)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> new PayloadInterceptorRSocket(this.delegate, interceptors, metadataMimeType, dataMimeType)) + .isInstanceOf(IllegalArgumentException.class); } @Test public void constructorWhenEmptyInterceptorsThenException() { List interceptors = Collections.emptyList(); - assertThatCode(() -> new PayloadInterceptorRSocket(this.delegate, interceptors, - metadataMimeType, dataMimeType)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> new PayloadInterceptorRSocket(this.delegate, interceptors, metadataMimeType, dataMimeType)) + .isInstanceOf(IllegalArgumentException.class); } // single interceptor @@ -127,9 +123,8 @@ public class PayloadInterceptorRSocketTests { PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate, Arrays.asList(this.interceptor), metadataMimeType, dataMimeType); - StepVerifier.create(interceptor.fireAndForget(this.payload)) - .then(() -> this.voidResult.assertWasSubscribed()) - .verifyComplete(); + StepVerifier.create(interceptor.fireAndForget(this.payload)).then(() -> this.voidResult.assertWasSubscribed()) + .verifyComplete(); verify(this.interceptor).intercept(this.exchange.capture(), any()); assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload); @@ -144,8 +139,8 @@ public class PayloadInterceptorRSocketTests { Arrays.asList(this.interceptor), metadataMimeType, dataMimeType); StepVerifier.create(interceptor.fireAndForget(this.payload)) - .then(() -> this.voidResult.assertWasNotSubscribed()) - .verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected)); + .then(() -> this.voidResult.assertWasNotSubscribed()) + .verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected)); verify(this.interceptor).intercept(this.exchange.capture(), any()); assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload); @@ -160,8 +155,7 @@ public class PayloadInterceptorRSocketTests { RSocket assertAuthentication = new RSocketProxy(this.delegate) { @Override public Mono fireAndForget(Payload payload) { - return assertAuthentication(authentication) - .flatMap(a -> super.fireAndForget(payload)); + return assertAuthentication(authentication).flatMap(a -> super.fireAndForget(payload)); } }; PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(assertAuthentication, @@ -183,10 +177,8 @@ public class PayloadInterceptorRSocketTests { Arrays.asList(this.interceptor), metadataMimeType, dataMimeType); StepVerifier.create(interceptor.requestResponse(this.payload)) - .then(() -> this.payloadResult.assertSubscribers()) - .then(() -> this.payloadResult.emit(this.payload)) - .expectNext(this.payload) - .verifyComplete(); + .then(() -> this.payloadResult.assertSubscribers()).then(() -> this.payloadResult.emit(this.payload)) + .expectNext(this.payload).verifyComplete(); verify(this.interceptor).intercept(this.exchange.capture(), any()); assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload); @@ -217,18 +209,15 @@ public class PayloadInterceptorRSocketTests { RSocket assertAuthentication = new RSocketProxy(this.delegate) { @Override public Mono requestResponse(Payload payload) { - return assertAuthentication(authentication) - .flatMap(a -> super.requestResponse(payload)); + return assertAuthentication(authentication).flatMap(a -> super.requestResponse(payload)); } }; PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(assertAuthentication, Arrays.asList(this.interceptor), metadataMimeType, dataMimeType); StepVerifier.create(interceptor.requestResponse(this.payload)) - .then(() -> this.payloadResult.assertSubscribers()) - .then(() -> this.payloadResult.emit(this.payload)) - .expectNext(this.payload) - .verifyComplete(); + .then(() -> this.payloadResult.assertSubscribers()).then(() -> this.payloadResult.emit(this.payload)) + .expectNext(this.payload).verifyComplete(); verify(this.interceptor).intercept(this.exchange.capture(), any()); assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload); @@ -243,11 +232,8 @@ public class PayloadInterceptorRSocketTests { PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate, Arrays.asList(this.interceptor), metadataMimeType, dataMimeType); - StepVerifier.create(interceptor.requestStream(this.payload)) - .then(() -> this.payloadResult.assertSubscribers()) - .then(() -> this.payloadResult.emit(this.payload)) - .expectNext(this.payload) - .verifyComplete(); + StepVerifier.create(interceptor.requestStream(this.payload)).then(() -> this.payloadResult.assertSubscribers()) + .then(() -> this.payloadResult.emit(this.payload)).expectNext(this.payload).verifyComplete(); verify(this.interceptor).intercept(this.exchange.capture(), any()); assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload); @@ -262,8 +248,8 @@ public class PayloadInterceptorRSocketTests { Arrays.asList(this.interceptor), metadataMimeType, dataMimeType); StepVerifier.create(interceptor.requestStream(this.payload)) - .then(() -> this.payloadResult.assertNoSubscribers()) - .verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected)); + .then(() -> this.payloadResult.assertNoSubscribers()) + .verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected)); verify(this.interceptor).intercept(this.exchange.capture(), any()); assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload); @@ -278,18 +264,14 @@ public class PayloadInterceptorRSocketTests { RSocket assertAuthentication = new RSocketProxy(this.delegate) { @Override public Flux requestStream(Payload payload) { - return assertAuthentication(authentication) - .flatMapMany(a -> super.requestStream(payload)); + return assertAuthentication(authentication).flatMapMany(a -> super.requestStream(payload)); } }; PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(assertAuthentication, Arrays.asList(this.interceptor), metadataMimeType, dataMimeType); - StepVerifier.create(interceptor.requestStream(this.payload)) - .then(() -> this.payloadResult.assertSubscribers()) - .then(() -> this.payloadResult.emit(this.payload)) - .expectNext(this.payload) - .verifyComplete(); + StepVerifier.create(interceptor.requestStream(this.payload)).then(() -> this.payloadResult.assertSubscribers()) + .then(() -> this.payloadResult.emit(this.payload)).expectNext(this.payload).verifyComplete(); verify(this.interceptor).intercept(this.exchange.capture(), any()); assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload); @@ -305,10 +287,8 @@ public class PayloadInterceptorRSocketTests { Arrays.asList(this.interceptor), metadataMimeType, dataMimeType); StepVerifier.create(interceptor.requestChannel(Flux.just(this.payload))) - .then(() -> this.payloadResult.assertSubscribers()) - .then(() -> this.payloadResult.emit(this.payload)) - .expectNext(this.payload) - .verifyComplete(); + .then(() -> this.payloadResult.assertSubscribers()).then(() -> this.payloadResult.emit(this.payload)) + .expectNext(this.payload).verifyComplete(); verify(this.interceptor).intercept(this.exchange.capture(), any()); assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload); @@ -324,8 +304,8 @@ public class PayloadInterceptorRSocketTests { Arrays.asList(this.interceptor), this.metadataMimeType, this.dataMimeType); StepVerifier.create(interceptor.requestChannel(Flux.just(this.payload))) - .then(() -> this.payloadResult.assertNoSubscribers()) - .verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected)); + .then(() -> this.payloadResult.assertNoSubscribers()) + .verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected)); verify(this.interceptor).intercept(this.exchange.capture(), any()); assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload); @@ -341,18 +321,14 @@ public class PayloadInterceptorRSocketTests { RSocket assertAuthentication = new RSocketProxy(this.delegate) { @Override public Flux requestChannel(Publisher payload) { - return assertAuthentication(authentication) - .flatMapMany(a -> super.requestChannel(payload)); + return assertAuthentication(authentication).flatMapMany(a -> super.requestChannel(payload)); } }; PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(assertAuthentication, Arrays.asList(this.interceptor), metadataMimeType, dataMimeType); - StepVerifier.create(interceptor.requestChannel(payload)) - .then(() -> this.payloadResult.assertSubscribers()) - .then(() -> this.payloadResult.emit(this.payload)) - .expectNext(this.payload) - .verifyComplete(); + StepVerifier.create(interceptor.requestChannel(payload)).then(() -> this.payloadResult.assertSubscribers()) + .then(() -> this.payloadResult.emit(this.payload)).expectNext(this.payload).verifyComplete(); verify(this.interceptor).intercept(this.exchange.capture(), any()); assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload); @@ -367,9 +343,8 @@ public class PayloadInterceptorRSocketTests { PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate, Arrays.asList(this.interceptor), metadataMimeType, dataMimeType); - StepVerifier.create(interceptor.metadataPush(this.payload)) - .then(() -> this.voidResult.assertWasSubscribed()) - .verifyComplete(); + StepVerifier.create(interceptor.metadataPush(this.payload)).then(() -> this.voidResult.assertWasSubscribed()) + .verifyComplete(); verify(this.interceptor).intercept(this.exchange.capture(), any()); assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload); @@ -383,9 +358,8 @@ public class PayloadInterceptorRSocketTests { PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate, Arrays.asList(this.interceptor), metadataMimeType, dataMimeType); - StepVerifier.create(interceptor.metadataPush(this.payload)) - .then(() -> this.voidResult.assertWasNotSubscribed()) - .verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected)); + StepVerifier.create(interceptor.metadataPush(this.payload)).then(() -> this.voidResult.assertWasNotSubscribed()) + .verifyErrorSatisfies(e -> assertThat(e).isEqualTo(expected)); verify(this.interceptor).intercept(this.exchange.capture(), any()); assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload); @@ -400,15 +374,13 @@ public class PayloadInterceptorRSocketTests { RSocket assertAuthentication = new RSocketProxy(this.delegate) { @Override public Mono metadataPush(Payload payload) { - return assertAuthentication(authentication) - .flatMap(a -> super.metadataPush(payload)); + return assertAuthentication(authentication).flatMap(a -> super.metadataPush(payload)); } }; PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(assertAuthentication, Arrays.asList(this.interceptor), metadataMimeType, dataMimeType); - StepVerifier.create(interceptor.metadataPush(this.payload)) - .verifyComplete(); + StepVerifier.create(interceptor.metadataPush(this.payload)).verifyComplete(); verify(this.interceptor).intercept(this.exchange.capture(), any()); assertThat(this.exchange.getValue().getPayload()).isEqualTo(this.payload); @@ -425,8 +397,7 @@ public class PayloadInterceptorRSocketTests { when(this.delegate.fireAndForget(any())).thenReturn(this.voidResult.mono()); PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate, - Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType, - dataMimeType); + Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType, dataMimeType); interceptor.fireAndForget(this.payload).block(); @@ -435,7 +406,6 @@ public class PayloadInterceptorRSocketTests { this.voidResult.assertWasSubscribed(); } - @Test public void fireAndForgetWhenInterceptorsMutatesPayloadThenDelegateInvoked() { when(this.interceptor.intercept(any(), any())).thenAnswer(withChainNext()); @@ -443,8 +413,7 @@ public class PayloadInterceptorRSocketTests { when(this.delegate.fireAndForget(any())).thenReturn(this.voidResult.mono()); PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate, - Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType, - dataMimeType); + Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType, dataMimeType); interceptor.fireAndForget(this.payload).block(); @@ -461,8 +430,7 @@ public class PayloadInterceptorRSocketTests { when(this.interceptor.intercept(any(), any())).thenReturn(Mono.error(expected)); PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate, - Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType, - dataMimeType); + Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType, dataMimeType); assertThatCode(() -> interceptor.fireAndForget(this.payload).block()).isEqualTo(expected); @@ -479,8 +447,7 @@ public class PayloadInterceptorRSocketTests { when(this.interceptor2.intercept(any(), any())).thenReturn(Mono.error(expected)); PayloadInterceptorRSocket interceptor = new PayloadInterceptorRSocket(this.delegate, - Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType, - dataMimeType); + Arrays.asList(this.interceptor, this.interceptor2), metadataMimeType, dataMimeType); assertThatCode(() -> interceptor.fireAndForget(this.payload).block()).isEqualTo(expected); @@ -491,16 +458,15 @@ public class PayloadInterceptorRSocketTests { } private Mono assertAuthentication(Authentication authentication) { - return ReactiveSecurityContextHolder.getContext() - .map(SecurityContext::getAuthentication) + return ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication) .doOnNext(a -> assertThat(a).isEqualTo(authentication)); } private Answer withAuthenticated(Authentication authentication) { return invocation -> { PayloadInterceptorChain c = (PayloadInterceptorChain) invocation.getArguments()[1]; - return c.next(new DefaultPayloadExchange(PayloadExchangeType.REQUEST_CHANNEL, this.payload, this.metadataMimeType, - this.dataMimeType)) + return c.next(new DefaultPayloadExchange(PayloadExchangeType.REQUEST_CHANNEL, this.payload, + this.metadataMimeType, this.dataMimeType)) .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)); }; } @@ -512,4 +478,5 @@ public class PayloadInterceptorRSocketTests { return chain.next(exchange); }; } + } diff --git a/rsocket/src/test/java/org/springframework/security/rsocket/core/PayloadSocketAcceptorInterceptorTests.java b/rsocket/src/test/java/org/springframework/security/rsocket/core/PayloadSocketAcceptorInterceptorTests.java index d06ac483d0..225a95b776 100644 --- a/rsocket/src/test/java/org/springframework/security/rsocket/core/PayloadSocketAcceptorInterceptorTests.java +++ b/rsocket/src/test/java/org/springframework/security/rsocket/core/PayloadSocketAcceptorInterceptorTests.java @@ -48,6 +48,7 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class PayloadSocketAcceptorInterceptorTests { + @Mock private PayloadInterceptor interceptor; @@ -79,7 +80,8 @@ public class PayloadSocketAcceptorInterceptorTests { PayloadExchange exchange = captureExchange(); - assertThat(exchange.getMetadataMimeType().toString()).isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); + assertThat(exchange.getMetadataMimeType().toString()) + .isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); assertThat(exchange.getDataMimeType()).isEqualTo(MediaType.APPLICATION_JSON); } @@ -100,7 +102,8 @@ public class PayloadSocketAcceptorInterceptorTests { PayloadExchange exchange = captureExchange(); - assertThat(exchange.getMetadataMimeType().toString()).isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); + assertThat(exchange.getMetadataMimeType().toString()) + .isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); assertThat(exchange.getDataMimeType()).isEqualTo(MediaType.APPLICATION_JSON); } @@ -117,9 +120,9 @@ public class PayloadSocketAcceptorInterceptorTests { result.fireAndForget(this.payload).block(); - ArgumentCaptor exchangeArg = - ArgumentCaptor.forClass(PayloadExchange.class); + ArgumentCaptor exchangeArg = ArgumentCaptor.forClass(PayloadExchange.class); verify(this.interceptor, times(2)).intercept(exchangeArg.capture(), any()); return exchangeArg.getValue(); } + } diff --git a/rsocket/src/test/java/org/springframework/security/rsocket/core/PayloadSocketAcceptorTests.java b/rsocket/src/test/java/org/springframework/security/rsocket/core/PayloadSocketAcceptorTests.java index 69b7e2356d..6d907f604c 100644 --- a/rsocket/src/test/java/org/springframework/security/rsocket/core/PayloadSocketAcceptorTests.java +++ b/rsocket/src/test/java/org/springframework/security/rsocket/core/PayloadSocketAcceptorTests.java @@ -100,8 +100,8 @@ public class PayloadSocketAcceptorTests { @Test public void acceptWhenDataMimeTypeNullThenException() { - assertThatCode(() -> this.acceptor.accept(this.setupPayload, this.rSocket) - .block()).isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> this.acceptor.accept(this.setupPayload, this.rSocket).block()) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -132,8 +132,8 @@ public class PayloadSocketAcceptorTests { PayloadExchange exchange = captureExchange(); - assertThat(exchange.getMetadataMimeType() - .toString()).isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); + assertThat(exchange.getMetadataMimeType().toString()) + .isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); assertThat(exchange.getDataMimeType()).isEqualTo(MediaType.APPLICATION_JSON); } @@ -148,18 +148,19 @@ public class PayloadSocketAcceptorTests { assertThat(exchange.getDataMimeType()).isEqualTo(MediaType.APPLICATION_JSON); } - @Test // gh-8654 public void acceptWhenDelegateAcceptRequiresReactiveSecurityContext() { when(this.setupPayload.metadataMimeType()).thenReturn(MediaType.TEXT_PLAIN_VALUE); when(this.setupPayload.dataMimeType()).thenReturn(MediaType.APPLICATION_JSON_VALUE); - SecurityContext expectedSecurityContext = new SecurityContextImpl(new TestingAuthenticationToken("user", "password", "ROLE_USER")); - CaptureSecurityContextSocketAcceptor captureSecurityContext = new CaptureSecurityContextSocketAcceptor(this.rSocket); + SecurityContext expectedSecurityContext = new SecurityContextImpl( + new TestingAuthenticationToken("user", "password", "ROLE_USER")); + CaptureSecurityContextSocketAcceptor captureSecurityContext = new CaptureSecurityContextSocketAcceptor( + this.rSocket); PayloadInterceptor authenticateInterceptor = (exchange, chain) -> { - Context withSecurityContext = ReactiveSecurityContextHolder.withSecurityContext(Mono.just(expectedSecurityContext)); - return chain.next(exchange) - .subscriberContext(withSecurityContext); + Context withSecurityContext = ReactiveSecurityContextHolder + .withSecurityContext(Mono.just(expectedSecurityContext)); + return chain.next(exchange).subscriberContext(withSecurityContext); }; List interceptors = Arrays.asList(authenticateInterceptor); this.acceptor = new PayloadSocketAcceptor(captureSecurityContext, interceptors); @@ -181,9 +182,9 @@ public class PayloadSocketAcceptorTests { result.fireAndForget(this.payload).block(); - ArgumentCaptor exchangeArg = - ArgumentCaptor.forClass(PayloadExchange.class); + ArgumentCaptor exchangeArg = ArgumentCaptor.forClass(PayloadExchange.class); verify(this.interceptor, times(2)).intercept(exchangeArg.capture(), any()); return exchangeArg.getValue(); } + } diff --git a/rsocket/src/test/java/org/springframework/security/rsocket/metadata/BasicAuthenticationDecoderTests.java b/rsocket/src/test/java/org/springframework/security/rsocket/metadata/BasicAuthenticationDecoderTests.java index 2654d2378c..258f29d8df 100644 --- a/rsocket/src/test/java/org/springframework/security/rsocket/metadata/BasicAuthenticationDecoderTests.java +++ b/rsocket/src/test/java/org/springframework/security/rsocket/metadata/BasicAuthenticationDecoderTests.java @@ -31,20 +31,18 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Rob Winch */ public class BasicAuthenticationDecoderTests { + @Test public void basicAuthenticationWhenEncodedThenDecodes() { BasicAuthenticationEncoder encoder = new BasicAuthenticationEncoder(); BasicAuthenticationDecoder decoder = new BasicAuthenticationDecoder(); - UsernamePasswordMetadata expectedCredentials = - new UsernamePasswordMetadata("rob", "password"); + UsernamePasswordMetadata expectedCredentials = new UsernamePasswordMetadata("rob", "password"); DefaultDataBufferFactory factory = new DefaultDataBufferFactory(); - ResolvableType elementType = ResolvableType - .forClass(UsernamePasswordMetadata.class); + ResolvableType elementType = ResolvableType.forClass(UsernamePasswordMetadata.class); MimeType mimeType = UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE; Map hints = null; - DataBuffer dataBuffer = encoder.encodeValue(expectedCredentials, factory, - elementType, mimeType, hints); + DataBuffer dataBuffer = encoder.encodeValue(expectedCredentials, factory, elementType, mimeType, hints); UsernamePasswordMetadata actualCredentials = decoder .decodeToMono(Mono.just(dataBuffer), elementType, mimeType, hints).block(); diff --git a/rsocket/src/test/java/org/springframework/security/rsocket/util/matcher/RoutePayloadExchangeMatcherTests.java b/rsocket/src/test/java/org/springframework/security/rsocket/util/matcher/RoutePayloadExchangeMatcherTests.java index 6d0b2ae73b..cf15b44ba3 100644 --- a/rsocket/src/test/java/org/springframework/security/rsocket/util/matcher/RoutePayloadExchangeMatcherTests.java +++ b/rsocket/src/test/java/org/springframework/security/rsocket/util/matcher/RoutePayloadExchangeMatcherTests.java @@ -44,8 +44,9 @@ import static org.mockito.Mockito.when; */ @RunWith(MockitoJUnitRunner.class) public class RoutePayloadExchangeMatcherTests { - static final MimeType COMPOSITE_METADATA = MimeTypeUtils.parseMimeType( - WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); + + static final MimeType COMPOSITE_METADATA = MimeTypeUtils + .parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); @Mock private MetadataExtractor metadataExtractor; @@ -69,14 +70,13 @@ public class RoutePayloadExchangeMatcherTests { public void setup() { this.pattern = "a.b"; this.matcher = new RoutePayloadExchangeMatcher(this.metadataExtractor, this.routeMatcher, this.pattern); - this.exchange = new DefaultPayloadExchange(PayloadExchangeType.REQUEST_CHANNEL, this.payload, COMPOSITE_METADATA, - MediaType.APPLICATION_JSON); + this.exchange = new DefaultPayloadExchange(PayloadExchangeType.REQUEST_CHANNEL, this.payload, + COMPOSITE_METADATA, MediaType.APPLICATION_JSON); } @Test public void matchesWhenNoRouteThenNotMatch() { - when(this.metadataExtractor.extract(any(), any())) - .thenReturn(Collections.emptyMap()); + when(this.metadataExtractor.extract(any(), any())).thenReturn(Collections.emptyMap()); PayloadExchangeMatcher.MatchResult result = this.matcher.matches(this.exchange).block(); assertThat(result.isMatch()).isFalse(); } @@ -113,4 +113,5 @@ public class RoutePayloadExchangeMatcherTests { assertThat(result.isMatch()).isTrue(); assertThat(result.getVariables()).containsAllEntriesOf(variables); } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/OpenSamlInitializationService.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/OpenSamlInitializationService.java index a533a2753e..67e36d0593 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/OpenSamlInitializationService.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/OpenSamlInitializationService.java @@ -36,17 +36,21 @@ import static java.lang.Boolean.TRUE; import static org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport.setParserPool; /** - * An initialization service for initializing OpenSAML. Each Spring Security OpenSAML-based component invokes - * the {@link #initialize()} method at static initialization time. + * An initialization service for initializing OpenSAML. Each Spring Security + * OpenSAML-based component invokes the {@link #initialize()} method at static + * initialization time. * - * {@link #initialize()} is idempotent and may be safely called in custom classes that need OpenSAML to be - * initialized in order to function correctly. It's recommended that you call this {@link #initialize()} method - * when using Spring Security and OpenSAML instead of OpenSAML's {@link InitializationService#initialize()}. + * {@link #initialize()} is idempotent and may be safely called in custom classes that + * need OpenSAML to be initialized in order to function correctly. It's recommended that + * you call this {@link #initialize()} method when using Spring Security and OpenSAML + * instead of OpenSAML's {@link InitializationService#initialize()}. * - * The primary purpose of {@link #initialize()} is to prepare OpenSAML's {@link XMLObjectProviderRegistry} - * with some reasonable defaults. Any changes that Spring Security makes to the registry happen in this method. + * The primary purpose of {@link #initialize()} is to prepare OpenSAML's + * {@link XMLObjectProviderRegistry} with some reasonable defaults. Any changes that + * Spring Security makes to the registry happen in this method. * - * To override those defaults, call {@link #requireInitialize(Consumer)} and change the registry: + * To override those defaults, call {@link #requireInitialize(Consumer)} and change the + * registry: * *
          * 	static {
        @@ -59,45 +63,50 @@ import static org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport.setP
          *
          * {@link #requireInitialize(Consumer)} may only be called once per application.
          *
        - * If the application already initialized OpenSAML before {@link #requireInitialize(Consumer)} was called,
        - * then the configuration changes will not be applied and an exception will be thrown. The reason for this is to
        - * alert you to the fact that there are likely some initialization ordering problems in your application that
        - * would otherwise lead to an unpredictable state.
        + * If the application already initialized OpenSAML before
        + * {@link #requireInitialize(Consumer)} was called, then the configuration changes will
        + * not be applied and an exception will be thrown. The reason for this is to alert you to
        + * the fact that there are likely some initialization ordering problems in your
        + * application that would otherwise lead to an unpredictable state.
          *
        - * If you must change the registry's configuration in multiple places in your application, you are expected
        - * to handle the initialization ordering issues yourself instead of trying to call {@link #requireInitialize(Consumer)}
        - * multiple times.
        + * If you must change the registry's configuration in multiple places in your application,
        + * you are expected to handle the initialization ordering issues yourself instead of
        + * trying to call {@link #requireInitialize(Consumer)} multiple times.
          *
          * @author Josh Cummings
          * @since 5.4
          */
         public class OpenSamlInitializationService {
        +
         	private static final Log log = LogFactory.getLog(OpenSamlInitializationService.class);
        +
         	private static final AtomicBoolean initialized = new AtomicBoolean(false);
         
         	/**
         	 * Ready OpenSAML for use and configure it with reasonable defaults.
         	 *
        -	 * Initialization is guaranteed to happen only once per application. This method will passively return
        -	 * {@code false} if initialization already took place earlier in the application.
        -	 *
        -	 * @return whether or not initialization was performed. The first thread to initialize OpenSAML will
        -	 * return {@code true} while the rest will return {@code false}.
        +	 * Initialization is guaranteed to happen only once per application. This method will
        +	 * passively return {@code false} if initialization already took place earlier in the
        +	 * application.
        +	 * @return whether or not initialization was performed. The first thread to initialize
        +	 * OpenSAML will return {@code true} while the rest will return {@code false}.
         	 * @throws Saml2Exception if OpenSAML failed to initialize
         	 */
         	public static boolean initialize() {
        -		return initialize(registry -> {});
        +		return initialize(registry -> {
        +		});
         	}
         
         	/**
        -	 * Ready OpenSAML for use, configure it with reasonable defaults, and modify the {@link XMLObjectProviderRegistry}
        -	 * using the provided {@link Consumer}.
        +	 * Ready OpenSAML for use, configure it with reasonable defaults, and modify the
        +	 * {@link XMLObjectProviderRegistry} using the provided {@link Consumer}.
         	 *
        -	 * Initialization is guaranteed to happen only once per application. This method will throw an exception
        -	 * if initialization already took place earlier in the application.
        -	 *
        -	 * @param registryConsumer the {@link Consumer} to further configure the {@link XMLObjectProviderRegistry}
        -	 * @throws Saml2Exception if initialization already happened previously or if OpenSAML failed to initialize
        +	 * Initialization is guaranteed to happen only once per application. This method will
        +	 * throw an exception if initialization already took place earlier in the application.
        +	 * @param registryConsumer the {@link Consumer} to further configure the
        +	 * {@link XMLObjectProviderRegistry}
        +	 * @throws Saml2Exception if initialization already happened previously or if OpenSAML
        +	 * failed to initialize
         	 */
         	public static void requireInitialize(Consumer registryConsumer) {
         		if (!initialize(registryConsumer)) {
        @@ -111,7 +120,8 @@ public class OpenSamlInitializationService {
         
         			try {
         				InitializationService.initialize();
        -			} catch (Exception e) {
        +			}
        +			catch (Exception e) {
         				throw new Saml2Exception(e);
         			}
         
        @@ -129,7 +139,8 @@ public class OpenSamlInitializationService {
         
         			try {
         				parserPool.initialize();
        -			} catch (Exception e) {
        +			}
        +			catch (Exception e) {
         				throw new Saml2Exception(e);
         			}
         			setParserPool(parserPool);
        @@ -138,9 +149,11 @@ public class OpenSamlInitializationService {
         
         			log.debug("Initialized OpenSAML");
         			return true;
        -		} else {
        +		}
        +		else {
         			log.debug("Refused to re-initialize OpenSAML");
         			return false;
         		}
         	}
        +
         }
        diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2Error.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2Error.java
        index 94b0450276..92338f5551 100644
        --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2Error.java
        +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2Error.java
        @@ -25,21 +25,23 @@ import org.springframework.util.Assert;
          * A representation of an SAML 2.0 Error.
          *
          * 

        - * At a minimum, an error response will contain an error code. - * The commonly used error code are defined in this class - * or a new codes can be defined in the future as arbitrary strings. + * At a minimum, an error response will contain an error code. The commonly used error + * code are defined in this class or a new codes can be defined in the future as arbitrary + * strings. *

        + * * @since 5.2 */ public class Saml2Error implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private final String errorCode; + private final String description; /** * Constructs a {@code Saml2Error} using the provided parameters. - * * @param errorCode the error code * @param description the error description */ @@ -51,7 +53,6 @@ public class Saml2Error implements Serializable { /** * Returns the error code. - * * @return the error code */ public final String getErrorCode() { @@ -60,7 +61,6 @@ public class Saml2Error implements Serializable { /** * Returns the error description. - * * @return the error description */ public final String getDescription() { @@ -69,7 +69,7 @@ public class Saml2Error implements Serializable { @Override public String toString() { - return "[" + this.getErrorCode() + "] " + - (this.getDescription() != null ? this.getDescription() : ""); + return "[" + this.getErrorCode() + "] " + (this.getDescription() != null ? this.getDescription() : ""); } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2ErrorCodes.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2ErrorCodes.java index 810c4338c7..63753f1121 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2ErrorCodes.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2ErrorCodes.java @@ -22,80 +22,84 @@ package org.springframework.security.saml2.core; * @since 5.2 */ public interface Saml2ErrorCodes { + /** - * SAML Data does not represent a SAML 2 Response object. - * A valid XML object was received, but that object was not a - * SAML 2 Response object of type {@code ResponseType} per specification + * SAML Data does not represent a SAML 2 Response object. A valid XML object was + * received, but that object was not a SAML 2 Response object of type + * {@code ResponseType} per specification * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=46 */ String UNKNOWN_RESPONSE_CLASS = "unknown_response_class"; + /** - * The response data is malformed or incomplete. - * An invalid XML object was received, and XML unmarshalling failed. + * The response data is malformed or incomplete. An invalid XML object was received, + * and XML unmarshalling failed. */ String MALFORMED_RESPONSE_DATA = "malformed_response_data"; + /** - * Response destination does not match the request URL. - * A SAML 2 response object was received at a URL that - * did not match the URL stored in the {code Destination} attribute - * in the Response object. + * Response destination does not match the request URL. A SAML 2 response object was + * received at a URL that did not match the URL stored in the {code Destination} + * attribute in the Response object. * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=38 */ String INVALID_DESTINATION = "invalid_destination"; + /** - * The assertion was not valid. - * The assertion used for authentication failed validation. - * Details around the failure will be present in the error description. + * The assertion was not valid. The assertion used for authentication failed + * validation. Details around the failure will be present in the error description. */ String INVALID_ASSERTION = "invalid_assertion"; + /** - * The signature of response or assertion was invalid. - * Either the response or the assertion was missing a signature - * or the signature could not be verified using the system's - * configured credentials. Most commonly the IDP's - * X509 certificate. + * The signature of response or assertion was invalid. Either the response or the + * assertion was missing a signature or the signature could not be verified using the + * system's configured credentials. Most commonly the IDP's X509 certificate. */ String INVALID_SIGNATURE = "invalid_signature"; + /** - * The assertion did not contain a subject element. - * The subject element, type SubjectType, contains - * a {@code NameID} or an {@code EncryptedID} that is used - * to assign the authenticated principal an identifier, - * typically a username. + * The assertion did not contain a subject element. The subject element, type + * SubjectType, contains a {@code NameID} or an {@code EncryptedID} that is used to + * assign the authenticated principal an identifier, typically a username. * * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=18 */ String SUBJECT_NOT_FOUND = "subject_not_found"; + /** - * The subject did not contain a user identifier - * The assertion contained a subject element, but the subject - * element did not have a {@code NameID} or {@code EncryptedID} - * element + * The subject did not contain a user identifier The assertion contained a subject + * element, but the subject element did not have a {@code NameID} or + * {@code EncryptedID} element * * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=18 */ String USERNAME_NOT_FOUND = "username_not_found"; + /** - * The system failed to decrypt an assertion or a name identifier. - * This error code will be thrown if the decryption of either a - * {@code EncryptedAssertion} or {@code EncryptedID} fails. + * The system failed to decrypt an assertion or a name identifier. This error code + * will be thrown if the decryption of either a {@code EncryptedAssertion} or + * {@code EncryptedID} fails. * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=17 */ String DECRYPTION_ERROR = "decryption_error"; + /** * An Issuer element contained a value that didn't * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=15 */ String INVALID_ISSUER = "invalid_issuer"; + /** - * An error happened during validation. - * Used when internal, non classified, errors are caught during the - * authentication process. + * An error happened during validation. Used when internal, non classified, errors are + * caught during the authentication process. */ String INTERNAL_VALIDATION_ERROR = "internal_validation_error"; + /** - * The relying party registration was not found. - * The registration ID did not correspond to any relying party registration. + * The relying party registration was not found. The registration ID did not + * correspond to any relying party registration. */ String RELYING_PARTY_REGISTRATION_NOT_FOUND = "relying_party_registration_not_found"; + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2X509Credential.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2X509Credential.java index 8569b390db..1aeb1649bf 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2X509Credential.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2X509Credential.java @@ -29,34 +29,35 @@ import static org.springframework.util.Assert.notNull; import static org.springframework.util.Assert.state; /** - * An object for holding a public certificate, any associated private key, and its intended - * - * usages - * - * (Line 584, Section 4.3 Credentials). + * An object for holding a public certificate, any associated private key, and its + * intended + * usages (Line 584, Section 4.3 Credentials). * * @since 5.4 * @author Filip Hanik * @author Josh Cummings */ public final class Saml2X509Credential { + public enum Saml2X509CredentialType { - VERIFICATION, - ENCRYPTION, - SIGNING, - DECRYPTION, + + VERIFICATION, ENCRYPTION, SIGNING, DECRYPTION, + } private final PrivateKey privateKey; + private final X509Certificate certificate; + private final Set credentialTypes; /** * Creates a {@link Saml2X509Credential} using the provided parameters - * * @param certificate the credential's public certificiate - * @param types the credential's intended usages, must be one of {@link Saml2X509CredentialType#VERIFICATION} or - * {@link Saml2X509CredentialType#ENCRYPTION} or both. + * @param types the credential's intended usages, must be one of + * {@link Saml2X509CredentialType#VERIFICATION} or + * {@link Saml2X509CredentialType#ENCRYPTION} or both. */ public Saml2X509Credential(X509Certificate certificate, Saml2X509CredentialType... types) { this(null, false, certificate, types); @@ -65,11 +66,11 @@ public final class Saml2X509Credential { /** * Creates a {@link Saml2X509Credential} using the provided parameters - * * @param privateKey the credential's private key * @param certificate the credential's public certificate - * @param types the credential's intended usages, must be one of {@link Saml2X509CredentialType#SIGNING} or - * {@link Saml2X509CredentialType#DECRYPTION} or both. + * @param types the credential's intended usages, must be one of + * {@link Saml2X509CredentialType#SIGNING} or + * {@link Saml2X509CredentialType#DECRYPTION} or both. */ public Saml2X509Credential(PrivateKey privateKey, X509Certificate certificate, Saml2X509CredentialType... types) { this(privateKey, true, certificate, types); @@ -78,7 +79,6 @@ public final class Saml2X509Credential { /** * Creates a {@link Saml2X509Credential} using the provided parameters - * * @param privateKey the credential's private key * @param certificate the credential's public certificate * @param types the credential's intended usages @@ -125,10 +125,7 @@ public final class Saml2X509Credential { return new Saml2X509Credential(privateKey, certificate, Saml2X509Credential.Saml2X509CredentialType.SIGNING); } - private Saml2X509Credential( - PrivateKey privateKey, - boolean keyRequired, - X509Certificate certificate, + private Saml2X509Credential(PrivateKey privateKey, boolean keyRequired, X509Certificate certificate, Saml2X509CredentialType... types) { notNull(certificate, "certificate cannot be null"); notEmpty(types, "credentials types cannot be empty"); @@ -142,7 +139,6 @@ public final class Saml2X509Credential { /** * Get the private key for this credential - * * @return the private key, may be null * @see {@link #Saml2X509Credential(PrivateKey, X509Certificate, Saml2X509CredentialType...)} */ @@ -152,7 +148,6 @@ public final class Saml2X509Credential { /** * Get the public certificate for this credential - * * @return the public certificate */ public X509Certificate getCertificate() { @@ -161,7 +156,6 @@ public final class Saml2X509Credential { /** * Indicate whether this credential can be used for signing - * * @return true if the credential has a {@link Saml2X509CredentialType#SIGNING} type */ public boolean isSigningCredential() { @@ -170,8 +164,8 @@ public final class Saml2X509Credential { /** * Indicate whether this credential can be used for decryption - * - * @return true if the credential has a {@link Saml2X509CredentialType#DECRYPTION} type + * @return true if the credential has a {@link Saml2X509CredentialType#DECRYPTION} + * type */ public boolean isDecryptionCredential() { return getCredentialTypes().contains(Saml2X509CredentialType.DECRYPTION); @@ -179,8 +173,8 @@ public final class Saml2X509Credential { /** * Indicate whether this credential can be used for verification - * - * @return true if the credential has a {@link Saml2X509CredentialType#VERIFICATION} type + * @return true if the credential has a {@link Saml2X509CredentialType#VERIFICATION} + * type */ public boolean isVerificationCredential() { return getCredentialTypes().contains(Saml2X509CredentialType.VERIFICATION); @@ -188,8 +182,8 @@ public final class Saml2X509Credential { /** * Indicate whether this credential can be used for encryption - * - * @return true if the credential has a {@link Saml2X509CredentialType#ENCRYPTION} type + * @return true if the credential has a {@link Saml2X509CredentialType#ENCRYPTION} + * type */ public boolean isEncryptionCredential() { return getCredentialTypes().contains(Saml2X509CredentialType.ENCRYPTION); @@ -197,7 +191,6 @@ public final class Saml2X509Credential { /** * List all this credential's intended usages - * * @return the set of this credential's intended usages */ public Set getCredentialTypes() { @@ -206,12 +199,13 @@ public final class Saml2X509Credential { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; Saml2X509Credential that = (Saml2X509Credential) o; - return Objects.equals(this.privateKey, that.privateKey) && - this.certificate.equals(that.certificate) && - this.credentialTypes.equals(that.credentialTypes); + return Objects.equals(this.privateKey, that.privateKey) && this.certificate.equals(that.certificate) + && this.credentialTypes.equals(that.credentialTypes); } @Override @@ -228,7 +222,8 @@ public final class Saml2X509Credential { break; } } - state(valid, () -> usage +" is not a valid usage for this credential"); + state(valid, () -> usage + " is not a valid usage for this credential"); } } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/credentials/Saml2X509Credential.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/credentials/Saml2X509Credential.java index a83fc06e75..f329ff08f8 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/credentials/Saml2X509Credential.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/credentials/Saml2X509Credential.java @@ -32,34 +32,41 @@ import static org.springframework.util.Assert.state; * Saml2X509Credential is meant to hold an X509 certificate, or an X509 certificate and a * private key. Per: * https://www.oasis-open.org/committees/download.php/8958/sstc-saml-implementation-guidelines-draft-01.pdf - * Line: 584, Section 4.3 Credentials Used for both signing, signature verification and encryption/decryption + * Line: 584, Section 4.3 Credentials Used for both signing, signature verification and + * encryption/decryption * * @since 5.2 - * @deprecated Use {@link org.springframework.security.saml2.core.Saml2X509Credential} instead + * @deprecated Use {@link org.springframework.security.saml2.core.Saml2X509Credential} + * instead */ @Deprecated public class Saml2X509Credential { + /** - * @deprecated Use {@link org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType} instead + * @deprecated Use + * {@link org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType} + * instead */ @Deprecated public enum Saml2X509CredentialType { - VERIFICATION, - ENCRYPTION, - SIGNING, - DECRYPTION, + + VERIFICATION, ENCRYPTION, SIGNING, DECRYPTION, + } private final PrivateKey privateKey; + private final X509Certificate certificate; + private final Set credentialTypes; /** * Creates a Saml2X509Credentials representing Identity Provider credentials for * verification, encryption or both. * @param certificate an IDP X509Certificate, cannot be null - * @param types credential types, must be one of {@link Saml2X509CredentialType#VERIFICATION} or - * {@link Saml2X509CredentialType#ENCRYPTION} or both. + * @param types credential types, must be one of + * {@link Saml2X509CredentialType#VERIFICATION} or + * {@link Saml2X509CredentialType#ENCRYPTION} or both. */ public Saml2X509Credential(X509Certificate certificate, Saml2X509CredentialType... types) { this(null, false, certificate, types); @@ -70,9 +77,11 @@ public class Saml2X509Credential { * Creates a Saml2X509Credentials representing Service Provider credentials for * signing, decryption or both. * @param privateKey a private key used for signing or decryption, cannot be null - * @param certificate an SP X509Certificate shared with identity providers, cannot be null - * @param types credential types, must be one of {@link Saml2X509CredentialType#SIGNING} or - * {@link Saml2X509CredentialType#DECRYPTION} or both. + * @param certificate an SP X509Certificate shared with identity providers, cannot be + * null + * @param types credential types, must be one of + * {@link Saml2X509CredentialType#SIGNING} or + * {@link Saml2X509CredentialType#DECRYPTION} or both. */ public Saml2X509Credential(PrivateKey privateKey, X509Certificate certificate, Saml2X509CredentialType... types) { this(privateKey, true, certificate, types); @@ -87,10 +96,7 @@ public class Saml2X509Credential { this.credentialTypes = types; } - private Saml2X509Credential( - PrivateKey privateKey, - boolean keyRequired, - X509Certificate certificate, + private Saml2X509Credential(PrivateKey privateKey, boolean keyRequired, X509Certificate certificate, Saml2X509CredentialType... types) { notNull(certificate, "certificate cannot be null"); notEmpty(types, "credentials types cannot be empty"); @@ -102,10 +108,9 @@ public class Saml2X509Credential { this.credentialTypes = new LinkedHashSet<>(asList(types)); } - /** - * Returns true if the credential has a private key and can be used for signing, the types will contain - * {@link Saml2X509CredentialType#SIGNING}. + * Returns true if the credential has a private key and can be used for signing, the + * types will contain {@link Saml2X509CredentialType#SIGNING}. * @return true if the credential is a {@link Saml2X509CredentialType#SIGNING} type */ public boolean isSigningCredential() { @@ -113,8 +118,8 @@ public class Saml2X509Credential { } /** - * Returns true if the credential has a private key and can be used for decryption, the types will contain - * {@link Saml2X509CredentialType#DECRYPTION}. + * Returns true if the credential has a private key and can be used for decryption, + * the types will contain {@link Saml2X509CredentialType#DECRYPTION}. * @return true if the credential is a {@link Saml2X509CredentialType#DECRYPTION} type */ public boolean isDecryptionCredential() { @@ -122,18 +127,20 @@ public class Saml2X509Credential { } /** - * Returns true if the credential has a certificate and can be used for signature verification, the types will contain - * {@link Saml2X509CredentialType#VERIFICATION}. - * @return true if the credential is a {@link Saml2X509CredentialType#VERIFICATION} type + * Returns true if the credential has a certificate and can be used for signature + * verification, the types will contain {@link Saml2X509CredentialType#VERIFICATION}. + * @return true if the credential is a {@link Saml2X509CredentialType#VERIFICATION} + * type */ public boolean isSignatureVerficationCredential() { return getCredentialTypes().contains(Saml2X509CredentialType.VERIFICATION); } /** - * Returns true if the credential has a certificate and can be used for signature verification, the types will contain - * {@link Saml2X509CredentialType#VERIFICATION}. - * @return true if the credential is a {@link Saml2X509CredentialType#VERIFICATION} type + * Returns true if the credential has a certificate and can be used for signature + * verification, the types will contain {@link Saml2X509CredentialType#VERIFICATION}. + * @return true if the credential is a {@link Saml2X509CredentialType#VERIFICATION} + * type */ public boolean isEncryptionCredential() { return getCredentialTypes().contains(Saml2X509CredentialType.ENCRYPTION); @@ -166,12 +173,13 @@ public class Saml2X509Credential { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; Saml2X509Credential that = (Saml2X509Credential) o; - return Objects.equals(this.privateKey, that.privateKey) && - this.certificate.equals(that.certificate) && - this.credentialTypes.equals(that.credentialTypes); + return Objects.equals(this.privateKey, that.privateKey) && this.certificate.equals(that.certificate) + && this.credentialTypes.equals(that.credentialTypes); } @Override @@ -188,7 +196,8 @@ public class Saml2X509Credential { break; } } - state(valid, () -> usage +" is not a valid usage for this credential"); + state(valid, () -> usage + " is not a valid usage for this credential"); } } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/AbstractSaml2AuthenticationRequest.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/AbstractSaml2AuthenticationRequest.java index 99ef2cdc22..3b3b6536fc 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/AbstractSaml2AuthenticationRequest.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/AbstractSaml2AuthenticationRequest.java @@ -23,11 +23,12 @@ import java.nio.charset.Charset; /** * Data holder for {@code AuthNRequest} parameters to be sent using either the - * {@link Saml2MessageBinding#POST} or {@link Saml2MessageBinding#REDIRECT} binding. - * Data will be encoded and possibly deflated, but will not be escaped for transport, - * ie URL encoded, {@link org.springframework.web.util.UriUtils#encode(String, Charset)} - * or HTML encoded, {@link org.springframework.web.util.HtmlUtils#htmlEscape(String)}. - * https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf (line 2031) + * {@link Saml2MessageBinding#POST} or {@link Saml2MessageBinding#REDIRECT} binding. Data + * will be encoded and possibly deflated, but will not be escaped for transport, ie URL + * encoded, {@link org.springframework.web.util.UriUtils#encode(String, Charset)} or HTML + * encoded, {@link org.springframework.web.util.HtmlUtils#htmlEscape(String)}. + * https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf + * (line 2031) * * @see Saml2AuthenticationRequestFactory#createPostAuthenticationRequest(Saml2AuthenticationRequestContext) * @see Saml2AuthenticationRequestFactory#createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext) @@ -36,19 +37,20 @@ import java.nio.charset.Charset; abstract class AbstractSaml2AuthenticationRequest { private final String samlRequest; + private final String relayState; + private final String authenticationRequestUri; /** * Mandatory constructor for the {@link AbstractSaml2AuthenticationRequest} - * @param samlRequest - the SAMLRequest XML data, SAML encoded, cannot be empty or null + * @param samlRequest - the SAMLRequest XML data, SAML encoded, cannot be empty or + * null * @param relayState - RelayState value that accompanies the request, may be null - * @param authenticationRequestUri - The authenticationRequestUri, a URL, where to send the XML message, cannot be empty or null + * @param authenticationRequestUri - The authenticationRequestUri, a URL, where to + * send the XML message, cannot be empty or null */ - AbstractSaml2AuthenticationRequest( - String samlRequest, - String relayState, - String authenticationRequestUri) { + AbstractSaml2AuthenticationRequest(String samlRequest, String relayState, String authenticationRequestUri) { Assert.hasText(samlRequest, "samlRequest cannot be null or empty"); Assert.hasText(authenticationRequestUri, "authenticationRequestUri cannot be null or empty"); this.authenticationRequestUri = authenticationRequestUri; @@ -57,9 +59,10 @@ abstract class AbstractSaml2AuthenticationRequest { } /** - * Returns the AuthNRequest XML value to be sent. This value is already encoded for transport. - * If {@link #getBinding()} is {@link Saml2MessageBinding#REDIRECT} the value is deflated and SAML encoded. - * If {@link #getBinding()} is {@link Saml2MessageBinding#POST} the value is SAML encoded. + * Returns the AuthNRequest XML value to be sent. This value is already encoded for + * transport. If {@link #getBinding()} is {@link Saml2MessageBinding#REDIRECT} the + * value is deflated and SAML encoded. If {@link #getBinding()} is + * {@link Saml2MessageBinding#POST} the value is SAML encoded. * @return the SAMLRequest parameter value */ public String getSamlRequest() { @@ -83,8 +86,9 @@ abstract class AbstractSaml2AuthenticationRequest { } /** - * Returns the binding this AuthNRequest will be sent and - * encoded with. If {@link Saml2MessageBinding#REDIRECT} is used, the DEFLATE encoding will be automatically applied. + * Returns the binding this AuthNRequest will be sent and encoded with. If + * {@link Saml2MessageBinding#REDIRECT} is used, the DEFLATE encoding will be + * automatically applied. * @return the binding this message will be sent with. */ public abstract Saml2MessageBinding getBinding(); @@ -93,8 +97,11 @@ abstract class AbstractSaml2AuthenticationRequest { * A builder for {@link AbstractSaml2AuthenticationRequest} and its subclasses. */ static class Builder> { + String authenticationRequestUri; + String samlRequest; + String relayState; protected Builder() { @@ -109,12 +116,10 @@ abstract class AbstractSaml2AuthenticationRequest { return (T) this; } - /** * Sets the {@code RelayState} parameter that will accompany this AuthNRequest - * - * @param relayState the relay state value, unencoded. if null or empty, the parameter will be removed from the - * map. + * @param relayState the relay state value, unencoded. if null or empty, the + * parameter will be removed from the map. * @return this object */ public T relayState(String relayState) { @@ -124,7 +129,6 @@ abstract class AbstractSaml2AuthenticationRequest { /** * Sets the {@code SAMLRequest} parameter that will accompany this AuthNRequest - * * @param samlRequest the SAMLRequest parameter. * @return this object */ @@ -134,8 +138,8 @@ abstract class AbstractSaml2AuthenticationRequest { } /** - * Sets the {@code authenticationRequestUri}, a URL that will receive the AuthNRequest message - * + * Sets the {@code authenticationRequestUri}, a URL that will receive the + * AuthNRequest message * @param authenticationRequestUri the relay state value, unencoded. * @return this object */ @@ -143,6 +147,7 @@ abstract class AbstractSaml2AuthenticationRequest { this.authenticationRequestUri = authenticationRequestUri; return _this(); } + } } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/DefaultSaml2AuthenticatedPrincipal.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/DefaultSaml2AuthenticatedPrincipal.java index b474c20aed..5223c084ec 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/DefaultSaml2AuthenticatedPrincipal.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/DefaultSaml2AuthenticatedPrincipal.java @@ -31,6 +31,7 @@ import java.util.Map; public class DefaultSaml2AuthenticatedPrincipal implements Saml2AuthenticatedPrincipal, Serializable { private final String name; + private final Map> attributes; public DefaultSaml2AuthenticatedPrincipal(String name, Map> attributes) { @@ -50,4 +51,5 @@ public class DefaultSaml2AuthenticatedPrincipal implements Saml2AuthenticatedPri public Map> getAttributes() { return this.attributes; } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java index e2c8bdb35c..c31f1f8f27 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java @@ -129,39 +129,48 @@ import static org.springframework.security.saml2.core.Saml2ErrorCodes.SUBJECT_NO import static org.springframework.util.Assert.notNull; /** - * Implementation of {@link AuthenticationProvider} for SAML authentications when receiving a - * {@code Response} object containing an {@code Assertion}. This implementation uses - * the {@code OpenSAML 3} library. + * Implementation of {@link AuthenticationProvider} for SAML authentications when + * receiving a {@code Response} object containing an {@code Assertion}. This + * implementation uses the {@code OpenSAML 3} library. * *

        - * The {@link OpenSamlAuthenticationProvider} supports {@link Saml2AuthenticationToken} objects - * that contain a SAML response in its decoded XML format {@link Saml2AuthenticationToken#getSaml2Response()} - * along with the information about the asserting party, the identity provider (IDP), as well as - * the relying party, the service provider (SP, this application). + * The {@link OpenSamlAuthenticationProvider} supports {@link Saml2AuthenticationToken} + * objects that contain a SAML response in its decoded XML format + * {@link Saml2AuthenticationToken#getSaml2Response()} along with the information about + * the asserting party, the identity provider (IDP), as well as the relying party, the + * service provider (SP, this application). *

        *

        - * The {@link Saml2AuthenticationToken} will be processed into a SAML Response object. - * The SAML response object can be signed. If the Response is signed, a signature will not be required on the assertion. + * The {@link Saml2AuthenticationToken} will be processed into a SAML Response object. The + * SAML response object can be signed. If the Response is signed, a signature will not be + * required on the assertion. *

        *

        - * While a response object can contain a list of assertion, this provider will only leverage - * the first valid assertion for the purpose of authentication. Assertions that do not pass validation - * will be ignored. If no valid assertions are found a {@link Saml2AuthenticationException} is thrown. + * While a response object can contain a list of assertion, this provider will only + * leverage the first valid assertion for the purpose of authentication. Assertions that + * do not pass validation will be ignored. If no valid assertions are found a + * {@link Saml2AuthenticationException} is thrown. *

        *

        - * This provider supports two types of encrypted SAML elements - *

        - * If the assertion is encrypted, then signature validation on the assertion is no longer required. + * This provider supports two types of encrypted SAML elements + * + * If the assertion is encrypted, then signature validation on the assertion is no longer + * required. *

        *

        - * This provider does not perform an X509 certificate validation on the configured asserting party, IDP, verification - * certificates. + * This provider does not perform an X509 certificate validation on the configured + * asserting party, IDP, verification certificates. *

        + * * @since 5.2 - * @see SAML 2 StatusResponse + * @see SAML 2 + * StatusResponse * @see OpenSAML 3 */ public final class OpenSamlAuthenticationProvider implements AuthenticationProvider { @@ -173,32 +182,35 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi private static Log logger = LogFactory.getLog(OpenSamlAuthenticationProvider.class); private final XMLObjectProviderRegistry registry; + private final ResponseUnmarshaller responseUnmarshaller; + private final ParserPool parserPool; - private Converter> authoritiesExtractor = - (a -> singletonList(new SimpleGrantedAuthority("ROLE_USER"))); + private Converter> authoritiesExtractor = (a -> singletonList( + new SimpleGrantedAuthority("ROLE_USER"))); + private GrantedAuthoritiesMapper authoritiesMapper = (a -> a); + private Duration responseTimeValidationSkew = Duration.ofMinutes(5); - private Function> authenticationConverter = - token -> response -> { - Assertion assertion = CollectionUtils.firstElement(response.getAssertions()); - String username = assertion.getSubject().getNameID().getValue(); - Map> attributes = getAssertionAttributes(assertion); - return new Saml2Authentication( - new DefaultSaml2AuthenticatedPrincipal(username, attributes), token.getSaml2Response(), - this.authoritiesMapper.mapAuthorities(getAssertionAuthorities(assertion))); - }; + private Function> authenticationConverter = token -> response -> { + Assertion assertion = CollectionUtils.firstElement(response.getAssertions()); + String username = assertion.getSubject().getNameID().getValue(); + Map> attributes = getAssertionAttributes(assertion); + return new Saml2Authentication(new DefaultSaml2AuthenticatedPrincipal(username, attributes), + token.getSaml2Response(), this.authoritiesMapper.mapAuthorities(getAssertionAuthorities(assertion))); + }; + + private Converter signatureTrustEngineConverter = new SignatureTrustEngineConverter(); + + private Converter assertionValidatorConverter = new SAML20AssertionValidatorConverter(); + + private Collection conditionValidators = Collections + .singleton(new AudienceRestrictionConditionValidator()); + + private Converter validationContextConverter = new ValidationContextConverter(); - private Converter signatureTrustEngineConverter = - new SignatureTrustEngineConverter(); - private Converter assertionValidatorConverter = - new SAML20AssertionValidatorConverter(); - private Collection conditionValidators = - Collections.singleton(new AudienceRestrictionConditionValidator()); - private Converter validationContextConverter = - new ValidationContextConverter(); private Converter decrypterConverter = new DecrypterConverter(); /** @@ -212,48 +224,47 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi } /** - * Set the the collection of {@link ConditionValidator}s used when validating an assertion. - * + * Set the the collection of {@link ConditionValidator}s used when validating an + * assertion. * @param conditionValidators the collection of validators to use * @since 5.4 */ - public void setConditionValidators( - Collection conditionValidators) { + public void setConditionValidators(Collection conditionValidators) { Assert.notEmpty(conditionValidators, "conditionValidators cannot be empty"); this.conditionValidators = conditionValidators; } /** - * Set the strategy for retrieving the {@link ValidationContext} used when - * validating an assertion. - * + * Set the strategy for retrieving the {@link ValidationContext} used when validating + * an assertion. * @param validationContextConverter the strategy to use * @since 5.4 */ - public void setValidationContextConverter( - Converter validationContextConverter) { + public void setValidationContextConverter(Converter validationContextConverter) { Assert.notNull(validationContextConverter, "validationContextConverter cannot be empty"); this.validationContextConverter = validationContextConverter; } /** - * Sets the {@link Converter} used for extracting assertion attributes that - * can be mapped to authorities. - * @param authoritiesExtractor the {@code Converter} used for mapping the - * assertion attributes to authorities + * Sets the {@link Converter} used for extracting assertion attributes that can be + * mapped to authorities. + * @param authoritiesExtractor the {@code Converter} used for mapping the assertion + * attributes to authorities */ - public void setAuthoritiesExtractor(Converter> authoritiesExtractor) { + public void setAuthoritiesExtractor( + Converter> authoritiesExtractor) { Assert.notNull(authoritiesExtractor, "authoritiesExtractor cannot be null"); this.authoritiesExtractor = authoritiesExtractor; } /** - * Sets the {@link GrantedAuthoritiesMapper} used for mapping assertion attributes - * to a new set of authorities which will be associated to the {@link Saml2Authentication}. - * Note: This implementation is only retrieving - * @param authoritiesMapper the {@link GrantedAuthoritiesMapper} used for mapping the user's authorities + * Sets the {@link GrantedAuthoritiesMapper} used for mapping assertion attributes to + * a new set of authorities which will be associated to the + * {@link Saml2Authentication}. Note: This implementation is only retrieving + * @param authoritiesMapper the {@link GrantedAuthoritiesMapper} used for mapping the + * user's authorities */ public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) { notNull(authoritiesMapper, "authoritiesMapper cannot be null"); @@ -271,8 +282,7 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi /** * @param authentication the authentication request object, must be of type - * {@link Saml2AuthenticationToken} - * + * {@link Saml2AuthenticationToken} * @return {@link Saml2Authentication} if the assertion is valid * @throws AuthenticationException if a validation exception occurs */ @@ -284,9 +294,11 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi Response response = parse(serializedResponse); process(token, response); return this.authenticationConverter.apply(token).convert(response); - } catch (Saml2AuthenticationException e) { + } + catch (Saml2AuthenticationException e) { throw e; - } catch (Exception e) { + } + catch (Exception e) { throw authException(INTERNAL_VALIDATION_ERROR, e.getMessage(), e); } } @@ -305,8 +317,8 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi private Response parse(String response) throws Saml2Exception, Saml2AuthenticationException { try { - Document document = this.parserPool.parse(new ByteArrayInputStream( - response.getBytes(StandardCharsets.UTF_8))); + Document document = this.parserPool + .parse(new ByteArrayInputStream(response.getBytes(StandardCharsets.UTF_8))); Element element = document.getDocumentElement(); return (Response) this.responseUnmarshaller.unmarshall(element); } @@ -327,8 +339,8 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi Decrypter decrypter = this.decrypterConverter.convert(token); List assertions = decryptAssertions(decrypter, response); if (!isSigned(responseSigned, assertions)) { - throw authException(INVALID_SIGNATURE, "Either the response or one of the assertions is unsigned. " + - "Please either sign the response or all of the assertions."); + throw authException(INVALID_SIGNATURE, "Either the response or one of the assertions is unsigned. " + + "Please either sign the response or all of the assertions."); } validationExceptions.putAll(validateAssertions(token, response)); @@ -343,12 +355,15 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi if (logger.isDebugEnabled()) { logger.debug("Successfully processed SAML Response [" + response.getID() + "]"); } - } else { + } + else { if (logger.isTraceEnabled()) { - logger.debug("Found " + validationExceptions.size() + " validation errors in SAML response [" + response.getID() + "]: " + - validationExceptions.values()); - } else if (logger.isDebugEnabled()) { - logger.debug("Found " + validationExceptions.size() + " validation errors in SAML response [" + response.getID() + "]"); + logger.debug("Found " + validationExceptions.size() + " validation errors in SAML response [" + + response.getID() + "]: " + validationExceptions.values()); + } + else if (logger.isDebugEnabled()) { + logger.debug("Found " + validationExceptions.size() + " validation errors in SAML response [" + + response.getID() + "]"); } } @@ -357,8 +372,8 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi } } - private Map validateResponse - (Saml2AuthenticationToken token, Response response) { + private Map validateResponse(Saml2AuthenticationToken token, + Response response) { Map validationExceptions = new HashMap<>(); String issuer = response.getIssuer().getValue(); @@ -367,7 +382,8 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); try { profileValidator.validate(response.getSignature()); - } catch (Exception e) { + } + catch (Exception e) { validationExceptions.put(INVALID_SIGNATURE, authException(INVALID_SIGNATURE, "Invalid signature for SAML Response [" + response.getID() + "]: ", e)); } @@ -375,13 +391,15 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi try { CriteriaSet criteriaSet = new CriteriaSet(); criteriaSet.add(new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(issuer))); - criteriaSet.add(new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion(SAMLConstants.SAML20P_NS))); + criteriaSet.add( + new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion(SAMLConstants.SAML20P_NS))); criteriaSet.add(new EvaluableUsageCredentialCriterion(new UsageCriterion(UsageType.SIGNING))); if (!this.signatureTrustEngineConverter.convert(token).validate(response.getSignature(), criteriaSet)) { validationExceptions.put(INVALID_SIGNATURE, authException(INVALID_SIGNATURE, "Invalid signature for SAML Response [" + response.getID() + "]")); } - } catch (Exception e) { + } + catch (Exception e) { validationExceptions.put(INVALID_SIGNATURE, authException(INVALID_SIGNATURE, "Invalid signature for SAML Response [" + response.getID() + "]: ", e)); } @@ -403,14 +421,14 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi return validationExceptions; } - private List decryptAssertions - (Decrypter decrypter, Response response) { + private List decryptAssertions(Decrypter decrypter, Response response) { List assertions = new ArrayList<>(); for (EncryptedAssertion encryptedAssertion : response.getEncryptedAssertions()) { try { Assertion assertion = decrypter.decrypt(encryptedAssertion); assertions.add(assertion); - } catch (DecryptionException e) { + } + catch (DecryptionException e) { throw authException(DECRYPTION_ERROR, e.getMessage(), e); } } @@ -418,8 +436,8 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi return response.getAssertions(); } - private Map validateAssertions - (Saml2AuthenticationToken token, Response response) { + private Map validateAssertions(Saml2AuthenticationToken token, + Response response) { List assertions = response.getAssertions(); if (assertions.isEmpty()) { throw authException(MALFORMED_RESPONSE_DATA, "No assertions found in response."); @@ -444,10 +462,10 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi context.getValidationFailureMessage()); validationExceptions.put(INVALID_ASSERTION, authException(INVALID_ASSERTION, message)); } - } catch (Exception e) { - String message = String.format("Invalid assertion [%s] for SAML response [%s]: %s", - assertion.getID(), ((Response) assertion.getParent()).getID(), - e.getMessage()); + } + catch (Exception e) { + String message = String.format("Invalid assertion [%s] for SAML response [%s]: %s", assertion.getID(), + ((Response) assertion.getParent()).getID(), e.getMessage()); validationExceptions.put(INVALID_ASSERTION, authException(INVALID_ASSERTION, message, e)); } } @@ -480,7 +498,8 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi NameID nameId = (NameID) decrypter.decrypt(assertion.getSubject().getEncryptedID()); assertion.getSubject().setNameID(nameId); return nameId; - } catch (DecryptionException e) { + } + catch (DecryptionException e) { throw authException(DECRYPTION_ERROR, e.getMessage(), e); } } @@ -534,19 +553,22 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi try { Element element = marshaller.marshall(xsAny); return SerializeSupport.nodeToString(element); - } catch (MarshallingException e) { + } + catch (MarshallingException e) { throw new Saml2Exception(e); } } return xsAny.getTextContent(); } - private static class SignatureTrustEngineConverter implements Converter { + private static class SignatureTrustEngineConverter + implements Converter { @Override public SignatureTrustEngine convert(Saml2AuthenticationToken token) { Set credentials = new HashSet<>(); - Collection keys = token.getRelyingPartyRegistration().getAssertingPartyDetails().getVerificationX509Credentials(); + Collection keys = token.getRelyingPartyRegistration().getAssertingPartyDetails() + .getVerificationX509Credentials(); for (Saml2X509Credential key : keys) { BasicX509Credential cred = new BasicX509Credential(key.getCertificate()); cred.setUsageType(UsageType.SIGNING); @@ -554,11 +576,10 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi credentials.add(cred); } CredentialResolver credentialsResolver = new CollectionCredentialResolver(credentials); - return new ExplicitKeySignatureTrustEngine( - credentialsResolver, - DefaultSecurityConfigurationBootstrap.buildBasicInlineKeyInfoCredentialResolver() - ); + return new ExplicitKeySignatureTrustEngine(credentialsResolver, + DefaultSecurityConfigurationBootstrap.buildBasicInlineKeyInfoCredentialResolver()); } + } private class ValidationContextConverter implements Converter { @@ -571,14 +592,19 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi params.put(CLOCK_SKEW, OpenSamlAuthenticationProvider.this.responseTimeValidationSkew.toMillis()); params.put(COND_VALID_AUDIENCES, singleton(audience)); params.put(SC_VALID_RECIPIENTS, singleton(recipient)); - params.put(SIGNATURE_REQUIRED, false); // this verification is performed earlier + params.put(SIGNATURE_REQUIRED, false); // this verification is performed + // earlier return new ValidationContext(params); } + } private class SAML20AssertionValidatorConverter implements Converter { + private final Collection subjects = new ArrayList<>(); + private final Collection statements = new ArrayList<>(); + private final SignaturePrevalidator validator = new SAMLSignatureProfileValidator(); SAML20AssertionValidatorConverter() { @@ -595,22 +621,19 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi @Override public SAML20AssertionValidator convert(Tuple tuple) { - Collection conditions = - OpenSamlAuthenticationProvider.this.conditionValidators; + Collection conditions = OpenSamlAuthenticationProvider.this.conditionValidators; return new SAML20AssertionValidator(conditions, this.subjects, this.statements, OpenSamlAuthenticationProvider.this.signatureTrustEngineConverter.convert(tuple.authentication), this.validator); } + } private static class DecrypterConverter implements Converter { + private final EncryptedKeyResolver encryptedKeyResolver = new ChainingEncryptedKeyResolver( - asList( - new InlineEncryptedKeyResolver(), - new EncryptedElementTypeEncryptedKeyResolver(), - new SimpleRetrievalMethodEncryptedKeyResolver() - ) - ); + asList(new InlineEncryptedKeyResolver(), new EncryptedElementTypeEncryptedKeyResolver(), + new SimpleRetrievalMethodEncryptedKeyResolver())); @Override public Decrypter convert(Saml2AuthenticationToken token) { @@ -624,6 +647,7 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi decrypter.setRootInNewDocument(true); return decrypter; } + } private static Saml2Error validationError(String code, String description) { @@ -643,12 +667,15 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi } /** - * A tuple containing the authentication token and the associated OpenSAML {@link Response}. + * A tuple containing the authentication token and the associated OpenSAML + * {@link Response}. * * @since 5.4 */ public static class Tuple { + private final Saml2AuthenticationToken authentication; + private final Response response; private Tuple(Saml2AuthenticationToken authentication, Response response) { @@ -663,5 +690,7 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi public Response getResponse() { return this.response; } + } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactory.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactory.java index f35686bbc2..9b23d8e37e 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactory.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactory.java @@ -70,6 +70,7 @@ import static org.springframework.util.StringUtils.hasText; * @since 5.2 */ public class OpenSamlAuthenticationRequestFactory implements Saml2AuthenticationRequestFactory { + static { OpenSamlInitializationService.initialize(); } @@ -77,19 +78,20 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication private Clock clock = Clock.systemUTC(); private AuthnRequestMarshaller marshaller; + private AuthnRequestBuilder authnRequestBuilder; + private IssuerBuilder issuerBuilder; - private Converter protocolBindingResolver = - context -> { - if (context == null) { - return SAMLConstants.SAML2_POST_BINDING_URI; - } - return context.getRelyingPartyRegistration().getAssertionConsumerServiceBinding().getUrn(); - }; + private Converter protocolBindingResolver = context -> { + if (context == null) { + return SAMLConstants.SAML2_POST_BINDING_URI; + } + return context.getRelyingPartyRegistration().getAssertionConsumerServiceBinding().getUrn(); + }; - private Function> authnRequestConsumerResolver - = context -> authnRequest -> {}; + private Function> authnRequestConsumerResolver = context -> authnRequest -> { + }; /** * Creates an {@link OpenSamlAuthenticationRequestFactory} @@ -100,19 +102,18 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication .getMarshaller(AuthnRequest.DEFAULT_ELEMENT_NAME); this.authnRequestBuilder = (AuthnRequestBuilder) registry.getBuilderFactory() .getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME); - this.issuerBuilder = (IssuerBuilder) registry.getBuilderFactory() - .getBuilder(Issuer.DEFAULT_ELEMENT_NAME); + this.issuerBuilder = (IssuerBuilder) registry.getBuilderFactory().getBuilder(Issuer.DEFAULT_ELEMENT_NAME); } @Override @Deprecated public String createAuthenticationRequest(Saml2AuthenticationRequest request) { - AuthnRequest authnRequest = createAuthnRequest(request.getIssuer(), - request.getDestination(), request.getAssertionConsumerServiceUrl(), - this.protocolBindingResolver.convert(null)); + AuthnRequest authnRequest = createAuthnRequest(request.getIssuer(), request.getDestination(), + request.getAssertionConsumerServiceUrl(), this.protocolBindingResolver.convert(null)); for (org.springframework.security.saml2.credentials.Saml2X509Credential credential : request.getCredentials()) { if (credential.isSigningCredential()) { - Credential cred = getSigningCredential(credential.getCertificate(), credential.getPrivateKey(), request.getIssuer()); + Credential cred = getSigningCredential(credential.getCertificate(), credential.getPrivateKey(), + request.getIssuer()); return serialize(sign(authnRequest, cred)); } } @@ -125,41 +126,34 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication @Override public Saml2PostAuthenticationRequest createPostAuthenticationRequest(Saml2AuthenticationRequestContext context) { AuthnRequest authnRequest = createAuthnRequest(context); - String xml = context.getRelyingPartyRegistration().getAssertingPartyDetails().getWantAuthnRequestsSigned() ? - serialize(sign(authnRequest, context.getRelyingPartyRegistration())) : - serialize(authnRequest); + String xml = context.getRelyingPartyRegistration().getAssertingPartyDetails().getWantAuthnRequestsSigned() + ? serialize(sign(authnRequest, context.getRelyingPartyRegistration())) : serialize(authnRequest); return Saml2PostAuthenticationRequest.withAuthenticationRequestContext(context) - .samlRequest(samlEncode(xml.getBytes(UTF_8))) - .build(); + .samlRequest(samlEncode(xml.getBytes(UTF_8))).build(); } /** * {@inheritDoc} */ @Override - public Saml2RedirectAuthenticationRequest createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext context) { + public Saml2RedirectAuthenticationRequest createRedirectAuthenticationRequest( + Saml2AuthenticationRequestContext context) { AuthnRequest authnRequest = createAuthnRequest(context); String xml = serialize(authnRequest); Builder result = Saml2RedirectAuthenticationRequest.withAuthenticationRequestContext(context); String deflatedAndEncoded = samlEncode(samlDeflate(xml)); - result.samlRequest(deflatedAndEncoded) - .relayState(context.getRelayState()); + result.samlRequest(deflatedAndEncoded).relayState(context.getRelayState()); if (context.getRelyingPartyRegistration().getAssertingPartyDetails().getWantAuthnRequestsSigned()) { - Collection signingCredentials = context.getRelyingPartyRegistration().getSigningX509Credentials(); + Collection signingCredentials = context.getRelyingPartyRegistration() + .getSigningX509Credentials(); for (Saml2X509Credential credential : signingCredentials) { Credential cred = getSigningCredential(credential.getCertificate(), credential.getPrivateKey(), ""); - Map signedParams = signQueryParameters( - cred, - deflatedAndEncoded, + Map signedParams = signQueryParameters(cred, deflatedAndEncoded, context.getRelayState()); - return result - .samlRequest(signedParams.get("SAMLRequest")) - .relayState(signedParams.get("RelayState")) - .sigAlg(signedParams.get("SigAlg")) - .signature(signedParams.get("Signature")) - .build(); + return result.samlRequest(signedParams.get("SAMLRequest")).relayState(signedParams.get("RelayState")) + .sigAlg(signedParams.get("SigAlg")).signature(signedParams.get("Signature")).build(); } throw new Saml2Exception("No signing credential provided"); } @@ -168,15 +162,14 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication } private AuthnRequest createAuthnRequest(Saml2AuthenticationRequestContext context) { - AuthnRequest authnRequest = createAuthnRequest(context.getIssuer(), - context.getDestination(), context.getAssertionConsumerServiceUrl(), - this.protocolBindingResolver.convert(context)); + AuthnRequest authnRequest = createAuthnRequest(context.getIssuer(), context.getDestination(), + context.getAssertionConsumerServiceUrl(), this.protocolBindingResolver.convert(context)); this.authnRequestConsumerResolver.apply(context).accept(authnRequest); return authnRequest; } - private AuthnRequest createAuthnRequest - (String issuer, String destination, String assertionConsumerServiceUrl, String protocolBinding) { + private AuthnRequest createAuthnRequest(String issuer, String destination, String assertionConsumerServiceUrl, + String protocolBinding) { AuthnRequest auth = this.authnRequestBuilder.buildObject(); auth.setID("ARQ" + UUID.randomUUID().toString().substring(1)); auth.setIssueInstant(new DateTime(this.clock.millis())); @@ -193,7 +186,6 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication /** * Set the {@link AuthnRequest} post-processor resolver - * * @param authnRequestConsumerResolver * @since 5.4 */ @@ -204,10 +196,7 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication } /** - * ' - * Use this {@link Clock} with {@link Instant#now()} for generating - * timestamps - * + * ' Use this {@link Clock} with {@link Instant#now()} for generating timestamps * @param clock */ public void setClock(Clock clock) { @@ -218,20 +207,20 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication /** * Sets the {@code protocolBinding} to use when generating authentication requests. * Acceptable values are {@link SAMLConstants#SAML2_POST_BINDING_URI} and - * {@link SAMLConstants#SAML2_REDIRECT_BINDING_URI} - * The IDP will be reading this value in the {@code AuthNRequest} to determine how to - * send the Response/Assertion to the ACS URL, assertion consumer service URL. - * + * {@link SAMLConstants#SAML2_REDIRECT_BINDING_URI} The IDP will be reading this value + * in the {@code AuthNRequest} to determine how to send the Response/Assertion to the + * ACS URL, assertion consumer service URL. * @param protocolBinding either {@link SAMLConstants#SAML2_POST_BINDING_URI} or * {@link SAMLConstants#SAML2_REDIRECT_BINDING_URI} * @throws IllegalArgumentException if the protocolBinding is not valid - * @deprecated Use {@link org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.Builder#assertionConsumerServiceBinding(Saml2MessageBinding)} + * @deprecated Use + * {@link org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.Builder#assertionConsumerServiceBinding(Saml2MessageBinding)} * instead */ @Deprecated public void setProtocolBinding(String protocolBinding) { - boolean isAllowedBinding = SAMLConstants.SAML2_POST_BINDING_URI.equals(protocolBinding) || - SAMLConstants.SAML2_REDIRECT_BINDING_URI.equals(protocolBinding); + boolean isAllowedBinding = SAMLConstants.SAML2_POST_BINDING_URI.equals(protocolBinding) + || SAMLConstants.SAML2_REDIRECT_BINDING_URI.equals(protocolBinding); if (!isAllowedBinding) { throw new IllegalArgumentException("Invalid protocol binding: " + protocolBinding); } @@ -240,8 +229,8 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication private AuthnRequest sign(AuthnRequest authnRequest, RelyingPartyRegistration relyingPartyRegistration) { for (Saml2X509Credential credential : relyingPartyRegistration.getSigningX509Credentials()) { - Credential cred = getSigningCredential( - credential.getCertificate(), credential.getPrivateKey(), relyingPartyRegistration.getEntityId()); + Credential cred = getSigningCredential(credential.getCertificate(), credential.getPrivateKey(), + relyingPartyRegistration.getEntityId()); return sign(authnRequest, cred); } throw new IllegalArgumentException("No signing credential provided"); @@ -256,7 +245,8 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication try { SignatureSupport.signObject(authnRequest, parameters); return authnRequest; - } catch (MarshallingException | SignatureException | SecurityException e) { + } + catch (MarshallingException | SignatureException | SecurityException e) { throw new Saml2Exception(e); } } @@ -268,36 +258,21 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication return cred; } - private Map signQueryParameters( - Credential credential, - String samlRequest, - String relayState) { + private Map signQueryParameters(Credential credential, String samlRequest, String relayState) { Assert.notNull(samlRequest, "samlRequest cannot be null"); String algorithmUri = SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256; StringBuilder queryString = new StringBuilder(); - queryString - .append("SAMLRequest") - .append("=") - .append(UriUtils.encode(samlRequest, StandardCharsets.ISO_8859_1)) + queryString.append("SAMLRequest").append("=").append(UriUtils.encode(samlRequest, StandardCharsets.ISO_8859_1)) .append("&"); if (hasText(relayState)) { - queryString - .append("RelayState") - .append("=") - .append(UriUtils.encode(relayState, StandardCharsets.ISO_8859_1)) - .append("&"); + queryString.append("RelayState").append("=") + .append(UriUtils.encode(relayState, StandardCharsets.ISO_8859_1)).append("&"); } - queryString - .append("SigAlg") - .append("=") - .append(UriUtils.encode(algorithmUri, StandardCharsets.ISO_8859_1)); + queryString.append("SigAlg").append("=").append(UriUtils.encode(algorithmUri, StandardCharsets.ISO_8859_1)); try { - byte[] rawSignature = XMLSigningUtil.signWithURI( - credential, - algorithmUri, - queryString.toString().getBytes(StandardCharsets.UTF_8) - ); + byte[] rawSignature = XMLSigningUtil.signWithURI(credential, algorithmUri, + queryString.toString().getBytes(StandardCharsets.UTF_8)); String b64Signature = Saml2Utils.samlEncode(rawSignature); Map result = new LinkedHashMap<>(); @@ -318,8 +293,10 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication try { Element element = this.marshaller.marshall(authnRequest); return SerializeSupport.nodeToString(element); - } catch (MarshallingException e) { + } + catch (MarshallingException e) { throw new Saml2Exception(e); } } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticatedPrincipal.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticatedPrincipal.java index 54cb297ffb..83cd4128c4 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticatedPrincipal.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticatedPrincipal.java @@ -31,9 +31,9 @@ import java.util.Map; * @since 5.2.2 */ public interface Saml2AuthenticatedPrincipal extends AuthenticatedPrincipal { + /** * Get the first value of Saml2 token attribute by name - * * @param name the name of the attribute * @param the type of the attribute * @return the first attribute value or {@code null} otherwise @@ -47,7 +47,6 @@ public interface Saml2AuthenticatedPrincipal extends AuthenticatedPrincipal { /** * Get the Saml2 token attribute by name - * * @param name the name of the attribute * @param the type of the attribute * @return the attribute or {@code null} otherwise @@ -60,11 +59,11 @@ public interface Saml2AuthenticatedPrincipal extends AuthenticatedPrincipal { /** * Get the Saml2 token attributes - * * @return the Saml2 token attributes * @since 5.4 */ default Map> getAttributes() { return Collections.emptyMap(); } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Authentication.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Authentication.java index a2a5951648..c4c2a9347e 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Authentication.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Authentication.java @@ -25,23 +25,23 @@ import org.springframework.util.Assert; import java.util.Collection; /** - * An implementation of an {@link AbstractAuthenticationToken} - * that represents an authenticated SAML 2.0 {@link Authentication}. + * An implementation of an {@link AbstractAuthenticationToken} that represents an + * authenticated SAML 2.0 {@link Authentication}. *

        - * The {@link Authentication} associates valid SAML assertion - * data with a Spring Security authentication object - * The complete assertion is contained in the object in String format, - * {@link Saml2Authentication#getSaml2Response()} + * The {@link Authentication} associates valid SAML assertion data with a Spring Security + * authentication object The complete assertion is contained in the object in String + * format, {@link Saml2Authentication#getSaml2Response()} + * * @since 5.2 * @see AbstractAuthenticationToken */ public class Saml2Authentication extends AbstractAuthenticationToken { private final AuthenticatedPrincipal principal; + private final String saml2Response; - public Saml2Authentication(AuthenticatedPrincipal principal, - String saml2Response, + public Saml2Authentication(AuthenticatedPrincipal principal, String saml2Response, Collection authorities) { super(authorities); Assert.notNull(principal, "principal cannot be null"); diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationException.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationException.java index 12b16a7358..b462b18ccf 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationException.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationException.java @@ -27,23 +27,23 @@ import org.springframework.util.Assert; *

        * There are a number of scenarios where an error may occur, for example: *

          - *
        • The response or assertion request is missing or malformed
        • - *
        • Missing or invalid subject
        • - *
        • Missing or invalid signatures
        • - *
        • The time period validation for the assertion fails
        • - *
        • One of the assertion conditions was not met
        • - *
        • Decryption failed
        • - *
        • Unable to locate a subject identifier, commonly known as username
        • + *
        • The response or assertion request is missing or malformed
        • + *
        • Missing or invalid subject
        • + *
        • Missing or invalid signatures
        • + *
        • The time period validation for the assertion fails
        • + *
        • One of the assertion conditions was not met
        • + *
        • Decryption failed
        • + *
        • Unable to locate a subject identifier, commonly known as username
        • *
        * * @since 5.2 */ public class Saml2AuthenticationException extends AuthenticationException { + private Saml2Error error; /** * Constructs a {@code Saml2AuthenticationException} using the provided parameters. - * * @param error the {@link Saml2Error SAML 2.0 Error} */ public Saml2AuthenticationException(Saml2Error error) { @@ -52,7 +52,6 @@ public class Saml2AuthenticationException extends AuthenticationException { /** * Constructs a {@code Saml2AuthenticationException} using the provided parameters. - * * @param error the {@link Saml2Error SAML 2.0 Error} * @param cause the root cause */ @@ -62,7 +61,6 @@ public class Saml2AuthenticationException extends AuthenticationException { /** * Constructs a {@code Saml2AuthenticationException} using the provided parameters. - * * @param error the {@link Saml2Error SAML 2.0 Error} * @param message the detail message */ @@ -73,7 +71,6 @@ public class Saml2AuthenticationException extends AuthenticationException { /** * Constructs a {@code Saml2AuthenticationException} using the provided parameters. - * * @param error the {@link Saml2Error SAML 2.0 Error} * @param message the detail message * @param cause the root cause @@ -85,57 +82,69 @@ public class Saml2AuthenticationException extends AuthenticationException { /** * Constructs a {@code Saml2AuthenticationException} using the provided parameters. - * - * @param error the {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error SAML 2.0 Error} - * @deprecated Use {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error} constructor instead + * @param error the + * {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error + * SAML 2.0 Error} + * @deprecated Use + * {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error} + * constructor instead */ @Deprecated - public Saml2AuthenticationException(org.springframework.security.saml2.provider.service.authentication.Saml2Error error) { + public Saml2AuthenticationException( + org.springframework.security.saml2.provider.service.authentication.Saml2Error error) { this(error, error.getDescription()); } /** * Constructs a {@code Saml2AuthenticationException} using the provided parameters. - * - * @param error the {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error SAML 2.0 Error} + * @param error the + * {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error + * SAML 2.0 Error} * @param cause the root cause - * @deprecated Use {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error} constructor instead + * @deprecated Use + * {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error} + * constructor instead */ @Deprecated - public Saml2AuthenticationException(org.springframework.security.saml2.provider.service.authentication.Saml2Error error, Throwable cause) { + public Saml2AuthenticationException( + org.springframework.security.saml2.provider.service.authentication.Saml2Error error, Throwable cause) { this(error, cause.getMessage(), cause); } /** * Constructs a {@code Saml2AuthenticationException} using the provided parameters. - * * @param error the {@link Saml2Error SAML 2.0 Error} * @param message the detail message * @deprecated Use {@link Saml2Error} constructor instead */ @Deprecated - public Saml2AuthenticationException(org.springframework.security.saml2.provider.service.authentication.Saml2Error error, String message) { + public Saml2AuthenticationException( + org.springframework.security.saml2.provider.service.authentication.Saml2Error error, String message) { super(message); this.setError(error); } /** * Constructs a {@code Saml2AuthenticationException} using the provided parameters. - * - * @param error the {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error SAML 2.0 Error} + * @param error the + * {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error + * SAML 2.0 Error} * @param message the detail message * @param cause the root cause - * @deprecated Use {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error} constructor instead + * @deprecated Use + * {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error} + * constructor instead */ @Deprecated - public Saml2AuthenticationException(org.springframework.security.saml2.provider.service.authentication.Saml2Error error, String message, Throwable cause) { + public Saml2AuthenticationException( + org.springframework.security.saml2.provider.service.authentication.Saml2Error error, String message, + Throwable cause) { super(message, cause); this.setError(error); } /** * Get the associated {@link Saml2Error} - * * @return the associated {@link Saml2Error} */ public Saml2Error getSaml2Error() { @@ -144,7 +153,6 @@ public class Saml2AuthenticationException extends AuthenticationException { /** * Returns the {@link Saml2Error SAML 2.0 Error}. - * * @return the {@link Saml2Error} * @deprecated Use {@link #getSaml2Error()} instead */ @@ -170,4 +178,5 @@ public class Saml2AuthenticationException extends AuthenticationException { sb.append('}'); return sb.toString(); } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequest.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequest.java index 1fcc1a80a2..c922a8c117 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequest.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequest.java @@ -25,24 +25,26 @@ import java.util.List; import java.util.function.Consumer; /** - * Data holder for information required to send an {@code AuthNRequest} - * from the service provider to the identity provider - * https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf (line 2031) + * Data holder for information required to send an {@code AuthNRequest} from the service + * provider to the identity provider + * https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf + * (line 2031) * * @since 5.2 * @deprecated use {@link Saml2AuthenticationRequestContext} */ @Deprecated public final class Saml2AuthenticationRequest { + private final String issuer; + private final List credentials; + private final String destination; + private final String assertionConsumerServiceUrl; - private Saml2AuthenticationRequest( - String issuer, - String destination, - String assertionConsumerServiceUrl, + private Saml2AuthenticationRequest(String issuer, String destination, String assertionConsumerServiceUrl, List credentials) { Assert.hasText(issuer, "issuer cannot be null"); Assert.hasText(destination, "destination cannot be null"); @@ -58,10 +60,9 @@ public final class Saml2AuthenticationRequest { } } - /** - * returns the issuer, the local SP entity ID, for this authentication request. - * This property should be used to populate the {@code AuthNRequest.Issuer} XML element. + * returns the issuer, the local SP entity ID, for this authentication request. This + * property should be used to populate the {@code AuthNRequest.Issuer} XML element. * This value typically is a URI, but can be an arbitrary string. * @return issuer */ @@ -70,8 +71,9 @@ public final class Saml2AuthenticationRequest { } /** - * returns the destination, the WEB Single Sign On URI, for this authentication request. - * This property populates the {@code AuthNRequest#Destination} XML attribute. + * returns the destination, the WEB Single Sign On URI, for this authentication + * request. This property populates the {@code AuthNRequest#Destination} XML + * attribute. * @return destination */ public String getDestination() { @@ -79,9 +81,9 @@ public final class Saml2AuthenticationRequest { } /** - * Returns the desired {@code AssertionConsumerServiceUrl} that this SP wishes to receive the - * assertion on. The IDP may or may not honor this request. - * This property populates the {@code AuthNRequest#AssertionConsumerServiceURL} XML attribute. + * Returns the desired {@code AssertionConsumerServiceUrl} that this SP wishes to + * receive the assertion on. The IDP may or may not honor this request. This property + * populates the {@code AuthNRequest#AssertionConsumerServiceURL} XML attribute. * @return the AssertionConsumerServiceURL value */ public String getAssertionConsumerServiceUrl() { @@ -89,7 +91,8 @@ public final class Saml2AuthenticationRequest { } /** - * Returns a list of credentials that can be used to sign the {@code AuthNRequest} object + * Returns a list of credentials that can be used to sign the {@code AuthNRequest} + * object * @return signing credentials */ public List getCredentials() { @@ -97,8 +100,7 @@ public final class Saml2AuthenticationRequest { } /** - * A builder for {@link Saml2AuthenticationRequest}. - * returns a builder object + * A builder for {@link Saml2AuthenticationRequest}. returns a builder object */ public static Builder builder() { return new Builder(); @@ -106,25 +108,25 @@ public final class Saml2AuthenticationRequest { /** * A builder for {@link Saml2AuthenticationRequest}. - * @param context a context object to copy values from. - * returns a builder object + * @param context a context object to copy values from. returns a builder object */ public static Builder withAuthenticationRequestContext(Saml2AuthenticationRequestContext context) { - return new Builder() - .assertionConsumerServiceUrl(context.getAssertionConsumerServiceUrl()) - .issuer(context.getIssuer()) - .destination(context.getDestination()) - .credentials(c -> c.addAll(context.getRelyingPartyRegistration().getCredentials())) - ; + return new Builder().assertionConsumerServiceUrl(context.getAssertionConsumerServiceUrl()) + .issuer(context.getIssuer()).destination(context.getDestination()) + .credentials(c -> c.addAll(context.getRelyingPartyRegistration().getCredentials())); } /** * A builder for {@link Saml2AuthenticationRequest}. */ public static class Builder { + private String issuer; + private List credentials = new LinkedList<>(); + private String destination; + private String assertionConsumerServiceUrl; private Builder() { @@ -141,11 +143,9 @@ public final class Saml2AuthenticationRequest { } /** - * Modifies the collection of {@link Saml2X509Credential} credentials - * used in communication between IDP and SP, specifically signing the - * authentication request. - * For example: - * + * Modifies the collection of {@link Saml2X509Credential} credentials used in + * communication between IDP and SP, specifically signing the authentication + * request. For example: * Saml2X509Credential credential = ...; * return Saml2AuthenticationRequest.withLocalSpEntityId("id") * .credentials(c -> c.add(credential)) @@ -161,7 +161,8 @@ public final class Saml2AuthenticationRequest { } /** - * Sets the Destination for the authentication request. Typically the {@code Service Provider EntityID} + * Sets the Destination for the authentication request. Typically the + * {@code Service Provider EntityID} * @param destination - a required value * @return this {@code Builder} */ @@ -187,12 +188,10 @@ public final class Saml2AuthenticationRequest { * @throws {@link IllegalArgumentException} if a required property is not set */ public Saml2AuthenticationRequest build() { - return new Saml2AuthenticationRequest( - this.issuer, - this.destination, - this.assertionConsumerServiceUrl, - this.credentials - ); + return new Saml2AuthenticationRequest(this.issuer, this.destination, this.assertionConsumerServiceUrl, + this.credentials); } + } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestContext.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestContext.java index 01343f2b3c..5902571aa9 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestContext.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestContext.java @@ -20,9 +20,9 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP import org.springframework.util.Assert; /** - * Data holder for information required to create an {@code AuthNRequest} - * to be sent from the service provider to the identity provider - *
        + * Data holder for information required to create an {@code AuthNRequest} to be sent from + * the service provider to the identity provider * Assertions and Protocols for SAML 2 (line 2031) * * @see Saml2AuthenticationRequestFactory#createPostAuthenticationRequest(Saml2AuthenticationRequestContext) @@ -30,16 +30,17 @@ import org.springframework.util.Assert; * @since 5.3 */ public class Saml2AuthenticationRequestContext { + private final RelyingPartyRegistration relyingPartyRegistration; + private final String issuer; + private final String assertionConsumerServiceUrl; + private final String relayState; - protected Saml2AuthenticationRequestContext( - RelyingPartyRegistration relyingPartyRegistration, - String issuer, - String assertionConsumerServiceUrl, - String relayState) { + protected Saml2AuthenticationRequestContext(RelyingPartyRegistration relyingPartyRegistration, String issuer, + String assertionConsumerServiceUrl, String relayState) { Assert.hasText(issuer, "issuer cannot be null or empty"); Assert.notNull(relyingPartyRegistration, "relyingPartyRegistration cannot be null"); Assert.hasText(assertionConsumerServiceUrl, "spAssertionConsumerServiceUrl cannot be null or empty"); @@ -50,7 +51,8 @@ public class Saml2AuthenticationRequestContext { } /** - * Returns the {@link RelyingPartyRegistration} configuration for which the AuthNRequest is intended for. + * Returns the {@link RelyingPartyRegistration} configuration for which the + * AuthNRequest is intended for. * @return the {@link RelyingPartyRegistration} configuration */ public RelyingPartyRegistration getRelyingPartyRegistration() { @@ -59,8 +61,8 @@ public class Saml2AuthenticationRequestContext { /** * Returns the {@code Issuer} value to be used in the {@code AuthNRequest} object. - * This property should be used to populate the {@code AuthNRequest.Issuer} XML element. - * This value typically is a URI, but can be an arbitrary string. + * This property should be used to populate the {@code AuthNRequest.Issuer} XML + * element. This value typically is a URI, but can be an arbitrary string. * @return the Issuer value */ public String getIssuer() { @@ -68,9 +70,9 @@ public class Saml2AuthenticationRequestContext { } /** - * Returns the desired {@code AssertionConsumerServiceUrl} that this SP wishes to receive the - * assertion on. The IDP may or may not honor this request. - * This property populates the {@code AuthNRequest.AssertionConsumerServiceURL} XML attribute. + * Returns the desired {@code AssertionConsumerServiceUrl} that this SP wishes to + * receive the assertion on. The IDP may or may not honor this request. This property + * populates the {@code AuthNRequest.AssertionConsumerServiceURL} XML attribute. * @return the AssertionConsumerServiceURL value */ public String getAssertionConsumerServiceUrl() { @@ -86,8 +88,9 @@ public class Saml2AuthenticationRequestContext { } /** - * Returns the {@code Destination}, the WEB Single Sign On URI, for this authentication request. - * This property can also populate the {@code AuthNRequest.Destination} XML attribute. + * Returns the {@code Destination}, the WEB Single Sign On URI, for this + * authentication request. This property can also populate the + * {@code AuthNRequest.Destination} XML attribute. * @return the Destination value */ public String getDestination() { @@ -106,9 +109,13 @@ public class Saml2AuthenticationRequestContext { * A builder for {@link Saml2AuthenticationRequestContext}. */ public static class Builder { + private String issuer; + private String assertionConsumerServiceUrl; + private String relayState; + private RelyingPartyRegistration relyingPartyRegistration; private Builder() { @@ -125,7 +132,8 @@ public class Saml2AuthenticationRequestContext { } /** - * Sets the {@link RelyingPartyRegistration} used to build the authentication request. + * Sets the {@link RelyingPartyRegistration} used to build the authentication + * request. * @param relyingPartyRegistration - a required value * @return this {@code Builder} */ @@ -147,7 +155,8 @@ public class Saml2AuthenticationRequestContext { /** * Sets the {@code RelayState} parameter that will accompany this AuthNRequest - * @param relayState the relay state value, unencoded. if null or empty, the parameter will be removed from the map. + * @param relayState the relay state value, unencoded. if null or empty, the + * parameter will be removed from the map. * @return this object */ public Builder relayState(String relayState) { @@ -161,12 +170,10 @@ public class Saml2AuthenticationRequestContext { * @throws {@link IllegalArgumentException} if a required property is not set */ public Saml2AuthenticationRequestContext build() { - return new Saml2AuthenticationRequestContext( - this.relyingPartyRegistration, - this.issuer, - this.assertionConsumerServiceUrl, - this.relayState - ); + return new Saml2AuthenticationRequestContext(this.relyingPartyRegistration, this.issuer, + this.assertionConsumerServiceUrl, this.relayState); } + } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestFactory.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestFactory.java index b70a4fe69c..a57a113c0d 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestFactory.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestFactory.java @@ -27,9 +27,9 @@ import static org.springframework.security.saml2.provider.service.authentication import static org.springframework.security.saml2.provider.service.authentication.Saml2Utils.samlEncode; /** - * Component that generates AuthenticationRequest, samlp:AuthnRequestType XML, and accompanying - * signature data. - * as defined by https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf + * Component that generates AuthenticationRequest, samlp:AuthnRequestType + * XML, and accompanying signature data. as defined by + * https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf * Page 50, Line 2147 * * @since 5.2 @@ -37,81 +37,81 @@ import static org.springframework.security.saml2.provider.service.authentication public interface Saml2AuthenticationRequestFactory { /** - * Creates an authentication request from the Service Provider, sp, to the Identity Provider, idp. - * The authentication result is an XML string that may be signed, encrypted, both or neither. - * This method only returns the {@code SAMLRequest} string for the request, and for a complete - * set of data parameters please use {@link #createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext)} - * or {@link #createPostAuthenticationRequest(Saml2AuthenticationRequestContext)} - * - * @param request information about the identity provider, - * the recipient of this authentication request and accompanying data - * @return XML data in the format of a String. This data may be signed, encrypted, both signed and encrypted with the - * signature embedded in the XML or neither signed and encrypted + * Creates an authentication request from the Service Provider, sp, to the Identity + * Provider, idp. The authentication result is an XML string that may be signed, + * encrypted, both or neither. This method only returns the {@code SAMLRequest} string + * for the request, and for a complete set of data parameters please use + * {@link #createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext)} or + * {@link #createPostAuthenticationRequest(Saml2AuthenticationRequestContext)} + * @param request information about the identity provider, the recipient of this + * authentication request and accompanying data + * @return XML data in the format of a String. This data may be signed, encrypted, + * both signed and encrypted with the signature embedded in the XML or neither signed + * and encrypted * @throws Saml2Exception when a SAML library exception occurs * @since 5.2 - * @deprecated please use {@link #createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext)} - * or {@link #createPostAuthenticationRequest(Saml2AuthenticationRequestContext)} - * This method will be removed in future versions of Spring Security + * @deprecated please use + * {@link #createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext)} or + * {@link #createPostAuthenticationRequest(Saml2AuthenticationRequestContext)} This + * method will be removed in future versions of Spring Security */ @Deprecated String createAuthenticationRequest(Saml2AuthenticationRequest request); /** - * Creates all the necessary AuthNRequest parameters for a REDIRECT binding. - * If the {@link Saml2AuthenticationRequestContext} doesn't contain any {@link Saml2X509CredentialType#SIGNING} credentials - * the result will not contain any signatures. - * The data set will be signed and encoded for REDIRECT binding including the DEFLATE encoding. - * It will contain the following parameters to be sent as part of the query string: - * {@code SAMLRequest, RelayState, SigAlg, Signature}. - * The default implementation, for sake of backwards compatibility, of this method returns the - * SAMLRequest message with an XML signature embedded, that should only be used for the{@link Saml2MessageBinding#POST} - * binding, but works over {@link Saml2MessageBinding#POST} with most providers. - * @param context - information about the identity provider, the recipient of this authentication request and - * accompanying data - * @return a {@link Saml2RedirectAuthenticationRequest} object with applicable http parameters - * necessary to make the AuthNRequest over a POST or REDIRECT binding. - * All parameters will be SAML encoded/deflated, but escaped, ie URI encoded or encoded for Form Data. + * Creates all the necessary AuthNRequest parameters for a REDIRECT binding. If the + * {@link Saml2AuthenticationRequestContext} doesn't contain any + * {@link Saml2X509CredentialType#SIGNING} credentials the result will not contain any + * signatures. The data set will be signed and encoded for REDIRECT binding including + * the DEFLATE encoding. It will contain the following parameters to be sent as part + * of the query string: {@code SAMLRequest, RelayState, SigAlg, Signature}. The + * default implementation, for sake of backwards compatibility, of this method returns + * the SAMLRequest message with an XML signature embedded, that should only be used + * for the{@link Saml2MessageBinding#POST} binding, but works over + * {@link Saml2MessageBinding#POST} with most providers. + * @param context - information about the identity provider, the recipient of this + * authentication request and accompanying data + * @return a {@link Saml2RedirectAuthenticationRequest} object with applicable http + * parameters necessary to make the AuthNRequest over a POST or REDIRECT binding. All + * parameters will be SAML encoded/deflated, but escaped, ie URI encoded or encoded + * for Form Data. * @throws Saml2Exception when a SAML library exception occurs * @since 5.3 */ default Saml2RedirectAuthenticationRequest createRedirectAuthenticationRequest( - Saml2AuthenticationRequestContext context - ) { - //backwards compatible with 5.2.x settings + Saml2AuthenticationRequestContext context) { + // backwards compatible with 5.2.x settings Saml2AuthenticationRequest.Builder resultBuilder = withAuthenticationRequestContext(context); String samlRequest = createAuthenticationRequest(resultBuilder.build()); samlRequest = samlEncode(samlDeflate(samlRequest)); - return Saml2RedirectAuthenticationRequest.withAuthenticationRequestContext(context) - .samlRequest(samlRequest) + return Saml2RedirectAuthenticationRequest.withAuthenticationRequestContext(context).samlRequest(samlRequest) .build(); } - /** - * Creates all the necessary AuthNRequest parameters for a POST binding. - * If the {@link Saml2AuthenticationRequestContext} doesn't contain any {@link Saml2X509CredentialType#SIGNING} credentials - * the result will not contain any signatures. - * The data set will be signed and encoded for POST binding and if applicable signed with XML signatures. - * will contain the following parameters to be sent as part of the form data: {@code SAMLRequest, RelayState}. - * The default implementation of this method returns the SAMLRequest message with an XML signature embedded, - * that should only be used for the {@link Saml2MessageBinding#POST} binding. - * @param context - information about the identity provider, the recipient of this authentication request and - * accompanying data - * @return a {@link Saml2PostAuthenticationRequest} object with applicable http parameters - * necessary to make the AuthNRequest over a POST binding. - * All parameters will be SAML encoded but not escaped for Form Data. + * Creates all the necessary AuthNRequest parameters for a POST binding. If the + * {@link Saml2AuthenticationRequestContext} doesn't contain any + * {@link Saml2X509CredentialType#SIGNING} credentials the result will not contain any + * signatures. The data set will be signed and encoded for POST binding and if + * applicable signed with XML signatures. will contain the following parameters to be + * sent as part of the form data: {@code SAMLRequest, RelayState}. The default + * implementation of this method returns the SAMLRequest message with an XML signature + * embedded, that should only be used for the {@link Saml2MessageBinding#POST} + * binding. + * @param context - information about the identity provider, the recipient of this + * authentication request and accompanying data + * @return a {@link Saml2PostAuthenticationRequest} object with applicable http + * parameters necessary to make the AuthNRequest over a POST binding. All parameters + * will be SAML encoded but not escaped for Form Data. * @throws Saml2Exception when a SAML library exception occurs * @since 5.3 */ - default Saml2PostAuthenticationRequest createPostAuthenticationRequest( - Saml2AuthenticationRequestContext context - ) { - //backwards compatible with 5.2.x settings + default Saml2PostAuthenticationRequest createPostAuthenticationRequest(Saml2AuthenticationRequestContext context) { + // backwards compatible with 5.2.x settings Saml2AuthenticationRequest.Builder resultBuilder = withAuthenticationRequestContext(context); String samlRequest = createAuthenticationRequest(resultBuilder.build()); samlRequest = samlEncode(samlRequest.getBytes(StandardCharsets.UTF_8)); - return Saml2PostAuthenticationRequest.withAuthenticationRequestContext(context) - .samlRequest(samlRequest) + return Saml2PostAuthenticationRequest.withAuthenticationRequestContext(context).samlRequest(samlRequest) .build(); } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationToken.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationToken.java index 22146994f0..a266dd93ec 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationToken.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationToken.java @@ -27,8 +27,8 @@ import org.springframework.util.Assert; import static org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.withRegistrationId; /** - * Represents an incoming SAML 2.0 response containing an assertion that has not been validated. - * {@link Saml2AuthenticationToken#isAuthenticated()} will always return false. + * Represents an incoming SAML 2.0 response containing an assertion that has not been + * validated. {@link Saml2AuthenticationToken#isAuthenticated()} will always return false. * * @since 5.2 * @author Filip Hanik @@ -37,23 +37,23 @@ import static org.springframework.security.saml2.provider.service.registration.R public class Saml2AuthenticationToken extends AbstractAuthenticationToken { private final RelyingPartyRegistration relyingPartyRegistration; + private final String saml2Response; /** * Creates a {@link Saml2AuthenticationToken} with the provided parameters * - * Note that the given {@link RelyingPartyRegistration} should have all its - * templates resolved at this point. See + * Note that the given {@link RelyingPartyRegistration} should have all its templates + * resolved at this point. See * {@link org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter} * for an example of performing that resolution. - * - * @param relyingPartyRegistration the resolved {@link RelyingPartyRegistration} to use + * @param relyingPartyRegistration the resolved {@link RelyingPartyRegistration} to + * use * @param saml2Response the SAML 2.0 response to authenticate * * @since 5.4 */ - public Saml2AuthenticationToken(RelyingPartyRegistration relyingPartyRegistration, - String saml2Response) { + public Saml2AuthenticationToken(RelyingPartyRegistration relyingPartyRegistration, String saml2Response) { super(Collections.emptyList()); Assert.notNull(relyingPartyRegistration, "relyingPartyRegistration cannot be null"); @@ -65,26 +65,23 @@ public class Saml2AuthenticationToken extends AbstractAuthenticationToken { /** * Creates an authentication token from an incoming SAML 2 Response object * @param saml2Response inflated and decoded XML representation of the SAML 2 Response - * @param recipientUri the URL that the SAML 2 Response was received at. Used for validation + * @param recipientUri the URL that the SAML 2 Response was received at. Used for + * validation * @param idpEntityId the entity ID of the asserting entity * @param localSpEntityId the configured local SP, the relying party, entity ID - * @param credentials the credentials configured for signature verification and decryption - * @deprecated Use {@link Saml2AuthenticationToken(RelyingPartyRegistration, String)} instead + * @param credentials the credentials configured for signature verification and + * decryption + * @deprecated Use {@link Saml2AuthenticationToken(RelyingPartyRegistration, String)} + * instead */ @Deprecated - public Saml2AuthenticationToken(String saml2Response, - String recipientUri, - String idpEntityId, - String localSpEntityId, - List credentials) { + public Saml2AuthenticationToken(String saml2Response, String recipientUri, String idpEntityId, + String localSpEntityId, List credentials) { super(null); - this.relyingPartyRegistration = withRegistrationId(idpEntityId) - .entityId(localSpEntityId) - .assertionConsumerServiceLocation(recipientUri) - .credentials(c -> c.addAll(credentials)) - .assertingPartyDetails(assertingParty -> assertingParty - .entityId(idpEntityId) - .singleSignOnServiceLocation(idpEntityId)) + this.relyingPartyRegistration = withRegistrationId(idpEntityId).entityId(localSpEntityId) + .assertionConsumerServiceLocation(recipientUri).credentials(c -> c.addAll(credentials)) + .assertingPartyDetails( + assertingParty -> assertingParty.entityId(idpEntityId).singleSignOnServiceLocation(idpEntityId)) .build(); this.saml2Response = saml2Response; } @@ -109,7 +106,6 @@ public class Saml2AuthenticationToken extends AbstractAuthenticationToken { /** * Get the resolved {@link RelyingPartyRegistration} associated with the request - * * @return the resolved {@link RelyingPartyRegistration} * @since 5.4 */ @@ -128,7 +124,9 @@ public class Saml2AuthenticationToken extends AbstractAuthenticationToken { /** * Returns the URI that the SAML 2 Response object came in on * @return URI as a string - * @deprecated Use {@link #getRelyingPartyRegistration().getAssertionConsumerServiceLocation()} instead + * @deprecated Use + * {@link #getRelyingPartyRegistration().getAssertionConsumerServiceLocation()} + * instead */ @Deprecated public String getRecipientUri() { @@ -148,7 +146,8 @@ public class Saml2AuthenticationToken extends AbstractAuthenticationToken { /** * Returns all the credentials associated with the relying party configuraiton * @return - * @deprecated Get the credentials through {@link #getRelyingPartyRegistration()} instead + * @deprecated Get the credentials through {@link #getRelyingPartyRegistration()} + * instead */ @Deprecated public List getX509Credentials() { @@ -176,10 +175,13 @@ public class Saml2AuthenticationToken extends AbstractAuthenticationToken { /** * Returns the configured IDP, asserting party, entity ID * @return a string representing the entity ID - * @deprecated Use {@link #getRelyingPartyRegistration().getAssertingPartyDetails().getEntityId()} instead + * @deprecated Use + * {@link #getRelyingPartyRegistration().getAssertingPartyDetails().getEntityId()} + * instead */ @Deprecated public String getIdpEntityId() { return this.relyingPartyRegistration.getAssertingPartyDetails().getEntityId(); } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Error.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Error.java index 721b0d5b5a..23f3d24d1b 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Error.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Error.java @@ -24,22 +24,23 @@ import org.springframework.security.core.SpringSecurityCoreVersion; * A representation of an SAML 2.0 Error. * *

        - * At a minimum, an error response will contain an error code. - * The commonly used error code are defined in this class - * or a new codes can be defined in the future as arbitrary strings. + * At a minimum, an error response will contain an error code. The commonly used error + * code are defined in this class or a new codes can be defined in the future as arbitrary + * strings. *

        + * * @since 5.2 * @deprecated Use {@link org.springframework.security.saml2.core.Saml2Error} instead */ @Deprecated public class Saml2Error implements Serializable { + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private final org.springframework.security.saml2.core.Saml2Error error; /** * Constructs a {@code Saml2Error} using the provided parameters. - * * @param errorCode the error code * @param description the error description */ @@ -49,7 +50,6 @@ public class Saml2Error implements Serializable { /** * Returns the error code. - * * @return the error code */ public final String getErrorCode() { @@ -58,7 +58,6 @@ public class Saml2Error implements Serializable { /** * Returns the error description. - * * @return the error description */ public final String getDescription() { @@ -67,7 +66,7 @@ public class Saml2Error implements Serializable { @Override public String toString() { - return "[" + this.getErrorCode() + "] " + - (this.getDescription() != null ? this.getDescription() : ""); + return "[" + this.getErrorCode() + "] " + (this.getDescription() != null ? this.getDescription() : ""); } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2ErrorCodes.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2ErrorCodes.java index b525f3a8e7..fbf31b24ec 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2ErrorCodes.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2ErrorCodes.java @@ -24,80 +24,84 @@ package org.springframework.security.saml2.provider.service.authentication; */ @Deprecated public interface Saml2ErrorCodes { + /** - * SAML Data does not represent a SAML 2 Response object. - * A valid XML object was received, but that object was not a - * SAML 2 Response object of type {@code ResponseType} per specification + * SAML Data does not represent a SAML 2 Response object. A valid XML object was + * received, but that object was not a SAML 2 Response object of type + * {@code ResponseType} per specification * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=46 */ String UNKNOWN_RESPONSE_CLASS = org.springframework.security.saml2.core.Saml2ErrorCodes.UNKNOWN_RESPONSE_CLASS; + /** - * The response data is malformed or incomplete. - * An invalid XML object was received, and XML unmarshalling failed. + * The response data is malformed or incomplete. An invalid XML object was received, + * and XML unmarshalling failed. */ String MALFORMED_RESPONSE_DATA = org.springframework.security.saml2.core.Saml2ErrorCodes.MALFORMED_RESPONSE_DATA; + /** - * Response destination does not match the request URL. - * A SAML 2 response object was received at a URL that - * did not match the URL stored in the {code Destination} attribute - * in the Response object. + * Response destination does not match the request URL. A SAML 2 response object was + * received at a URL that did not match the URL stored in the {code Destination} + * attribute in the Response object. * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=38 */ String INVALID_DESTINATION = org.springframework.security.saml2.core.Saml2ErrorCodes.INVALID_DESTINATION; + /** - * The assertion was not valid. - * The assertion used for authentication failed validation. - * Details around the failure will be present in the error description. + * The assertion was not valid. The assertion used for authentication failed + * validation. Details around the failure will be present in the error description. */ String INVALID_ASSERTION = org.springframework.security.saml2.core.Saml2ErrorCodes.INVALID_ASSERTION; + /** - * The signature of response or assertion was invalid. - * Either the response or the assertion was missing a signature - * or the signature could not be verified using the system's - * configured credentials. Most commonly the IDP's - * X509 certificate. + * The signature of response or assertion was invalid. Either the response or the + * assertion was missing a signature or the signature could not be verified using the + * system's configured credentials. Most commonly the IDP's X509 certificate. */ String INVALID_SIGNATURE = org.springframework.security.saml2.core.Saml2ErrorCodes.INVALID_SIGNATURE; + /** - * The assertion did not contain a subject element. - * The subject element, type SubjectType, contains - * a {@code NameID} or an {@code EncryptedID} that is used - * to assign the authenticated principal an identifier, - * typically a username. + * The assertion did not contain a subject element. The subject element, type + * SubjectType, contains a {@code NameID} or an {@code EncryptedID} that is used to + * assign the authenticated principal an identifier, typically a username. * * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=18 */ String SUBJECT_NOT_FOUND = org.springframework.security.saml2.core.Saml2ErrorCodes.SUBJECT_NOT_FOUND; + /** - * The subject did not contain a user identifier - * The assertion contained a subject element, but the subject - * element did not have a {@code NameID} or {@code EncryptedID} - * element + * The subject did not contain a user identifier The assertion contained a subject + * element, but the subject element did not have a {@code NameID} or + * {@code EncryptedID} element * * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=18 */ String USERNAME_NOT_FOUND = org.springframework.security.saml2.core.Saml2ErrorCodes.USERNAME_NOT_FOUND; + /** - * The system failed to decrypt an assertion or a name identifier. - * This error code will be thrown if the decryption of either a - * {@code EncryptedAssertion} or {@code EncryptedID} fails. + * The system failed to decrypt an assertion or a name identifier. This error code + * will be thrown if the decryption of either a {@code EncryptedAssertion} or + * {@code EncryptedID} fails. * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=17 */ String DECRYPTION_ERROR = org.springframework.security.saml2.core.Saml2ErrorCodes.DECRYPTION_ERROR; + /** * An Issuer element contained a value that didn't * https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=15 */ String INVALID_ISSUER = org.springframework.security.saml2.core.Saml2ErrorCodes.INVALID_ISSUER; + /** - * An error happened during validation. - * Used when internal, non classified, errors are caught during the - * authentication process. + * An error happened during validation. Used when internal, non classified, errors are + * caught during the authentication process. */ String INTERNAL_VALIDATION_ERROR = org.springframework.security.saml2.core.Saml2ErrorCodes.INTERNAL_VALIDATION_ERROR; + /** - * The relying party registration was not found. - * The registration ID did not correspond to any relying party registration. + * The relying party registration was not found. The registration ID did not + * correspond to any relying party registration. */ String RELYING_PARTY_REGISTRATION_NOT_FOUND = org.springframework.security.saml2.core.Saml2ErrorCodes.RELYING_PARTY_REGISTRATION_NOT_FOUND; + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2PostAuthenticationRequest.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2PostAuthenticationRequest.java index d621a7c704..7d3f3aab41 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2PostAuthenticationRequest.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2PostAuthenticationRequest.java @@ -21,19 +21,17 @@ import org.springframework.security.saml2.provider.service.registration.Saml2Mes import static org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding.POST; /** - * Data holder for information required to send an {@code AuthNRequest} over a POST binding - * from the service provider to the identity provider - * https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf (line 2031) + * Data holder for information required to send an {@code AuthNRequest} over a POST + * binding from the service provider to the identity provider + * https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf + * (line 2031) * * @see Saml2AuthenticationRequestFactory * @since 5.3 */ public class Saml2PostAuthenticationRequest extends AbstractSaml2AuthenticationRequest { - private Saml2PostAuthenticationRequest( - String samlRequest, - String relayState, - String authenticationRequestUri) { + private Saml2PostAuthenticationRequest(String samlRequest, String relayState, String authenticationRequestUri) { super(samlRequest, relayState, authenticationRequestUri); } @@ -46,17 +44,16 @@ public class Saml2PostAuthenticationRequest extends AbstractSaml2AuthenticationR } /** - * Constructs a {@link Builder} from a {@link Saml2AuthenticationRequestContext} object. - * By default the {@link Saml2PostAuthenticationRequest#getAuthenticationRequestUri()} will be set to the - * {@link Saml2AuthenticationRequestContext#getDestination()} value. - * @param context input providing {@code Destination}, {@code RelayState}, and {@code Issuer} objects. + * Constructs a {@link Builder} from a {@link Saml2AuthenticationRequestContext} + * object. By default the + * {@link Saml2PostAuthenticationRequest#getAuthenticationRequestUri()} will be set to + * the {@link Saml2AuthenticationRequestContext#getDestination()} value. + * @param context input providing {@code Destination}, {@code RelayState}, and + * {@code Issuer} objects. * @return a modifiable builder object */ public static Builder withAuthenticationRequestContext(Saml2AuthenticationRequestContext context) { - return new Builder() - .authenticationRequestUri(context.getDestination()) - .relayState(context.getRelayState()) - ; + return new Builder().authenticationRequestUri(context.getDestination()).relayState(context.getRelayState()); } /** @@ -73,13 +70,9 @@ public class Saml2PostAuthenticationRequest extends AbstractSaml2AuthenticationR * @return an immutable {@link Saml2PostAuthenticationRequest} object. */ public Saml2PostAuthenticationRequest build() { - return new Saml2PostAuthenticationRequest( - this.samlRequest, - this.relayState, - this.authenticationRequestUri - ); + return new Saml2PostAuthenticationRequest(this.samlRequest, this.relayState, this.authenticationRequestUri); } + } - } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2RedirectAuthenticationRequest.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2RedirectAuthenticationRequest.java index fdfc8372aa..d5ae3c32c5 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2RedirectAuthenticationRequest.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2RedirectAuthenticationRequest.java @@ -21,9 +21,10 @@ import org.springframework.security.saml2.provider.service.registration.Saml2Mes import static org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding.REDIRECT; /** - * Data holder for information required to send an {@code AuthNRequest} over a REDIRECT binding - * from the service provider to the identity provider - * https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf (line 2031) + * Data holder for information required to send an {@code AuthNRequest} over a REDIRECT + * binding from the service provider to the identity provider + * https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf + * (line 2031) * * @see Saml2AuthenticationRequestFactory * @since 5.3 @@ -31,13 +32,10 @@ import static org.springframework.security.saml2.provider.service.registration.S public class Saml2RedirectAuthenticationRequest extends AbstractSaml2AuthenticationRequest { private final String sigAlg; + private final String signature; - private Saml2RedirectAuthenticationRequest( - String samlRequest, - String sigAlg, - String signature, - String relayState, + private Saml2RedirectAuthenticationRequest(String samlRequest, String sigAlg, String signature, String relayState, String authenticationRequestUri) { super(samlRequest, relayState, authenticationRequestUri); this.sigAlg = sigAlg; @@ -61,7 +59,7 @@ public class Saml2RedirectAuthenticationRequest extends AbstractSaml2Authenticat } /** - * @return {@link Saml2MessageBinding#REDIRECT} + * @return {@link Saml2MessageBinding#REDIRECT} */ @Override public Saml2MessageBinding getBinding() { @@ -69,24 +67,25 @@ public class Saml2RedirectAuthenticationRequest extends AbstractSaml2Authenticat } /** - * Constructs a {@link Saml2RedirectAuthenticationRequest.Builder} from a {@link Saml2AuthenticationRequestContext} object. - * By default the {@link Saml2RedirectAuthenticationRequest#getAuthenticationRequestUri()} will be set to the - * {@link Saml2AuthenticationRequestContext#getDestination()} value. - * @param context input providing {@code Destination}, {@code RelayState}, and {@code Issuer} objects. + * Constructs a {@link Saml2RedirectAuthenticationRequest.Builder} from a + * {@link Saml2AuthenticationRequestContext} object. By default the + * {@link Saml2RedirectAuthenticationRequest#getAuthenticationRequestUri()} will be + * set to the {@link Saml2AuthenticationRequestContext#getDestination()} value. + * @param context input providing {@code Destination}, {@code RelayState}, and + * {@code Issuer} objects. * @return a modifiable builder object */ public static Builder withAuthenticationRequestContext(Saml2AuthenticationRequestContext context) { - return new Builder() - .authenticationRequestUri(context.getDestination()) - .relayState(context.getRelayState()) - ; + return new Builder().authenticationRequestUri(context.getDestination()).relayState(context.getRelayState()); } /** * Builder class for a {@link Saml2RedirectAuthenticationRequest} object. */ public static class Builder extends AbstractSaml2AuthenticationRequest.Builder { + private String sigAlg; + private String signature; private Builder() { @@ -118,16 +117,10 @@ public class Saml2RedirectAuthenticationRequest extends AbstractSaml2Authenticat * @return an immutable {@link Saml2RedirectAuthenticationRequest} object. */ public Saml2RedirectAuthenticationRequest build() { - return new Saml2RedirectAuthenticationRequest( - this.samlRequest, - this.sigAlg, - this.signature, - this.relayState, - this.authenticationRequestUri - ); + return new Saml2RedirectAuthenticationRequest(this.samlRequest, this.sigAlg, this.signature, + this.relayState, this.authenticationRequestUri); } } - } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Utils.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Utils.java index ae271df111..b1efb7b1df 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Utils.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Utils.java @@ -34,8 +34,7 @@ import static java.util.zip.Deflater.DEFLATED; */ final class Saml2Utils { - - private static Base64 BASE64 = new Base64(0, new byte[]{'\n'}); + private static Base64 BASE64 = new Base64(0, new byte[] { '\n' }); static String samlEncode(byte[] b) { return BASE64.encodeAsString(b); @@ -70,4 +69,5 @@ final class Saml2Utils { throw new Saml2Exception("Unable to inflate string", e); } } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlMetadataResolver.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlMetadataResolver.java index bc27e60ec9..c7b43e2637 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlMetadataResolver.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlMetadataResolver.java @@ -47,14 +47,15 @@ import static org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport.getB import static org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport.getMarshallerFactory; /** - * Resolves the SAML 2.0 Relying Party Metadata for a given {@link RelyingPartyRegistration} - * using the OpenSAML API. + * Resolves the SAML 2.0 Relying Party Metadata for a given + * {@link RelyingPartyRegistration} using the OpenSAML API. * * @author Jakub Kubrynski * @author Josh Cummings * @since 5.4 */ public final class OpenSamlMetadataResolver implements Saml2MetadataResolver { + static { OpenSamlInitializationService.initialize(); } @@ -62,8 +63,8 @@ public final class OpenSamlMetadataResolver implements Saml2MetadataResolver { private final EntityDescriptorMarshaller entityDescriptorMarshaller; public OpenSamlMetadataResolver() { - this.entityDescriptorMarshaller = (EntityDescriptorMarshaller) - getMarshallerFactory().getMarshaller(EntityDescriptor.DEFAULT_ELEMENT_NAME); + this.entityDescriptorMarshaller = (EntityDescriptorMarshaller) getMarshallerFactory() + .getMarshaller(EntityDescriptor.DEFAULT_ELEMENT_NAME); Assert.notNull(this.entityDescriptorMarshaller, "entityDescriptorMarshaller cannot be null"); } @@ -85,10 +86,10 @@ public final class OpenSamlMetadataResolver implements Saml2MetadataResolver { SPSSODescriptor spSsoDescriptor = build(SPSSODescriptor.DEFAULT_ELEMENT_NAME); spSsoDescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); spSsoDescriptor.setWantAssertionsSigned(true); - spSsoDescriptor.getKeyDescriptors().addAll(buildKeys( - registration.getSigningX509Credentials(), UsageType.SIGNING)); - spSsoDescriptor.getKeyDescriptors().addAll(buildKeys( - registration.getDecryptionX509Credentials(), UsageType.ENCRYPTION)); + spSsoDescriptor.getKeyDescriptors() + .addAll(buildKeys(registration.getSigningX509Credentials(), UsageType.SIGNING)); + spSsoDescriptor.getKeyDescriptors() + .addAll(buildKeys(registration.getDecryptionX509Credentials(), UsageType.ENCRYPTION)); spSsoDescriptor.getAssertionConsumerServices().add(buildAssertionConsumerService(registration)); return spSsoDescriptor; } @@ -110,7 +111,8 @@ public final class OpenSamlMetadataResolver implements Saml2MetadataResolver { try { x509Certificate.setValue(new String(Base64.getEncoder().encode(certificate.getEncoded()))); - } catch (CertificateEncodingException e) { + } + catch (CertificateEncodingException e) { throw new Saml2Exception("Cannot encode certificate " + certificate.toString()); } @@ -139,13 +141,14 @@ public final class OpenSamlMetadataResolver implements Saml2MetadataResolver { return (T) builder.buildObject(elementName); } - private String serialize(EntityDescriptor entityDescriptor) { try { Element element = this.entityDescriptorMarshaller.marshall(entityDescriptor); return SerializeSupport.prettyPrintXML(element); - } catch (Exception e) { + } + catch (Exception e) { throw new Saml2Exception(e); } } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/Saml2MetadataResolver.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/Saml2MetadataResolver.java index adfafcf56c..999a124771 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/Saml2MetadataResolver.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/Saml2MetadataResolver.java @@ -19,18 +19,20 @@ package org.springframework.security.saml2.provider.service.metadata; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; /** - * Resolves the SAML 2.0 Relying Party Metadata for a given {@link RelyingPartyRegistration} + * Resolves the SAML 2.0 Relying Party Metadata for a given + * {@link RelyingPartyRegistration} * * @author Jakub Kubrynski * @author Josh Cummings * @since 5.4 */ public interface Saml2MetadataResolver { + /** * Resolve the given relying party's metadata - * * @param relyingPartyRegistration the relying party * @return the relying party's metadata */ String resolve(RelyingPartyRegistration relyingPartyRegistration); + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/InMemoryRelyingPartyRegistrationRepository.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/InMemoryRelyingPartyRegistrationRepository.java index 4f28cea5e8..df53cfa514 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/InMemoryRelyingPartyRegistrationRepository.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/InMemoryRelyingPartyRegistrationRepository.java @@ -46,14 +46,13 @@ public class InMemoryRelyingPartyRegistrationRepository } private static Map createMappingToIdentityProvider( - Collection rps - ) { + Collection rps) { LinkedHashMap result = new LinkedHashMap<>(); for (RelyingPartyRegistration rp : rps) { notNull(rp, "relying party collection cannot contain null values"); String key = rp.getRegistrationId(); notNull(rp, "relying party identifier cannot be null"); - Assert.isNull(result.get(key), () -> "relying party duplicate identifier '" + key+"' detected."); + Assert.isNull(result.get(key), () -> "relying party duplicate identifier '" + key + "' detected."); result.put(key, rp); } return Collections.unmodifiableMap(result); @@ -61,7 +60,7 @@ public class InMemoryRelyingPartyRegistrationRepository @Override public RelyingPartyRegistration findByRegistrationId(String id) { - return this.byRegistrationId.get(id); + return this.byRegistrationId.get(id); } @Override diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter.java index 77c3e0c988..c62e7bbb50 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter.java @@ -54,12 +54,13 @@ import static org.springframework.security.saml2.core.Saml2X509Credential.verifi import static org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.withRegistrationId; /** - * An {@link HttpMessageConverter} that takes an {@code IDPSSODescriptor} in an HTTP response - * and converts it into a {@link RelyingPartyRegistration.Builder}. + * An {@link HttpMessageConverter} that takes an {@code IDPSSODescriptor} in an HTTP + * response and converts it into a {@link RelyingPartyRegistration.Builder}. * - * The primary use case for this is constructing a {@link RelyingPartyRegistration} for inclusion in a - * {@link RelyingPartyRegistrationRepository}. To do so, you can include an instance of this converter in a - * {@link org.springframework.web.client.RestOperations} like so: + * The primary use case for this is constructing a {@link RelyingPartyRegistration} for + * inclusion in a {@link RelyingPartyRegistrationRepository}. To do so, you can include an + * instance of this converter in a {@link org.springframework.web.client.RestOperations} + * like so: * *
          * 		RestOperations rest = new RestTemplate(Collections.singletonList(
        @@ -69,11 +70,12 @@ import static org.springframework.security.saml2.provider.service.registration.R
          * 		RelyingPartyRegistration registration = builder.registrationId("registration-id").build();
          * 
        * - * Note that this will only configure the asserting party (IDP) half of the {@link RelyingPartyRegistration}, - * meaning where and how to send AuthnRequests, how to verify Assertions, etc. + * Note that this will only configure the asserting party (IDP) half of the + * {@link RelyingPartyRegistration}, meaning where and how to send AuthnRequests, how to + * verify Assertions, etc. * - * To further configure the {@link RelyingPartyRegistration} with relying party (SP) information, you may - * invoke the appropriate methods on the builder. + * To further configure the {@link RelyingPartyRegistration} with relying party (SP) + * information, you may invoke the appropriate methods on the builder. * * @author Josh Cummings * @since 5.4 @@ -86,6 +88,7 @@ public class OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter } private final EntityDescriptorUnmarshaller unmarshaller; + private final ParserPool parserPool; /** @@ -126,8 +129,8 @@ public class OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter * {@inheritDoc} */ @Override - public RelyingPartyRegistration.Builder read(Class clazz, HttpInputMessage inputMessage) - throws IOException, HttpMessageNotReadableException { + public RelyingPartyRegistration.Builder read(Class clazz, + HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { EntityDescriptor descriptor = entityDescriptor(inputMessage.getBody()); IDPSSODescriptor idpssoDescriptor = descriptor.getIDPSSODescriptor(SAML20P_NS); @@ -158,11 +161,11 @@ public class OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter } } if (verification.isEmpty()) { - throw new Saml2Exception("Metadata response is missing verification certificates, necessary for verifying SAML assertions"); + throw new Saml2Exception( + "Metadata response is missing verification certificates, necessary for verifying SAML assertions"); } RelyingPartyRegistration.Builder builder = withRegistrationId(descriptor.getEntityID()) - .assertingPartyDetails(party -> party - .entityId(descriptor.getEntityID()) + .assertingPartyDetails(party -> party.entityId(descriptor.getEntityID()) .wantAuthnRequestsSigned(TRUE.equals(idpssoDescriptor.getWantAuthnRequestsSigned())) .verificationX509Credentials(c -> c.addAll(verification)) .encryptionX509Credentials(c -> c.addAll(encryption))); @@ -170,23 +173,26 @@ public class OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter Saml2MessageBinding binding; if (singleSignOnService.getBinding().equals(Saml2MessageBinding.POST.getUrn())) { binding = Saml2MessageBinding.POST; - } else if (singleSignOnService.getBinding().equals(Saml2MessageBinding.REDIRECT.getUrn())) { + } + else if (singleSignOnService.getBinding().equals(Saml2MessageBinding.REDIRECT.getUrn())) { binding = Saml2MessageBinding.REDIRECT; - } else { + } + else { continue; } - builder.assertingPartyDetails(party -> party - .singleSignOnServiceLocation(singleSignOnService.getLocation()) + builder.assertingPartyDetails(party -> party.singleSignOnServiceLocation(singleSignOnService.getLocation()) .singleSignOnServiceBinding(binding)); return builder; } - throw new Saml2Exception("Metadata response is missing a SingleSignOnService, necessary for sending AuthnRequests"); + throw new Saml2Exception( + "Metadata response is missing a SingleSignOnService, necessary for sending AuthnRequests"); } private List certificates(KeyDescriptor keyDescriptor) { try { return KeyInfoSupport.getCertificates(keyDescriptor.getKeyInfo()); - } catch (CertificateException e) { + } + catch (CertificateException e) { throw new Saml2Exception(e); } } @@ -196,13 +202,16 @@ public class OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter Document document = this.parserPool.parse(inputStream); Element element = document.getDocumentElement(); return (EntityDescriptor) this.unmarshaller.unmarshall(element); - } catch (Exception e) { + } + catch (Exception e) { throw new Saml2Exception(e); } } @Override - public void write(RelyingPartyRegistration.Builder builder, MediaType contentType, HttpOutputMessage outputMessage) throws HttpMessageNotWritableException { + public void write(RelyingPartyRegistration.Builder builder, MediaType contentType, HttpOutputMessage outputMessage) + throws HttpMessageNotWritableException { throw new HttpMessageNotWritableException("This converter cannot write a RelyingPartyRegistration.Builder"); } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java index 9d6d0e2662..e275c51161 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java @@ -28,14 +28,18 @@ import java.util.function.Consumer; import java.util.function.Function; import org.springframework.security.saml2.core.Saml2X509Credential; +import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.AssertingPartyDetails; +import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.ProviderDetails; import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter; import org.springframework.util.Assert; /** - * Represents a configured relying party (aka Service Provider) and asserting party (aka Identity Provider) pair. + * Represents a configured relying party (aka Service Provider) and asserting party (aka + * Identity Provider) pair. * *

        - * Each RP/AP pair is uniquely identified using a {@code registrationId}, an arbitrary string. + * Each RP/AP pair is uniquely identified using a {@code registrationId}, an arbitrary + * string. * *

        * A fully configured registration may look like: @@ -70,20 +74,23 @@ import org.springframework.util.Assert; public class RelyingPartyRegistration { private final String registrationId; + private final String entityId; + private final String assertionConsumerServiceLocation; + private final Saml2MessageBinding assertionConsumerServiceBinding; + private final ProviderDetails providerDetails; + private final List credentials; + private final Collection decryptionX509Credentials; + private final Collection signingX509Credentials; - private RelyingPartyRegistration( - String registrationId, - String entityId, - String assertionConsumerServiceLocation, - Saml2MessageBinding assertionConsumerServiceBinding, - ProviderDetails providerDetails, + private RelyingPartyRegistration(String registrationId, String entityId, String assertionConsumerServiceLocation, + Saml2MessageBinding assertionConsumerServiceBinding, ProviderDetails providerDetails, Collection credentials, Collection decryptionX509Credentials, Collection signingX509Credentials) { @@ -106,8 +113,7 @@ public class RelyingPartyRegistration { Assert.notNull(signingX509Credentials, "signingX509Credentials cannot be null"); for (Saml2X509Credential c : signingX509Credentials) { Assert.notNull(c, "signingX509Credentials cannot contain null elements"); - Assert.isTrue(c.isSigningCredential(), - "All signingX509Credentials must have a usage of SIGNING set"); + Assert.isTrue(c.isSigningCredential(), "All signingX509Credentials must have a usage of SIGNING set"); } this.registrationId = registrationId; this.entityId = entityId; @@ -121,7 +127,6 @@ public class RelyingPartyRegistration { /** * Get the unique registration id for this RP/AP pair - * * @return the unique registration id for this RP/AP pair */ public String getRegistrationId() { @@ -129,18 +134,17 @@ public class RelyingPartyRegistration { } /** - * Get the relying party's - * EntityID. + * Get the relying party's EntityID. * *

        - * Equivalent to the value found in the relying party's - * <EntityDescriptor EntityID="..."/> + * Equivalent to the value found in the relying party's <EntityDescriptor + * EntityID="..."/> * *

        - * This value may contain a number of placeholders, which need to be - * resolved before use. They are {@code baseUrl}, {@code registrationId}, - * {@code baseScheme}, {@code baseHost}, and {@code basePort}. - * + * This value may contain a number of placeholders, which need to be resolved before + * use. They are {@code baseUrl}, {@code registrationId}, {@code baseScheme}, + * {@code baseHost}, and {@code basePort}. * @return the relying party's EntityID * @since 5.4 */ @@ -149,14 +153,13 @@ public class RelyingPartyRegistration { } /** - * Get the AssertionConsumerService Location. - * Equivalent to the value found in <AssertionConsumerService Location="..."/> - * in the relying party's <SPSSODescriptor>. - * - * This value may contain a number of placeholders, which need to be - * resolved before use. They are {@code baseUrl}, {@code registrationId}, - * {@code baseScheme}, {@code baseHost}, and {@code basePort}. + * Get the AssertionConsumerService Location. Equivalent to the value found in + * <AssertionConsumerService Location="..."/> in the relying party's + * <SPSSODescriptor>. * + * This value may contain a number of placeholders, which need to be resolved before + * use. They are {@code baseUrl}, {@code registrationId}, {@code baseScheme}, + * {@code baseHost}, and {@code basePort}. * @return the AssertionConsumerService Location * @since 5.4 */ @@ -165,10 +168,9 @@ public class RelyingPartyRegistration { } /** - * Get the AssertionConsumerService Binding. - * Equivalent to the value found in <AssertionConsumerService Binding="..."/> - * in the relying party's <SPSSODescriptor>. - * + * Get the AssertionConsumerService Binding. Equivalent to the value found in + * <AssertionConsumerService Binding="..."/> in the relying party's + * <SPSSODescriptor>. * @return the AssertionConsumerService Binding * @since 5.4 */ @@ -177,9 +179,10 @@ public class RelyingPartyRegistration { } /** - * Get the {@link Collection} of decryption {@link Saml2X509Credential}s associated with this relying party - * - * @return the {@link Collection} of decryption {@link Saml2X509Credential}s associated with this relying party + * Get the {@link Collection} of decryption {@link Saml2X509Credential}s associated + * with this relying party + * @return the {@link Collection} of decryption {@link Saml2X509Credential}s + * associated with this relying party * @since 5.4 */ public Collection getDecryptionX509Credentials() { @@ -187,9 +190,10 @@ public class RelyingPartyRegistration { } /** - * Get the {@link Collection} of signing {@link Saml2X509Credential}s associated with this relying party - * - * @return the {@link Collection} of signing {@link Saml2X509Credential}s associated with this relying party + * Get the {@link Collection} of signing {@link Saml2X509Credential}s associated with + * this relying party + * @return the {@link Collection} of signing {@link Saml2X509Credential}s associated + * with this relying party * @since 5.4 */ public Collection getSigningX509Credentials() { @@ -198,7 +202,6 @@ public class RelyingPartyRegistration { /** * Get the configuration details for the Asserting Party - * * @return the {@link AssertingPartyDetails} * @since 5.4 */ @@ -209,7 +212,8 @@ public class RelyingPartyRegistration { /** * Returns the entity ID of the IDP, the asserting party. * @return entity ID of the asserting party - * @deprecated use {@link AssertingPartyDetails#getEntityId} from {@link #getAssertingPartyDetails} + * @deprecated use {@link AssertingPartyDetails#getEntityId} from + * {@link #getAssertingPartyDetails} */ @Deprecated public String getRemoteIdpEntityId() { @@ -218,8 +222,8 @@ public class RelyingPartyRegistration { /** * returns the URL template for which ACS URL authentication requests should contain - * Possible variables are {@code baseUrl}, {@code registrationId}, - * {@code baseScheme}, {@code baseHost}, and {@code basePort}. + * Possible variables are {@code baseUrl}, {@code registrationId}, {@code baseScheme}, + * {@code baseHost}, and {@code basePort}. * @return string containing the ACS URL template, with or without variables present * @deprecated Use {@link #getAssertionConsumerServiceLocation} instead */ @@ -229,10 +233,11 @@ public class RelyingPartyRegistration { } /** - * Contains the URL for which to send the SAML 2 Authentication Request to initiate - * a single sign on flow. + * Contains the URL for which to send the SAML 2 Authentication Request to initiate a + * single sign on flow. * @return a IDP URL that accepts REDIRECT or POST binding for authentication requests - * @deprecated use {@link AssertingPartyDetails#getSingleSignOnServiceLocation} from {@link #getAssertingPartyDetails} + * @deprecated use {@link AssertingPartyDetails#getSingleSignOnServiceLocation} from + * {@link #getAssertingPartyDetails} */ @Deprecated public String getIdpWebSsoUrl() { @@ -252,8 +257,8 @@ public class RelyingPartyRegistration { /** * The local relying party, or Service Provider, can generate it's entity ID based on - * possible variables of {@code baseUrl}, {@code registrationId}, - * {@code baseScheme}, {@code baseHost}, and {@code basePort}, for example + * possible variables of {@code baseUrl}, {@code registrationId}, {@code baseScheme}, + * {@code baseHost}, and {@code basePort}, for example * {@code {baseUrl}/saml2/service-provider-metadata/{registrationId}} * @return a string containing the entity ID or entity ID template * @deprecated Use {@link #getEntityId} instead @@ -264,10 +269,11 @@ public class RelyingPartyRegistration { } /** - * Returns a list of configured credentials to be used in message exchanges between relying party, SP, and - * asserting party, IDP. + * Returns a list of configured credentials to be used in message exchanges between + * relying party, SP, and asserting party, IDP. * @return a list of credentials - * @deprecated Instead of retrieving all credentials, use the appropriate method for obtaining the correct type + * @deprecated Instead of retrieving all credentials, use the appropriate method for + * obtaining the correct type */ @Deprecated public List getCredentials() { @@ -278,11 +284,13 @@ public class RelyingPartyRegistration { * @return a filtered list containing only credentials of type * {@link org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType#VERIFICATION}. * Returns an empty list of credentials are not found - * @deprecated Use {@link #getAssertingPartyDetails().getSigningX509Credentials()} instead + * @deprecated Use {@link #getAssertingPartyDetails().getSigningX509Credentials()} + * instead */ @Deprecated public List getVerificationCredentials() { - return filterCredentials(org.springframework.security.saml2.credentials.Saml2X509Credential::isSignatureVerficationCredential); + return filterCredentials( + org.springframework.security.saml2.credentials.Saml2X509Credential::isSignatureVerficationCredential); } /** @@ -293,18 +301,21 @@ public class RelyingPartyRegistration { */ @Deprecated public List getSigningCredentials() { - return filterCredentials(org.springframework.security.saml2.credentials.Saml2X509Credential::isSigningCredential); + return filterCredentials( + org.springframework.security.saml2.credentials.Saml2X509Credential::isSigningCredential); } /** * @return a filtered list containing only credentials of type * {@link org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType#ENCRYPTION}. * Returns an empty list of credentials are not found - * @deprecated Use {@link AssertingPartyDetails#getEncryptionX509Credentials()} instead + * @deprecated Use {@link AssertingPartyDetails#getEncryptionX509Credentials()} + * instead */ @Deprecated public List getEncryptionCredentials() { - return filterCredentials(org.springframework.security.saml2.credentials.Saml2X509Credential::isEncryptionCredential); + return filterCredentials( + org.springframework.security.saml2.credentials.Saml2X509Credential::isEncryptionCredential); } /** @@ -315,7 +326,8 @@ public class RelyingPartyRegistration { */ @Deprecated public List getDecryptionCredentials() { - return filterCredentials(org.springframework.security.saml2.credentials.Saml2X509Credential::isDecryptionCredential); + return filterCredentials( + org.springframework.security.saml2.credentials.Saml2X509Credential::isDecryptionCredential); } private List filterCredentials( @@ -331,7 +343,8 @@ public class RelyingPartyRegistration { } /** - * Creates a {@code RelyingPartyRegistration} {@link Builder} with a known {@code registrationId} + * Creates a {@code RelyingPartyRegistration} {@link Builder} with a known + * {@code registrationId} * @param registrationId a string identifier for the {@code RelyingPartyRegistration} * @return {@code Builder} to create a {@code RelyingPartyRegistration} object */ @@ -341,48 +354,53 @@ public class RelyingPartyRegistration { } /** - * Creates a {@code RelyingPartyRegistration} {@link Builder} based on an existing object + * Creates a {@code RelyingPartyRegistration} {@link Builder} based on an existing + * object * @param registration the {@code RelyingPartyRegistration} * @return {@code Builder} to create a {@code RelyingPartyRegistration} object */ public static Builder withRelyingPartyRegistration(RelyingPartyRegistration registration) { Assert.notNull(registration, "registration cannot be null"); - return withRegistrationId(registration.getRegistrationId()) - .entityId(registration.getEntityId()) + return withRegistrationId(registration.getRegistrationId()).entityId(registration.getEntityId()) .signingX509Credentials(c -> c.addAll(registration.getSigningX509Credentials())) .decryptionX509Credentials(c -> c.addAll(registration.getDecryptionX509Credentials())) .assertionConsumerServiceLocation(registration.getAssertionConsumerServiceLocation()) .assertionConsumerServiceBinding(registration.getAssertionConsumerServiceBinding()) .assertingPartyDetails(assertingParty -> assertingParty - .entityId(registration.getAssertingPartyDetails().getEntityId()) - .wantAuthnRequestsSigned(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()) - .verificationX509Credentials(c -> c.addAll(registration.getAssertingPartyDetails().getVerificationX509Credentials())) - .encryptionX509Credentials(c -> c.addAll(registration.getAssertingPartyDetails().getEncryptionX509Credentials())) - .singleSignOnServiceLocation(registration.getAssertingPartyDetails().getSingleSignOnServiceLocation()) - .singleSignOnServiceBinding(registration.getAssertingPartyDetails().getSingleSignOnServiceBinding()) - ); + .entityId(registration.getAssertingPartyDetails().getEntityId()) + .wantAuthnRequestsSigned(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()) + .verificationX509Credentials( + c -> c.addAll(registration.getAssertingPartyDetails().getVerificationX509Credentials())) + .encryptionX509Credentials( + c -> c.addAll(registration.getAssertingPartyDetails().getEncryptionX509Credentials())) + .singleSignOnServiceLocation( + registration.getAssertingPartyDetails().getSingleSignOnServiceLocation()) + .singleSignOnServiceBinding( + registration.getAssertingPartyDetails().getSingleSignOnServiceBinding())); } - /** * The configuration metadata of the Asserting party * * @since 5.4 */ public final static class AssertingPartyDetails { + private final String entityId; + private final boolean wantAuthnRequestsSigned; + private final Collection verificationX509Credentials; + private final Collection encryptionX509Credentials; + private final String singleSignOnServiceLocation; + private final Saml2MessageBinding singleSignOnServiceBinding; - private AssertingPartyDetails( - String entityId, - boolean wantAuthnRequestsSigned, + private AssertingPartyDetails(String entityId, boolean wantAuthnRequestsSigned, Collection verificationX509Credentials, - Collection encryptionX509Credentials, - String singleSignOnServiceLocation, + Collection encryptionX509Credentials, String singleSignOnServiceLocation, Saml2MessageBinding singleSignOnServiceBinding) { Assert.hasText(entityId, "entityId cannot be null or empty"); @@ -409,18 +427,17 @@ public class RelyingPartyRegistration { } /** - * Get the asserting party's - * EntityID. + * Get the asserting party's EntityID. * *

        - * Equivalent to the value found in the asserting party's - * <EntityDescriptor EntityID="..."/> + * Equivalent to the value found in the asserting party's <EntityDescriptor + * EntityID="..."/> * *

        - * This value may contain a number of placeholders, which need to be - * resolved before use. They are {@code baseUrl}, {@code registrationId}, + * This value may contain a number of placeholders, which need to be resolved + * before use. They are {@code baseUrl}, {@code registrationId}, * {@code baseScheme}, {@code baseHost}, and {@code basePort}. - * * @return the asserting party's EntityID */ public String getEntityId() { @@ -428,9 +445,8 @@ public class RelyingPartyRegistration { } /** - * Get the WantAuthnRequestsSigned setting, indicating the asserting party's preference that - * relying parties should sign the AuthnRequest before sending. - * + * Get the WantAuthnRequestsSigned setting, indicating the asserting party's + * preference that relying parties should sign the AuthnRequest before sending. * @return the WantAuthnRequestsSigned value */ public boolean getWantAuthnRequestsSigned() { @@ -438,9 +454,10 @@ public class RelyingPartyRegistration { } /** - * Get all verification {@link Saml2X509Credential}s associated with this asserting party - * - * @return all verification {@link Saml2X509Credential}s associated with this asserting party + * Get all verification {@link Saml2X509Credential}s associated with this + * asserting party + * @return all verification {@link Saml2X509Credential}s associated with this + * asserting party * @since 5.4 */ public Collection getVerificationX509Credentials() { @@ -448,9 +465,10 @@ public class RelyingPartyRegistration { } /** - * Get all encryption {@link Saml2X509Credential}s associated with this asserting party - * - * @return all encryption {@link Saml2X509Credential}s associated with this asserting party + * Get all encryption {@link Saml2X509Credential}s associated with this asserting + * party + * @return all encryption {@link Saml2X509Credential}s associated with this + * asserting party * @since 5.4 */ public Collection getEncryptionX509Credentials() { @@ -458,14 +476,13 @@ public class RelyingPartyRegistration { } /** - * Get the - * SingleSignOnService + * Get the SingleSignOnService * Location. * *

        - * Equivalent to the value found in <SingleSignOnService Location="..."/> - * in the asserting party's <IDPSSODescriptor>. - * + * Equivalent to the value found in <SingleSignOnService Location="..."/> in + * the asserting party's <IDPSSODescriptor>. * @return the SingleSignOnService Location */ public String getSingleSignOnServiceLocation() { @@ -473,14 +490,13 @@ public class RelyingPartyRegistration { } /** - * Get the - * SingleSignOnService + * Get the SingleSignOnService * Binding. * *

        - * Equivalent to the value found in <SingleSignOnService Binding="..."/> - * in the asserting party's <IDPSSODescriptor>. - * + * Equivalent to the value found in <SingleSignOnService Binding="..."/> in + * the asserting party's <IDPSSODescriptor>. * @return the SingleSignOnService Location */ public Saml2MessageBinding getSingleSignOnServiceBinding() { @@ -488,19 +504,24 @@ public class RelyingPartyRegistration { } public final static class Builder { + private String entityId; + private boolean wantAuthnRequestsSigned = true; + private Collection verificationX509Credentials = new HashSet<>(); + private Collection encryptionX509Credentials = new HashSet<>(); + private String singleSignOnServiceLocation; + private Saml2MessageBinding singleSignOnServiceBinding = Saml2MessageBinding.REDIRECT; /** - * Set the asserting party's - * EntityID. - * Equivalent to the value found in the asserting party's - * <EntityDescriptor EntityID="..."/> - * + * Set the asserting party's EntityID. + * Equivalent to the value found in the asserting party's <EntityDescriptor + * EntityID="..."/> * @param entityId the asserting party's EntityID * @return the {@link ProviderDetails.Builder} for further configuration */ @@ -510,9 +531,9 @@ public class RelyingPartyRegistration { } /** - * Set the WantAuthnRequestsSigned setting, indicating the asserting party's preference that - * relying parties should sign the AuthnRequest before sending. - * + * Set the WantAuthnRequestsSigned setting, indicating the asserting party's + * preference that relying parties should sign the AuthnRequest before + * sending. * @param wantAuthnRequestsSigned the WantAuthnRequestsSigned setting * @return the {@link ProviderDetails.Builder} for further configuration */ @@ -523,9 +544,10 @@ public class RelyingPartyRegistration { /** * Apply this {@link Consumer} to the list of {@link Saml2X509Credential}s - * - * @param credentialsConsumer a {@link Consumer} of the {@link List} of {@link Saml2X509Credential}s - * @return the {@link RelyingPartyRegistration.Builder} for further configuration + * @param credentialsConsumer a {@link Consumer} of the {@link List} of + * {@link Saml2X509Credential}s + * @return the {@link RelyingPartyRegistration.Builder} for further + * configuration * @since 5.4 */ public Builder verificationX509Credentials(Consumer> credentialsConsumer) { @@ -535,9 +557,10 @@ public class RelyingPartyRegistration { /** * Apply this {@link Consumer} to the list of {@link Saml2X509Credential}s - * - * @param credentialsConsumer a {@link Consumer} of the {@link List} of {@link Saml2X509Credential}s - * @return the {@link RelyingPartyRegistration.Builder} for further configuration + * @param credentialsConsumer a {@link Consumer} of the {@link List} of + * {@link Saml2X509Credential}s + * @return the {@link RelyingPartyRegistration.Builder} for further + * configuration * @since 5.4 */ public Builder encryptionX509Credentials(Consumer> credentialsConsumer) { @@ -546,14 +569,13 @@ public class RelyingPartyRegistration { } /** - * Set the - * SingleSignOnService + * Set the SingleSignOnService * Location. * *

        - * Equivalent to the value found in <SingleSignOnService Location="..."/> - * in the asserting party's <IDPSSODescriptor>. - * + * Equivalent to the value found in <SingleSignOnService + * Location="..."/> in the asserting party's <IDPSSODescriptor>. * @param singleSignOnServiceLocation the SingleSignOnService Location * @return the {@link ProviderDetails.Builder} for further configuration */ @@ -563,14 +585,13 @@ public class RelyingPartyRegistration { } /** - * Set the - * SingleSignOnService + * Set the SingleSignOnService * Binding. * *

        * Equivalent to the value found in <SingleSignOnService Binding="..."/> * in the asserting party's <IDPSSODescriptor>. - * * @param singleSignOnServiceBinding the SingleSignOnService Binding * @return the {@link ProviderDetails.Builder} for further configuration */ @@ -580,29 +601,29 @@ public class RelyingPartyRegistration { } /** - * Creates an immutable ProviderDetails object representing the configuration for an Identity Provider, IDP + * Creates an immutable ProviderDetails object representing the configuration + * for an Identity Provider, IDP * @return immutable ProviderDetails object */ public AssertingPartyDetails build() { - return new AssertingPartyDetails( - this.entityId, - this.wantAuthnRequestsSigned, - this.verificationX509Credentials, - this.encryptionX509Credentials, - this.singleSignOnServiceLocation, - this.singleSignOnServiceBinding - ); + return new AssertingPartyDetails(this.entityId, this.wantAuthnRequestsSigned, + this.verificationX509Credentials, this.encryptionX509Credentials, + this.singleSignOnServiceLocation, this.singleSignOnServiceBinding); } + } + } /** * Configuration for IDP SSO endpoint configuration + * * @since 5.3 * @deprecated Use {@link AssertingPartyDetails} instead */ @Deprecated public final static class ProviderDetails { + private final AssertingPartyDetails assertingPartyDetails; private ProviderDetails(AssertingPartyDetails assertingPartyDetails) { @@ -619,17 +640,18 @@ public class RelyingPartyRegistration { } /** - * Contains the URL for which to send the SAML 2 Authentication Request to initiate - * a single sign on flow. - * @return a IDP URL that accepts REDIRECT or POST binding for authentication requests + * Contains the URL for which to send the SAML 2 Authentication Request to + * initiate a single sign on flow. + * @return a IDP URL that accepts REDIRECT or POST binding for authentication + * requests */ public String getWebSsoUrl() { return this.assertingPartyDetails.getSingleSignOnServiceLocation(); } /** - * @return {@code true} if AuthNRequests from this relying party to the IDP should be signed - * {@code false} if no signature is required. + * @return {@code true} if AuthNRequests from this relying party to the IDP should + * be signed {@code false} if no signature is required. */ public boolean isSignAuthNRequest() { return this.assertingPartyDetails.getWantAuthnRequestsSigned(); @@ -644,20 +666,20 @@ public class RelyingPartyRegistration { /** * Builder for IDP SSO endpoint configuration + * * @since 5.3 * @deprecated Use {@link AssertingPartyDetails.Builder} instead */ @Deprecated public final static class Builder { - private final AssertingPartyDetails.Builder assertingPartyDetailsBuilder = - new AssertingPartyDetails.Builder(); + + private final AssertingPartyDetails.Builder assertingPartyDetailsBuilder = new AssertingPartyDetails.Builder(); /** - * Set the asserting party's - * EntityID. - * Equivalent to the value found in the asserting party's - * <EntityDescriptor EntityID="..."/> - * + * Set the asserting party's EntityID. + * Equivalent to the value found in the asserting party's <EntityDescriptor + * EntityID="..."/> * @param entityId the asserting party's EntityID * @return the {@link Builder} for further configuration * @since 5.4 @@ -668,9 +690,10 @@ public class RelyingPartyRegistration { } /** - * Sets the {@code SSO URL} for the remote asserting party, the Identity Provider. - * - * @param url - a URL that accepts authentication requests via REDIRECT or POST bindings + * Sets the {@code SSO URL} for the remote asserting party, the Identity + * Provider. + * @param url - a URL that accepts authentication requests via REDIRECT or + * POST bindings * @return this object */ public Builder webSsoUrl(String url) { @@ -680,7 +703,6 @@ public class RelyingPartyRegistration { /** * Set to true if the AuthNRequest message should be signed - * * @param signAuthNRequest true if the message should be signed * @return this object */ @@ -689,11 +711,10 @@ public class RelyingPartyRegistration { return this; } - /** * Sets the message binding to be used when sending an AuthNRequest message - * - * @param binding either {@link Saml2MessageBinding#POST} or {@link Saml2MessageBinding#REDIRECT} + * @param binding either {@link Saml2MessageBinding#POST} or + * {@link Saml2MessageBinding#REDIRECT} * @return this object */ public Builder binding(Saml2MessageBinding binding) { @@ -702,30 +723,41 @@ public class RelyingPartyRegistration { } /** - * Creates an immutable ProviderDetails object representing the configuration for an Identity Provider, IDP + * Creates an immutable ProviderDetails object representing the configuration + * for an Identity Provider, IDP * @return immutable ProviderDetails object */ public ProviderDetails build() { return new ProviderDetails(this.assertingPartyDetailsBuilder.build()); } + } + } public final static class Builder { + private String registrationId; + private String entityId = "{baseUrl}/saml2/service-provider-metadata/{registrationId}"; + private Collection signingX509Credentials = new HashSet<>(); + private Collection decryptionX509Credentials = new HashSet<>(); - private String assertionConsumerServiceLocation = "{baseUrl}" + Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI; + + private String assertionConsumerServiceLocation = "{baseUrl}" + + Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI; + private Saml2MessageBinding assertionConsumerServiceBinding = Saml2MessageBinding.POST; + private ProviderDetails.Builder providerDetails = new ProviderDetails.Builder(); + private Collection credentials = new HashSet<>(); private Builder(String registrationId) { this.registrationId = registrationId; } - /** * Sets the {@code registrationId} template. Often be used in URL paths * @param id registrationId for this object, should be unique @@ -737,15 +769,14 @@ public class RelyingPartyRegistration { } /** - * Set the relying party's - * EntityID. - * Equivalent to the value found in the relying party's - * <EntityDescriptor EntityID="..."/> - * - * This value may contain a number of placeholders. - * They are {@code baseUrl}, {@code registrationId}, - * {@code baseScheme}, {@code baseHost}, and {@code basePort}. + * Set the relying party's EntityID. + * Equivalent to the value found in the relying party's <EntityDescriptor + * EntityID="..."/> * + * This value may contain a number of placeholders. They are {@code baseUrl}, + * {@code registrationId}, {@code baseScheme}, {@code baseHost}, and + * {@code basePort}. * @return the {@link Builder} for further configuration * @since 5.4 */ @@ -755,10 +786,11 @@ public class RelyingPartyRegistration { } /** - * Apply this {@link Consumer} to the {@link Collection} of {@link Saml2X509Credential}s - * for the purposes of modifying the {@link Collection} - * - * @param credentialsConsumer - the {@link Consumer} for modifying the {@link Collection} + * Apply this {@link Consumer} to the {@link Collection} of + * {@link Saml2X509Credential}s for the purposes of modifying the + * {@link Collection} + * @param credentialsConsumer - the {@link Consumer} for modifying the + * {@link Collection} * @return the {@link Builder} for further configuration * @since 5.4 */ @@ -768,10 +800,11 @@ public class RelyingPartyRegistration { } /** - * Apply this {@link Consumer} to the {@link Collection} of {@link Saml2X509Credential}s - * for the purposes of modifying the {@link Collection} - * - * @param credentialsConsumer - the {@link Consumer} for modifying the {@link Collection} + * Apply this {@link Consumer} to the {@link Collection} of + * {@link Saml2X509Credential}s for the purposes of modifying the + * {@link Collection} + * @param credentialsConsumer - the {@link Consumer} for modifying the + * {@link Collection} * @return the {@link Builder} for further configuration * @since 5.4 */ @@ -781,18 +814,18 @@ public class RelyingPartyRegistration { } /** - * Set the AssertionConsumerService + * Set the AssertionConsumerService * Location. * *

        - * Equivalent to the value found in <AssertionConsumerService Location="..."/> - * in the relying party's <SPSSODescriptor> + * Equivalent to the value found in <AssertionConsumerService + * Location="..."/> in the relying party's <SPSSODescriptor> * *

        - * This value may contain a number of placeholders. - * They are {@code baseUrl}, {@code registrationId}, - * {@code baseScheme}, {@code baseHost}, and {@code basePort}. - * + * This value may contain a number of placeholders. They are {@code baseUrl}, + * {@code registrationId}, {@code baseScheme}, {@code baseHost}, and + * {@code basePort}. * @param assertionConsumerServiceLocation * @return the {@link Builder} for further configuration * @since 5.4 @@ -803,13 +836,13 @@ public class RelyingPartyRegistration { } /** - * Set the AssertionConsumerService + * Set the AssertionConsumerService * Binding. * *

        - * Equivalent to the value found in <AssertionConsumerService Binding="..."/> - * in the relying party's <SPSSODescriptor> - * + * Equivalent to the value found in <AssertionConsumerService + * Binding="..."/> in the relying party's <SPSSODescriptor> * @param assertionConsumerServiceBinding * @return the {@link Builder} for further configuration * @since 5.4 @@ -821,7 +854,6 @@ public class RelyingPartyRegistration { /** * Apply this {@link Consumer} to further configure the Asserting Party details - * * @param assertingPartyDetails The {@link Consumer} to apply * @return the {@link Builder} for further configuration * @since 5.4 @@ -832,10 +864,8 @@ public class RelyingPartyRegistration { } /** - * Modifies the collection of {@link Saml2X509Credential} objects - * used in communication between IDP and SP - * For example: - * + * Modifies the collection of {@link Saml2X509Credential} objects used in + * communication between IDP and SP For example: * Saml2X509Credential credential = ...; * return RelyingPartyRegistration.withRegistrationId("id") * .credentials(c -> c.add(credential)) @@ -844,22 +874,27 @@ public class RelyingPartyRegistration { * * @param credentials - a consumer that can modify the collection of credentials * @return this object - * @deprecated Use {@link #signingX509Credentials} or {@link #decryptionX509Credentials} instead - * for relying party keys or {@link AssertingPartyDetails.Builder#verificationX509Credentials} or - * {@link AssertingPartyDetails.Builder#encryptionX509Credentials} for asserting party keys + * @deprecated Use {@link #signingX509Credentials} or + * {@link #decryptionX509Credentials} instead for relying party keys or + * {@link AssertingPartyDetails.Builder#verificationX509Credentials} or + * {@link AssertingPartyDetails.Builder#encryptionX509Credentials} for asserting + * party keys */ @Deprecated - public Builder credentials(Consumer> credentials) { + public Builder credentials( + Consumer> credentials) { credentials.accept(this.credentials); return this; } /** - * Assertion Consumer - * Service URL template. It can contain variables {@code baseUrl}, {@code registrationId}, - * {@code baseScheme}, {@code baseHost}, and {@code basePort}. - * @param assertionConsumerServiceUrlTemplate the Assertion Consumer Service URL template (i.e. - * "{baseUrl}/login/saml2/sso/{registrationId}". + * Assertion + * Consumer Service URL template. It can contain variables {@code baseUrl}, + * {@code registrationId}, {@code baseScheme}, {@code baseHost}, and + * {@code basePort}. + * @param assertionConsumerServiceUrlTemplate the Assertion Consumer Service URL + * template (i.e. "{baseUrl}/login/saml2/sso/{registrationId}". * @return this object * @deprecated Use {@link #assertionConsumerServiceLocation} instead. */ @@ -870,10 +905,12 @@ public class RelyingPartyRegistration { } /** - * Sets the {@code entityId} for the remote asserting party, the Identity Provider. + * Sets the {@code entityId} for the remote asserting party, the Identity + * Provider. * @param entityId the IDP entityId * @return this object - * @deprecated use {@link #assertingPartyDetails(Consumer< AssertingPartyDetails.Builder >)} + * @deprecated use {@link #assertingPartyDetails(Consumer< + * AssertingPartyDetails.Builder >)} */ @Deprecated public Builder remoteIdpEntityId(String entityId) { @@ -883,9 +920,11 @@ public class RelyingPartyRegistration { /** * Sets the {@code SSO URL} for the remote asserting party, the Identity Provider. - * @param url - a URL that accepts authentication requests via REDIRECT or POST bindings + * @param url - a URL that accepts authentication requests via REDIRECT or POST + * bindings * @return this object - * @deprecated use {@link #assertingPartyDetails(Consumer< AssertingPartyDetails.Builder >)} + * @deprecated use {@link #assertingPartyDetails(Consumer< + * AssertingPartyDetails.Builder >)} */ @Deprecated public Builder idpWebSsoUrl(String url) { @@ -894,9 +933,10 @@ public class RelyingPartyRegistration { } /** - * Sets the local relying party, or Service Provider, entity Id template. - * can generate it's entity ID based on possible variables of {@code baseUrl}, {@code registrationId}, - * {@code baseScheme}, {@code baseHost}, and {@code basePort}, for example + * Sets the local relying party, or Service Provider, entity Id template. can + * generate it's entity ID based on possible variables of {@code baseUrl}, + * {@code registrationId}, {@code baseScheme}, {@code baseHost}, and + * {@code basePort}, for example * {@code {baseUrl}/saml2/service-provider-metadata/{registrationId}} * @return a string containing the entity ID or entity ID template * @deprecated Use {@link #entityId} instead @@ -920,7 +960,8 @@ public class RelyingPartyRegistration { } /** - * Constructs a RelyingPartyRegistration object based on the builder configurations + * Constructs a RelyingPartyRegistration object based on the builder + * configurations * @return a RelyingPartyRegistration instance */ public RelyingPartyRegistration build() { @@ -933,12 +974,10 @@ public class RelyingPartyRegistration { decryptionX509Credentials(c -> c.add(mapped)); } if (credential.isSignatureVerficationCredential()) { - this.providerDetails.assertingPartyDetailsBuilder - .verificationX509Credentials(c -> c.add(mapped)); + this.providerDetails.assertingPartyDetailsBuilder.verificationX509Credentials(c -> c.add(mapped)); } if (credential.isEncryptionCredential()) { - this.providerDetails.assertingPartyDetailsBuilder - .encryptionX509Credentials(c -> c.add(mapped)); + this.providerDetails.assertingPartyDetailsBuilder.encryptionX509Credentials(c -> c.add(mapped)); } } @@ -955,20 +994,16 @@ public class RelyingPartyRegistration { this.credentials.add(toDeprecated(credential)); } - return new RelyingPartyRegistration( - this.registrationId, - this.entityId, - this.assertionConsumerServiceLocation, - this.assertionConsumerServiceBinding, - this.providerDetails.build(), - this.credentials, - this.decryptionX509Credentials, - this.signingX509Credentials - ); + return new RelyingPartyRegistration(this.registrationId, this.entityId, + this.assertionConsumerServiceLocation, this.assertionConsumerServiceBinding, + this.providerDetails.build(), this.credentials, this.decryptionX509Credentials, + this.signingX509Credentials); } + } - private static Saml2X509Credential fromDeprecated(org.springframework.security.saml2.credentials.Saml2X509Credential credential) { + private static Saml2X509Credential fromDeprecated( + org.springframework.security.saml2.credentials.Saml2X509Credential credential) { PrivateKey privateKey = credential.getPrivateKey(); X509Certificate certificate = credential.getCertificate(); Set credentialTypes = new HashSet<>(); @@ -987,22 +1022,29 @@ public class RelyingPartyRegistration { return new Saml2X509Credential(privateKey, certificate, credentialTypes); } - private static org.springframework.security.saml2.credentials.Saml2X509Credential toDeprecated(Saml2X509Credential credential) { + private static org.springframework.security.saml2.credentials.Saml2X509Credential toDeprecated( + Saml2X509Credential credential) { PrivateKey privateKey = credential.getPrivateKey(); X509Certificate certificate = credential.getCertificate(); Set credentialTypes = new HashSet<>(); if (credential.isSigningCredential()) { - credentialTypes.add(org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.SIGNING); + credentialTypes.add( + org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.SIGNING); } if (credential.isVerificationCredential()) { - credentialTypes.add(org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.VERIFICATION); + credentialTypes.add( + org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.VERIFICATION); } if (credential.isEncryptionCredential()) { - credentialTypes.add(org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION); + credentialTypes.add( + org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION); } if (credential.isDecryptionCredential()) { - credentialTypes.add(org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.DECRYPTION); + credentialTypes.add( + org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.DECRYPTION); } - return new org.springframework.security.saml2.credentials.Saml2X509Credential(privateKey, certificate, credentialTypes); + return new org.springframework.security.saml2.credentials.Saml2X509Credential(privateKey, certificate, + credentialTypes); } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationRepository.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationRepository.java index 7f2d6943f5..48e6419ff5 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationRepository.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationRepository.java @@ -25,9 +25,8 @@ package org.springframework.security.saml2.provider.service.registration; public interface RelyingPartyRegistrationRepository { /** - * Returns the relying party registration identified by the provided {@code registrationId}, - * or {@code null} if not found. - * + * Returns the relying party registration identified by the provided + * {@code registrationId}, or {@code null} if not found. * @param registrationId the registration identifier * @return the {@link RelyingPartyRegistration} if found, otherwise {@code null} */ diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrations.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrations.java index 29b9363afb..4c0a33710d 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrations.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrations.java @@ -30,12 +30,13 @@ import org.springframework.web.client.RestTemplate; * @since 5.4 */ public final class RelyingPartyRegistrations { - private static final RestOperations rest = new RestTemplate - (Arrays.asList(new OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter())); + + private static final RestOperations rest = new RestTemplate( + Arrays.asList(new OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter())); /** - * Return a {@link RelyingPartyRegistration.Builder} based off of the given - * SAML 2.0 Asserting Party (IDP) metadata. + * Return a {@link RelyingPartyRegistration.Builder} based off of the given SAML 2.0 + * Asserting Party (IDP) metadata. * * Note that by default the registrationId is set to be the given metadata location, * but this will most often not be sufficient. To complete the configuration, most @@ -48,21 +49,23 @@ public final class RelyingPartyRegistrations { * .build(); *

        * - * Also note that an {@code IDPSSODescriptor} typically only contains information about - * the asserting party. Thus, you will need to remember to still populate anything about the - * relying party, like any private keys the relying party will use for signing AuthnRequests. - * + * Also note that an {@code IDPSSODescriptor} typically only contains information + * about the asserting party. Thus, you will need to remember to still populate + * anything about the relying party, like any private keys the relying party will use + * for signing AuthnRequests. * @param metadataLocation * @return the {@link RelyingPartyRegistration.Builder} for further configuration */ public static RelyingPartyRegistration.Builder fromMetadataLocation(String metadataLocation) { try { return rest.getForObject(metadataLocation, RelyingPartyRegistration.Builder.class); - } catch (RestClientException e) { + } + catch (RestClientException e) { if (e.getCause() instanceof Saml2Exception) { throw (Saml2Exception) e.getCause(); } throw new Saml2Exception(e); } } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/Saml2MessageBinding.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/Saml2MessageBinding.java index 154dcc88f4..f8d43315d0 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/Saml2MessageBinding.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/Saml2MessageBinding.java @@ -17,17 +17,17 @@ package org.springframework.security.saml2.provider.service.registration; /** - * The type of bindings that messages are exchanged using - * Supported bindings are {@code urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST} - * and {@code urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect}. - * In addition there is support for {@code urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect} - * with an XML signature in the message rather than query parameters. + * The type of bindings that messages are exchanged using Supported bindings are + * {@code urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST} and + * {@code urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect}. In addition there is + * support for {@code urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect} with an XML + * signature in the message rather than query parameters. * @since 5.3 */ public enum Saml2MessageBinding { - POST("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"), - REDIRECT("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"); + POST("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"), REDIRECT( + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"); private final String urn; @@ -42,4 +42,5 @@ public enum Saml2MessageBinding { public String getUrn() { return urn; } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilter.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilter.java index c073ff0092..afea906f24 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilter.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilter.java @@ -40,12 +40,14 @@ import static org.springframework.util.StringUtils.hasText; public class Saml2WebSsoAuthenticationFilter extends AbstractAuthenticationProcessingFilter { public static final String DEFAULT_FILTER_PROCESSES_URI = "/login/saml2/sso/{registrationId}"; + private final AuthenticationConverter authenticationConverter; /** - * Creates a {@code Saml2WebSsoAuthenticationFilter} authentication filter that is configured - * to use the {@link #DEFAULT_FILTER_PROCESSES_URI} processing URL - * @param relyingPartyRegistrationRepository - repository of configured SAML 2 entities. Required. + * Creates a {@code Saml2WebSsoAuthenticationFilter} authentication filter that is + * configured to use the {@link #DEFAULT_FILTER_PROCESSES_URI} processing URL + * @param relyingPartyRegistrationRepository - repository of configured SAML 2 + * entities. Required. */ public Saml2WebSsoAuthenticationFilter(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) { this(relyingPartyRegistrationRepository, DEFAULT_FILTER_PROCESSES_URI); @@ -53,35 +55,32 @@ public class Saml2WebSsoAuthenticationFilter extends AbstractAuthenticationProce /** * Creates a {@code Saml2WebSsoAuthenticationFilter} authentication filter - * @param relyingPartyRegistrationRepository - repository of configured SAML 2 entities. Required. - * @param filterProcessesUrl the processing URL, must contain a {registrationId} variable. Required. + * @param relyingPartyRegistrationRepository - repository of configured SAML 2 + * entities. Required. + * @param filterProcessesUrl the processing URL, must contain a {registrationId} + * variable. Required. */ - public Saml2WebSsoAuthenticationFilter( - RelyingPartyRegistrationRepository relyingPartyRegistrationRepository, + public Saml2WebSsoAuthenticationFilter(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository, String filterProcessesUrl) { - this(new Saml2AuthenticationTokenConverter - (new DefaultRelyingPartyRegistrationResolver(relyingPartyRegistrationRepository)), - filterProcessesUrl); + this(new Saml2AuthenticationTokenConverter( + new DefaultRelyingPartyRegistrationResolver(relyingPartyRegistrationRepository)), filterProcessesUrl); } /** * Creates a {@link Saml2WebSsoAuthenticationFilter} given the provided parameters - * - * @param authenticationConverter the strategy for converting an {@link HttpServletRequest} - * into an {@link Authentication} - * @param filterProcessingUrl the processing URL, must contain a {registrationId} variable + * @param authenticationConverter the strategy for converting an + * {@link HttpServletRequest} into an {@link Authentication} + * @param filterProcessingUrl the processing URL, must contain a {registrationId} + * variable * @since 5.4 */ - public Saml2WebSsoAuthenticationFilter( - AuthenticationConverter authenticationConverter, + public Saml2WebSsoAuthenticationFilter(AuthenticationConverter authenticationConverter, String filterProcessingUrl) { super(filterProcessingUrl); Assert.notNull(authenticationConverter, "authenticationConverter cannot be null"); Assert.hasText(filterProcessingUrl, "filterProcessesUrl must contain a URL pattern"); - Assert.isTrue( - filterProcessingUrl.contains("{registrationId}"), - "filterProcessesUrl must contain a {registrationId} match variable" - ); + Assert.isTrue(filterProcessingUrl.contains("{registrationId}"), + "filterProcessesUrl must contain a {registrationId} match variable"); this.authenticationConverter = authenticationConverter; setAllowSessionCreation(true); setSessionAuthenticationStrategy(new ChangeSessionIdAuthenticationStrategy()); @@ -103,4 +102,5 @@ public class Saml2WebSsoAuthenticationFilter extends AbstractAuthenticationProce } return getAuthenticationManager().authenticate(authentication); } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationRequestFilter.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationRequestFilter.java index 3fa3e9522c..ea3520147c 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationRequestFilter.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationRequestFilter.java @@ -47,22 +47,22 @@ import static java.nio.charset.StandardCharsets.ISO_8859_1; /** * This {@code Filter} formulates a - * SAML 2.0 AuthnRequest (line 1968) - * and redirects to a configured asserting party. + * SAML 2.0 + * AuthnRequest (line 1968) and redirects to a configured asserting party. * *

        - * It supports the - * HTTP-Redirect (line 520) - * and - * HTTP-POST (line 753) - * bindings. + * It supports the HTTP-Redirect + * (line 520) and HTTP-POST + * (line 753) bindings. * *

        - * By default, this {@code Filter} responds to authentication requests - * at the {@code URI} {@code /oauth2/authorization/{registrationId}}. - * The {@code URI} template variable {@code {registrationId}} represents the - * {@link RelyingPartyRegistration#getRegistrationId() registration identifier} of the relying party - * that is used for initiating the authentication request. + * By default, this {@code Filter} responds to authentication requests at the {@code URI} + * {@code /oauth2/authorization/{registrationId}}. The {@code URI} template variable + * {@code {registrationId}} represents the + * {@link RelyingPartyRegistration#getRegistrationId() registration identifier} of the + * relying party that is used for initiating the authentication request. * * @since 5.2 * @author Filip Hanik @@ -71,27 +71,32 @@ import static java.nio.charset.StandardCharsets.ISO_8859_1; public class Saml2WebSsoAuthenticationRequestFilter extends OncePerRequestFilter { private final Saml2AuthenticationRequestContextResolver authenticationRequestContextResolver; + private Saml2AuthenticationRequestFactory authenticationRequestFactory; private RequestMatcher redirectMatcher = new AntPathRequestMatcher("/saml2/authenticate/{registrationId}"); /** - * Construct a {@link Saml2WebSsoAuthenticationRequestFilter} with the provided parameters - * - * @param relyingPartyRegistrationRepository a repository for relying party configurations - * @deprecated use the constructor that takes a {@link Saml2AuthenticationRequestFactory} + * Construct a {@link Saml2WebSsoAuthenticationRequestFilter} with the provided + * parameters + * @param relyingPartyRegistrationRepository a repository for relying party + * configurations + * @deprecated use the constructor that takes a + * {@link Saml2AuthenticationRequestFactory} */ @Deprecated - public Saml2WebSsoAuthenticationRequestFilter(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) { + public Saml2WebSsoAuthenticationRequestFilter( + RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) { this(new DefaultSaml2AuthenticationRequestContextResolver( new DefaultRelyingPartyRegistrationResolver(relyingPartyRegistrationRepository)), new org.springframework.security.saml2.provider.service.authentication.OpenSamlAuthenticationRequestFactory()); } /** - * Construct a {@link Saml2WebSsoAuthenticationRequestFilter} with the provided parameters - * - * @param authenticationRequestContextResolver a strategy for formulating a {@link Saml2AuthenticationRequestContext} + * Construct a {@link Saml2WebSsoAuthenticationRequestFilter} with the provided + * parameters + * @param authenticationRequestContextResolver a strategy for formulating a + * {@link Saml2AuthenticationRequestContext} * @since 5.4 */ public Saml2WebSsoAuthenticationRequestFilter( @@ -105,9 +110,10 @@ public class Saml2WebSsoAuthenticationRequestFilter extends OncePerRequestFilter } /** - * Use the given {@link Saml2AuthenticationRequestFactory} for formulating the SAML 2.0 AuthnRequest - * - * @param authenticationRequestFactory the {@link Saml2AuthenticationRequestFactory} to use + * Use the given {@link Saml2AuthenticationRequestFactory} for formulating the SAML + * 2.0 AuthnRequest + * @param authenticationRequestFactory the {@link Saml2AuthenticationRequestFactory} + * to use * @deprecated use the constructor instead */ @Deprecated @@ -118,7 +124,6 @@ public class Saml2WebSsoAuthenticationRequestFilter extends OncePerRequestFilter /** * Use the given {@link RequestMatcher} that activates this filter for a given request - * * @param redirectMatcher the {@link RequestMatcher} to use */ public void setRedirectMatcher(RequestMatcher redirectMatcher) { @@ -147,41 +152,36 @@ public class Saml2WebSsoAuthenticationRequestFilter extends OncePerRequestFilter RelyingPartyRegistration relyingParty = context.getRelyingPartyRegistration(); if (relyingParty.getAssertingPartyDetails().getSingleSignOnServiceBinding() == Saml2MessageBinding.REDIRECT) { sendRedirect(response, context); - } else { + } + else { sendPost(response, context); } } private void sendRedirect(HttpServletResponse response, Saml2AuthenticationRequestContext context) throws IOException { - Saml2RedirectAuthenticationRequest authenticationRequest = - this.authenticationRequestFactory.createRedirectAuthenticationRequest(context); + Saml2RedirectAuthenticationRequest authenticationRequest = this.authenticationRequestFactory + .createRedirectAuthenticationRequest(context); UriComponentsBuilder uriBuilder = UriComponentsBuilder .fromUriString(authenticationRequest.getAuthenticationRequestUri()); addParameter("SAMLRequest", authenticationRequest.getSamlRequest(), uriBuilder); addParameter("RelayState", authenticationRequest.getRelayState(), uriBuilder); addParameter("SigAlg", authenticationRequest.getSigAlg(), uriBuilder); addParameter("Signature", authenticationRequest.getSignature(), uriBuilder); - String redirectUrl = uriBuilder - .build(true) - .toUriString(); + String redirectUrl = uriBuilder.build(true).toUriString(); response.sendRedirect(redirectUrl); } private void addParameter(String name, String value, UriComponentsBuilder builder) { Assert.hasText(name, "name cannot be empty or null"); if (StringUtils.hasText(value)) { - builder.queryParam( - UriUtils.encode(name, ISO_8859_1), - UriUtils.encode(value, ISO_8859_1) - ); + builder.queryParam(UriUtils.encode(name, ISO_8859_1), UriUtils.encode(value, ISO_8859_1)); } } - private void sendPost(HttpServletResponse response, Saml2AuthenticationRequestContext context) - throws IOException { - Saml2PostAuthenticationRequest authenticationRequest = - this.authenticationRequestFactory.createPostAuthenticationRequest(context); + private void sendPost(HttpServletResponse response, Saml2AuthenticationRequestContext context) throws IOException { + Saml2PostAuthenticationRequest authenticationRequest = this.authenticationRequestFactory + .createPostAuthenticationRequest(context); String html = createSamlPostRequestFormData(authenticationRequest); response.setContentType(MediaType.TEXT_HTML_VALUE); response.getWriter().write(html); @@ -191,42 +191,26 @@ public class Saml2WebSsoAuthenticationRequestFilter extends OncePerRequestFilter String authenticationRequestUri = authenticationRequest.getAuthenticationRequestUri(); String relayState = authenticationRequest.getRelayState(); String samlRequest = authenticationRequest.getSamlRequest(); - StringBuilder postHtml = new StringBuilder() - .append("\n") - .append("\n") - .append(" \n") - .append(" \n") - .append(" \n") - .append(" \n") - .append("

        \n") .append(" Note: Since your browser does not support JavaScript,\n") .append(" you must press the Continue button once to proceed.\n") - .append("

        \n") - .append(" \n") - .append(" \n") + .append("

        \n").append(" \n").append(" \n") .append("
        \n") .append("
        \n") .append(" \n"); + .append(HtmlUtils.htmlEscape(samlRequest)).append("\"/>\n"); if (StringUtils.hasText(relayState)) { - postHtml - .append(" \n"); + postHtml.append(" \n"); } - postHtml - .append("
        \n") - .append("
        \n").append(" \n") + .append(" \n").append(" \n").append(""); return postHtml.toString(); } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/DefaultRelyingPartyRegistrationResolver.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/DefaultRelyingPartyRegistrationResolver.java index 3768233fdf..bdc60fcc0b 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/DefaultRelyingPartyRegistrationResolver.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/DefaultRelyingPartyRegistrationResolver.java @@ -37,8 +37,8 @@ import static org.springframework.web.util.UriComponentsBuilder.fromHttpUrl; /** * A {@link Converter} that resolves a {@link RelyingPartyRegistration} by extracting the - * registration id from the request, querying a {@link RelyingPartyRegistrationRepository}, - * and resolving any template values. + * registration id from the request, querying a + * {@link RelyingPartyRegistrationRepository}, and resolving any template values. * * @since 5.4 * @author Josh Cummings @@ -49,10 +49,11 @@ public final class DefaultRelyingPartyRegistrationResolver private static final char PATH_DELIMITER = '/'; private final RelyingPartyRegistrationRepository relyingPartyRegistrationRepository; + private final Converter registrationIdResolver = new RegistrationIdResolver(); - public DefaultRelyingPartyRegistrationResolver - (RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) { + public DefaultRelyingPartyRegistrationResolver( + RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) { Assert.notNull(relyingPartyRegistrationRepository, "relyingPartyRegistrationRepository cannot be null"); this.relyingPartyRegistrationRepository = relyingPartyRegistrationRepository; @@ -64,8 +65,8 @@ public final class DefaultRelyingPartyRegistrationResolver if (registrationId == null) { return null; } - RelyingPartyRegistration relyingPartyRegistration = - this.relyingPartyRegistrationRepository.findByRegistrationId(registrationId); + RelyingPartyRegistration relyingPartyRegistration = this.relyingPartyRegistrationRepository + .findByRegistrationId(registrationId); if (relyingPartyRegistration == null) { return null; } @@ -73,12 +74,10 @@ public final class DefaultRelyingPartyRegistrationResolver String applicationUri = getApplicationUri(request); Function templateResolver = templateResolver(applicationUri, relyingPartyRegistration); String relyingPartyEntityId = templateResolver.apply(relyingPartyRegistration.getEntityId()); - String assertionConsumerServiceLocation = templateResolver.apply( - relyingPartyRegistration.getAssertionConsumerServiceLocation()); - return withRelyingPartyRegistration(relyingPartyRegistration) - .entityId(relyingPartyEntityId) - .assertionConsumerServiceLocation(assertionConsumerServiceLocation) - .build(); + String assertionConsumerServiceLocation = templateResolver + .apply(relyingPartyRegistration.getAssertionConsumerServiceLocation()); + return withRelyingPartyRegistration(relyingPartyRegistration).entityId(relyingPartyEntityId) + .assertionConsumerServiceLocation(assertionConsumerServiceLocation).build(); } private Function templateResolver(String applicationUri, RelyingPartyRegistration relyingParty) { @@ -89,9 +88,7 @@ public final class DefaultRelyingPartyRegistrationResolver String entityId = relyingParty.getAssertingPartyDetails().getEntityId(); String registrationId = relyingParty.getRegistrationId(); Map uriVariables = new HashMap<>(); - UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(baseUrl) - .replaceQuery(null) - .fragment(null) + UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(baseUrl).replaceQuery(null).fragment(null) .build(); String scheme = uriComponents.getScheme(); uriVariables.put("baseScheme", scheme == null ? "" : scheme); @@ -109,21 +106,17 @@ public final class DefaultRelyingPartyRegistrationResolver uriVariables.put("entityId", StringUtils.hasText(entityId) ? entityId : ""); uriVariables.put("registrationId", StringUtils.hasText(registrationId) ? registrationId : ""); - return UriComponentsBuilder.fromUriString(template) - .buildAndExpand(uriVariables) - .toUriString(); + return UriComponentsBuilder.fromUriString(template).buildAndExpand(uriVariables).toUriString(); } private static String getApplicationUri(HttpServletRequest request) { - UriComponents uriComponents = fromHttpUrl(buildFullRequestUrl(request)) - .replacePath(request.getContextPath()) - .replaceQuery(null) - .fragment(null) - .build(); + UriComponents uriComponents = fromHttpUrl(buildFullRequestUrl(request)).replacePath(request.getContextPath()) + .replaceQuery(null).fragment(null).build(); return uriComponents.toUriString(); } private static class RegistrationIdResolver implements Converter { + private final RequestMatcher requestMatcher = new AntPathRequestMatcher("/**/{registrationId}"); @Override @@ -131,5 +124,7 @@ public final class DefaultRelyingPartyRegistrationResolver RequestMatcher.MatchResult result = this.requestMatcher.matcher(request); return result.getVariables().get("registrationId"); } + } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/DefaultSaml2AuthenticationRequestContextResolver.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/DefaultSaml2AuthenticationRequestContextResolver.java index b9d15b7860..c6f40dc24d 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/DefaultSaml2AuthenticationRequestContextResolver.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/DefaultSaml2AuthenticationRequestContextResolver.java @@ -27,21 +27,23 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP import org.springframework.util.Assert; /** - * The default implementation for {@link Saml2AuthenticationRequestContextResolver} - * which uses the current request and given relying party to formulate a {@link Saml2AuthenticationRequestContext} + * The default implementation for {@link Saml2AuthenticationRequestContextResolver} which + * uses the current request and given relying party to formulate a + * {@link Saml2AuthenticationRequestContext} * * @author Shazin Sadakath * @author Josh Cummings * @since 5.4 */ -public final class DefaultSaml2AuthenticationRequestContextResolver implements Saml2AuthenticationRequestContextResolver { +public final class DefaultSaml2AuthenticationRequestContextResolver + implements Saml2AuthenticationRequestContextResolver { private final Log logger = LogFactory.getLog(getClass()); private final Converter relyingPartyRegistrationResolver; - public DefaultSaml2AuthenticationRequestContextResolver - (Converter relyingPartyRegistrationResolver) { + public DefaultSaml2AuthenticationRequestContextResolver( + Converter relyingPartyRegistrationResolver) { this.relyingPartyRegistrationResolver = relyingPartyRegistrationResolver; } @@ -56,20 +58,19 @@ public final class DefaultSaml2AuthenticationRequestContextResolver implements S return null; } if (this.logger.isDebugEnabled()) { - this.logger.debug("Creating SAML 2.0 Authentication Request for Asserting Party [" + - relyingParty.getRegistrationId() + "]"); + this.logger.debug("Creating SAML 2.0 Authentication Request for Asserting Party [" + + relyingParty.getRegistrationId() + "]"); } return createRedirectAuthenticationRequestContext(request, relyingParty); } - private Saml2AuthenticationRequestContext createRedirectAuthenticationRequestContext( - HttpServletRequest request, RelyingPartyRegistration relyingParty) { + private Saml2AuthenticationRequestContext createRedirectAuthenticationRequestContext(HttpServletRequest request, + RelyingPartyRegistration relyingParty) { - return Saml2AuthenticationRequestContext.builder() - .issuer(relyingParty.getEntityId()) + return Saml2AuthenticationRequestContext.builder().issuer(relyingParty.getEntityId()) .relyingPartyRegistration(relyingParty) .assertionConsumerServiceUrl(relyingParty.getAssertionConsumerServiceLocation()) - .relayState(request.getParameter("RelayState")) - .build(); + .relayState(request.getParameter("RelayState")).build(); } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/Saml2AuthenticationRequestContextResolver.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/Saml2AuthenticationRequestContextResolver.java index db24c8ff90..233d93b23d 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/Saml2AuthenticationRequestContextResolver.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/Saml2AuthenticationRequestContextResolver.java @@ -22,7 +22,8 @@ import org.springframework.security.saml2.provider.service.authentication.Saml2A /** * This {@code Saml2AuthenticationRequestContextResolver} formulates a - * SAML 2.0 AuthnRequest (line 1968) + * SAML 2.0 + * AuthnRequest (line 1968) * * @author Shazin Sadakath * @author Josh Cummings @@ -31,11 +32,11 @@ import org.springframework.security.saml2.provider.service.authentication.Saml2A public interface Saml2AuthenticationRequestContextResolver { /** - * This {@code resolve} method is defined to create a {@link Saml2AuthenticationRequestContext} - * - * + * This {@code resolve} method is defined to create a + * {@link Saml2AuthenticationRequestContext} * @param request the current request * @return the created {@link Saml2AuthenticationRequestContext} for the request */ Saml2AuthenticationRequestContext resolve(HttpServletRequest request); + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/Saml2AuthenticationTokenConverter.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/Saml2AuthenticationTokenConverter.java index 632ef955b9..29be8459f2 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/Saml2AuthenticationTokenConverter.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/Saml2AuthenticationTokenConverter.java @@ -35,26 +35,27 @@ import org.springframework.util.Assert; import static java.nio.charset.StandardCharsets.UTF_8; /** - * An {@link AuthenticationConverter} that generates a {@link Saml2AuthenticationToken} appropriate - * for authenticated a SAML 2.0 Assertion against an + * An {@link AuthenticationConverter} that generates a {@link Saml2AuthenticationToken} + * appropriate for authenticated a SAML 2.0 Assertion against an * {@link org.springframework.security.authentication.AuthenticationManager}. * * @author Josh Cummings * @since 5.4 */ public final class Saml2AuthenticationTokenConverter implements AuthenticationConverter { - private static Base64 BASE64 = new Base64(0, new byte[]{'\n'}); + + private static Base64 BASE64 = new Base64(0, new byte[] { '\n' }); private final Converter relyingPartyRegistrationResolver; /** - * Constructs a {@link Saml2AuthenticationTokenConverter} given a strategy for resolving + * Constructs a {@link Saml2AuthenticationTokenConverter} given a strategy for + * resolving {@link RelyingPartyRegistration}s + * @param relyingPartyRegistrationResolver the strategy for resolving * {@link RelyingPartyRegistration}s - * - * @param relyingPartyRegistrationResolver the strategy for resolving {@link RelyingPartyRegistration}s */ - public Saml2AuthenticationTokenConverter - (Converter relyingPartyRegistrationResolver) { + public Saml2AuthenticationTokenConverter( + Converter relyingPartyRegistrationResolver) { Assert.notNull(relyingPartyRegistrationResolver, "relyingPartyRegistrationResolver cannot be null"); this.relyingPartyRegistrationResolver = relyingPartyRegistrationResolver; } @@ -102,4 +103,5 @@ public final class Saml2AuthenticationTokenConverter implements AuthenticationCo throw new Saml2Exception("Unable to inflate string", e); } } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilter.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilter.java index 50cb27803c..097d79ea11 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilter.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilter.java @@ -42,6 +42,7 @@ import org.springframework.web.filter.OncePerRequestFilter; public final class Saml2MetadataFilter extends OncePerRequestFilter { private final Converter relyingPartyRegistrationConverter; + private final Saml2MetadataResolver saml2MetadataResolver; private RequestMatcher requestMatcher = new AntPathRequestMatcher( @@ -65,8 +66,7 @@ public final class Saml2MetadataFilter extends OncePerRequestFilter { return; } - RelyingPartyRegistration relyingPartyRegistration = - this.relyingPartyRegistrationConverter.convert(request); + RelyingPartyRegistration relyingPartyRegistration = this.relyingPartyRegistrationConverter.convert(request); if (relyingPartyRegistration == null) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return; @@ -88,13 +88,13 @@ public final class Saml2MetadataFilter extends OncePerRequestFilter { } /** - * Set the {@link RequestMatcher} that determines whether this filter should - * handle the incoming {@link HttpServletRequest} - * + * Set the {@link RequestMatcher} that determines whether this filter should handle + * the incoming {@link HttpServletRequest} * @param requestMatcher */ public void setRequestMatcher(RequestMatcher requestMatcher) { Assert.notNull(requestMatcher, "requestMatcher cannot be null"); this.requestMatcher = requestMatcher; } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/OpenSamlInitializationServiceTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/OpenSamlInitializationServiceTests.java index 5a09bf70d9..ca2924b3fd 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/OpenSamlInitializationServiceTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/OpenSamlInitializationServiceTests.java @@ -37,8 +37,8 @@ public class OpenSamlInitializationServiceTests { OpenSamlInitializationService.initialize(); XMLObjectProviderRegistry registry = ConfigurationService.get(XMLObjectProviderRegistry.class); assertThat(registry.getParserPool()).isNotNull(); - assertThatCode(() -> OpenSamlInitializationService.requireInitialize(r -> {})) - .isInstanceOf(Saml2Exception.class) - .hasMessageContaining("OpenSAML was already initialized previously"); + assertThatCode(() -> OpenSamlInitializationService.requireInitialize(r -> { + })).isInstanceOf(Saml2Exception.class).hasMessageContaining("OpenSAML was already initialized previously"); } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/Saml2Utils.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/Saml2Utils.java index 3de1cecc9b..7e0c1773ad 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/Saml2Utils.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/Saml2Utils.java @@ -32,7 +32,7 @@ import static java.util.zip.Deflater.DEFLATED; public final class Saml2Utils { - private static Base64 BASE64 = new Base64(0, new byte[]{'\n'}); + private static Base64 BASE64 = new Base64(0, new byte[] { '\n' }); public static String samlEncode(byte[] b) { return BASE64.encodeAsString(b); @@ -67,4 +67,5 @@ public final class Saml2Utils { throw new Saml2Exception("Unable to inflate string", e); } } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/Saml2X509CredentialTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/Saml2X509CredentialTests.java index e3f7b32109..600f2a4260 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/Saml2X509CredentialTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/Saml2X509CredentialTests.java @@ -40,44 +40,43 @@ public class Saml2X509CredentialTests { public ExpectedException exception = ExpectedException.none(); private PrivateKey key; + private X509Certificate certificate; @Before public void setup() throws Exception { - String keyData = "-----BEGIN PRIVATE KEY-----\n" + - "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANG7v8QjQGU3MwQE\n" + - "VUBxvH6Uuiy/MhZT7TV0ZNjyAF2ExA1gpn3aUxx6jYK5UnrpxRRE/KbeLucYbOhK\n" + - "cDECt77Rggz5TStrOta0BQTvfluRyoQtmQ5Nkt6Vqg7O2ZapFt7k64Sal7AftzH6\n" + - "Q2BxWN1y04bLdDrH4jipqRj/2qEFAgMBAAECgYEAj4ExY1jjdN3iEDuOwXuRB+Nn\n" + - "x7pC4TgntE2huzdKvLJdGvIouTArce8A6JM5NlTBvm69mMepvAHgcsiMH1zGr5J5\n" + - "wJz23mGOyhM1veON41/DJTVG+cxq4soUZhdYy3bpOuXGMAaJ8QLMbQQoivllNihd\n" + - "vwH0rNSK8LTYWWPZYIECQQDxct+TFX1VsQ1eo41K0T4fu2rWUaxlvjUGhK6HxTmY\n" + - "8OMJptunGRJL1CUjIb45Uz7SP8TPz5FwhXWsLfS182kRAkEA3l+Qd9C9gdpUh1uX\n" + - "oPSNIxn5hFUrSTW1EwP9QH9vhwb5Vr8Jrd5ei678WYDLjUcx648RjkjhU9jSMzIx\n" + - "EGvYtQJBAMm/i9NR7IVyyNIgZUpz5q4LI21rl1r4gUQuD8vA36zM81i4ROeuCly0\n" + - "KkfdxR4PUfnKcQCX11YnHjk9uTFj75ECQEFY/gBnxDjzqyF35hAzrYIiMPQVfznt\n" + - "YX/sDTE2AdVBVGaMj1Cb51bPHnNC6Q5kXKQnj/YrLqRQND09Q7ParX0CQQC5NxZr\n" + - "9jKqhHj8yQD6PlXTsY4Occ7DH6/IoDenfdEVD5qlet0zmd50HatN2Jiqm5ubN7CM\n" + - "INrtuLp4YHbgk1mi\n" + - "-----END PRIVATE KEY-----"; + String keyData = "-----BEGIN PRIVATE KEY-----\n" + + "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANG7v8QjQGU3MwQE\n" + + "VUBxvH6Uuiy/MhZT7TV0ZNjyAF2ExA1gpn3aUxx6jYK5UnrpxRRE/KbeLucYbOhK\n" + + "cDECt77Rggz5TStrOta0BQTvfluRyoQtmQ5Nkt6Vqg7O2ZapFt7k64Sal7AftzH6\n" + + "Q2BxWN1y04bLdDrH4jipqRj/2qEFAgMBAAECgYEAj4ExY1jjdN3iEDuOwXuRB+Nn\n" + + "x7pC4TgntE2huzdKvLJdGvIouTArce8A6JM5NlTBvm69mMepvAHgcsiMH1zGr5J5\n" + + "wJz23mGOyhM1veON41/DJTVG+cxq4soUZhdYy3bpOuXGMAaJ8QLMbQQoivllNihd\n" + + "vwH0rNSK8LTYWWPZYIECQQDxct+TFX1VsQ1eo41K0T4fu2rWUaxlvjUGhK6HxTmY\n" + + "8OMJptunGRJL1CUjIb45Uz7SP8TPz5FwhXWsLfS182kRAkEA3l+Qd9C9gdpUh1uX\n" + + "oPSNIxn5hFUrSTW1EwP9QH9vhwb5Vr8Jrd5ei678WYDLjUcx648RjkjhU9jSMzIx\n" + + "EGvYtQJBAMm/i9NR7IVyyNIgZUpz5q4LI21rl1r4gUQuD8vA36zM81i4ROeuCly0\n" + + "KkfdxR4PUfnKcQCX11YnHjk9uTFj75ECQEFY/gBnxDjzqyF35hAzrYIiMPQVfznt\n" + + "YX/sDTE2AdVBVGaMj1Cb51bPHnNC6Q5kXKQnj/YrLqRQND09Q7ParX0CQQC5NxZr\n" + + "9jKqhHj8yQD6PlXTsY4Occ7DH6/IoDenfdEVD5qlet0zmd50HatN2Jiqm5ubN7CM\n" + "INrtuLp4YHbgk1mi\n" + + "-----END PRIVATE KEY-----"; key = RsaKeyConverters.pkcs8().convert(new ByteArrayInputStream(keyData.getBytes(UTF_8))); final CertificateFactory factory = CertificateFactory.getInstance("X.509"); - String certificateData = "-----BEGIN CERTIFICATE-----\n" + - "MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMC\n" + - "VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEjAQBgNVBAcMCVZhbmNvdXZlcjEdMBsG\n" + - "A1UECgwUU3ByaW5nIFNlY3VyaXR5IFNBTUwxCzAJBgNVBAsMAnNwMSAwHgYDVQQD\n" + - "DBdzcC5zcHJpbmcuc2VjdXJpdHkuc2FtbDAeFw0xODA1MTQxNDMwNDRaFw0yODA1\n" + - "MTExNDMwNDRaMIGEMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjES\n" + - "MBAGA1UEBwwJVmFuY291dmVyMR0wGwYDVQQKDBRTcHJpbmcgU2VjdXJpdHkgU0FN\n" + - "TDELMAkGA1UECwwCc3AxIDAeBgNVBAMMF3NwLnNwcmluZy5zZWN1cml0eS5zYW1s\n" + - "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRu7/EI0BlNzMEBFVAcbx+lLos\n" + - "vzIWU+01dGTY8gBdhMQNYKZ92lMceo2CuVJ66cUURPym3i7nGGzoSnAxAre+0YIM\n" + - "+U0razrWtAUE735bkcqELZkOTZLelaoOztmWqRbe5OuEmpewH7cx+kNgcVjdctOG\n" + - "y3Q6x+I4qakY/9qhBQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAAeViTvHOyQopWEi\n" + - "XOfI2Z9eukwrSknDwq/zscR0YxwwqDBMt/QdAODfSwAfnciiYLkmEjlozWRtOeN+\n" + - "qK7UFgP1bRl5qksrYX5S0z2iGJh0GvonLUt3e20Ssfl5tTEDDnAEUMLfBkyaxEHD\n" + - "RZ/nbTJ7VTeZOSyRoVn5XHhpuJ0B\n" + - "-----END CERTIFICATE-----"; + String certificateData = "-----BEGIN CERTIFICATE-----\n" + + "MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMC\n" + + "VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEjAQBgNVBAcMCVZhbmNvdXZlcjEdMBsG\n" + + "A1UECgwUU3ByaW5nIFNlY3VyaXR5IFNBTUwxCzAJBgNVBAsMAnNwMSAwHgYDVQQD\n" + + "DBdzcC5zcHJpbmcuc2VjdXJpdHkuc2FtbDAeFw0xODA1MTQxNDMwNDRaFw0yODA1\n" + + "MTExNDMwNDRaMIGEMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjES\n" + + "MBAGA1UEBwwJVmFuY291dmVyMR0wGwYDVQQKDBRTcHJpbmcgU2VjdXJpdHkgU0FN\n" + + "TDELMAkGA1UECwwCc3AxIDAeBgNVBAMMF3NwLnNwcmluZy5zZWN1cml0eS5zYW1s\n" + + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRu7/EI0BlNzMEBFVAcbx+lLos\n" + + "vzIWU+01dGTY8gBdhMQNYKZ92lMceo2CuVJ66cUURPym3i7nGGzoSnAxAre+0YIM\n" + + "+U0razrWtAUE735bkcqELZkOTZLelaoOztmWqRbe5OuEmpewH7cx+kNgcVjdctOG\n" + + "y3Q6x+I4qakY/9qhBQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAAeViTvHOyQopWEi\n" + + "XOfI2Z9eukwrSknDwq/zscR0YxwwqDBMt/QdAODfSwAfnciiYLkmEjlozWRtOeN+\n" + + "qK7UFgP1bRl5qksrYX5S0z2iGJh0GvonLUt3e20Ssfl5tTEDDnAEUMLfBkyaxEHD\n" + + "RZ/nbTJ7VTeZOSyRoVn5XHhpuJ0B\n" + "-----END CERTIFICATE-----"; certificate = (X509Certificate) factory .generateCertificate(new ByteArrayInputStream(certificateData.getBytes(UTF_8))); } @@ -195,4 +194,5 @@ public class Saml2X509CredentialTests { exception.expect(IllegalArgumentException.class); Saml2X509Credential.encryption(null); } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/TestSaml2X509Credentials.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/TestSaml2X509Credentials.java index f2d711882e..2df52901cd 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/TestSaml2X509Credentials.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/core/TestSaml2X509Credentials.java @@ -34,6 +34,7 @@ import static org.springframework.security.saml2.core.Saml2X509Credential.Saml2X import static org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType.VERIFICATION; public final class TestSaml2X509Credentials { + public static Saml2X509Credential assertingPartySigningCredential() { return new Saml2X509Credential(idpPrivateKey(), idpCertificate(), SIGNING); } @@ -61,9 +62,7 @@ public final class TestSaml2X509Credentials { private static X509Certificate certificate(String cert) { ByteArrayInputStream certBytes = new ByteArrayInputStream(cert.getBytes()); try { - return (X509Certificate) CertificateFactory - .getInstance("X.509") - .generateCertificate(certBytes); + return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(certBytes); } catch (CertificateException e) { throw new Saml2Exception(e); @@ -79,101 +78,97 @@ public final class TestSaml2X509Credentials { } } - private static X509Certificate idpCertificate() { - return certificate("-----BEGIN CERTIFICATE-----\n" - + "MIIEEzCCAvugAwIBAgIJAIc1qzLrv+5nMA0GCSqGSIb3DQEBCwUAMIGfMQswCQYD\n" - + "VQQGEwJVUzELMAkGA1UECAwCQ08xFDASBgNVBAcMC0Nhc3RsZSBSb2NrMRwwGgYD\n" - + "VQQKDBNTYW1sIFRlc3RpbmcgU2VydmVyMQswCQYDVQQLDAJJVDEgMB4GA1UEAwwX\n" - + "c2ltcGxlc2FtbHBocC5jZmFwcHMuaW8xIDAeBgkqhkiG9w0BCQEWEWZoYW5pa0Bw\n" - + "aXZvdGFsLmlvMB4XDTE1MDIyMzIyNDUwM1oXDTI1MDIyMjIyNDUwM1owgZ8xCzAJ\n" - + "BgNVBAYTAlVTMQswCQYDVQQIDAJDTzEUMBIGA1UEBwwLQ2FzdGxlIFJvY2sxHDAa\n" - + "BgNVBAoME1NhbWwgVGVzdGluZyBTZXJ2ZXIxCzAJBgNVBAsMAklUMSAwHgYDVQQD\n" - + "DBdzaW1wbGVzYW1scGhwLmNmYXBwcy5pbzEgMB4GCSqGSIb3DQEJARYRZmhhbmlr\n" - + "QHBpdm90YWwuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4cn62\n" - + "E1xLqpN34PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz\n" - + "2ZivLwZXW+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWW\n" - + "RDodcoHEfDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQ\n" - + "nX8Ttl7hZ6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5\n" - + "cljz0X/TXy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gph\n" - + "iJH3jvZ7I+J5lS8VAgMBAAGjUDBOMB0GA1UdDgQWBBTTyP6Cc5HlBJ5+ucVCwGc5\n" - + "ogKNGzAfBgNVHSMEGDAWgBTTyP6Cc5HlBJ5+ucVCwGc5ogKNGzAMBgNVHRMEBTAD\n" - + "AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAvMS4EQeP/ipV4jOG5lO6/tYCb/iJeAduO\n" - + "nRhkJk0DbX329lDLZhTTL/x/w/9muCVcvLrzEp6PN+VWfw5E5FWtZN0yhGtP9R+v\n" - + "ZnrV+oc2zGD+no1/ySFOe3EiJCO5dehxKjYEmBRv5sU/LZFKZpozKN/BMEa6CqLu\n" - + "xbzb7ykxVr7EVFXwltPxzE9TmL9OACNNyF5eJHWMRMllarUvkcXlh4pux4ks9e6z\n" - + "V9DQBy2zds9f1I3qxg0eX6JnGrXi/ZiCT+lJgVe3ZFXiejiLAiKB04sXW3ti0LW3\n" - + "lx13Y1YlQ4/tlpgTgfIJxKV6nyPiLoK0nywbMd+vpAirDt2Oc+hk\n" - + "-----END CERTIFICATE-----\n"); + private static X509Certificate idpCertificate() { + return certificate( + "-----BEGIN CERTIFICATE-----\n" + "MIIEEzCCAvugAwIBAgIJAIc1qzLrv+5nMA0GCSqGSIb3DQEBCwUAMIGfMQswCQYD\n" + + "VQQGEwJVUzELMAkGA1UECAwCQ08xFDASBgNVBAcMC0Nhc3RsZSBSb2NrMRwwGgYD\n" + + "VQQKDBNTYW1sIFRlc3RpbmcgU2VydmVyMQswCQYDVQQLDAJJVDEgMB4GA1UEAwwX\n" + + "c2ltcGxlc2FtbHBocC5jZmFwcHMuaW8xIDAeBgkqhkiG9w0BCQEWEWZoYW5pa0Bw\n" + + "aXZvdGFsLmlvMB4XDTE1MDIyMzIyNDUwM1oXDTI1MDIyMjIyNDUwM1owgZ8xCzAJ\n" + + "BgNVBAYTAlVTMQswCQYDVQQIDAJDTzEUMBIGA1UEBwwLQ2FzdGxlIFJvY2sxHDAa\n" + + "BgNVBAoME1NhbWwgVGVzdGluZyBTZXJ2ZXIxCzAJBgNVBAsMAklUMSAwHgYDVQQD\n" + + "DBdzaW1wbGVzYW1scGhwLmNmYXBwcy5pbzEgMB4GCSqGSIb3DQEJARYRZmhhbmlr\n" + + "QHBpdm90YWwuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4cn62\n" + + "E1xLqpN34PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz\n" + + "2ZivLwZXW+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWW\n" + + "RDodcoHEfDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQ\n" + + "nX8Ttl7hZ6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5\n" + + "cljz0X/TXy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gph\n" + + "iJH3jvZ7I+J5lS8VAgMBAAGjUDBOMB0GA1UdDgQWBBTTyP6Cc5HlBJ5+ucVCwGc5\n" + + "ogKNGzAfBgNVHSMEGDAWgBTTyP6Cc5HlBJ5+ucVCwGc5ogKNGzAMBgNVHRMEBTAD\n" + + "AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAvMS4EQeP/ipV4jOG5lO6/tYCb/iJeAduO\n" + + "nRhkJk0DbX329lDLZhTTL/x/w/9muCVcvLrzEp6PN+VWfw5E5FWtZN0yhGtP9R+v\n" + + "ZnrV+oc2zGD+no1/ySFOe3EiJCO5dehxKjYEmBRv5sU/LZFKZpozKN/BMEa6CqLu\n" + + "xbzb7ykxVr7EVFXwltPxzE9TmL9OACNNyF5eJHWMRMllarUvkcXlh4pux4ks9e6z\n" + + "V9DQBy2zds9f1I3qxg0eX6JnGrXi/ZiCT+lJgVe3ZFXiejiLAiKB04sXW3ti0LW3\n" + + "lx13Y1YlQ4/tlpgTgfIJxKV6nyPiLoK0nywbMd+vpAirDt2Oc+hk\n" + "-----END CERTIFICATE-----\n"); } - private static PrivateKey idpPrivateKey() { - return privateKey("-----BEGIN PRIVATE KEY-----\n" - + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC4cn62E1xLqpN3\n" - + "4PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz2ZivLwZX\n" - + "W+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWWRDodcoHE\n" - + "fDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQnX8Ttl7h\n" - + "Z6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5cljz0X/T\n" - + "Xy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gphiJH3jvZ7\n" - + "I+J5lS8VAgMBAAECggEBAKyxBlIS7mcp3chvq0RF7B3PHFJMMzkwE+t3pLJcs4cZ\n" - + "nezh/KbREfP70QjXzk/llnZCvxeIs5vRu24vbdBm79qLHqBuHp8XfHHtuo2AfoAQ\n" - + "l4h047Xc/+TKMivnPQ0jX9qqndKDLqZDf5wnbslDmlskvF0a/MjsLU0TxtOfo+dB\n" - + "t55FW11cGqxZwhS5Gnr+cbw3OkHz23b9gEOt9qfwPVepeysbmm9FjU+k4yVa7rAN\n" - + "xcbzVb6Y7GCITe2tgvvEHmjB9BLmWrH3mZ3Af17YU/iN6TrpPd6Sj3QoS+2wGtAe\n" - + "HbUs3CKJu7bIHcj4poal6Kh8519S+erJTtqQ8M0ZiEECgYEA43hLYAPaUueFkdfh\n" - + "9K/7ClH6436CUH3VdizwUXi26fdhhV/I/ot6zLfU2mgEHU22LBECWQGtAFm8kv0P\n" - + "zPn+qjaR3e62l5PIlSYbnkIidzoDZ2ztu4jF5LgStlTJQPteFEGgZVl5o9DaSZOq\n" - + "Yd7G3XqXuQ1VGMW58G5FYJPtA1cCgYEAz5TPUtK+R2KXHMjUwlGY9AefQYRYmyX2\n" - + "Tn/OFgKvY8lpAkMrhPKONq7SMYc8E9v9G7A0dIOXvW7QOYSapNhKU+np3lUafR5F\n" - + "4ZN0bxZ9qjHbn3AMYeraKjeutHvlLtbHdIc1j3sxe/EzltRsYmiqLdEBW0p6hwWg\n" - + "tyGhYWVyaXMCgYAfDOKtHpmEy5nOCLwNXKBWDk7DExfSyPqEgSnk1SeS1HP5ctPK\n" - + "+1st6sIhdiVpopwFc+TwJWxqKdW18tlfT5jVv1E2DEnccw3kXilS9xAhWkfwrEvf\n" - + "V5I74GydewFl32o+NZ8hdo9GL1I8zO1rIq/et8dSOWGuWf9BtKu/vTGTTQKBgFxU\n" - + "VjsCnbvmsEwPUAL2hE/WrBFaKocnxXx5AFNt8lEyHtDwy4Sg1nygGcIJ4sD6koQk\n" - + "RdClT3LkvR04TAiSY80bN/i6ZcPNGUwSaDGZEWAIOSWbkwZijZNFnSGOEgxZX/IG\n" - + "yd39766vREEMTwEeiMNEOZQ/dmxkJm4OOVe25cLdAoGACOtPnq1Fxay80UYBf4rQ\n" - + "+bJ9yX1ulB8WIree1hD7OHSB2lRHxrVYWrglrTvkh63Lgx+EcsTV788OsvAVfPPz\n" - + "BZrn8SdDlQqalMxUBYEFwnsYD3cQ8yOUnijFVC4xNcdDv8OIqVgSk4KKxU5AshaA\n" + "xk6Mox+u8Cc2eAK12H13i+8=\n" - + "-----END PRIVATE KEY-----\n"); + return privateKey( + "-----BEGIN PRIVATE KEY-----\n" + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC4cn62E1xLqpN3\n" + + "4PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz2ZivLwZX\n" + + "W+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWWRDodcoHE\n" + + "fDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQnX8Ttl7h\n" + + "Z6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5cljz0X/T\n" + + "Xy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gphiJH3jvZ7\n" + + "I+J5lS8VAgMBAAECggEBAKyxBlIS7mcp3chvq0RF7B3PHFJMMzkwE+t3pLJcs4cZ\n" + + "nezh/KbREfP70QjXzk/llnZCvxeIs5vRu24vbdBm79qLHqBuHp8XfHHtuo2AfoAQ\n" + + "l4h047Xc/+TKMivnPQ0jX9qqndKDLqZDf5wnbslDmlskvF0a/MjsLU0TxtOfo+dB\n" + + "t55FW11cGqxZwhS5Gnr+cbw3OkHz23b9gEOt9qfwPVepeysbmm9FjU+k4yVa7rAN\n" + + "xcbzVb6Y7GCITe2tgvvEHmjB9BLmWrH3mZ3Af17YU/iN6TrpPd6Sj3QoS+2wGtAe\n" + + "HbUs3CKJu7bIHcj4poal6Kh8519S+erJTtqQ8M0ZiEECgYEA43hLYAPaUueFkdfh\n" + + "9K/7ClH6436CUH3VdizwUXi26fdhhV/I/ot6zLfU2mgEHU22LBECWQGtAFm8kv0P\n" + + "zPn+qjaR3e62l5PIlSYbnkIidzoDZ2ztu4jF5LgStlTJQPteFEGgZVl5o9DaSZOq\n" + + "Yd7G3XqXuQ1VGMW58G5FYJPtA1cCgYEAz5TPUtK+R2KXHMjUwlGY9AefQYRYmyX2\n" + + "Tn/OFgKvY8lpAkMrhPKONq7SMYc8E9v9G7A0dIOXvW7QOYSapNhKU+np3lUafR5F\n" + + "4ZN0bxZ9qjHbn3AMYeraKjeutHvlLtbHdIc1j3sxe/EzltRsYmiqLdEBW0p6hwWg\n" + + "tyGhYWVyaXMCgYAfDOKtHpmEy5nOCLwNXKBWDk7DExfSyPqEgSnk1SeS1HP5ctPK\n" + + "+1st6sIhdiVpopwFc+TwJWxqKdW18tlfT5jVv1E2DEnccw3kXilS9xAhWkfwrEvf\n" + + "V5I74GydewFl32o+NZ8hdo9GL1I8zO1rIq/et8dSOWGuWf9BtKu/vTGTTQKBgFxU\n" + + "VjsCnbvmsEwPUAL2hE/WrBFaKocnxXx5AFNt8lEyHtDwy4Sg1nygGcIJ4sD6koQk\n" + + "RdClT3LkvR04TAiSY80bN/i6ZcPNGUwSaDGZEWAIOSWbkwZijZNFnSGOEgxZX/IG\n" + + "yd39766vREEMTwEeiMNEOZQ/dmxkJm4OOVe25cLdAoGACOtPnq1Fxay80UYBf4rQ\n" + + "+bJ9yX1ulB8WIree1hD7OHSB2lRHxrVYWrglrTvkh63Lgx+EcsTV788OsvAVfPPz\n" + + "BZrn8SdDlQqalMxUBYEFwnsYD3cQ8yOUnijFVC4xNcdDv8OIqVgSk4KKxU5AshaA\n" + + "xk6Mox+u8Cc2eAK12H13i+8=\n" + "-----END PRIVATE KEY-----\n"); } private static X509Certificate spCertificate() { - return certificate("-----BEGIN CERTIFICATE-----\n" + - "MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMC\n" + - "VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEjAQBgNVBAcMCVZhbmNvdXZlcjEdMBsG\n" + - "A1UECgwUU3ByaW5nIFNlY3VyaXR5IFNBTUwxCzAJBgNVBAsMAnNwMSAwHgYDVQQD\n" + - "DBdzcC5zcHJpbmcuc2VjdXJpdHkuc2FtbDAeFw0xODA1MTQxNDMwNDRaFw0yODA1\n" + - "MTExNDMwNDRaMIGEMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjES\n" + - "MBAGA1UEBwwJVmFuY291dmVyMR0wGwYDVQQKDBRTcHJpbmcgU2VjdXJpdHkgU0FN\n" + - "TDELMAkGA1UECwwCc3AxIDAeBgNVBAMMF3NwLnNwcmluZy5zZWN1cml0eS5zYW1s\n" + - "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRu7/EI0BlNzMEBFVAcbx+lLos\n" + - "vzIWU+01dGTY8gBdhMQNYKZ92lMceo2CuVJ66cUURPym3i7nGGzoSnAxAre+0YIM\n" + - "+U0razrWtAUE735bkcqELZkOTZLelaoOztmWqRbe5OuEmpewH7cx+kNgcVjdctOG\n" + - "y3Q6x+I4qakY/9qhBQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAAeViTvHOyQopWEi\n" + - "XOfI2Z9eukwrSknDwq/zscR0YxwwqDBMt/QdAODfSwAfnciiYLkmEjlozWRtOeN+\n" + - "qK7UFgP1bRl5qksrYX5S0z2iGJh0GvonLUt3e20Ssfl5tTEDDnAEUMLfBkyaxEHD\n" + - "RZ/nbTJ7VTeZOSyRoVn5XHhpuJ0B\n" + - "-----END CERTIFICATE-----"); + return certificate( + "-----BEGIN CERTIFICATE-----\n" + "MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMC\n" + + "VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEjAQBgNVBAcMCVZhbmNvdXZlcjEdMBsG\n" + + "A1UECgwUU3ByaW5nIFNlY3VyaXR5IFNBTUwxCzAJBgNVBAsMAnNwMSAwHgYDVQQD\n" + + "DBdzcC5zcHJpbmcuc2VjdXJpdHkuc2FtbDAeFw0xODA1MTQxNDMwNDRaFw0yODA1\n" + + "MTExNDMwNDRaMIGEMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjES\n" + + "MBAGA1UEBwwJVmFuY291dmVyMR0wGwYDVQQKDBRTcHJpbmcgU2VjdXJpdHkgU0FN\n" + + "TDELMAkGA1UECwwCc3AxIDAeBgNVBAMMF3NwLnNwcmluZy5zZWN1cml0eS5zYW1s\n" + + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRu7/EI0BlNzMEBFVAcbx+lLos\n" + + "vzIWU+01dGTY8gBdhMQNYKZ92lMceo2CuVJ66cUURPym3i7nGGzoSnAxAre+0YIM\n" + + "+U0razrWtAUE735bkcqELZkOTZLelaoOztmWqRbe5OuEmpewH7cx+kNgcVjdctOG\n" + + "y3Q6x+I4qakY/9qhBQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAAeViTvHOyQopWEi\n" + + "XOfI2Z9eukwrSknDwq/zscR0YxwwqDBMt/QdAODfSwAfnciiYLkmEjlozWRtOeN+\n" + + "qK7UFgP1bRl5qksrYX5S0z2iGJh0GvonLUt3e20Ssfl5tTEDDnAEUMLfBkyaxEHD\n" + + "RZ/nbTJ7VTeZOSyRoVn5XHhpuJ0B\n" + "-----END CERTIFICATE-----"); } private static PrivateKey spPrivateKey() { - return privateKey("-----BEGIN PRIVATE KEY-----\n" + - "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANG7v8QjQGU3MwQE\n" + - "VUBxvH6Uuiy/MhZT7TV0ZNjyAF2ExA1gpn3aUxx6jYK5UnrpxRRE/KbeLucYbOhK\n" + - "cDECt77Rggz5TStrOta0BQTvfluRyoQtmQ5Nkt6Vqg7O2ZapFt7k64Sal7AftzH6\n" + - "Q2BxWN1y04bLdDrH4jipqRj/2qEFAgMBAAECgYEAj4ExY1jjdN3iEDuOwXuRB+Nn\n" + - "x7pC4TgntE2huzdKvLJdGvIouTArce8A6JM5NlTBvm69mMepvAHgcsiMH1zGr5J5\n" + - "wJz23mGOyhM1veON41/DJTVG+cxq4soUZhdYy3bpOuXGMAaJ8QLMbQQoivllNihd\n" + - "vwH0rNSK8LTYWWPZYIECQQDxct+TFX1VsQ1eo41K0T4fu2rWUaxlvjUGhK6HxTmY\n" + - "8OMJptunGRJL1CUjIb45Uz7SP8TPz5FwhXWsLfS182kRAkEA3l+Qd9C9gdpUh1uX\n" + - "oPSNIxn5hFUrSTW1EwP9QH9vhwb5Vr8Jrd5ei678WYDLjUcx648RjkjhU9jSMzIx\n" + - "EGvYtQJBAMm/i9NR7IVyyNIgZUpz5q4LI21rl1r4gUQuD8vA36zM81i4ROeuCly0\n" + - "KkfdxR4PUfnKcQCX11YnHjk9uTFj75ECQEFY/gBnxDjzqyF35hAzrYIiMPQVfznt\n" + - "YX/sDTE2AdVBVGaMj1Cb51bPHnNC6Q5kXKQnj/YrLqRQND09Q7ParX0CQQC5NxZr\n" + - "9jKqhHj8yQD6PlXTsY4Occ7DH6/IoDenfdEVD5qlet0zmd50HatN2Jiqm5ubN7CM\n" + - "INrtuLp4YHbgk1mi\n" + - "-----END PRIVATE KEY-----"); + return privateKey( + "-----BEGIN PRIVATE KEY-----\n" + "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANG7v8QjQGU3MwQE\n" + + "VUBxvH6Uuiy/MhZT7TV0ZNjyAF2ExA1gpn3aUxx6jYK5UnrpxRRE/KbeLucYbOhK\n" + + "cDECt77Rggz5TStrOta0BQTvfluRyoQtmQ5Nkt6Vqg7O2ZapFt7k64Sal7AftzH6\n" + + "Q2BxWN1y04bLdDrH4jipqRj/2qEFAgMBAAECgYEAj4ExY1jjdN3iEDuOwXuRB+Nn\n" + + "x7pC4TgntE2huzdKvLJdGvIouTArce8A6JM5NlTBvm69mMepvAHgcsiMH1zGr5J5\n" + + "wJz23mGOyhM1veON41/DJTVG+cxq4soUZhdYy3bpOuXGMAaJ8QLMbQQoivllNihd\n" + + "vwH0rNSK8LTYWWPZYIECQQDxct+TFX1VsQ1eo41K0T4fu2rWUaxlvjUGhK6HxTmY\n" + + "8OMJptunGRJL1CUjIb45Uz7SP8TPz5FwhXWsLfS182kRAkEA3l+Qd9C9gdpUh1uX\n" + + "oPSNIxn5hFUrSTW1EwP9QH9vhwb5Vr8Jrd5ei678WYDLjUcx648RjkjhU9jSMzIx\n" + + "EGvYtQJBAMm/i9NR7IVyyNIgZUpz5q4LI21rl1r4gUQuD8vA36zM81i4ROeuCly0\n" + + "KkfdxR4PUfnKcQCX11YnHjk9uTFj75ECQEFY/gBnxDjzqyF35hAzrYIiMPQVfznt\n" + + "YX/sDTE2AdVBVGaMj1Cb51bPHnNC6Q5kXKQnj/YrLqRQND09Q7ParX0CQQC5NxZr\n" + + "9jKqhHj8yQD6PlXTsY4Occ7DH6/IoDenfdEVD5qlet0zmd50HatN2Jiqm5ubN7CM\n" + "INrtuLp4YHbgk1mi\n" + + "-----END PRIVATE KEY-----"); } } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/credentials/Saml2X509CredentialTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/credentials/Saml2X509CredentialTests.java index 292619040d..db58fd8f5a 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/credentials/Saml2X509CredentialTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/credentials/Saml2X509CredentialTests.java @@ -40,45 +40,45 @@ public class Saml2X509CredentialTests { public ExpectedException exception = ExpectedException.none(); private Saml2X509Credential credential; + private PrivateKey key; + private X509Certificate certificate; @Before public void setup() throws Exception { - String keyData = "-----BEGIN PRIVATE KEY-----\n" + - "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANG7v8QjQGU3MwQE\n" + - "VUBxvH6Uuiy/MhZT7TV0ZNjyAF2ExA1gpn3aUxx6jYK5UnrpxRRE/KbeLucYbOhK\n" + - "cDECt77Rggz5TStrOta0BQTvfluRyoQtmQ5Nkt6Vqg7O2ZapFt7k64Sal7AftzH6\n" + - "Q2BxWN1y04bLdDrH4jipqRj/2qEFAgMBAAECgYEAj4ExY1jjdN3iEDuOwXuRB+Nn\n" + - "x7pC4TgntE2huzdKvLJdGvIouTArce8A6JM5NlTBvm69mMepvAHgcsiMH1zGr5J5\n" + - "wJz23mGOyhM1veON41/DJTVG+cxq4soUZhdYy3bpOuXGMAaJ8QLMbQQoivllNihd\n" + - "vwH0rNSK8LTYWWPZYIECQQDxct+TFX1VsQ1eo41K0T4fu2rWUaxlvjUGhK6HxTmY\n" + - "8OMJptunGRJL1CUjIb45Uz7SP8TPz5FwhXWsLfS182kRAkEA3l+Qd9C9gdpUh1uX\n" + - "oPSNIxn5hFUrSTW1EwP9QH9vhwb5Vr8Jrd5ei678WYDLjUcx648RjkjhU9jSMzIx\n" + - "EGvYtQJBAMm/i9NR7IVyyNIgZUpz5q4LI21rl1r4gUQuD8vA36zM81i4ROeuCly0\n" + - "KkfdxR4PUfnKcQCX11YnHjk9uTFj75ECQEFY/gBnxDjzqyF35hAzrYIiMPQVfznt\n" + - "YX/sDTE2AdVBVGaMj1Cb51bPHnNC6Q5kXKQnj/YrLqRQND09Q7ParX0CQQC5NxZr\n" + - "9jKqhHj8yQD6PlXTsY4Occ7DH6/IoDenfdEVD5qlet0zmd50HatN2Jiqm5ubN7CM\n" + - "INrtuLp4YHbgk1mi\n" + - "-----END PRIVATE KEY-----"; + String keyData = "-----BEGIN PRIVATE KEY-----\n" + + "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANG7v8QjQGU3MwQE\n" + + "VUBxvH6Uuiy/MhZT7TV0ZNjyAF2ExA1gpn3aUxx6jYK5UnrpxRRE/KbeLucYbOhK\n" + + "cDECt77Rggz5TStrOta0BQTvfluRyoQtmQ5Nkt6Vqg7O2ZapFt7k64Sal7AftzH6\n" + + "Q2BxWN1y04bLdDrH4jipqRj/2qEFAgMBAAECgYEAj4ExY1jjdN3iEDuOwXuRB+Nn\n" + + "x7pC4TgntE2huzdKvLJdGvIouTArce8A6JM5NlTBvm69mMepvAHgcsiMH1zGr5J5\n" + + "wJz23mGOyhM1veON41/DJTVG+cxq4soUZhdYy3bpOuXGMAaJ8QLMbQQoivllNihd\n" + + "vwH0rNSK8LTYWWPZYIECQQDxct+TFX1VsQ1eo41K0T4fu2rWUaxlvjUGhK6HxTmY\n" + + "8OMJptunGRJL1CUjIb45Uz7SP8TPz5FwhXWsLfS182kRAkEA3l+Qd9C9gdpUh1uX\n" + + "oPSNIxn5hFUrSTW1EwP9QH9vhwb5Vr8Jrd5ei678WYDLjUcx648RjkjhU9jSMzIx\n" + + "EGvYtQJBAMm/i9NR7IVyyNIgZUpz5q4LI21rl1r4gUQuD8vA36zM81i4ROeuCly0\n" + + "KkfdxR4PUfnKcQCX11YnHjk9uTFj75ECQEFY/gBnxDjzqyF35hAzrYIiMPQVfznt\n" + + "YX/sDTE2AdVBVGaMj1Cb51bPHnNC6Q5kXKQnj/YrLqRQND09Q7ParX0CQQC5NxZr\n" + + "9jKqhHj8yQD6PlXTsY4Occ7DH6/IoDenfdEVD5qlet0zmd50HatN2Jiqm5ubN7CM\n" + "INrtuLp4YHbgk1mi\n" + + "-----END PRIVATE KEY-----"; key = RsaKeyConverters.pkcs8().convert(new ByteArrayInputStream(keyData.getBytes(UTF_8))); final CertificateFactory factory = CertificateFactory.getInstance("X.509"); - String certificateData = "-----BEGIN CERTIFICATE-----\n" + - "MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMC\n" + - "VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEjAQBgNVBAcMCVZhbmNvdXZlcjEdMBsG\n" + - "A1UECgwUU3ByaW5nIFNlY3VyaXR5IFNBTUwxCzAJBgNVBAsMAnNwMSAwHgYDVQQD\n" + - "DBdzcC5zcHJpbmcuc2VjdXJpdHkuc2FtbDAeFw0xODA1MTQxNDMwNDRaFw0yODA1\n" + - "MTExNDMwNDRaMIGEMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjES\n" + - "MBAGA1UEBwwJVmFuY291dmVyMR0wGwYDVQQKDBRTcHJpbmcgU2VjdXJpdHkgU0FN\n" + - "TDELMAkGA1UECwwCc3AxIDAeBgNVBAMMF3NwLnNwcmluZy5zZWN1cml0eS5zYW1s\n" + - "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRu7/EI0BlNzMEBFVAcbx+lLos\n" + - "vzIWU+01dGTY8gBdhMQNYKZ92lMceo2CuVJ66cUURPym3i7nGGzoSnAxAre+0YIM\n" + - "+U0razrWtAUE735bkcqELZkOTZLelaoOztmWqRbe5OuEmpewH7cx+kNgcVjdctOG\n" + - "y3Q6x+I4qakY/9qhBQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAAeViTvHOyQopWEi\n" + - "XOfI2Z9eukwrSknDwq/zscR0YxwwqDBMt/QdAODfSwAfnciiYLkmEjlozWRtOeN+\n" + - "qK7UFgP1bRl5qksrYX5S0z2iGJh0GvonLUt3e20Ssfl5tTEDDnAEUMLfBkyaxEHD\n" + - "RZ/nbTJ7VTeZOSyRoVn5XHhpuJ0B\n" + - "-----END CERTIFICATE-----"; + String certificateData = "-----BEGIN CERTIFICATE-----\n" + + "MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMC\n" + + "VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEjAQBgNVBAcMCVZhbmNvdXZlcjEdMBsG\n" + + "A1UECgwUU3ByaW5nIFNlY3VyaXR5IFNBTUwxCzAJBgNVBAsMAnNwMSAwHgYDVQQD\n" + + "DBdzcC5zcHJpbmcuc2VjdXJpdHkuc2FtbDAeFw0xODA1MTQxNDMwNDRaFw0yODA1\n" + + "MTExNDMwNDRaMIGEMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjES\n" + + "MBAGA1UEBwwJVmFuY291dmVyMR0wGwYDVQQKDBRTcHJpbmcgU2VjdXJpdHkgU0FN\n" + + "TDELMAkGA1UECwwCc3AxIDAeBgNVBAMMF3NwLnNwcmluZy5zZWN1cml0eS5zYW1s\n" + + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRu7/EI0BlNzMEBFVAcbx+lLos\n" + + "vzIWU+01dGTY8gBdhMQNYKZ92lMceo2CuVJ66cUURPym3i7nGGzoSnAxAre+0YIM\n" + + "+U0razrWtAUE735bkcqELZkOTZLelaoOztmWqRbe5OuEmpewH7cx+kNgcVjdctOG\n" + + "y3Q6x+I4qakY/9qhBQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAAeViTvHOyQopWEi\n" + + "XOfI2Z9eukwrSknDwq/zscR0YxwwqDBMt/QdAODfSwAfnciiYLkmEjlozWRtOeN+\n" + + "qK7UFgP1bRl5qksrYX5S0z2iGJh0GvonLUt3e20Ssfl5tTEDDnAEUMLfBkyaxEHD\n" + + "RZ/nbTJ7VTeZOSyRoVn5XHhpuJ0B\n" + "-----END CERTIFICATE-----"; certificate = (X509Certificate) factory .generateCertificate(new ByteArrayInputStream(certificateData.getBytes(UTF_8))); } @@ -145,5 +145,4 @@ public class Saml2X509CredentialTests { new Saml2X509Credential(certificate, DECRYPTION); } - } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/credentials/TestSaml2X509Credentials.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/credentials/TestSaml2X509Credentials.java index 001e864f89..90fdd0fae5 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/credentials/TestSaml2X509Credentials.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/credentials/TestSaml2X509Credentials.java @@ -34,6 +34,7 @@ import static org.springframework.security.saml2.credentials.Saml2X509Credential import static org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.VERIFICATION; public final class TestSaml2X509Credentials { + public static Saml2X509Credential assertingPartySigningCredential() { return new Saml2X509Credential(idpPrivateKey(), idpCertificate(), SIGNING); } @@ -61,9 +62,7 @@ public final class TestSaml2X509Credentials { private static X509Certificate certificate(String cert) { ByteArrayInputStream certBytes = new ByteArrayInputStream(cert.getBytes()); try { - return (X509Certificate) CertificateFactory - .getInstance("X.509") - .generateCertificate(certBytes); + return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(certBytes); } catch (CertificateException e) { throw new Saml2Exception(e); @@ -79,101 +78,97 @@ public final class TestSaml2X509Credentials { } } - private static X509Certificate idpCertificate() { - return certificate("-----BEGIN CERTIFICATE-----\n" - + "MIIEEzCCAvugAwIBAgIJAIc1qzLrv+5nMA0GCSqGSIb3DQEBCwUAMIGfMQswCQYD\n" - + "VQQGEwJVUzELMAkGA1UECAwCQ08xFDASBgNVBAcMC0Nhc3RsZSBSb2NrMRwwGgYD\n" - + "VQQKDBNTYW1sIFRlc3RpbmcgU2VydmVyMQswCQYDVQQLDAJJVDEgMB4GA1UEAwwX\n" - + "c2ltcGxlc2FtbHBocC5jZmFwcHMuaW8xIDAeBgkqhkiG9w0BCQEWEWZoYW5pa0Bw\n" - + "aXZvdGFsLmlvMB4XDTE1MDIyMzIyNDUwM1oXDTI1MDIyMjIyNDUwM1owgZ8xCzAJ\n" - + "BgNVBAYTAlVTMQswCQYDVQQIDAJDTzEUMBIGA1UEBwwLQ2FzdGxlIFJvY2sxHDAa\n" - + "BgNVBAoME1NhbWwgVGVzdGluZyBTZXJ2ZXIxCzAJBgNVBAsMAklUMSAwHgYDVQQD\n" - + "DBdzaW1wbGVzYW1scGhwLmNmYXBwcy5pbzEgMB4GCSqGSIb3DQEJARYRZmhhbmlr\n" - + "QHBpdm90YWwuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4cn62\n" - + "E1xLqpN34PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz\n" - + "2ZivLwZXW+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWW\n" - + "RDodcoHEfDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQ\n" - + "nX8Ttl7hZ6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5\n" - + "cljz0X/TXy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gph\n" - + "iJH3jvZ7I+J5lS8VAgMBAAGjUDBOMB0GA1UdDgQWBBTTyP6Cc5HlBJ5+ucVCwGc5\n" - + "ogKNGzAfBgNVHSMEGDAWgBTTyP6Cc5HlBJ5+ucVCwGc5ogKNGzAMBgNVHRMEBTAD\n" - + "AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAvMS4EQeP/ipV4jOG5lO6/tYCb/iJeAduO\n" - + "nRhkJk0DbX329lDLZhTTL/x/w/9muCVcvLrzEp6PN+VWfw5E5FWtZN0yhGtP9R+v\n" - + "ZnrV+oc2zGD+no1/ySFOe3EiJCO5dehxKjYEmBRv5sU/LZFKZpozKN/BMEa6CqLu\n" - + "xbzb7ykxVr7EVFXwltPxzE9TmL9OACNNyF5eJHWMRMllarUvkcXlh4pux4ks9e6z\n" - + "V9DQBy2zds9f1I3qxg0eX6JnGrXi/ZiCT+lJgVe3ZFXiejiLAiKB04sXW3ti0LW3\n" - + "lx13Y1YlQ4/tlpgTgfIJxKV6nyPiLoK0nywbMd+vpAirDt2Oc+hk\n" - + "-----END CERTIFICATE-----\n"); + private static X509Certificate idpCertificate() { + return certificate( + "-----BEGIN CERTIFICATE-----\n" + "MIIEEzCCAvugAwIBAgIJAIc1qzLrv+5nMA0GCSqGSIb3DQEBCwUAMIGfMQswCQYD\n" + + "VQQGEwJVUzELMAkGA1UECAwCQ08xFDASBgNVBAcMC0Nhc3RsZSBSb2NrMRwwGgYD\n" + + "VQQKDBNTYW1sIFRlc3RpbmcgU2VydmVyMQswCQYDVQQLDAJJVDEgMB4GA1UEAwwX\n" + + "c2ltcGxlc2FtbHBocC5jZmFwcHMuaW8xIDAeBgkqhkiG9w0BCQEWEWZoYW5pa0Bw\n" + + "aXZvdGFsLmlvMB4XDTE1MDIyMzIyNDUwM1oXDTI1MDIyMjIyNDUwM1owgZ8xCzAJ\n" + + "BgNVBAYTAlVTMQswCQYDVQQIDAJDTzEUMBIGA1UEBwwLQ2FzdGxlIFJvY2sxHDAa\n" + + "BgNVBAoME1NhbWwgVGVzdGluZyBTZXJ2ZXIxCzAJBgNVBAsMAklUMSAwHgYDVQQD\n" + + "DBdzaW1wbGVzYW1scGhwLmNmYXBwcy5pbzEgMB4GCSqGSIb3DQEJARYRZmhhbmlr\n" + + "QHBpdm90YWwuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4cn62\n" + + "E1xLqpN34PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz\n" + + "2ZivLwZXW+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWW\n" + + "RDodcoHEfDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQ\n" + + "nX8Ttl7hZ6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5\n" + + "cljz0X/TXy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gph\n" + + "iJH3jvZ7I+J5lS8VAgMBAAGjUDBOMB0GA1UdDgQWBBTTyP6Cc5HlBJ5+ucVCwGc5\n" + + "ogKNGzAfBgNVHSMEGDAWgBTTyP6Cc5HlBJ5+ucVCwGc5ogKNGzAMBgNVHRMEBTAD\n" + + "AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAvMS4EQeP/ipV4jOG5lO6/tYCb/iJeAduO\n" + + "nRhkJk0DbX329lDLZhTTL/x/w/9muCVcvLrzEp6PN+VWfw5E5FWtZN0yhGtP9R+v\n" + + "ZnrV+oc2zGD+no1/ySFOe3EiJCO5dehxKjYEmBRv5sU/LZFKZpozKN/BMEa6CqLu\n" + + "xbzb7ykxVr7EVFXwltPxzE9TmL9OACNNyF5eJHWMRMllarUvkcXlh4pux4ks9e6z\n" + + "V9DQBy2zds9f1I3qxg0eX6JnGrXi/ZiCT+lJgVe3ZFXiejiLAiKB04sXW3ti0LW3\n" + + "lx13Y1YlQ4/tlpgTgfIJxKV6nyPiLoK0nywbMd+vpAirDt2Oc+hk\n" + "-----END CERTIFICATE-----\n"); } - private static PrivateKey idpPrivateKey() { - return privateKey("-----BEGIN PRIVATE KEY-----\n" - + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC4cn62E1xLqpN3\n" - + "4PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz2ZivLwZX\n" - + "W+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWWRDodcoHE\n" - + "fDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQnX8Ttl7h\n" - + "Z6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5cljz0X/T\n" - + "Xy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gphiJH3jvZ7\n" - + "I+J5lS8VAgMBAAECggEBAKyxBlIS7mcp3chvq0RF7B3PHFJMMzkwE+t3pLJcs4cZ\n" - + "nezh/KbREfP70QjXzk/llnZCvxeIs5vRu24vbdBm79qLHqBuHp8XfHHtuo2AfoAQ\n" - + "l4h047Xc/+TKMivnPQ0jX9qqndKDLqZDf5wnbslDmlskvF0a/MjsLU0TxtOfo+dB\n" - + "t55FW11cGqxZwhS5Gnr+cbw3OkHz23b9gEOt9qfwPVepeysbmm9FjU+k4yVa7rAN\n" - + "xcbzVb6Y7GCITe2tgvvEHmjB9BLmWrH3mZ3Af17YU/iN6TrpPd6Sj3QoS+2wGtAe\n" - + "HbUs3CKJu7bIHcj4poal6Kh8519S+erJTtqQ8M0ZiEECgYEA43hLYAPaUueFkdfh\n" - + "9K/7ClH6436CUH3VdizwUXi26fdhhV/I/ot6zLfU2mgEHU22LBECWQGtAFm8kv0P\n" - + "zPn+qjaR3e62l5PIlSYbnkIidzoDZ2ztu4jF5LgStlTJQPteFEGgZVl5o9DaSZOq\n" - + "Yd7G3XqXuQ1VGMW58G5FYJPtA1cCgYEAz5TPUtK+R2KXHMjUwlGY9AefQYRYmyX2\n" - + "Tn/OFgKvY8lpAkMrhPKONq7SMYc8E9v9G7A0dIOXvW7QOYSapNhKU+np3lUafR5F\n" - + "4ZN0bxZ9qjHbn3AMYeraKjeutHvlLtbHdIc1j3sxe/EzltRsYmiqLdEBW0p6hwWg\n" - + "tyGhYWVyaXMCgYAfDOKtHpmEy5nOCLwNXKBWDk7DExfSyPqEgSnk1SeS1HP5ctPK\n" - + "+1st6sIhdiVpopwFc+TwJWxqKdW18tlfT5jVv1E2DEnccw3kXilS9xAhWkfwrEvf\n" - + "V5I74GydewFl32o+NZ8hdo9GL1I8zO1rIq/et8dSOWGuWf9BtKu/vTGTTQKBgFxU\n" - + "VjsCnbvmsEwPUAL2hE/WrBFaKocnxXx5AFNt8lEyHtDwy4Sg1nygGcIJ4sD6koQk\n" - + "RdClT3LkvR04TAiSY80bN/i6ZcPNGUwSaDGZEWAIOSWbkwZijZNFnSGOEgxZX/IG\n" - + "yd39766vREEMTwEeiMNEOZQ/dmxkJm4OOVe25cLdAoGACOtPnq1Fxay80UYBf4rQ\n" - + "+bJ9yX1ulB8WIree1hD7OHSB2lRHxrVYWrglrTvkh63Lgx+EcsTV788OsvAVfPPz\n" - + "BZrn8SdDlQqalMxUBYEFwnsYD3cQ8yOUnijFVC4xNcdDv8OIqVgSk4KKxU5AshaA\n" + "xk6Mox+u8Cc2eAK12H13i+8=\n" - + "-----END PRIVATE KEY-----\n"); + return privateKey( + "-----BEGIN PRIVATE KEY-----\n" + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC4cn62E1xLqpN3\n" + + "4PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz2ZivLwZX\n" + + "W+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWWRDodcoHE\n" + + "fDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQnX8Ttl7h\n" + + "Z6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5cljz0X/T\n" + + "Xy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gphiJH3jvZ7\n" + + "I+J5lS8VAgMBAAECggEBAKyxBlIS7mcp3chvq0RF7B3PHFJMMzkwE+t3pLJcs4cZ\n" + + "nezh/KbREfP70QjXzk/llnZCvxeIs5vRu24vbdBm79qLHqBuHp8XfHHtuo2AfoAQ\n" + + "l4h047Xc/+TKMivnPQ0jX9qqndKDLqZDf5wnbslDmlskvF0a/MjsLU0TxtOfo+dB\n" + + "t55FW11cGqxZwhS5Gnr+cbw3OkHz23b9gEOt9qfwPVepeysbmm9FjU+k4yVa7rAN\n" + + "xcbzVb6Y7GCITe2tgvvEHmjB9BLmWrH3mZ3Af17YU/iN6TrpPd6Sj3QoS+2wGtAe\n" + + "HbUs3CKJu7bIHcj4poal6Kh8519S+erJTtqQ8M0ZiEECgYEA43hLYAPaUueFkdfh\n" + + "9K/7ClH6436CUH3VdizwUXi26fdhhV/I/ot6zLfU2mgEHU22LBECWQGtAFm8kv0P\n" + + "zPn+qjaR3e62l5PIlSYbnkIidzoDZ2ztu4jF5LgStlTJQPteFEGgZVl5o9DaSZOq\n" + + "Yd7G3XqXuQ1VGMW58G5FYJPtA1cCgYEAz5TPUtK+R2KXHMjUwlGY9AefQYRYmyX2\n" + + "Tn/OFgKvY8lpAkMrhPKONq7SMYc8E9v9G7A0dIOXvW7QOYSapNhKU+np3lUafR5F\n" + + "4ZN0bxZ9qjHbn3AMYeraKjeutHvlLtbHdIc1j3sxe/EzltRsYmiqLdEBW0p6hwWg\n" + + "tyGhYWVyaXMCgYAfDOKtHpmEy5nOCLwNXKBWDk7DExfSyPqEgSnk1SeS1HP5ctPK\n" + + "+1st6sIhdiVpopwFc+TwJWxqKdW18tlfT5jVv1E2DEnccw3kXilS9xAhWkfwrEvf\n" + + "V5I74GydewFl32o+NZ8hdo9GL1I8zO1rIq/et8dSOWGuWf9BtKu/vTGTTQKBgFxU\n" + + "VjsCnbvmsEwPUAL2hE/WrBFaKocnxXx5AFNt8lEyHtDwy4Sg1nygGcIJ4sD6koQk\n" + + "RdClT3LkvR04TAiSY80bN/i6ZcPNGUwSaDGZEWAIOSWbkwZijZNFnSGOEgxZX/IG\n" + + "yd39766vREEMTwEeiMNEOZQ/dmxkJm4OOVe25cLdAoGACOtPnq1Fxay80UYBf4rQ\n" + + "+bJ9yX1ulB8WIree1hD7OHSB2lRHxrVYWrglrTvkh63Lgx+EcsTV788OsvAVfPPz\n" + + "BZrn8SdDlQqalMxUBYEFwnsYD3cQ8yOUnijFVC4xNcdDv8OIqVgSk4KKxU5AshaA\n" + + "xk6Mox+u8Cc2eAK12H13i+8=\n" + "-----END PRIVATE KEY-----\n"); } private static X509Certificate spCertificate() { - return certificate("-----BEGIN CERTIFICATE-----\n" + - "MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMC\n" + - "VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEjAQBgNVBAcMCVZhbmNvdXZlcjEdMBsG\n" + - "A1UECgwUU3ByaW5nIFNlY3VyaXR5IFNBTUwxCzAJBgNVBAsMAnNwMSAwHgYDVQQD\n" + - "DBdzcC5zcHJpbmcuc2VjdXJpdHkuc2FtbDAeFw0xODA1MTQxNDMwNDRaFw0yODA1\n" + - "MTExNDMwNDRaMIGEMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjES\n" + - "MBAGA1UEBwwJVmFuY291dmVyMR0wGwYDVQQKDBRTcHJpbmcgU2VjdXJpdHkgU0FN\n" + - "TDELMAkGA1UECwwCc3AxIDAeBgNVBAMMF3NwLnNwcmluZy5zZWN1cml0eS5zYW1s\n" + - "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRu7/EI0BlNzMEBFVAcbx+lLos\n" + - "vzIWU+01dGTY8gBdhMQNYKZ92lMceo2CuVJ66cUURPym3i7nGGzoSnAxAre+0YIM\n" + - "+U0razrWtAUE735bkcqELZkOTZLelaoOztmWqRbe5OuEmpewH7cx+kNgcVjdctOG\n" + - "y3Q6x+I4qakY/9qhBQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAAeViTvHOyQopWEi\n" + - "XOfI2Z9eukwrSknDwq/zscR0YxwwqDBMt/QdAODfSwAfnciiYLkmEjlozWRtOeN+\n" + - "qK7UFgP1bRl5qksrYX5S0z2iGJh0GvonLUt3e20Ssfl5tTEDDnAEUMLfBkyaxEHD\n" + - "RZ/nbTJ7VTeZOSyRoVn5XHhpuJ0B\n" + - "-----END CERTIFICATE-----"); + return certificate( + "-----BEGIN CERTIFICATE-----\n" + "MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMC\n" + + "VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEjAQBgNVBAcMCVZhbmNvdXZlcjEdMBsG\n" + + "A1UECgwUU3ByaW5nIFNlY3VyaXR5IFNBTUwxCzAJBgNVBAsMAnNwMSAwHgYDVQQD\n" + + "DBdzcC5zcHJpbmcuc2VjdXJpdHkuc2FtbDAeFw0xODA1MTQxNDMwNDRaFw0yODA1\n" + + "MTExNDMwNDRaMIGEMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjES\n" + + "MBAGA1UEBwwJVmFuY291dmVyMR0wGwYDVQQKDBRTcHJpbmcgU2VjdXJpdHkgU0FN\n" + + "TDELMAkGA1UECwwCc3AxIDAeBgNVBAMMF3NwLnNwcmluZy5zZWN1cml0eS5zYW1s\n" + + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRu7/EI0BlNzMEBFVAcbx+lLos\n" + + "vzIWU+01dGTY8gBdhMQNYKZ92lMceo2CuVJ66cUURPym3i7nGGzoSnAxAre+0YIM\n" + + "+U0razrWtAUE735bkcqELZkOTZLelaoOztmWqRbe5OuEmpewH7cx+kNgcVjdctOG\n" + + "y3Q6x+I4qakY/9qhBQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAAeViTvHOyQopWEi\n" + + "XOfI2Z9eukwrSknDwq/zscR0YxwwqDBMt/QdAODfSwAfnciiYLkmEjlozWRtOeN+\n" + + "qK7UFgP1bRl5qksrYX5S0z2iGJh0GvonLUt3e20Ssfl5tTEDDnAEUMLfBkyaxEHD\n" + + "RZ/nbTJ7VTeZOSyRoVn5XHhpuJ0B\n" + "-----END CERTIFICATE-----"); } private static PrivateKey spPrivateKey() { - return privateKey("-----BEGIN PRIVATE KEY-----\n" + - "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANG7v8QjQGU3MwQE\n" + - "VUBxvH6Uuiy/MhZT7TV0ZNjyAF2ExA1gpn3aUxx6jYK5UnrpxRRE/KbeLucYbOhK\n" + - "cDECt77Rggz5TStrOta0BQTvfluRyoQtmQ5Nkt6Vqg7O2ZapFt7k64Sal7AftzH6\n" + - "Q2BxWN1y04bLdDrH4jipqRj/2qEFAgMBAAECgYEAj4ExY1jjdN3iEDuOwXuRB+Nn\n" + - "x7pC4TgntE2huzdKvLJdGvIouTArce8A6JM5NlTBvm69mMepvAHgcsiMH1zGr5J5\n" + - "wJz23mGOyhM1veON41/DJTVG+cxq4soUZhdYy3bpOuXGMAaJ8QLMbQQoivllNihd\n" + - "vwH0rNSK8LTYWWPZYIECQQDxct+TFX1VsQ1eo41K0T4fu2rWUaxlvjUGhK6HxTmY\n" + - "8OMJptunGRJL1CUjIb45Uz7SP8TPz5FwhXWsLfS182kRAkEA3l+Qd9C9gdpUh1uX\n" + - "oPSNIxn5hFUrSTW1EwP9QH9vhwb5Vr8Jrd5ei678WYDLjUcx648RjkjhU9jSMzIx\n" + - "EGvYtQJBAMm/i9NR7IVyyNIgZUpz5q4LI21rl1r4gUQuD8vA36zM81i4ROeuCly0\n" + - "KkfdxR4PUfnKcQCX11YnHjk9uTFj75ECQEFY/gBnxDjzqyF35hAzrYIiMPQVfznt\n" + - "YX/sDTE2AdVBVGaMj1Cb51bPHnNC6Q5kXKQnj/YrLqRQND09Q7ParX0CQQC5NxZr\n" + - "9jKqhHj8yQD6PlXTsY4Occ7DH6/IoDenfdEVD5qlet0zmd50HatN2Jiqm5ubN7CM\n" + - "INrtuLp4YHbgk1mi\n" + - "-----END PRIVATE KEY-----"); + return privateKey( + "-----BEGIN PRIVATE KEY-----\n" + "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANG7v8QjQGU3MwQE\n" + + "VUBxvH6Uuiy/MhZT7TV0ZNjyAF2ExA1gpn3aUxx6jYK5UnrpxRRE/KbeLucYbOhK\n" + + "cDECt77Rggz5TStrOta0BQTvfluRyoQtmQ5Nkt6Vqg7O2ZapFt7k64Sal7AftzH6\n" + + "Q2BxWN1y04bLdDrH4jipqRj/2qEFAgMBAAECgYEAj4ExY1jjdN3iEDuOwXuRB+Nn\n" + + "x7pC4TgntE2huzdKvLJdGvIouTArce8A6JM5NlTBvm69mMepvAHgcsiMH1zGr5J5\n" + + "wJz23mGOyhM1veON41/DJTVG+cxq4soUZhdYy3bpOuXGMAaJ8QLMbQQoivllNihd\n" + + "vwH0rNSK8LTYWWPZYIECQQDxct+TFX1VsQ1eo41K0T4fu2rWUaxlvjUGhK6HxTmY\n" + + "8OMJptunGRJL1CUjIb45Uz7SP8TPz5FwhXWsLfS182kRAkEA3l+Qd9C9gdpUh1uX\n" + + "oPSNIxn5hFUrSTW1EwP9QH9vhwb5Vr8Jrd5ei678WYDLjUcx648RjkjhU9jSMzIx\n" + + "EGvYtQJBAMm/i9NR7IVyyNIgZUpz5q4LI21rl1r4gUQuD8vA36zM81i4ROeuCly0\n" + + "KkfdxR4PUfnKcQCX11YnHjk9uTFj75ECQEFY/gBnxDjzqyF35hAzrYIiMPQVfznt\n" + + "YX/sDTE2AdVBVGaMj1Cb51bPHnNC6Q5kXKQnj/YrLqRQND09Q7ParX0CQQC5NxZr\n" + + "9jKqhHj8yQD6PlXTsY4Occ7DH6/IoDenfdEVD5qlet0zmd50HatN2Jiqm5ubN7CM\n" + "INrtuLp4YHbgk1mi\n" + + "-----END PRIVATE KEY-----"); } } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/DefaultSaml2AuthenticatedPrincipalTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/DefaultSaml2AuthenticatedPrincipalTests.java index 0352be6741..fabb649f78 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/DefaultSaml2AuthenticatedPrincipalTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/DefaultSaml2AuthenticatedPrincipalTests.java @@ -44,15 +44,13 @@ public class DefaultSaml2AuthenticatedPrincipalTests { Map> attributes = new LinkedHashMap<>(); attributes.put("email", Arrays.asList("john.doe@example.com", "doe.john@example.com")); assertThatCode(() -> new DefaultSaml2AuthenticatedPrincipal(null, attributes)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("name cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessageContaining("name cannot be null"); } @Test public void createDefaultSaml2AuthenticatedPrincipalWhenAttributesNullThenException() { assertThatCode(() -> new DefaultSaml2AuthenticatedPrincipal("user", null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("attributes cannot be null"); + .isInstanceOf(IllegalArgumentException.class).hasMessageContaining("attributes cannot be null"); } @Test @@ -87,4 +85,5 @@ public class DefaultSaml2AuthenticatedPrincipalTests { assertThat((Boolean) registrationInfo.get(0)).isEqualTo(registered); assertThat((Instant) registrationInfo.get(1)).isEqualTo(registeredDate); } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProviderTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProviderTests.java index 2b7e885c1e..25fe55dca4 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProviderTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProviderTests.java @@ -97,7 +97,9 @@ import static org.springframework.util.StringUtils.hasText; public class OpenSamlAuthenticationProviderTests { private static String DESTINATION = "https://localhost/login/saml2/sso/idp-alias"; + private static String RELYING_PARTY_ENTITY_ID = "https://localhost/saml2/service-provider-metadata/idp-alias"; + private static String ASSERTING_PARTY_ENTITY_ID = "https://some.idp.test/saml2/idp"; private OpenSamlAuthenticationProvider provider = new OpenSamlAuthenticationProvider(); @@ -109,7 +111,8 @@ public class OpenSamlAuthenticationProviderTests { public void supportsWhenSaml2AuthenticationTokenThenReturnTrue() { assertThat(this.provider.supports(Saml2AuthenticationToken.class)) - .withFailMessage(OpenSamlAuthenticationProvider.class + "should support " + Saml2AuthenticationToken.class) + .withFailMessage( + OpenSamlAuthenticationProvider.class + "should support " + Saml2AuthenticationToken.class) .isTrue(); } @@ -151,8 +154,7 @@ public class OpenSamlAuthenticationProviderTests { @Test public void authenticateWhenNoAssertionsPresentThenThrowAuthenticationException() { this.exception.expect( - authenticationMatcher(Saml2ErrorCodes.MALFORMED_RESPONSE_DATA, "No assertions found in response.") - ); + authenticationMatcher(Saml2ErrorCodes.MALFORMED_RESPONSE_DATA, "No assertions found in response.")); Saml2AuthenticationToken token = token(response(), assertingPartySigningCredential()); this.provider.authenticate(token); @@ -174,11 +176,7 @@ public class OpenSamlAuthenticationProviderTests { Response response = response(); Assertion assertion = assertion(); - assertion - .getSubject() - .getSubjectConfirmations() - .get(0) - .getSubjectConfirmationData() + assertion.getSubject().getSubjectConfirmations().get(0).getSubjectConfirmationData() .setNotOnOrAfter(DateTime.now().minus(Duration.standardDays(3))); signed(assertion, assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID); response.getAssertions().add(assertion); @@ -187,7 +185,7 @@ public class OpenSamlAuthenticationProviderTests { } @Test - public void authenticateWhenMissingSubjectThenThrowAuthenticationException() { + public void authenticateWhenMissingSubjectThenThrowAuthenticationException() { this.exception.expect(authenticationMatcher(Saml2ErrorCodes.SUBJECT_NOT_FOUND)); Response response = response(); @@ -205,10 +203,7 @@ public class OpenSamlAuthenticationProviderTests { Response response = response(); Assertion assertion = assertion(); - assertion - .getSubject() - .getNameID() - .setValue(null); + assertion.getSubject().getNameID().setValue(null); signed(assertion, assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID); response.getAssertions().add(assertion); Saml2AuthenticationToken token = token(response, relyingPartyVerifyingCredential()); @@ -219,9 +214,8 @@ public class OpenSamlAuthenticationProviderTests { public void authenticateWhenAssertionContainsValidationAddressThenItSucceeds() throws Exception { Response response = response(); Assertion assertion = assertion(); - assertion.getSubject().getSubjectConfirmations().forEach( - sc -> sc.getSubjectConfirmationData().setAddress("10.10.10.10") - ); + assertion.getSubject().getSubjectConfirmations() + .forEach(sc -> sc.getSubjectConfirmationData().setAddress("10.10.10.10")); signed(assertion, assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID); response.getAssertions().add(assertion); Saml2AuthenticationToken token = token(response, relyingPartyVerifyingCredential()); @@ -268,11 +262,14 @@ public class OpenSamlAuthenticationProviderTests { when(marshaller.marshall(any(XMLObject.class))).thenReturn(attributeElement); try { - XMLObjectProviderRegistrySupport.getMarshallerFactory().registerMarshaller(AttributeValue.DEFAULT_ELEMENT_NAME, marshaller); + XMLObjectProviderRegistrySupport.getMarshallerFactory() + .registerMarshaller(AttributeValue.DEFAULT_ELEMENT_NAME, marshaller); this.provider.authenticate(token); verify(marshaller, atLeastOnce()).marshall(any(XMLObject.class)); - } finally { - XMLObjectProviderRegistrySupport.getMarshallerFactory().deregisterMarshaller(AttributeValue.DEFAULT_ELEMENT_NAME); + } + finally { + XMLObjectProviderRegistrySupport.getMarshallerFactory() + .deregisterMarshaller(AttributeValue.DEFAULT_ELEMENT_NAME); } } @@ -293,7 +290,8 @@ public class OpenSamlAuthenticationProviderTests { Assertion assertion = signed(assertion(), assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID); EncryptedAssertion encryptedAssertion = encrypted(assertion, assertingPartyEncryptingCredential()); response.getEncryptedAssertions().add(encryptedAssertion); - Saml2AuthenticationToken token = token(response, relyingPartyVerifyingCredential(), relyingPartyDecryptingCredential()); + Saml2AuthenticationToken token = token(response, relyingPartyVerifyingCredential(), + relyingPartyDecryptingCredential()); this.provider.authenticate(token); } @@ -303,7 +301,8 @@ public class OpenSamlAuthenticationProviderTests { EncryptedAssertion encryptedAssertion = encrypted(assertion(), assertingPartyEncryptingCredential()); response.getEncryptedAssertions().add(encryptedAssertion); signed(response, assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID); - Saml2AuthenticationToken token = token(response, relyingPartyVerifyingCredential(), relyingPartyDecryptingCredential()); + Saml2AuthenticationToken token = token(response, relyingPartyVerifyingCredential(), + relyingPartyDecryptingCredential()); this.provider.authenticate(token); } @@ -317,16 +316,15 @@ public class OpenSamlAuthenticationProviderTests { assertion.getSubject().setEncryptedID(encryptedID); response.getAssertions().add(assertion); signed(assertion, assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID); - Saml2AuthenticationToken token = token(response, relyingPartyVerifyingCredential(), relyingPartyDecryptingCredential()); + Saml2AuthenticationToken token = token(response, relyingPartyVerifyingCredential(), + relyingPartyDecryptingCredential()); this.provider.authenticate(token); } - @Test public void authenticateWhenDecryptionKeysAreMissingThenThrowAuthenticationException() throws Exception { - this.exception.expect( - authenticationMatcher(Saml2ErrorCodes.DECRYPTION_ERROR, "Failed to decrypt EncryptedData") - ); + this.exception + .expect(authenticationMatcher(Saml2ErrorCodes.DECRYPTION_ERROR, "Failed to decrypt EncryptedData")); Response response = response(); EncryptedAssertion encryptedAssertion = encrypted(assertion(), assertingPartyEncryptingCredential()); @@ -337,9 +335,8 @@ public class OpenSamlAuthenticationProviderTests { @Test public void authenticateWhenDecryptionKeysAreWrongThenThrowAuthenticationException() throws Exception { - this.exception.expect( - authenticationMatcher(Saml2ErrorCodes.DECRYPTION_ERROR, "Failed to decrypt EncryptedData") - ); + this.exception + .expect(authenticationMatcher(Saml2ErrorCodes.DECRYPTION_ERROR, "Failed to decrypt EncryptedData")); Response response = response(); EncryptedAssertion encryptedAssertion = encrypted(assertion(), assertingPartyEncryptingCredential()); @@ -354,7 +351,8 @@ public class OpenSamlAuthenticationProviderTests { Assertion assertion = signed(assertion(), assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID); EncryptedAssertion encryptedAssertion = encrypted(assertion, assertingPartyEncryptingCredential()); response.getEncryptedAssertions().add(encryptedAssertion); - Saml2AuthenticationToken token = token(response, relyingPartyVerifyingCredential(), relyingPartyDecryptingCredential()); + Saml2AuthenticationToken token = token(response, relyingPartyVerifyingCredential(), + relyingPartyDecryptingCredential()); Saml2Authentication authentication = (Saml2Authentication) this.provider.authenticate(token); // the following code will throw an exception if authentication isn't serializable @@ -409,8 +407,7 @@ public class OpenSamlAuthenticationProviderTests { @Test public void setConditionValidatorsWhenNullOrEmptyThenIllegalArgument() { - assertThatCode(() -> this.provider.setConditionValidators(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> this.provider.setConditionValidators(null)).isInstanceOf(IllegalArgumentException.class); assertThatCode(() -> this.provider.setConditionValidators(Collections.emptyList())) .isInstanceOf(IllegalArgumentException.class); @@ -425,7 +422,8 @@ public class OpenSamlAuthenticationProviderTests { Marshaller marshaller = getMarshallerFactory().getMarshaller(object); Element element = marshaller.marshall(object); return SerializeSupport.nodeToString(element); - } catch (MarshallingException e) { + } + catch (MarshallingException e) { throw new Saml2Exception(e); } } @@ -455,7 +453,7 @@ public class OpenSamlAuthenticationProviderTests { @Override public void describeTo(Description desc) { - String excepting = "Saml2AuthenticationException[code="+code+"; description="+description+"]"; + String excepting = "Saml2AuthenticationException[code=" + code + "; description=" + description + "]"; desc.appendText(excepting); } @@ -468,8 +466,8 @@ public class OpenSamlAuthenticationProviderTests { } private Saml2AuthenticationToken token(String payload, Saml2X509Credential... credentials) { - return new Saml2AuthenticationToken(payload, - DESTINATION, ASSERTING_PARTY_ENTITY_ID, RELYING_PARTY_ENTITY_ID, Arrays.asList(credentials)); + return new Saml2AuthenticationToken(payload, DESTINATION, ASSERTING_PARTY_ENTITY_ID, RELYING_PARTY_ENTITY_ID, + Arrays.asList(credentials)); } private static Element element(String xml) throws Exception { @@ -478,4 +476,5 @@ public class OpenSamlAuthenticationProviderTests { Document doc = builder.parse(new InputSource(new StringReader(xml))); return doc.getDocumentElement(); } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactoryTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactoryTests.java index 8b8da0de9e..31bd0db6f2 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactoryTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactoryTests.java @@ -57,10 +57,13 @@ import static org.springframework.security.saml2.provider.service.registration.S public class OpenSamlAuthenticationRequestFactoryTests { private OpenSamlAuthenticationRequestFactory factory; + private Saml2AuthenticationRequestContext.Builder contextBuilder; + private Saml2AuthenticationRequestContext context; private RelyingPartyRegistration.Builder relyingPartyRegistrationBuilder; + private RelyingPartyRegistration relyingPartyRegistration; private AuthnRequestUnmarshaller unmarshaller = (AuthnRequestUnmarshaller) getUnmarshallerFactory() @@ -74,30 +77,27 @@ public class OpenSamlAuthenticationRequestFactoryTests { this.relyingPartyRegistrationBuilder = RelyingPartyRegistration.withRegistrationId("id") .assertionConsumerServiceLocation("template") .providerDetails(c -> c.webSsoUrl("https://destination/sso")) - .providerDetails(c -> c.entityId("remote-entity-id")) - .localEntityIdTemplate("local-entity-id") + .providerDetails(c -> c.entityId("remote-entity-id")).localEntityIdTemplate("local-entity-id") .credentials(c -> c.add(relyingPartySigningCredential())); this.relyingPartyRegistration = this.relyingPartyRegistrationBuilder.build(); - contextBuilder = Saml2AuthenticationRequestContext.builder() - .issuer("https://issuer") - .relyingPartyRegistration(relyingPartyRegistration) - .assertionConsumerServiceUrl("https://issuer/sso"); + contextBuilder = Saml2AuthenticationRequestContext.builder().issuer("https://issuer") + .relyingPartyRegistration(relyingPartyRegistration).assertionConsumerServiceUrl("https://issuer/sso"); context = contextBuilder.build(); factory = new OpenSamlAuthenticationRequestFactory(); } @Test public void createAuthenticationRequestWhenInvokingDeprecatedMethodThenReturnsXML() { - Saml2AuthenticationRequest request = Saml2AuthenticationRequest.withAuthenticationRequestContext(context).build(); + Saml2AuthenticationRequest request = Saml2AuthenticationRequest.withAuthenticationRequestContext(context) + .build(); String result = factory.createAuthenticationRequest(request); - assertThat(result.replace("\n", "")).startsWith(" c.signAuthNRequest(false)) - .build() - ) + context = contextBuilder.relayState("Relay State Value") + .relyingPartyRegistration(withRelyingPartyRegistration(relyingPartyRegistration) + .providerDetails(c -> c.signAuthNRequest(false)).build()) .build(); Saml2RedirectAuthenticationRequest result = factory.createRedirectAuthenticationRequest(context); assertThat(result.getSamlRequest()).isNotEmpty(); @@ -127,37 +123,26 @@ public class OpenSamlAuthenticationRequestFactoryTests { @Test public void createPostAuthenticationRequestWhenNotSignRequestThenNoSignatureIsPresent() { - context = contextBuilder - .relayState("Relay State Value") - .relyingPartyRegistration( - withRelyingPartyRegistration(relyingPartyRegistration) - .providerDetails(c -> c.signAuthNRequest(false)) - .build() - ) + context = contextBuilder.relayState("Relay State Value") + .relyingPartyRegistration(withRelyingPartyRegistration(relyingPartyRegistration) + .providerDetails(c -> c.signAuthNRequest(false)).build()) .build(); Saml2PostAuthenticationRequest result = factory.createPostAuthenticationRequest(context); assertThat(result.getSamlRequest()).isNotEmpty(); assertThat(result.getRelayState()).isEqualTo("Relay State Value"); assertThat(result.getBinding()).isEqualTo(POST); - assertThat(new String(samlDecode(result.getSamlRequest()), UTF_8)) - .doesNotContain("ds:Signature"); + assertThat(new String(samlDecode(result.getSamlRequest()), UTF_8)).doesNotContain("ds:Signature"); } @Test public void createPostAuthenticationRequestWhenSignRequestThenSignatureIsPresent() { - context = contextBuilder - .relayState("Relay State Value") - .relyingPartyRegistration( - withRelyingPartyRegistration(relyingPartyRegistration) - .build() - ) - .build(); + context = contextBuilder.relayState("Relay State Value") + .relyingPartyRegistration(withRelyingPartyRegistration(relyingPartyRegistration).build()).build(); Saml2PostAuthenticationRequest result = factory.createPostAuthenticationRequest(context); assertThat(result.getSamlRequest()).isNotEmpty(); assertThat(result.getRelayState()).isEqualTo("Relay State Value"); assertThat(result.getBinding()).isEqualTo(POST); - assertThat(new String(samlDecode(result.getSamlRequest()), UTF_8)) - .contains("ds:Signature"); + assertThat(new String(samlDecode(result.getSamlRequest()), UTF_8)).contains("ds:Signature"); } @Test @@ -182,9 +167,10 @@ public class OpenSamlAuthenticationRequestFactoryTests { @Test public void createPostAuthenticationRequestWhenAuthnRequestConsumerThenUses() { - Function> authnRequestConsumerResolver = - mock(Function.class); - when(authnRequestConsumerResolver.apply(this.context)).thenReturn(authnRequest -> {}); + Function> authnRequestConsumerResolver = mock( + Function.class); + when(authnRequestConsumerResolver.apply(this.context)).thenReturn(authnRequest -> { + }); this.factory.setAuthnRequestConsumerResolver(authnRequestConsumerResolver); this.factory.createPostAuthenticationRequest(this.context); @@ -193,9 +179,10 @@ public class OpenSamlAuthenticationRequestFactoryTests { @Test public void createRedirectAuthenticationRequestWhenAuthnRequestConsumerThenUses() { - Function> authnRequestConsumerResolver = - mock(Function.class); - when(authnRequestConsumerResolver.apply(this.context)).thenReturn(authnRequest -> {}); + Function> authnRequestConsumerResolver = mock( + Function.class); + when(authnRequestConsumerResolver.apply(this.context)).thenReturn(authnRequest -> { + }); this.factory.setAuthnRequestConsumerResolver(authnRequestConsumerResolver); this.factory.createRedirectAuthenticationRequest(this.context); @@ -211,11 +198,9 @@ public class OpenSamlAuthenticationRequestFactoryTests { @Test public void createPostAuthenticationRequestWhenAssertionConsumerServiceBindingThenUses() { RelyingPartyRegistration relyingPartyRegistration = this.relyingPartyRegistrationBuilder - .assertionConsumerServiceBinding(REDIRECT) - .build(); + .assertionConsumerServiceBinding(REDIRECT).build(); Saml2AuthenticationRequestContext context = this.contextBuilder - .relyingPartyRegistration(relyingPartyRegistration) - .build(); + .relyingPartyRegistration(relyingPartyRegistration).build(); Saml2PostAuthenticationRequest request = this.factory.createPostAuthenticationRequest(context); String samlRequest = request.getSamlRequest(); String inflated = new String(samlDecode(samlRequest)); @@ -223,9 +208,9 @@ public class OpenSamlAuthenticationRequestFactoryTests { } private AuthnRequest getAuthNRequest(Saml2MessageBinding binding) { - AbstractSaml2AuthenticationRequest result = (binding == REDIRECT) ? - factory.createRedirectAuthenticationRequest(context) : - factory.createPostAuthenticationRequest(context); + AbstractSaml2AuthenticationRequest result = (binding == REDIRECT) + ? factory.createRedirectAuthenticationRequest(context) + : factory.createPostAuthenticationRequest(context); String samlRequest = result.getSamlRequest(); assertThat(samlRequest).isNotEmpty(); if (result.getBinding() == REDIRECT) { @@ -235,8 +220,7 @@ public class OpenSamlAuthenticationRequestFactoryTests { samlRequest = new String(samlDecode(samlRequest), UTF_8); } try { - Document document = getParserPool().parse( - new ByteArrayInputStream(samlRequest.getBytes(UTF_8))); + Document document = getParserPool().parse(new ByteArrayInputStream(samlRequest.getBytes(UTF_8))); Element element = document.getDocumentElement(); return (AuthnRequest) this.unmarshaller.unmarshall(element); } @@ -244,4 +228,5 @@ public class OpenSamlAuthenticationRequestFactoryTests { throw new Saml2Exception(e); } } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestFactoryTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestFactoryTests.java index 563473a35d..9f60be3e14 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestFactoryTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestFactoryTests.java @@ -35,20 +35,16 @@ public class Saml2AuthenticationRequestFactoryTests { private RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("id") .assertionConsumerServiceUrlTemplate("template") .providerDetails(c -> c.webSsoUrl("https://example.com/destination")) - .providerDetails(c -> c.entityId("remote-entity-id")) - .localEntityIdTemplate("local-entity-id") - .credentials(c -> c.add(relyingPartySigningCredential())) - .build(); + .providerDetails(c -> c.entityId("remote-entity-id")).localEntityIdTemplate("local-entity-id") + .credentials(c -> c.add(relyingPartySigningCredential())).build(); @Test public void createAuthenticationRequestParametersWhenRedirectDefaultIsUsedMessageIsDeflatedAndEncoded() { - final String value = "Test String: "+ UUID.randomUUID().toString(); + final String value = "Test String: " + UUID.randomUUID().toString(); Saml2AuthenticationRequestFactory factory = request -> value; Saml2AuthenticationRequestContext request = Saml2AuthenticationRequestContext.builder() - .relyingPartyRegistration(registration) - .issuer("https://example.com/issuer") - .assertionConsumerServiceUrl("https://example.com/acs-url") - .build(); + .relyingPartyRegistration(registration).issuer("https://example.com/issuer") + .assertionConsumerServiceUrl("https://example.com/acs-url").build(); Saml2RedirectAuthenticationRequest response = factory.createRedirectAuthenticationRequest(request); String resultValue = response.getSamlRequest(); byte[] decoded = samlDecode(resultValue); @@ -58,16 +54,15 @@ public class Saml2AuthenticationRequestFactoryTests { @Test public void createAuthenticationRequestParametersWhenPostDefaultIsUsedMessageIsEncoded() { - final String value = "Test String: "+ UUID.randomUUID().toString(); + final String value = "Test String: " + UUID.randomUUID().toString(); Saml2AuthenticationRequestFactory factory = request -> value; Saml2AuthenticationRequestContext request = Saml2AuthenticationRequestContext.builder() - .relyingPartyRegistration(registration) - .issuer("https://example.com/issuer") - .assertionConsumerServiceUrl("https://example.com/acs-url") - .build(); + .relyingPartyRegistration(registration).issuer("https://example.com/issuer") + .assertionConsumerServiceUrl("https://example.com/acs-url").build(); Saml2PostAuthenticationRequest response = factory.createPostAuthenticationRequest(request); String resultValue = response.getSamlRequest(); byte[] decoded = samlDecode(resultValue); assertThat(new String(decoded)).isEqualTo(value); } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestOpenSamlObjects.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestOpenSamlObjects.java index 9267ef93dd..c5356f4cea 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestOpenSamlObjects.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestOpenSamlObjects.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Base64; import java.util.List; import java.util.UUID; + import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import javax.xml.namespace.QName; @@ -81,16 +82,21 @@ import org.springframework.security.saml2.core.Saml2X509Credential; import static org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport.getBuilderFactory; final class TestOpenSamlObjects { + static { OpenSamlInitializationService.initialize(); } private static String USERNAME = "test@saml.user"; + private static String DESTINATION = "https://localhost/login/saml2/sso/idp-alias"; + private static String RELYING_PARTY_ENTITY_ID = "https://localhost/saml2/service-provider-metadata/idp-alias"; + private static String ASSERTING_PARTY_ENTITY_ID = "https://some.idp.test/saml2/idp"; - private static SecretKey SECRET_KEY = - new SecretKeySpec(Base64.getDecoder().decode("shOnwNMoCv88HKMEa91+FlYoD5RNvzMTAL5LGxZKIFk="), "AES"); + + private static SecretKey SECRET_KEY = new SecretKeySpec( + Base64.getDecoder().decode("shOnwNMoCv88HKMEa91+FlYoD5RNvzMTAL5LGxZKIFk="), "AES"); static Response response() { return response(DESTINATION, ASSERTING_PARTY_ENTITY_ID); @@ -98,7 +104,7 @@ final class TestOpenSamlObjects { static Response response(String destination, String issuerEntityId) { Response response = build(Response.DEFAULT_ELEMENT_NAME); - response.setID("R"+UUID.randomUUID().toString()); + response.setID("R" + UUID.randomUUID().toString()); response.setIssueInstant(DateTime.now()); response.setVersion(SAMLVersion.VERSION_20); response.setID("_" + UUID.randomUUID().toString()); @@ -111,14 +117,9 @@ final class TestOpenSamlObjects { return assertion(USERNAME, ASSERTING_PARTY_ENTITY_ID, RELYING_PARTY_ENTITY_ID, DESTINATION); } - static Assertion assertion( - String username, - String issuerEntityId, - String recipientEntityId, - String recipientUri - ) { + static Assertion assertion(String username, String issuerEntityId, String recipientEntityId, String recipientUri) { Assertion assertion = build(Assertion.DEFAULT_ELEMENT_NAME); - assertion.setID("A"+ UUID.randomUUID().toString()); + assertion.setID("A" + UUID.randomUUID().toString()); assertion.setIssueInstant(DateTime.now()); assertion.setVersion(SAMLVersion.VERSION_20); assertion.setIssueInstant(DateTime.now()); @@ -135,7 +136,6 @@ final class TestOpenSamlObjects { return assertion; } - static Issuer issuer(String entityId) { Issuer issuer = build(Issuer.DEFAULT_ELEMENT_NAME); issuer.setValue(entityId); @@ -184,7 +184,8 @@ final class TestOpenSamlObjects { return cred; } - static Credential getSigningCredential(org.springframework.security.saml2.credentials.Saml2X509Credential credential, String entityId) { + static Credential getSigningCredential( + org.springframework.security.saml2.credentials.Saml2X509Credential credential, String entityId) { BasicCredential cred = getBasicCredential(credential); cred.setEntityId(entityId); cred.setUsageType(UsageType.SIGNING); @@ -192,17 +193,12 @@ final class TestOpenSamlObjects { } static BasicCredential getBasicCredential(Saml2X509Credential credential) { - return CredentialSupport.getSimpleCredential( - credential.getCertificate(), - credential.getPrivateKey() - ); + return CredentialSupport.getSimpleCredential(credential.getCertificate(), credential.getPrivateKey()); } - static BasicCredential getBasicCredential(org.springframework.security.saml2.credentials.Saml2X509Credential credential) { - return CredentialSupport.getSimpleCredential( - credential.getCertificate(), - credential.getPrivateKey() - ); + static BasicCredential getBasicCredential( + org.springframework.security.saml2.credentials.Saml2X509Credential credential) { + return CredentialSupport.getSimpleCredential(credential.getCertificate(), credential.getPrivateKey()); } static T signed(T signable, Saml2X509Credential credential, String entityId) { @@ -214,14 +210,16 @@ final class TestOpenSamlObjects { parameters.setSignatureCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); try { SignatureSupport.signObject(signable, parameters); - } catch (MarshallingException | SignatureException | SecurityException e) { + } + catch (MarshallingException | SignatureException | SecurityException e) { throw new Saml2Exception(e); } return signable; } - static T signed(T signable, org.springframework.security.saml2.credentials.Saml2X509Credential credential, String entityId) { + static T signed(T signable, + org.springframework.security.saml2.credentials.Saml2X509Credential credential, String entityId) { SignatureSigningParameters parameters = new SignatureSigningParameters(); Credential signingCredential = getSigningCredential(credential, entityId); parameters.setSigningCredential(signingCredential); @@ -230,7 +228,8 @@ final class TestOpenSamlObjects { parameters.setSignatureCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); try { SignatureSupport.signObject(signable, parameters); - } catch (MarshallingException | SignatureException | SecurityException e) { + } + catch (MarshallingException | SignatureException | SecurityException e) { throw new Saml2Exception(e); } @@ -248,7 +247,8 @@ final class TestOpenSamlObjects { } } - static EncryptedAssertion encrypted(Assertion assertion, org.springframework.security.saml2.credentials.Saml2X509Credential credential) { + static EncryptedAssertion encrypted(Assertion assertion, + org.springframework.security.saml2.credentials.Saml2X509Credential credential) { X509Certificate certificate = credential.getCertificate(); Encrypter encrypter = getEncrypter(certificate); try { @@ -270,7 +270,8 @@ final class TestOpenSamlObjects { } } - static EncryptedID encrypted(NameID nameId, org.springframework.security.saml2.credentials.Saml2X509Credential credential) { + static EncryptedID encrypted(NameID nameId, + org.springframework.security.saml2.credentials.Saml2X509Credential credential) { X509Certificate certificate = credential.getCertificate(); Encrypter encrypter = getEncrypter(certificate); try { @@ -347,14 +348,16 @@ final class TestOpenSamlObjects { Attribute registeredAttr = attributeBuilder.buildObject(); registeredAttr.setName("registered"); - XSBoolean registered = new XSBooleanBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSBoolean.TYPE_NAME); + XSBoolean registered = new XSBooleanBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, + XSBoolean.TYPE_NAME); registered.setValue(new XSBooleanValue(true, false)); registeredAttr.getAttributeValues().add(registered); attrStmt2.getAttributes().add(registeredAttr); Attribute registeredDateAttr = attributeBuilder.buildObject(); registeredDateAttr.setName("registeredDate"); - XSDateTime registeredDate = new XSDateTimeBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSDateTime.TYPE_NAME); + XSDateTime registeredDate = new XSDateTimeBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, + XSDateTime.TYPE_NAME); registeredDate.setValue(DateTime.parse("1970-01-01T00:00:00Z")); registeredDateAttr.getAttributeValues().add(registeredDate); attrStmt2.getAttributes().add(registeredDateAttr); @@ -367,4 +370,5 @@ final class TestOpenSamlObjects { static T build(QName qName) { return (T) getBuilderFactory().getBuilder(qName).buildObject(qName); } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestSaml2AuthenticationRequestContexts.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestSaml2AuthenticationRequestContexts.java index 57a721146e..d5f784373a 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestSaml2AuthenticationRequestContexts.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestSaml2AuthenticationRequestContexts.java @@ -22,11 +22,11 @@ import static org.springframework.security.saml2.provider.service.registration.T * Test {@link Saml2AuthenticationRequestContext}s */ public class TestSaml2AuthenticationRequestContexts { + public static Saml2AuthenticationRequestContext.Builder authenticationRequestContext() { - return Saml2AuthenticationRequestContext.builder() - .relayState("relayState") - .issuer("issuer") + return Saml2AuthenticationRequestContext.builder().relayState("relayState").issuer("issuer") .relyingPartyRegistration(relyingPartyRegistration().build()) .assertionConsumerServiceUrl("assertionConsumerServiceUrl"); } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlMetadataResolverTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlMetadataResolverTests.java index 161e6124a9..f062d23502 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlMetadataResolverTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlMetadataResolverTests.java @@ -34,20 +34,15 @@ public class OpenSamlMetadataResolverTests { @Test public void resolveWhenRelyingPartyThenMetadataMatches() { // given - RelyingPartyRegistration relyingPartyRegistration = full() - .assertionConsumerServiceBinding(REDIRECT) - .build(); + RelyingPartyRegistration relyingPartyRegistration = full().assertionConsumerServiceBinding(REDIRECT).build(); OpenSamlMetadataResolver openSamlMetadataResolver = new OpenSamlMetadataResolver(); // when String metadata = openSamlMetadataResolver.resolve(relyingPartyRegistration); // then - assertThat(metadata) - .contains("") + assertThat(metadata).contains("") .contains("") .contains("MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBh") .contains("Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"") @@ -58,9 +53,8 @@ public class OpenSamlMetadataResolverTests { public void resolveWhenRelyingPartyNoCredentialsThenMetadataMatches() { // given RelyingPartyRegistration relyingPartyRegistration = noCredentials() - .assertingPartyDetails(party -> party - .verificationX509Credentials(c -> c.add(relyingPartyVerifyingCredential())) - ) + .assertingPartyDetails( + party -> party.verificationX509Credentials(c -> c.add(relyingPartyVerifyingCredential()))) .build(); OpenSamlMetadataResolver openSamlMetadataResolver = new OpenSamlMetadataResolver(); @@ -68,13 +62,11 @@ public class OpenSamlMetadataResolverTests { String metadata = openSamlMetadataResolver.resolve(relyingPartyRegistration); // then - assertThat(metadata) - .contains("") + assertThat(metadata).contains("") .doesNotContain("") .contains("Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\"") .contains("Location=\"https://rp.example.org/acs\" index=\"1\""); } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverterTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverterTests.java index e9a85b8a01..7241cfc1a9 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverterTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverterTests.java @@ -33,30 +33,24 @@ import static org.assertj.core.api.Assertions.assertThatCode; import static org.springframework.http.HttpStatus.OK; public class OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverterTests { - private static final String CERTIFICATE = - "MIIEEzCCAvugAwIBAgIJAIc1qzLrv+5nMA0GCSqGSIb3DQEBCwUAMIGfMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ08xFDASBgNVBAcMC0Nhc3RsZSBSb2NrMRwwGgYDVQQKDBNTYW1sIFRlc3RpbmcgU2VydmVyMQswCQYDVQQLDAJJVDEgMB4GA1UEAwwXc2ltcGxlc2FtbHBocC5jZmFwcHMuaW8xIDAeBgkqhkiG9w0BCQEWEWZoYW5pa0BwaXZvdGFsLmlvMB4XDTE1MDIyMzIyNDUwM1oXDTI1MDIyMjIyNDUwM1owgZ8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDTzEUMBIGA1UEBwwLQ2FzdGxlIFJvY2sxHDAaBgNVBAoME1NhbWwgVGVzdGluZyBTZXJ2ZXIxCzAJBgNVBAsMAklUMSAwHgYDVQQDDBdzaW1wbGVzYW1scGhwLmNmYXBwcy5pbzEgMB4GCSqGSIb3DQEJARYRZmhhbmlrQHBpdm90YWwuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4cn62E1xLqpN34PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz2ZivLwZXW+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWWRDodcoHEfDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQnX8Ttl7hZ6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5cljz0X/TXy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gphiJH3jvZ7I+J5lS8VAgMBAAGjUDBOMB0GA1UdDgQWBBTTyP6Cc5HlBJ5+ucVCwGc5ogKNGzAfBgNVHSMEGDAWgBTTyP6Cc5HlBJ5+ucVCwGc5ogKNGzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAvMS4EQeP/ipV4jOG5lO6/tYCb/iJeAduOnRhkJk0DbX329lDLZhTTL/x/w/9muCVcvLrzEp6PN+VWfw5E5FWtZN0yhGtP9R+vZnrV+oc2zGD+no1/ySFOe3EiJCO5dehxKjYEmBRv5sU/LZFKZpozKN/BMEa6CqLuxbzb7ykxVr7EVFXwltPxzE9TmL9OACNNyF5eJHWMRMllarUvkcXlh4pux4ks9e6zV9DQBy2zds9f1I3qxg0eX6JnGrXi/ZiCT+lJgVe3ZFXiejiLAiKB04sXW3ti0LW3lx13Y1YlQ4/tlpgTgfIJxKV6nyPiLoK0nywbMd+vpAirDt2Oc+hk"; - private static final String ENTITY_DESCRIPTOR_TEMPLATE = - "\n" + - "\n%s" + - ""; - private static final String IDP_SSO_DESCRIPTOR_TEMPLATE = - "\n" + - "%s\n" + - ""; - private static final String KEY_DESCRIPTOR_TEMPLATE = - "\n" + - "\n" + - "\n" + - "" + CERTIFICATE + "\n" + - "\n" + - "\n" + - ""; - private static final String SINGLE_SIGN_ON_SERVICE_TEMPLATE = - ""; + private static final String CERTIFICATE = "MIIEEzCCAvugAwIBAgIJAIc1qzLrv+5nMA0GCSqGSIb3DQEBCwUAMIGfMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ08xFDASBgNVBAcMC0Nhc3RsZSBSb2NrMRwwGgYDVQQKDBNTYW1sIFRlc3RpbmcgU2VydmVyMQswCQYDVQQLDAJJVDEgMB4GA1UEAwwXc2ltcGxlc2FtbHBocC5jZmFwcHMuaW8xIDAeBgkqhkiG9w0BCQEWEWZoYW5pa0BwaXZvdGFsLmlvMB4XDTE1MDIyMzIyNDUwM1oXDTI1MDIyMjIyNDUwM1owgZ8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDTzEUMBIGA1UEBwwLQ2FzdGxlIFJvY2sxHDAaBgNVBAoME1NhbWwgVGVzdGluZyBTZXJ2ZXIxCzAJBgNVBAsMAklUMSAwHgYDVQQDDBdzaW1wbGVzYW1scGhwLmNmYXBwcy5pbzEgMB4GCSqGSIb3DQEJARYRZmhhbmlrQHBpdm90YWwuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4cn62E1xLqpN34PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz2ZivLwZXW+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWWRDodcoHEfDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQnX8Ttl7hZ6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5cljz0X/TXy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gphiJH3jvZ7I+J5lS8VAgMBAAGjUDBOMB0GA1UdDgQWBBTTyP6Cc5HlBJ5+ucVCwGc5ogKNGzAfBgNVHSMEGDAWgBTTyP6Cc5HlBJ5+ucVCwGc5ogKNGzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAvMS4EQeP/ipV4jOG5lO6/tYCb/iJeAduOnRhkJk0DbX329lDLZhTTL/x/w/9muCVcvLrzEp6PN+VWfw5E5FWtZN0yhGtP9R+vZnrV+oc2zGD+no1/ySFOe3EiJCO5dehxKjYEmBRv5sU/LZFKZpozKN/BMEa6CqLuxbzb7ykxVr7EVFXwltPxzE9TmL9OACNNyF5eJHWMRMllarUvkcXlh4pux4ks9e6zV9DQBy2zds9f1I3qxg0eX6JnGrXi/ZiCT+lJgVe3ZFXiejiLAiKB04sXW3ti0LW3lx13Y1YlQ4/tlpgTgfIJxKV6nyPiLoK0nywbMd+vpAirDt2Oc+hk"; + + private static final String ENTITY_DESCRIPTOR_TEMPLATE = "\n" + + "\n%s" + + ""; + + private static final String IDP_SSO_DESCRIPTOR_TEMPLATE = "\n" + + "%s\n" + ""; + + private static final String KEY_DESCRIPTOR_TEMPLATE = "\n" + + "\n" + "\n" + + "" + CERTIFICATE + "\n" + "\n" + "\n" + + ""; + + private static final String SINGLE_SIGN_ON_SERVICE_TEMPLATE = ""; private OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter converter; @@ -67,8 +61,8 @@ public class OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverterTests { @Test public void readWhenMissingIDPSSODescriptorThenException() { - MockClientHttpResponse response = new MockClientHttpResponse - ((String.format(ENTITY_DESCRIPTOR_TEMPLATE, "")).getBytes(), OK); + MockClientHttpResponse response = new MockClientHttpResponse( + (String.format(ENTITY_DESCRIPTOR_TEMPLATE, "")).getBytes(), OK); assertThatCode(() -> this.converter.read(RelyingPartyRegistration.Builder.class, response)) .isInstanceOf(Saml2Exception.class) .hasMessageContaining("Metadata response is missing the necessary IDPSSODescriptor element"); @@ -76,41 +70,34 @@ public class OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverterTests { @Test public void readWhenMissingVerificationKeyThenException() { - String payload = String.format(ENTITY_DESCRIPTOR_TEMPLATE, - String.format(IDP_SSO_DESCRIPTOR_TEMPLATE, "")); + String payload = String.format(ENTITY_DESCRIPTOR_TEMPLATE, String.format(IDP_SSO_DESCRIPTOR_TEMPLATE, "")); MockClientHttpResponse response = new MockClientHttpResponse(payload.getBytes(), OK); assertThatCode(() -> this.converter.read(RelyingPartyRegistration.Builder.class, response)) - .isInstanceOf(Saml2Exception.class) - .hasMessageContaining("Metadata response is missing verification certificates, necessary for verifying SAML assertions"); + .isInstanceOf(Saml2Exception.class).hasMessageContaining( + "Metadata response is missing verification certificates, necessary for verifying SAML assertions"); } @Test public void readWhenMissingSingleSignOnServiceThenException() { String payload = String.format(ENTITY_DESCRIPTOR_TEMPLATE, - String.format(IDP_SSO_DESCRIPTOR_TEMPLATE, - String.format(KEY_DESCRIPTOR_TEMPLATE, "use=\"signing\"") - )); + String.format(IDP_SSO_DESCRIPTOR_TEMPLATE, String.format(KEY_DESCRIPTOR_TEMPLATE, "use=\"signing\""))); MockClientHttpResponse response = new MockClientHttpResponse(payload.getBytes(), OK); assertThatCode(() -> this.converter.read(RelyingPartyRegistration.Builder.class, response)) - .isInstanceOf(Saml2Exception.class) - .hasMessageContaining("Metadata response is missing a SingleSignOnService, necessary for sending AuthnRequests"); + .isInstanceOf(Saml2Exception.class).hasMessageContaining( + "Metadata response is missing a SingleSignOnService, necessary for sending AuthnRequests"); } @Test public void readWhenDescriptorFullySpecifiedThenConfigures() throws Exception { String payload = String.format(ENTITY_DESCRIPTOR_TEMPLATE, String.format(IDP_SSO_DESCRIPTOR_TEMPLATE, - String.format(KEY_DESCRIPTOR_TEMPLATE, "use=\"signing\"") + - String.format(KEY_DESCRIPTOR_TEMPLATE, "use=\"encryption\"") + - String.format(SINGLE_SIGN_ON_SERVICE_TEMPLATE) - )); + String.format(KEY_DESCRIPTOR_TEMPLATE, "use=\"signing\"") + + String.format(KEY_DESCRIPTOR_TEMPLATE, "use=\"encryption\"") + + String.format(SINGLE_SIGN_ON_SERVICE_TEMPLATE))); MockClientHttpResponse response = new MockClientHttpResponse(payload.getBytes(), OK); - RelyingPartyRegistration registration = - this.converter.read(RelyingPartyRegistration.Builder.class, response) - .registrationId("one") - .build(); - RelyingPartyRegistration.AssertingPartyDetails details = - registration.getAssertingPartyDetails(); + RelyingPartyRegistration registration = this.converter.read(RelyingPartyRegistration.Builder.class, response) + .registrationId("one").build(); + RelyingPartyRegistration.AssertingPartyDetails details = registration.getAssertingPartyDetails(); assertThat(details.getWantAuthnRequestsSigned()).isFalse(); assertThat(details.getSingleSignOnServiceLocation()).isEqualTo("sso-location"); assertThat(details.getSingleSignOnServiceBinding()).isEqualTo(Saml2MessageBinding.REDIRECT); @@ -125,18 +112,12 @@ public class OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverterTests { @Test public void readWhenKeyDescriptorHasNoUseThenConfiguresBothKeyTypes() throws Exception { - String payload = String.format(ENTITY_DESCRIPTOR_TEMPLATE, - String.format(IDP_SSO_DESCRIPTOR_TEMPLATE, - String.format(KEY_DESCRIPTOR_TEMPLATE, "") + - String.format(SINGLE_SIGN_ON_SERVICE_TEMPLATE) - )); + String payload = String.format(ENTITY_DESCRIPTOR_TEMPLATE, String.format(IDP_SSO_DESCRIPTOR_TEMPLATE, + String.format(KEY_DESCRIPTOR_TEMPLATE, "") + String.format(SINGLE_SIGN_ON_SERVICE_TEMPLATE))); MockClientHttpResponse response = new MockClientHttpResponse(payload.getBytes(), OK); - RelyingPartyRegistration registration = - this.converter.read(RelyingPartyRegistration.Builder.class, response) - .registrationId("one") - .build(); - RelyingPartyRegistration.AssertingPartyDetails details = - registration.getAssertingPartyDetails(); + RelyingPartyRegistration registration = this.converter.read(RelyingPartyRegistration.Builder.class, response) + .registrationId("one").build(); + RelyingPartyRegistration.AssertingPartyDetails details = registration.getAssertingPartyDetails(); assertThat(details.getVerificationX509Credentials().iterator().next().getCertificate()) .isEqualTo(x509Certificate(CERTIFICATE)); assertThat(details.getEncryptionX509Credentials()).hasSize(1); @@ -147,10 +128,11 @@ public class OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverterTests { X509Certificate x509Certificate(String data) { try { InputStream certificate = new ByteArrayInputStream(Base64.getDecoder().decode(data.getBytes())); - return (X509Certificate) CertificateFactory.getInstance("X.509") - .generateCertificate(certificate); - } catch (Exception e) { + return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(certificate); + } + catch (Exception e) { throw new IllegalArgumentException(e); } } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationTests.java index d8cd44acd5..cad36be5d4 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationTests.java @@ -30,21 +30,16 @@ public class RelyingPartyRegistrationTests { @Test public void withRelyingPartyRegistrationWorks() { - RelyingPartyRegistration registration = relyingPartyRegistration() - .providerDetails(p -> p.binding(POST)) + RelyingPartyRegistration registration = relyingPartyRegistration().providerDetails(p -> p.binding(POST)) .providerDetails(p -> p.signAuthNRequest(false)) - .assertionConsumerServiceBinding(Saml2MessageBinding.REDIRECT) - .build(); + .assertionConsumerServiceBinding(Saml2MessageBinding.REDIRECT).build(); RelyingPartyRegistration copy = RelyingPartyRegistration.withRelyingPartyRegistration(registration).build(); compareRegistrations(registration, copy); } private void compareRegistrations(RelyingPartyRegistration registration, RelyingPartyRegistration copy) { - assertThat(copy.getRegistrationId()) - .isEqualTo(registration.getRegistrationId()) - .isEqualTo("simplesamlphp"); - assertThat(copy.getProviderDetails().getEntityId()) - .isEqualTo(registration.getProviderDetails().getEntityId()) + assertThat(copy.getRegistrationId()).isEqualTo(registration.getRegistrationId()).isEqualTo("simplesamlphp"); + assertThat(copy.getProviderDetails().getEntityId()).isEqualTo(registration.getProviderDetails().getEntityId()) .isEqualTo(copy.getAssertingPartyDetails().getEntityId()) .isEqualTo(registration.getAssertingPartyDetails().getEntityId()) .isEqualTo("https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/metadata.php"); @@ -53,38 +48,26 @@ public class RelyingPartyRegistrationTests { .isEqualTo(copy.getAssertionConsumerServiceLocation()) .isEqualTo(registration.getAssertionConsumerServiceLocation()) .isEqualTo("{baseUrl}" + Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI); - assertThat(copy.getCredentials()) - .containsAll(registration.getCredentials()) - .containsExactly( - registration.getCredentials().get(0), - registration.getCredentials().get(1) - ); - assertThat(copy.getLocalEntityIdTemplate()) - .isEqualTo(registration.getLocalEntityIdTemplate()) - .isEqualTo(copy.getEntityId()) - .isEqualTo(registration.getEntityId()) + assertThat(copy.getCredentials()).containsAll(registration.getCredentials()) + .containsExactly(registration.getCredentials().get(0), registration.getCredentials().get(1)); + assertThat(copy.getLocalEntityIdTemplate()).isEqualTo(registration.getLocalEntityIdTemplate()) + .isEqualTo(copy.getEntityId()).isEqualTo(registration.getEntityId()) .isEqualTo("{baseUrl}/saml2/service-provider-metadata/{registrationId}"); - assertThat(copy.getProviderDetails().getWebSsoUrl()) - .isEqualTo(registration.getProviderDetails().getWebSsoUrl()) + assertThat(copy.getProviderDetails().getWebSsoUrl()).isEqualTo(registration.getProviderDetails().getWebSsoUrl()) .isEqualTo(copy.getAssertingPartyDetails().getSingleSignOnServiceLocation()) .isEqualTo(registration.getAssertingPartyDetails().getSingleSignOnServiceLocation()) .isEqualTo("https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php"); - assertThat(copy.getProviderDetails().getBinding()) - .isEqualTo(registration.getProviderDetails().getBinding()) + assertThat(copy.getProviderDetails().getBinding()).isEqualTo(registration.getProviderDetails().getBinding()) .isEqualTo(copy.getAssertingPartyDetails().getSingleSignOnServiceBinding()) - .isEqualTo(registration.getAssertingPartyDetails().getSingleSignOnServiceBinding()) - .isEqualTo(POST); + .isEqualTo(registration.getAssertingPartyDetails().getSingleSignOnServiceBinding()).isEqualTo(POST); assertThat(copy.getProviderDetails().isSignAuthNRequest()) .isEqualTo(registration.getProviderDetails().isSignAuthNRequest()) .isEqualTo(copy.getAssertingPartyDetails().getWantAuthnRequestsSigned()) - .isEqualTo(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()) - .isFalse(); + .isEqualTo(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()).isFalse(); assertThat(copy.getAssertionConsumerServiceBinding()) .isEqualTo(registration.getAssertionConsumerServiceBinding()); - assertThat(copy.getDecryptionX509Credentials()) - .isEqualTo(registration.getDecryptionX509Credentials()); - assertThat(copy.getSigningX509Credentials()) - .isEqualTo(registration.getSigningX509Credentials()); + assertThat(copy.getDecryptionX509Credentials()).isEqualTo(registration.getDecryptionX509Credentials()); + assertThat(copy.getSigningX509Credentials()).isEqualTo(registration.getSigningX509Credentials()); assertThat(copy.getAssertingPartyDetails().getEncryptionX509Credentials()) .isEqualTo(registration.getAssertingPartyDetails().getEncryptionX509Credentials()); assertThat(copy.getAssertingPartyDetails().getVerificationX509Credentials()) @@ -93,16 +76,13 @@ public class RelyingPartyRegistrationTests { @Test public void buildWhenUsingDefaultsThenAssertionConsumerServiceBindingDefaultsToPost() { - RelyingPartyRegistration relyingPartyRegistration = withRegistrationId("id") - .entityId("entity-id") + RelyingPartyRegistration relyingPartyRegistration = withRegistrationId("id").entityId("entity-id") .assertionConsumerServiceLocation("location") - .assertingPartyDetails(assertingParty -> assertingParty - .entityId("entity-id") - .singleSignOnServiceLocation("location")) - .credentials(c -> c.add(relyingPartyVerifyingCredential())) - .build(); + .assertingPartyDetails( + assertingParty -> assertingParty.entityId("entity-id").singleSignOnServiceLocation("location")) + .credentials(c -> c.add(relyingPartyVerifyingCredential())).build(); - assertThat(relyingPartyRegistration.getAssertionConsumerServiceBinding()) - .isEqualTo(POST); + assertThat(relyingPartyRegistration.getAssertionConsumerServiceBinding()).isEqualTo(POST); } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationsTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationsTests.java index c3dfaed2b2..1af5ede3b7 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationsTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationsTests.java @@ -29,108 +29,72 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; * Tests for {@link RelyingPartyRegistration} */ public class RelyingPartyRegistrationsTests { - private static final String IDP_SSO_DESCRIPTOR_PAYLOAD = - "\n" + - " \n" + - " \n" + - " \n" + - " example.com\n" + - " \n" + - " \n" + - " \n" + - " Consortium GARR IdP\n" + - " \n" + - " \n" + - " Consortium GARR IdP\n" + - " \n" + - " \n" + - " \n" + - " This Identity Provider gives support for the Consortium GARR's user community\n" + - " \n" + - " \n" + - " Questo Identity Provider di test fornisce supporto alla comunita' utenti GARR\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " MIIDZjCCAk6gAwIBAgIVAL9O+PA7SXtlwZZY8MVSE9On1cVWMA0GCSqGSIb3DQEB\n" + - " BQUAMCkxJzAlBgNVBAMTHmlkZW0tcHVwYWdlbnQuZG16LWludC51bmltby5pdDAe\n" + - " Fw0xMzA3MjQwMDQ0MTRaFw0zMzA3MjQwMDQ0MTRaMCkxJzAlBgNVBAMTHmlkZW0t\n" + - " cHVwYWdlbnQuZG16LWludC51bmltby5pdDCCASIwDQYJKoZIhvcNAMIIDQADggEP\n" + - " ADCCAQoCggEBAIAcp/VyzZGXUF99kwj4NvL/Rwv4YvBgLWzpCuoxqHZ/hmBwJtqS\n" + - " v0y9METBPFbgsF3hCISnxbcmNVxf/D0MoeKtw1YPbsUmow/bFe+r72hZ+IVAcejN\n" + - " iDJ7t5oTjsRN1t1SqvVVk6Ryk5AZhpFW+W9pE9N6c7kJ16Rp2/mbtax9OCzxpece\n" + - " byi1eiLfIBmkcRawL/vCc2v6VLI18i6HsNVO3l2yGosKCbuSoGDx2fCdAOk/rgdz\n" + - " cWOvFsIZSKuD+FVbSS/J9GVs7yotsS4PRl4iX9UMnfDnOMfO7bcBgbXtDl4SCU1v\n" + - " dJrRw7IL/pLz34Rv9a8nYitrzrxtLOp3nYUCAwEAAaOBhDCBgTBgBgMIIDEEWTBX\n" + - " gh5pZGVtLXB1cGFnZW50LmRtei1pbnQudW5pbW8uaXSGNWh0dHBzOi8vaWRlbS1w\n" + - " dXBhZ2VudC5kbXotaW50LnVuaW1vLml0L2lkcC9zaGliYm9sZXRoMB0GA1UdDgQW\n" + - " BBT8PANzz+adGnTRe8ldcyxAwe4VnzANBgkqhkiG9w0BAQUFAAOCAQEAOEnO8Clu\n" + - " 9z/Lf/8XOOsTdxJbV29DIF3G8KoQsB3dBsLwPZVEAQIP6ceS32Xaxrl6FMTDDNkL\n" + - " qUvvInUisw0+I5zZwYHybJQCletUWTnz58SC4C9G7FpuXHFZnOGtRcgGD1NOX4UU\n" + - " duus/4nVcGSLhDjszZ70Xtj0gw2Sn46oQPHTJ81QZ3Y9ih+Aj1c9OtUSBwtWZFkU\n" + - " yooAKoR8li68Yb21zN2N65AqV+ndL98M8xUYMKLONuAXStDeoVCipH6PJ09Z5U2p\n" + - " V5p4IQRV6QBsNw9CISJFuHzkVYTH5ZxzN80Ru46vh4y2M0Nu8GQ9I085KoZkrf5e\n" + - " Cq53OZt9ISjHEw==\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " Consortium GARR\n" + - " \n" + - " \n" + - " Consortium GARR\n" + - " \n" + - " \n" + - " \n" + - " Consortium GARR\n" + - " \n" + - " \n" + - " Consortium GARR\n" + - " \n" + - " \n" + - " \n" + - " https://example.org\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " mailto:technical.contact@example.com\n" + - " \n" + - " \n" + - ""; + + private static final String IDP_SSO_DESCRIPTOR_PAYLOAD = "\n" + " \n" + + " \n" + + " \n" + " example.com\n" + + " \n" + " \n" + " \n" + + " Consortium GARR IdP\n" + " \n" + + " \n" + " Consortium GARR IdP\n" + + " \n" + " \n" + " \n" + + " This Identity Provider gives support for the Consortium GARR's user community\n" + + " \n" + " \n" + + " Questo Identity Provider di test fornisce supporto alla comunita' utenti GARR\n" + + " \n" + " \n" + " \n" + " \n" + + " \n" + " \n" + " \n" + + " \n" + + " MIIDZjCCAk6gAwIBAgIVAL9O+PA7SXtlwZZY8MVSE9On1cVWMA0GCSqGSIb3DQEB\n" + + " BQUAMCkxJzAlBgNVBAMTHmlkZW0tcHVwYWdlbnQuZG16LWludC51bmltby5pdDAe\n" + + " Fw0xMzA3MjQwMDQ0MTRaFw0zMzA3MjQwMDQ0MTRaMCkxJzAlBgNVBAMTHmlkZW0t\n" + + " cHVwYWdlbnQuZG16LWludC51bmltby5pdDCCASIwDQYJKoZIhvcNAMIIDQADggEP\n" + + " ADCCAQoCggEBAIAcp/VyzZGXUF99kwj4NvL/Rwv4YvBgLWzpCuoxqHZ/hmBwJtqS\n" + + " v0y9METBPFbgsF3hCISnxbcmNVxf/D0MoeKtw1YPbsUmow/bFe+r72hZ+IVAcejN\n" + + " iDJ7t5oTjsRN1t1SqvVVk6Ryk5AZhpFW+W9pE9N6c7kJ16Rp2/mbtax9OCzxpece\n" + + " byi1eiLfIBmkcRawL/vCc2v6VLI18i6HsNVO3l2yGosKCbuSoGDx2fCdAOk/rgdz\n" + + " cWOvFsIZSKuD+FVbSS/J9GVs7yotsS4PRl4iX9UMnfDnOMfO7bcBgbXtDl4SCU1v\n" + + " dJrRw7IL/pLz34Rv9a8nYitrzrxtLOp3nYUCAwEAAaOBhDCBgTBgBgMIIDEEWTBX\n" + + " gh5pZGVtLXB1cGFnZW50LmRtei1pbnQudW5pbW8uaXSGNWh0dHBzOi8vaWRlbS1w\n" + + " dXBhZ2VudC5kbXotaW50LnVuaW1vLml0L2lkcC9zaGliYm9sZXRoMB0GA1UdDgQW\n" + + " BBT8PANzz+adGnTRe8ldcyxAwe4VnzANBgkqhkiG9w0BAQUFAAOCAQEAOEnO8Clu\n" + + " 9z/Lf/8XOOsTdxJbV29DIF3G8KoQsB3dBsLwPZVEAQIP6ceS32Xaxrl6FMTDDNkL\n" + + " qUvvInUisw0+I5zZwYHybJQCletUWTnz58SC4C9G7FpuXHFZnOGtRcgGD1NOX4UU\n" + + " duus/4nVcGSLhDjszZ70Xtj0gw2Sn46oQPHTJ81QZ3Y9ih+Aj1c9OtUSBwtWZFkU\n" + + " yooAKoR8li68Yb21zN2N65AqV+ndL98M8xUYMKLONuAXStDeoVCipH6PJ09Z5U2p\n" + + " V5p4IQRV6QBsNw9CISJFuHzkVYTH5ZxzN80Ru46vh4y2M0Nu8GQ9I085KoZkrf5e\n" + + " Cq53OZt9ISjHEw==\n" + " \n" + + " \n" + " \n" + " \n" + " \n" + + " \n" + + " \n" + " \n" + " \n" + + " \n" + " Consortium GARR\n" + + " \n" + " \n" + + " Consortium GARR\n" + " \n" + " \n" + + " \n" + " Consortium GARR\n" + + " \n" + " \n" + + " Consortium GARR\n" + " \n" + " \n" + + " \n" + " https://example.org\n" + + " \n" + " \n" + " \n" + + " \n" + + " mailto:technical.contact@example.com\n" + + " \n" + " \n" + ""; @Test public void fromMetadataLocationWhenResolvableThenPopulatesBuilder() throws Exception { try (MockWebServer server = new MockWebServer()) { server.enqueue(new MockResponse().setBody(IDP_SSO_DESCRIPTOR_PAYLOAD).setResponseCode(200)); RelyingPartyRegistration registration = RelyingPartyRegistrations - .fromMetadataLocation(server.url("/").toString()) - .entityId("rp") - .build(); + .fromMetadataLocation(server.url("/").toString()).entityId("rp").build(); RelyingPartyRegistration.AssertingPartyDetails details = registration.getAssertingPartyDetails(); assertThat(details.getEntityId()).isEqualTo("https://idp.example.com/idp/shibboleth"); assertThat(details.getSingleSignOnServiceLocation()) .isEqualTo("https://idp.example.com/idp/profile/SAML2/POST/SSO"); - assertThat(details.getSingleSignOnServiceBinding()) - .isEqualTo(Saml2MessageBinding.POST); + assertThat(details.getSingleSignOnServiceBinding()).isEqualTo(Saml2MessageBinding.POST); assertThat(details.getVerificationX509Credentials()).hasSize(1); assertThat(details.getEncryptionX509Credentials()).hasSize(1); } @@ -156,4 +120,5 @@ public class RelyingPartyRegistrationsTests { .isInstanceOf(Saml2Exception.class); } } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/TestRelyingPartyRegistrations.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/TestRelyingPartyRegistrations.java index c378576f26..dd0f502553 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/TestRelyingPartyRegistrations.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/TestRelyingPartyRegistrations.java @@ -33,40 +33,32 @@ public class TestRelyingPartyRegistrations { String rpEntityId = "{baseUrl}/saml2/service-provider-metadata/{registrationId}"; Saml2X509Credential signingCredential = relyingPartySigningCredential(); - String assertionConsumerServiceLocation = "{baseUrl}" + Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI; + String assertionConsumerServiceLocation = "{baseUrl}" + + Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI; String apEntityId = "https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/metadata.php"; Saml2X509Credential verificationCertificate = relyingPartyVerifyingCredential(); String singleSignOnServiceLocation = "https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php"; - return RelyingPartyRegistration.withRegistrationId(registrationId) - .entityId(rpEntityId) + return RelyingPartyRegistration.withRegistrationId(registrationId).entityId(rpEntityId) .assertionConsumerServiceLocation(assertionConsumerServiceLocation) .credentials(c -> c.add(signingCredential)) - .providerDetails(c -> c - .entityId(apEntityId) - .webSsoUrl(singleSignOnServiceLocation)) - .credentials(c -> c.add(verificationCertificate)); + .providerDetails(c -> c.entityId(apEntityId).webSsoUrl(singleSignOnServiceLocation)) + .credentials(c -> c.add(verificationCertificate)); } public static RelyingPartyRegistration.Builder noCredentials() { - return RelyingPartyRegistration.withRegistrationId("registration-id") - .entityId("rp-entity-id") - .assertionConsumerServiceLocation("https://rp.example.org/acs") - .assertingPartyDetails(party -> party - .entityId("ap-entity-id") - .singleSignOnServiceLocation("https://ap.example.org/sso") - ); + return RelyingPartyRegistration.withRegistrationId("registration-id").entityId("rp-entity-id") + .assertionConsumerServiceLocation("https://rp.example.org/acs").assertingPartyDetails(party -> party + .entityId("ap-entity-id").singleSignOnServiceLocation("https://ap.example.org/sso")); } public static RelyingPartyRegistration.Builder full() { return noCredentials() .signingX509Credentials(c -> c.add(TestSaml2X509Credentials.relyingPartySigningCredential())) .decryptionX509Credentials(c -> c.add(TestSaml2X509Credentials.relyingPartyDecryptingCredential())) - .assertingPartyDetails(party -> party - .verificationX509Credentials(c -> c.add( - TestSaml2X509Credentials.relyingPartyVerifyingCredential()) - ) - ); + .assertingPartyDetails(party -> party.verificationX509Credentials( + c -> c.add(TestSaml2X509Credentials.relyingPartyVerifyingCredential()))); } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilterTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilterTests.java index b685adab56..495cfa3498 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilterTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilterTests.java @@ -36,8 +36,11 @@ import static org.mockito.Mockito.when; public class Saml2WebSsoAuthenticationFilterTests { private Saml2WebSsoAuthenticationFilter filter; + private RelyingPartyRegistrationRepository repository = mock(RelyingPartyRegistrationRepository.class); + private MockHttpServletRequest request = new MockHttpServletRequest(); + private HttpServletResponse response = new MockHttpServletResponse(); @Rule @@ -87,9 +90,11 @@ public class Saml2WebSsoAuthenticationFilterTests { try { filter.attemptAuthentication(request, response); failBecauseExceptionWasNotThrown(Saml2AuthenticationException.class); - } catch (Exception e) { + } + catch (Exception e) { assertThat(e).isInstanceOf(Saml2AuthenticationException.class); assertThat(e.getMessage()).isEqualTo("No relying party registration found"); } } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationRequestFilterTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationRequestFilterTests.java index 1ea4d636c9..8a12be054d 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationRequestFilterTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationRequestFilterTests.java @@ -48,14 +48,21 @@ import static org.springframework.security.saml2.provider.service.registration.S public class Saml2WebSsoAuthenticationRequestFilterTests { private static final String IDP_SSO_URL = "https://sso-url.example.com/IDP/SSO"; + private Saml2WebSsoAuthenticationRequestFilter filter; + private RelyingPartyRegistrationRepository repository = mock(RelyingPartyRegistrationRepository.class); + private Saml2AuthenticationRequestFactory factory = mock(Saml2AuthenticationRequestFactory.class); - private Saml2AuthenticationRequestContextResolver resolver = - mock(Saml2AuthenticationRequestContextResolver.class); + + private Saml2AuthenticationRequestContextResolver resolver = mock(Saml2AuthenticationRequestContextResolver.class); + private MockHttpServletRequest request; + private MockHttpServletResponse response; + private MockFilterChain filterChain; + private RelyingPartyRegistration.Builder rpBuilder; @Before @@ -67,10 +74,8 @@ public class Saml2WebSsoAuthenticationRequestFilterTests { filterChain = new MockFilterChain(); - rpBuilder = RelyingPartyRegistration - .withRegistrationId("registration-id") - .providerDetails(c -> c.entityId("idp-entity-id")) - .providerDetails(c -> c.webSsoUrl(IDP_SSO_URL)) + rpBuilder = RelyingPartyRegistration.withRegistrationId("registration-id") + .providerDetails(c -> c.entityId("idp-entity-id")).providerDetails(c -> c.webSsoUrl(IDP_SSO_URL)) .assertionConsumerServiceUrlTemplate("template") .credentials(c -> c.add(assertingPartyPrivateCredential())); } @@ -79,9 +84,7 @@ public class Saml2WebSsoAuthenticationRequestFilterTests { public void doFilterWhenNoRelayStateThenRedirectDoesNotContainParameter() throws ServletException, IOException { when(repository.findByRegistrationId("registration-id")).thenReturn(rpBuilder.build()); filter.doFilterInternal(request, response, filterChain); - assertThat(response.getHeader("Location")) - .doesNotContain("RelayState=") - .startsWith(IDP_SSO_URL); + assertThat(response.getHeader("Location")).doesNotContain("RelayState=").startsWith(IDP_SSO_URL); } @Test @@ -89,9 +92,7 @@ public class Saml2WebSsoAuthenticationRequestFilterTests { when(repository.findByRegistrationId("registration-id")).thenReturn(rpBuilder.build()); request.setParameter("RelayState", "my-relay-state"); filter.doFilterInternal(request, response, filterChain); - assertThat(response.getHeader("Location")) - .contains("RelayState=my-relay-state") - .startsWith(IDP_SSO_URL); + assertThat(response.getHeader("Location")).contains("RelayState=my-relay-state").startsWith(IDP_SSO_URL); } @Test @@ -101,53 +102,36 @@ public class Saml2WebSsoAuthenticationRequestFilterTests { final String relayStateEncoded = UriUtils.encode(relayStateValue, StandardCharsets.ISO_8859_1); request.setParameter("RelayState", relayStateValue); filter.doFilterInternal(request, response, filterChain); - assertThat(response.getHeader("Location")) - .contains("RelayState="+relayStateEncoded) - .startsWith(IDP_SSO_URL); + assertThat(response.getHeader("Location")).contains("RelayState=" + relayStateEncoded).startsWith(IDP_SSO_URL); } @Test public void doFilterWhenSimpleSignatureSpecifiedThenSignatureParametersAreInTheRedirectURL() throws Exception { - when(repository.findByRegistrationId("registration-id")).thenReturn( - rpBuilder - .build() - ); + when(repository.findByRegistrationId("registration-id")).thenReturn(rpBuilder.build()); final String relayStateValue = "https://my-relay-state.example.com?with=param&other=param"; final String relayStateEncoded = UriUtils.encode(relayStateValue, StandardCharsets.ISO_8859_1); request.setParameter("RelayState", relayStateValue); filter.doFilterInternal(request, response, filterChain); - assertThat(response.getHeader("Location")) - .contains("RelayState="+relayStateEncoded) - .contains("SigAlg=") - .contains("Signature=") - .startsWith(IDP_SSO_URL); + assertThat(response.getHeader("Location")).contains("RelayState=" + relayStateEncoded).contains("SigAlg=") + .contains("Signature=").startsWith(IDP_SSO_URL); } @Test public void doFilterWhenSignatureIsDisabledThenSignatureParametersAreNotInTheRedirectURL() throws Exception { - when(repository.findByRegistrationId("registration-id")).thenReturn( - rpBuilder - .providerDetails(c -> c.signAuthNRequest(false)) - .build() - ); + when(repository.findByRegistrationId("registration-id")) + .thenReturn(rpBuilder.providerDetails(c -> c.signAuthNRequest(false)).build()); final String relayStateValue = "https://my-relay-state.example.com?with=param&other=param"; final String relayStateEncoded = UriUtils.encode(relayStateValue, StandardCharsets.ISO_8859_1); request.setParameter("RelayState", relayStateValue); filter.doFilterInternal(request, response, filterChain); - assertThat(response.getHeader("Location")) - .contains("RelayState="+relayStateEncoded) - .doesNotContain("SigAlg=") - .doesNotContain("Signature=") - .startsWith(IDP_SSO_URL); + assertThat(response.getHeader("Location")).contains("RelayState=" + relayStateEncoded).doesNotContain("SigAlg=") + .doesNotContain("Signature=").startsWith(IDP_SSO_URL); } @Test public void doFilterWhenPostFormDataIsPresent() throws Exception { - when(repository.findByRegistrationId("registration-id")).thenReturn( - rpBuilder - .providerDetails(c -> c.binding(POST)) - .build() - ); + when(repository.findByRegistrationId("registration-id")) + .thenReturn(rpBuilder.providerDetails(c -> c.binding(POST)).build()); final String relayStateValue = "https://my-relay-state.example.com?with=param&other=param&javascript{alert('1');}"; final String relayStateEncoded = HtmlUtils.htmlEscape(relayStateValue); request.setParameter("RelayState", relayStateValue); @@ -156,28 +140,23 @@ public class Saml2WebSsoAuthenticationRequestFilterTests { assertThat(response.getContentAsString()) .contains("
        ") .contains(" c.binding(POST)) - .build(); + RelyingPartyRegistration relyingParty = this.rpBuilder.providerDetails(c -> c.binding(POST)).build(); Saml2PostAuthenticationRequest authenticationRequest = mock(Saml2PostAuthenticationRequest.class); when(authenticationRequest.getAuthenticationRequestUri()).thenReturn("uri"); when(authenticationRequest.getRelayState()).thenReturn("relay"); when(authenticationRequest.getSamlRequest()).thenReturn("saml"); when(this.repository.findByRegistrationId("registration-id")).thenReturn(relyingParty); - when(this.factory.createPostAuthenticationRequest(any())) - .thenReturn(authenticationRequest); + when(this.factory.createPostAuthenticationRequest(any())).thenReturn(authenticationRequest); - Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter - (this.repository); + Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(this.repository); filter.setAuthenticationRequestFactory(this.factory); filter.doFilterInternal(this.request, this.response, this.filterChain); - assertThat(this.response.getContentAsString()) - .contains("") + assertThat(this.response.getContentAsString()).contains("") .contains(" c.binding(POST)) - .build(); + RelyingPartyRegistration relyingParty = this.rpBuilder.providerDetails(c -> c.binding(POST)).build(); Saml2PostAuthenticationRequest authenticationRequest = mock(Saml2PostAuthenticationRequest.class); when(authenticationRequest.getAuthenticationRequestUri()).thenReturn("uri"); when(authenticationRequest.getRelayState()).thenReturn("relay"); when(authenticationRequest.getSamlRequest()).thenReturn("saml"); - when(this.resolver.resolve(this.request)).thenReturn(authenticationRequestContext() - .relyingPartyRegistration(relyingParty) - .build()); - when(this.factory.createPostAuthenticationRequest(any())) - .thenReturn(authenticationRequest); + when(this.resolver.resolve(this.request)) + .thenReturn(authenticationRequestContext().relyingPartyRegistration(relyingParty).build()); + when(this.factory.createPostAuthenticationRequest(any())).thenReturn(authenticationRequest); - Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter - (this.resolver, this.factory); + Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(this.resolver, + this.factory); filter.doFilterInternal(this.request, this.response, this.filterChain); - assertThat(this.response.getContentAsString()) - .contains("") + assertThat(this.response.getContentAsString()).contains("") .contains(" filter.setRedirectMatcher(null)) - .isInstanceOf(IllegalArgumentException.class); + Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(this.repository); + assertThatCode(() -> filter.setRedirectMatcher(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void setAuthenticationRequestFactoryWhenNullThenException() { Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(this.repository); - assertThatCode(() -> filter.setAuthenticationRequestFactory(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> filter.setAuthenticationRequestFactory(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void doFilterWhenRequestMatcherFailsThenSkipsFilter() throws Exception { - Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter - (this.repository); + Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(this.repository); filter.setRedirectMatcher(request -> false); filter.doFilter(this.request, this.response, this.filterChain); verifyNoInteractions(this.repository); @@ -234,9 +204,9 @@ public class Saml2WebSsoAuthenticationRequestFilterTests { @Test public void doFilterWhenRelyingPartyRegistrationNotFoundThenUnauthorized() throws Exception { - Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter - (this.repository); + Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(this.repository); filter.doFilter(this.request, this.response, this.filterChain); assertThat(this.response.getStatus()).isEqualTo(401); } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/DefaultRelyingPartyRegistrationResolverTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/DefaultRelyingPartyRegistrationResolverTests.java index 693075f803..99f5e261a0 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/DefaultRelyingPartyRegistrationResolverTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/DefaultRelyingPartyRegistrationResolverTests.java @@ -31,11 +31,14 @@ import static org.springframework.security.saml2.provider.service.registration.T * Tests for {@link DefaultRelyingPartyRegistrationResolver} */ public class DefaultRelyingPartyRegistrationResolverTests { + private final RelyingPartyRegistration registration = relyingPartyRegistration().build(); - private final RelyingPartyRegistrationRepository repository = - new InMemoryRelyingPartyRegistrationRepository(this.registration); - private final DefaultRelyingPartyRegistrationResolver resolver = - new DefaultRelyingPartyRegistrationResolver(this.repository); + + private final RelyingPartyRegistrationRepository repository = new InMemoryRelyingPartyRegistrationRepository( + this.registration); + + private final DefaultRelyingPartyRegistrationResolver resolver = new DefaultRelyingPartyRegistrationResolver( + this.repository); @Test public void resolveWhenRequestContainsRegistrationIdThenResolves() { @@ -43,8 +46,7 @@ public class DefaultRelyingPartyRegistrationResolverTests { request.setPathInfo("/some/path/" + this.registration.getRegistrationId()); RelyingPartyRegistration registration = this.resolver.convert(request); assertThat(registration).isNotNull(); - assertThat(registration.getRegistrationId()) - .isEqualTo(this.registration.getRegistrationId()); + assertThat(registration.getRegistrationId()).isEqualTo(this.registration.getRegistrationId()); assertThat(registration.getEntityId()) .isEqualTo("http://localhost/saml2/service-provider-metadata/" + this.registration.getRegistrationId()); assertThat(registration.getAssertionConsumerServiceLocation()) @@ -71,4 +73,5 @@ public class DefaultRelyingPartyRegistrationResolverTests { assertThatCode(() -> new DefaultRelyingPartyRegistrationResolver(null)) .isInstanceOf(IllegalArgumentException.class); } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/DefaultSaml2AuthenticationRequestContextResolverTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/DefaultSaml2AuthenticationRequestContextResolverTests.java index 80f2cd6afc..2419929132 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/DefaultSaml2AuthenticationRequestContextResolverTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/DefaultSaml2AuthenticationRequestContextResolverTests.java @@ -36,23 +36,27 @@ import static org.springframework.security.saml2.credentials.TestSaml2X509Creden public class DefaultSaml2AuthenticationRequestContextResolverTests { private static final String ASSERTING_PARTY_SSO_URL = "https://idp.example.com/sso"; + private static final String RELYING_PARTY_SSO_URL = "https://sp.example.com/sso"; + private static final String ASSERTING_PARTY_ENTITY_ID = "asserting-party-entity-id"; + private static final String RELYING_PARTY_ENTITY_ID = "relying-party-entity-id"; + private static final String REGISTRATION_ID = "registration-id"; private MockHttpServletRequest request; + private RelyingPartyRegistration.Builder relyingPartyBuilder; - private Saml2AuthenticationRequestContextResolver authenticationRequestContextResolver - = new DefaultSaml2AuthenticationRequestContextResolver( - new DefaultRelyingPartyRegistrationResolver(id -> relyingPartyBuilder.build())); + + private Saml2AuthenticationRequestContextResolver authenticationRequestContextResolver = new DefaultSaml2AuthenticationRequestContextResolver( + new DefaultRelyingPartyRegistrationResolver(id -> relyingPartyBuilder.build())); @Before public void setup() { this.request = new MockHttpServletRequest(); this.request.setPathInfo("/saml2/authenticate/registration-id"); - this.relyingPartyBuilder = RelyingPartyRegistration - .withRegistrationId(REGISTRATION_ID) + this.relyingPartyBuilder = RelyingPartyRegistration.withRegistrationId(REGISTRATION_ID) .localEntityIdTemplate(RELYING_PARTY_ENTITY_ID) .providerDetails(c -> c.entityId(ASSERTING_PARTY_ENTITY_ID)) .providerDetails(c -> c.webSsoUrl(ASSERTING_PARTY_SSO_URL)) @@ -63,8 +67,7 @@ public class DefaultSaml2AuthenticationRequestContextResolverTests { @Test public void resolveWhenRequestAndRelyingPartyNotNullThenCreateSaml2AuthenticationRequestContext() { this.request.addParameter("RelayState", "relay-state"); - Saml2AuthenticationRequestContext context = - this.authenticationRequestContextResolver.resolve(this.request); + Saml2AuthenticationRequestContext context = this.authenticationRequestContextResolver.resolve(this.request); assertThat(context).isNotNull(); assertThat(context.getAssertionConsumerServiceUrl()).isEqualTo(RELYING_PARTY_SSO_URL); @@ -77,20 +80,16 @@ public class DefaultSaml2AuthenticationRequestContextResolverTests { @Test public void resolveWhenAssertionConsumerServiceUrlTemplateContainsRegistrationIdThenResolves() { - this.relyingPartyBuilder - .assertionConsumerServiceLocation("/saml2/authenticate/{registrationId}"); - Saml2AuthenticationRequestContext context = - this.authenticationRequestContextResolver.resolve(this.request); + this.relyingPartyBuilder.assertionConsumerServiceLocation("/saml2/authenticate/{registrationId}"); + Saml2AuthenticationRequestContext context = this.authenticationRequestContextResolver.resolve(this.request); assertThat(context.getAssertionConsumerServiceUrl()).isEqualTo("/saml2/authenticate/registration-id"); } @Test public void resolveWhenAssertionConsumerServiceUrlTemplateContainsBaseUrlThenResolves() { - this.relyingPartyBuilder - .assertionConsumerServiceLocation("{baseUrl}/saml2/authenticate/{registrationId}"); - Saml2AuthenticationRequestContext context = - this.authenticationRequestContextResolver.resolve(this.request); + this.relyingPartyBuilder.assertionConsumerServiceLocation("{baseUrl}/saml2/authenticate/{registrationId}"); + Saml2AuthenticationRequestContext context = this.authenticationRequestContextResolver.resolve(this.request); assertThat(context.getAssertionConsumerServiceUrl()) .isEqualTo("http://localhost/saml2/authenticate/registration-id"); @@ -98,8 +97,8 @@ public class DefaultSaml2AuthenticationRequestContextResolverTests { @Test public void resolveWhenRelyingPartyNullThenException() { - assertThatCode(() -> - this.authenticationRequestContextResolver.resolve(null)) + assertThatCode(() -> this.authenticationRequestContextResolver.resolve(null)) .isInstanceOf(IllegalArgumentException.class); } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2AuthenticationTokenConverterTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2AuthenticationTokenConverterTests.java index 74b987ea63..9889c5a793 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2AuthenticationTokenConverterTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2AuthenticationTokenConverterTests.java @@ -43,6 +43,7 @@ import static org.springframework.security.saml2.provider.service.registration.T @RunWith(MockitoJUnitRunner.class) public class Saml2AuthenticationTokenConverterTests { + @Mock Converter relyingPartyRegistrationResolver; @@ -50,8 +51,8 @@ public class Saml2AuthenticationTokenConverterTests { @Test public void convertWhenSamlResponseThenToken() { - Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter - (this.relyingPartyRegistrationResolver); + Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter( + this.relyingPartyRegistrationResolver); when(this.relyingPartyRegistrationResolver.convert(any(HttpServletRequest.class))) .thenReturn(this.relyingPartyRegistration); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -64,8 +65,8 @@ public class Saml2AuthenticationTokenConverterTests { @Test public void convertWhenNoSamlResponseThenNull() { - Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter - (this.relyingPartyRegistrationResolver); + Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter( + this.relyingPartyRegistrationResolver); when(this.relyingPartyRegistrationResolver.convert(any(HttpServletRequest.class))) .thenReturn(this.relyingPartyRegistration); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -74,18 +75,17 @@ public class Saml2AuthenticationTokenConverterTests { @Test public void convertWhenNoRelyingPartyRegistrationThenNull() { - Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter - (this.relyingPartyRegistrationResolver); - when(this.relyingPartyRegistrationResolver.convert(any(HttpServletRequest.class))) - .thenReturn(null); + Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter( + this.relyingPartyRegistrationResolver); + when(this.relyingPartyRegistrationResolver.convert(any(HttpServletRequest.class))).thenReturn(null); MockHttpServletRequest request = new MockHttpServletRequest(); assertThat(converter.convert(request)).isNull(); } @Test public void convertWhenGetRequestThenInflates() { - Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter - (this.relyingPartyRegistrationResolver); + Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter( + this.relyingPartyRegistrationResolver); when(this.relyingPartyRegistrationResolver.convert(any(HttpServletRequest.class))) .thenReturn(this.relyingPartyRegistration); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -101,14 +101,13 @@ public class Saml2AuthenticationTokenConverterTests { @Test public void constructorWhenResolverIsNullThenIllegalArgument() { - assertThatCode(() -> new Saml2AuthenticationTokenConverter(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> new Saml2AuthenticationTokenConverter(null)).isInstanceOf(IllegalArgumentException.class); } @Test public void convertWhenUsingSamlUtilsBase64ThenXmlIsValid() throws Exception { - Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter - (this.relyingPartyRegistrationResolver); + Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter( + this.relyingPartyRegistrationResolver); when(this.relyingPartyRegistrationResolver.convert(any(HttpServletRequest.class))) .thenReturn(this.relyingPartyRegistration); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -118,8 +117,7 @@ public class Saml2AuthenticationTokenConverterTests { } private void validateSsoCircleXml(String xml) { - assertThat(xml) - .contains("InResponseTo=\"ARQ9a73ead-7dcf-45a8-89eb-26f3c9900c36\"") + assertThat(xml).contains("InResponseTo=\"ARQ9a73ead-7dcf-45a8-89eb-26f3c9900c36\"") .contains(" ID=\"s246d157446618e90e43fb79bdd4d9e9e19cf2c7c4\"") .contains("https://idp.ssocircle.com"); } @@ -129,4 +127,5 @@ public class Saml2AuthenticationTokenConverterTests { String response = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8); return UriUtils.decode(response, UTF_8); } + } diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilterTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilterTests.java index 658afcbd96..afcee7b395 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilterTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/Saml2MetadataFilterTests.java @@ -42,18 +42,23 @@ import static org.springframework.security.saml2.provider.service.registration.T public class Saml2MetadataFilterTests { RelyingPartyRegistrationRepository repository; + Saml2MetadataResolver resolver; + Saml2MetadataFilter filter; + MockHttpServletRequest request; + MockHttpServletResponse response; + FilterChain chain; @Before public void setup() { this.repository = mock(RelyingPartyRegistrationRepository.class); this.resolver = mock(Saml2MetadataResolver.class); - this.filter = new Saml2MetadataFilter( - new DefaultRelyingPartyRegistrationResolver(this.repository), this.resolver); + this.filter = new Saml2MetadataFilter(new DefaultRelyingPartyRegistrationResolver(this.repository), + this.resolver); this.request = new MockHttpServletRequest(); this.response = new MockHttpServletResponse(); this.chain = mock(FilterChain.class); @@ -103,8 +108,8 @@ public class Saml2MetadataFilterTests { // given this.request.setPathInfo("/saml2/service-provider-metadata/validRegistration"); RelyingPartyRegistration validRegistration = noCredentials() - .assertingPartyDetails(party -> party - .verificationX509Credentials(c -> c.add(relyingPartyVerifyingCredential()))) + .assertingPartyDetails( + party -> party.verificationX509Credentials(c -> c.add(relyingPartyVerifyingCredential()))) .build(); String generatedMetadata = "test"; @@ -138,7 +143,7 @@ public class Saml2MetadataFilterTests { @Test public void setRequestMatcherWhenNullThenIllegalArgument() { - assertThatCode(() -> this.filter.setRequestMatcher(null)) - .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> this.filter.setRequestMatcher(null)).isInstanceOf(IllegalArgumentException.class); } + } diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/TagLibConfig.java b/taglibs/src/main/java/org/springframework/security/taglibs/TagLibConfig.java index ec4360991a..fecf9288b9 100644 --- a/taglibs/src/main/java/org/springframework/security/taglibs/TagLibConfig.java +++ b/taglibs/src/main/java/org/springframework/security/taglibs/TagLibConfig.java @@ -29,6 +29,7 @@ import javax.servlet.jsp.tagext.Tag; * @author Luke Taylor */ public final class TagLibConfig { + static Log logger = LogFactory.getLog("spring-security-taglibs"); static final boolean DISABLE_UI_SECURITY; @@ -53,7 +54,6 @@ public final class TagLibConfig { /** * Returns EVAL_BODY_INCLUDE if the authorized flag is true or UI security has been * disabled. Otherwise returns SKIP_BODY. - * * @param authorized whether the user is authorized to see the content or not */ public static int evalOrSkip(boolean authorized) { @@ -75,4 +75,5 @@ public final class TagLibConfig { public static String getSecuredUiSuffix() { return SECURED_UI_SUFFIX; } + } diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/authz/AbstractAuthorizeTag.java b/taglibs/src/main/java/org/springframework/security/taglibs/authz/AbstractAuthorizeTag.java index 1da2aa966c..fff580bc65 100644 --- a/taglibs/src/main/java/org/springframework/security/taglibs/authz/AbstractAuthorizeTag.java +++ b/taglibs/src/main/java/org/springframework/security/taglibs/authz/AbstractAuthorizeTag.java @@ -55,8 +55,11 @@ import org.springframework.util.StringUtils; * @since 3.1.0 */ public abstract class AbstractAuthorizeTag { + private String access; + private String url; + private String method = "GET"; /** @@ -85,7 +88,6 @@ public abstract class AbstractAuthorizeTag { *
      12. url, method
      13. * * The above combinations are mutually exclusive and evaluated in the given order. - * * @return the result of the authorization decision * @throws IOException */ @@ -112,7 +114,6 @@ public abstract class AbstractAuthorizeTag { * Make an authorization decision based on a Spring EL expression. See the * "Expression-Based Access Control" chapter in Spring Security for details on what * expressions can be used. - * * @return the result of the authorization decision * @throws IOException */ @@ -134,37 +135,30 @@ public abstract class AbstractAuthorizeTag { throw ioException; } - return ExpressionUtils.evaluateAsBoolean(accessExpression, - createExpressionEvaluationContext(handler)); + return ExpressionUtils.evaluateAsBoolean(accessExpression, createExpressionEvaluationContext(handler)); } /** * Allows the {@code EvaluationContext} to be customized for variable lookup etc. */ - protected EvaluationContext createExpressionEvaluationContext( - SecurityExpressionHandler handler) { - FilterInvocation f = new FilterInvocation(getRequest(), getResponse(), - (request, response) -> { - throw new UnsupportedOperationException(); - }); + protected EvaluationContext createExpressionEvaluationContext(SecurityExpressionHandler handler) { + FilterInvocation f = new FilterInvocation(getRequest(), getResponse(), (request, response) -> { + throw new UnsupportedOperationException(); + }); - return handler.createEvaluationContext(SecurityContextHolder.getContext() - .getAuthentication(), f); + return handler.createEvaluationContext(SecurityContextHolder.getContext().getAuthentication(), f); } /** * Make an authorization decision based on the URL and HTTP method attributes. True is * returned if the user is allowed to access the given URL as defined. - * * @return the result of the authorization decision * @throws IOException */ public boolean authorizeUsingUrlCheck() throws IOException { String contextPath = ((HttpServletRequest) getRequest()).getContextPath(); - Authentication currentUser = SecurityContextHolder.getContext() - .getAuthentication(); - return getPrivilegeEvaluator().isAllowed(contextPath, getUrl(), getMethod(), - currentUser); + Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); + return getPrivilegeEvaluator().isAllowed(contextPath, getUrl(), getMethod(), currentUser); } public String getAccess() { @@ -194,22 +188,20 @@ public abstract class AbstractAuthorizeTag { /*------------- Private helper methods -----------------*/ @SuppressWarnings({ "unchecked", "rawtypes" }) - private SecurityExpressionHandler getExpressionHandler() - throws IOException { - ApplicationContext appContext = SecurityWebApplicationContextUtils.findRequiredWebApplicationContext(getServletContext()); - Map handlers = appContext - .getBeansOfType(SecurityExpressionHandler.class); + private SecurityExpressionHandler getExpressionHandler() throws IOException { + ApplicationContext appContext = SecurityWebApplicationContextUtils + .findRequiredWebApplicationContext(getServletContext()); + Map handlers = appContext.getBeansOfType(SecurityExpressionHandler.class); for (SecurityExpressionHandler h : handlers.values()) { - if (FilterInvocation.class.equals(GenericTypeResolver.resolveTypeArgument( - h.getClass(), SecurityExpressionHandler.class))) { + if (FilterInvocation.class + .equals(GenericTypeResolver.resolveTypeArgument(h.getClass(), SecurityExpressionHandler.class))) { return h; } } - throw new IOException( - "No visible WebSecurityExpressionHandler instance could be found in the application " - + "context. There must be at least one in order to support expressions in JSP 'authorize' tags."); + throw new IOException("No visible WebSecurityExpressionHandler instance could be found in the application " + + "context. There must be at least one in order to support expressions in JSP 'authorize' tags."); } private WebInvocationPrivilegeEvaluator getPrivilegeEvaluator() throws IOException { @@ -219,9 +211,9 @@ public abstract class AbstractAuthorizeTag { return privEvaluatorFromRequest; } - ApplicationContext ctx = SecurityWebApplicationContextUtils.findRequiredWebApplicationContext(getServletContext()); - Map wipes = ctx - .getBeansOfType(WebInvocationPrivilegeEvaluator.class); + ApplicationContext ctx = SecurityWebApplicationContextUtils + .findRequiredWebApplicationContext(getServletContext()); + Map wipes = ctx.getBeansOfType(WebInvocationPrivilegeEvaluator.class); if (wipes.size() == 0) { throw new IOException( @@ -231,4 +223,5 @@ public abstract class AbstractAuthorizeTag { return (WebInvocationPrivilegeEvaluator) wipes.values().toArray()[0]; } + } diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/authz/AccessControlListTag.java b/taglibs/src/main/java/org/springframework/security/taglibs/authz/AccessControlListTag.java index 0d1c6149e3..b2b1d9ef6e 100644 --- a/taglibs/src/main/java/org/springframework/security/taglibs/authz/AccessControlListTag.java +++ b/taglibs/src/main/java/org/springframework/security/taglibs/authz/AccessControlListTag.java @@ -34,7 +34,6 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.taglibs.TagLibConfig; import org.springframework.security.web.context.support.SecurityWebApplicationContextUtils; - /** * An implementation of {@link Tag} that allows its body through if all authorizations are * granted to the request's principal. @@ -53,6 +52,7 @@ import org.springframework.security.web.context.support.SecurityWebApplicationCo * @author Rob Winch */ public class AccessControlListTag extends TagSupport { + // ~ Static fields/initializers // ===================================================================================== @@ -62,9 +62,13 @@ public class AccessControlListTag extends TagSupport { // ================================================================================================ private ApplicationContext applicationContext; + private Object domainObject; + private PermissionEvaluator permissionEvaluator; + private String hasPermission = ""; + private String var; // ~ Methods @@ -86,11 +90,11 @@ public class AccessControlListTag extends TagSupport { return evalBody(); } - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { if (logger.isDebugEnabled()) { - logger.debug("SecurityContextHolder did not return a non-null Authentication object, so skipping tag body"); + logger.debug( + "SecurityContextHolder did not return a non-null Authentication object, so skipping tag body"); } return skipBody(); @@ -98,8 +102,7 @@ public class AccessControlListTag extends TagSupport { List requiredPermissions = parseHasPermission(hasPermission); for (Object requiredPermission : requiredPermissions) { - if (!permissionEvaluator.hasPermission(authentication, domainObject, - requiredPermission)) { + if (!permissionEvaluator.hasPermission(authentication, domainObject, requiredPermission)) { return skipBody(); } } @@ -138,10 +141,8 @@ public class AccessControlListTag extends TagSupport { /** * Allows test cases to override where application context obtained from. - * * @param pageContext so the ServletContext can be accessed as required * by Spring's WebApplicationContextUtils - * * @return the Spring application context (never null) */ protected ApplicationContext getContext(PageContext pageContext) { @@ -183,8 +184,8 @@ public class AccessControlListTag extends TagSupport { return map.values().iterator().next(); } - throw new JspException("Found incorrect number of " + type.getSimpleName() - + " instances in " + "application context - you must have only have one!"); + throw new JspException("Found incorrect number of " + type.getSimpleName() + " instances in " + + "application context - you must have only have one!"); } public void setDomainObject(Object domainObject) { @@ -198,4 +199,5 @@ public class AccessControlListTag extends TagSupport { public void setVar(String var) { this.var = var; } + } diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/authz/AuthenticationTag.java b/taglibs/src/main/java/org/springframework/security/taglibs/authz/AuthenticationTag.java index e740ffb6ec..90d7200f65 100644 --- a/taglibs/src/main/java/org/springframework/security/taglibs/authz/AuthenticationTag.java +++ b/taglibs/src/main/java/org/springframework/security/taglibs/authz/AuthenticationTag.java @@ -47,9 +47,13 @@ public class AuthenticationTag extends TagSupport { // ================================================================================================ private String var; + private String property; + private int scope; + private boolean scopeSpecified; + private boolean htmlEscape = true; // ~ Methods @@ -160,4 +164,5 @@ public class AuthenticationTag extends TagSupport { protected boolean isHtmlEscape() { return htmlEscape; } + } diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/authz/JspAuthorizeTag.java b/taglibs/src/main/java/org/springframework/security/taglibs/authz/JspAuthorizeTag.java index 5ee16f7a3e..de9d1bb675 100644 --- a/taglibs/src/main/java/org/springframework/security/taglibs/authz/JspAuthorizeTag.java +++ b/taglibs/src/main/java/org/springframework/security/taglibs/authz/JspAuthorizeTag.java @@ -61,7 +61,6 @@ public class JspAuthorizeTag extends AbstractAuthorizeTag implements Tag { /** * Invokes the base class {@link AbstractAuthorizeTag#authorize()} method to decide if * the body of the tag should be skipped or not. - * * @return {@link Tag#SKIP_BODY} or {@link Tag#EVAL_BODY_INCLUDE} */ public int doStartTag() throws JspException { @@ -85,15 +84,12 @@ public class JspAuthorizeTag extends AbstractAuthorizeTag implements Tag { } @Override - protected EvaluationContext createExpressionEvaluationContext( - SecurityExpressionHandler handler) { - return new PageContextVariableLookupEvaluationContext( - super.createExpressionEvaluationContext(handler)); + protected EvaluationContext createExpressionEvaluationContext(SecurityExpressionHandler handler) { + return new PageContextVariableLookupEvaluationContext(super.createExpressionEvaluationContext(handler)); } /** * Default processing of the end tag returning EVAL_PAGE. - * * @return EVAL_PAGE * @see Tag#doEndTag() */ @@ -158,8 +154,7 @@ public class JspAuthorizeTag extends AbstractAuthorizeTag implements Tag { return pageContext.getServletContext(); } - private final class PageContextVariableLookupEvaluationContext implements - EvaluationContext { + private final class PageContextVariableLookupEvaluationContext implements EvaluationContext { private EvaluationContext delegate; @@ -215,6 +210,7 @@ public class JspAuthorizeTag extends AbstractAuthorizeTag implements Tag { } return result; } + } } diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/authz/package-info.java b/taglibs/src/main/java/org/springframework/security/taglibs/authz/package-info.java index b0d0ce4388..e85e0b40da 100644 --- a/taglibs/src/main/java/org/springframework/security/taglibs/authz/package-info.java +++ b/taglibs/src/main/java/org/springframework/security/taglibs/authz/package-info.java @@ -17,4 +17,3 @@ * JSP Security tag library implementation. */ package org.springframework.security.taglibs.authz; - diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/csrf/AbstractCsrfTag.java b/taglibs/src/main/java/org/springframework/security/taglibs/csrf/AbstractCsrfTag.java index aff3d5f936..366a8fcfe4 100644 --- a/taglibs/src/main/java/org/springframework/security/taglibs/csrf/AbstractCsrfTag.java +++ b/taglibs/src/main/java/org/springframework/security/taglibs/csrf/AbstractCsrfTag.java @@ -33,8 +33,7 @@ abstract class AbstractCsrfTag extends TagSupport { @Override public int doEndTag() throws JspException { - CsrfToken token = (CsrfToken) this.pageContext.getRequest().getAttribute( - CsrfToken.class.getName()); + CsrfToken token = (CsrfToken) this.pageContext.getRequest().getAttribute(CsrfToken.class.getName()); if (token != null) { try { this.pageContext.getOut().write(this.handleToken(token)); @@ -48,4 +47,5 @@ abstract class AbstractCsrfTag extends TagSupport { } protected abstract String handleToken(CsrfToken token); + } diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/csrf/CsrfInputTag.java b/taglibs/src/main/java/org/springframework/security/taglibs/csrf/CsrfInputTag.java index 1b339a8b34..ade138fb54 100644 --- a/taglibs/src/main/java/org/springframework/security/taglibs/csrf/CsrfInputTag.java +++ b/taglibs/src/main/java/org/springframework/security/taglibs/csrf/CsrfInputTag.java @@ -29,7 +29,7 @@ public class CsrfInputTag extends AbstractCsrfTag { @Override public String handleToken(CsrfToken token) { - return ""; + return ""; } + } diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/csrf/CsrfMetaTagsTag.java b/taglibs/src/main/java/org/springframework/security/taglibs/csrf/CsrfMetaTagsTag.java index 11ad6d0a3b..e196dd8a2e 100644 --- a/taglibs/src/main/java/org/springframework/security/taglibs/csrf/CsrfMetaTagsTag.java +++ b/taglibs/src/main/java/org/springframework/security/taglibs/csrf/CsrfMetaTagsTag.java @@ -29,9 +29,9 @@ public class CsrfMetaTagsTag extends AbstractCsrfTag { @Override public String handleToken(CsrfToken token) { - return "" + "" + ""; + return "" + + "" + + ""; } + } diff --git a/taglibs/src/main/java/org/springframework/security/taglibs/package-info.java b/taglibs/src/main/java/org/springframework/security/taglibs/package-info.java index 719ba06d3e..11e50856d9 100644 --- a/taglibs/src/main/java/org/springframework/security/taglibs/package-info.java +++ b/taglibs/src/main/java/org/springframework/security/taglibs/package-info.java @@ -17,4 +17,3 @@ * Security related tag libraries that can be used in JSPs and templates. */ package org.springframework.security.taglibs; - diff --git a/taglibs/src/test/java/org/springframework/security/taglibs/TldTests.java b/taglibs/src/test/java/org/springframework/security/taglibs/TldTests.java index 44176488a9..24a69c89d5 100644 --- a/taglibs/src/test/java/org/springframework/security/taglibs/TldTests.java +++ b/taglibs/src/test/java/org/springframework/security/taglibs/TldTests.java @@ -27,9 +27,9 @@ import static org.assertj.core.api.Assertions.assertThat; public class TldTests { - //SEC-2324 + // SEC-2324 @Test - public void testTldVersionIsCorrect() throws Exception{ + public void testTldVersionIsCorrect() throws Exception { String SPRING_SECURITY_VERSION = "springSecurityVersion"; String version = System.getProperty(SPRING_SECURITY_VERSION); @@ -45,5 +45,4 @@ public class TldTests { assertThat(version).startsWith(tlibVersion); } - } diff --git a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AbstractAuthorizeTagTests.java b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AbstractAuthorizeTagTests.java index 7a7497bd94..26b6efff14 100644 --- a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AbstractAuthorizeTagTests.java +++ b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AbstractAuthorizeTagTests.java @@ -45,14 +45,17 @@ import org.springframework.security.web.access.expression.DefaultWebSecurityExpr import org.springframework.web.context.WebApplicationContext; /** - * * @author Rob Winch * */ public class AbstractAuthorizeTagTests { + private AbstractAuthorizeTag tag; + private MockHttpServletRequest request; + private MockHttpServletResponse response; + private MockServletContext servletContext; @Before @@ -73,8 +76,7 @@ public class AbstractAuthorizeTagTests { String uri = "/something"; WebInvocationPrivilegeEvaluator expected = mock(WebInvocationPrivilegeEvaluator.class); tag.setUrl(uri); - request.setAttribute(WebAttributes.WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE, - expected); + request.setAttribute(WebAttributes.WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE, expected); tag.authorizeUsingUrlCheck(); @@ -87,7 +89,8 @@ public class AbstractAuthorizeTagTests { WebInvocationPrivilegeEvaluator expected = mock(WebInvocationPrivilegeEvaluator.class); tag.setUrl(uri); WebApplicationContext wac = mock(WebApplicationContext.class); - when(wac.getBeansOfType(WebInvocationPrivilegeEvaluator.class)).thenReturn(Collections.singletonMap("wipe", expected)); + when(wac.getBeansOfType(WebInvocationPrivilegeEvaluator.class)) + .thenReturn(Collections.singletonMap("wipe", expected)); servletContext.setAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher", wac); tag.authorizeUsingUrlCheck(); @@ -102,7 +105,8 @@ public class AbstractAuthorizeTagTests { DefaultWebSecurityExpressionHandler expected = new DefaultWebSecurityExpressionHandler(); tag.setAccess("permitAll"); WebApplicationContext wac = mock(WebApplicationContext.class); - when(wac.getBeansOfType(SecurityExpressionHandler.class)).thenReturn(Collections.singletonMap("wipe", expected)); + when(wac.getBeansOfType(SecurityExpressionHandler.class)) + .thenReturn(Collections.singletonMap("wipe", expected)); servletContext.setAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher", wac); assertThat(tag.authorize()).isTrue(); @@ -124,5 +128,7 @@ public class AbstractAuthorizeTagTests { protected ServletContext getServletContext() { return servletContext; } + } + } diff --git a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AccessControlListTagTests.java b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AccessControlListTagTests.java index cba9d213ea..a37c2f974a 100644 --- a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AccessControlListTagTests.java +++ b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AccessControlListTagTests.java @@ -34,16 +34,19 @@ import javax.servlet.jsp.tagext.Tag; import java.util.*; /** - * * @author Luke Taylor * @author Rob Winch * @since 3.0 */ @SuppressWarnings("unchecked") public class AccessControlListTagTests { + AccessControlListTag tag; + PermissionEvaluator pe; + MockPageContext pageContext; + Authentication bob = new TestingAuthenticationToken("bob", "bobspass", "A"); @Before @@ -60,10 +63,8 @@ public class AccessControlListTagTests { when(ctx.getBeansOfType(PermissionEvaluator.class)).thenReturn(beanMap); MockServletContext servletCtx = new MockServletContext(); - servletCtx.setAttribute( - WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ctx); - pageContext = new MockPageContext(servletCtx, new MockHttpServletRequest(), - new MockHttpServletResponse()); + servletCtx.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ctx); + pageContext = new MockPageContext(servletCtx, new MockHttpServletRequest(), new MockHttpServletResponse()); tag.setPageContext(pageContext); } @@ -179,4 +180,5 @@ public class AccessControlListTagTests { assertThat(tag.doStartTag()).isEqualTo(Tag.SKIP_BODY); assertThat((Boolean) pageContext.getAttribute("allowed")).isFalse(); } + } diff --git a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthenticationTagTests.java b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthenticationTagTests.java index d768b992a6..edadacd968 100644 --- a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthenticationTagTests.java +++ b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthenticationTagTests.java @@ -35,13 +35,15 @@ import org.springframework.security.core.userdetails.User; * @author Ben Alex */ public class AuthenticationTagTests { + // ~ Instance fields // ================================================================================================ private final MyAuthenticationTag authenticationTag = new MyAuthenticationTag(); - private final Authentication auth = new TestingAuthenticationToken(new User( - "rodUserDetails", "koala", true, true, true, true, - AuthorityUtils.NO_AUTHORITIES), "koala", AuthorityUtils.NO_AUTHORITIES); + + private final Authentication auth = new TestingAuthenticationToken( + new User("rodUserDetails", "koala", true, true, true, true, AuthorityUtils.NO_AUTHORITIES), "koala", + AuthorityUtils.NO_AUTHORITIES); // ~ Methods // ======================================================================================================== @@ -64,8 +66,7 @@ public class AuthenticationTagTests { @Test public void testOperationWhenPrincipalIsAString() throws JspException { SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken("rodAsString", "koala", - AuthorityUtils.NO_AUTHORITIES)); + new TestingAuthenticationToken("rodAsString", "koala", AuthorityUtils.NO_AUTHORITIES)); authenticationTag.setProperty("principal"); assertThat(authenticationTag.doStartTag()).isEqualTo(Tag.SKIP_BODY); @@ -85,9 +86,8 @@ public class AuthenticationTagTests { @Test public void testOperationWhenPrincipalIsNull() throws JspException { - SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken(null, "koala", - AuthorityUtils.NO_AUTHORITIES)); + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken(null, "koala", AuthorityUtils.NO_AUTHORITIES)); authenticationTag.setProperty("principal"); assertThat(authenticationTag.doStartTag()).isEqualTo(Tag.SKIP_BODY); @@ -127,8 +127,7 @@ public class AuthenticationTagTests { @Test public void htmlEscapingIsUsedByDefault() throws Exception { - SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken("<>& ", "")); + SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("<>& ", "")); authenticationTag.setProperty("name"); authenticationTag.doStartTag(); authenticationTag.doEndTag(); @@ -137,8 +136,7 @@ public class AuthenticationTagTests { @Test public void settingHtmlEscapeToFalsePreventsEscaping() throws Exception { - SecurityContextHolder.getContext().setAuthentication( - new TestingAuthenticationToken("<>& ", "")); + SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("<>& ", "")); authenticationTag.setProperty("name"); authenticationTag.setHtmlEscape("false"); authenticationTag.doStartTag(); @@ -150,6 +148,7 @@ public class AuthenticationTagTests { // ================================================================================================== private class MyAuthenticationTag extends AuthenticationTag { + String lastMessage = null; public String getLastMessage() { @@ -159,5 +158,7 @@ public class AuthenticationTagTests { protected void writeMessage(String msg) { lastMessage = msg; } + } + } diff --git a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagTests.java b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagTests.java index 25c8e926e3..a5c8fdb5db 100644 --- a/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagTests.java +++ b/taglibs/src/test/java/org/springframework/security/taglibs/authz/AuthorizeTagTests.java @@ -48,15 +48,19 @@ import org.springframework.web.context.support.StaticWebApplicationContext; */ @RunWith(MockitoJUnitRunner.class) public class AuthorizeTagTests { + // ~ Instance fields // ================================================================================================ @Mock private PermissionEvaluator permissionEvaluator; + private JspAuthorizeTag authorizeTag; + private MockHttpServletRequest request = new MockHttpServletRequest(); - private final TestingAuthenticationToken currentUser = new TestingAuthenticationToken( - "abc", "123", "ROLE SUPERVISOR", "ROLE_TELLER"); + + private final TestingAuthenticationToken currentUser = new TestingAuthenticationToken("abc", "123", + "ROLE SUPERVISOR", "ROLE_TELLER"); // ~ Methods // ======================================================================================================== @@ -70,15 +74,12 @@ public class AuthorizeTagTests { .rootBeanDefinition(DefaultWebSecurityExpressionHandler.class); webExpressionHandler.addPropertyValue("permissionEvaluator", permissionEvaluator); - ctx.registerBeanDefinition("expressionHandler", - webExpressionHandler.getBeanDefinition()); + ctx.registerBeanDefinition("expressionHandler", webExpressionHandler.getBeanDefinition()); ctx.registerSingleton("wipe", MockWebInvocationPrivilegeEvaluator.class); MockServletContext servletCtx = new MockServletContext(); - servletCtx.setAttribute( - WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ctx); + servletCtx.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ctx); authorizeTag = new JspAuthorizeTag(); - authorizeTag.setPageContext(new MockPageContext(servletCtx, request, - new MockHttpServletResponse())); + authorizeTag.setPageContext(new MockPageContext(servletCtx, request, new MockHttpServletResponse())); } @After @@ -92,10 +93,8 @@ public class AuthorizeTagTests { public void taglibsDocumentationHasPermissionOr() throws Exception { Object domain = new Object(); request.setAttribute("domain", domain); - authorizeTag - .setAccess("hasPermission(#domain,'read') or hasPermission(#domain,'write')"); - when(permissionEvaluator.hasPermission(eq(currentUser), eq(domain), anyString())) - .thenReturn(true); + authorizeTag.setAccess("hasPermission(#domain,'read') or hasPermission(#domain,'write')"); + when(permissionEvaluator.hasPermission(eq(currentUser), eq(domain), anyString())).thenReturn(true); assertThat(authorizeTag.doStartTag()).isEqualTo(Tag.EVAL_BODY_INCLUDE); } @@ -154,16 +153,16 @@ public class AuthorizeTagTests { assertThat(authorizeTag.doStartTag()).isEqualTo(Tag.SKIP_BODY); } - public static class MockWebInvocationPrivilegeEvaluator implements - WebInvocationPrivilegeEvaluator { + public static class MockWebInvocationPrivilegeEvaluator implements WebInvocationPrivilegeEvaluator { public boolean isAllowed(String uri, Authentication authentication) { return "/allowed".equals(uri); } - public boolean isAllowed(String contextPath, String uri, String method, - Authentication authentication) { + public boolean isAllowed(String contextPath, String uri, String method, Authentication authentication) { return "/allowed".equals(uri) && (method == null || "GET".equals(method)); } + } + } diff --git a/taglibs/src/test/java/org/springframework/security/taglibs/csrf/AbstractCsrfTagTests.java b/taglibs/src/test/java/org/springframework/security/taglibs/csrf/AbstractCsrfTagTests.java index f34050034a..45e5db311a 100644 --- a/taglibs/src/test/java/org/springframework/security/taglibs/csrf/AbstractCsrfTagTests.java +++ b/taglibs/src/test/java/org/springframework/security/taglibs/csrf/AbstractCsrfTagTests.java @@ -37,7 +37,9 @@ import static org.assertj.core.api.Assertions.*; public class AbstractCsrfTagTests { public MockTag tag; + private MockHttpServletRequest request; + private MockHttpServletResponse response; @Before @@ -45,8 +47,7 @@ public class AbstractCsrfTagTests { MockServletContext servletContext = new MockServletContext(); this.request = new MockHttpServletRequest(servletContext); this.response = new MockHttpServletResponse(); - MockPageContext pageContext = new MockPageContext(servletContext, this.request, - this.response); + MockPageContext pageContext = new MockPageContext(servletContext, this.request, this.response); this.tag = new MockTag(); this.tag.setPageContext(pageContext); } @@ -59,15 +60,14 @@ public class AbstractCsrfTagTests { int returned = this.tag.doEndTag(); assertThat(returned).as("The returned value is not correct.").isEqualTo(TagSupport.EVAL_PAGE); - assertThat(this.response.getContentAsString()).withFailMessage("The output value is not correct.").isEqualTo(""); + assertThat(this.response.getContentAsString()).withFailMessage("The output value is not correct.") + .isEqualTo(""); } @Test - public void hasCsrfRendersReturnedValue() throws JspException, - UnsupportedEncodingException { + public void hasCsrfRendersReturnedValue() throws JspException, UnsupportedEncodingException { - CsrfToken token = new DefaultCsrfToken("X-Csrf-Token", "_csrf", - "abc123def456ghi789"); + CsrfToken token = new DefaultCsrfToken("X-Csrf-Token", "_csrf", "abc123def456ghi789"); this.request.setAttribute(CsrfToken.class.getName(), token); this.tag.handleReturn = "fooBarBazQux"; @@ -75,16 +75,15 @@ public class AbstractCsrfTagTests { int returned = this.tag.doEndTag(); assertThat(returned).as("The returned value is not correct.").isEqualTo(TagSupport.EVAL_PAGE); - assertThat(this.response.getContentAsString()).withFailMessage("The output value is not correct.").isEqualTo("fooBarBazQux"); + assertThat(this.response.getContentAsString()).withFailMessage("The output value is not correct.") + .isEqualTo("fooBarBazQux"); assertThat(this.tag.token).as("The token is not correct.").isSameAs(token); } @Test - public void hasCsrfRendersDifferentValue() throws JspException, - UnsupportedEncodingException { + public void hasCsrfRendersDifferentValue() throws JspException, UnsupportedEncodingException { - CsrfToken token = new DefaultCsrfToken("X-Csrf-Token", "_csrf", - "abc123def456ghi789"); + CsrfToken token = new DefaultCsrfToken("X-Csrf-Token", "_csrf", "abc123def456ghi789"); this.request.setAttribute(CsrfToken.class.getName(), token); this.tag.handleReturn = ""; @@ -92,13 +91,15 @@ public class AbstractCsrfTagTests { int returned = this.tag.doEndTag(); assertThat(returned).as("The returned value is not correct.").isEqualTo(TagSupport.EVAL_PAGE); - assertThat(this.response.getContentAsString()).withFailMessage("The output value is not correct.").isEqualTo(""); + assertThat(this.response.getContentAsString()).withFailMessage("The output value is not correct.") + .isEqualTo(""); assertThat(this.tag.token).as("The token is not correct.").isSameAs(token); } private static class MockTag extends AbstractCsrfTag { private CsrfToken token; + private String handleReturn; @Override @@ -106,5 +107,7 @@ public class AbstractCsrfTagTests { this.token = token; return this.handleReturn; } + } + } diff --git a/taglibs/src/test/java/org/springframework/security/taglibs/csrf/CsrfInputTagTests.java b/taglibs/src/test/java/org/springframework/security/taglibs/csrf/CsrfInputTagTests.java index 4f68345705..17b3bdec19 100644 --- a/taglibs/src/test/java/org/springframework/security/taglibs/csrf/CsrfInputTagTests.java +++ b/taglibs/src/test/java/org/springframework/security/taglibs/csrf/CsrfInputTagTests.java @@ -36,24 +36,24 @@ public class CsrfInputTagTests { @Test public void handleTokenReturnsHiddenInput() { - CsrfToken token = new DefaultCsrfToken("X-Csrf-Token", "_csrf", - "abc123def456ghi789"); + CsrfToken token = new DefaultCsrfToken("X-Csrf-Token", "_csrf", "abc123def456ghi789"); String value = this.tag.handleToken(token); assertThat(value).as("The returned value should not be null.").isNotNull(); - assertThat( - value).withFailMessage("The output is not correct.").isEqualTo(""); + assertThat(value).withFailMessage("The output is not correct.") + .isEqualTo(""); } @Test public void handleTokenReturnsHiddenInputDifferentTokenValue() { - CsrfToken token = new DefaultCsrfToken("X-Csrf-Token", "csrfParameter", - "fooBarBazQux"); + CsrfToken token = new DefaultCsrfToken("X-Csrf-Token", "csrfParameter", "fooBarBazQux"); String value = this.tag.handleToken(token); assertThat(value).as("The returned value should not be null.").isNotNull(); - assertThat(value).withFailMessage("The output is not correct.").isEqualTo(""); + assertThat(value).withFailMessage("The output is not correct.") + .isEqualTo(""); } + } diff --git a/taglibs/src/test/java/org/springframework/security/taglibs/csrf/CsrfMetaTagsTagTests.java b/taglibs/src/test/java/org/springframework/security/taglibs/csrf/CsrfMetaTagsTagTests.java index f71f19e9ca..ae3e0b20ed 100644 --- a/taglibs/src/test/java/org/springframework/security/taglibs/csrf/CsrfMetaTagsTagTests.java +++ b/taglibs/src/test/java/org/springframework/security/taglibs/csrf/CsrfMetaTagsTagTests.java @@ -36,27 +36,28 @@ public class CsrfMetaTagsTagTests { @Test public void handleTokenRendersTags() { - CsrfToken token = new DefaultCsrfToken("X-Csrf-Token", "_csrf", - "abc123def456ghi789"); + CsrfToken token = new DefaultCsrfToken("X-Csrf-Token", "_csrf", "abc123def456ghi789"); String value = this.tag.handleToken(token); assertThat(value).as("The returned value should not be null.").isNotNull(); - assertThat(value).withFailMessage("The output is not correct.").isEqualTo("" - + "" - + ""); + assertThat(value).withFailMessage("The output is not correct.") + .isEqualTo("" + + "" + + ""); } @Test public void handleTokenRendersTagsDifferentToken() { - CsrfToken token = new DefaultCsrfToken("csrfHeader", "csrfParameter", - "fooBarBazQux"); + CsrfToken token = new DefaultCsrfToken("csrfHeader", "csrfParameter", "fooBarBazQux"); String value = this.tag.handleToken(token); assertThat(value).as("The returned value should not be null.").isNotNull(); - assertThat(value).withFailMessage("The output is not correct.").isEqualTo("" - + "" - + ""); + assertThat(value).withFailMessage("The output is not correct.") + .isEqualTo("" + + "" + + ""); } + } diff --git a/test/src/main/java/org/springframework/security/test/context/TestSecurityContextHolder.java b/test/src/main/java/org/springframework/security/test/context/TestSecurityContextHolder.java index fc22058465..bb90171497 100644 --- a/test/src/main/java/org/springframework/security/test/context/TestSecurityContextHolder.java +++ b/test/src/main/java/org/springframework/security/test/context/TestSecurityContextHolder.java @@ -46,7 +46,8 @@ import org.springframework.util.Assert; * *
      14. The test is ran. When used with {@link MockMvc} it is typically used with * {@link SecurityMockMvcRequestPostProcessors#testSecurityContext()}. Which ensures the - * {@link SecurityContext} from {@link TestSecurityContextHolder} is properly populated.
      15. + * {@link SecurityContext} from {@link TestSecurityContextHolder} is properly + * populated. *
      16. After the test is executed, the {@link TestSecurityContextHolder} and the * {@link SecurityContextHolder} are cleared out
      17. * @@ -71,7 +72,6 @@ public final class TestSecurityContextHolder { /** * Gets the {@link SecurityContext} from {@link TestSecurityContextHolder}. - * * @return the {@link SecurityContext} from {@link TestSecurityContextHolder}. */ public static SecurityContext getContext() { @@ -97,10 +97,9 @@ public final class TestSecurityContextHolder { } /** - * Creates a new {@link SecurityContext} with the given {@link Authentication}. - * The {@link SecurityContext} is set on {@link TestSecurityContextHolder} and + * Creates a new {@link SecurityContext} with the given {@link Authentication}. The + * {@link SecurityContext} is set on {@link TestSecurityContextHolder} and * {@link SecurityContextHolder}. - * * @param authentication the {@link Authentication} to use * @since 5.1.1 */ @@ -114,7 +113,6 @@ public final class TestSecurityContextHolder { /** * Gets the default {@link SecurityContext} by delegating to the * {@link SecurityContextHolder} - * * @return the default {@link SecurityContext} */ private static SecurityContext getDefaultContext() { @@ -123,4 +121,5 @@ public final class TestSecurityContextHolder { private TestSecurityContextHolder() { } + } diff --git a/test/src/main/java/org/springframework/security/test/context/annotation/SecurityTestExecutionListeners.java b/test/src/main/java/org/springframework/security/test/context/annotation/SecurityTestExecutionListeners.java index 0ae6271523..0d76e26b4c 100644 --- a/test/src/main/java/org/springframework/security/test/context/annotation/SecurityTestExecutionListeners.java +++ b/test/src/main/java/org/springframework/security/test/context/annotation/SecurityTestExecutionListeners.java @@ -28,11 +28,10 @@ import org.springframework.security.test.context.support.WithSecurityContextTest import org.springframework.test.context.TestExecutionListeners; /** - * There are many times a user may want to use Spring Security's test support - * (i.e. WithMockUser) but have no need for any other - * {@link TestExecutionListeners} (i.e. no need to setup an - * {@link ApplicationContext}). This annotation is a meta annotation that only - * enables Spring Security's {@link TestExecutionListeners}. + * There are many times a user may want to use Spring Security's test support (i.e. + * WithMockUser) but have no need for any other {@link TestExecutionListeners} (i.e. no + * need to setup an {@link ApplicationContext}). This annotation is a meta annotation that + * only enables Spring Security's {@link TestExecutionListeners}. * * @author Rob Winch * @since 4.0.2 @@ -43,7 +42,8 @@ import org.springframework.test.context.TestExecutionListeners; @Inherited @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) -@TestExecutionListeners(inheritListeners = false, listeners = {WithSecurityContextTestExecutionListener.class, - ReactorContextTestExecutionListener.class}) +@TestExecutionListeners(inheritListeners = false, + listeners = { WithSecurityContextTestExecutionListener.class, ReactorContextTestExecutionListener.class }) public @interface SecurityTestExecutionListeners { + } diff --git a/test/src/main/java/org/springframework/security/test/context/support/DelegatingTestExecutionListener.java b/test/src/main/java/org/springframework/security/test/context/support/DelegatingTestExecutionListener.java index 3b34dda6bf..170d5f0e5a 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/DelegatingTestExecutionListener.java +++ b/test/src/main/java/org/springframework/security/test/context/support/DelegatingTestExecutionListener.java @@ -25,8 +25,7 @@ import org.springframework.util.Assert; * @author Rob Winch * @since 5.0 */ -class DelegatingTestExecutionListener - extends AbstractTestExecutionListener { +class DelegatingTestExecutionListener extends AbstractTestExecutionListener { private final TestExecutionListener delegate; @@ -69,4 +68,5 @@ class DelegatingTestExecutionListener public void afterTestClass(TestContext testContext) throws Exception { delegate.afterTestClass(testContext); } + } diff --git a/test/src/main/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListener.java b/test/src/main/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListener.java index 0ad8200938..5e1d95cc59 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListener.java +++ b/test/src/main/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListener.java @@ -40,10 +40,10 @@ import reactor.util.context.Context; * @see WithSecurityContextTestExecutionListener * @see org.springframework.security.test.context.annotation.SecurityTestExecutionListeners */ -public class ReactorContextTestExecutionListener - extends DelegatingTestExecutionListener { +public class ReactorContextTestExecutionListener extends DelegatingTestExecutionListener { private static final String HOOKS_CLASS_NAME = "reactor.core.publisher.Hooks"; + private static final String CONTEXT_OPERATOR_KEY = SecurityContext.class.getName(); public ReactorContextTestExecutionListener() { @@ -51,16 +51,18 @@ public class ReactorContextTestExecutionListener } private static TestExecutionListener createDelegate() { - return ClassUtils.isPresent(HOOKS_CLASS_NAME, ReactorContextTestExecutionListener.class.getClassLoader()) ? - new DelegateTestExecutionListener() : - new AbstractTestExecutionListener() {}; + return ClassUtils.isPresent(HOOKS_CLASS_NAME, ReactorContextTestExecutionListener.class.getClassLoader()) + ? new DelegateTestExecutionListener() : new AbstractTestExecutionListener() { + }; } private static class DelegateTestExecutionListener extends AbstractTestExecutionListener { + @Override public void beforeTestMethod(TestContext testContext) { SecurityContext securityContext = TestSecurityContextHolder.getContext(); - Hooks.onLastOperator(CONTEXT_OPERATOR_KEY, Operators.lift((s, sub) -> new SecuritySubContext<>(sub, securityContext))); + Hooks.onLastOperator(CONTEXT_OPERATOR_KEY, + Operators.lift((s, sub) -> new SecuritySubContext<>(sub, securityContext))); } @Override @@ -69,9 +71,12 @@ public class ReactorContextTestExecutionListener } private static class SecuritySubContext implements CoreSubscriber { - private static String CONTEXT_DEFAULTED_ATTR_NAME = SecuritySubContext.class.getName().concat(".CONTEXT_DEFAULTED_ATTR_NAME"); + + private static String CONTEXT_DEFAULTED_ATTR_NAME = SecuritySubContext.class.getName() + .concat(".CONTEXT_DEFAULTED_ATTR_NAME"); private final CoreSubscriber delegate; + private final SecurityContext securityContext; SecuritySubContext(CoreSubscriber delegate, SecurityContext securityContext) { @@ -90,8 +95,7 @@ public class ReactorContextTestExecutionListener if (authentication == null) { return context; } - Context toMerge = ReactiveSecurityContextHolder.withSecurityContext( - Mono.just(this.securityContext)); + Context toMerge = ReactiveSecurityContextHolder.withSecurityContext(Mono.just(this.securityContext)); return toMerge.putAll(context); } @@ -114,7 +118,9 @@ public class ReactorContextTestExecutionListener public void onComplete() { delegate.onComplete(); } + } + } /** @@ -124,4 +130,5 @@ public class ReactorContextTestExecutionListener public int getOrder() { return 11000; } + } diff --git a/test/src/main/java/org/springframework/security/test/context/support/TestExecutionEvent.java b/test/src/main/java/org/springframework/security/test/context/support/TestExecutionEvent.java index 2051494549..e778c552c4 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/TestExecutionEvent.java +++ b/test/src/main/java/org/springframework/security/test/context/support/TestExecutionEvent.java @@ -19,20 +19,25 @@ package org.springframework.security.test.context.support; import org.springframework.test.context.TestContext; /** - * Represents the events on the methods of {@link org.springframework.test.context.TestExecutionListener} + * Represents the events on the methods of + * {@link org.springframework.test.context.TestExecutionListener} * * @author Rob Winch * @since 5.1 */ public enum TestExecutionEvent { + /** - * Associated to {@link org.springframework.test.context.TestExecutionListener#beforeTestMethod(TestContext)} + * Associated to + * {@link org.springframework.test.context.TestExecutionListener#beforeTestMethod(TestContext)} * event. */ TEST_METHOD, /** - * Associated to {@link org.springframework.test.context.TestExecutionListener#beforeTestExecution(TestContext)} + * Associated to + * {@link org.springframework.test.context.TestExecutionListener#beforeTestExecution(TestContext)} * event. */ TEST_EXECUTION + } diff --git a/test/src/main/java/org/springframework/security/test/context/support/WithAnonymousUser.java b/test/src/main/java/org/springframework/security/test/context/support/WithAnonymousUser.java index 7ce99146e3..a08275bca9 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/WithAnonymousUser.java +++ b/test/src/main/java/org/springframework/security/test/context/support/WithAnonymousUser.java @@ -28,12 +28,12 @@ import org.springframework.security.core.context.SecurityContext; import org.springframework.test.context.TestContext; /** - * When used with {@link WithSecurityContextTestExecutionListener} this - * annotation can be added to a test method to emulate running with an anonymous - * user. The {@link SecurityContext} that is used will contain an - * {@link AnonymousAuthenticationToken}. This is useful when a user wants to run - * a majority of tests as a specific user and wishes to override a few methods - * to be anonymous. For example: + * When used with {@link WithSecurityContextTestExecutionListener} this annotation can be + * added to a test method to emulate running with an anonymous user. The + * {@link SecurityContext} that is used will contain an + * {@link AnonymousAuthenticationToken}. This is useful when a user wants to run a + * majority of tests as a specific user and wishes to override a few methods to be + * anonymous. For example: * *
          * 
        @@ -47,8 +47,7 @@ import org.springframework.test.context.TestContext;
          *
          *     // ... lots of tests ran with a default user ...
          * }
        - * 
        - * 
        + * * * @author Rob Winch * @since 4.1 @@ -69,4 +68,5 @@ public @interface WithAnonymousUser { */ @AliasFor(annotation = WithSecurityContext.class) TestExecutionEvent setupBefore() default TestExecutionEvent.TEST_METHOD; + } diff --git a/test/src/main/java/org/springframework/security/test/context/support/WithAnonymousUserSecurityContextFactory.java b/test/src/main/java/org/springframework/security/test/context/support/WithAnonymousUserSecurityContextFactory.java index 8d7cf4a043..11409e1d8b 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/WithAnonymousUserSecurityContextFactory.java +++ b/test/src/main/java/org/springframework/security/test/context/support/WithAnonymousUserSecurityContextFactory.java @@ -25,17 +25,15 @@ import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; /** - * A {@link WithAnonymousUserSecurityContextFactory} that runs with an {@link AnonymousAuthenticationToken}. - * . + * A {@link WithAnonymousUserSecurityContextFactory} that runs with an + * {@link AnonymousAuthenticationToken}. . * * @see WithUserDetails - * * @author Rob Winch * @since 4.1 */ -final class WithAnonymousUserSecurityContextFactory implements - WithSecurityContextFactory { +final class WithAnonymousUserSecurityContextFactory implements WithSecurityContextFactory { public SecurityContext createSecurityContext(WithAnonymousUser withUser) { List authorities = AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"); @@ -44,4 +42,5 @@ final class WithAnonymousUserSecurityContextFactory implements context.setAuthentication(authentication); return context; } + } \ No newline at end of file diff --git a/test/src/main/java/org/springframework/security/test/context/support/WithMockUser.java b/test/src/main/java/org/springframework/security/test/context/support/WithMockUser.java index d7500ffcb3..23a2e2204c 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/WithMockUser.java +++ b/test/src/main/java/org/springframework/security/test/context/support/WithMockUser.java @@ -56,6 +56,7 @@ import org.springframework.test.web.servlet.MockMvc; @Documented @WithSecurityContext(factory = WithMockUserSecurityContextFactory.class) public @interface WithMockUser { + /** * Convenience mechanism for specifying the username. The default is "user". If * {@link #username()} is specified it will be used instead of {@link #value()} @@ -78,9 +79,9 @@ public @interface WithMockUser { * with "ROLE_". For example, the default will result in "ROLE_USER" being used. *

        *

        - * If {@link #authorities()} is specified this property cannot be changed from the default. + * If {@link #authorities()} is specified this property cannot be changed from the + * default. *

        - * * @return */ String[] roles() default { "USER" }; @@ -94,7 +95,6 @@ public @interface WithMockUser { * If this property is specified then {@link #roles()} is not used. This differs from * {@link #roles()} in that it does not prefix the values passed in automatically. *

        - * * @return */ String[] authorities() default {}; @@ -114,4 +114,5 @@ public @interface WithMockUser { */ @AliasFor(annotation = WithSecurityContext.class) TestExecutionEvent setupBefore() default TestExecutionEvent.TEST_METHOD; + } diff --git a/test/src/main/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactory.java b/test/src/main/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactory.java index d2cc86d966..5de64847e2 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactory.java +++ b/test/src/main/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactory.java @@ -35,15 +35,13 @@ import org.springframework.util.StringUtils; * @since 4.0 * @see WithMockUser */ -final class WithMockUserSecurityContextFactory implements - WithSecurityContextFactory { +final class WithMockUserSecurityContextFactory implements WithSecurityContextFactory { public SecurityContext createSecurityContext(WithMockUser withUser) { - String username = StringUtils.hasLength(withUser.username()) ? withUser - .username() : withUser.value(); + String username = StringUtils.hasLength(withUser.username()) ? withUser.username() : withUser.value(); if (username == null) { - throw new IllegalArgumentException(withUser - + " cannot have null username on both username and value properties"); + throw new IllegalArgumentException( + withUser + " cannot have null username on both username and value properties"); } List grantedAuthorities = new ArrayList<>(); @@ -54,21 +52,22 @@ final class WithMockUserSecurityContextFactory implements if (grantedAuthorities.isEmpty()) { for (String role : withUser.roles()) { if (role.startsWith("ROLE_")) { - throw new IllegalArgumentException("roles cannot start with ROLE_ Got " - + role); + throw new IllegalArgumentException("roles cannot start with ROLE_ Got " + role); } grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_" + role)); } - } else if (!(withUser.roles().length == 1 && "USER".equals(withUser.roles()[0]))) { - throw new IllegalStateException("You cannot define roles attribute "+ Arrays.asList(withUser.roles())+" with authorities attribute "+ Arrays.asList(withUser.authorities())); + } + else if (!(withUser.roles().length == 1 && "USER".equals(withUser.roles()[0]))) { + throw new IllegalStateException("You cannot define roles attribute " + Arrays.asList(withUser.roles()) + + " with authorities attribute " + Arrays.asList(withUser.authorities())); } - User principal = new User(username, withUser.password(), true, true, true, true, - grantedAuthorities); - Authentication authentication = new UsernamePasswordAuthenticationToken( - principal, principal.getPassword(), principal.getAuthorities()); + User principal = new User(username, withUser.password(), true, true, true, true, grantedAuthorities); + Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), + principal.getAuthorities()); SecurityContext context = SecurityContextHolder.createEmptyContext(); context.setAuthentication(authentication); return context; } + } diff --git a/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContext.java b/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContext.java index 5f401eecf8..a97bb44794 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContext.java +++ b/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContext.java @@ -54,11 +54,11 @@ import org.springframework.test.context.TestContext; @Inherited @Documented public @interface WithSecurityContext { + /** * The {@link WithUserDetailsSecurityContextFactory} to use to create the * {@link SecurityContext}. It can contain {@link Autowired} and other Spring * annotations. - * * @return */ Class> factory(); diff --git a/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContextFactory.java b/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContextFactory.java index e99060b5e7..c00e589fab 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContextFactory.java +++ b/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContextFactory.java @@ -25,7 +25,6 @@ import org.springframework.security.test.context.TestSecurityContextHolder; * {@link SecurityContext} that is populated in the {@link TestSecurityContextHolder}. * * @author Rob Winch - * * @param * @see WithSecurityContext * @see WithMockUser @@ -36,10 +35,10 @@ public interface WithSecurityContextFactory { /** * Create a {@link SecurityContext} given an Annotation. - * * @param annotation the {@link Annotation} to create the {@link SecurityContext} * from. Cannot be null. * @return the {@link SecurityContext} to use. Cannot be null. */ SecurityContext createSecurityContext(A annotation); + } \ No newline at end of file diff --git a/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContextTestExecutionListener.java b/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContextTestExecutionListener.java index 0d7321a9f0..c62ac3412f 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContextTestExecutionListener.java +++ b/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContextTestExecutionListener.java @@ -47,10 +47,10 @@ import org.springframework.test.web.servlet.MockMvc; * @see ReactorContextTestExecutionListener * @see org.springframework.security.test.context.annotation.SecurityTestExecutionListeners */ -public class WithSecurityContextTestExecutionListener - extends AbstractTestExecutionListener { +public class WithSecurityContextTestExecutionListener extends AbstractTestExecutionListener { - static final String SECURITY_CONTEXT_ATTR_NAME = WithSecurityContextTestExecutionListener.class.getName().concat(".SECURITY_CONTEXT"); + static final String SECURITY_CONTEXT_ATTR_NAME = WithSecurityContextTestExecutionListener.class.getName() + .concat(".SECURITY_CONTEXT"); /** * Sets up the {@link SecurityContext} for each test method. First the specific method @@ -60,21 +60,19 @@ public class WithSecurityContextTestExecutionListener */ @Override public void beforeTestMethod(TestContext testContext) { - TestSecurityContext testSecurityContext = createTestSecurityContext( - testContext.getTestMethod(), testContext); + TestSecurityContext testSecurityContext = createTestSecurityContext(testContext.getTestMethod(), testContext); if (testSecurityContext == null) { - testSecurityContext = createTestSecurityContext(testContext.getTestClass(), - testContext); + testSecurityContext = createTestSecurityContext(testContext.getTestClass(), testContext); } if (testSecurityContext == null) { return; } - Supplier supplier = testSecurityContext - .getSecurityContextSupplier(); + Supplier supplier = testSecurityContext.getSecurityContextSupplier(); if (testSecurityContext.getTestExecutionEvent() == TestExecutionEvent.TEST_METHOD) { TestSecurityContextHolder.setContext(supplier.get()); - } else { + } + else { testContext.setAttribute(SECURITY_CONTEXT_ATTR_NAME, supplier); } } @@ -92,19 +90,17 @@ public class WithSecurityContextTestExecutionListener } } - private TestSecurityContext createTestSecurityContext(AnnotatedElement annotated, - TestContext context) { - WithSecurityContext withSecurityContext = AnnotatedElementUtils - .findMergedAnnotation(annotated, WithSecurityContext.class); + private TestSecurityContext createTestSecurityContext(AnnotatedElement annotated, TestContext context) { + WithSecurityContext withSecurityContext = AnnotatedElementUtils.findMergedAnnotation(annotated, + WithSecurityContext.class); return createTestSecurityContext(annotated, withSecurityContext, context); } - private TestSecurityContext createTestSecurityContext(Class annotated, - TestContext context) { + private TestSecurityContext createTestSecurityContext(Class annotated, TestContext context) { MetaAnnotationUtils.AnnotationDescriptor withSecurityContextDescriptor = MetaAnnotationUtils .findAnnotationDescriptor(annotated, WithSecurityContext.class); - WithSecurityContext withSecurityContext = withSecurityContextDescriptor == null - ? null : withSecurityContextDescriptor.getAnnotation(); + WithSecurityContext withSecurityContext = withSecurityContextDescriptor == null ? null + : withSecurityContextDescriptor.getAnnotation(); return createTestSecurityContext(annotated, withSecurityContext, context); } @@ -114,35 +110,32 @@ public class WithSecurityContextTestExecutionListener if (withSecurityContext == null) { return null; } - withSecurityContext = AnnotationUtils - .synthesizeAnnotation(withSecurityContext, annotated); + withSecurityContext = AnnotationUtils.synthesizeAnnotation(withSecurityContext, annotated); WithSecurityContextFactory factory = createFactory(withSecurityContext, context); Class type = (Class) GenericTypeResolver - .resolveTypeArgument(factory.getClass(), - WithSecurityContextFactory.class); + .resolveTypeArgument(factory.getClass(), WithSecurityContextFactory.class); Annotation annotation = findAnnotation(annotated, type); Supplier supplier = () -> { try { return factory.createSecurityContext(annotation); - } catch (RuntimeException e) { - throw new IllegalStateException( - "Unable to create SecurityContext using " + annotation, e); + } + catch (RuntimeException e) { + throw new IllegalStateException("Unable to create SecurityContext using " + annotation, e); } }; TestExecutionEvent initialize = withSecurityContext.setupBefore(); return new TestSecurityContext(supplier, initialize); } - private Annotation findAnnotation(AnnotatedElement annotated, - Class type) { + private Annotation findAnnotation(AnnotatedElement annotated, Class type) { Annotation findAnnotation = AnnotationUtils.findAnnotation(annotated, type); if (findAnnotation != null) { return findAnnotation; } Annotation[] allAnnotations = AnnotationUtils.getAnnotations(annotated); for (Annotation annotationToTest : allAnnotations) { - WithSecurityContext withSecurityContext = AnnotationUtils.findAnnotation( - annotationToTest.annotationType(), WithSecurityContext.class); + WithSecurityContext withSecurityContext = AnnotationUtils.findAnnotation(annotationToTest.annotationType(), + WithSecurityContext.class); if (withSecurityContext != null) { return annotationToTest; } @@ -150,13 +143,11 @@ public class WithSecurityContextTestExecutionListener return null; } - private WithSecurityContextFactory createFactory( - WithSecurityContext withSecurityContext, TestContext testContext) { - Class> clazz = withSecurityContext - .factory(); + private WithSecurityContextFactory createFactory(WithSecurityContext withSecurityContext, + TestContext testContext) { + Class> clazz = withSecurityContext.factory(); try { - return testContext.getApplicationContext().getAutowireCapableBeanFactory() - .createBean(clazz); + return testContext.getApplicationContext().getAutowireCapableBeanFactory().createBean(clazz); } catch (IllegalStateException e) { return BeanUtils.instantiateClass(clazz); @@ -184,11 +175,12 @@ public class WithSecurityContextTestExecutionListener } static class TestSecurityContext { + private final Supplier securityContextSupplier; + private final TestExecutionEvent testExecutionEvent; - TestSecurityContext(Supplier securityContextSupplier, - TestExecutionEvent testExecutionEvent) { + TestSecurityContext(Supplier securityContextSupplier, TestExecutionEvent testExecutionEvent) { this.securityContextSupplier = securityContextSupplier; this.testExecutionEvent = testExecutionEvent; } @@ -200,5 +192,7 @@ public class WithSecurityContextTestExecutionListener public TestExecutionEvent getTestExecutionEvent() { return this.testExecutionEvent; } + } + } diff --git a/test/src/main/java/org/springframework/security/test/context/support/WithUserDetails.java b/test/src/main/java/org/springframework/security/test/context/support/WithUserDetails.java index 453539946c..ac2fee5b00 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/WithUserDetails.java +++ b/test/src/main/java/org/springframework/security/test/context/support/WithUserDetails.java @@ -55,18 +55,17 @@ import org.springframework.test.web.servlet.MockMvc; @Documented @WithSecurityContext(factory = WithUserDetailsSecurityContextFactory.class) public @interface WithUserDetails { + /** * The username to look up in the {@link UserDetailsService} - * * @return */ String value() default "user"; /** - * The bean name for the {@link UserDetailsService} to use. If this is not - * provided, then the lookup is done by type and expects only a single + * The bean name for the {@link UserDetailsService} to use. If this is not provided, + * then the lookup is done by type and expects only a single * {@link UserDetailsService} bean to be exposed. - * * @return the bean name for the {@link UserDetailsService} to use. * @since 4.1 */ @@ -81,4 +80,5 @@ public @interface WithUserDetails { */ @AliasFor(annotation = WithSecurityContext.class) TestExecutionEvent setupBefore() default TestExecutionEvent.TEST_METHOD; + } diff --git a/test/src/main/java/org/springframework/security/test/context/support/WithUserDetailsSecurityContextFactory.java b/test/src/main/java/org/springframework/security/test/context/support/WithUserDetailsSecurityContextFactory.java index caa8dc6351..0bb706ddfb 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/WithUserDetailsSecurityContextFactory.java +++ b/test/src/main/java/org/springframework/security/test/context/support/WithUserDetailsSecurityContextFactory.java @@ -36,15 +36,14 @@ import org.springframework.util.StringUtils; * . * * @see WithUserDetails - * * @author Rob Winch * @since 4.0 */ -final class WithUserDetailsSecurityContextFactory implements - WithSecurityContextFactory { +final class WithUserDetailsSecurityContextFactory implements WithSecurityContextFactory { - private static final boolean reactorPresent = ClassUtils.isPresent("reactor.core.publisher.Mono", WithUserDetailsSecurityContextFactory.class.getClassLoader()); + private static final boolean reactorPresent = ClassUtils.isPresent("reactor.core.publisher.Mono", + WithUserDetailsSecurityContextFactory.class.getClassLoader()); private BeanFactory beans; @@ -59,8 +58,8 @@ final class WithUserDetailsSecurityContextFactory implements String username = withUser.value(); Assert.hasLength(username, "value() must be non empty String"); UserDetails principal = userDetailsService.loadUserByUsername(username); - Authentication authentication = new UsernamePasswordAuthenticationToken( - principal, principal.getPassword(), principal.getAuthorities()); + Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), + principal.getAuthorities()); SecurityContext context = SecurityContextHolder.createEmptyContext(); context.setAuthentication(authentication); return context; @@ -73,35 +72,35 @@ final class WithUserDetailsSecurityContextFactory implements return reactive; } } - return StringUtils.hasLength(beanName) - ? this.beans.getBean(beanName, UserDetailsService.class) - : this.beans.getBean(UserDetailsService.class); + return StringUtils.hasLength(beanName) ? this.beans.getBean(beanName, UserDetailsService.class) + : this.beans.getBean(UserDetailsService.class); } public UserDetailsService findAndAdaptReactiveUserDetailsService(String beanName) { try { - ReactiveUserDetailsService reactiveUserDetailsService = StringUtils - .hasLength(beanName) ? - this.beans.getBean(beanName, ReactiveUserDetailsService.class) : - this.beans.getBean(ReactiveUserDetailsService.class); + ReactiveUserDetailsService reactiveUserDetailsService = StringUtils.hasLength(beanName) + ? this.beans.getBean(beanName, ReactiveUserDetailsService.class) + : this.beans.getBean(ReactiveUserDetailsService.class); return new ReactiveUserDetailsServiceAdapter(reactiveUserDetailsService); - } catch(NoSuchBeanDefinitionException | BeanNotOfRequiredTypeException notReactive) { + } + catch (NoSuchBeanDefinitionException | BeanNotOfRequiredTypeException notReactive) { return null; } } private class ReactiveUserDetailsServiceAdapter implements UserDetailsService { + private final ReactiveUserDetailsService userDetailsService; - private ReactiveUserDetailsServiceAdapter( - ReactiveUserDetailsService userDetailsService) { + private ReactiveUserDetailsServiceAdapter(ReactiveUserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } @Override - public UserDetails loadUserByUsername(String username) - throws UsernameNotFoundException { + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { return this.userDetailsService.findByUsername(username).block(); } + } + } diff --git a/test/src/main/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurers.java b/test/src/main/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurers.java index 997f41eb23..153e4692cd 100644 --- a/test/src/main/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurers.java +++ b/test/src/main/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurers.java @@ -108,49 +108,46 @@ public class SecurityMockServerConfigurers { public static MockServerConfigurer springSecurity() { return new MockServerConfigurer() { public void beforeServerCreated(WebHttpHandlerBuilder builder) { - builder.filters( filters -> filters.add(0, new MutatorFilter())); + builder.filters(filters -> filters.add(0, new MutatorFilter())); } }; } /** * Updates the ServerWebExchange to use the provided Authentication as the Principal - * * @param authentication the Authentication to use. * @return the configurer to use */ - public static T mockAuthentication(Authentication authentication) { + public static T mockAuthentication( + Authentication authentication) { return (T) new MutatorWebTestClientConfigurer(() -> Mono.just(authentication).map(SecurityContextImpl::new)); } /** - * Updates the ServerWebExchange to use the provided UserDetails to create a UsernamePasswordAuthenticationToken as - * the Principal - * + * Updates the ServerWebExchange to use the provided UserDetails to create a + * UsernamePasswordAuthenticationToken as the Principal * @param userDetails the UserDetails to use. * @return the configurer to use */ public static T mockUser(UserDetails userDetails) { - return mockAuthentication(new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities())); + return mockAuthentication(new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), + userDetails.getAuthorities())); } /** - * Updates the ServerWebExchange to use a UserDetails to create a UsernamePasswordAuthenticationToken as - * the Principal. This uses a default username of "user", password of "password", and granted authorities of - * "ROLE_USER". - * + * Updates the ServerWebExchange to use a UserDetails to create a + * UsernamePasswordAuthenticationToken as the Principal. This uses a default username + * of "user", password of "password", and granted authorities of "ROLE_USER". * @return the {@link UserExchangeMutator} to use */ public static UserExchangeMutator mockUser() { return mockUser("user"); } - /** - * Updates the ServerWebExchange to use a UserDetails to create a UsernamePasswordAuthenticationToken as - * the Principal. This uses a default password of "password" and granted authorities of - * "ROLE_USER". - * + * Updates the ServerWebExchange to use a UserDetails to create a + * UsernamePasswordAuthenticationToken as the Principal. This uses a default password + * of "password" and granted authorities of "ROLE_USER". * @return the {@link WebTestClientConfigurer} to use */ public static UserExchangeMutator mockUser(String username) { @@ -159,11 +156,9 @@ public class SecurityMockServerConfigurers { /** * Updates the ServerWebExchange to establish a {@link SecurityContext} that has a - * {@link JwtAuthenticationToken} for the - * {@link Authentication} and a {@link Jwt} for the - * {@link Authentication#getPrincipal()}. All details are - * declarative and do not require the JWT to be valid. - * + * {@link JwtAuthenticationToken} for the {@link Authentication} and a {@link Jwt} for + * the {@link Authentication#getPrincipal()}. All details are declarative and do not + * require the JWT to be valid. * @return the {@link JwtMutator} to further configure or use * @since 5.2 */ @@ -173,11 +168,9 @@ public class SecurityMockServerConfigurers { /** * Updates the ServerWebExchange to establish a {@link SecurityContext} that has a - * {@link BearerTokenAuthentication} for the - * {@link Authentication} and an {@link OAuth2AuthenticatedPrincipal} for the - * {@link Authentication#getPrincipal()}. All details are - * declarative and do not require the token to be valid. - * + * {@link BearerTokenAuthentication} for the {@link Authentication} and an + * {@link OAuth2AuthenticatedPrincipal} for the {@link Authentication#getPrincipal()}. + * All details are declarative and do not require the token to be valid. * @return the {@link OpaqueTokenMutator} to further configure or use * @since 5.3 */ @@ -187,43 +180,39 @@ public class SecurityMockServerConfigurers { /** * Updates the ServerWebExchange to establish a {@link SecurityContext} that has a - * {@link OAuth2AuthenticationToken} for the - * {@link Authentication}. All details are + * {@link OAuth2AuthenticationToken} for the {@link Authentication}. All details are * declarative and do not require the corresponding OAuth 2.0 tokens to be valid. - * * @return the {@link OAuth2LoginMutator} to further configure or use * @since 5.3 */ public static OAuth2LoginMutator mockOAuth2Login() { - OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", - null, null, Collections.singleton("read")); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", null, + null, Collections.singleton("read")); return new OAuth2LoginMutator(accessToken); } /** * Updates the ServerWebExchange to establish a {@link SecurityContext} that has a - * {@link OAuth2AuthenticationToken} for the - * {@link Authentication}. All details are + * {@link OAuth2AuthenticationToken} for the {@link Authentication}. All details are * declarative and do not require the corresponding OAuth 2.0 tokens to be valid. - * * @return the {@link OidcLoginMutator} to further configure or use * @since 5.3 */ public static OidcLoginMutator mockOidcLogin() { - OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", - null, null, Collections.singleton("read")); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", null, + null, Collections.singleton("read")); return new OidcLoginMutator(accessToken); } /** - * Updates the ServerWebExchange to establish a {@link OAuth2AuthorizedClient} in the session. - * All details are declarative and do not require the corresponding OAuth 2.0 tokens to be valid. + * Updates the ServerWebExchange to establish a {@link OAuth2AuthorizedClient} in the + * session. All details are declarative and do not require the corresponding OAuth 2.0 + * tokens to be valid. * *

        - * The support works by associating the authorized client to the ServerWebExchange - * via the {@link WebSessionServerOAuth2AuthorizedClientRepository} + * The support works by associating the authorized client to the ServerWebExchange via + * the {@link WebSessionServerOAuth2AuthorizedClientRepository} *

        - * * @return the {@link OAuth2ClientMutator} to further configure or use * @since 5.3 */ @@ -232,15 +221,16 @@ public class SecurityMockServerConfigurers { } /** - * Updates the ServerWebExchange to establish a {@link OAuth2AuthorizedClient} in the session. - * All details are declarative and do not require the corresponding OAuth 2.0 tokens to be valid. + * Updates the ServerWebExchange to establish a {@link OAuth2AuthorizedClient} in the + * session. All details are declarative and do not require the corresponding OAuth 2.0 + * tokens to be valid. * *

        - * The support works by associating the authorized client to the ServerWebExchange - * via the {@link WebSessionServerOAuth2AuthorizedClientRepository} + * The support works by associating the authorized client to the ServerWebExchange via + * the {@link WebSessionServerOAuth2AuthorizedClientRepository} *

        - * - * @param registrationId The registration id associated with the {@link OAuth2AuthorizedClient} + * @param registrationId The registration id associated with the + * {@link OAuth2AuthorizedClient} * @return the {@link OAuth2ClientMutator} to further configure or use * @since 5.3 */ @@ -256,16 +246,14 @@ public class SecurityMockServerConfigurers { @Override public void afterConfigurerAdded(WebTestClient.Builder builder, - @Nullable WebHttpHandlerBuilder httpHandlerBuilder, - @Nullable ClientHttpConnector connector) { + @Nullable WebHttpHandlerBuilder httpHandlerBuilder, @Nullable ClientHttpConnector connector) { CsrfWebFilter filter = new CsrfWebFilter(); - filter.setRequireCsrfProtectionMatcher( e -> ServerWebExchangeMatcher.MatchResult.notMatch()); - httpHandlerBuilder.filters( filters -> filters.add(0, filter)); + filter.setRequireCsrfProtectionMatcher(e -> ServerWebExchangeMatcher.MatchResult.notMatch()); + httpHandlerBuilder.filters(filters -> filters.add(0, filter)); } @Override - public void afterConfigureAdded( - WebTestClient.MockServerSpec serverSpec) { + public void afterConfigureAdded(WebTestClient.MockServerSpec serverSpec) { } @@ -274,14 +262,18 @@ public class SecurityMockServerConfigurers { } - private CsrfMutator() {} + private CsrfMutator() { + } + } /** - * Updates the WebServerExchange using {@code {@link SecurityMockServerConfigurers#mockUser(UserDetails)}}. Defaults to use a - * password of "password" and granted authorities of "ROLE_USER". + * Updates the WebServerExchange using {@code {@link + * SecurityMockServerConfigurers#mockUser(UserDetails)}}. Defaults to use a password + * of "password" and granted authorities of "ROLE_USER". */ public static class UserExchangeMutator implements WebTestClientConfigurer, MockServerConfigurer { + private final User.UserBuilder userBuilder; private UserExchangeMutator(String username) { @@ -301,9 +293,8 @@ public class SecurityMockServerConfigurers { } /** - * Specifies the roles to use. Default is "USER". This is similar to authorities except each role is - * automatically prefixed with "ROLE_USER". - * + * Specifies the roles to use. Default is "USER". This is similar to authorities + * except each role is automatically prefixed with "ROLE_USER". * @param roles the roles to use. * @return the UserExchangeMutator */ @@ -314,7 +305,6 @@ public class SecurityMockServerConfigurers { /** * Specifies the {@code GrantedAuthority}s to use. Default is "ROLE_USER". - * * @param authorities the authorities to use. * @return the UserExchangeMutator */ @@ -325,7 +315,6 @@ public class SecurityMockServerConfigurers { /** * Specifies the {@code GrantedAuthority}s to use. Default is "ROLE_USER". - * * @param authorities the authorities to use. * @return the UserExchangeMutator */ @@ -375,37 +364,46 @@ public class SecurityMockServerConfigurers { } @Override - public void afterConfigurerAdded(WebTestClient.Builder builder, @Nullable WebHttpHandlerBuilder webHttpHandlerBuilder, @Nullable ClientHttpConnector clientHttpConnector) { + public void afterConfigurerAdded(WebTestClient.Builder builder, + @Nullable WebHttpHandlerBuilder webHttpHandlerBuilder, + @Nullable ClientHttpConnector clientHttpConnector) { configurer().afterConfigurerAdded(builder, webHttpHandlerBuilder, clientHttpConnector); } private T configurer() { return mockUser(this.userBuilder.build()); } + } private static class MutatorWebTestClientConfigurer implements WebTestClientConfigurer, MockServerConfigurer { + private final Supplier> context; private MutatorWebTestClientConfigurer(Supplier> context) { this.context = context; } + @Override public void beforeServerCreated(WebHttpHandlerBuilder builder) { builder.filters(addSetupMutatorFilter()); } @Override - public void afterConfigurerAdded(WebTestClient.Builder builder, @Nullable WebHttpHandlerBuilder webHttpHandlerBuilder, @Nullable ClientHttpConnector clientHttpConnector) { + public void afterConfigurerAdded(WebTestClient.Builder builder, + @Nullable WebHttpHandlerBuilder webHttpHandlerBuilder, + @Nullable ClientHttpConnector clientHttpConnector) { webHttpHandlerBuilder.filters(addSetupMutatorFilter()); } private Consumer> addSetupMutatorFilter() { return filters -> filters.add(0, new SetupMutatorFilter(this.context)); } + } private static class SetupMutatorFilter implements WebFilter { + private final Supplier> context; private SetupMutatorFilter(Supplier> context) { @@ -417,9 +415,11 @@ public class SecurityMockServerConfigurers { exchange.getAttributes().computeIfAbsent(MutatorFilter.ATTRIBUTE_NAME, key -> this.context); return webFilterChain.filter(exchange); } + } private static class MutatorFilter implements WebFilter { + public static final String ATTRIBUTE_NAME = "context"; @Override @@ -428,47 +428,48 @@ public class SecurityMockServerConfigurers { if (context != null) { exchange.getAttributes().remove(ATTRIBUTE_NAME); return webFilterChain.filter(exchange) - .subscriberContext(ReactiveSecurityContextHolder.withSecurityContext(context.get())); + .subscriberContext(ReactiveSecurityContextHolder.withSecurityContext(context.get())); } return webFilterChain.filter(exchange); } + } /** - * Updates the WebServerExchange using - * {@code {@link SecurityMockServerConfigurers#mockAuthentication(Authentication)}}. + * Updates the WebServerExchange using {@code {@link + * SecurityMockServerConfigurers#mockAuthentication(Authentication)}}. * * @author Jérôme Wacongne <ch4mp@c4-soft.com> * @author Josh Cummings * @since 5.2 */ public static class JwtMutator implements WebTestClientConfigurer, MockServerConfigurer { + private Jwt jwt; - private Converter> authoritiesConverter = - new JwtGrantedAuthoritiesConverter(); + + private Converter> authoritiesConverter = new JwtGrantedAuthoritiesConverter(); private JwtMutator() { - jwt((jwt) -> {}); + jwt((jwt) -> { + }); } /** - * Use the given {@link Jwt.Builder} {@link Consumer} to configure the underlying {@link Jwt} + * Use the given {@link Jwt.Builder} {@link Consumer} to configure the underlying + * {@link Jwt} * - * This method first creates a default {@link Jwt.Builder} instance with default values for - * the {@code alg}, {@code sub}, and {@code scope} claims. The {@link Consumer} can then modify - * these or provide additional configuration. - * - * Calling {@link SecurityMockServerConfigurers#mockJwt()} is the equivalent of calling - * {@code SecurityMockMvcRequestPostProcessors.mockJwt().jwt(() -> {})}. + * This method first creates a default {@link Jwt.Builder} instance with default + * values for the {@code alg}, {@code sub}, and {@code scope} claims. The + * {@link Consumer} can then modify these or provide additional configuration. * + * Calling {@link SecurityMockServerConfigurers#mockJwt()} is the equivalent of + * calling {@code SecurityMockMvcRequestPostProcessors.mockJwt().jwt(() -> {})}. * @param jwtBuilderConsumer For configuring the underlying {@link Jwt} * @return the {@link JwtMutator} for further configuration */ public JwtMutator jwt(Consumer jwtBuilderConsumer) { - Jwt.Builder jwtBuilder = Jwt.withTokenValue("token") - .header("alg", "none") - .claim(SUB, "user") - .claim("scope", "read"); + Jwt.Builder jwtBuilder = Jwt.withTokenValue("token").header("alg", "none").claim(SUB, "user").claim("scope", + "read"); jwtBuilderConsumer.accept(jwtBuilder); this.jwt = jwtBuilder.build(); return this; @@ -476,7 +477,6 @@ public class SecurityMockServerConfigurers { /** * Use the given {@link Jwt} - * * @param jwt The {@link Jwt} to use * @return the {@link JwtMutator} for further configuration */ @@ -510,9 +510,8 @@ public class SecurityMockServerConfigurers { /** * Provides the configured {@link Jwt} so that custom authorities can be derived * from it - * - * @param authoritiesConverter the conversion strategy from {@link Jwt} to a {@link Collection} - * of {@link GrantedAuthority}s + * @param authoritiesConverter the conversion strategy from {@link Jwt} to a + * {@link Collection} of {@link GrantedAuthority}s * @return the {@link JwtMutator} for further configuration */ public JwtMutator authorities(Converter> authoritiesConverter) { @@ -532,10 +531,8 @@ public class SecurityMockServerConfigurers { } @Override - public void afterConfigurerAdded( - WebTestClient.Builder builder, - @Nullable WebHttpHandlerBuilder httpHandlerBuilder, - @Nullable ClientHttpConnector connector) { + public void afterConfigurerAdded(WebTestClient.Builder builder, + @Nullable WebHttpHandlerBuilder httpHandlerBuilder, @Nullable ClientHttpConnector connector) { httpHandlerBuilder.filter((exchange, chain) -> { CsrfWebFilter.skipExchange(exchange); return chain.filter(exchange); @@ -544,8 +541,10 @@ public class SecurityMockServerConfigurers { } private T configurer() { - return mockAuthentication(new JwtAuthenticationToken(this.jwt, this.authoritiesConverter.convert(this.jwt))); + return mockAuthentication( + new JwtAuthenticationToken(this.jwt, this.authoritiesConverter.convert(this.jwt))); } + } /** @@ -553,17 +552,20 @@ public class SecurityMockServerConfigurers { * @since 5.3 */ public final static class OpaqueTokenMutator implements WebTestClientConfigurer, MockServerConfigurer { + private Supplier> attributes = this::defaultAttributes; + private Supplier> authorities = this::defaultAuthorities; private Supplier principal = this::defaultPrincipal; - private OpaqueTokenMutator() { } + private OpaqueTokenMutator() { + } /** * Mutate the attributes using the given {@link Consumer} - * - * @param attributesConsumer The {@link Consumer} for mutating the {@Map} of attributes + * @param attributesConsumer The {@link Consumer} for mutating the {@Map} of + * attributes * @return the {@link OpaqueTokenMutator} for further configuration */ public OpaqueTokenMutator attributes(Consumer> attributesConsumer) { @@ -623,10 +625,8 @@ public class SecurityMockServerConfigurers { } @Override - public void afterConfigurerAdded( - WebTestClient.Builder builder, - @Nullable WebHttpHandlerBuilder httpHandlerBuilder, - @Nullable ClientHttpConnector connector) { + public void afterConfigurerAdded(WebTestClient.Builder builder, + @Nullable WebHttpHandlerBuilder httpHandlerBuilder, @Nullable ClientHttpConnector connector) { httpHandlerBuilder.filter((exchange, chain) -> { CsrfWebFilter.skipExchange(exchange); return chain.filter(exchange); @@ -637,8 +637,8 @@ public class SecurityMockServerConfigurers { private T configurer() { OAuth2AuthenticatedPrincipal principal = this.principal.get(); OAuth2AccessToken accessToken = getOAuth2AccessToken(principal); - BearerTokenAuthentication token = new BearerTokenAuthentication - (principal, accessToken, principal.getAuthorities()); + BearerTokenAuthentication token = new BearerTokenAuthentication(principal, accessToken, + principal.getAuthorities()); return mockAuthentication(token); } @@ -666,21 +666,18 @@ public class SecurityMockServerConfigurers { } private OAuth2AuthenticatedPrincipal defaultPrincipal() { - return new OAuth2IntrospectionAuthenticatedPrincipal - (this.attributes.get(), this.authorities.get()); + return new OAuth2IntrospectionAuthenticatedPrincipal(this.attributes.get(), this.authorities.get()); } private Collection getAuthorities(Collection scopes) { - return scopes.stream() - .map(scope -> new SimpleGrantedAuthority("SCOPE_" + scope)) + return scopes.stream().map(scope -> new SimpleGrantedAuthority("SCOPE_" + scope)) .collect(Collectors.toList()); } private OAuth2AccessToken getOAuth2AccessToken(OAuth2AuthenticatedPrincipal principal) { Instant expiresAt = getInstant(principal.getAttributes(), "exp"); Instant issuedAt = getInstant(principal.getAttributes(), "iat"); - return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "token", issuedAt, expiresAt); + return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token", issuedAt, expiresAt); } private Instant getInstant(Map attributes, String name) { @@ -693,6 +690,7 @@ public class SecurityMockServerConfigurers { } throw new IllegalArgumentException(name + " attribute must be of type Instant"); } + } /** @@ -700,17 +698,20 @@ public class SecurityMockServerConfigurers { * @since 5.3 */ public final static class OAuth2LoginMutator implements WebTestClientConfigurer, MockServerConfigurer { + private final String nameAttributeKey = "sub"; private ClientRegistration clientRegistration; + private OAuth2AccessToken accessToken; private Supplier> authorities = this::defaultAuthorities; + private Supplier> attributes = this::defaultAttributes; + private Supplier oauth2User = this::defaultPrincipal; - private final ServerOAuth2AuthorizedClientRepository authorizedClientRepository = - new WebSessionServerOAuth2AuthorizedClientRepository(); + private final ServerOAuth2AuthorizedClientRepository authorizedClientRepository = new WebSessionServerOAuth2AuthorizedClientRepository(); private OAuth2LoginMutator(OAuth2AccessToken accessToken) { this.accessToken = accessToken; @@ -719,7 +720,6 @@ public class SecurityMockServerConfigurers { /** * Use the provided authorities in the {@link Authentication} - * * @param authorities the authorities to use * @return the {@link OAuth2LoginMutator} for further configuration */ @@ -732,7 +732,6 @@ public class SecurityMockServerConfigurers { /** * Use the provided authorities in the {@link Authentication} - * * @param authorities the authorities to use * @return the {@link OAuth2LoginMutator} for further configuration */ @@ -745,8 +744,8 @@ public class SecurityMockServerConfigurers { /** * Mutate the attributes using the given {@link Consumer} - * - * @param attributesConsumer The {@link Consumer} for mutating the {@Map} of attributes + * @param attributesConsumer The {@link Consumer} for mutating the {@Map} of + * attributes * @return the {@link OAuth2LoginMutator} for further configuration */ public OAuth2LoginMutator attributes(Consumer> attributesConsumer) { @@ -762,7 +761,6 @@ public class SecurityMockServerConfigurers { /** * Use the provided {@link OAuth2User} as the authenticated user. - * * @param oauth2User the {@link OAuth2User} to use * @return the {@link OAuth2LoginMutator} for further configuration */ @@ -777,9 +775,9 @@ public class SecurityMockServerConfigurers { * The supplied {@link ClientRegistration} will be registered into an * {@link WebSessionServerOAuth2AuthorizedClientRepository}. Tests relying on * {@link org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient} - * annotations should register an {@link WebSessionServerOAuth2AuthorizedClientRepository} bean - * to the application context. - * + * annotations should register an + * {@link WebSessionServerOAuth2AuthorizedClientRepository} bean to the + * application context. * @param clientRegistration the {@link ClientRegistration} to use * @return the {@link OAuth2LoginMutator} for further configuration */ @@ -791,34 +789,24 @@ public class SecurityMockServerConfigurers { @Override public void beforeServerCreated(WebHttpHandlerBuilder builder) { OAuth2AuthenticationToken token = getToken(); - mockOAuth2Client() - .accessToken(this.accessToken) - .clientRegistration(this.clientRegistration) - .principalName(token.getPrincipal().getName()) - .beforeServerCreated(builder); + mockOAuth2Client().accessToken(this.accessToken).clientRegistration(this.clientRegistration) + .principalName(token.getPrincipal().getName()).beforeServerCreated(builder); mockAuthentication(token).beforeServerCreated(builder); } @Override public void afterConfigureAdded(WebTestClient.MockServerSpec serverSpec) { OAuth2AuthenticationToken token = getToken(); - mockOAuth2Client() - .accessToken(this.accessToken) - .clientRegistration(this.clientRegistration) - .principalName(token.getPrincipal().getName()) - .afterConfigureAdded(serverSpec); + mockOAuth2Client().accessToken(this.accessToken).clientRegistration(this.clientRegistration) + .principalName(token.getPrincipal().getName()).afterConfigureAdded(serverSpec); mockAuthentication(token).afterConfigureAdded(serverSpec); } @Override - public void afterConfigurerAdded( - WebTestClient.Builder builder, - @Nullable WebHttpHandlerBuilder httpHandlerBuilder, - @Nullable ClientHttpConnector connector) { + public void afterConfigurerAdded(WebTestClient.Builder builder, + @Nullable WebHttpHandlerBuilder httpHandlerBuilder, @Nullable ClientHttpConnector connector) { OAuth2AuthenticationToken token = getToken(); - mockOAuth2Client() - .accessToken(this.accessToken) - .clientRegistration(this.clientRegistration) + mockOAuth2Client().accessToken(this.accessToken).clientRegistration(this.clientRegistration) .principalName(token.getPrincipal().getName()) .afterConfigurerAdded(builder, httpHandlerBuilder, connector); mockAuthentication(token).afterConfigurerAdded(builder, httpHandlerBuilder, connector); @@ -826,14 +814,13 @@ public class SecurityMockServerConfigurers { private OAuth2AuthenticationToken getToken() { OAuth2User oauth2User = this.oauth2User.get(); - return new OAuth2AuthenticationToken(oauth2User, oauth2User.getAuthorities(), this.clientRegistration.getRegistrationId()); + return new OAuth2AuthenticationToken(oauth2User, oauth2User.getAuthorities(), + this.clientRegistration.getRegistrationId()); } private ClientRegistration.Builder clientRegistrationBuilder() { - return ClientRegistration.withRegistrationId("test") - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .clientId("test-client") - .tokenUri("https://token-uri.example.org"); + return ClientRegistration.withRegistrationId("test").authorizationGrantType(AuthorizationGrantType.PASSWORD) + .clientId("test-client").tokenUri("https://token-uri.example.org"); } private Collection defaultAuthorities() { @@ -854,6 +841,7 @@ public class SecurityMockServerConfigurers { private OAuth2User defaultPrincipal() { return new DefaultOAuth2User(this.authorities.get(), this.attributes.get(), this.nameAttributeKey); } + } /** @@ -861,15 +849,20 @@ public class SecurityMockServerConfigurers { * @since 5.3 */ public final static class OidcLoginMutator implements WebTestClientConfigurer, MockServerConfigurer { + private ClientRegistration clientRegistration; + private OAuth2AccessToken accessToken; + private OidcIdToken idToken; + private OidcUserInfo userInfo; + private Supplier oidcUser = this::defaultPrincipal; + private Collection authorities; - ServerOAuth2AuthorizedClientRepository authorizedClientRepository = - new WebSessionServerOAuth2AuthorizedClientRepository(); + ServerOAuth2AuthorizedClientRepository authorizedClientRepository = new WebSessionServerOAuth2AuthorizedClientRepository(); private OidcLoginMutator(OAuth2AccessToken accessToken) { this.accessToken = accessToken; @@ -878,7 +871,6 @@ public class SecurityMockServerConfigurers { /** * Use the provided authorities in the {@link Authentication} - * * @param authorities the authorities to use * @return the {@link OidcLoginMutator} for further configuration */ @@ -891,7 +883,6 @@ public class SecurityMockServerConfigurers { /** * Use the provided authorities in the {@link Authentication} - * * @param authorities the authorities to use * @return the {@link OidcLoginMutator} for further configuration */ @@ -904,8 +895,8 @@ public class SecurityMockServerConfigurers { /** * Use the provided {@link OidcIdToken} when constructing the authenticated user - * - * @param idTokenBuilderConsumer a {@link Consumer} of a {@link OidcIdToken.Builder} + * @param idTokenBuilderConsumer a {@link Consumer} of a + * {@link OidcIdToken.Builder} * @return the {@link OidcLoginMutator} for further configuration */ public OidcLoginMutator idToken(Consumer idTokenBuilderConsumer) { @@ -919,8 +910,8 @@ public class SecurityMockServerConfigurers { /** * Use the provided {@link OidcUserInfo} when constructing the authenticated user - * - * @param userInfoBuilderConsumer a {@link Consumer} of a {@link OidcUserInfo.Builder} + * @param userInfoBuilderConsumer a {@link Consumer} of a + * {@link OidcUserInfo.Builder} * @return the {@link OidcLoginMutator} for further configuration */ public OidcLoginMutator userInfoToken(Consumer userInfoBuilderConsumer) { @@ -934,9 +925,8 @@ public class SecurityMockServerConfigurers { /** * Use the provided {@link OidcUser} as the authenticated user. *

        - * Supplying an {@link OidcUser} will take precedence over {@link #idToken}, {@link #userInfo}, - * and list of {@link GrantedAuthority}s to use. - * + * Supplying an {@link OidcUser} will take precedence over {@link #idToken}, + * {@link #userInfo}, and list of {@link GrantedAuthority}s to use. * @param oidcUser the {@link OidcUser} to use * @return the {@link OidcLoginMutator} for further configuration */ @@ -951,9 +941,9 @@ public class SecurityMockServerConfigurers { * The supplied {@link ClientRegistration} will be registered into an * {@link WebSessionServerOAuth2AuthorizedClientRepository}. Tests relying on * {@link org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient} - * annotations should register an {@link WebSessionServerOAuth2AuthorizedClientRepository} bean - * to the application context. - * + * annotations should register an + * {@link WebSessionServerOAuth2AuthorizedClientRepository} bean to the + * application context. * @param clientRegistration the {@link ClientRegistration} to use * @return the {@link OidcLoginMutator} for further configuration */ @@ -965,49 +955,38 @@ public class SecurityMockServerConfigurers { @Override public void beforeServerCreated(WebHttpHandlerBuilder builder) { OAuth2AuthenticationToken token = getToken(); - mockOAuth2Client() - .accessToken(this.accessToken) - .principalName(token.getPrincipal().getName()) - .clientRegistration(this.clientRegistration) - .beforeServerCreated(builder); + mockOAuth2Client().accessToken(this.accessToken).principalName(token.getPrincipal().getName()) + .clientRegistration(this.clientRegistration).beforeServerCreated(builder); mockAuthentication(token).beforeServerCreated(builder); } @Override public void afterConfigureAdded(WebTestClient.MockServerSpec serverSpec) { OAuth2AuthenticationToken token = getToken(); - mockOAuth2Client() - .accessToken(this.accessToken) - .principalName(token.getPrincipal().getName()) - .clientRegistration(this.clientRegistration) - .afterConfigureAdded(serverSpec); + mockOAuth2Client().accessToken(this.accessToken).principalName(token.getPrincipal().getName()) + .clientRegistration(this.clientRegistration).afterConfigureAdded(serverSpec); mockAuthentication(token).afterConfigureAdded(serverSpec); } @Override - public void afterConfigurerAdded( - WebTestClient.Builder builder, - @Nullable WebHttpHandlerBuilder httpHandlerBuilder, - @Nullable ClientHttpConnector connector) { + public void afterConfigurerAdded(WebTestClient.Builder builder, + @Nullable WebHttpHandlerBuilder httpHandlerBuilder, @Nullable ClientHttpConnector connector) { OAuth2AuthenticationToken token = getToken(); - mockOAuth2Client() - .accessToken(this.accessToken) - .principalName(token.getPrincipal().getName()) + mockOAuth2Client().accessToken(this.accessToken).principalName(token.getPrincipal().getName()) .clientRegistration(this.clientRegistration) .afterConfigurerAdded(builder, httpHandlerBuilder, connector); mockAuthentication(token).afterConfigurerAdded(builder, httpHandlerBuilder, connector); } private ClientRegistration.Builder clientRegistrationBuilder() { - return ClientRegistration.withRegistrationId("test") - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .clientId("test-client") - .tokenUri("https://token-uri.example.org"); + return ClientRegistration.withRegistrationId("test").authorizationGrantType(AuthorizationGrantType.PASSWORD) + .clientId("test-client").tokenUri("https://token-uri.example.org"); } private OAuth2AuthenticationToken getToken() { OidcUser oidcUser = this.oidcUser.get(); - return new OAuth2AuthenticationToken(oidcUser, oidcUser.getAuthorities(), this.clientRegistration.getRegistrationId()); + return new OAuth2AuthenticationToken(oidcUser, oidcUser.getAuthorities(), + this.clientRegistration.getRegistrationId()); } private Collection getAuthorities() { @@ -1018,7 +997,8 @@ public class SecurityMockServerConfigurers { authorities.add(new SimpleGrantedAuthority("SCOPE_" + authority)); } return authorities; - } else { + } + else { return this.authorities; } } @@ -1026,7 +1006,8 @@ public class SecurityMockServerConfigurers { private OidcIdToken getOidcIdToken() { if (this.idToken == null) { return new OidcIdToken("id-token", null, null, Collections.singletonMap(IdTokenClaimNames.SUB, "user")); - } else { + } + else { return this.idToken; } } @@ -1038,6 +1019,7 @@ public class SecurityMockServerConfigurers { private OidcUser defaultPrincipal() { return new DefaultOidcUser(getAuthorities(), getOidcIdToken(), this.userInfo); } + } /** @@ -1045,28 +1027,33 @@ public class SecurityMockServerConfigurers { * @since 5.3 */ public final static class OAuth2ClientMutator implements WebTestClientConfigurer, MockServerConfigurer { + private String registrationId = "test"; + private ClientRegistration clientRegistration; + private String principalName = "user"; + private OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", null, null, Collections.singleton("read")); - private ServerOAuth2AuthorizedClientRepository authorizedClientRepository = - new WebSessionServerOAuth2AuthorizedClientRepository(); + private ServerOAuth2AuthorizedClientRepository authorizedClientRepository = new WebSessionServerOAuth2AuthorizedClientRepository(); private OAuth2ClientMutator() { } private OAuth2ClientMutator(String registrationId) { this.registrationId = registrationId; - clientRegistration(c -> {}); + clientRegistration(c -> { + }); } /** * Use this {@link ClientRegistration} - * * @param clientRegistration - * @return the {@link SecurityMockMvcRequestPostProcessors.OAuth2ClientRequestPostProcessor} for further configuration + * @return the + * {@link SecurityMockMvcRequestPostProcessors.OAuth2ClientRequestPostProcessor} + * for further configuration */ public OAuth2ClientMutator clientRegistration(ClientRegistration clientRegistration) { this.clientRegistration = clientRegistration; @@ -1075,12 +1062,13 @@ public class SecurityMockServerConfigurers { /** * Use this {@link Consumer} to configure a {@link ClientRegistration} - * * @param clientRegistrationConfigurer the {@link ClientRegistration} configurer - * @return the {@link SecurityMockMvcRequestPostProcessors.OAuth2ClientRequestPostProcessor} for further configuration + * @return the + * {@link SecurityMockMvcRequestPostProcessors.OAuth2ClientRequestPostProcessor} + * for further configuration */ - public OAuth2ClientMutator clientRegistration - (Consumer clientRegistrationConfigurer) { + public OAuth2ClientMutator clientRegistration( + Consumer clientRegistrationConfigurer) { ClientRegistration.Builder builder = clientRegistrationBuilder(); clientRegistrationConfigurer.accept(builder); @@ -1090,7 +1078,6 @@ public class SecurityMockServerConfigurers { /** * Use this as the resource owner's principal name - * * @param principalName the resource owner's principal name * @return the {@link OAuth2ClientMutator} for further configuration */ @@ -1102,16 +1089,16 @@ public class SecurityMockServerConfigurers { /** * Use this {@link OAuth2AccessToken} - * * @param accessToken the {@link OAuth2AccessToken} to use - * @return the {@link SecurityMockMvcRequestPostProcessors.OAuth2ClientRequestPostProcessor} for further configuration + * @return the + * {@link SecurityMockMvcRequestPostProcessors.OAuth2ClientRequestPostProcessor} + * for further configuration */ public OAuth2ClientMutator accessToken(OAuth2AccessToken accessToken) { this.accessToken = accessToken; return this; } - @Override public void beforeServerCreated(WebHttpHandlerBuilder builder) { builder.filters(addAuthorizedClientFilter()); @@ -1123,10 +1110,8 @@ public class SecurityMockServerConfigurers { } @Override - public void afterConfigurerAdded( - WebTestClient.Builder builder, - @Nullable WebHttpHandlerBuilder httpHandlerBuilder, - @Nullable ClientHttpConnector connector) { + public void afterConfigurerAdded(WebTestClient.Builder builder, + @Nullable WebHttpHandlerBuilder httpHandlerBuilder, @Nullable ClientHttpConnector connector) { httpHandlerBuilder.filters(addAuthorizedClientFilter()); } @@ -1136,8 +1121,8 @@ public class SecurityMockServerConfigurers { ReactiveOAuth2AuthorizedClientManager authorizationClientManager = OAuth2ClientServerTestUtils .getOAuth2AuthorizedClientManager(exchange); if (!(authorizationClientManager instanceof TestReactiveOAuth2AuthorizedClientManager)) { - authorizationClientManager = - new TestReactiveOAuth2AuthorizedClientManager(authorizationClientManager); + authorizationClientManager = new TestReactiveOAuth2AuthorizedClientManager( + authorizationClientManager); OAuth2ClientServerTestUtils.setOAuth2AuthorizedClientManager(exchange, authorizationClientManager); } TestReactiveOAuth2AuthorizedClientManager.enable(exchange); @@ -1148,32 +1133,30 @@ public class SecurityMockServerConfigurers { private OAuth2AuthorizedClient getClient() { if (this.clientRegistration == null) { - throw new IllegalArgumentException("Please specify a ClientRegistration via one " + - "of the clientRegistration methods"); + throw new IllegalArgumentException( + "Please specify a ClientRegistration via one " + "of the clientRegistration methods"); } return new OAuth2AuthorizedClient(this.clientRegistration, this.principalName, this.accessToken); } private ClientRegistration.Builder clientRegistrationBuilder() { return ClientRegistration.withRegistrationId(this.registrationId) - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .clientId("test-client") - .clientSecret("test-secret") - .tokenUri("https://idp.example.org/oauth/token"); + .authorizationGrantType(AuthorizationGrantType.PASSWORD).clientId("test-client") + .clientSecret("test-secret").tokenUri("https://idp.example.org/oauth/token"); } /** - * Used to wrap the {@link OAuth2AuthorizedClientManager} to provide support for testing when the - * request is wrapped + * Used to wrap the {@link OAuth2AuthorizedClientManager} to provide support for + * testing when the request is wrapped */ private static class TestReactiveOAuth2AuthorizedClientManager implements ReactiveOAuth2AuthorizedClientManager { - final static String TOKEN_ATTR_NAME = TestReactiveOAuth2AuthorizedClientManager.class - .getName().concat(".TOKEN"); + final static String TOKEN_ATTR_NAME = TestReactiveOAuth2AuthorizedClientManager.class.getName() + .concat(".TOKEN"); - final static String ENABLED_ATTR_NAME = TestReactiveOAuth2AuthorizedClientManager.class - .getName().concat(".ENABLED"); + final static String ENABLED_ATTR_NAME = TestReactiveOAuth2AuthorizedClientManager.class.getName() + .concat(".ENABLED"); private final ReactiveOAuth2AuthorizedClientManager delegate; @@ -1183,12 +1166,12 @@ public class SecurityMockServerConfigurers { @Override public Mono authorize(OAuth2AuthorizeRequest authorizeRequest) { - ServerWebExchange exchange = - authorizeRequest.getAttribute(ServerWebExchange.class.getName()); + ServerWebExchange exchange = authorizeRequest.getAttribute(ServerWebExchange.class.getName()); if (isEnabled(exchange)) { OAuth2AuthorizedClient client = exchange.getAttribute(TOKEN_ATTR_NAME); return Mono.just(client); - } else { + } + else { return this.delegate.authorize(authorizeRequest); } } @@ -1200,43 +1183,45 @@ public class SecurityMockServerConfigurers { public boolean isEnabled(ServerWebExchange exchange) { return TRUE.equals(exchange.getAttribute(ENABLED_ATTR_NAME)); } + } private static class OAuth2ClientServerTestUtils { - private static final ServerOAuth2AuthorizedClientRepository DEFAULT_CLIENT_REPO = - new WebSessionServerOAuth2AuthorizedClientRepository(); + + private static final ServerOAuth2AuthorizedClientRepository DEFAULT_CLIENT_REPO = new WebSessionServerOAuth2AuthorizedClientRepository(); /** - * Gets the {@link ReactiveOAuth2AuthorizedClientManager} for the specified {@link ServerWebExchange}. - * If one is not found, one based off of {@link WebSessionServerOAuth2AuthorizedClientRepository} is used. - * + * Gets the {@link ReactiveOAuth2AuthorizedClientManager} for the specified + * {@link ServerWebExchange}. If one is not found, one based off of + * {@link WebSessionServerOAuth2AuthorizedClientRepository} is used. * @param exchange the {@link ServerWebExchange} to obtain the * {@link ReactiveOAuth2AuthorizedClientManager} * @return the {@link ReactiveOAuth2AuthorizedClientManager} for the specified * {@link ServerWebExchange} */ - public static ReactiveOAuth2AuthorizedClientManager getOAuth2AuthorizedClientManager(ServerWebExchange exchange) { - OAuth2AuthorizedClientArgumentResolver resolver = - findResolver(exchange, OAuth2AuthorizedClientArgumentResolver.class); + public static ReactiveOAuth2AuthorizedClientManager getOAuth2AuthorizedClientManager( + ServerWebExchange exchange) { + OAuth2AuthorizedClientArgumentResolver resolver = findResolver(exchange, + OAuth2AuthorizedClientArgumentResolver.class); if (resolver == null) { - return authorizeRequest -> DEFAULT_CLIENT_REPO.loadAuthorizedClient - (authorizeRequest.getClientRegistrationId(), authorizeRequest.getPrincipal(), exchange); + return authorizeRequest -> DEFAULT_CLIENT_REPO.loadAuthorizedClient( + authorizeRequest.getClientRegistrationId(), authorizeRequest.getPrincipal(), exchange); } - return (ReactiveOAuth2AuthorizedClientManager) - ReflectionTestUtils.getField(resolver, "authorizedClientManager"); + return (ReactiveOAuth2AuthorizedClientManager) ReflectionTestUtils.getField(resolver, + "authorizedClientManager"); } /** - * Sets the {@link ReactiveOAuth2AuthorizedClientManager} for the specified {@link ServerWebExchange}. - * + * Sets the {@link ReactiveOAuth2AuthorizedClientManager} for the specified + * {@link ServerWebExchange}. * @param exchange the {@link ServerWebExchange} to obtain the * {@link ReactiveOAuth2AuthorizedClientManager} * @param manager the {@link ReactiveOAuth2AuthorizedClientManager} to set */ public static void setOAuth2AuthorizedClientManager(ServerWebExchange exchange, ReactiveOAuth2AuthorizedClientManager manager) { - OAuth2AuthorizedClientArgumentResolver resolver = - findResolver(exchange, OAuth2AuthorizedClientArgumentResolver.class); + OAuth2AuthorizedClientArgumentResolver resolver = findResolver(exchange, + OAuth2AuthorizedClientArgumentResolver.class); if (resolver == null) { return; } @@ -1246,14 +1231,16 @@ public class SecurityMockServerConfigurers { @SuppressWarnings("unchecked") static T findResolver(ServerWebExchange exchange, Class resolverClass) { - if (!ClassUtils.isPresent - ("org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter", null)) { + if (!ClassUtils.isPresent( + "org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter", + null)) { return null; } return WebFluxClasspathGuard.findResolver(exchange, resolverClass); } private static class WebFluxClasspathGuard { + static T findResolver(ServerWebExchange exchange, Class resolverClass) { RequestMappingHandlerAdapter handlerAdapter = getRequestMappingHandlerAdapter(exchange); @@ -1264,8 +1251,8 @@ public class SecurityMockServerConfigurers { if (configurer == null) { return null; } - List resolvers = (List) - ReflectionTestUtils.invokeGetterMethod(configurer, "customResolvers"); + List resolvers = (List) ReflectionTestUtils + .invokeGetterMethod(configurer, "customResolvers"); if (resolvers == null) { return null; } @@ -1277,7 +1264,8 @@ public class SecurityMockServerConfigurers { return null; } - private static RequestMappingHandlerAdapter getRequestMappingHandlerAdapter(ServerWebExchange exchange) { + private static RequestMappingHandlerAdapter getRequestMappingHandlerAdapter( + ServerWebExchange exchange) { ApplicationContext context = exchange.getApplicationContext(); if (context != null) { String[] names = context.getBeanNamesForType(RequestMappingHandlerAdapter.class); @@ -1287,10 +1275,14 @@ public class SecurityMockServerConfigurers { } return null; } + } private OAuth2ClientServerTestUtils() { } + } + } + } diff --git a/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestBuilders.java b/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestBuilders.java index fb5a69d24d..47a7c7e304 100644 --- a/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestBuilders.java +++ b/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestBuilders.java @@ -42,7 +42,6 @@ public final class SecurityMockMvcRequestBuilders { /** * Creates a request (including any necessary {@link CsrfToken}) that will submit a * form based login to POST "/login". - * * @return the FormLoginRequestBuilder for further customizations */ public static FormLoginRequestBuilder formLogin() { @@ -52,9 +51,7 @@ public final class SecurityMockMvcRequestBuilders { /** * Creates a request (including any necessary {@link CsrfToken}) that will submit a * form based login to POST {@code loginProcessingUrl}. - * * @param loginProcessingUrl the URL to POST to - * * @return the FormLoginRequestBuilder for further customizations */ public static FormLoginRequestBuilder formLogin(String loginProcessingUrl) { @@ -63,7 +60,6 @@ public final class SecurityMockMvcRequestBuilders { /** * Creates a logout request. - * * @return the LogoutRequestBuilder for additional customizations */ public static LogoutRequestBuilder logout() { @@ -73,9 +69,7 @@ public final class SecurityMockMvcRequestBuilders { /** * Creates a logout request (including any necessary {@link CsrfToken}) to the * specified {@code logoutUrl} - * * @param logoutUrl the logout request URL - * * @return the LogoutRequestBuilder for additional customizations */ public static LogoutRequestBuilder logout(String logoutUrl) { @@ -89,14 +83,17 @@ public final class SecurityMockMvcRequestBuilders { * @since 4.0 */ public static final class LogoutRequestBuilder implements RequestBuilder, Mergeable { + private String logoutUrl = "/logout"; + private RequestPostProcessor postProcessor = csrf(); + private Mergeable parent; @Override public MockHttpServletRequest buildRequest(ServletContext servletContext) { - MockHttpServletRequestBuilder logoutRequest = post(this.logoutUrl) - .accept(MediaType.TEXT_HTML, MediaType.ALL); + MockHttpServletRequestBuilder logoutRequest = post(this.logoutUrl).accept(MediaType.TEXT_HTML, + MediaType.ALL); if (this.parent != null) { logoutRequest = (MockHttpServletRequestBuilder) logoutRequest.merge(this.parent); @@ -110,7 +107,6 @@ public final class SecurityMockMvcRequestBuilders { /** * Specifies the logout URL to POST to. Defaults to "/logout". - * * @param logoutUrl the logout URL to POST to. Defaults to "/logout". * @return the {@link LogoutRequestBuilder} for additional customizations */ @@ -121,14 +117,12 @@ public final class SecurityMockMvcRequestBuilders { /** * Specifies the logout URL to POST to. - * * @param logoutUrl the logout URL to POST to. * @param uriVars the URI variables * @return the {@link LogoutRequestBuilder} for additional customizations */ public LogoutRequestBuilder logoutUrl(String logoutUrl, Object... uriVars) { - this.logoutUrl = UriComponentsBuilder.fromPath(logoutUrl) - .buildAndExpand(uriVars).encode().toString(); + this.logoutUrl = UriComponentsBuilder.fromPath(logoutUrl).buildAndExpand(uriVars).encode().toString(); return this; } @@ -145,13 +139,15 @@ public final class SecurityMockMvcRequestBuilders { if (parent instanceof Mergeable) { this.parent = (Mergeable) parent; return this; - } else { + } + else { throw new IllegalArgumentException("Cannot merge with [" + parent.getClass().getName() + "]"); } } private LogoutRequestBuilder() { } + } /** @@ -161,22 +157,27 @@ public final class SecurityMockMvcRequestBuilders { * @since 4.0 */ public static final class FormLoginRequestBuilder implements RequestBuilder, Mergeable { + private String usernameParam = "username"; + private String passwordParam = "password"; + private String username = "user"; + private String password = "password"; + private String loginProcessingUrl = "/login"; + private MediaType acceptMediaType = MediaType.APPLICATION_FORM_URLENCODED; + private Mergeable parent; private RequestPostProcessor postProcessor = csrf(); @Override public MockHttpServletRequest buildRequest(ServletContext servletContext) { - MockHttpServletRequestBuilder loginRequest = post(this.loginProcessingUrl) - .accept(this.acceptMediaType) - .param(this.usernameParam, this.username) - .param(this.passwordParam, this.password); + MockHttpServletRequestBuilder loginRequest = post(this.loginProcessingUrl).accept(this.acceptMediaType) + .param(this.usernameParam, this.username).param(this.passwordParam, this.password); if (this.parent != null) { loginRequest = (MockHttpServletRequestBuilder) loginRequest.merge(this.parent); @@ -190,7 +191,6 @@ public final class SecurityMockMvcRequestBuilders { /** * Specifies the URL to POST to. Default is "/login" - * * @param loginProcessingUrl the URL to POST to. Default is "/login" * @return the {@link FormLoginRequestBuilder} for additional customizations */ @@ -201,14 +201,13 @@ public final class SecurityMockMvcRequestBuilders { /** * Specifies the URL to POST to. - * * @param loginProcessingUrl the URL to POST to * @param uriVars the URI variables * @return the {@link FormLoginRequestBuilder} for additional customizations */ public FormLoginRequestBuilder loginProcessingUrl(String loginProcessingUrl, Object... uriVars) { - this.loginProcessingUrl = UriComponentsBuilder.fromPath(loginProcessingUrl) - .buildAndExpand(uriVars).encode().toString(); + this.loginProcessingUrl = UriComponentsBuilder.fromPath(loginProcessingUrl).buildAndExpand(uriVars).encode() + .toString(); return this; } @@ -256,14 +255,12 @@ public final class SecurityMockMvcRequestBuilders { /** * Specify both the password parameter name and the password. - * * @param passwordParameter the HTTP parameter to place the password. Default is * "password". * @param password the value of the password parameter. Default is "password". * @return the {@link FormLoginRequestBuilder} for additional customizations */ - public FormLoginRequestBuilder password(String passwordParameter, - String password) { + public FormLoginRequestBuilder password(String passwordParameter, String password) { passwordParam(passwordParameter); this.password = password; return this; @@ -271,7 +268,6 @@ public final class SecurityMockMvcRequestBuilders { /** * Specify both the password parameter name and the password. - * * @param usernameParameter the HTTP parameter to place the username. Default is * "username". * @param username the value of the username parameter. Default is "user". @@ -285,7 +281,6 @@ public final class SecurityMockMvcRequestBuilders { /** * Specify a media type to set as the Accept header in the request. - * * @param acceptMediaType the {@link MediaType} to set the Accept header to. * Default is: MediaType.APPLICATION_FORM_URLENCODED * @return the {@link FormLoginRequestBuilder} for additional customizations @@ -305,18 +300,21 @@ public final class SecurityMockMvcRequestBuilders { if (parent == null) { return this; } - if (parent instanceof Mergeable ) { + if (parent instanceof Mergeable) { this.parent = (Mergeable) parent; return this; - } else { + } + else { throw new IllegalArgumentException("Cannot merge with [" + parent.getClass().getName() + "]"); } } private FormLoginRequestBuilder() { } + } private SecurityMockMvcRequestBuilders() { } + } diff --git a/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessors.java b/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessors.java index 866396e754..1821fa1ab6 100644 --- a/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessors.java +++ b/test/src/main/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessors.java @@ -119,7 +119,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Creates a DigestRequestPostProcessor that enables easily adding digest based * authentication to a request. - * * @return the DigestRequestPostProcessor to use */ public static DigestRequestPostProcessor digest() { @@ -129,7 +128,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Creates a DigestRequestPostProcessor that enables easily adding digest based * authentication to a request. - * * @param username the username to use * @return the DigestRequestPostProcessor to use */ @@ -149,28 +147,24 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Finds an X509Cetificate using a resoureName and populates it on the request. - * * @param resourceName the name of the X509Certificate resource * @return the * {@link org.springframework.test.web.servlet.request.RequestPostProcessor} to use. * @throws IOException * @throws CertificateException */ - public static RequestPostProcessor x509(String resourceName) - throws IOException, CertificateException { + public static RequestPostProcessor x509(String resourceName) throws IOException, CertificateException { ResourceLoader loader = new DefaultResourceLoader(); Resource resource = loader.getResource(resourceName); InputStream inputStream = resource.getInputStream(); CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - X509Certificate certificate = (X509Certificate) certFactory - .generateCertificate(inputStream); + X509Certificate certificate = (X509Certificate) certFactory.generateCertificate(inputStream); return x509(certificate); } /** * Creates a {@link RequestPostProcessor} that will automatically populate a valid * {@link CsrfToken} in the request. - * * @return the {@link CsrfRequestPostProcessor} for further customizations. */ public static CsrfRequestPostProcessor csrf() { @@ -180,7 +174,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Creates a {@link RequestPostProcessor} that can be used to ensure that the * resulting request is ran with the user in the {@link TestSecurityContextHolder}. - * * @return the {@link RequestPostProcessor} to sue */ public static RequestPostProcessor testSecurityContext() { @@ -207,7 +200,6 @@ public final class SecurityMockMvcRequestPostProcessors { *

      18. Manually adding {@link SecurityContextPersistenceFilter} to the MockMvc * instance may make sense when using MockMvcBuilders standaloneSetup
      19. * - * * @param username the username to populate * @return the {@link UserRequestPostProcessor} for additional customization */ @@ -235,7 +227,6 @@ public final class SecurityMockMvcRequestPostProcessors { *
      20. Manually adding {@link SecurityContextPersistenceFilter} to the MockMvc * instance may make sense when using MockMvcBuilders standaloneSetup
      21. * - * * @param user the UserDetails to populate * @return the {@link RequestPostProcessor} to use */ @@ -244,15 +235,14 @@ public final class SecurityMockMvcRequestPostProcessors { } /** - * Establish a {@link SecurityContext} that has a - * {@link JwtAuthenticationToken} for the - * {@link Authentication} and a {@link Jwt} for the - * {@link Authentication#getPrincipal()}. All details are - * declarative and do not require the JWT to be valid. + * Establish a {@link SecurityContext} that has a {@link JwtAuthenticationToken} for + * the {@link Authentication} and a {@link Jwt} for the + * {@link Authentication#getPrincipal()}. All details are declarative and do not + * require the JWT to be valid. * *

        - * The support works by associating the authentication to the HttpServletRequest. To associate - * the request to the SecurityContextHolder you need to ensure that the + * The support works by associating the authentication to the HttpServletRequest. To + * associate the request to the SecurityContextHolder you need to ensure that the * SecurityContextPersistenceFilter is associated with the MockMvc instance. A few * ways to do this are: *

        @@ -263,7 +253,6 @@ public final class SecurityMockMvcRequestPostProcessors { *
      22. Manually adding {@link SecurityContextPersistenceFilter} to the MockMvc * instance may make sense when using MockMvcBuilders standaloneSetup
      23. * - * * @return the {@link JwtRequestPostProcessor} for additional customization */ public static JwtRequestPostProcessor jwt() { @@ -271,15 +260,14 @@ public final class SecurityMockMvcRequestPostProcessors { } /** - * Establish a {@link SecurityContext} that has a - * {@link BearerTokenAuthentication} for the - * {@link Authentication} and a {@link OAuth2AuthenticatedPrincipal} for the - * {@link Authentication#getPrincipal()}. All details are - * declarative and do not require the token to be valid + * Establish a {@link SecurityContext} that has a {@link BearerTokenAuthentication} + * for the {@link Authentication} and a {@link OAuth2AuthenticatedPrincipal} for the + * {@link Authentication#getPrincipal()}. All details are declarative and do not + * require the token to be valid * *

        - * The support works by associating the authentication to the HttpServletRequest. To associate - * the request to the SecurityContextHolder you need to ensure that the + * The support works by associating the authentication to the HttpServletRequest. To + * associate the request to the SecurityContextHolder you need to ensure that the * SecurityContextPersistenceFilter is associated with the MockMvc instance. A few * ways to do this are: *

        @@ -290,7 +278,6 @@ public final class SecurityMockMvcRequestPostProcessors { *
      24. Manually adding {@link SecurityContextPersistenceFilter} to the MockMvc * instance may make sense when using MockMvcBuilders standaloneSetup
      25. * - * * @return the {@link OpaqueTokenRequestPostProcessor} for additional customization * @since 5.3 */ @@ -316,7 +303,6 @@ public final class SecurityMockMvcRequestPostProcessors { *
      26. Manually adding {@link SecurityContextPersistenceFilter} to the MockMvc * instance may make sense when using MockMvcBuilders standaloneSetup
      27. * - * * @param authentication the Authentication to populate * @return the {@link RequestPostProcessor} to use */ @@ -348,7 +334,6 @@ public final class SecurityMockMvcRequestPostProcessors { * // ... lots of tests ran with a default user ... * } * - * * @return the {@link RequestPostProcessor} to use */ public static RequestPostProcessor anonymous() { @@ -373,7 +358,6 @@ public final class SecurityMockMvcRequestPostProcessors { * Convenience mechanism for setting the Authorization header to use HTTP Basic with * the given username and password. This method will automatically perform the * necessary Base64 encoding. - * * @param username the username to include in the Authorization header. * @param password the password to include in the Authorization header. * @return the {@link RequestPostProcessor} to use @@ -383,15 +367,14 @@ public final class SecurityMockMvcRequestPostProcessors { } /** - * Establish a {@link SecurityContext} that has a - * {@link OAuth2AuthenticationToken} for the - * {@link Authentication}, a {@link OAuth2User} as the principal, - * and a {@link OAuth2AuthorizedClient} in the session. All details are - * declarative and do not require associated tokens to be valid. + * Establish a {@link SecurityContext} that has a {@link OAuth2AuthenticationToken} + * for the {@link Authentication}, a {@link OAuth2User} as the principal, and a + * {@link OAuth2AuthorizedClient} in the session. All details are declarative and do + * not require associated tokens to be valid. * *

        - * The support works by associating the authentication to the HttpServletRequest. To associate - * the request to the SecurityContextHolder you need to ensure that the + * The support works by associating the authentication to the HttpServletRequest. To + * associate the request to the SecurityContextHolder you need to ensure that the * SecurityContextPersistenceFilter is associated with the MockMvc instance. A few * ways to do this are: *

        @@ -402,26 +385,24 @@ public final class SecurityMockMvcRequestPostProcessors { *
      28. Manually adding {@link SecurityContextPersistenceFilter} to the MockMvc * instance may make sense when using MockMvcBuilders standaloneSetup
      29. * - * * @return the {@link OidcLoginRequestPostProcessor} for additional customization * @since 5.3 */ public static OAuth2LoginRequestPostProcessor oauth2Login() { - OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", - null, null, Collections.singleton("read")); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", null, + null, Collections.singleton("read")); return new OAuth2LoginRequestPostProcessor(accessToken); } /** - * Establish a {@link SecurityContext} that has a - * {@link OAuth2AuthenticationToken} for the - * {@link Authentication}, a {@link OidcUser} as the principal, - * and a {@link OAuth2AuthorizedClient} in the session. All details are - * declarative and do not require associated tokens to be valid. + * Establish a {@link SecurityContext} that has a {@link OAuth2AuthenticationToken} + * for the {@link Authentication}, a {@link OidcUser} as the principal, and a + * {@link OAuth2AuthorizedClient} in the session. All details are declarative and do + * not require associated tokens to be valid. * *

        - * The support works by associating the authentication to the HttpServletRequest. To associate - * the request to the SecurityContextHolder you need to ensure that the + * The support works by associating the authentication to the HttpServletRequest. To + * associate the request to the SecurityContextHolder you need to ensure that the * SecurityContextPersistenceFilter is associated with the MockMvc instance. A few * ways to do this are: *

        @@ -432,13 +413,12 @@ public final class SecurityMockMvcRequestPostProcessors { *
      30. Manually adding {@link SecurityContextPersistenceFilter} to the MockMvc * instance may make sense when using MockMvcBuilders standaloneSetup
      31. * - * * @return the {@link OidcLoginRequestPostProcessor} for additional customization * @since 5.3 */ public static OidcLoginRequestPostProcessor oidcLogin() { - OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", - null, null, Collections.singleton("read")); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", null, + null, Collections.singleton("read")); return new OidcLoginRequestPostProcessor(accessToken); } @@ -450,7 +430,6 @@ public final class SecurityMockMvcRequestPostProcessors { * The support works by associating the authorized client to the HttpServletRequest * via the {@link HttpSessionOAuth2AuthorizedClientRepository} *

        - * * @return the {@link OAuth2ClientRequestPostProcessor} for additional customization * @since 5.3 */ @@ -466,7 +445,6 @@ public final class SecurityMockMvcRequestPostProcessors { * The support works by associating the authorized client to the HttpServletRequest * via the {@link HttpSessionOAuth2AuthorizedClientRepository} *

        - * * @param registrationId The registration id for the {@link OAuth2AuthorizedClient} * @return the {@link OAuth2ClientRequestPostProcessor} for additional customization * @since 5.3 @@ -479,6 +457,7 @@ public final class SecurityMockMvcRequestPostProcessors { * Populates the X509Certificate instances onto the request */ private static class X509RequestPostProcessor implements RequestPostProcessor { + private final X509Certificate[] certificates; private X509RequestPostProcessor(X509Certificate... certificates) { @@ -488,10 +467,10 @@ public final class SecurityMockMvcRequestPostProcessors { @Override public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { - request.setAttribute("javax.servlet.request.X509Certificate", - this.certificates); + request.setAttribute("javax.servlet.request.X509Certificate", this.certificates); return request; } + } /** @@ -516,15 +495,13 @@ public final class SecurityMockMvcRequestPostProcessors { public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { CsrfTokenRepository repository = WebTestUtils.getCsrfTokenRepository(request); if (!(repository instanceof TestCsrfTokenRepository)) { - repository = new TestCsrfTokenRepository( - new HttpSessionCsrfTokenRepository()); + repository = new TestCsrfTokenRepository(new HttpSessionCsrfTokenRepository()); WebTestUtils.setCsrfTokenRepository(request, repository); } TestCsrfTokenRepository.enable(request); CsrfToken token = repository.generateToken(request); repository.saveToken(token, request, new MockHttpServletResponse()); - String tokenValue = this.useInvalidToken ? "invalid" + token.getToken() - : token.getToken(); + String tokenValue = this.useInvalidToken ? "invalid" + token.getToken() : token.getToken(); if (this.asHeader) { request.addHeader(token.getHeaderName(), tokenValue); } @@ -537,7 +514,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Instead of using the {@link CsrfToken} as a request parameter (default) will * populate the {@link CsrfToken} as a header. - * * @return the {@link CsrfRequestPostProcessor} for additional customizations */ public CsrfRequestPostProcessor asHeader() { @@ -547,7 +523,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Populates an invalid token value on the request. - * * @return the {@link CsrfRequestPostProcessor} for additional customizations */ public CsrfRequestPostProcessor useInvalidToken() { @@ -563,11 +538,10 @@ public final class SecurityMockMvcRequestPostProcessors { * request is wrapped (i.e. Spring Session is in use). */ static class TestCsrfTokenRepository implements CsrfTokenRepository { - final static String TOKEN_ATTR_NAME = TestCsrfTokenRepository.class.getName() - .concat(".TOKEN"); - final static String ENABLED_ATTR_NAME = TestCsrfTokenRepository.class - .getName().concat(".ENABLED"); + final static String TOKEN_ATTR_NAME = TestCsrfTokenRepository.class.getName().concat(".TOKEN"); + + final static String ENABLED_ATTR_NAME = TestCsrfTokenRepository.class.getName().concat(".ENABLED"); private final CsrfTokenRepository delegate; @@ -581,8 +555,7 @@ public final class SecurityMockMvcRequestPostProcessors { } @Override - public void saveToken(CsrfToken token, HttpServletRequest request, - HttpServletResponse response) { + public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) { if (isEnabled(request)) { request.setAttribute(TOKEN_ATTR_NAME, token); } @@ -608,10 +581,13 @@ public final class SecurityMockMvcRequestPostProcessors { public boolean isEnabled(HttpServletRequest request) { return TRUE.equals(request.getAttribute(ENABLED_ATTR_NAME)); } + } + } public static class DigestRequestPostProcessor implements RequestPostProcessor { + private String username = "user"; private String password = "password"; @@ -670,13 +646,11 @@ public final class SecurityMockMvcRequestPostProcessors { private String createAuthorizationHeader(MockHttpServletRequest request) { String uri = request.getRequestURI(); - String responseDigest = generateDigest(this.username, this.realm, - this.password, request.getMethod(), uri, this.qop, this.nonce, - this.nc, this.cnonce); - return "Digest username=\"" + this.username + "\", realm=\"" + this.realm - + "\", nonce=\"" + this.nonce + "\", uri=\"" + uri + "\", response=\"" - + responseDigest + "\", qop=" + this.qop + ", nc=" + this.nc - + ", cnonce=\"" + this.cnonce + "\""; + String responseDigest = generateDigest(this.username, this.realm, this.password, request.getMethod(), uri, + this.qop, this.nonce, this.nc, this.cnonce); + return "Digest username=\"" + this.username + "\", realm=\"" + this.realm + "\", nonce=\"" + this.nonce + + "\", uri=\"" + uri + "\", response=\"" + responseDigest + "\", qop=" + this.qop + ", nc=" + + this.nc + ", cnonce=\"" + this.cnonce + "\""; } @Override @@ -691,7 +665,6 @@ public final class SecurityMockMvcRequestPostProcessors { * Both the server and user agent should compute the response * independently. Provided as a static method to simplify the coding of user * agents. - * * @param username the user's login name. * @param realm the name of the realm. * @param password the user's password in plaintext or ready-encoded. @@ -704,9 +677,8 @@ public final class SecurityMockMvcRequestPostProcessors { * @return the MD5 of the digest authentication response, encoded in hex * @throws IllegalArgumentException if the supplied qop value is unsupported. */ - private static String generateDigest(String username, String realm, - String password, String httpMethod, String uri, String qop, String nonce, - String nc, String cnonce) throws IllegalArgumentException { + private static String generateDigest(String username, String realm, String password, String httpMethod, + String uri, String qop, String nonce, String nc, String cnonce) throws IllegalArgumentException { String a1Md5 = encodePasswordInA1Format(username, realm, password); String a2 = httpMethod + ":" + uri; String a2Md5 = md5Hex(a2); @@ -719,19 +691,16 @@ public final class SecurityMockMvcRequestPostProcessors { } else if ("auth".equals(qop)) { // As per RFC 2617 compliant clients - digest = a1Md5 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" - + a2Md5; + digest = a1Md5 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + a2Md5; } else { - throw new IllegalArgumentException( - "This method does not support a qop: '" + qop + "'"); + throw new IllegalArgumentException("This method does not support a qop: '" + qop + "'"); } return md5Hex(digest); } - static String encodePasswordInA1Format(String username, String realm, - String password) { + static String encodePasswordInA1Format(String username, String realm, String password) { String a1 = username + ":" + realm + ":" + password; return md5Hex(a1); @@ -740,6 +709,7 @@ public final class SecurityMockMvcRequestPostProcessors { private static String md5Hex(String a2) { return DigestUtils.md5DigestAsHex(a2.getBytes(StandardCharsets.UTF_8)); } + } /** @@ -751,7 +721,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Saves the specified {@link Authentication} into an empty * {@link SecurityContext} using the {@link SecurityContextRepository}. - * * @param authentication the {@link Authentication} to save * @param request the {@link HttpServletRequest} to use */ @@ -763,25 +732,20 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Saves the {@link SecurityContext} using the {@link SecurityContextRepository} - * * @param securityContext the {@link SecurityContext} to save * @param request the {@link HttpServletRequest} to use */ final void save(SecurityContext securityContext, HttpServletRequest request) { - SecurityContextRepository securityContextRepository = WebTestUtils - .getSecurityContextRepository(request); + SecurityContextRepository securityContextRepository = WebTestUtils.getSecurityContextRepository(request); boolean isTestRepository = securityContextRepository instanceof TestSecurityContextRepository; if (!isTestRepository) { - securityContextRepository = new TestSecurityContextRepository( - securityContextRepository); - WebTestUtils.setSecurityContextRepository(request, - securityContextRepository); + securityContextRepository = new TestSecurityContextRepository(securityContextRepository); + WebTestUtils.setSecurityContextRepository(request, securityContextRepository); } HttpServletResponse response = new MockHttpServletResponse(); - HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder( - request, response); + HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response); securityContextRepository.loadContext(requestResponseHolder); request = requestResponseHolder.getRequest(); @@ -795,8 +759,8 @@ public final class SecurityMockMvcRequestPostProcessors { * stateless mode */ static class TestSecurityContextRepository implements SecurityContextRepository { - private final static String ATTR_NAME = TestSecurityContextRepository.class - .getName().concat(".REPO"); + + private final static String ATTR_NAME = TestSecurityContextRepository.class.getName().concat(".REPO"); private final SecurityContextRepository delegate; @@ -805,35 +769,33 @@ public final class SecurityMockMvcRequestPostProcessors { } @Override - public SecurityContext loadContext( - HttpRequestResponseHolder requestResponseHolder) { + public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) { SecurityContext result = getContext(requestResponseHolder.getRequest()); // always load from the delegate to ensure the request/response in the // holder are updated // remember the SecurityContextRepository is used in many different // locations - SecurityContext delegateResult = this.delegate - .loadContext(requestResponseHolder); + SecurityContext delegateResult = this.delegate.loadContext(requestResponseHolder); return result == null ? delegateResult : result; } @Override - public void saveContext(SecurityContext context, HttpServletRequest request, - HttpServletResponse response) { + public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) { request.setAttribute(ATTR_NAME, context); this.delegate.saveContext(context, request, response); } @Override public boolean containsContext(HttpServletRequest request) { - return getContext(request) != null - || this.delegate.containsContext(request); + return getContext(request) != null || this.delegate.containsContext(request); } private static SecurityContext getContext(HttpServletRequest request) { return (SecurityContext) request.getAttribute(ATTR_NAME); } + } + } /** @@ -844,15 +806,15 @@ public final class SecurityMockMvcRequestPostProcessors { * @author Rob Winch * @since 4.0 */ - private final static class TestSecurityContextHolderPostProcessor extends - SecurityContextRequestPostProcessorSupport implements RequestPostProcessor { + private final static class TestSecurityContextHolderPostProcessor extends SecurityContextRequestPostProcessorSupport + implements RequestPostProcessor { + private SecurityContext EMPTY = SecurityContextHolder.createEmptyContext(); @Override public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { // TestSecurityContextHolder is only a default value - SecurityContext existingContext = TestSecurityContextRepository - .getContext(request); + SecurityContext existingContext = TestSecurityContextRepository.getContext(request); if (existingContext != null) { return request; } @@ -864,6 +826,7 @@ public final class SecurityMockMvcRequestPostProcessors { return request; } + } /** @@ -873,8 +836,8 @@ public final class SecurityMockMvcRequestPostProcessors { * @author Rob Winch * @since 4.0 */ - private final static class SecurityContextRequestPostProcessor extends - SecurityContextRequestPostProcessorSupport implements RequestPostProcessor { + private final static class SecurityContextRequestPostProcessor extends SecurityContextRequestPostProcessorSupport + implements RequestPostProcessor { private final SecurityContext securityContext; @@ -887,6 +850,7 @@ public final class SecurityMockMvcRequestPostProcessors { save(this.securityContext, request); return request; } + } /** @@ -897,8 +861,9 @@ public final class SecurityMockMvcRequestPostProcessors { * @since 4.0 * */ - private final static class AuthenticationRequestPostProcessor extends - SecurityContextRequestPostProcessorSupport implements RequestPostProcessor { + private final static class AuthenticationRequestPostProcessor extends SecurityContextRequestPostProcessorSupport + implements RequestPostProcessor { + private final Authentication authentication; private AuthenticationRequestPostProcessor(Authentication authentication) { @@ -912,6 +877,7 @@ public final class SecurityMockMvcRequestPostProcessors { save(this.authentication, request); return request; } + } /** @@ -922,13 +888,13 @@ public final class SecurityMockMvcRequestPostProcessors { * @author Rob Winch * @since 4.0 */ - private final static class UserDetailsRequestPostProcessor - implements RequestPostProcessor { + private final static class UserDetailsRequestPostProcessor implements RequestPostProcessor { + private final RequestPostProcessor delegate; UserDetailsRequestPostProcessor(UserDetails user) { - Authentication token = new UsernamePasswordAuthenticationToken(user, - user.getPassword(), user.getAuthorities()); + Authentication token = new UsernamePasswordAuthenticationToken(user, user.getPassword(), + user.getAuthorities()); this.delegate = new AuthenticationRequestPostProcessor(token); } @@ -937,6 +903,7 @@ public final class SecurityMockMvcRequestPostProcessors { public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { return this.delegate.postProcessRequest(request); } + } /** @@ -946,8 +913,8 @@ public final class SecurityMockMvcRequestPostProcessors { * @author Rob Winch * @since 4.0 */ - public final static class UserRequestPostProcessor extends - SecurityContextRequestPostProcessorSupport implements RequestPostProcessor { + public final static class UserRequestPostProcessor extends SecurityContextRequestPostProcessorSupport + implements RequestPostProcessor { private String username; @@ -955,8 +922,7 @@ public final class SecurityMockMvcRequestPostProcessors { private static final String ROLE_PREFIX = "ROLE_"; - private Collection authorities = AuthorityUtils - .createAuthorityList("ROLE_USER"); + private Collection authorities = AuthorityUtils.createAuthorityList("ROLE_USER"); private boolean enabled = true; @@ -978,7 +944,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Specify the roles of the user to authenticate as. This method is similar to * {@link #authorities(GrantedAuthority...)}, but just not as flexible. - * * @param roles The roles to populate. Note that if the role does not start with * {@link #ROLE_PREFIX} it will automatically be prepended. This means by default * {@code roles("ROLE_USER")} and {@code roles("USER")} are equivalent. @@ -987,14 +952,11 @@ public final class SecurityMockMvcRequestPostProcessors { * @return the UserRequestPostProcessor for further customizations */ public UserRequestPostProcessor roles(String... roles) { - List authorities = new ArrayList<>( - roles.length); + List authorities = new ArrayList<>(roles.length); for (String role : roles) { if (role.startsWith(ROLE_PREFIX)) { - throw new IllegalArgumentException( - "Role should not start with " + ROLE_PREFIX - + " since this method automatically prefixes with this value. Got " - + role); + throw new IllegalArgumentException("Role should not start with " + ROLE_PREFIX + + " since this method automatically prefixes with this value. Got " + role); } else { authorities.add(new SimpleGrantedAuthority(ROLE_PREFIX + role)); @@ -1006,7 +968,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Populates the user's {@link GrantedAuthority}'s. The default is ROLE_USER. - * * @param authorities * @see #roles(String...) * @return the UserRequestPostProcessor for further customizations @@ -1017,20 +978,17 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Populates the user's {@link GrantedAuthority}'s. The default is ROLE_USER. - * * @param authorities * @see #roles(String...) * @return the UserRequestPostProcessor for further customizations */ - public UserRequestPostProcessor authorities( - Collection authorities) { + public UserRequestPostProcessor authorities(Collection authorities) { this.authorities = authorities; return this; } /** * Populates the user's password. The default is "password" - * * @param password the user's password * @return the UserRequestPostProcessor for further customizations */ @@ -1041,8 +999,7 @@ public final class SecurityMockMvcRequestPostProcessors { @Override public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { - UserDetailsRequestPostProcessor delegate = new UserDetailsRequestPostProcessor( - createUser()); + UserDetailsRequestPostProcessor delegate = new UserDetailsRequestPostProcessor(createUser()); return delegate.postProcessRequest(request); } @@ -1051,14 +1008,15 @@ public final class SecurityMockMvcRequestPostProcessors { * @return the {@link User} for the principal */ private User createUser() { - return new User(this.username, this.password, this.enabled, - this.accountNonExpired, this.credentialsNonExpired, - this.accountNonLocked, this.authorities); + return new User(this.username, this.password, this.enabled, this.accountNonExpired, + this.credentialsNonExpired, this.accountNonLocked, this.authorities); } + } - private static class AnonymousRequestPostProcessor extends - SecurityContextRequestPostProcessorSupport implements RequestPostProcessor { + private static class AnonymousRequestPostProcessor extends SecurityContextRequestPostProcessorSupport + implements RequestPostProcessor { + private AuthenticationRequestPostProcessor delegate = new AuthenticationRequestPostProcessor( new AnonymousAuthenticationToken("key", "anonymous", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"))); @@ -1073,9 +1031,11 @@ public final class SecurityMockMvcRequestPostProcessors { public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { return this.delegate.postProcessRequest(request); } + } private static class HttpBasicRequestPostProcessor implements RequestPostProcessor { + private String headerValue; private HttpBasicRequestPostProcessor(String username, String password) { @@ -1089,6 +1049,7 @@ public final class SecurityMockMvcRequestPostProcessors { request.addHeader("Authorization", this.headerValue); return request; } + } /** @@ -1097,32 +1058,32 @@ public final class SecurityMockMvcRequestPostProcessors { * @since 5.2 */ public final static class JwtRequestPostProcessor implements RequestPostProcessor { + private Jwt jwt; - private Converter> authoritiesConverter = - new JwtGrantedAuthoritiesConverter(); + + private Converter> authoritiesConverter = new JwtGrantedAuthoritiesConverter(); private JwtRequestPostProcessor() { - this.jwt((jwt) -> {}); + this.jwt((jwt) -> { + }); } /** - * Use the given {@link Jwt.Builder} {@link Consumer} to configure the underlying {@link Jwt} + * Use the given {@link Jwt.Builder} {@link Consumer} to configure the underlying + * {@link Jwt} * - * This method first creates a default {@link Jwt.Builder} instance with default values for - * the {@code alg}, {@code sub}, and {@code scope} claims. The {@link Consumer} can then modify - * these or provide additional configuration. - * - * Calling {@link SecurityMockMvcRequestPostProcessors#jwt()} is the equivalent of calling - * {@code SecurityMockMvcRequestPostProcessors.jwt().jwt(() -> {})}. + * This method first creates a default {@link Jwt.Builder} instance with default + * values for the {@code alg}, {@code sub}, and {@code scope} claims. The + * {@link Consumer} can then modify these or provide additional configuration. * + * Calling {@link SecurityMockMvcRequestPostProcessors#jwt()} is the equivalent of + * calling {@code SecurityMockMvcRequestPostProcessors.jwt().jwt(() -> {})}. * @param jwtBuilderConsumer For configuring the underlying {@link Jwt} * @return the {@link JwtRequestPostProcessor} for additional customization */ public JwtRequestPostProcessor jwt(Consumer jwtBuilderConsumer) { - Jwt.Builder jwtBuilder = Jwt.withTokenValue("token") - .header("alg", "none") - .claim(SUB, "user") - .claim("scope", "read"); + Jwt.Builder jwtBuilder = Jwt.withTokenValue("token").header("alg", "none").claim(SUB, "user").claim("scope", + "read"); jwtBuilderConsumer.accept(jwtBuilder); this.jwt = jwtBuilder.build(); return this; @@ -1130,7 +1091,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Use the given {@link Jwt} - * * @param jwt The {@link Jwt} to use * @return the {@link JwtRequestPostProcessor} for additional customization */ @@ -1164,9 +1124,8 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Provides the configured {@link Jwt} so that custom authorities can be derived * from it - * - * @param authoritiesConverter the conversion strategy from {@link Jwt} to a {@link Collection} - * of {@link GrantedAuthority}s + * @param authoritiesConverter the conversion strategy from {@link Jwt} to a + * {@link Collection} of {@link GrantedAuthority}s * @return the {@link JwtRequestPostProcessor} for further configuration */ public JwtRequestPostProcessor authorities(Converter> authoritiesConverter) { @@ -1190,17 +1149,20 @@ public final class SecurityMockMvcRequestPostProcessors { * @since 5.3 */ public final static class OpaqueTokenRequestPostProcessor implements RequestPostProcessor { + private Supplier> attributes = this::defaultAttributes; + private Supplier> authorities = this::defaultAuthorities; private Supplier principal = this::defaultPrincipal; - private OpaqueTokenRequestPostProcessor() { } + private OpaqueTokenRequestPostProcessor() { + } /** * Mutate the attributes using the given {@link Consumer} - * - * @param attributesConsumer The {@link Consumer} for mutating the {@Map} of attributes + * @param attributesConsumer The {@link Consumer} for mutating the {@Map} of + * attributes * @return the {@link OpaqueTokenRequestPostProcessor} for further configuration */ public OpaqueTokenRequestPostProcessor attributes(Consumer> attributesConsumer) { @@ -1254,8 +1216,8 @@ public final class SecurityMockMvcRequestPostProcessors { CsrfFilter.skipRequest(request); OAuth2AuthenticatedPrincipal principal = this.principal.get(); OAuth2AccessToken accessToken = getOAuth2AccessToken(principal); - BearerTokenAuthentication token = new BearerTokenAuthentication - (principal, accessToken, principal.getAuthorities()); + BearerTokenAuthentication token = new BearerTokenAuthentication(principal, accessToken, + principal.getAuthorities()); return new AuthenticationRequestPostProcessor(token).postProcessRequest(request); } @@ -1283,21 +1245,18 @@ public final class SecurityMockMvcRequestPostProcessors { } private OAuth2AuthenticatedPrincipal defaultPrincipal() { - return new OAuth2IntrospectionAuthenticatedPrincipal - (this.attributes.get(), this.authorities.get()); + return new OAuth2IntrospectionAuthenticatedPrincipal(this.attributes.get(), this.authorities.get()); } private Collection getAuthorities(Collection scopes) { - return scopes.stream() - .map(scope -> new SimpleGrantedAuthority("SCOPE_" + scope)) + return scopes.stream().map(scope -> new SimpleGrantedAuthority("SCOPE_" + scope)) .collect(Collectors.toList()); } private OAuth2AccessToken getOAuth2AccessToken(OAuth2AuthenticatedPrincipal principal) { Instant expiresAt = getInstant(principal.getAttributes(), "exp"); Instant issuedAt = getInstant(principal.getAttributes(), "iat"); - return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - "token", issuedAt, expiresAt); + return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token", issuedAt, expiresAt); } private Instant getInstant(Map attributes, String name) { @@ -1310,6 +1269,7 @@ public final class SecurityMockMvcRequestPostProcessors { } throw new IllegalArgumentException(name + " attribute must be of type Instant"); } + } /** @@ -1317,13 +1277,17 @@ public final class SecurityMockMvcRequestPostProcessors { * @since 5.3 */ public final static class OAuth2LoginRequestPostProcessor implements RequestPostProcessor { + private final String nameAttributeKey = "sub"; private ClientRegistration clientRegistration; + private OAuth2AccessToken accessToken; private Supplier> authorities = this::defaultAuthorities; + private Supplier> attributes = this::defaultAttributes; + private Supplier oauth2User = this::defaultPrincipal; private OAuth2LoginRequestPostProcessor(OAuth2AccessToken accessToken) { @@ -1333,7 +1297,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Use the provided authorities in the {@link Authentication} - * * @param authorities the authorities to use * @return the {@link OAuth2LoginRequestPostProcessor} for further configuration */ @@ -1346,7 +1309,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Use the provided authorities in the {@link Authentication} - * * @param authorities the authorities to use * @return the {@link OAuth2LoginRequestPostProcessor} for further configuration */ @@ -1359,8 +1321,8 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Mutate the attributes using the given {@link Consumer} - * - * @param attributesConsumer The {@link Consumer} for mutating the {@Map} of attributes + * @param attributesConsumer The {@link Consumer} for mutating the {@Map} of + * attributes * @return the {@link OAuth2LoginRequestPostProcessor} for further configuration */ public OAuth2LoginRequestPostProcessor attributes(Consumer> attributesConsumer) { @@ -1376,7 +1338,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Use the provided {@link OAuth2User} as the authenticated user. - * * @param oauth2User the {@link OAuth2User} to use * @return the {@link OAuth2LoginRequestPostProcessor} for further configuration */ @@ -1391,9 +1352,9 @@ public final class SecurityMockMvcRequestPostProcessors { * The supplied {@link ClientRegistration} will be registered into an * {@link HttpSessionOAuth2AuthorizedClientRepository}. Tests relying on * {@link org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient} - * annotations should register an {@link HttpSessionOAuth2AuthorizedClientRepository} bean - * to the application context. - * + * annotations should register an + * {@link HttpSessionOAuth2AuthorizedClientRepository} bean to the application + * context. * @param clientRegistration the {@link ClientRegistration} to use * @return the {@link OAuth2LoginRequestPostProcessor} for further configuration */ @@ -1405,22 +1366,17 @@ public final class SecurityMockMvcRequestPostProcessors { @Override public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { OAuth2User oauth2User = this.oauth2User.get(); - OAuth2AuthenticationToken token = new OAuth2AuthenticationToken - (oauth2User, oauth2User.getAuthorities(), this.clientRegistration.getRegistrationId()); + OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(oauth2User, oauth2User.getAuthorities(), + this.clientRegistration.getRegistrationId()); request = new AuthenticationRequestPostProcessor(token).postProcessRequest(request); - return new OAuth2ClientRequestPostProcessor() - .clientRegistration(this.clientRegistration) - .principalName(oauth2User.getName()) - .accessToken(this.accessToken) - .postProcessRequest(request); + return new OAuth2ClientRequestPostProcessor().clientRegistration(this.clientRegistration) + .principalName(oauth2User.getName()).accessToken(this.accessToken).postProcessRequest(request); } private ClientRegistration.Builder clientRegistrationBuilder() { - return ClientRegistration.withRegistrationId("test") - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .clientId("test-client") - .tokenUri("https://token-uri.example.org"); + return ClientRegistration.withRegistrationId("test").authorizationGrantType(AuthorizationGrantType.PASSWORD) + .clientId("test-client").tokenUri("https://token-uri.example.org"); } private Collection defaultAuthorities() { @@ -1441,6 +1397,7 @@ public final class SecurityMockMvcRequestPostProcessors { private OAuth2User defaultPrincipal() { return new DefaultOAuth2User(this.authorities.get(), this.attributes.get(), this.nameAttributeKey); } + } /** @@ -1448,11 +1405,17 @@ public final class SecurityMockMvcRequestPostProcessors { * @since 5.3 */ public final static class OidcLoginRequestPostProcessor implements RequestPostProcessor { + private ClientRegistration clientRegistration; + private OAuth2AccessToken accessToken; + private OidcIdToken idToken; + private OidcUserInfo userInfo; + private Supplier oidcUser = this::defaultPrincipal; + private Collection authorities; private OidcLoginRequestPostProcessor(OAuth2AccessToken accessToken) { @@ -1462,7 +1425,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Use the provided authorities in the {@link Authentication} - * * @param authorities the authorities to use * @return the {@link OidcLoginRequestPostProcessor} for further configuration */ @@ -1475,7 +1437,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Use the provided authorities in the {@link Authentication} - * * @param authorities the authorities to use * @return the {@link OidcLoginRequestPostProcessor} for further configuration */ @@ -1488,8 +1449,8 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Use the provided {@link OidcIdToken} when constructing the authenticated user - * - * @param idTokenBuilderConsumer a {@link Consumer} of a {@link OidcIdToken.Builder} + * @param idTokenBuilderConsumer a {@link Consumer} of a + * {@link OidcIdToken.Builder} * @return the {@link OidcLoginRequestPostProcessor} for further configuration */ public OidcLoginRequestPostProcessor idToken(Consumer idTokenBuilderConsumer) { @@ -1503,8 +1464,8 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Use the provided {@link OidcUserInfo} when constructing the authenticated user - * - * @param userInfoBuilderConsumer a {@link Consumer} of a {@link OidcUserInfo.Builder} + * @param userInfoBuilderConsumer a {@link Consumer} of a + * {@link OidcUserInfo.Builder} * @return the {@link OidcLoginRequestPostProcessor} for further configuration */ public OidcLoginRequestPostProcessor userInfoToken(Consumer userInfoBuilderConsumer) { @@ -1517,8 +1478,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Use the provided {@link OidcUser} as the authenticated user. - * - * * @param oidcUser the {@link OidcUser} to use * @return the {@link OidcLoginRequestPostProcessor} for further configuration */ @@ -1533,9 +1492,9 @@ public final class SecurityMockMvcRequestPostProcessors { * The supplied {@link ClientRegistration} will be registered into an * {@link HttpSessionOAuth2AuthorizedClientRepository}. Tests relying on * {@link org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient} - * annotations should register an {@link HttpSessionOAuth2AuthorizedClientRepository} bean - * to the application context. - * + * annotations should register an + * {@link HttpSessionOAuth2AuthorizedClientRepository} bean to the application + * context. * @param clientRegistration the {@link ClientRegistration} to use * @return the {@link OidcLoginRequestPostProcessor} for further configuration */ @@ -1547,17 +1506,13 @@ public final class SecurityMockMvcRequestPostProcessors { @Override public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { OidcUser oidcUser = this.oidcUser.get(); - return new OAuth2LoginRequestPostProcessor(this.accessToken) - .oauth2User(oidcUser) - .clientRegistration(this.clientRegistration) - .postProcessRequest(request); + return new OAuth2LoginRequestPostProcessor(this.accessToken).oauth2User(oidcUser) + .clientRegistration(this.clientRegistration).postProcessRequest(request); } private ClientRegistration.Builder clientRegistrationBuilder() { - return ClientRegistration.withRegistrationId("test") - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .clientId("test-client") - .tokenUri("https://token-uri.example.org"); + return ClientRegistration.withRegistrationId("test").authorizationGrantType(AuthorizationGrantType.PASSWORD) + .clientId("test-client").tokenUri("https://token-uri.example.org"); } private Collection getAuthorities() { @@ -1568,16 +1523,17 @@ public final class SecurityMockMvcRequestPostProcessors { authorities.add(new SimpleGrantedAuthority("SCOPE_" + authority)); } return authorities; - } else { + } + else { return this.authorities; } } private OidcIdToken getOidcIdToken() { if (this.idToken == null) { - return new OidcIdToken("id-token", null, null, - Collections.singletonMap(IdTokenClaimNames.SUB, "user")); - } else { + return new OidcIdToken("id-token", null, null, Collections.singletonMap(IdTokenClaimNames.SUB, "user")); + } + else { return this.idToken; } } @@ -1589,6 +1545,7 @@ public final class SecurityMockMvcRequestPostProcessors { private OidcUser defaultPrincipal() { return new DefaultOidcUser(getAuthorities(), getOidcIdToken(), this.userInfo); } + } /** @@ -1596,9 +1553,13 @@ public final class SecurityMockMvcRequestPostProcessors { * @since 5.3 */ public final static class OAuth2ClientRequestPostProcessor implements RequestPostProcessor { + private String registrationId = "test"; + private ClientRegistration clientRegistration; + private String principalName = "user"; + private OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", null, null, Collections.singleton("read")); @@ -1607,12 +1568,12 @@ public final class SecurityMockMvcRequestPostProcessors { private OAuth2ClientRequestPostProcessor(String registrationId) { this.registrationId = registrationId; - clientRegistration(c -> {}); + clientRegistration(c -> { + }); } /** * Use this {@link ClientRegistration} - * * @param clientRegistration * @return the {@link OAuth2ClientRequestPostProcessor} for further configuration */ @@ -1623,12 +1584,11 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Use this {@link Consumer} to configure a {@link ClientRegistration} - * * @param clientRegistrationConfigurer the {@link ClientRegistration} configurer * @return the {@link OAuth2ClientRequestPostProcessor} for further configuration */ - public OAuth2ClientRequestPostProcessor clientRegistration - (Consumer clientRegistrationConfigurer) { + public OAuth2ClientRequestPostProcessor clientRegistration( + Consumer clientRegistrationConfigurer) { ClientRegistration.Builder builder = clientRegistrationBuilder(); clientRegistrationConfigurer.accept(builder); @@ -1638,7 +1598,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Use this as the resource owner's principal name - * * @param principalName the resource owner's principal name * @return the {@link OAuth2ClientRequestPostProcessor} for further configuration */ @@ -1650,7 +1609,6 @@ public final class SecurityMockMvcRequestPostProcessors { /** * Use this {@link OAuth2AccessToken} - * * @param accessToken the {@link OAuth2AccessToken} to use * @return the {@link OAuth2ClientRequestPostProcessor} for further configuration */ @@ -1662,17 +1620,16 @@ public final class SecurityMockMvcRequestPostProcessors { @Override public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { if (this.clientRegistration == null) { - throw new IllegalArgumentException("Please specify a ClientRegistration via one " + - "of the clientRegistration methods"); + throw new IllegalArgumentException( + "Please specify a ClientRegistration via one " + "of the clientRegistration methods"); } - OAuth2AuthorizedClient client = new OAuth2AuthorizedClient - (this.clientRegistration, this.principalName, this.accessToken); + OAuth2AuthorizedClient client = new OAuth2AuthorizedClient(this.clientRegistration, this.principalName, + this.accessToken); OAuth2AuthorizedClientManager authorizationClientManager = OAuth2ClientServletTestUtils .getOAuth2AuthorizedClientManager(request); if (!(authorizationClientManager instanceof TestOAuth2AuthorizedClientManager)) { - authorizationClientManager = - new TestOAuth2AuthorizedClientManager(authorizationClientManager); + authorizationClientManager = new TestOAuth2AuthorizedClientManager(authorizationClientManager); OAuth2ClientServletTestUtils.setOAuth2AuthorizedClientManager(request, authorizationClientManager); } TestOAuth2AuthorizedClientManager.enable(request); @@ -1682,24 +1639,20 @@ public final class SecurityMockMvcRequestPostProcessors { private ClientRegistration.Builder clientRegistrationBuilder() { return ClientRegistration.withRegistrationId(this.registrationId) - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .clientId("test-client") - .clientSecret("test-secret") - .tokenUri("https://idp.example.org/oauth/token"); + .authorizationGrantType(AuthorizationGrantType.PASSWORD).clientId("test-client") + .clientSecret("test-secret").tokenUri("https://idp.example.org/oauth/token"); } /** - * Used to wrap the {@link OAuth2AuthorizedClientManager} to provide support for testing when the - * request is wrapped + * Used to wrap the {@link OAuth2AuthorizedClientManager} to provide support for + * testing when the request is wrapped */ - private static class TestOAuth2AuthorizedClientManager - implements OAuth2AuthorizedClientManager { + private static class TestOAuth2AuthorizedClientManager implements OAuth2AuthorizedClientManager { - final static String TOKEN_ATTR_NAME = TestOAuth2AuthorizedClientManager.class.getName() - .concat(".TOKEN"); + final static String TOKEN_ATTR_NAME = TestOAuth2AuthorizedClientManager.class.getName().concat(".TOKEN"); - final static String ENABLED_ATTR_NAME = TestOAuth2AuthorizedClientManager.class - .getName().concat(".ENABLED"); + final static String ENABLED_ATTR_NAME = TestOAuth2AuthorizedClientManager.class.getName() + .concat(".ENABLED"); private final OAuth2AuthorizedClientManager delegate; @@ -1709,11 +1662,11 @@ public final class SecurityMockMvcRequestPostProcessors { @Override public OAuth2AuthorizedClient authorize(OAuth2AuthorizeRequest authorizeRequest) { - HttpServletRequest request = - authorizeRequest.getAttribute(HttpServletRequest.class.getName()); + HttpServletRequest request = authorizeRequest.getAttribute(HttpServletRequest.class.getName()); if (isEnabled(request)) { return (OAuth2AuthorizedClient) request.getAttribute(TOKEN_ATTR_NAME); - } else { + } + else { return this.delegate.authorize(authorizeRequest); } } @@ -1725,43 +1678,44 @@ public final class SecurityMockMvcRequestPostProcessors { public boolean isEnabled(HttpServletRequest request) { return TRUE.equals(request.getAttribute(ENABLED_ATTR_NAME)); } + } private static class OAuth2ClientServletTestUtils { - private static final OAuth2AuthorizedClientRepository DEFAULT_CLIENT_REPO = - new HttpSessionOAuth2AuthorizedClientRepository(); + + private static final OAuth2AuthorizedClientRepository DEFAULT_CLIENT_REPO = new HttpSessionOAuth2AuthorizedClientRepository(); /** - * Gets the {@link OAuth2AuthorizedClientManager} for the specified {@link HttpServletRequest}. - * If one is not found, one based off of {@link HttpSessionOAuth2AuthorizedClientRepository} is used. - * + * Gets the {@link OAuth2AuthorizedClientManager} for the specified + * {@link HttpServletRequest}. If one is not found, one based off of + * {@link HttpSessionOAuth2AuthorizedClientRepository} is used. * @param request the {@link HttpServletRequest} to obtain the * {@link OAuth2AuthorizedClientManager} * @return the {@link OAuth2AuthorizedClientManager} for the specified * {@link HttpServletRequest} */ public static OAuth2AuthorizedClientManager getOAuth2AuthorizedClientManager(HttpServletRequest request) { - OAuth2AuthorizedClientArgumentResolver resolver = - findResolver(request, OAuth2AuthorizedClientArgumentResolver.class); + OAuth2AuthorizedClientArgumentResolver resolver = findResolver(request, + OAuth2AuthorizedClientArgumentResolver.class); if (resolver == null) { - return authorizeRequest -> DEFAULT_CLIENT_REPO.loadAuthorizedClient - (authorizeRequest.getClientRegistrationId(), authorizeRequest.getPrincipal(), request); + return authorizeRequest -> DEFAULT_CLIENT_REPO.loadAuthorizedClient( + authorizeRequest.getClientRegistrationId(), authorizeRequest.getPrincipal(), request); } - return (OAuth2AuthorizedClientManager) - ReflectionTestUtils.getField(resolver, "authorizedClientManager"); + return (OAuth2AuthorizedClientManager) ReflectionTestUtils.getField(resolver, + "authorizedClientManager"); } /** - * Sets the {@link OAuth2AuthorizedClientManager} for the specified {@link HttpServletRequest}. - * + * Sets the {@link OAuth2AuthorizedClientManager} for the specified + * {@link HttpServletRequest}. * @param request the {@link HttpServletRequest} to obtain the * {@link OAuth2AuthorizedClientManager} * @param manager the {@link OAuth2AuthorizedClientManager} to set */ public static void setOAuth2AuthorizedClientManager(HttpServletRequest request, OAuth2AuthorizedClientManager manager) { - OAuth2AuthorizedClientArgumentResolver resolver = - findResolver(request, OAuth2AuthorizedClientArgumentResolver.class); + OAuth2AuthorizedClientArgumentResolver resolver = findResolver(request, + OAuth2AuthorizedClientArgumentResolver.class); if (resolver == null) { return; } @@ -1771,14 +1725,15 @@ public final class SecurityMockMvcRequestPostProcessors { @SuppressWarnings("unchecked") static T findResolver(HttpServletRequest request, Class resolverClass) { - if (!ClassUtils.isPresent - ("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter", null)) { + if (!ClassUtils.isPresent( + "org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter", null)) { return null; } return WebMvcClasspathGuard.findResolver(request, resolverClass); } private static class WebMvcClasspathGuard { + static T findResolver(HttpServletRequest request, Class resolverClass) { ServletContext servletContext = request.getServletContext(); @@ -1798,9 +1753,9 @@ public final class SecurityMockMvcRequestPostProcessors { return null; } - private static RequestMappingHandlerAdapter getRequestMappingHandlerAdapter(ServletContext servletContext) { - WebApplicationContext context = WebApplicationContextUtils - .getWebApplicationContext(servletContext); + private static RequestMappingHandlerAdapter getRequestMappingHandlerAdapter( + ServletContext servletContext) { + WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext); if (context != null) { String[] names = context.getBeanNamesForType(RequestMappingHandlerAdapter.class); if (names.length > 0) { @@ -1809,13 +1764,17 @@ public final class SecurityMockMvcRequestPostProcessors { } return null; } + } private OAuth2ClientServletTestUtils() { } + } + } private SecurityMockMvcRequestPostProcessors() { } + } diff --git a/test/src/main/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchers.java b/test/src/main/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchers.java index a4f93652ac..6c09322364 100644 --- a/test/src/main/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchers.java +++ b/test/src/main/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchers.java @@ -46,7 +46,6 @@ public final class SecurityMockMvcResultMatchers { /** * {@link ResultMatcher} that verifies that a specified user is authenticated. - * * @return the {@link AuthenticatedMatcher} to use */ public static AuthenticatedMatcher authenticated() { @@ -55,23 +54,20 @@ public final class SecurityMockMvcResultMatchers { /** * {@link ResultMatcher} that verifies that no user is authenticated. - * * @return the {@link AuthenticatedMatcher} to use */ public static ResultMatcher unauthenticated() { return new UnAuthenticatedMatcher(); } - private static abstract class AuthenticationMatcher> - implements ResultMatcher { + private static abstract class AuthenticationMatcher> implements ResultMatcher { protected SecurityContext load(MvcResult result) { - HttpRequestResponseHolder holder = new HttpRequestResponseHolder( - result.getRequest(), result.getResponse()); - SecurityContextRepository repository = WebTestUtils - .getSecurityContextRepository(result.getRequest()); + HttpRequestResponseHolder holder = new HttpRequestResponseHolder(result.getRequest(), result.getResponse()); + SecurityContextRepository repository = WebTestUtils.getSecurityContextRepository(result.getRequest()); return repository.loadContext(holder); } + } /** @@ -81,14 +77,18 @@ public final class SecurityMockMvcResultMatchers { * @author Rob Winch * @since 4.0 */ - public static final class AuthenticatedMatcher - extends AuthenticationMatcher { + public static final class AuthenticatedMatcher extends AuthenticationMatcher { private SecurityContext expectedContext; + private Authentication expectedAuthentication; + private Object expectedAuthenticationPrincipal; + private String expectedAuthenticationName; + private Collection expectedGrantedAuthorities; + private Consumer assertAuthentication; @Override @@ -104,25 +104,20 @@ public final class SecurityMockMvcResultMatchers { } if (this.expectedContext != null) { - assertEquals(this.expectedContext + " does not equal " + context, - this.expectedContext, context); + assertEquals(this.expectedContext + " does not equal " + context, this.expectedContext, context); } if (this.expectedAuthentication != null) { - assertEquals( - this.expectedAuthentication + " does not equal " - + context.getAuthentication(), + assertEquals(this.expectedAuthentication + " does not equal " + context.getAuthentication(), this.expectedAuthentication, context.getAuthentication()); } if (this.expectedAuthenticationPrincipal != null) { - assertTrue("Authentication cannot be null", - context.getAuthentication() != null); + assertTrue("Authentication cannot be null", context.getAuthentication() != null); assertEquals( this.expectedAuthenticationPrincipal + " does not equal " + context.getAuthentication().getPrincipal(), - this.expectedAuthenticationPrincipal, - context.getAuthentication().getPrincipal()); + this.expectedAuthenticationPrincipal, context.getAuthentication().getPrincipal()); } if (this.expectedAuthenticationName != null) { @@ -134,14 +129,10 @@ public final class SecurityMockMvcResultMatchers { if (this.expectedGrantedAuthorities != null) { assertTrue("Authentication cannot be null", auth != null); - Collection authorities = auth - .getAuthorities(); - assertTrue( - authorities + " does not contain the same authorities as " - + this.expectedGrantedAuthorities, + Collection authorities = auth.getAuthorities(); + assertTrue(authorities + " does not contain the same authorities as " + this.expectedGrantedAuthorities, authorities.containsAll(this.expectedGrantedAuthorities)); - assertTrue(this.expectedGrantedAuthorities - + " does not contain the same authorities as " + authorities, + assertTrue(this.expectedGrantedAuthorities + " does not contain the same authorities as " + authorities, this.expectedGrantedAuthorities.containsAll(authorities)); } } @@ -158,7 +149,6 @@ public final class SecurityMockMvcResultMatchers { /** * Specifies the expected username - * * @param expected the expected username * @return the {@link AuthenticatedMatcher} for further customization */ @@ -168,7 +158,6 @@ public final class SecurityMockMvcResultMatchers { /** * Specifies the expected {@link SecurityContext} - * * @param expected the expected {@link SecurityContext} * @return the {@link AuthenticatedMatcher} for further customization */ @@ -179,7 +168,6 @@ public final class SecurityMockMvcResultMatchers { /** * Specifies the expected {@link Authentication} - * * @param expected the expected {@link Authentication} * @return the {@link AuthenticatedMatcher} for further customization */ @@ -190,7 +178,6 @@ public final class SecurityMockMvcResultMatchers { /** * Specifies the expected principal - * * @param expected the expected principal * @return the {@link AuthenticatedMatcher} for further customization */ @@ -201,7 +188,6 @@ public final class SecurityMockMvcResultMatchers { /** * Specifies the expected {@link Authentication#getName()} - * * @param expected the expected {@link Authentication#getName()} * @return the {@link AuthenticatedMatcher} for further customization */ @@ -212,19 +198,16 @@ public final class SecurityMockMvcResultMatchers { /** * Specifies the {@link Authentication#getAuthorities()} - * * @param expected the {@link Authentication#getAuthorities()} * @return the {@link AuthenticatedMatcher} for further customization */ - public AuthenticatedMatcher withAuthorities( - Collection expected) { + public AuthenticatedMatcher withAuthorities(Collection expected) { this.expectedGrantedAuthorities = expected; return this; } /** * Specifies the {@link Authentication#getAuthorities()} - * * @param roles the roles. Each value is automatically prefixed with "ROLE_" * @return the {@link AuthenticatedMatcher} for further customization */ @@ -238,6 +221,7 @@ public final class SecurityMockMvcResultMatchers { AuthenticatedMatcher() { } + } /** @@ -247,8 +231,8 @@ public final class SecurityMockMvcResultMatchers { * @author Rob Winch * @since 4.0 */ - private static final class UnAuthenticatedMatcher - extends AuthenticationMatcher { + private static final class UnAuthenticatedMatcher extends AuthenticationMatcher { + private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); @Override @@ -257,14 +241,15 @@ public final class SecurityMockMvcResultMatchers { Authentication authentication = context.getAuthentication(); assertTrue("Expected anonymous Authentication got " + context, - authentication == null - || this.trustResolver.isAnonymous(authentication)); + authentication == null || this.trustResolver.isAnonymous(authentication)); } private UnAuthenticatedMatcher() { } + } private SecurityMockMvcResultMatchers() { } + } diff --git a/test/src/main/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurer.java b/test/src/main/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurer.java index 41e0b9fcee..da9ee1dd6e 100644 --- a/test/src/main/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurer.java +++ b/test/src/main/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurer.java @@ -41,6 +41,7 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock * @since 4.0 */ final class SecurityMockMvcConfigurer extends MockMvcConfigurerAdapter { + private final DelegateFilter delegateFilter; /** @@ -64,25 +65,20 @@ final class SecurityMockMvcConfigurer extends MockMvcConfigurerAdapter { } @Override - public RequestPostProcessor beforeMockMvcCreated( - ConfigurableMockMvcBuilder builder, WebApplicationContext context) { + public RequestPostProcessor beforeMockMvcCreated(ConfigurableMockMvcBuilder builder, + WebApplicationContext context) { String securityBeanId = BeanIds.SPRING_SECURITY_FILTER_CHAIN; - if (getSpringSecurityFilterChain() == null - && context.containsBean(securityBeanId)) { - setSpringSecurityFitlerChain(context.getBean(securityBeanId, - Filter.class)); + if (getSpringSecurityFilterChain() == null && context.containsBean(securityBeanId)) { + setSpringSecurityFitlerChain(context.getBean(securityBeanId, Filter.class)); } if (getSpringSecurityFilterChain() == null) { - throw new IllegalStateException( - "springSecurityFilterChain cannot be null. Ensure a Bean with the name " - + securityBeanId - + " implementing Filter is present or inject the Filter to be used."); + throw new IllegalStateException("springSecurityFilterChain cannot be null. Ensure a Bean with the name " + + securityBeanId + " implementing Filter is present or inject the Filter to be used."); } // This is used by other test support to obtain the FilterChainProxy - context.getServletContext().setAttribute(BeanIds.SPRING_SECURITY_FILTER_CHAIN, - getSpringSecurityFilterChain()); + context.getServletContext().setAttribute(BeanIds.SPRING_SECURITY_FILTER_CHAIN, getSpringSecurityFilterChain()); return testSecurityContext(); } @@ -96,11 +92,13 @@ final class SecurityMockMvcConfigurer extends MockMvcConfigurerAdapter { } /** - * Allows adding in {@link #afterConfigurerAdded(ConfigurableMockMvcBuilder)} to preserve Filter order and then - * lazily set the delegate in {@link #beforeMockMvcCreated(ConfigurableMockMvcBuilder, WebApplicationContext)}. + * Allows adding in {@link #afterConfigurerAdded(ConfigurableMockMvcBuilder)} to + * preserve Filter order and then lazily set the delegate in + * {@link #beforeMockMvcCreated(ConfigurableMockMvcBuilder, WebApplicationContext)}. * - * {@link org.springframework.web.filter.DelegatingFilterProxy} is not used because it is not easy to lazily set - * the delegate or get the delegate which is necessary for the test infrastructure. + * {@link org.springframework.web.filter.DelegatingFilterProxy} is not used because it + * is not easy to lazily set the delegate or get the delegate which is necessary for + * the test infrastructure. */ static class DelegateFilter implements Filter { @@ -120,9 +118,9 @@ final class SecurityMockMvcConfigurer extends MockMvcConfigurerAdapter { Filter getDelegate() { Filter result = this.delegate; if (result == null) { - throw new IllegalStateException("delegate cannot be null. Ensure a Bean with the name " - + BeanIds.SPRING_SECURITY_FILTER_CHAIN - + " implementing Filter is present or inject the Filter to be used."); + throw new IllegalStateException( + "delegate cannot be null. Ensure a Bean with the name " + BeanIds.SPRING_SECURITY_FILTER_CHAIN + + " implementing Filter is present or inject the Filter to be used."); } return result; } @@ -157,5 +155,7 @@ final class SecurityMockMvcConfigurer extends MockMvcConfigurerAdapter { public String toString() { return getDelegate().toString(); } + } + } diff --git a/test/src/main/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurers.java b/test/src/main/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurers.java index 9145c57e90..0f4f748e32 100644 --- a/test/src/main/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurers.java +++ b/test/src/main/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurers.java @@ -28,6 +28,7 @@ import javax.servlet.Filter; * @author Rob Winch */ public final class SecurityMockMvcConfigurers { + /** * Configures the MockMvcBuilder for use with Spring Security. Specifically the * configurer adds the Spring Bean named "springSecurityFilterChain" as a Filter. It @@ -35,7 +36,6 @@ public final class SecurityMockMvcConfigurers { * by applying * {@link org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors#testSecurityContext()} * . - * * @return the {@link org.springframework.test.web.servlet.setup.MockMvcConfigurer} to * use */ @@ -49,15 +49,13 @@ public final class SecurityMockMvcConfigurers { * TestSecurityContextHolder is leveraged for each request by applying * {@link org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors#testSecurityContext()} * . - * * @param springSecurityFilterChain the Filter to be added - * * @return the {@link org.springframework.test.web.servlet.setup.MockMvcConfigurer} to * use */ public static MockMvcConfigurer springSecurity(Filter springSecurityFilterChain) { - Assert.notNull(springSecurityFilterChain, - "springSecurityFilterChain cannot be null"); + Assert.notNull(springSecurityFilterChain, "springSecurityFilterChain cannot be null"); return new SecurityMockMvcConfigurer(springSecurityFilterChain); } + } diff --git a/test/src/main/java/org/springframework/security/test/web/support/WebTestUtils.java b/test/src/main/java/org/springframework/security/test/web/support/WebTestUtils.java index 98294cd08a..6c2c7c0613 100644 --- a/test/src/main/java/org/springframework/security/test/web/support/WebTestUtils.java +++ b/test/src/main/java/org/springframework/security/test/web/support/WebTestUtils.java @@ -41,23 +41,22 @@ import org.springframework.web.context.support.WebApplicationContextUtils; * @since 4.0 */ public abstract class WebTestUtils { + private static final SecurityContextRepository DEFAULT_CONTEXT_REPO = new HttpSessionSecurityContextRepository(); + private static final CsrfTokenRepository DEFAULT_TOKEN_REPO = new HttpSessionCsrfTokenRepository(); /** * Gets the {@link SecurityContextRepository} for the specified * {@link HttpServletRequest}. If one is not found, a default * {@link HttpSessionSecurityContextRepository} is used. - * * @param request the {@link HttpServletRequest} to obtain the * {@link SecurityContextRepository} * @return the {@link SecurityContextRepository} for the specified * {@link HttpServletRequest} */ - public static SecurityContextRepository getSecurityContextRepository( - HttpServletRequest request) { - SecurityContextPersistenceFilter filter = findFilter(request, - SecurityContextPersistenceFilter.class); + public static SecurityContextRepository getSecurityContextRepository(HttpServletRequest request) { + SecurityContextPersistenceFilter filter = findFilter(request, SecurityContextPersistenceFilter.class); if (filter == null) { return DEFAULT_CONTEXT_REPO; } @@ -67,15 +66,13 @@ public abstract class WebTestUtils { /** * Sets the {@link SecurityContextRepository} for the specified * {@link HttpServletRequest}. - * * @param request the {@link HttpServletRequest} to obtain the * {@link SecurityContextRepository} * @param securityContextRepository the {@link SecurityContextRepository} to set */ public static void setSecurityContextRepository(HttpServletRequest request, SecurityContextRepository securityContextRepository) { - SecurityContextPersistenceFilter filter = findFilter(request, - SecurityContextPersistenceFilter.class); + SecurityContextPersistenceFilter filter = findFilter(request, SecurityContextPersistenceFilter.class); if (filter != null) { ReflectionTestUtils.setField(filter, "repo", securityContextRepository); } @@ -84,7 +81,6 @@ public abstract class WebTestUtils { /** * Gets the {@link CsrfTokenRepository} for the specified {@link HttpServletRequest}. * If one is not found, the default {@link HttpSessionCsrfTokenRepository} is used. - * * @param request the {@link HttpServletRequest} to obtain the * {@link CsrfTokenRepository} * @return the {@link CsrfTokenRepository} for the specified @@ -95,19 +91,16 @@ public abstract class WebTestUtils { if (filter == null) { return DEFAULT_TOKEN_REPO; } - return (CsrfTokenRepository) ReflectionTestUtils.getField(filter, - "tokenRepository"); + return (CsrfTokenRepository) ReflectionTestUtils.getField(filter, "tokenRepository"); } /** * Sets the {@link CsrfTokenRepository} for the specified {@link HttpServletRequest}. - * * @param request the {@link HttpServletRequest} to obtain the * {@link CsrfTokenRepository} * @param repository the {@link CsrfTokenRepository} to set */ - public static void setCsrfTokenRepository(HttpServletRequest request, - CsrfTokenRepository repository) { + public static void setCsrfTokenRepository(HttpServletRequest request, CsrfTokenRepository repository) { CsrfFilter filter = findFilter(request, CsrfFilter.class); if (filter != null) { ReflectionTestUtils.setField(filter, "tokenRepository", repository); @@ -115,15 +108,13 @@ public abstract class WebTestUtils { } @SuppressWarnings("unchecked") - static T findFilter(HttpServletRequest request, - Class filterClass) { + static T findFilter(HttpServletRequest request, Class filterClass) { ServletContext servletContext = request.getServletContext(); Filter springSecurityFilterChain = getSpringSecurityFilterChain(servletContext); if (springSecurityFilterChain == null) { return null; } - List filters = ReflectionTestUtils - .invokeMethod(springSecurityFilterChain, "getFilters", request); + List filters = ReflectionTestUtils.invokeMethod(springSecurityFilterChain, "getFilters", request); if (filters == null) { return null; } @@ -136,8 +127,7 @@ public abstract class WebTestUtils { } private static Filter getSpringSecurityFilterChain(ServletContext servletContext) { - Filter result = (Filter) servletContext - .getAttribute(BeanIds.SPRING_SECURITY_FILTER_CHAIN); + Filter result = (Filter) servletContext.getAttribute(BeanIds.SPRING_SECURITY_FILTER_CHAIN); if (result != null) { return result; } @@ -145,8 +135,7 @@ public abstract class WebTestUtils { .getWebApplicationContext(servletContext); if (webApplicationContext != null) { try { - return webApplicationContext.getBean( - AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME, + return webApplicationContext.getBean(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME, Filter.class); } catch (NoSuchBeanDefinitionException notFound) { @@ -157,4 +146,5 @@ public abstract class WebTestUtils { private WebTestUtils() { } + } diff --git a/test/src/test/java/org/springframework/security/test/context/TestSecurityContextHolderTests.java b/test/src/test/java/org/springframework/security/test/context/TestSecurityContextHolderTests.java index a15f9ed5c2..515b02558b 100644 --- a/test/src/test/java/org/springframework/security/test/context/TestSecurityContextHolderTests.java +++ b/test/src/test/java/org/springframework/security/test/context/TestSecurityContextHolderTests.java @@ -72,4 +72,5 @@ public class TestSecurityContextHolderTests { assertThat(TestSecurityContextHolder.getContext().getAuthentication()).isSameAs(authentication); } + } diff --git a/test/src/test/java/org/springframework/security/test/context/annotation/SecurityTestExecutionListenerTests.java b/test/src/test/java/org/springframework/security/test/context/annotation/SecurityTestExecutionListenerTests.java index 0e378b6346..8c46563128 100644 --- a/test/src/test/java/org/springframework/security/test/context/annotation/SecurityTestExecutionListenerTests.java +++ b/test/src/test/java/org/springframework/security/test/context/annotation/SecurityTestExecutionListenerTests.java @@ -39,16 +39,13 @@ public class SecurityTestExecutionListenerTests { assertThat(SecurityContextHolder.getContext().getAuthentication().getName()).isEqualTo("user"); } - @WithMockUser @Test public void reactorContextTestSecurityContextHolderExecutionListenerTestIsRegistered() { - Mono name = ReactiveSecurityContextHolder.getContext() - .map(SecurityContext::getAuthentication) - .map(Principal::getName); + Mono name = ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication) + .map(Principal::getName); - StepVerifier.create(name) - .expectNext("user") - .verifyComplete(); + StepVerifier.create(name).expectNext("user").verifyComplete(); } + } diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/CustomUserDetails.java b/test/src/test/java/org/springframework/security/test/context/showcase/CustomUserDetails.java index 6300d5a883..f0857d1d20 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/CustomUserDetails.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/CustomUserDetails.java @@ -25,8 +25,11 @@ import java.util.Collection; * @author Rob Winch */ public class CustomUserDetails implements UserDetails { + private final String name; + private final String username; + private final Collection authorities; public CustomUserDetails(String name, String username) { @@ -67,4 +70,5 @@ public class CustomUserDetails implements UserDetails { public String toString() { return "CustomUserDetails{" + "username='" + username + '\'' + '}'; } + } \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockCustomUser.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockCustomUser.java index 73058bc2c4..935f7954f7 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockCustomUser.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockCustomUser.java @@ -22,6 +22,7 @@ import org.springframework.security.test.context.support.WithSecurityContext; */ @WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class) public @interface WithMockCustomUser { + /** * The username to be used. The default is rob * @return @@ -33,7 +34,6 @@ public @interface WithMockCustomUser { * {@link org.springframework.security.core.GrantedAuthority} will be created for each * value within roles. Each value in roles will automatically be prefixed with * "ROLE_". For example, the default will result in "ROLE_USER" being used. - * * @return */ String[] roles() default { "USER" }; @@ -43,4 +43,5 @@ public @interface WithMockCustomUser { * @return */ String name() default "Rob Winch"; + } diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockCustomUserSecurityContextFactory.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockCustomUserSecurityContextFactory.java index 67d0b28453..0a829c8039 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockCustomUserSecurityContextFactory.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockCustomUserSecurityContextFactory.java @@ -24,16 +24,16 @@ import org.springframework.security.test.context.support.WithSecurityContextFact /** * @author Rob Winch */ -public class WithMockCustomUserSecurityContextFactory implements - WithSecurityContextFactory { +public class WithMockCustomUserSecurityContextFactory implements WithSecurityContextFactory { + public SecurityContext createSecurityContext(WithMockCustomUser customUser) { SecurityContext context = SecurityContextHolder.createEmptyContext(); - CustomUserDetails principal = new CustomUserDetails(customUser.name(), - customUser.username()); - Authentication auth = new UsernamePasswordAuthenticationToken(principal, - "password", principal.getAuthorities()); + CustomUserDetails principal = new CustomUserDetails(customUser.name(), customUser.username()); + Authentication auth = new UsernamePasswordAuthenticationToken(principal, "password", + principal.getAuthorities()); context.setAuthentication(auth); return context; } + } diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserParentTests.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserParentTests.java index a15edc44d6..431f2b41fd 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserParentTests.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserParentTests.java @@ -48,6 +48,7 @@ public class WithMockUserParentTests extends WithMockUserParent { @EnableGlobalMethodSecurity(prePostEnabled = true) @ComponentScan(basePackageClasses = HelloMessageService.class) static class Config { + @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -56,5 +57,7 @@ public class WithMockUserParentTests extends WithMockUserParent { .withUser("user").password("password").roles("USER"); // @formatter:on } + } + } \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java index a525f310b5..b0c060c9cd 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithMockUserTests.java @@ -37,6 +37,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = WithMockUserTests.Config.class) public class WithMockUserTests { + @Autowired private MessageService messageService; @@ -63,8 +64,7 @@ public class WithMockUserTests { @WithMockUser(username = "admin", roles = { "USER", "ADMIN" }) public void getMessageWithMockUserCustomUser() { String message = messageService.getMessage(); - assertThat(message).contains("admin").contains("ROLE_USER") - .contains("ROLE_ADMIN"); + assertThat(message).contains("admin").contains("ROLE_USER").contains("ROLE_ADMIN"); } @Test @@ -77,6 +77,7 @@ public class WithMockUserTests { @EnableGlobalMethodSecurity(prePostEnabled = true) @ComponentScan(basePackageClasses = HelloMessageService.class) static class Config { + @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -85,5 +86,7 @@ public class WithMockUserTests { .withUser("user").password("password").roles("USER"); // @formatter:on } + } + } \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java index 8143f4f01a..4f2b36d35a 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java @@ -42,6 +42,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = WithUserDetailsTests.Config.class) public class WithUserDetailsTests { + @Autowired private MessageService messageService; @@ -67,7 +68,7 @@ public class WithUserDetailsTests { } @Test - @WithUserDetails(value="customUsername", userDetailsServiceBeanName="myUserDetailsService") + @WithUserDetails(value = "customUsername", userDetailsServiceBeanName = "myUserDetailsService") public void getMessageWithUserDetailsServiceBeanName() { String message = messageService.getMessage(); assertThat(message).contains("customUsername"); @@ -77,6 +78,7 @@ public class WithUserDetailsTests { @EnableGlobalMethodSecurity(prePostEnabled = true) @ComponentScan(basePackageClasses = HelloMessageService.class) static class Config { + @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off @@ -89,6 +91,7 @@ public class WithUserDetailsTests { public UserDetailsService myUserDetailsService() { return new CustomUserDetailsService(); } + } private Object getPrincipal() { @@ -97,9 +100,10 @@ public class WithUserDetailsTests { static class CustomUserDetailsService implements UserDetailsService { - public UserDetails loadUserByUsername(final String username) - throws UsernameNotFoundException { + public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException { return new CustomUserDetails("name", username); } + } + } diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/service/HelloMessageService.java b/test/src/test/java/org/springframework/security/test/context/showcase/service/HelloMessageService.java index 79c23e6a0a..93fc0048e1 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/service/HelloMessageService.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/service/HelloMessageService.java @@ -28,8 +28,8 @@ public class HelloMessageService implements MessageService { @PreAuthorize("authenticated") public String getMessage() { - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); return "Hello " + authentication; } + } diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/service/MessageService.java b/test/src/test/java/org/springframework/security/test/context/showcase/service/MessageService.java index 4a78e2c546..ce83abda47 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/service/MessageService.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/service/MessageService.java @@ -19,5 +19,7 @@ package org.springframework.security.test.context.showcase.service; * @author Rob Winch */ public interface MessageService { + String getMessage(); + } diff --git a/test/src/test/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListenerTests.java b/test/src/test/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListenerTests.java index 9a47499de7..efb491b1db 100644 --- a/test/src/test/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListenerTests.java +++ b/test/src/test/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListenerTests.java @@ -49,8 +49,7 @@ public class ReactorContextTestExecutionListenerTests { @Mock private TestContext testContext; - private ReactorContextTestExecutionListener listener = - new ReactorContextTestExecutionListener(); + private ReactorContextTestExecutionListener listener = new ReactorContextTestExecutionListener(); @After public void cleanup() { @@ -62,11 +61,9 @@ public class ReactorContextTestExecutionListenerTests { public void beforeTestMethodWhenSecurityContextEmptyThenReactorContextNull() throws Exception { this.listener.beforeTestMethod(this.testContext); - Mono result = ReactiveSecurityContextHolder - .getContext(); + Mono result = ReactiveSecurityContextHolder.getContext(); - StepVerifier.create(result) - .verifyComplete(); + StepVerifier.create(result).verifyComplete(); } @Test @@ -75,16 +72,15 @@ public class ReactorContextTestExecutionListenerTests { this.listener.beforeTestMethod(this.testContext); - Mono result = ReactiveSecurityContextHolder - .getContext(); + Mono result = ReactiveSecurityContextHolder.getContext(); - StepVerifier.create(result) - .verifyComplete(); + StepVerifier.create(result).verifyComplete(); } @Test public void beforeTestMethodWhenAuthenticationThenReactorContextHasAuthentication() throws Exception { - TestingAuthenticationToken expectedAuthentication = new TestingAuthenticationToken("user", "password", "ROLE_USER"); + TestingAuthenticationToken expectedAuthentication = new TestingAuthenticationToken("user", "password", + "ROLE_USER"); TestSecurityContextHolder.setAuthentication(expectedAuthentication); this.listener.beforeTestMethod(this.testContext); @@ -94,7 +90,8 @@ public class ReactorContextTestExecutionListenerTests { @Test public void beforeTestMethodWhenCustomContext() throws Exception { - TestingAuthenticationToken expectedAuthentication = new TestingAuthenticationToken("user", "password", "ROLE_USER"); + TestingAuthenticationToken expectedAuthentication = new TestingAuthenticationToken("user", "password", + "ROLE_USER"); SecurityContext context = new CustomContext(expectedAuthentication); TestSecurityContextHolder.setContext(context); @@ -104,6 +101,7 @@ public class ReactorContextTestExecutionListenerTests { } static class CustomContext implements SecurityContext { + private Authentication authentication; CustomContext(Authentication authentication) { @@ -119,43 +117,42 @@ public class ReactorContextTestExecutionListenerTests { public void setAuthentication(Authentication authentication) { this.authentication = authentication; } + } @Test - public void beforeTestMethodWhenExistingAuthenticationThenReactorContextHasOriginalAuthentication() throws Exception { - TestingAuthenticationToken expectedAuthentication = new TestingAuthenticationToken("user", "password", "ROLE_USER"); - TestingAuthenticationToken contextHolder = new TestingAuthenticationToken("contextHolder", "password", "ROLE_USER"); + public void beforeTestMethodWhenExistingAuthenticationThenReactorContextHasOriginalAuthentication() + throws Exception { + TestingAuthenticationToken expectedAuthentication = new TestingAuthenticationToken("user", "password", + "ROLE_USER"); + TestingAuthenticationToken contextHolder = new TestingAuthenticationToken("contextHolder", "password", + "ROLE_USER"); TestSecurityContextHolder.setAuthentication(contextHolder); this.listener.beforeTestMethod(this.testContext); Mono authentication = Mono.just("any") - .flatMap(s -> ReactiveSecurityContextHolder.getContext() - .map(SecurityContext::getAuthentication) - ) - .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(expectedAuthentication)); + .flatMap(s -> ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication)) + .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(expectedAuthentication)); - StepVerifier.create(authentication) - .expectNext(expectedAuthentication) - .verifyComplete(); + StepVerifier.create(authentication).expectNext(expectedAuthentication).verifyComplete(); } @Test public void beforeTestMethodWhenClearThenReactorContextDoesNotOverride() throws Exception { - TestingAuthenticationToken expectedAuthentication = new TestingAuthenticationToken("user", "password", "ROLE_USER"); - TestingAuthenticationToken contextHolder = new TestingAuthenticationToken("contextHolder", "password", "ROLE_USER"); + TestingAuthenticationToken expectedAuthentication = new TestingAuthenticationToken("user", "password", + "ROLE_USER"); + TestingAuthenticationToken contextHolder = new TestingAuthenticationToken("contextHolder", "password", + "ROLE_USER"); TestSecurityContextHolder.setAuthentication(contextHolder); this.listener.beforeTestMethod(this.testContext); Mono authentication = Mono.just("any") - .flatMap(s -> ReactiveSecurityContextHolder.getContext() - .map(SecurityContext::getAuthentication) - ) - .subscriberContext(ReactiveSecurityContextHolder.clearContext()); + .flatMap(s -> ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication)) + .subscriberContext(ReactiveSecurityContextHolder.clearContext()); - StepVerifier.create(authentication) - .verifyComplete(); + StepVerifier.create(authentication).verifyComplete(); } @Test @@ -194,32 +191,28 @@ public class ReactorContextTestExecutionListenerTests { } @Test - public void checkSecurityContextResolutionWhenSubscribedContextCalledOnTheDifferentThreadThanWithSecurityContextTestExecutionListener() throws Exception { - TestingAuthenticationToken contextHolder = new TestingAuthenticationToken("contextHolder", "password", "ROLE_USER"); + public void checkSecurityContextResolutionWhenSubscribedContextCalledOnTheDifferentThreadThanWithSecurityContextTestExecutionListener() + throws Exception { + TestingAuthenticationToken contextHolder = new TestingAuthenticationToken("contextHolder", "password", + "ROLE_USER"); TestSecurityContextHolder.setAuthentication(contextHolder); this.listener.beforeTestMethod(this.testContext); - ForkJoinPool.commonPool() - .submit(() -> assertAuthentication(contextHolder)) - .join(); + ForkJoinPool.commonPool().submit(() -> assertAuthentication(contextHolder)).join(); } public void assertAuthentication(Authentication expected) { Mono authentication = ReactiveSecurityContextHolder.getContext() - .map(SecurityContext::getAuthentication); + .map(SecurityContext::getAuthentication); - StepVerifier.create(authentication) - .expectNext(expected) - .verifyComplete(); + StepVerifier.create(authentication).expectNext(expected).verifyComplete(); } - private void assertSecurityContext(SecurityContext expected) { Mono securityContext = ReactiveSecurityContextHolder.getContext(); - StepVerifier.create(securityContext) - .expectNext(expected) - .verifyComplete(); + StepVerifier.create(securityContext).expectNext(expected).verifyComplete(); } + } diff --git a/test/src/test/java/org/springframework/security/test/context/support/WithAnonymousUserTests.java b/test/src/test/java/org/springframework/security/test/context/support/WithAnonymousUserTests.java index 838becec27..1092a0973b 100644 --- a/test/src/test/java/org/springframework/security/test/context/support/WithAnonymousUserTests.java +++ b/test/src/test/java/org/springframework/security/test/context/support/WithAnonymousUserTests.java @@ -26,22 +26,23 @@ import static org.assertj.core.api.Assertions.assertThat; * @since 5.0 */ public class WithAnonymousUserTests { + @Test public void defaults() { WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(Annotated.class, - WithSecurityContext.class); + WithSecurityContext.class); assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_METHOD); } @WithAnonymousUser private class Annotated { + } @Test public void findMergedAnnotationWhenSetupExplicitThenOverridden() { - WithSecurityContext context = AnnotatedElementUtils - .findMergedAnnotation(SetupExplicit.class, + WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(SetupExplicit.class, WithSecurityContext.class); assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_METHOD); @@ -49,17 +50,20 @@ public class WithAnonymousUserTests { @WithAnonymousUser(setupBefore = TestExecutionEvent.TEST_METHOD) private class SetupExplicit { + } @Test public void findMergedAnnotationWhenSetupOverriddenThenOverridden() { WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(SetupOverridden.class, - WithSecurityContext.class); + WithSecurityContext.class); assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_EXECUTION); } @WithAnonymousUser(setupBefore = TestExecutionEvent.TEST_EXECUTION) private class SetupOverridden { + } + } diff --git a/test/src/test/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactoryTests.java b/test/src/test/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactoryTests.java index a129baeece..6899c89aa6 100644 --- a/test/src/test/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactoryTests.java +++ b/test/src/test/java/org/springframework/security/test/context/support/WithMockUserSecurityContextFactoryTests.java @@ -49,8 +49,7 @@ public class WithMockUserSecurityContextFactoryTests { when(withUser.roles()).thenReturn(new String[] { "USER" }); when(withUser.authorities()).thenReturn(new String[] {}); - assertThat(factory.createSecurityContext(withUser).getAuthentication().getName()) - .isEqualTo(withUser.value()); + assertThat(factory.createSecurityContext(withUser).getAuthentication().getName()).isEqualTo(withUser.value()); } @Test @@ -71,10 +70,8 @@ public class WithMockUserSecurityContextFactoryTests { when(withUser.roles()).thenReturn(new String[] { "USER", "CUSTOM" }); when(withUser.authorities()).thenReturn(new String[] {}); - assertThat( - factory.createSecurityContext(withUser).getAuthentication() - .getAuthorities()).extracting("authority").containsOnly( - "ROLE_USER", "ROLE_CUSTOM"); + assertThat(factory.createSecurityContext(withUser).getAuthentication().getAuthorities()).extracting("authority") + .containsOnly("ROLE_USER", "ROLE_CUSTOM"); } @Test @@ -84,10 +81,8 @@ public class WithMockUserSecurityContextFactoryTests { when(withUser.roles()).thenReturn(new String[] { "USER" }); when(withUser.authorities()).thenReturn(new String[] { "USER", "CUSTOM" }); - assertThat( - factory.createSecurityContext(withUser).getAuthentication() - .getAuthorities()).extracting("authority").containsOnly( - "USER", "CUSTOM"); + assertThat(factory.createSecurityContext(withUser).getAuthentication().getAuthorities()).extracting("authority") + .containsOnly("USER", "CUSTOM"); } @Test(expected = IllegalStateException.class) @@ -107,4 +102,5 @@ public class WithMockUserSecurityContextFactoryTests { factory.createSecurityContext(withUser); } + } diff --git a/test/src/test/java/org/springframework/security/test/context/support/WithMockUserTests.java b/test/src/test/java/org/springframework/security/test/context/support/WithMockUserTests.java index ed040a3caf..c60eaead3b 100644 --- a/test/src/test/java/org/springframework/security/test/context/support/WithMockUserTests.java +++ b/test/src/test/java/org/springframework/security/test/context/support/WithMockUserTests.java @@ -25,8 +25,7 @@ public class WithMockUserTests { @Test public void defaults() { - WithMockUser mockUser = AnnotatedElementUtils.findMergedAnnotation(Annotated.class, - WithMockUser.class); + WithMockUser mockUser = AnnotatedElementUtils.findMergedAnnotation(Annotated.class, WithMockUser.class); assertThat(mockUser.value()).isEqualTo("user"); assertThat(mockUser.username()).isEmpty(); assertThat(mockUser.password()).isEqualTo("password"); @@ -34,19 +33,19 @@ public class WithMockUserTests { assertThat(mockUser.setupBefore()).isEqualByComparingTo(TestExecutionEvent.TEST_METHOD); WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(Annotated.class, - WithSecurityContext.class); + WithSecurityContext.class); assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_METHOD); } @WithMockUser private class Annotated { + } @Test public void findMergedAnnotationWhenSetupExplicitThenOverridden() { - WithSecurityContext context = AnnotatedElementUtils - .findMergedAnnotation(SetupExplicit.class, + WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(SetupExplicit.class, WithSecurityContext.class); assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_METHOD); @@ -54,17 +53,20 @@ public class WithMockUserTests { @WithMockUser(setupBefore = TestExecutionEvent.TEST_METHOD) private class SetupExplicit { + } @Test public void findMergedAnnotationWhenSetupOverriddenThenOverridden() { WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(SetupOverridden.class, - WithSecurityContext.class); + WithSecurityContext.class); assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_EXECUTION); } @WithMockUser(setupBefore = TestExecutionEvent.TEST_EXECUTION) private class SetupOverridden { + } + } diff --git a/test/src/test/java/org/springframework/security/test/context/support/WithSecurityContextTestExcecutionListenerTests.java b/test/src/test/java/org/springframework/security/test/context/support/WithSecurityContextTestExcecutionListenerTests.java index c44e3e2a36..da8b1884f1 100644 --- a/test/src/test/java/org/springframework/security/test/context/support/WithSecurityContextTestExcecutionListenerTests.java +++ b/test/src/test/java/org/springframework/security/test/context/support/WithSecurityContextTestExcecutionListenerTests.java @@ -50,6 +50,7 @@ import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class WithSecurityContextTestExcecutionListenerTests { + private ConfigurableApplicationContext context; @Mock @@ -76,8 +77,7 @@ public class WithSecurityContextTestExcecutionListenerTests { public void beforeTestMethodNullSecurityContextNoError() throws Exception { Class testClass = FakeTest.class; when(testContext.getTestClass()).thenReturn(testClass); - when(testContext.getTestMethod()).thenReturn( - ReflectionUtils.findMethod(testClass, "testNoAnnotation")); + when(testContext.getTestMethod()).thenReturn(ReflectionUtils.findMethod(testClass, "testNoAnnotation")); listener.beforeTestMethod(testContext); } @@ -87,14 +87,13 @@ public class WithSecurityContextTestExcecutionListenerTests { public void beforeTestMethodNoApplicationContext() throws Exception { Class testClass = FakeTest.class; when(testContext.getApplicationContext()).thenThrow(new IllegalStateException()); - when(testContext.getTestMethod()).thenReturn( - ReflectionUtils.findMethod(testClass, "testWithMockUser")); + when(testContext.getTestMethod()).thenReturn(ReflectionUtils.findMethod(testClass, "testWithMockUser")); listener.beforeTestMethod(testContext); - assertThat(TestSecurityContextHolder.getContext().getAuthentication().getName()) - .isEqualTo("user"); + assertThat(TestSecurityContextHolder.getContext().getAuthentication().getName()).isEqualTo("user"); } + // gh-3962 @Test public void withSecurityContextAfterSqlScripts() { @@ -126,13 +125,11 @@ public class WithSecurityContextTestExcecutionListenerTests { @Test // gh-3837 public void handlesGenericAnnotation() throws Exception { - Method method = ReflectionUtils.findMethod( - WithSecurityContextTestExcecutionListenerTests.class, + Method method = ReflectionUtils.findMethod(WithSecurityContextTestExcecutionListenerTests.class, "handlesGenericAnnotationTestMethod"); TestContext testContext = mock(TestContext.class); when(testContext.getTestMethod()).thenReturn(method); - when(testContext.getApplicationContext()) - .thenThrow(new IllegalStateException("")); + when(testContext.getApplicationContext()).thenThrow(new IllegalStateException("")); this.listener.beforeTestMethod(testContext); @@ -147,11 +144,12 @@ public class WithSecurityContextTestExcecutionListenerTests { @Retention(RetentionPolicy.RUNTIME) @WithSecurityContext(factory = SuperClassWithSecurityContextFactory.class) @interface WithSuperClassWithSecurityContext { + String username() default "WithSuperClassWithSecurityContext"; + } - static class SuperClassWithSecurityContextFactory - implements WithSecurityContextFactory { + static class SuperClassWithSecurityContextFactory implements WithSecurityContextFactory { @Override public SecurityContext createSecurityContext(Annotation annotation) { @@ -159,9 +157,11 @@ public class WithSecurityContextTestExcecutionListenerTests { context.setAuthentication(new TestingAuthenticationToken(annotation, "NA")); return context; } + } static class FakeTest { + public void testNoAnnotation() { } @@ -169,9 +169,12 @@ public class WithSecurityContextTestExcecutionListenerTests { public void testWithMockUser() { } + } @Configuration static class Config { + } + } diff --git a/test/src/test/java/org/springframework/security/test/context/support/WithSecurityContextTestExecutionListenerTests.java b/test/src/test/java/org/springframework/security/test/context/support/WithSecurityContextTestExecutionListenerTests.java index bb3c8cfd0c..8b2c1dd8c8 100644 --- a/test/src/test/java/org/springframework/security/test/context/support/WithSecurityContextTestExecutionListenerTests.java +++ b/test/src/test/java/org/springframework/security/test/context/support/WithSecurityContextTestExecutionListenerTests.java @@ -54,8 +54,10 @@ import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) @ContextConfiguration(classes = WithSecurityContextTestExecutionListenerTests.NoOpConfiguration.class) public class WithSecurityContextTestExecutionListenerTests { + @ClassRule public static final SpringClassRule spring = new SpringClassRule(); + @Rule public final SpringMethodRule springMethod = new SpringMethodRule(); @@ -81,7 +83,8 @@ public class WithSecurityContextTestExecutionListenerTests { this.listener.beforeTestMethod(this.testContext); assertThat(TestSecurityContextHolder.getContext().getAuthentication()).isNotNull(); - verify(this.testContext, never()).setAttribute(eq(WithSecurityContextTestExecutionListener.SECURITY_CONTEXT_ATTR_NAME), any(SecurityContext.class)); + verify(this.testContext, never()).setAttribute( + eq(WithSecurityContextTestExecutionListener.SECURITY_CONTEXT_ATTR_NAME), any(SecurityContext.class)); } @Test @@ -93,7 +96,8 @@ public class WithSecurityContextTestExecutionListenerTests { this.listener.beforeTestMethod(this.testContext); assertThat(TestSecurityContextHolder.getContext().getAuthentication()).isNotNull(); - verify(this.testContext, never()).setAttribute(eq(WithSecurityContextTestExecutionListener.SECURITY_CONTEXT_ATTR_NAME), any(SecurityContext.class)); + verify(this.testContext, never()).setAttribute( + eq(WithSecurityContextTestExecutionListener.SECURITY_CONTEXT_ATTR_NAME), any(SecurityContext.class)); } @Test @@ -105,8 +109,8 @@ public class WithSecurityContextTestExecutionListenerTests { this.listener.beforeTestMethod(this.testContext); assertThat(TestSecurityContextHolder.getContext().getAuthentication()).isNull(); - verify(this.testContext).setAttribute(eq(WithSecurityContextTestExecutionListener.SECURITY_CONTEXT_ATTR_NAME) - , ArgumentMatchers.>any()); + verify(this.testContext).setAttribute(eq(WithSecurityContextTestExecutionListener.SECURITY_CONTEXT_ATTR_NAME), + ArgumentMatchers.>any()); } @Test @@ -148,17 +152,22 @@ public class WithSecurityContextTestExecutionListenerTests { SecurityContextImpl securityContext = new SecurityContextImpl(); securityContext.setAuthentication(new TestingAuthenticationToken("user", "passsword", "ROLE_USER")); Supplier supplier = () -> securityContext; - when(this.testContext.removeAttribute(WithSecurityContextTestExecutionListener.SECURITY_CONTEXT_ATTR_NAME)).thenReturn(supplier); + when(this.testContext.removeAttribute(WithSecurityContextTestExecutionListener.SECURITY_CONTEXT_ATTR_NAME)) + .thenReturn(supplier); this.listener.beforeTestExecution(this.testContext); - assertThat(TestSecurityContextHolder.getContext().getAuthentication()).isEqualTo(securityContext.getAuthentication()); + assertThat(TestSecurityContextHolder.getContext().getAuthentication()) + .isEqualTo(securityContext.getAuthentication()); } @Configuration - static class NoOpConfiguration {} + static class NoOpConfiguration { + + } static class TheTest { + @WithMockUser(setupBefore = TestExecutionEvent.TEST_EXECUTION) public void withMockUserTestExecution() { } @@ -174,6 +183,7 @@ public class WithSecurityContextTestExecutionListenerTests { @WithUserDetails(setupBefore = TestExecutionEvent.TEST_EXECUTION) public void withUserDetails() { } + } } diff --git a/test/src/test/java/org/springframework/security/test/context/support/WithUserDetailsSecurityContextFactoryTests.java b/test/src/test/java/org/springframework/security/test/context/support/WithUserDetailsSecurityContextFactoryTests.java index 50b6e8aff0..4cf7a1800b 100644 --- a/test/src/test/java/org/springframework/security/test/context/support/WithUserDetailsSecurityContextFactoryTests.java +++ b/test/src/test/java/org/springframework/security/test/context/support/WithUserDetailsSecurityContextFactoryTests.java @@ -40,10 +40,13 @@ public class WithUserDetailsSecurityContextFactoryTests { @Mock private ReactiveUserDetailsService reactiveUserDetailsService; + @Mock private UserDetailsService userDetailsService; + @Mock private UserDetails userDetails; + @Mock private BeanFactory beans; @@ -78,8 +81,7 @@ public class WithUserDetailsSecurityContextFactoryTests { when(userDetailsService.loadUserByUsername(username)).thenReturn(userDetails); SecurityContext context = factory.createSecurityContext(withUserDetails); - assertThat(context.getAuthentication()).isInstanceOf( - UsernamePasswordAuthenticationToken.class); + assertThat(context.getAuthentication()).isInstanceOf(UsernamePasswordAuthenticationToken.class); assertThat(context.getAuthentication().getPrincipal()).isEqualTo(userDetails); verify(beans).getBean(UserDetailsService.class); } @@ -89,15 +91,15 @@ public class WithUserDetailsSecurityContextFactoryTests { public void createSecurityContextWithUserDetailsServiceName() { String beanName = "secondUserDetailsServiceBean"; String username = "user"; - when(this.beans.getBean(beanName, ReactiveUserDetailsService.class)).thenThrow(new BeanNotOfRequiredTypeException("", ReactiveUserDetailsService.class, UserDetailsService.class)); + when(this.beans.getBean(beanName, ReactiveUserDetailsService.class)).thenThrow( + new BeanNotOfRequiredTypeException("", ReactiveUserDetailsService.class, UserDetailsService.class)); when(withUserDetails.value()).thenReturn(username); when(withUserDetails.userDetailsServiceBeanName()).thenReturn(beanName); when(userDetailsService.loadUserByUsername(username)).thenReturn(userDetails); when(beans.getBean(beanName, UserDetailsService.class)).thenReturn(userDetailsService); SecurityContext context = factory.createSecurityContext(withUserDetails); - assertThat(context.getAuthentication()).isInstanceOf( - UsernamePasswordAuthenticationToken.class); + assertThat(context.getAuthentication()).isInstanceOf(UsernamePasswordAuthenticationToken.class); assertThat(context.getAuthentication().getPrincipal()).isEqualTo(userDetails); verify(beans).getBean(beanName, UserDetailsService.class); } @@ -110,8 +112,7 @@ public class WithUserDetailsSecurityContextFactoryTests { when(this.reactiveUserDetailsService.findByUsername(username)).thenReturn(Mono.just(userDetails)); SecurityContext context = factory.createSecurityContext(withUserDetails); - assertThat(context.getAuthentication()).isInstanceOf( - UsernamePasswordAuthenticationToken.class); + assertThat(context.getAuthentication()).isInstanceOf(UsernamePasswordAuthenticationToken.class); assertThat(context.getAuthentication().getPrincipal()).isEqualTo(userDetails); verify(this.beans).getBean(ReactiveUserDetailsService.class); } @@ -122,13 +123,14 @@ public class WithUserDetailsSecurityContextFactoryTests { String username = "user"; when(withUserDetails.value()).thenReturn(username); when(withUserDetails.userDetailsServiceBeanName()).thenReturn(beanName); - when(this.beans.getBean(beanName, ReactiveUserDetailsService.class)).thenReturn(this.reactiveUserDetailsService); + when(this.beans.getBean(beanName, ReactiveUserDetailsService.class)) + .thenReturn(this.reactiveUserDetailsService); when(this.reactiveUserDetailsService.findByUsername(username)).thenReturn(Mono.just(userDetails)); SecurityContext context = factory.createSecurityContext(withUserDetails); - assertThat(context.getAuthentication()).isInstanceOf( - UsernamePasswordAuthenticationToken.class); + assertThat(context.getAuthentication()).isInstanceOf(UsernamePasswordAuthenticationToken.class); assertThat(context.getAuthentication().getPrincipal()).isEqualTo(userDetails); verify(this.beans).getBean(beanName, ReactiveUserDetailsService.class); } + } diff --git a/test/src/test/java/org/springframework/security/test/context/support/WithUserDetailsTests.java b/test/src/test/java/org/springframework/security/test/context/support/WithUserDetailsTests.java index 3c4f12749d..cb3681b902 100644 --- a/test/src/test/java/org/springframework/security/test/context/support/WithUserDetailsTests.java +++ b/test/src/test/java/org/springframework/security/test/context/support/WithUserDetailsTests.java @@ -25,12 +25,10 @@ public class WithUserDetailsTests { @Test public void defaults() { - WithUserDetails userDetails = AnnotationUtils.findAnnotation(Annotated.class, - WithUserDetails.class); + WithUserDetails userDetails = AnnotationUtils.findAnnotation(Annotated.class, WithUserDetails.class); assertThat(userDetails.value()).isEqualTo("user"); - WithSecurityContext context = AnnotatedElementUtils - .findMergedAnnotation(Annotated.class, + WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(Annotated.class, WithSecurityContext.class); assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_METHOD); @@ -38,12 +36,12 @@ public class WithUserDetailsTests { @WithUserDetails private static class Annotated { + } @Test public void findMergedAnnotationWhenSetupExplicitThenOverridden() { - WithSecurityContext context = AnnotatedElementUtils - .findMergedAnnotation(SetupExplicit.class, + WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(SetupExplicit.class, WithSecurityContext.class); assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_METHOD); @@ -51,12 +49,12 @@ public class WithUserDetailsTests { @WithUserDetails(setupBefore = TestExecutionEvent.TEST_METHOD) private class SetupExplicit { + } @Test public void findMergedAnnotationWhenSetupOverriddenThenOverridden() { - WithSecurityContext context = AnnotatedElementUtils - .findMergedAnnotation(SetupOverridden.class, + WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(SetupOverridden.class, WithSecurityContext.class); assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_EXECUTION); @@ -64,5 +62,7 @@ public class WithUserDetailsTests { @WithUserDetails(setupBefore = TestExecutionEvent.TEST_EXECUTION) private class SetupOverridden { + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/reactive/server/AbstractMockServerConfigurersTests.java b/test/src/test/java/org/springframework/security/test/web/reactive/server/AbstractMockServerConfigurersTests.java index 6af2661f64..e984952640 100644 --- a/test/src/test/java/org/springframework/security/test/web/reactive/server/AbstractMockServerConfigurersTests.java +++ b/test/src/test/java/org/springframework/security/test/web/reactive/server/AbstractMockServerConfigurersTests.java @@ -34,13 +34,12 @@ import static org.assertj.core.api.Assertions.assertThat; * @since 5.0 */ abstract class AbstractMockServerConfigurersTests { + protected PrincipalController controller = new PrincipalController(); + protected SecurityContextController securityContextController = new SecurityContextController(); - protected User.UserBuilder userBuilder = User - .withUsername("user") - .password("password") - .roles("USER"); + protected User.UserBuilder userBuilder = User.withUsername("user").password("password").roles("USER"); protected void assertPrincipalCreatedFromUserDetails(Principal principal, UserDetails originalUserDetails) { assertThat(principal).isInstanceOf(UsernamePasswordAuthenticationToken.class); @@ -56,6 +55,7 @@ abstract class AbstractMockServerConfigurersTests { @RestController protected static class PrincipalController { + volatile Principal principal; @RequestMapping("/**") @@ -74,10 +74,12 @@ abstract class AbstractMockServerConfigurersTests { assertThat(this.principal).isEqualTo(expected); this.principal = null; } + } @RestController protected static class SecurityContextController { + volatile SecurityContext securityContext; @RequestMapping("/**") @@ -91,5 +93,7 @@ abstract class AbstractMockServerConfigurersTests { this.securityContext = null; return result; } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurerOpaqueTokenTests.java b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurerOpaqueTokenTests.java index c44da6255a..1a19e6d064 100644 --- a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurerOpaqueTokenTests.java +++ b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurerOpaqueTokenTests.java @@ -45,31 +45,24 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock */ @RunWith(MockitoJUnitRunner.class) public class SecurityMockServerConfigurerOpaqueTokenTests extends AbstractMockServerConfigurersTests { + private GrantedAuthority authority1 = new SimpleGrantedAuthority("one"); private GrantedAuthority authority2 = new SimpleGrantedAuthority("two"); - private WebTestClient client = WebTestClient - .bindToController(securityContextController) + private WebTestClient client = WebTestClient.bindToController(securityContextController) .webFilter(new SecurityContextServerWebExchangeWebFilter()) - .argumentResolvers(resolvers -> resolvers.addCustomResolver( - new CurrentSecurityContextArgumentResolver(new ReactiveAdapterRegistry()))) - .apply(springSecurity()) - .configureClient() - .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) - .build(); + .argumentResolvers(resolvers -> resolvers + .addCustomResolver(new CurrentSecurityContextArgumentResolver(new ReactiveAdapterRegistry()))) + .apply(springSecurity()).configureClient() + .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).build(); @Test public void mockOpaqueTokenWhenUsingDefaultsThenBearerTokenAuthentication() { - this.client - .mutateWith(mockOpaqueToken()) - .get() - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOpaqueToken()).get().exchange().expectStatus().isOk(); SecurityContext context = securityContextController.removeSecurityContext(); - assertThat(context.getAuthentication()).isInstanceOf( - BearerTokenAuthentication.class); + assertThat(context.getAuthentication()).isInstanceOf(BearerTokenAuthentication.class); BearerTokenAuthentication token = (BearerTokenAuthentication) context.getAuthentication(); assertThat(token.getAuthorities()).isNotEmpty(); assertThat(token.getToken()).isNotNull(); @@ -78,27 +71,19 @@ public class SecurityMockServerConfigurerOpaqueTokenTests extends AbstractMockSe @Test public void mockOpaqueTokenWhenAuthoritiesThenBearerTokenAuthentication() { - this.client - .mutateWith(mockOpaqueToken() - .authorities(this.authority1, this.authority2)) - .get() - .exchange() + this.client.mutateWith(mockOpaqueToken().authorities(this.authority1, this.authority2)).get().exchange() .expectStatus().isOk(); SecurityContext context = securityContextController.removeSecurityContext(); - assertThat((List) context.getAuthentication().getAuthorities()) - .containsOnly(this.authority1, this.authority2); + assertThat((List) context.getAuthentication().getAuthorities()).containsOnly(this.authority1, + this.authority2); } @Test public void mockOpaqueTokenWhenAttributesThenBearerTokenAuthentication() { String sub = new String("my-subject"); - this.client - .mutateWith(mockOpaqueToken() - .attributes(attributes -> attributes.put(SUBJECT, sub))) - .get() - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOpaqueToken().attributes(attributes -> attributes.put(SUBJECT, sub))).get() + .exchange().expectStatus().isOk(); SecurityContext context = securityContextController.removeSecurityContext(); assertThat(context.getAuthentication()).isInstanceOf(BearerTokenAuthentication.class); @@ -109,12 +94,7 @@ public class SecurityMockServerConfigurerOpaqueTokenTests extends AbstractMockSe @Test public void mockOpaqueTokenWhenPrincipalThenBearerTokenAuthentication() { OAuth2AuthenticatedPrincipal principal = active(); - this.client - .mutateWith(mockOpaqueToken() - .principal(principal)) - .get() - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOpaqueToken().principal(principal)).get().exchange().expectStatus().isOk(); SecurityContext context = securityContextController.removeSecurityContext(); assertThat(context.getAuthentication()).isInstanceOf(BearerTokenAuthentication.class); @@ -126,13 +106,8 @@ public class SecurityMockServerConfigurerOpaqueTokenTests extends AbstractMockSe public void mockOpaqueTokenWhenPrincipalSpecifiedThenLastCalledTakesPrecedence() { OAuth2AuthenticatedPrincipal principal = active(a -> a.put("scope", "user")); - this.client - .mutateWith(mockOpaqueToken() - .attributes(a -> a.put(SUBJECT, "foo")) - .principal(principal)) - .get() - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOpaqueToken().attributes(a -> a.put(SUBJECT, "foo")).principal(principal)).get() + .exchange().expectStatus().isOk(); SecurityContext context = securityContextController.removeSecurityContext(); assertThat(context.getAuthentication()).isInstanceOf(BearerTokenAuthentication.class); @@ -140,13 +115,8 @@ public class SecurityMockServerConfigurerOpaqueTokenTests extends AbstractMockSe assertThat((String) ((OAuth2AuthenticatedPrincipal) token.getPrincipal()).getAttribute(SUBJECT)) .isEqualTo(principal.getAttribute(SUBJECT)); - this.client - .mutateWith(mockOpaqueToken() - .principal(principal) - .attributes(a -> a.put(SUBJECT, "bar"))) - .get() - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOpaqueToken().principal(principal).attributes(a -> a.put(SUBJECT, "bar"))).get() + .exchange().expectStatus().isOk(); context = securityContextController.removeSecurityContext(); assertThat(context.getAuthentication()).isInstanceOf(BearerTokenAuthentication.class); @@ -154,4 +124,5 @@ public class SecurityMockServerConfigurerOpaqueTokenTests extends AbstractMockSe assertThat((String) ((OAuth2AuthenticatedPrincipal) token.getPrincipal()).getAttribute(SUBJECT)) .isEqualTo("bar"); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersAnnotatedTests.java b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersAnnotatedTests.java index cce61fba7b..540fe4c4fe 100644 --- a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersAnnotatedTests.java +++ b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersAnnotatedTests.java @@ -42,21 +42,14 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock @SecurityTestExecutionListeners public class SecurityMockServerConfigurersAnnotatedTests extends AbstractMockServerConfigurersTests { - WebTestClient client = WebTestClient - .bindToController(controller) - .webFilter(new SecurityContextServerWebExchangeWebFilter()) - .apply(springSecurity()) - .configureClient() - .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) - .build(); + WebTestClient client = WebTestClient.bindToController(controller) + .webFilter(new SecurityContextServerWebExchangeWebFilter()).apply(springSecurity()).configureClient() + .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).build(); @Test @WithMockUser public void withMockUserWhenOnMethodThenSuccess() { - client - .get() - .exchange() - .expectStatus().isOk(); + client.get().exchange().expectStatus().isOk(); Authentication authentication = TestSecurityContextHolder.getContext().getAuthentication(); controller.assertPrincipalIsEqualTo(authentication); @@ -65,20 +58,13 @@ public class SecurityMockServerConfigurersAnnotatedTests extends AbstractMockSer @Test @WithMockUser public void withMockUserWhenGlobalMockPrincipalThenOverridesAnnotation() { - TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", "ROLE_USER"); - client = WebTestClient - .bindToController(controller) - .webFilter(new SecurityContextServerWebExchangeWebFilter()) - .apply(springSecurity()) - .apply(mockAuthentication(authentication)) - .configureClient() - .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) - .build(); + TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", + "ROLE_USER"); + client = WebTestClient.bindToController(controller).webFilter(new SecurityContextServerWebExchangeWebFilter()) + .apply(springSecurity()).apply(mockAuthentication(authentication)).configureClient() + .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).build(); - client - .get() - .exchange() - .expectStatus().isOk(); + client.get().exchange().expectStatus().isOk(); controller.assertPrincipalIsEqualTo(authentication); } @@ -86,12 +72,9 @@ public class SecurityMockServerConfigurersAnnotatedTests extends AbstractMockSer @Test @WithMockUser public void withMockUserWhenMutateWithMockPrincipalThenOverridesAnnotation() { - TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", "ROLE_USER"); - client - .mutateWith(mockAuthentication(authentication)) - .get() - .exchange() - .expectStatus().isOk(); + TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", + "ROLE_USER"); + client.mutateWith(mockAuthentication(authentication)).get().exchange().expectStatus().isOk(); controller.assertPrincipalIsEqualTo(authentication); } @@ -99,20 +82,13 @@ public class SecurityMockServerConfigurersAnnotatedTests extends AbstractMockSer @Test @WithMockUser public void withMockUserWhenMutateWithMockPrincipalAndNoMutateThenOverridesAnnotationAndUsesAnnotation() { - TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", "ROLE_USER"); - client - .mutateWith(mockAuthentication(authentication)) - .get() - .exchange() - .expectStatus().isOk(); + TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", + "ROLE_USER"); + client.mutateWith(mockAuthentication(authentication)).get().exchange().expectStatus().isOk(); controller.assertPrincipalIsEqualTo(authentication); - - client - .get() - .exchange() - .expectStatus().isOk(); + client.get().exchange().expectStatus().isOk(); assertPrincipalCreatedFromUserDetails(controller.removePrincipal(), userBuilder.build()); } @@ -121,16 +97,7 @@ public class SecurityMockServerConfigurersAnnotatedTests extends AbstractMockSer @WithMockUser public void withMockUserWhenOnMethodAndRequestIsExecutedOnDifferentThreadThenSuccess() { Authentication authentication = TestSecurityContextHolder.getContext().getAuthentication(); - ForkJoinPool - .commonPool() - .submit(() -> - client - .get() - .exchange() - .expectStatus() - .isOk() - ) - .join(); + ForkJoinPool.commonPool().submit(() -> client.get().exchange().expectStatus().isOk()).join(); controller.assertPrincipalIsEqualTo(authentication); } @@ -138,32 +105,18 @@ public class SecurityMockServerConfigurersAnnotatedTests extends AbstractMockSer @Test @WithMockUser public void withMockUserAndWithCallOnSeparateThreadWhenMutateWithMockPrincipalAndNoMutateThenOverridesAnnotationAndUsesAnnotation() { - TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", "ROLE_USER"); + TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", + "ROLE_USER"); - ForkJoinPool - .commonPool() - .submit(() -> - client - .mutateWith(mockAuthentication(authentication)) - .get() - .exchange() - .expectStatus().isOk() - ) - .join(); + ForkJoinPool.commonPool().submit( + () -> client.mutateWith(mockAuthentication(authentication)).get().exchange().expectStatus().isOk()) + .join(); controller.assertPrincipalIsEqualTo(authentication); - - ForkJoinPool - .commonPool() - .submit(() -> - client - .get() - .exchange() - .expectStatus().isOk() - ) - .join(); + ForkJoinPool.commonPool().submit(() -> client.get().exchange().expectStatus().isOk()).join(); assertPrincipalCreatedFromUserDetails(controller.removePrincipal(), userBuilder.build()); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersClassAnnotatedTests.java b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersClassAnnotatedTests.java index 25c2afae1d..7c68c798f0 100644 --- a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersClassAnnotatedTests.java +++ b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersClassAnnotatedTests.java @@ -42,21 +42,15 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock @RunWith(SpringRunner.class) @SecurityTestExecutionListeners public class SecurityMockServerConfigurersClassAnnotatedTests extends AbstractMockServerConfigurersTests { - WebTestClient client = WebTestClient - .bindToController(controller) - .webFilter(new SecurityContextServerWebExchangeWebFilter()) - .apply(springSecurity()) - .configureClient() - .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) - .build(); + + WebTestClient client = WebTestClient.bindToController(controller) + .webFilter(new SecurityContextServerWebExchangeWebFilter()).apply(springSecurity()).configureClient() + .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).build(); @Test public void wheMockUserWhenClassAnnotatedThenSuccess() { - client - .get() - .exchange() - .expectStatus().isOk() - .expectBody(String.class).consumeWith( response -> assertThat(response.getResponseBody()).contains("\"username\":\"user\"")); + client.get().exchange().expectStatus().isOk().expectBody(String.class) + .consumeWith(response -> assertThat(response.getResponseBody()).contains("\"username\":\"user\"")); Authentication authentication = TestSecurityContextHolder.getContext().getAuthentication(); controller.assertPrincipalIsEqualTo(authentication); @@ -65,11 +59,8 @@ public class SecurityMockServerConfigurersClassAnnotatedTests extends AbstractMo @Test @WithMockUser("method-user") public void withMockUserWhenClassAndMethodAnnotationThenMethodOverrides() { - client - .get() - .exchange() - .expectStatus().isOk() - .expectBody(String.class).consumeWith( response -> assertThat(response.getResponseBody()).contains("\"username\":\"method-user\"")); + client.get().exchange().expectStatus().isOk().expectBody(String.class).consumeWith( + response -> assertThat(response.getResponseBody()).contains("\"username\":\"method-user\"")); Authentication authentication = TestSecurityContextHolder.getContext().getAuthentication(); controller.assertPrincipalIsEqualTo(authentication); @@ -77,14 +68,12 @@ public class SecurityMockServerConfigurersClassAnnotatedTests extends AbstractMo @Test public void withMockUserWhenMutateWithThenMustateWithOverrides() { - client - .mutateWith(mockUser("mutateWith-mockUser")) - .get() - .exchange() - .expectStatus().isOk() - .expectBody(String.class).consumeWith( response -> assertThat(response.getResponseBody()).contains("\"username\":\"mutateWith-mockUser\"")); + client.mutateWith(mockUser("mutateWith-mockUser")).get().exchange().expectStatus().isOk() + .expectBody(String.class).consumeWith(response -> assertThat(response.getResponseBody()) + .contains("\"username\":\"mutateWith-mockUser\"")); Principal principal = controller.removePrincipal(); assertPrincipalCreatedFromUserDetails(principal, userBuilder.username("mutateWith-mockUser").build()); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersJwtTests.java b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersJwtTests.java index e92100fa39..02a01cc8e3 100644 --- a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersJwtTests.java +++ b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersJwtTests.java @@ -47,33 +47,26 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock */ @RunWith(MockitoJUnitRunner.class) public class SecurityMockServerConfigurersJwtTests extends AbstractMockServerConfigurersTests { + @Mock GrantedAuthority authority1; @Mock GrantedAuthority authority2; - WebTestClient client = WebTestClient - .bindToController(securityContextController) + WebTestClient client = WebTestClient.bindToController(securityContextController) .webFilter(new SecurityContextServerWebExchangeWebFilter()) - .argumentResolvers(resolvers -> resolvers.addCustomResolver( - new CurrentSecurityContextArgumentResolver(new ReactiveAdapterRegistry()))) - .apply(springSecurity()) - .configureClient() - .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) - .build(); + .argumentResolvers(resolvers -> resolvers + .addCustomResolver(new CurrentSecurityContextArgumentResolver(new ReactiveAdapterRegistry()))) + .apply(springSecurity()).configureClient() + .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).build(); @Test public void mockJwtWhenUsingDefaultsTheCreatesJwtAuthentication() { - client - .mutateWith(mockJwt()) - .get() - .exchange() - .expectStatus().isOk(); + client.mutateWith(mockJwt()).get().exchange().expectStatus().isOk(); SecurityContext context = securityContextController.removeSecurityContext(); - assertThat(context.getAuthentication()).isInstanceOf( - JwtAuthenticationToken.class); + assertThat(context.getAuthentication()).isInstanceOf(JwtAuthenticationToken.class); JwtAuthenticationToken token = (JwtAuthenticationToken) context.getAuthentication(); assertThat(token.getAuthorities()).isNotEmpty(); assertThat(token.getToken()).isNotNull(); @@ -84,79 +77,54 @@ public class SecurityMockServerConfigurersJwtTests extends AbstractMockServerCon @Test public void mockJwtWhenProvidingBuilderConsumerThenProducesJwtAuthentication() { String name = new String("user"); - client - .mutateWith(mockJwt().jwt(jwt -> jwt.subject(name))) - .get() - .exchange() - .expectStatus().isOk(); + client.mutateWith(mockJwt().jwt(jwt -> jwt.subject(name))).get().exchange().expectStatus().isOk(); SecurityContext context = securityContextController.removeSecurityContext(); - assertThat(context.getAuthentication()).isInstanceOf( - JwtAuthenticationToken.class); + assertThat(context.getAuthentication()).isInstanceOf(JwtAuthenticationToken.class); JwtAuthenticationToken token = (JwtAuthenticationToken) context.getAuthentication(); assertThat(token.getToken().getSubject()).isSameAs(name); } @Test public void mockJwtWhenProvidingCustomAuthoritiesThenProducesJwtAuthentication() { - client - .mutateWith(mockJwt().jwt(jwt -> jwt.claim("scope", "ignored authorities")) - .authorities(this.authority1, this.authority2)) - .get() - .exchange() - .expectStatus().isOk(); + client.mutateWith(mockJwt().jwt(jwt -> jwt.claim("scope", "ignored authorities")).authorities(this.authority1, + this.authority2)).get().exchange().expectStatus().isOk(); SecurityContext context = securityContextController.removeSecurityContext(); - assertThat((List) context.getAuthentication().getAuthorities()) - .containsOnly(this.authority1, this.authority2); + assertThat((List) context.getAuthentication().getAuthorities()).containsOnly(this.authority1, + this.authority2); } @Test public void mockJwtWhenProvidingScopedAuthoritiesThenProducesJwtAuthentication() { - client - .mutateWith(mockJwt().jwt(jwt -> jwt.claim("scope", "scoped authorities"))) - .get() - .exchange() + client.mutateWith(mockJwt().jwt(jwt -> jwt.claim("scope", "scoped authorities"))).get().exchange() .expectStatus().isOk(); SecurityContext context = securityContextController.removeSecurityContext(); - assertThat((List) context.getAuthentication().getAuthorities()) - .containsOnly(new SimpleGrantedAuthority("SCOPE_scoped"), - new SimpleGrantedAuthority("SCOPE_authorities")); + assertThat((List) context.getAuthentication().getAuthorities()).containsOnly( + new SimpleGrantedAuthority("SCOPE_scoped"), new SimpleGrantedAuthority("SCOPE_authorities")); } @Test public void mockJwtWhenProvidingGrantedAuthoritiesThenProducesJwtAuthentication() { - client - .mutateWith(mockJwt().jwt(jwt -> jwt.claim("scope", "ignored authorities")) - .authorities(jwt -> Arrays.asList(this.authority1))) - .get() - .exchange() - .expectStatus().isOk(); + client.mutateWith(mockJwt().jwt(jwt -> jwt.claim("scope", "ignored authorities")) + .authorities(jwt -> Arrays.asList(this.authority1))).get().exchange().expectStatus().isOk(); SecurityContext context = securityContextController.removeSecurityContext(); - assertThat((List) context.getAuthentication().getAuthorities()) - .containsOnly(this.authority1); + assertThat((List) context.getAuthentication().getAuthorities()).containsOnly(this.authority1); } @Test public void mockJwtWhenProvidingPreparedJwtThenProducesJwtAuthentication() { - Jwt originalToken = TestJwts.jwt() - .header("header1", "value1") - .subject("some_user") - .build(); - this.client - .mutateWith(mockJwt().jwt(originalToken)) - .get() - .exchange() - .expectStatus().isOk(); + Jwt originalToken = TestJwts.jwt().header("header1", "value1").subject("some_user").build(); + this.client.mutateWith(mockJwt().jwt(originalToken)).get().exchange().expectStatus().isOk(); SecurityContext context = securityContextController.removeSecurityContext(); - assertThat(context.getAuthentication()).isInstanceOf( - JwtAuthenticationToken.class); + assertThat(context.getAuthentication()).isInstanceOf(JwtAuthenticationToken.class); JwtAuthenticationToken retrievedToken = (JwtAuthenticationToken) context.getAuthentication(); assertThat(retrievedToken.getToken().getSubject()).isEqualTo("some_user"); assertThat(retrievedToken.getToken().getTokenValue()).isEqualTo("token"); assertThat(retrievedToken.getToken().getHeaders().get("header1")).isEqualTo("value1"); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersOAuth2ClientTests.java b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersOAuth2ClientTests.java index c860da6b46..242f0a4327 100644 --- a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersOAuth2ClientTests.java +++ b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersOAuth2ClientTests.java @@ -54,6 +54,7 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock @RunWith(MockitoJUnitRunner.class) public class SecurityMockServerConfigurersOAuth2ClientTests extends AbstractMockServerConfigurersTests { + private OAuth2LoginController controller = new OAuth2LoginController(); @Mock @@ -66,36 +67,26 @@ public class SecurityMockServerConfigurersOAuth2ClientTests extends AbstractMock @Before public void setup() { - this.client = WebTestClient - .bindToController(this.controller) - .argumentResolvers(c -> c.addCustomResolver( - new OAuth2AuthorizedClientArgumentResolver - (this.clientRegistrationRepository, this.authorizedClientRepository))) - .webFilter(new SecurityContextServerWebExchangeWebFilter()) - .apply(springSecurity()) - .configureClient() - .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) - .build(); + this.client = WebTestClient.bindToController(this.controller) + .argumentResolvers(c -> c.addCustomResolver(new OAuth2AuthorizedClientArgumentResolver( + this.clientRegistrationRepository, this.authorizedClientRepository))) + .webFilter(new SecurityContextServerWebExchangeWebFilter()).apply(springSecurity()).configureClient() + .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).build(); } @Test - public void oauth2ClientWhenUsingDefaultsThenException() - throws Exception { + public void oauth2ClientWhenUsingDefaultsThenException() throws Exception { WebHttpHandlerBuilder builder = WebHttpHandlerBuilder.webHandler(new DispatcherHandler()); assertThatCode(() -> mockOAuth2Client().beforeServerCreated(builder)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("ClientRegistration"); + .isInstanceOf(IllegalArgumentException.class).hasMessageContaining("ClientRegistration"); } @Test - public void oauth2ClientWhenUsingRegistrationIdThenProducesAuthorizedClient() - throws Exception { + public void oauth2ClientWhenUsingRegistrationIdThenProducesAuthorizedClient() throws Exception { - this.client.mutateWith(mockOAuth2Client("registration-id")) - .get().uri("/client") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOAuth2Client("registration-id")).get().uri("/client").exchange().expectStatus() + .isOk(); OAuth2AuthorizedClient client = this.controller.authorizedClient; assertThat(client).isNotNull(); @@ -105,15 +96,12 @@ public class SecurityMockServerConfigurersOAuth2ClientTests extends AbstractMock } @Test - public void oauth2ClientWhenClientRegistrationThenUses() - throws Exception { + public void oauth2ClientWhenClientRegistrationThenUses() throws Exception { - ClientRegistration clientRegistration = clientRegistration() - .registrationId("registration-id").clientId("client-id").build(); - this.client.mutateWith(mockOAuth2Client().clientRegistration(clientRegistration)) - .get().uri("/client") - .exchange() - .expectStatus().isOk(); + ClientRegistration clientRegistration = clientRegistration().registrationId("registration-id") + .clientId("client-id").build(); + this.client.mutateWith(mockOAuth2Client().clientRegistration(clientRegistration)).get().uri("/client") + .exchange().expectStatus().isOk(); OAuth2AuthorizedClient client = this.controller.authorizedClient; assertThat(client).isNotNull(); @@ -123,14 +111,10 @@ public class SecurityMockServerConfigurersOAuth2ClientTests extends AbstractMock } @Test - public void oauth2ClientWhenClientRegistrationConsumerThenUses() - throws Exception { + public void oauth2ClientWhenClientRegistrationConsumerThenUses() throws Exception { - this.client.mutateWith(mockOAuth2Client("registration-id") - .clientRegistration(c -> c.clientId("client-id"))) - .get().uri("/client") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOAuth2Client("registration-id").clientRegistration(c -> c.clientId("client-id"))) + .get().uri("/client").exchange().expectStatus().isOk(); OAuth2AuthorizedClient client = this.controller.authorizedClient; assertThat(client).isNotNull(); @@ -142,24 +126,16 @@ public class SecurityMockServerConfigurersOAuth2ClientTests extends AbstractMock @Test public void oauth2ClientWhenPrincipalNameThenUses() throws Exception { - this.client.mutateWith(mockOAuth2Client("registration-id") - .principalName("test-subject")) - .get().uri("/client") - .exchange() - .expectStatus().isOk() - .expectBody(String.class).isEqualTo("test-subject"); + this.client.mutateWith(mockOAuth2Client("registration-id").principalName("test-subject")).get().uri("/client") + .exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("test-subject"); } @Test - public void oauth2ClientWhenAccessTokenThenUses() - throws Exception { + public void oauth2ClientWhenAccessTokenThenUses() throws Exception { OAuth2AccessToken accessToken = noScopes(); - this.client.mutateWith(mockOAuth2Client("registration-id") - .accessToken(accessToken)) - .get().uri("/client") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOAuth2Client("registration-id").accessToken(accessToken)).get().uri("/client") + .exchange().expectStatus().isOk(); OAuth2AuthorizedClient client = this.controller.authorizedClient; assertThat(client).isNotNull(); @@ -170,39 +146,36 @@ public class SecurityMockServerConfigurersOAuth2ClientTests extends AbstractMock @Test public void oauth2ClientWhenUsedOnceThenDoesNotAffectRemainingTests() throws Exception { - this.client.mutateWith(mockOAuth2Client("registration-id")) - .get().uri("/client") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOAuth2Client("registration-id")).get().uri("/client").exchange().expectStatus() + .isOk(); OAuth2AuthorizedClient client = this.controller.authorizedClient; assertThat(client).isNotNull(); assertThat(client.getClientRegistration().getClientId()).isEqualTo("test-client"); client = new OAuth2AuthorizedClient(clientRegistration().build(), "sub", noScopes()); - when(this.authorizedClientRepository - .loadAuthorizedClient(eq("registration-id"), any(Authentication.class), any(ServerWebExchange.class))) - .thenReturn(Mono.just(client)); - this.client - .get().uri("/client") - .exchange() - .expectStatus().isOk(); + when(this.authorizedClientRepository.loadAuthorizedClient(eq("registration-id"), any(Authentication.class), + any(ServerWebExchange.class))).thenReturn(Mono.just(client)); + this.client.get().uri("/client").exchange().expectStatus().isOk(); client = this.controller.authorizedClient; assertThat(client).isNotNull(); assertThat(client.getClientRegistration().getClientId()).isEqualTo("client-id"); - verify(this.authorizedClientRepository).loadAuthorizedClient( - eq("registration-id"), any(Authentication.class), any(ServerWebExchange.class)); + verify(this.authorizedClientRepository).loadAuthorizedClient(eq("registration-id"), any(Authentication.class), + any(ServerWebExchange.class)); } @RestController static class OAuth2LoginController { + volatile OAuth2AuthorizedClient authorizedClient; @GetMapping("/client") - String authorizedClient - (@RegisteredOAuth2AuthorizedClient("registration-id") OAuth2AuthorizedClient authorizedClient) { + String authorizedClient( + @RegisteredOAuth2AuthorizedClient("registration-id") OAuth2AuthorizedClient authorizedClient) { this.authorizedClient = authorizedClient; return authorizedClient.getPrincipalName(); } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersOAuth2LoginTests.java b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersOAuth2LoginTests.java index 2e13d5a0de..a07af62850 100644 --- a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersOAuth2LoginTests.java +++ b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersOAuth2LoginTests.java @@ -49,6 +49,7 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock @RunWith(MockitoJUnitRunner.class) public class SecurityMockServerConfigurersOAuth2LoginTests extends AbstractMockServerConfigurersTests { + private OAuth2LoginController controller = new OAuth2LoginController(); @Mock @@ -61,41 +62,29 @@ public class SecurityMockServerConfigurersOAuth2LoginTests extends AbstractMockS @Before public void setup() { - this.client = WebTestClient - .bindToController(this.controller) - .argumentResolvers(c -> c.addCustomResolver( - new OAuth2AuthorizedClientArgumentResolver - (this.clientRegistrationRepository, this.authorizedClientRepository))) - .webFilter(new SecurityContextServerWebExchangeWebFilter()) - .apply(springSecurity()) - .configureClient() - .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) - .build(); + this.client = WebTestClient.bindToController(this.controller) + .argumentResolvers(c -> c.addCustomResolver(new OAuth2AuthorizedClientArgumentResolver( + this.clientRegistrationRepository, this.authorizedClientRepository))) + .webFilter(new SecurityContextServerWebExchangeWebFilter()).apply(springSecurity()).configureClient() + .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).build(); } @Test public void oauth2LoginWhenUsingDefaultsThenProducesDefaultAuthentication() { - this.client.mutateWith(mockOAuth2Login()) - .get().uri("/token") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOAuth2Login()).get().uri("/token").exchange().expectStatus().isOk(); OAuth2AuthenticationToken token = this.controller.token; assertThat(token).isNotNull(); assertThat(token.getAuthorizedClientRegistrationId()).isEqualTo("test"); assertThat(token.getPrincipal()).isInstanceOf(OAuth2User.class); - assertThat(token.getPrincipal().getAttributes()) - .containsEntry("sub", "user"); + assertThat(token.getPrincipal().getAttributes()).containsEntry("sub", "user"); assertThat((Collection) token.getPrincipal().getAuthorities()) .contains(new SimpleGrantedAuthority("SCOPE_read")); } @Test public void oauth2LoginWhenUsingDefaultsThenProducesDefaultAuthorizedClient() { - this.client.mutateWith(mockOAuth2Login()) - .get().uri("/client") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOAuth2Login()).get().uri("/client").exchange().expectStatus().isOk(); OAuth2AuthorizedClient client = this.controller.authorizedClient; assertThat(client).isNotNull(); @@ -106,11 +95,8 @@ public class SecurityMockServerConfigurersOAuth2LoginTests extends AbstractMockS @Test public void oauth2LoginWhenAuthoritiesSpecifiedThenGrantsAccess() { - this.client.mutateWith(mockOAuth2Login() - .authorities(new SimpleGrantedAuthority("SCOPE_admin"))) - .get().uri("/token") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOAuth2Login().authorities(new SimpleGrantedAuthority("SCOPE_admin"))).get() + .uri("/token").exchange().expectStatus().isOk(); OAuth2AuthenticationToken token = this.controller.token; assertThat((Collection) token.getPrincipal().getAuthorities()) @@ -119,78 +105,54 @@ public class SecurityMockServerConfigurersOAuth2LoginTests extends AbstractMockS @Test public void oauth2LoginWhenAttributeSpecifiedThenUserHasAttribute() { - this.client.mutateWith(mockOAuth2Login() - .attributes(a -> a.put("iss", "https://idp.example.org"))) - .get().uri("/token") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOAuth2Login().attributes(a -> a.put("iss", "https://idp.example.org"))).get() + .uri("/token").exchange().expectStatus().isOk(); OAuth2AuthenticationToken token = this.controller.token; - assertThat(token.getPrincipal().getAttributes()) - .containsEntry("iss", "https://idp.example.org"); + assertThat(token.getPrincipal().getAttributes()).containsEntry("iss", "https://idp.example.org"); } @Test public void oauth2LoginWhenNameSpecifiedThenUserHasName() throws Exception { - OAuth2User oauth2User = new DefaultOAuth2User( - AuthorityUtils.commaSeparatedStringToAuthorityList("SCOPE_read"), - Collections.singletonMap("custom-attribute", "test-subject"), - "custom-attribute"); + OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.commaSeparatedStringToAuthorityList("SCOPE_read"), + Collections.singletonMap("custom-attribute", "test-subject"), "custom-attribute"); - this.client.mutateWith(mockOAuth2Login() - .oauth2User(oauth2User)) - .get().uri("/token") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOAuth2Login().oauth2User(oauth2User)).get().uri("/token").exchange().expectStatus() + .isOk(); OAuth2AuthenticationToken token = this.controller.token; - assertThat(token.getPrincipal().getName()) - .isEqualTo("test-subject"); + assertThat(token.getPrincipal().getName()).isEqualTo("test-subject"); - this.client.mutateWith(mockOAuth2Login() - .oauth2User(oauth2User)) - .get().uri("/client") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOAuth2Login().oauth2User(oauth2User)).get().uri("/client").exchange().expectStatus() + .isOk(); OAuth2AuthorizedClient client = this.controller.authorizedClient; - assertThat(client.getPrincipalName()) - .isEqualTo("test-subject"); + assertThat(client.getPrincipalName()).isEqualTo("test-subject"); } @Test public void oauth2LoginWhenOAuth2UserSpecifiedThenLastCalledTakesPrecedence() throws Exception { - OAuth2User oauth2User = new DefaultOAuth2User( - AuthorityUtils.createAuthorityList("SCOPE_read"), - Collections.singletonMap("sub", "subject"), - "sub"); + OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("SCOPE_read"), + Collections.singletonMap("sub", "subject"), "sub"); - this.client.mutateWith(mockOAuth2Login() - .attributes(a -> a.put("subject", "foo")) - .oauth2User(oauth2User)) - .get().uri("/token") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOAuth2Login().attributes(a -> a.put("subject", "foo")).oauth2User(oauth2User)).get() + .uri("/token").exchange().expectStatus().isOk(); OAuth2AuthenticationToken token = this.controller.token; - assertThat(token.getPrincipal().getAttributes()) - .containsEntry("sub", "subject"); + assertThat(token.getPrincipal().getAttributes()).containsEntry("sub", "subject"); - this.client.mutateWith(mockOAuth2Login() - .oauth2User(oauth2User) - .attributes(a -> a.put("sub", "bar"))) - .get().uri("/token") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOAuth2Login().oauth2User(oauth2User).attributes(a -> a.put("sub", "bar"))).get() + .uri("/token").exchange().expectStatus().isOk(); token = this.controller.token; - assertThat(token.getPrincipal().getAttributes()) - .containsEntry("sub", "bar"); + assertThat(token.getPrincipal().getAttributes()).containsEntry("sub", "bar"); } @RestController static class OAuth2LoginController { + volatile OAuth2AuthenticationToken token; + volatile OAuth2AuthorizedClient authorizedClient; @GetMapping("/token") @@ -200,10 +162,11 @@ public class SecurityMockServerConfigurersOAuth2LoginTests extends AbstractMockS } @GetMapping("/client") - String authorizedClient - (@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient) { + String authorizedClient(@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient) { this.authorizedClient = authorizedClient; return authorizedClient.getPrincipalName(); } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersOidcLoginTests.java b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersOidcLoginTests.java index 3388f5518d..3758384d10 100644 --- a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersOidcLoginTests.java +++ b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersOidcLoginTests.java @@ -51,6 +51,7 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock @RunWith(MockitoJUnitRunner.class) public class SecurityMockServerConfigurersOidcLoginTests extends AbstractMockServerConfigurersTests { + private OAuth2LoginController controller = new OAuth2LoginController(); @Mock @@ -63,43 +64,30 @@ public class SecurityMockServerConfigurersOidcLoginTests extends AbstractMockSer @Before public void setup() { - this.client = WebTestClient - .bindToController(this.controller) - .argumentResolvers(c -> c.addCustomResolver( - new OAuth2AuthorizedClientArgumentResolver - (this.clientRegistrationRepository, this.authorizedClientRepository))) - .webFilter(new SecurityContextServerWebExchangeWebFilter()) - .apply(springSecurity()) - .configureClient() - .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) - .build(); + this.client = WebTestClient.bindToController(this.controller) + .argumentResolvers(c -> c.addCustomResolver(new OAuth2AuthorizedClientArgumentResolver( + this.clientRegistrationRepository, this.authorizedClientRepository))) + .webFilter(new SecurityContextServerWebExchangeWebFilter()).apply(springSecurity()).configureClient() + .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).build(); } @Test public void oidcLoginWhenUsingDefaultsThenProducesDefaultAuthentication() { - this.client.mutateWith(mockOidcLogin()) - .get().uri("/token") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOidcLogin()).get().uri("/token").exchange().expectStatus().isOk(); OAuth2AuthenticationToken token = this.controller.token; assertThat(token).isNotNull(); assertThat(token.getAuthorizedClientRegistrationId()).isEqualTo("test"); assertThat(token.getPrincipal()).isInstanceOf(OidcUser.class); - assertThat(token.getPrincipal().getAttributes()) - .containsEntry("sub", "user"); + assertThat(token.getPrincipal().getAttributes()).containsEntry("sub", "user"); assertThat((Collection) token.getPrincipal().getAuthorities()) .contains(new SimpleGrantedAuthority("SCOPE_read")); - assertThat(((OidcUser) token.getPrincipal()).getIdToken().getTokenValue()) - .isEqualTo("id-token"); + assertThat(((OidcUser) token.getPrincipal()).getIdToken().getTokenValue()).isEqualTo("id-token"); } @Test public void oidcLoginWhenUsingDefaultsThenProducesDefaultAuthorizedClient() { - this.client.mutateWith(mockOidcLogin()) - .get().uri("/client") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOidcLogin()).get().uri("/client").exchange().expectStatus().isOk(); OAuth2AuthorizedClient client = this.controller.authorizedClient; assertThat(client).isNotNull(); @@ -110,11 +98,8 @@ public class SecurityMockServerConfigurersOidcLoginTests extends AbstractMockSer @Test public void oidcLoginWhenAuthoritiesSpecifiedThenGrantsAccess() { - this.client.mutateWith(mockOidcLogin() - .authorities(new SimpleGrantedAuthority("SCOPE_admin"))) - .get().uri("/token") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOidcLogin().authorities(new SimpleGrantedAuthority("SCOPE_admin"))).get() + .uri("/token").exchange().expectStatus().isOk(); OAuth2AuthenticationToken token = this.controller.token; assertThat((Collection) token.getPrincipal().getAuthorities()) @@ -123,90 +108,64 @@ public class SecurityMockServerConfigurersOidcLoginTests extends AbstractMockSer @Test public void oidcLoginWhenIdTokenSpecifiedThenUserHasClaims() { - this.client.mutateWith(mockOidcLogin() - .idToken(i -> i.issuer("https://idp.example.org"))) - .get().uri("/token") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOidcLogin().idToken(i -> i.issuer("https://idp.example.org"))).get().uri("/token") + .exchange().expectStatus().isOk(); OAuth2AuthenticationToken token = this.controller.token; - assertThat(token.getPrincipal().getAttributes()) - .containsEntry("iss", "https://idp.example.org"); + assertThat(token.getPrincipal().getAttributes()).containsEntry("iss", "https://idp.example.org"); } @Test public void oidcLoginWhenUserInfoSpecifiedThenUserHasClaims() throws Exception { - this.client.mutateWith(mockOidcLogin() - .userInfoToken(u -> u.email("email@email"))) - .get().uri("/token") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOidcLogin().userInfoToken(u -> u.email("email@email"))).get().uri("/token") + .exchange().expectStatus().isOk(); OAuth2AuthenticationToken token = this.controller.token; - assertThat(token.getPrincipal().getAttributes()) - .containsEntry("email", "email@email"); + assertThat(token.getPrincipal().getAttributes()).containsEntry("email", "email@email"); } @Test public void oidcUserWhenNameSpecifiedThenUserHasName() throws Exception { - OidcUser oidcUser = new DefaultOidcUser( - AuthorityUtils.commaSeparatedStringToAuthorityList("SCOPE_read"), + OidcUser oidcUser = new DefaultOidcUser(AuthorityUtils.commaSeparatedStringToAuthorityList("SCOPE_read"), OidcIdToken.withTokenValue("id-token").claim("custom-attribute", "test-subject").build(), "custom-attribute"); - this.client.mutateWith(mockOAuth2Login() - .oauth2User(oidcUser)) - .get().uri("/token") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOAuth2Login().oauth2User(oidcUser)).get().uri("/token").exchange().expectStatus() + .isOk(); OAuth2AuthenticationToken token = this.controller.token; - assertThat(token.getPrincipal().getName()) - .isEqualTo("test-subject"); + assertThat(token.getPrincipal().getName()).isEqualTo("test-subject"); - this.client.mutateWith(mockOAuth2Login() - .oauth2User(oidcUser)) - .get().uri("/client") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOAuth2Login().oauth2User(oidcUser)).get().uri("/client").exchange().expectStatus() + .isOk(); OAuth2AuthorizedClient client = this.controller.authorizedClient; - assertThat(client.getPrincipalName()) - .isEqualTo("test-subject"); + assertThat(client.getPrincipalName()).isEqualTo("test-subject"); } // gh-7794 @Test public void oidcLoginWhenOidcUserSpecifiedThenLastCalledTakesPrecedence() throws Exception { - OidcUser oidcUser = new DefaultOidcUser( - AuthorityUtils.createAuthorityList("SCOPE_read"), idToken().build()); + OidcUser oidcUser = new DefaultOidcUser(AuthorityUtils.createAuthorityList("SCOPE_read"), idToken().build()); - this.client.mutateWith(mockOidcLogin() - .idToken(i -> i.subject("foo")) - .oidcUser(oidcUser)) - .get().uri("/token") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOidcLogin().idToken(i -> i.subject("foo")).oidcUser(oidcUser)).get().uri("/token") + .exchange().expectStatus().isOk(); OAuth2AuthenticationToken token = this.controller.token; - assertThat(token.getPrincipal().getAttributes()) - .containsEntry("sub", "subject"); + assertThat(token.getPrincipal().getAttributes()).containsEntry("sub", "subject"); - this.client.mutateWith(mockOidcLogin() - .oidcUser(oidcUser) - .idToken(i -> i.subject("bar"))) - .get().uri("/token") - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(mockOidcLogin().oidcUser(oidcUser).idToken(i -> i.subject("bar"))).get().uri("/token") + .exchange().expectStatus().isOk(); token = this.controller.token; - assertThat(token.getPrincipal().getAttributes()) - .containsEntry("sub", "bar"); + assertThat(token.getPrincipal().getAttributes()).containsEntry("sub", "bar"); } @RestController static class OAuth2LoginController { + volatile OAuth2AuthenticationToken token; + volatile OAuth2AuthorizedClient authorizedClient; @GetMapping("/token") @@ -216,10 +175,11 @@ public class SecurityMockServerConfigurersOidcLoginTests extends AbstractMockSer } @GetMapping("/client") - String authorizedClient - (@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient) { + String authorizedClient(@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient) { this.authorizedClient = authorizedClient; return authorizedClient.getPrincipalName(); } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersTests.java b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersTests.java index 11203e8d09..4bd771830d 100644 --- a/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersTests.java +++ b/test/src/test/java/org/springframework/security/test/web/reactive/server/SecurityMockServerConfigurersTests.java @@ -37,50 +37,33 @@ import static org.springframework.security.test.web.reactive.server.SecurityMock * @since 5.0 */ public class SecurityMockServerConfigurersTests extends AbstractMockServerConfigurersTests { - WebTestClient client = WebTestClient - .bindToController(controller) - .webFilter( new CsrfWebFilter(), new SecurityContextServerWebExchangeWebFilter()) - .apply(springSecurity()) - .configureClient() - .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) - .build(); + + WebTestClient client = WebTestClient.bindToController(controller) + .webFilter(new CsrfWebFilter(), new SecurityContextServerWebExchangeWebFilter()).apply(springSecurity()) + .configureClient().defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).build(); @Test public void mockAuthenticationWhenLocalThenSuccess() { - TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", "ROLE_USER"); - client - .mutateWith(mockAuthentication(authentication)) - .get() - .exchange() - .expectStatus().isOk(); + TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", + "ROLE_USER"); + client.mutateWith(mockAuthentication(authentication)).get().exchange().expectStatus().isOk(); controller.assertPrincipalIsEqualTo(authentication); } @Test public void mockAuthenticationWhenGlobalThenSuccess() { - TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", "ROLE_USER"); - client = WebTestClient - .bindToController(controller) - .webFilter(new SecurityContextServerWebExchangeWebFilter()) - .apply(springSecurity()) - .apply(mockAuthentication(authentication)) - .configureClient() - .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) - .build(); - client - .get() - .exchange() - .expectStatus().isOk(); + TestingAuthenticationToken authentication = new TestingAuthenticationToken("authentication", "secret", + "ROLE_USER"); + client = WebTestClient.bindToController(controller).webFilter(new SecurityContextServerWebExchangeWebFilter()) + .apply(springSecurity()).apply(mockAuthentication(authentication)).configureClient() + .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).build(); + client.get().exchange().expectStatus().isOk(); controller.assertPrincipalIsEqualTo(authentication); } @Test public void mockUserWhenDefaultsThenSuccess() { - client - .mutateWith(mockUser()) - .get() - .exchange() - .expectStatus().isOk(); + client.mutateWith(mockUser()).get().exchange().expectStatus().isOk(); Principal actual = controller.removePrincipal(); @@ -89,18 +72,10 @@ public class SecurityMockServerConfigurersTests extends AbstractMockServerConfig @Test public void mockUserWhenGlobalThenSuccess() { - client = WebTestClient - .bindToController(controller) - .webFilter(new SecurityContextServerWebExchangeWebFilter()) - .apply(springSecurity()) - .apply(mockUser()) - .configureClient() - .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) - .build(); - client - .get() - .exchange() - .expectStatus().isOk(); + client = WebTestClient.bindToController(controller).webFilter(new SecurityContextServerWebExchangeWebFilter()) + .apply(springSecurity()).apply(mockUser()).configureClient() + .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).build(); + client.get().exchange().expectStatus().isOk(); Principal actual = controller.removePrincipal(); @@ -109,11 +84,7 @@ public class SecurityMockServerConfigurersTests extends AbstractMockServerConfig @Test public void mockUserStringWhenLocalThenSuccess() { - client - .mutateWith(mockUser(userBuilder.build().getUsername())) - .get() - .exchange() - .expectStatus().isOk(); + client.mutateWith(mockUser(userBuilder.build().getUsername())).get().exchange().expectStatus().isOk(); Principal actual = controller.removePrincipal(); @@ -123,11 +94,8 @@ public class SecurityMockServerConfigurersTests extends AbstractMockServerConfig @Test public void mockUserStringWhenCustomThenSuccess() { this.userBuilder = User.withUsername("admin").password("secret").roles("USER", "ADMIN"); - client - .mutateWith(mockUser("admin").password("secret").roles("USER", "ADMIN")) - .get() - .exchange() - .expectStatus().isOk(); + client.mutateWith(mockUser("admin").password("secret").roles("USER", "ADMIN")).get().exchange().expectStatus() + .isOk(); Principal actual = controller.removePrincipal(); @@ -137,11 +105,7 @@ public class SecurityMockServerConfigurersTests extends AbstractMockServerConfig @Test public void mockUserUserDetailsLocalThenSuccess() { UserDetails userDetails = this.userBuilder.build(); - client - .mutateWith(mockUser(userDetails)) - .get() - .exchange() - .expectStatus().isOk(); + client.mutateWith(mockUser(userDetails)).get().exchange().expectStatus().isOk(); Principal actual = controller.removePrincipal(); @@ -150,34 +114,20 @@ public class SecurityMockServerConfigurersTests extends AbstractMockServerConfig @Test public void csrfWhenMutateWithThenDisablesCsrf() { - this.client - .post() - .exchange() - .expectStatus().isEqualTo(HttpStatus.FORBIDDEN) - .expectBody().consumeWith( b -> assertThat(new String(b.getResponseBody())).contains("CSRF")); + this.client.post().exchange().expectStatus().isEqualTo(HttpStatus.FORBIDDEN).expectBody() + .consumeWith(b -> assertThat(new String(b.getResponseBody())).contains("CSRF")); - this.client - .mutateWith(csrf()) - .post() - .exchange() - .expectStatus().isOk(); + this.client.mutateWith(csrf()).post().exchange().expectStatus().isOk(); } @Test public void csrfWhenGlobalThenDisablesCsrf() { - this.client = WebTestClient - .bindToController(this.controller) - .webFilter(new CsrfWebFilter()) - .apply(springSecurity()) - .apply(csrf()) - .configureClient() - .build(); + this.client = WebTestClient.bindToController(this.controller).webFilter(new CsrfWebFilter()) + .apply(springSecurity()).apply(csrf()).configureClient().build(); - this.client - .get() - .exchange() - .expectStatus().isOk(); + this.client.get().exchange().expectStatus().isOk(); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/Sec2935Tests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/Sec2935Tests.java index 58633511ce..00f9dff771 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/Sec2935Tests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/Sec2935Tests.java @@ -44,7 +44,6 @@ import org.springframework.web.context.WebApplicationContext; * @author Rob Winch */ - @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @WebAppConfiguration @@ -57,89 +56,62 @@ public class Sec2935Tests { @Before public void setup() { - mvc = MockMvcBuilders.webAppContextSetup(context) - .apply(springSecurity()) - .build(); + mvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build(); } // SEC-2935 @Test public void postProcessorUserNoUser() throws Exception { - mvc - .perform(get("/admin/abc").with(user("user").roles("ADMIN", "USER"))) - .andExpect(status().isNotFound()) - .andExpect(authenticated().withUsername("user")); + mvc.perform(get("/admin/abc").with(user("user").roles("ADMIN", "USER"))).andExpect(status().isNotFound()) + .andExpect(authenticated().withUsername("user")); - mvc - .perform(get("/admin/abc")) - .andExpect(status().isUnauthorized()) - .andExpect(unauthenticated()); + mvc.perform(get("/admin/abc")).andExpect(status().isUnauthorized()).andExpect(unauthenticated()); } @Test public void postProcessorUserOtherUser() throws Exception { - mvc - .perform(get("/admin/abc").with(user("user1").roles("ADMIN", "USER"))) - .andExpect(status().isNotFound()) - .andExpect(authenticated().withUsername("user1")); + mvc.perform(get("/admin/abc").with(user("user1").roles("ADMIN", "USER"))).andExpect(status().isNotFound()) + .andExpect(authenticated().withUsername("user1")); - mvc - .perform(get("/admin/abc").with(user("user2").roles("USER"))) - .andExpect(status().isForbidden()) - .andExpect(authenticated().withUsername("user2")); + mvc.perform(get("/admin/abc").with(user("user2").roles("USER"))).andExpect(status().isForbidden()) + .andExpect(authenticated().withUsername("user2")); } @WithMockUser @Test public void postProcessorUserWithMockUser() throws Exception { - mvc - .perform(get("/admin/abc").with(user("user1").roles("ADMIN", "USER"))) - .andExpect(status().isNotFound()) - .andExpect(authenticated().withUsername("user1")); + mvc.perform(get("/admin/abc").with(user("user1").roles("ADMIN", "USER"))).andExpect(status().isNotFound()) + .andExpect(authenticated().withUsername("user1")); - mvc - .perform(get("/admin/abc")) - .andExpect(status().isForbidden()) - .andExpect(authenticated().withUsername("user")); + mvc.perform(get("/admin/abc")).andExpect(status().isForbidden()) + .andExpect(authenticated().withUsername("user")); } // SEC-2941 @Test public void defaultRequest() throws Exception { - mvc = MockMvcBuilders.webAppContextSetup(context) - .apply(springSecurity()) - .defaultRequest(get("/").with(user("default"))) - .build(); + mvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()) + .defaultRequest(get("/").with(user("default"))).build(); - mvc - .perform(get("/admin/abc").with(user("user1").roles("ADMIN", "USER"))) - .andExpect(status().isNotFound()) - .andExpect(authenticated().withUsername("user1")); + mvc.perform(get("/admin/abc").with(user("user1").roles("ADMIN", "USER"))).andExpect(status().isNotFound()) + .andExpect(authenticated().withUsername("user1")); - mvc - .perform(get("/admin/abc")) - .andExpect(status().isForbidden()) - .andExpect(authenticated().withUsername("default")); + mvc.perform(get("/admin/abc")).andExpect(status().isForbidden()) + .andExpect(authenticated().withUsername("default")); } @Ignore @WithMockUser @Test public void defaultRequestOverridesWithMockUser() throws Exception { - mvc = MockMvcBuilders.webAppContextSetup(context) - .apply(springSecurity()) - .defaultRequest(get("/").with(user("default"))) - .build(); + mvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()) + .defaultRequest(get("/").with(user("default"))).build(); - mvc - .perform(get("/admin/abc").with(user("user1").roles("ADMIN", "USER"))) - .andExpect(status().isNotFound()) - .andExpect(authenticated().withUsername("user1")); + mvc.perform(get("/admin/abc").with(user("user1").roles("ADMIN", "USER"))).andExpect(status().isNotFound()) + .andExpect(authenticated().withUsername("user1")); - mvc - .perform(get("/admin/abc")) - .andExpect(status().isForbidden()) - .andExpect(authenticated().withUsername("default")); + mvc.perform(get("/admin/abc")).andExpect(status().isForbidden()) + .andExpect(authenticated().withUsername("default")); } @EnableWebSecurity @@ -162,5 +134,7 @@ public class Sec2935Tests { public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication(); } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestBuildersFormLoginTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestBuildersFormLoginTests.java index 3a00f6a080..5b3ba5f44e 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestBuildersFormLoginTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestBuildersFormLoginTests.java @@ -39,6 +39,7 @@ import static org.powermock.api.mockito.PowerMockito.when; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin; public class SecurityMockMvcRequestBuildersFormLoginTests { + private MockServletContext servletContext; @Before @@ -55,16 +56,15 @@ public class SecurityMockMvcRequestBuildersFormLoginTests { assertThat(request.getParameter("username")).isEqualTo("user"); assertThat(request.getParameter("password")).isEqualTo("password"); assertThat(request.getMethod()).isEqualTo("POST"); - assertThat(request.getParameter(token.getParameterName())) - .isEqualTo(token.getToken()); + assertThat(request.getParameter(token.getParameterName())).isEqualTo(token.getToken()); assertThat(request.getRequestURI()).isEqualTo("/login"); assertThat(request.getParameter("_csrf")).isNotNull(); } @Test public void custom() { - MockHttpServletRequest request = formLogin("/login").user("username", "admin") - .password("password", "secret").buildRequest(this.servletContext); + MockHttpServletRequest request = formLogin("/login").user("username", "admin").password("password", "secret") + .buildRequest(this.servletContext); CsrfToken token = (CsrfToken) request .getAttribute(CsrfRequestPostProcessor.TestCsrfTokenRepository.TOKEN_ATTR_NAME); @@ -72,8 +72,7 @@ public class SecurityMockMvcRequestBuildersFormLoginTests { assertThat(request.getParameter("username")).isEqualTo("admin"); assertThat(request.getParameter("password")).isEqualTo("secret"); assertThat(request.getMethod()).isEqualTo("POST"); - assertThat(request.getParameter(token.getParameterName())) - .isEqualTo(token.getToken()); + assertThat(request.getParameter(token.getParameterName())).isEqualTo(token.getToken()); assertThat(request.getRequestURI()).isEqualTo("/login"); } @@ -88,14 +87,13 @@ public class SecurityMockMvcRequestBuildersFormLoginTests { assertThat(request.getParameter("username")).isEqualTo("admin"); assertThat(request.getParameter("password")).isEqualTo("secret"); assertThat(request.getMethod()).isEqualTo("POST"); - assertThat(request.getParameter(token.getParameterName())) - .isEqualTo(token.getToken()); + assertThat(request.getParameter(token.getParameterName())).isEqualTo(token.getToken()); assertThat(request.getRequestURI()).isEqualTo("/uri-login/val1/val2"); } /** - * spring-restdocs uses postprocessors to do its trick. It will work only if these are merged together - * with our request builders. (gh-7572) + * spring-restdocs uses postprocessors to do its trick. It will work only if these are + * merged together with our request builders. (gh-7572) * @throws Exception */ @Test @@ -103,9 +101,7 @@ public class SecurityMockMvcRequestBuildersFormLoginTests { RequestPostProcessor postProcessor = mock(RequestPostProcessor.class); when(postProcessor.postProcessRequest(any())).thenAnswer(i -> i.getArgument(0)); MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new Object()) - .defaultRequest(MockMvcRequestBuilders.get("/").with(postProcessor)) - .build(); - + .defaultRequest(MockMvcRequestBuilders.get("/").with(postProcessor)).build(); MvcResult mvcResult = mockMvc.perform(formLogin()).andReturn(); assertThat(mvcResult.getRequest().getMethod()).isEqualTo(HttpMethod.POST.name()); @@ -121,10 +117,10 @@ public class SecurityMockMvcRequestBuildersFormLoginTests { // gh-3920 @Test public void usesAcceptMediaForContentNegotiation() { - MockHttpServletRequest request = formLogin("/login").user("username", "admin") - .password("password", "secret").buildRequest(this.servletContext); + MockHttpServletRequest request = formLogin("/login").user("username", "admin").password("password", "secret") + .buildRequest(this.servletContext); - assertThat(request.getHeader("Accept")) - .isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE); + assertThat(request.getHeader("Accept")).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED_VALUE); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestBuildersFormLogoutTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestBuildersFormLogoutTests.java index b6271e9409..a65ba5a5d0 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestBuildersFormLogoutTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestBuildersFormLogoutTests.java @@ -39,6 +39,7 @@ import static org.powermock.api.mockito.PowerMockito.when; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.logout; public class SecurityMockMvcRequestBuildersFormLogoutTests { + private MockServletContext servletContext; @Before @@ -50,43 +51,42 @@ public class SecurityMockMvcRequestBuildersFormLogoutTests { public void defaults() { MockHttpServletRequest request = logout().buildRequest(servletContext); - CsrfToken token = (CsrfToken) request.getAttribute(CsrfRequestPostProcessor.TestCsrfTokenRepository.TOKEN_ATTR_NAME); + CsrfToken token = (CsrfToken) request + .getAttribute(CsrfRequestPostProcessor.TestCsrfTokenRepository.TOKEN_ATTR_NAME); assertThat(request.getMethod()).isEqualTo("POST"); - assertThat(request.getParameter(token.getParameterName())).isEqualTo( - token.getToken()); + assertThat(request.getParameter(token.getParameterName())).isEqualTo(token.getToken()); assertThat(request.getRequestURI()).isEqualTo("/logout"); } @Test public void custom() { - MockHttpServletRequest request = logout("/admin/logout").buildRequest( - servletContext); + MockHttpServletRequest request = logout("/admin/logout").buildRequest(servletContext); - CsrfToken token = (CsrfToken) request.getAttribute(CsrfRequestPostProcessor.TestCsrfTokenRepository.TOKEN_ATTR_NAME); + CsrfToken token = (CsrfToken) request + .getAttribute(CsrfRequestPostProcessor.TestCsrfTokenRepository.TOKEN_ATTR_NAME); assertThat(request.getMethod()).isEqualTo("POST"); - assertThat(request.getParameter(token.getParameterName())).isEqualTo( - token.getToken()); + assertThat(request.getParameter(token.getParameterName())).isEqualTo(token.getToken()); assertThat(request.getRequestURI()).isEqualTo("/admin/logout"); } @Test public void customWithUriVars() { - MockHttpServletRequest request = logout().logoutUrl("/uri-logout/{var1}/{var2}", "val1", "val2").buildRequest( - servletContext); + MockHttpServletRequest request = logout().logoutUrl("/uri-logout/{var1}/{var2}", "val1", "val2") + .buildRequest(servletContext); - CsrfToken token = (CsrfToken) request.getAttribute(CsrfRequestPostProcessor.TestCsrfTokenRepository.TOKEN_ATTR_NAME); + CsrfToken token = (CsrfToken) request + .getAttribute(CsrfRequestPostProcessor.TestCsrfTokenRepository.TOKEN_ATTR_NAME); assertThat(request.getMethod()).isEqualTo("POST"); - assertThat(request.getParameter(token.getParameterName())).isEqualTo( - token.getToken()); + assertThat(request.getParameter(token.getParameterName())).isEqualTo(token.getToken()); assertThat(request.getRequestURI()).isEqualTo("/uri-logout/val1/val2"); } /** - * spring-restdocs uses postprocessors to do its trick. It will work only if these are merged together - * with our request builders. (gh-7572) + * spring-restdocs uses postprocessors to do its trick. It will work only if these are + * merged together with our request builders. (gh-7572) * @throws Exception */ @Test @@ -94,8 +94,7 @@ public class SecurityMockMvcRequestBuildersFormLogoutTests { RequestPostProcessor postProcessor = mock(RequestPostProcessor.class); when(postProcessor.postProcessRequest(any())).thenAnswer(i -> i.getArgument(0)); MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new Object()) - .defaultRequest(MockMvcRequestBuilders.get("/").with(postProcessor)) - .build(); + .defaultRequest(MockMvcRequestBuilders.get("/").with(postProcessor)).build(); MvcResult mvcResult = mockMvc.perform(logout()).andReturn(); assertThat(mvcResult.getRequest().getMethod()).isEqualTo(HttpMethod.POST.name()); @@ -105,4 +104,5 @@ public class SecurityMockMvcRequestBuildersFormLogoutTests { assertThat(mvcResult.getRequest().getParameter("_csrf")).isNotEmpty(); verify(postProcessor).postProcessRequest(any()); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests.java index 51c92c5032..a7dd2d0c4a 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests.java @@ -92,10 +92,14 @@ public class SecurityMockMvcRequestPostProcessorsAuthenticationStatelessTests { @RestController static class Controller { + @RequestMapping public String hello() { return "Hello"; } + } + } + } \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationTests.java index 357e386719..9a8f0d392f 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsAuthenticationTests.java @@ -44,10 +44,13 @@ import org.springframework.security.web.context.SecurityContextRepository; @RunWith(PowerMockRunner.class) @PrepareOnlyThisForTest(WebTestUtils.class) -@PowerMockIgnore({"javax.security.auth.*", "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", "javax.xml.parsers.*"}) +@PowerMockIgnore({ "javax.security.auth.*", "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", + "javax.xml.parsers.*" }) public class SecurityMockMvcRequestPostProcessorsAuthenticationTests { + @Captor private ArgumentCaptor contextCaptor; + @Mock private SecurityContextRepository repository; @@ -71,8 +74,7 @@ public class SecurityMockMvcRequestPostProcessorsAuthenticationTests { public void userDetails() { authentication(authentication).postProcessRequest(request); - verify(repository).saveContext(contextCaptor.capture(), eq(request), - any(HttpServletResponse.class)); + verify(repository).saveContext(contextCaptor.capture(), eq(request), any(HttpServletResponse.class)); SecurityContext context = contextCaptor.getValue(); assertThat(context.getAuthentication()).isSameAs(authentication); } @@ -81,4 +83,5 @@ public class SecurityMockMvcRequestPostProcessorsAuthenticationTests { spy(WebTestUtils.class); when(WebTestUtils.getSecurityContextRepository(request)).thenReturn(repository); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCertificateTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCertificateTests.java index 2d471ebb38..0953513cdb 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCertificateTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCertificateTests.java @@ -29,6 +29,7 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock @RunWith(MockitoJUnitRunner.class) public class SecurityMockMvcRequestPostProcessorsCertificateTests { + @Mock private X509Certificate certificate; @@ -41,8 +42,7 @@ public class SecurityMockMvcRequestPostProcessorsCertificateTests { @Test public void x509SingleCertificate() { - MockHttpServletRequest postProcessedRequest = x509(certificate) - .postProcessRequest(request); + MockHttpServletRequest postProcessedRequest = x509(certificate).postProcessRequest(request); X509Certificate[] certificates = (X509Certificate[]) postProcessedRequest .getAttribute("javax.servlet.request.X509Certificate"); @@ -52,14 +52,14 @@ public class SecurityMockMvcRequestPostProcessorsCertificateTests { @Test public void x509ResourceName() throws Exception { - MockHttpServletRequest postProcessedRequest = x509("rod.cer").postProcessRequest( - request); + MockHttpServletRequest postProcessedRequest = x509("rod.cer").postProcessRequest(request); X509Certificate[] certificates = (X509Certificate[]) postProcessedRequest .getAttribute("javax.servlet.request.X509Certificate"); assertThat(certificates).hasSize(1); - assertThat(certificates[0].getSubjectDN().getName()).isEqualTo( - "CN=rod, OU=Spring Security, O=Spring Framework"); + assertThat(certificates[0].getSubjectDN().getName()) + .isEqualTo("CN=rod, OU=Spring Security, O=Spring Framework"); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCsrfDebugFilterTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCsrfDebugFilterTests.java index b65a219236..7c7d9923d0 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCsrfDebugFilterTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCsrfDebugFilterTests.java @@ -53,6 +53,7 @@ public class SecurityMockMvcRequestPostProcessorsCsrfDebugFilterTests { @EnableWebSecurity static class Config extends WebSecurityConfigurerAdapter { + static CsrfTokenRepository cookieCsrfTokenRepository = new CookieCsrfTokenRepository(); @Override @@ -65,5 +66,7 @@ public class SecurityMockMvcRequestPostProcessorsCsrfDebugFilterTests { // Enable the DebugFilter web.debug(true); } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCsrfTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCsrfTests.java index 26caba94e7..cfdd8d009a 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCsrfTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCsrfTests.java @@ -62,10 +62,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @ContextConfiguration @WebAppConfiguration public class SecurityMockMvcRequestPostProcessorsCsrfTests { + @Autowired WebApplicationContext wac; + @Autowired TheController controller; + @Autowired FilterChainProxy springSecurityFilterChain; @@ -177,6 +180,7 @@ public class SecurityMockMvcRequestPostProcessorsCsrfTests { assertThat(request.getParameter("_csrf")).isNotNull(); assertThat(request.getHeader("X-CSRF-TOKEN")).isNull(); } + } public static ResultMatcher csrfAsHeader() { @@ -191,18 +195,19 @@ public class SecurityMockMvcRequestPostProcessorsCsrfTests { assertThat(request.getParameter("_csrf")).isNull(); assertThat(request.getHeader("X-CSRF-TOKEN")).isNotNull(); } + } static class SessionRepositoryFilter extends OncePerRequestFilter { @Override - protected void doFilterInternal(HttpServletRequest request, - HttpServletResponse response, FilterChain filterChain) - throws ServletException, IOException { + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { filterChain.doFilter(new SessionRequestWrapper(request), response); } static class SessionRequestWrapper extends HttpServletRequestWrapper { + HttpSession session = new MockHttpSession(); SessionRequestWrapper(HttpServletRequest request) { @@ -218,21 +223,28 @@ public class SecurityMockMvcRequestPostProcessorsCsrfTests { public HttpSession getSession() { return this.session; } + } + } @EnableWebSecurity static class Config extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) { } @RestController static class TheController { + @RequestMapping("/") String index() { return "Hi"; } + } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsDigestTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsDigestTests.java index 39bae21942..412a3bce13 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsDigestTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsDigestTests.java @@ -39,6 +39,7 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock public class SecurityMockMvcRequestPostProcessorsDigestTests { private DigestAuthenticationFilter filter; + private MockHttpServletRequest request; private String username; @@ -56,8 +57,8 @@ public class SecurityMockMvcRequestPostProcessorsDigestTests { entryPoint.setKey("key"); entryPoint.setRealmName("Spring Security"); filter = new DigestAuthenticationFilter(); - filter.setUserDetailsService(username -> new User(username, password, AuthorityUtils - .createAuthorityList("ROLE_USER"))); + filter.setUserDetailsService( + username -> new User(username, password, AuthorityUtils.createAuthorityList("ROLE_USER"))); filter.setAuthenticationEntryPoint(entryPoint); filter.afterPropertiesSet(); } @@ -69,8 +70,7 @@ public class SecurityMockMvcRequestPostProcessorsDigestTests { @Test public void digestWithFilter() throws Exception { - MockHttpServletRequest postProcessedRequest = digest() - .postProcessRequest(request); + MockHttpServletRequest postProcessedRequest = digest().postProcessRequest(request); assertThat(extractUser()).isEqualTo("user"); } @@ -78,8 +78,7 @@ public class SecurityMockMvcRequestPostProcessorsDigestTests { @Test public void digestWithFilterCustomUsername() throws Exception { String username = "admin"; - MockHttpServletRequest postProcessedRequest = digest(username) - .postProcessRequest(request); + MockHttpServletRequest postProcessedRequest = digest(username).postProcessRequest(request); assertThat(extractUser()).isEqualTo(username); } @@ -88,8 +87,7 @@ public class SecurityMockMvcRequestPostProcessorsDigestTests { public void digestWithFilterCustomPassword() throws Exception { String username = "custom"; password = "secret"; - MockHttpServletRequest postProcessedRequest = digest(username).password(password) - .postProcessRequest(request); + MockHttpServletRequest postProcessedRequest = digest(username).password(password).postProcessRequest(request); assertThat(extractUser()).isEqualTo(username); } @@ -98,8 +96,8 @@ public class SecurityMockMvcRequestPostProcessorsDigestTests { public void digestWithFilterCustomRealm() throws Exception { String username = "admin"; entryPoint.setRealmName("Custom"); - MockHttpServletRequest postProcessedRequest = digest(username).realm( - entryPoint.getRealmName()).postProcessRequest(request); + MockHttpServletRequest postProcessedRequest = digest(username).realm(entryPoint.getRealmName()) + .postProcessRequest(request); assertThat(extractUser()).isEqualTo(username); } @@ -107,8 +105,7 @@ public class SecurityMockMvcRequestPostProcessorsDigestTests { @Test public void digestWithFilterFails() throws Exception { String username = "admin"; - MockHttpServletRequest postProcessedRequest = digest(username).realm("Invalid") - .postProcessRequest(request); + MockHttpServletRequest postProcessedRequest = digest(username).realm("Invalid").postProcessRequest(request); assertThat(extractUser()).isNull(); } @@ -117,11 +114,11 @@ public class SecurityMockMvcRequestPostProcessorsDigestTests { filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain() { @Override public void doFilter(ServletRequest request, ServletResponse response) { - Authentication authentication = SecurityContextHolder.getContext() - .getAuthentication(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); username = authentication == null ? null : authentication.getName(); } }); return username; } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsJwtTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsJwtTests.java index 24441de7dc..2e1e95039a 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsJwtTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsJwtTests.java @@ -60,6 +60,7 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock */ @RunWith(MockitoJUnitRunner.class) public class SecurityMockMvcRequestPostProcessorsJwtTests { + @Captor private ArgumentCaptor contextCaptor; @@ -70,6 +71,7 @@ public class SecurityMockMvcRequestPostProcessorsJwtTests { @Mock private GrantedAuthority authority1; + @Mock private GrantedAuthority authority2; @@ -95,8 +97,7 @@ public class SecurityMockMvcRequestPostProcessorsJwtTests { verify(this.repository).saveContext(this.contextCaptor.capture(), eq(this.request), any(HttpServletResponse.class)); SecurityContext context = this.contextCaptor.getValue(); - assertThat(context.getAuthentication()).isInstanceOf( - JwtAuthenticationToken.class); + assertThat(context.getAuthentication()).isInstanceOf(JwtAuthenticationToken.class); JwtAuthenticationToken token = (JwtAuthenticationToken) context.getAuthentication(); assertThat(token.getAuthorities()).isNotEmpty(); assertThat(token.getToken()).isNotNull(); @@ -112,57 +113,48 @@ public class SecurityMockMvcRequestPostProcessorsJwtTests { verify(this.repository).saveContext(this.contextCaptor.capture(), eq(this.request), any(HttpServletResponse.class)); SecurityContext context = this.contextCaptor.getValue(); - assertThat(context.getAuthentication()).isInstanceOf( - JwtAuthenticationToken.class); + assertThat(context.getAuthentication()).isInstanceOf(JwtAuthenticationToken.class); JwtAuthenticationToken token = (JwtAuthenticationToken) context.getAuthentication(); assertThat(token.getToken().getSubject()).isSameAs(name); } @Test public void jwtWhenProvidingCustomAuthoritiesThenProducesJwtAuthentication() { - jwt().jwt(jwt -> jwt.claim("scope", "ignored authorities")) - .authorities(this.authority1, this.authority2) + jwt().jwt(jwt -> jwt.claim("scope", "ignored authorities")).authorities(this.authority1, this.authority2) .postProcessRequest(this.request); verify(this.repository).saveContext(this.contextCaptor.capture(), eq(this.request), any(HttpServletResponse.class)); SecurityContext context = this.contextCaptor.getValue(); - assertThat((List) context.getAuthentication().getAuthorities()) - .containsOnly(this.authority1, this.authority2); + assertThat((List) context.getAuthentication().getAuthorities()).containsOnly(this.authority1, + this.authority2); } @Test public void jwtWhenProvidingScopedAuthoritiesThenProducesJwtAuthentication() { - jwt().jwt(jwt -> jwt.claim("scope", "scoped authorities")) - .postProcessRequest(this.request); + jwt().jwt(jwt -> jwt.claim("scope", "scoped authorities")).postProcessRequest(this.request); verify(this.repository).saveContext(this.contextCaptor.capture(), eq(this.request), any(HttpServletResponse.class)); SecurityContext context = this.contextCaptor.getValue(); - assertThat((List) context.getAuthentication().getAuthorities()) - .containsOnly(new SimpleGrantedAuthority("SCOPE_scoped"), - new SimpleGrantedAuthority("SCOPE_authorities")); + assertThat((List) context.getAuthentication().getAuthorities()).containsOnly( + new SimpleGrantedAuthority("SCOPE_scoped"), new SimpleGrantedAuthority("SCOPE_authorities")); } @Test public void jwtWhenProvidingGrantedAuthoritiesThenProducesJwtAuthentication() { - jwt().jwt(jwt -> jwt.claim("scope", "ignored authorities")) - .authorities(jwt -> Arrays.asList(this.authority1)) + jwt().jwt(jwt -> jwt.claim("scope", "ignored authorities")).authorities(jwt -> Arrays.asList(this.authority1)) .postProcessRequest(this.request); verify(this.repository).saveContext(this.contextCaptor.capture(), eq(this.request), any(HttpServletResponse.class)); SecurityContext context = this.contextCaptor.getValue(); - assertThat((List) context.getAuthentication().getAuthorities()) - .containsOnly(this.authority1); + assertThat((List) context.getAuthentication().getAuthorities()).containsOnly(this.authority1); } @Test public void jwtWhenProvidingPreparedJwtThenUsesItForAuthentication() { - Jwt originalToken = TestJwts.jwt() - .header("header1", "value1") - .subject("some_user") - .build(); + Jwt originalToken = TestJwts.jwt().header("header1", "value1").subject("some_user").build(); jwt().jwt(originalToken).postProcessRequest(this.request); verify(this.repository).saveContext(this.contextCaptor.capture(), eq(this.request), @@ -173,4 +165,5 @@ public class SecurityMockMvcRequestPostProcessorsJwtTests { assertThat(retrievedToken.getToken().getTokenValue()).isEqualTo("token"); assertThat(retrievedToken.getToken().getHeaders().get("header1")).isEqualTo("value1"); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2ClientTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2ClientTests.java index 0f2b0e75ff..4814f4b0f8 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2ClientTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2ClientTests.java @@ -69,6 +69,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @ContextConfiguration @WebAppConfiguration public class SecurityMockMvcRequestPostProcessorsOAuth2ClientTests { + @Autowired WebApplicationContext context; @@ -89,19 +90,15 @@ public class SecurityMockMvcRequestPostProcessorsOAuth2ClientTests { TestSecurityContextHolder.clearContext(); } - @Test - public void oauth2ClientWhenUsingDefaultsThenException() - throws Exception { + public void oauth2ClientWhenUsingDefaultsThenException() throws Exception { assertThatCode(() -> oauth2Client().postProcessRequest(new MockHttpServletRequest())) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("ClientRegistration"); + .isInstanceOf(IllegalArgumentException.class).hasMessageContaining("ClientRegistration"); } @Test - public void oauth2ClientWhenUsingDefaultsThenProducesDefaultAuthorizedClient() - throws Exception { + public void oauth2ClientWhenUsingDefaultsThenProducesDefaultAuthorizedClient() throws Exception { this.mvc.perform(get("/access-token").with(oauth2Client("registration-id"))) .andExpect(content().string("access-token")); @@ -110,19 +107,16 @@ public class SecurityMockMvcRequestPostProcessorsOAuth2ClientTests { } @Test - public void oauth2ClientWhenClientRegistrationThenUses() - throws Exception { + public void oauth2ClientWhenClientRegistrationThenUses() throws Exception { - ClientRegistration clientRegistration = clientRegistration() - .registrationId("registration-id").clientId("client-id").build(); - this.mvc.perform(get("/client-id") - .with(oauth2Client().clientRegistration(clientRegistration))) + ClientRegistration clientRegistration = clientRegistration().registrationId("registration-id") + .clientId("client-id").build(); + this.mvc.perform(get("/client-id").with(oauth2Client().clientRegistration(clientRegistration))) .andExpect(content().string("client-id")); } @Test - public void oauth2ClientWhenClientRegistrationConsumerThenUses() - throws Exception { + public void oauth2ClientWhenClientRegistrationConsumerThenUses() throws Exception { this.mvc.perform(get("/client-id") .with(oauth2Client("registration-id").clientRegistration(c -> c.clientId("client-id")))) @@ -131,38 +125,35 @@ public class SecurityMockMvcRequestPostProcessorsOAuth2ClientTests { @Test public void oauth2ClientWhenPrincipalNameThenUses() throws Exception { - this.mvc.perform(get("/principal-name") - .with(oauth2Client("registration-id").principalName("test-subject"))) + this.mvc.perform(get("/principal-name").with(oauth2Client("registration-id").principalName("test-subject"))) .andExpect(content().string("test-subject")); } @Test public void oauth2ClientWhenAccessTokenThenUses() throws Exception { OAuth2AccessToken accessToken = noScopes(); - this.mvc.perform(get("/access-token") - .with(oauth2Client("registration-id").accessToken(accessToken))) + this.mvc.perform(get("/access-token").with(oauth2Client("registration-id").accessToken(accessToken))) .andExpect(content().string("no-scopes")); } @Test public void oauth2ClientWhenUsedOnceThenDoesNotAffectRemainingTests() throws Exception { - this.mvc.perform(get("/client-id") - .with(oauth2Client("registration-id"))) + this.mvc.perform(get("/client-id").with(oauth2Client("registration-id"))) .andExpect(content().string("test-client")); OAuth2AuthorizedClient client = new OAuth2AuthorizedClient(clientRegistration().build(), "sub", noScopes()); OAuth2AuthorizedClientRepository repository = this.context.getBean(OAuth2AuthorizedClientRepository.class); - when(repository.loadAuthorizedClient(eq("registration-id"), any(Authentication.class), any(HttpServletRequest.class))) - .thenReturn(client); - this.mvc.perform(get("/client-id")) - .andExpect(content().string("client-id")); - verify(repository).loadAuthorizedClient( - eq("registration-id"), any(Authentication.class), any(HttpServletRequest.class)); + when(repository.loadAuthorizedClient(eq("registration-id"), any(Authentication.class), + any(HttpServletRequest.class))).thenReturn(client); + this.mvc.perform(get("/client-id")).andExpect(content().string("client-id")); + verify(repository).loadAuthorizedClient(eq("registration-id"), any(Authentication.class), + any(HttpServletRequest.class)); } @EnableWebSecurity @EnableWebMvc static class OAuth2ClientConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -179,7 +170,6 @@ public class SecurityMockMvcRequestPostProcessorsOAuth2ClientTests { return mock(ClientRegistrationRepository.class); } - @Bean OAuth2AuthorizedClientRepository authorizedClientRepository() { return mock(OAuth2AuthorizedClientRepository.class); @@ -187,20 +177,27 @@ public class SecurityMockMvcRequestPostProcessorsOAuth2ClientTests { @RestController static class PrincipalController { + @GetMapping("/access-token") - String accessToken(@RegisteredOAuth2AuthorizedClient("registration-id") OAuth2AuthorizedClient authorizedClient) { + String accessToken( + @RegisteredOAuth2AuthorizedClient("registration-id") OAuth2AuthorizedClient authorizedClient) { return authorizedClient.getAccessToken().getTokenValue(); } @GetMapping("/principal-name") - String principalName(@RegisteredOAuth2AuthorizedClient("registration-id") OAuth2AuthorizedClient authorizedClient) { + String principalName( + @RegisteredOAuth2AuthorizedClient("registration-id") OAuth2AuthorizedClient authorizedClient) { return authorizedClient.getPrincipalName(); } @GetMapping("/client-id") - String clientId(@RegisteredOAuth2AuthorizedClient("registration-id") OAuth2AuthorizedClient authorizedClient) { + String clientId( + @RegisteredOAuth2AuthorizedClient("registration-id") OAuth2AuthorizedClient authorizedClient) { return authorizedClient.getClientRegistration().getClientId(); } + } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2LoginTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2LoginTests.java index deb4d0bb9d..d01a9809c6 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2LoginTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOAuth2LoginTests.java @@ -69,6 +69,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @ContextConfiguration @WebAppConfiguration public class SecurityMockMvcRequestPostProcessorsOAuth2LoginTests { + @Autowired WebApplicationContext context; @@ -85,86 +86,69 @@ public class SecurityMockMvcRequestPostProcessorsOAuth2LoginTests { } @Test - public void oauth2LoginWhenUsingDefaultsThenProducesDefaultAuthentication() - throws Exception { + public void oauth2LoginWhenUsingDefaultsThenProducesDefaultAuthentication() throws Exception { - this.mvc.perform(get("/name").with(oauth2Login())) - .andExpect(content().string("user")); - this.mvc.perform(get("/admin/id-token/name").with(oauth2Login())) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/name").with(oauth2Login())).andExpect(content().string("user")); + this.mvc.perform(get("/admin/id-token/name").with(oauth2Login())).andExpect(status().isForbidden()); } @Test - public void oauth2LoginWhenUsingDefaultsThenProducesDefaultAuthorizedClient() - throws Exception { + public void oauth2LoginWhenUsingDefaultsThenProducesDefaultAuthorizedClient() throws Exception { - this.mvc.perform(get("/client-id").with(oauth2Login())) - .andExpect(content().string("test-client")); + this.mvc.perform(get("/client-id").with(oauth2Login())).andExpect(content().string("test-client")); } @Test public void oauth2LoginWhenAuthoritiesSpecifiedThenGrantsAccess() throws Exception { - this.mvc.perform(get("/admin/scopes") - .with(oauth2Login().authorities(new SimpleGrantedAuthority("SCOPE_admin")))) + this.mvc.perform( + get("/admin/scopes").with(oauth2Login().authorities(new SimpleGrantedAuthority("SCOPE_admin")))) .andExpect(content().string("[\"SCOPE_admin\"]")); } @Test public void oauth2LoginWhenAttributeSpecifiedThenUserHasAttribute() throws Exception { - this.mvc.perform(get("/attributes/iss") - .with(oauth2Login().attributes(a -> a.put("iss", "https://idp.example.org")))) + this.mvc.perform( + get("/attributes/iss").with(oauth2Login().attributes(a -> a.put("iss", "https://idp.example.org")))) .andExpect(content().string("https://idp.example.org")); } @Test public void oauth2LoginWhenNameSpecifiedThenUserHasName() throws Exception { - OAuth2User oauth2User = new DefaultOAuth2User( - AuthorityUtils.commaSeparatedStringToAuthorityList("SCOPE_read"), - Collections.singletonMap("custom-attribute", "test-subject"), - "custom-attribute"); - this.mvc.perform(get("/attributes/custom-attribute") - .with(oauth2Login().oauth2User(oauth2User))) + OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.commaSeparatedStringToAuthorityList("SCOPE_read"), + Collections.singletonMap("custom-attribute", "test-subject"), "custom-attribute"); + this.mvc.perform(get("/attributes/custom-attribute").with(oauth2Login().oauth2User(oauth2User))) .andExpect(content().string("test-subject")); - this.mvc.perform(get("/name") - .with(oauth2Login().oauth2User(oauth2User))) + this.mvc.perform(get("/name").with(oauth2Login().oauth2User(oauth2User))) .andExpect(content().string("test-subject")); - this.mvc.perform(get("/client-name") - .with(oauth2Login().oauth2User(oauth2User))) + this.mvc.perform(get("/client-name").with(oauth2Login().oauth2User(oauth2User))) .andExpect(content().string("test-subject")); } @Test public void oauth2LoginWhenClientRegistrationSpecifiedThenUses() throws Exception { - this.mvc.perform(get("/client-id") - .with(oauth2Login().clientRegistration(clientRegistration().build()))) + this.mvc.perform(get("/client-id").with(oauth2Login().clientRegistration(clientRegistration().build()))) .andExpect(content().string("client-id")); } @Test public void oauth2LoginWhenOAuth2UserSpecifiedThenLastCalledTakesPrecedence() throws Exception { - OAuth2User oauth2User = new DefaultOAuth2User( - AuthorityUtils.createAuthorityList("SCOPE_read"), - Collections.singletonMap("username", "user"), - "username"); + OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("SCOPE_read"), + Collections.singletonMap("username", "user"), "username"); - this.mvc.perform(get("/attributes/sub") - .with(oauth2Login() - .attributes(a -> a.put("sub", "bar")) - .oauth2User(oauth2User))) - .andExpect(status().isOk()) - .andExpect(content().string("no-attribute")); - this.mvc.perform(get("/attributes/sub") - .with(oauth2Login() - .oauth2User(oauth2User) - .attributes(a -> a.put("sub", "bar")))) + this.mvc.perform( + get("/attributes/sub").with(oauth2Login().attributes(a -> a.put("sub", "bar")).oauth2User(oauth2User))) + .andExpect(status().isOk()).andExpect(content().string("no-attribute")); + this.mvc.perform( + get("/attributes/sub").with(oauth2Login().oauth2User(oauth2User).attributes(a -> a.put("sub", "bar")))) .andExpect(content().string("bar")); } @EnableWebSecurity @EnableWebMvc static class OAuth2LoginConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -188,6 +172,7 @@ public class SecurityMockMvcRequestPostProcessorsOAuth2LoginTests { @RestController static class PrincipalController { + @GetMapping("/name") String name(@AuthenticationPrincipal OAuth2User oauth2User) { return oauth2User.getName(); @@ -204,8 +189,8 @@ public class SecurityMockMvcRequestPostProcessorsOAuth2LoginTests { } @GetMapping("/attributes/{attribute}") - String attributes( - @AuthenticationPrincipal OAuth2User oauth2User, @PathVariable("attribute") String attribute) { + String attributes(@AuthenticationPrincipal OAuth2User oauth2User, + @PathVariable("attribute") String attribute) { return Optional.ofNullable((String) oauth2User.getAttribute(attribute)).orElse("no-attribute"); } @@ -214,9 +199,11 @@ public class SecurityMockMvcRequestPostProcessorsOAuth2LoginTests { List scopes( @AuthenticationPrincipal(expression = "authorities") Collection authorities) { - return authorities.stream().map(GrantedAuthority::getAuthority) - .collect(Collectors.toList()); + return authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()); } + } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOidcLoginTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOidcLoginTests.java index 6171c335f5..efecfc0395 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOidcLoginTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOidcLoginTests.java @@ -70,6 +70,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @ContextConfiguration @WebAppConfiguration public class SecurityMockMvcRequestPostProcessorsOidcLoginTests { + @Autowired WebApplicationContext context; @@ -91,86 +92,66 @@ public class SecurityMockMvcRequestPostProcessorsOidcLoginTests { } @Test - public void oidcLoginWhenUsingDefaultsThenProducesDefaultAuthentication() - throws Exception { + public void oidcLoginWhenUsingDefaultsThenProducesDefaultAuthentication() throws Exception { - this.mvc.perform(get("/name").with(oidcLogin())) - .andExpect(content().string("user")); - this.mvc.perform(get("/admin/id-token/name").with(oidcLogin())) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/name").with(oidcLogin())).andExpect(content().string("user")); + this.mvc.perform(get("/admin/id-token/name").with(oidcLogin())).andExpect(status().isForbidden()); } @Test - public void oidcLoginWhenUsingDefaultsThenProducesDefaultAuthorizedClient() - throws Exception { + public void oidcLoginWhenUsingDefaultsThenProducesDefaultAuthorizedClient() throws Exception { - this.mvc.perform(get("/access-token").with(oidcLogin())) - .andExpect(content().string("access-token")); + this.mvc.perform(get("/access-token").with(oidcLogin())).andExpect(content().string("access-token")); } @Test public void oidcLoginWhenAuthoritiesSpecifiedThenGrantsAccess() throws Exception { - this.mvc.perform(get("/admin/scopes") - .with(oidcLogin().authorities(new SimpleGrantedAuthority("SCOPE_admin")))) + this.mvc.perform(get("/admin/scopes").with(oidcLogin().authorities(new SimpleGrantedAuthority("SCOPE_admin")))) .andExpect(content().string("[\"SCOPE_admin\"]")); } @Test public void oidcLoginWhenIdTokenSpecifiedThenUserHasClaims() throws Exception { - this.mvc.perform(get("/id-token/iss") - .with(oidcLogin().idToken(i -> i.issuer("https://idp.example.org")))) + this.mvc.perform(get("/id-token/iss").with(oidcLogin().idToken(i -> i.issuer("https://idp.example.org")))) .andExpect(content().string("https://idp.example.org")); } @Test public void oidcLoginWhenUserInfoSpecifiedThenUserHasClaims() throws Exception { - this.mvc.perform(get("/user-info/email") - .with(oidcLogin().userInfoToken(u -> u.email("email@email")))) + this.mvc.perform(get("/user-info/email").with(oidcLogin().userInfoToken(u -> u.email("email@email")))) .andExpect(content().string("email@email")); } @Test public void oidcLoginWhenNameSpecifiedThenUserHasName() throws Exception { - OidcUser oidcUser = new DefaultOidcUser( - AuthorityUtils.commaSeparatedStringToAuthorityList("SCOPE_read"), + OidcUser oidcUser = new DefaultOidcUser(AuthorityUtils.commaSeparatedStringToAuthorityList("SCOPE_read"), OidcIdToken.withTokenValue("id-token").claim("custom-attribute", "test-subject").build(), "custom-attribute"); - this.mvc.perform(get("/id-token/custom-attribute") - .with(oidcLogin().oidcUser(oidcUser))) + this.mvc.perform(get("/id-token/custom-attribute").with(oidcLogin().oidcUser(oidcUser))) .andExpect(content().string("test-subject")); - this.mvc.perform(get("/name") - .with(oidcLogin().oidcUser(oidcUser))) - .andExpect(content().string("test-subject")); + this.mvc.perform(get("/name").with(oidcLogin().oidcUser(oidcUser))).andExpect(content().string("test-subject")); - this.mvc.perform(get("/client-name") - .with(oidcLogin().oidcUser(oidcUser))) + this.mvc.perform(get("/client-name").with(oidcLogin().oidcUser(oidcUser))) .andExpect(content().string("test-subject")); } // gh-7794 @Test public void oidcLoginWhenOidcUserSpecifiedThenLastCalledTakesPrecedence() throws Exception { - OidcUser oidcUser = new DefaultOidcUser( - AuthorityUtils.createAuthorityList("SCOPE_read"), idToken().build()); + OidcUser oidcUser = new DefaultOidcUser(AuthorityUtils.createAuthorityList("SCOPE_read"), idToken().build()); - this.mvc.perform(get("/id-token/sub") - .with(oidcLogin() - .idToken(i -> i.subject("foo")) - .oidcUser(oidcUser))) - .andExpect(status().isOk()) - .andExpect(content().string("subject")); - this.mvc.perform(get("/id-token/sub") - .with(oidcLogin() - .oidcUser(oidcUser) - .idToken(i -> i.subject("bar")))) + this.mvc.perform(get("/id-token/sub").with(oidcLogin().idToken(i -> i.subject("foo")).oidcUser(oidcUser))) + .andExpect(status().isOk()).andExpect(content().string("subject")); + this.mvc.perform(get("/id-token/sub").with(oidcLogin().oidcUser(oidcUser).idToken(i -> i.subject("bar")))) .andExpect(content().string("bar")); } @EnableWebSecurity @EnableWebMvc static class OAuth2LoginConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -188,7 +169,6 @@ public class SecurityMockMvcRequestPostProcessorsOidcLoginTests { return mock(ClientRegistrationRepository.class); } - @Bean OAuth2AuthorizedClientRepository oAuth2AuthorizedClientRepository() { return mock(OAuth2AuthorizedClientRepository.class); @@ -196,6 +176,7 @@ public class SecurityMockMvcRequestPostProcessorsOidcLoginTests { @RestController static class PrincipalController { + @GetMapping("/name") String name(@AuthenticationPrincipal OidcUser oidcUser) { return oidcUser.getName(); @@ -222,11 +203,13 @@ public class SecurityMockMvcRequestPostProcessorsOidcLoginTests { } @GetMapping("/admin/scopes") - List scopes(@AuthenticationPrincipal(expression = "authorities") - Collection authorities) { - return authorities.stream().map(GrantedAuthority::getAuthority) - .collect(Collectors.toList()); + List scopes( + @AuthenticationPrincipal(expression = "authorities") Collection authorities) { + return authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()); } + } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOpaqueTokenTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOpaqueTokenTests.java index 572b672e81..53dd72627f 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOpaqueTokenTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsOpaqueTokenTests.java @@ -64,6 +64,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @ContextConfiguration @WebAppConfiguration public class SecurityMockMvcRequestPostProcessorsOpaqueTokenTests { + @Autowired WebApplicationContext context; @@ -80,19 +81,16 @@ public class SecurityMockMvcRequestPostProcessorsOpaqueTokenTests { } @Test - public void opaqueTokenWhenUsingDefaultsThenProducesDefaultAuthentication() - throws Exception { + public void opaqueTokenWhenUsingDefaultsThenProducesDefaultAuthentication() throws Exception { - this.mvc.perform(get("/name").with(opaqueToken())) - .andExpect(content().string("user")); - this.mvc.perform(get("/admin/scopes").with(opaqueToken())) - .andExpect(status().isForbidden()); + this.mvc.perform(get("/name").with(opaqueToken())).andExpect(content().string("user")); + this.mvc.perform(get("/admin/scopes").with(opaqueToken())).andExpect(status().isForbidden()); } @Test public void opaqueTokenWhenAttributeSpecifiedThenUserHasAttribute() throws Exception { - this.mvc.perform(get("/opaque-token/iss") - .with(opaqueToken().attributes(a -> a.put("iss", "https://idp.example.org")))) + this.mvc.perform( + get("/opaque-token/iss").with(opaqueToken().attributes(a -> a.put("iss", "https://idp.example.org")))) .andExpect(content().string("https://idp.example.org")); } @@ -103,8 +101,7 @@ public class SecurityMockMvcRequestPostProcessorsOpaqueTokenTests { when(principal.getName()).thenReturn("ben"); when(principal.getAuthorities()).thenReturn(authorities); - this.mvc.perform(get("/name").with(opaqueToken().principal(principal))) - .andExpect(content().string("ben")); + this.mvc.perform(get("/name").with(opaqueToken().principal(principal))).andExpect(content().string("ben")); } // gh-7800 @@ -112,22 +109,18 @@ public class SecurityMockMvcRequestPostProcessorsOpaqueTokenTests { public void opaqueTokenWhenPrincipalSpecifiedThenLastCalledTakesPrecedence() throws Exception { OAuth2AuthenticatedPrincipal principal = active(a -> a.put("scope", "user")); - this.mvc.perform(get("/opaque-token/sub") - .with(opaqueToken() - .attributes(a -> a.put("sub", "foo")) - .principal(principal))) - .andExpect(status().isOk()) - .andExpect(content().string((String) principal.getAttribute("sub"))); - this.mvc.perform(get("/opaque-token/sub") - .with(opaqueToken() - .principal(principal) - .attributes(a -> a.put("sub", "bar")))) + this.mvc.perform( + get("/opaque-token/sub").with(opaqueToken().attributes(a -> a.put("sub", "foo")).principal(principal))) + .andExpect(status().isOk()).andExpect(content().string((String) principal.getAttribute("sub"))); + this.mvc.perform( + get("/opaque-token/sub").with(opaqueToken().principal(principal).attributes(a -> a.put("sub", "bar")))) .andExpect(content().string("bar")); } @EnableWebSecurity @EnableWebMvc static class OAuth2LoginConfig extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off @@ -144,6 +137,7 @@ public class SecurityMockMvcRequestPostProcessorsOpaqueTokenTests { @RestController static class PrincipalController { + @GetMapping("/name") String name(@AuthenticationPrincipal OAuth2AuthenticatedPrincipal principal) { return principal.getName(); @@ -157,12 +151,14 @@ public class SecurityMockMvcRequestPostProcessorsOpaqueTokenTests { } @GetMapping("/admin/scopes") - List scopes(@AuthenticationPrincipal(expression = "authorities") - Collection authorities) { + List scopes( + @AuthenticationPrincipal(expression = "authorities") Collection authorities) { - return authorities.stream().map(GrantedAuthority::getAuthority) - .collect(Collectors.toList()); + return authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()); } + } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsSecurityContextTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsSecurityContextTests.java index 2ba412c1a7..1c64417cfc 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsSecurityContextTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsSecurityContextTests.java @@ -43,10 +43,13 @@ import org.springframework.security.web.context.SecurityContextRepository; @RunWith(PowerMockRunner.class) @PrepareOnlyThisForTest(WebTestUtils.class) -@PowerMockIgnore({"javax.security.auth.*", "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", "javax.xml.parsers.*"}) +@PowerMockIgnore({ "javax.security.auth.*", "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", + "javax.xml.parsers.*" }) public class SecurityMockMvcRequestPostProcessorsSecurityContextTests { + @Captor private ArgumentCaptor contextCaptor; + @Mock private SecurityContextRepository repository; @@ -70,8 +73,7 @@ public class SecurityMockMvcRequestPostProcessorsSecurityContextTests { public void userDetails() { securityContext(expectedContext).postProcessRequest(request); - verify(repository).saveContext(contextCaptor.capture(), eq(request), - any(HttpServletResponse.class)); + verify(repository).saveContext(contextCaptor.capture(), eq(request), any(HttpServletResponse.class)); SecurityContext context = contextCaptor.getValue(); assertThat(context).isSameAs(this.expectedContext); } @@ -80,4 +82,5 @@ public class SecurityMockMvcRequestPostProcessorsSecurityContextTests { spy(WebTestUtils.class); when(WebTestUtils.getSecurityContextRepository(request)).thenReturn(repository); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTests.java index cc01f37ac1..6d30683d18 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTests.java @@ -57,8 +57,7 @@ public class SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTes @Before public void setup() { - mvc = MockMvcBuilders.webAppContextSetup(context) - .addFilters(springSecurityFilterChain) + mvc = MockMvcBuilders.webAppContextSetup(context).addFilters(springSecurityFilterChain) .defaultRequest(get("/").with(testSecurityContext())).build(); } @@ -92,10 +91,14 @@ public class SecurityMockMvcRequestPostProcessorsTestSecurityContextStatelessTes @RestController static class Controller { + @RequestMapping public String hello() { return "Hello"; } + } + } + } \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextTests.java index 65ed0f969b..73f1b42f2d 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsTestSecurityContextTests.java @@ -40,10 +40,13 @@ import org.springframework.security.web.context.SecurityContextRepository; @RunWith(PowerMockRunner.class) @PrepareOnlyThisForTest(WebTestUtils.class) -@PowerMockIgnore({"javax.security.auth.*", "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", "javax.xml.parsers.*"}) +@PowerMockIgnore({ "javax.security.auth.*", "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", + "javax.xml.parsers.*" }) public class SecurityMockMvcRequestPostProcessorsTestSecurityContextTests { + @Mock private SecurityContext context; + @Mock private SecurityContextRepository repository; @@ -66,8 +69,7 @@ public class SecurityMockMvcRequestPostProcessorsTestSecurityContextTests { testSecurityContext().postProcessRequest(request); - verify(repository).saveContext(eq(context), eq(request), - any(HttpServletResponse.class)); + verify(repository).saveContext(eq(context), eq(request), any(HttpServletResponse.class)); } // Ensure it does not fail if TestSecurityContextHolder is not initialized @@ -83,4 +85,5 @@ public class SecurityMockMvcRequestPostProcessorsTestSecurityContextTests { spy(WebTestUtils.class); when(WebTestUtils.getSecurityContextRepository(request)).thenReturn(repository); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsUserDetailsTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsUserDetailsTests.java index c2e8136e52..2e7bee6151 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsUserDetailsTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsUserDetailsTests.java @@ -45,10 +45,13 @@ import org.springframework.security.web.context.SecurityContextRepository; @RunWith(PowerMockRunner.class) @PrepareOnlyThisForTest(WebTestUtils.class) -@PowerMockIgnore({"javax.security.auth.*", "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", "javax.xml.parsers.*"}) +@PowerMockIgnore({ "javax.security.auth.*", "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", + "javax.xml.parsers.*" }) public class SecurityMockMvcRequestPostProcessorsUserDetailsTests { + @Captor private ArgumentCaptor contextCaptor; + @Mock private SecurityContextRepository repository; @@ -72,11 +75,9 @@ public class SecurityMockMvcRequestPostProcessorsUserDetailsTests { public void userDetails() { user(userDetails).postProcessRequest(request); - verify(repository).saveContext(contextCaptor.capture(), eq(request), - any(HttpServletResponse.class)); + verify(repository).saveContext(contextCaptor.capture(), eq(request), any(HttpServletResponse.class)); SecurityContext context = contextCaptor.getValue(); - assertThat(context.getAuthentication()).isInstanceOf( - UsernamePasswordAuthenticationToken.class); + assertThat(context.getAuthentication()).isInstanceOf(UsernamePasswordAuthenticationToken.class); assertThat(context.getAuthentication().getPrincipal()).isSameAs(userDetails); } @@ -84,4 +85,5 @@ public class SecurityMockMvcRequestPostProcessorsUserDetailsTests { spy(WebTestUtils.class); when(WebTestUtils.getSecurityContextRepository(request)).thenReturn(repository); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsUserTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsUserTests.java index bc9e2f088a..02546f3a63 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsUserTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsUserTests.java @@ -48,10 +48,13 @@ import org.springframework.security.web.context.SecurityContextRepository; @RunWith(PowerMockRunner.class) @PrepareOnlyThisForTest(WebTestUtils.class) -@PowerMockIgnore({"javax.security.auth.*", "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", "javax.xml.parsers.*"}) +@PowerMockIgnore({ "javax.security.auth.*", "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", + "javax.xml.parsers.*" }) public class SecurityMockMvcRequestPostProcessorsUserTests { + @Captor private ArgumentCaptor contextCaptor; + @Mock private SecurityContextRepository repository; @@ -59,6 +62,7 @@ public class SecurityMockMvcRequestPostProcessorsUserTests { @Mock private GrantedAuthority authority1; + @Mock private GrantedAuthority authority2; @@ -79,33 +83,27 @@ public class SecurityMockMvcRequestPostProcessorsUserTests { user(username).postProcessRequest(request); - verify(repository).saveContext(contextCaptor.capture(), eq(request), - any(HttpServletResponse.class)); + verify(repository).saveContext(contextCaptor.capture(), eq(request), any(HttpServletResponse.class)); SecurityContext context = contextCaptor.getValue(); - assertThat(context.getAuthentication()).isInstanceOf( - UsernamePasswordAuthenticationToken.class); + assertThat(context.getAuthentication()).isInstanceOf(UsernamePasswordAuthenticationToken.class); assertThat(context.getAuthentication().getName()).isEqualTo(username); assertThat(context.getAuthentication().getCredentials()).isEqualTo("password"); - assertThat(context.getAuthentication().getAuthorities()).extracting("authority") - .containsOnly("ROLE_USER"); + assertThat(context.getAuthentication().getAuthorities()).extracting("authority").containsOnly("ROLE_USER"); } @Test public void userWithCustom() { String username = "customuser"; - user(username).roles("CUSTOM", "ADMIN").password("newpass") - .postProcessRequest(request); + user(username).roles("CUSTOM", "ADMIN").password("newpass").postProcessRequest(request); - verify(repository).saveContext(contextCaptor.capture(), eq(request), - any(HttpServletResponse.class)); + verify(repository).saveContext(contextCaptor.capture(), eq(request), any(HttpServletResponse.class)); SecurityContext context = contextCaptor.getValue(); - assertThat(context.getAuthentication()).isInstanceOf( - UsernamePasswordAuthenticationToken.class); + assertThat(context.getAuthentication()).isInstanceOf(UsernamePasswordAuthenticationToken.class); assertThat(context.getAuthentication().getName()).isEqualTo(username); assertThat(context.getAuthentication().getCredentials()).isEqualTo("newpass"); - assertThat(context.getAuthentication().getAuthorities()).extracting("authority") - .containsOnly("ROLE_CUSTOM", "ROLE_ADMIN"); + assertThat(context.getAuthentication().getAuthorities()).extracting("authority").containsOnly("ROLE_CUSTOM", + "ROLE_ADMIN"); } @Test @@ -114,11 +112,10 @@ public class SecurityMockMvcRequestPostProcessorsUserTests { user(username).authorities(authority1, authority2).postProcessRequest(request); - verify(repository).saveContext(contextCaptor.capture(), eq(request), - any(HttpServletResponse.class)); + verify(repository).saveContext(contextCaptor.capture(), eq(request), any(HttpServletResponse.class)); SecurityContext context = contextCaptor.getValue(); - assertThat((List) context.getAuthentication().getAuthorities()) - .containsOnly(authority1, authority2); + assertThat((List) context.getAuthentication().getAuthorities()).containsOnly(authority1, + authority2); } @Test(expected = IllegalArgumentException.class) @@ -130,18 +127,17 @@ public class SecurityMockMvcRequestPostProcessorsUserTests { public void userCustomAuthoritiesList() { String username = "customuser"; - user(username).authorities(Arrays.asList(authority1, authority2)) - .postProcessRequest(request); + user(username).authorities(Arrays.asList(authority1, authority2)).postProcessRequest(request); - verify(repository).saveContext(contextCaptor.capture(), eq(request), - any(HttpServletResponse.class)); + verify(repository).saveContext(contextCaptor.capture(), eq(request), any(HttpServletResponse.class)); SecurityContext context = contextCaptor.getValue(); - assertThat((List) context.getAuthentication().getAuthorities()) - .containsOnly(authority1, authority2); + assertThat((List) context.getAuthentication().getAuthorities()).containsOnly(authority1, + authority2); } private void mockWebTestUtils() { spy(WebTestUtils.class); when(WebTestUtils.getSecurityContextRepository(request)).thenReturn(repository); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/response/Gh3409Tests.java b/test/src/test/java/org/springframework/security/test/web/servlet/response/Gh3409Tests.java index d879c54691..6e2857091b 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/response/Gh3409Tests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/response/Gh3409Tests.java @@ -106,5 +106,7 @@ public class Gh3409Tests { // @formatter:on } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchersTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchersTests.java index fdb23bcf24..30a1c4b004 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchersTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchersTests.java @@ -47,6 +47,7 @@ import static org.springframework.security.test.web.servlet.setup.SecurityMockMv @ContextConfiguration(classes = SecurityMockMvcResultMatchersTests.Config.class) @WebAppConfiguration public class SecurityMockMvcResultMatchersTests { + @Autowired private WebApplicationContext context; @@ -64,16 +65,14 @@ public class SecurityMockMvcResultMatchersTests { @Test public void withAuthenticationWhenMatchesThenSuccess() throws Exception { - this.mockMvc.perform(formLogin()) - .andExpect(authenticated().withAuthentication(auth -> - assertThat(auth).isInstanceOf(UsernamePasswordAuthenticationToken.class))); + this.mockMvc.perform(formLogin()).andExpect(authenticated() + .withAuthentication(auth -> assertThat(auth).isInstanceOf(UsernamePasswordAuthenticationToken.class))); } @Test(expected = AssertionError.class) public void withAuthenticationWhenNotMatchesThenFails() throws Exception { - this.mockMvc - .perform(formLogin()) - .andExpect(authenticated().withAuthentication(auth -> assertThat(auth.getName()).isEqualTo("notmatch"))); + this.mockMvc.perform(formLogin()).andExpect( + authenticated().withAuthentication(auth -> assertThat(auth.getName()).isEqualTo("notmatch"))); } // SEC-2719 @@ -110,10 +109,14 @@ public class SecurityMockMvcResultMatchersTests { @RestController static class Controller { + @RequestMapping("/") public String ok() { return "ok"; } + } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockWithAuthoritiesMvcResultMatchersTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockWithAuthoritiesMvcResultMatchersTests.java index 5753a20f98..33ce9a23bd 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockWithAuthoritiesMvcResultMatchersTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/response/SecurityMockWithAuthoritiesMvcResultMatchersTests.java @@ -49,6 +49,7 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc; @ContextConfiguration(classes = SecurityMockWithAuthoritiesMvcResultMatchersTests.Config.class) @WebAppConfiguration public class SecurityMockWithAuthoritiesMvcResultMatchersTests { + @Autowired private WebApplicationContext context; @@ -56,8 +57,7 @@ public class SecurityMockWithAuthoritiesMvcResultMatchersTests { @Before public void setup() { - mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()) - .build(); + mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build(); } @Test @@ -65,8 +65,7 @@ public class SecurityMockWithAuthoritiesMvcResultMatchersTests { List grantedAuthorities = new ArrayList<>(); grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN")); grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_SELLER")); - mockMvc.perform(formLogin()) - .andExpect(authenticated().withAuthorities(grantedAuthorities)); + mockMvc.perform(formLogin()).andExpect(authenticated().withAuthorities(grantedAuthorities)); } @Test(expected = AssertionError.class) @@ -90,10 +89,14 @@ public class SecurityMockWithAuthoritiesMvcResultMatchersTests { @RestController static class Controller { + @RequestMapping("/") public String ok() { return "ok"; } + } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurerTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurerTests.java index 9bb74d7966..97e19fbb17 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurerTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurerTests.java @@ -36,14 +36,19 @@ import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class SecurityMockMvcConfigurerTests { + @Mock private Filter filter; + @Mock private Filter beanFilter; + @Mock private ConfigurableMockMvcBuilder builder; + @Mock private WebApplicationContext context; + @Mock private ServletContext servletContext; @@ -61,8 +66,7 @@ public class SecurityMockMvcConfigurerTests { configurer.beforeMockMvcCreated(this.builder, this.context); assertFilterAdded(this.filter); - verify(this.servletContext).setAttribute(BeanIds.SPRING_SECURITY_FILTER_CHAIN, - this.filter); + verify(this.servletContext).setAttribute(BeanIds.SPRING_SECURITY_FILTER_CHAIN, this.filter); } @Test @@ -95,15 +99,15 @@ public class SecurityMockMvcConfigurerTests { } private void assertFilterAdded(Filter filter) { - ArgumentCaptor filterArg = ArgumentCaptor.forClass( - SecurityMockMvcConfigurer.DelegateFilter.class); + ArgumentCaptor filterArg = ArgumentCaptor + .forClass(SecurityMockMvcConfigurer.DelegateFilter.class); verify(this.builder).addFilters(filterArg.capture()); assertThat(filterArg.getValue().getDelegate()).isEqualTo(filter); } private void returnFilterBean() { when(this.context.containsBean(anyString())).thenReturn(true); - when(this.context.getBean(anyString(), eq(Filter.class))) - .thenReturn(this.beanFilter); + when(this.context.getBean(anyString(), eq(Filter.class))).thenReturn(this.beanFilter); } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurersTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurersTests.java index 162114d6ee..44e0452330 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurersTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/setup/SecurityMockMvcConfigurersTests.java @@ -42,46 +42,45 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @RunWith(SpringRunner.class) @WebAppConfiguration public class SecurityMockMvcConfigurersTests { + @Autowired WebApplicationContext wac; Filter noOpFilter = mock(Filter.class); /** - * Since noOpFilter is first does not continue the chain, security will not be invoked and the status should be OK - * + * Since noOpFilter is first does not continue the chain, security will not be invoked + * and the status should be OK * @throws Exception */ @Test public void applySpringSecurityWhenAddFilterFirstThenFilterFirst() throws Exception { - MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.wac) - .addFilters(this.noOpFilter) - .apply(springSecurity()) - .build(); + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).addFilters(this.noOpFilter) + .apply(springSecurity()).build(); - mockMvc.perform(get("/")) - .andExpect(status().isOk()); + mockMvc.perform(get("/")).andExpect(status().isOk()); } /** - * Since noOpFilter is second security will be invoked and the status will be not OK. We know this because if noOpFilter - * were first security would not be invoked sincet noOpFilter does not continue the FilterChain + * Since noOpFilter is second security will be invoked and the status will be not OK. + * We know this because if noOpFilter were first security would not be invoked sincet + * noOpFilter does not continue the FilterChain * @throws Exception */ @Test public void applySpringSecurityWhenAddFilterSecondThenSecurityFirst() throws Exception { - MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.wac) - .apply(springSecurity()) - .addFilters(this.noOpFilter) - .build(); + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).apply(springSecurity()) + .addFilters(this.noOpFilter).build(); - mockMvc.perform(get("/")) - .andExpect(status().is4xxClientError()); + mockMvc.perform(get("/")).andExpect(status().is4xxClientError()); } @Configuration @EnableWebMvc @EnableWebSecurity @Import(AuthenticationTestConfiguration.class) - static class Config {} + static class Config { + + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CsrfShowcaseTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CsrfShowcaseTests.java index b61a4247ef..99ee310c1c 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CsrfShowcaseTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CsrfShowcaseTests.java @@ -83,5 +83,7 @@ public class CsrfShowcaseTests { .withUser("user").password("password").roles("USER"); // @formatter:on } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CustomCsrfShowcaseTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CustomCsrfShowcaseTests.java index ad66e089a1..211d5929d9 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CustomCsrfShowcaseTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/CustomCsrfShowcaseTests.java @@ -56,8 +56,8 @@ public class CustomCsrfShowcaseTests { @Before public void setup() { - mvc = MockMvcBuilders.webAppContextSetup(context) - .defaultRequest(get("/").with(csrf())).apply(springSecurity()).build(); + mvc = MockMvcBuilders.webAppContextSetup(context).defaultRequest(get("/").with(csrf())).apply(springSecurity()) + .build(); } @Test @@ -98,5 +98,7 @@ public class CustomCsrfShowcaseTests { repo.setParameterName("custom_csrf"); return repo; } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/DefaultCsrfShowcaseTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/DefaultCsrfShowcaseTests.java index 42081d209f..5c7480e343 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/DefaultCsrfShowcaseTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/csrf/DefaultCsrfShowcaseTests.java @@ -48,8 +48,8 @@ public class DefaultCsrfShowcaseTests { @Before public void setup() { - mvc = MockMvcBuilders.webAppContextSetup(context) - .defaultRequest(get("/").with(csrf())).apply(springSecurity()).build(); + mvc = MockMvcBuilders.webAppContextSetup(context).defaultRequest(get("/").with(csrf())).apply(springSecurity()) + .build(); } @Test @@ -78,5 +78,7 @@ public class DefaultCsrfShowcaseTests { .withUser("user").password("password").roles("USER"); // @formatter:on } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/AuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/AuthenticationTests.java index bc445ea770..24665d3289 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/AuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/AuthenticationTests.java @@ -54,10 +54,8 @@ public class AuthenticationTests { @Before public void setup() { - mvc = MockMvcBuilders.webAppContextSetup(context) - .apply(springSecurity()) - .defaultRequest(get("/").accept(MediaType.TEXT_HTML)) - .build(); + mvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()) + .defaultRequest(get("/").accept(MediaType.TEXT_HTML)).build(); } @Test @@ -67,29 +65,26 @@ public class AuthenticationTests { @Test public void httpBasicAuthenticationSuccess() throws Exception { - mvc.perform(get("/secured/butnotfound").with(httpBasic("user", "password"))) - .andExpect(status().isNotFound()) + mvc.perform(get("/secured/butnotfound").with(httpBasic("user", "password"))).andExpect(status().isNotFound()) .andExpect(authenticated().withUsername("user")); } @Test public void authenticationSuccess() throws Exception { - mvc.perform(formLogin()).andExpect(status().isFound()) - .andExpect(redirectedUrl("/")) + mvc.perform(formLogin()).andExpect(status().isFound()).andExpect(redirectedUrl("/")) .andExpect(authenticated().withUsername("user")); } @Test public void authenticationFailed() throws Exception { - mvc.perform(formLogin().user("user").password("invalid")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/login?error")) - .andExpect(unauthenticated()); + mvc.perform(formLogin().user("user").password("invalid")).andExpect(status().isFound()) + .andExpect(redirectedUrl("/login?error")).andExpect(unauthenticated()); } @EnableWebSecurity @EnableWebMvc static class Config extends WebSecurityConfigurerAdapter { + @Bean public UserDetailsService userDetailsService() { // @formatter:off @@ -97,5 +92,7 @@ public class AuthenticationTests { return new InMemoryUserDetailsManager(user); // @formatter:on } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomConfigAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomConfigAuthenticationTests.java index eedcc107fc..2edcd0e68a 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomConfigAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomConfigAuthenticationTests.java @@ -64,26 +64,21 @@ public class CustomConfigAuthenticationTests { @Test public void authenticationSuccess() throws Exception { - mvc.perform( - formLogin("/authenticate").user("user", "user").password("pass", - "password")).andExpect(status().isFound()) - .andExpect(redirectedUrl("/")) + mvc.perform(formLogin("/authenticate").user("user", "user").password("pass", "password")) + .andExpect(status().isFound()).andExpect(redirectedUrl("/")) .andExpect(authenticated().withUsername("user")); } @Test public void withUserSuccess() throws Exception { - mvc.perform(get("/").with(user("user"))) - .andExpect(status().isNotFound()) + mvc.perform(get("/").with(user("user"))).andExpect(status().isNotFound()) .andExpect(authenticated().withUsername("user")); } @Test public void authenticationFailed() throws Exception { - mvc.perform( - formLogin("/authenticate").user("user", "notfound").password("pass", - "invalid")).andExpect(status().isFound()) - .andExpect(redirectedUrl("/authenticate?error")) + mvc.perform(formLogin("/authenticate").user("user", "notfound").password("pass", "invalid")) + .andExpect(status().isFound()).andExpect(redirectedUrl("/authenticate?error")) .andExpect(unauthenticated()); } @@ -122,5 +117,7 @@ public class CustomConfigAuthenticationTests { repo.setSpringSecurityContextKey("CUSTOM"); return repo; } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomLoginRequestBuilderAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomLoginRequestBuilderAuthenticationTests.java index 821efe3b88..8fed1f3daa 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomLoginRequestBuilderAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/CustomLoginRequestBuilderAuthenticationTests.java @@ -58,23 +58,18 @@ public class CustomLoginRequestBuilderAuthenticationTests { @Test public void authenticationSuccess() throws Exception { - mvc.perform(login()) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/")) + mvc.perform(login()).andExpect(status().isFound()).andExpect(redirectedUrl("/")) .andExpect(authenticated().withUsername("user")); } @Test public void authenticationFailed() throws Exception { - mvc.perform(login().user("notfound").password("invalid")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/authenticate?error")) - .andExpect(unauthenticated()); + mvc.perform(login().user("notfound").password("invalid")).andExpect(status().isFound()) + .andExpect(redirectedUrl("/authenticate?error")).andExpect(unauthenticated()); } static FormLoginRequestBuilder login() { - return SecurityMockMvcRequestBuilders.formLogin("/authenticate") - .userParameter("user").passwordParam("pass"); + return SecurityMockMvcRequestBuilders.formLogin("/authenticate").userParameter("user").passwordParam("pass"); } @EnableWebSecurity @@ -102,5 +97,7 @@ public class CustomLoginRequestBuilderAuthenticationTests { return new InMemoryUserDetailsManager(user); } // @formatter:on + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/DefaultfSecurityRequestsTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/DefaultfSecurityRequestsTests.java index 31858ba6d6..db78fdeed0 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/DefaultfSecurityRequestsTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/DefaultfSecurityRequestsTests.java @@ -49,15 +49,14 @@ public class DefaultfSecurityRequestsTests { @Before public void setup() { - mvc = MockMvcBuilders.webAppContextSetup(context) - .defaultRequest(get("/").with(user("user").roles("ADMIN"))) + mvc = MockMvcBuilders.webAppContextSetup(context).defaultRequest(get("/").with(user("user").roles("ADMIN"))) .apply(springSecurity()).build(); } @Test public void requestProtectedUrlWithUser() throws Exception { mvc.perform(get("/")) - // Ensure we got past Security + // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with user .andExpect(authenticated().withUsername("user")); @@ -66,7 +65,7 @@ public class DefaultfSecurityRequestsTests { @Test public void requestProtectedUrlWithAdmin() throws Exception { mvc.perform(get("/admin")) - // Ensure we got past Security + // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with user .andExpect(authenticated().withUsername("user")); @@ -105,5 +104,7 @@ public class DefaultfSecurityRequestsTests { .withUser("user").password("password").roles("USER"); // @formatter:on } + } + } \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/SecurityRequestsTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/SecurityRequestsTests.java index 4514754ff5..964aa64793 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/SecurityRequestsTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/SecurityRequestsTests.java @@ -63,7 +63,7 @@ public class SecurityRequestsTests { @Test public void requestProtectedUrlWithUser() throws Exception { mvc.perform(get("/").with(user("user"))) - // Ensure we got past Security + // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with user .andExpect(authenticated().withUsername("user")); @@ -72,7 +72,7 @@ public class SecurityRequestsTests { @Test public void requestProtectedUrlWithAdmin() throws Exception { mvc.perform(get("/admin").with(user("admin").roles("ADMIN"))) - // Ensure we got past Security + // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with admin .andExpect(authenticated().withUsername("admin")); @@ -82,7 +82,7 @@ public class SecurityRequestsTests { public void requestProtectedUrlWithUserDetails() throws Exception { UserDetails user = userDetailsService.loadUserByUsername("user"); mvc.perform(get("/").with(user(user))) - // Ensure we got past Security + // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with user .andExpect(authenticated().withAuthenticationPrincipal(user)); @@ -90,10 +90,9 @@ public class SecurityRequestsTests { @Test public void requestProtectedUrlWithAuthentication() throws Exception { - Authentication authentication = new TestingAuthenticationToken("test", "notused", - "ROLE_USER"); + Authentication authentication = new TestingAuthenticationToken("test", "notused", "ROLE_USER"); mvc.perform(get("/").with(authentication(authentication))) - // Ensure we got past Security + // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with user .andExpect(authenticated().withAuthentication(authentication)); @@ -129,5 +128,7 @@ public class SecurityRequestsTests { public UserDetailsService userDetailsServiceBean() throws Exception { return super.userDetailsServiceBean(); } + } + } \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithAdminRob.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithAdminRob.java index bf65b937c5..1c8d7ed3c5 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithAdminRob.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithAdminRob.java @@ -28,6 +28,7 @@ import org.springframework.security.test.context.support.WithMockUser; @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented -@WithMockUser(value="rob", roles="ADMIN") +@WithMockUser(value = "rob", roles = "ADMIN") public @interface WithAdminRob { + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserAuthenticationTests.java index 4a58ac6bde..8d18ae7c11 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserAuthenticationTests.java @@ -49,15 +49,14 @@ public class WithUserAuthenticationTests { @Before public void setup() { - mvc = MockMvcBuilders.webAppContextSetup(context) - .apply(SecurityMockMvcConfigurers.springSecurity()).build(); + mvc = MockMvcBuilders.webAppContextSetup(context).apply(SecurityMockMvcConfigurers.springSecurity()).build(); } @Test @WithMockUser public void requestProtectedUrlWithUser() throws Exception { mvc.perform(get("/")) - // Ensure we got past Security + // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with user .andExpect(authenticated().withUsername("user")); @@ -67,7 +66,7 @@ public class WithUserAuthenticationTests { @WithAdminRob public void requestProtectedUrlWithAdminRob() throws Exception { mvc.perform(get("/")) - // Ensure we got past Security + // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with user .andExpect(authenticated().withUsername("rob").withRoles("ADMIN")); @@ -77,7 +76,7 @@ public class WithUserAuthenticationTests { @WithMockUser(roles = "ADMIN") public void requestProtectedUrlWithAdmin() throws Exception { mvc.perform(get("/admin")) - // Ensure we got past Security + // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with user .andExpect(authenticated().withUsername("user").withRoles("ADMIN")); @@ -107,5 +106,7 @@ public class WithUserAuthenticationTests { .withUser("user").password("password").roles("USER"); // @formatter:on } + } + } \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserClassLevelAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserClassLevelAuthenticationTests.java index a0bd420579..fd2460f0ba 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserClassLevelAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserClassLevelAuthenticationTests.java @@ -58,7 +58,7 @@ public class WithUserClassLevelAuthenticationTests { @Test public void requestProtectedUrlWithUser() throws Exception { mvc.perform(get("/")) - // Ensure we got past Security + // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with user .andExpect(authenticated().withUsername("user")); @@ -67,7 +67,7 @@ public class WithUserClassLevelAuthenticationTests { @Test public void requestProtectedUrlWithAdmin() throws Exception { mvc.perform(get("/admin")) - // Ensure we got past Security + // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with user .andExpect(authenticated().withUsername("user").withRoles("ADMIN")); @@ -107,5 +107,7 @@ public class WithUserClassLevelAuthenticationTests { .withUser("user").password("password").roles("USER"); // @formatter:on } + } + } \ No newline at end of file diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsAuthenticationTests.java index be7234f3ef..e5faa59067 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsAuthenticationTests.java @@ -58,7 +58,7 @@ public class WithUserDetailsAuthenticationTests { @WithUserDetails public void requestProtectedUrlWithUser() throws Exception { mvc.perform(get("/")) - // Ensure we got past Security + // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with user .andExpect(authenticated().withUsername("user")); @@ -71,8 +71,7 @@ public class WithUserDetailsAuthenticationTests { // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with user - .andExpect( - authenticated().withUsername("admin").withRoles("ADMIN", "USER")); + .andExpect(authenticated().withUsername("admin").withRoles("ADMIN", "USER")); } @EnableWebSecurity @@ -106,5 +105,7 @@ public class WithUserDetailsAuthenticationTests { .withUser("admin").password("password").roles("USER", "ADMIN"); // @formatter:on } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsClassLevelAuthenticationTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsClassLevelAuthenticationTests.java index 9c34d662df..e6a0007a01 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsClassLevelAuthenticationTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/showcase/secured/WithUserDetailsClassLevelAuthenticationTests.java @@ -61,8 +61,7 @@ public class WithUserDetailsClassLevelAuthenticationTests { // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with user - .andExpect( - authenticated().withUsername("admin").withRoles("ADMIN", "USER")); + .andExpect(authenticated().withUsername("admin").withRoles("ADMIN", "USER")); } @Test @@ -71,8 +70,7 @@ public class WithUserDetailsClassLevelAuthenticationTests { // Ensure we got past Security .andExpect(status().isNotFound()) // Ensure it appears we are authenticated with user - .andExpect( - authenticated().withUsername("admin").withRoles("ADMIN", "USER")); + .andExpect(authenticated().withUsername("admin").withRoles("ADMIN", "USER")); } @EnableWebSecurity @@ -106,5 +104,7 @@ public class WithUserDetailsClassLevelAuthenticationTests { .withUser("admin").password("password").roles("USER", "ADMIN"); // @formatter:on } + } + } diff --git a/test/src/test/java/org/springframework/security/test/web/support/WebTestUtilsTests.java b/test/src/test/java/org/springframework/security/test/web/support/WebTestUtilsTests.java index 914eb046b5..bed3c0dc20 100644 --- a/test/src/test/java/org/springframework/security/test/web/support/WebTestUtilsTests.java +++ b/test/src/test/java/org/springframework/security/test/web/support/WebTestUtilsTests.java @@ -47,12 +47,15 @@ import static org.springframework.security.test.web.support.WebTestUtils.getSecu @RunWith(MockitoJUnitRunner.class) public class WebTestUtilsTests { + @Mock private SecurityContextRepository contextRepo; + @Mock private CsrfTokenRepository csrfRepo; private MockHttpServletRequest request; + private ConfigurableApplicationContext context; @Before @@ -69,22 +72,19 @@ public class WebTestUtilsTests { @Test public void getCsrfTokenRepositorytNoWac() { - assertThat(getCsrfTokenRepository(this.request)) - .isInstanceOf(HttpSessionCsrfTokenRepository.class); + assertThat(getCsrfTokenRepository(this.request)).isInstanceOf(HttpSessionCsrfTokenRepository.class); } @Test public void getCsrfTokenRepositorytNoSecurity() { loadConfig(Config.class); - assertThat(getCsrfTokenRepository(this.request)) - .isInstanceOf(HttpSessionCsrfTokenRepository.class); + assertThat(getCsrfTokenRepository(this.request)).isInstanceOf(HttpSessionCsrfTokenRepository.class); } @Test public void getCsrfTokenRepositorytSecurityNoCsrf() { loadConfig(SecurityNoCsrfConfig.class); - assertThat(getCsrfTokenRepository(this.request)) - .isInstanceOf(HttpSessionCsrfTokenRepository.class); + assertThat(getCsrfTokenRepository(this.request)).isInstanceOf(HttpSessionCsrfTokenRepository.class); } @Test @@ -99,22 +99,19 @@ public class WebTestUtilsTests { @Test public void getSecurityContextRepositoryNoWac() { - assertThat(getSecurityContextRepository(this.request)) - .isInstanceOf(HttpSessionSecurityContextRepository.class); + assertThat(getSecurityContextRepository(this.request)).isInstanceOf(HttpSessionSecurityContextRepository.class); } @Test public void getSecurityContextRepositoryNoSecurity() { loadConfig(Config.class); - assertThat(getSecurityContextRepository(this.request)) - .isInstanceOf(HttpSessionSecurityContextRepository.class); + assertThat(getSecurityContextRepository(this.request)).isInstanceOf(HttpSessionSecurityContextRepository.class); } @Test public void getSecurityContextRepositorySecurityNoCsrf() { loadConfig(SecurityNoCsrfConfig.class); - assertThat(getSecurityContextRepository(this.request)) - .isInstanceOf(HttpSessionSecurityContextRepository.class); + assertThat(getSecurityContextRepository(this.request)).isInstanceOf(HttpSessionSecurityContextRepository.class); } @Test @@ -130,8 +127,7 @@ public class WebTestUtilsTests { public void findFilterNoMatchingFilters() { loadConfig(PartialSecurityConfig.class); - assertThat(WebTestUtils.findFilter(this.request, - SecurityContextPersistenceFilter.class)).isNull(); + assertThat(WebTestUtils.findFilter(this.request, SecurityContextPersistenceFilter.class)).isNull(); } @Test @@ -141,11 +137,9 @@ public class WebTestUtilsTests { CsrfFilter toFind = new CsrfFilter(new HttpSessionCsrfTokenRepository()); FilterChainProxy springSecurityFilterChain = new FilterChainProxy( new DefaultSecurityFilterChain(AnyRequestMatcher.INSTANCE, toFind)); - this.request.getServletContext().setAttribute( - BeanIds.SPRING_SECURITY_FILTER_CHAIN, springSecurityFilterChain); + this.request.getServletContext().setAttribute(BeanIds.SPRING_SECURITY_FILTER_CHAIN, springSecurityFilterChain); - assertThat(WebTestUtils.findFilter(this.request, toFind.getClass())) - .isEqualTo(toFind); + assertThat(WebTestUtils.findFilter(this.request, toFind.getClass())).isEqualTo(toFind); } @Test @@ -155,11 +149,9 @@ public class WebTestUtilsTests { CsrfFilter toFind = new CsrfFilter(new HttpSessionCsrfTokenRepository()); FilterChainProxy springSecurityFilterChain = new FilterChainProxy( new DefaultSecurityFilterChain(AnyRequestMatcher.INSTANCE, toFind)); - this.request.getServletContext().setAttribute( - BeanIds.SPRING_SECURITY_FILTER_CHAIN, springSecurityFilterChain); + this.request.getServletContext().setAttribute(BeanIds.SPRING_SECURITY_FILTER_CHAIN, springSecurityFilterChain); - assertThat(WebTestUtils.findFilter(this.request, toFind.getClass())) - .isSameAs(toFind); + assertThat(WebTestUtils.findFilter(this.request, toFind.getClass())).isSameAs(toFind); } private void loadConfig(Class config) { @@ -167,12 +159,13 @@ public class WebTestUtilsTests { context.register(config); context.refresh(); this.context = context; - this.request.getServletContext().setAttribute( - WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context); + this.request.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, + context); } @Configuration static class Config { + } @EnableWebSecurity @@ -182,10 +175,12 @@ public class WebTestUtilsTests { protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); } + } @EnableWebSecurity static class CustomSecurityConfig extends WebSecurityConfigurerAdapter { + static CsrfTokenRepository CSRF_REPO; static SecurityContextRepository CONTEXT_REPO; @@ -200,6 +195,7 @@ public class WebTestUtilsTests { .securityContextRepository(CONTEXT_REPO); // @formatter:on } + } @EnableWebSecurity @@ -212,14 +208,17 @@ public class WebTestUtilsTests { .antMatcher("/willnotmatchthis"); // @formatter:on } + } @Configuration static class NoSecurityConfig { + } @EnableWebSecurity static class SecurityConfigWithDefaults extends WebSecurityConfigurerAdapter { } + } diff --git a/web/src/main/java/org/springframework/security/web/AuthenticationEntryPoint.java b/web/src/main/java/org/springframework/security/web/AuthenticationEntryPoint.java index 3e992ad67f..fe20e437ea 100644 --- a/web/src/main/java/org/springframework/security/web/AuthenticationEntryPoint.java +++ b/web/src/main/java/org/springframework/security/web/AuthenticationEntryPoint.java @@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletResponse; * @author Ben Alex */ public interface AuthenticationEntryPoint { + // ~ Methods // ======================================================================================================== @@ -44,12 +45,12 @@ public interface AuthenticationEntryPoint { *

        * Implementations should modify the headers on the ServletResponse as * necessary to commence the authentication process. - * * @param request that resulted in an AuthenticationException * @param response so that the user agent can begin authentication * @param authException that caused the invocation * */ - void commence(HttpServletRequest request, HttpServletResponse response, - AuthenticationException authException) throws IOException, ServletException; + void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) + throws IOException, ServletException; + } diff --git a/web/src/main/java/org/springframework/security/web/DefaultRedirectStrategy.java b/web/src/main/java/org/springframework/security/web/DefaultRedirectStrategy.java index 983f5ce29c..e8db558a53 100644 --- a/web/src/main/java/org/springframework/security/web/DefaultRedirectStrategy.java +++ b/web/src/main/java/org/springframework/security/web/DefaultRedirectStrategy.java @@ -45,8 +45,7 @@ public class DefaultRedirectStrategy implements RedirectStrategy { * information (HTTP or HTTPS), so will cause problems if a redirect is being * performed to change to HTTPS, for example. */ - public void sendRedirect(HttpServletRequest request, HttpServletResponse response, - String url) throws IOException { + public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException { String redirectUrl = calculateRedirectUrl(request.getContextPath(), url); redirectUrl = response.encodeRedirectURL(redirectUrl); @@ -98,10 +97,11 @@ public class DefaultRedirectStrategy implements RedirectStrategy { } /** - * Returns true, if the redirection URL should be calculated - * minus the protocol and context path (defaults to false). + * Returns true, if the redirection URL should be calculated minus the + * protocol and context path (defaults to false). */ protected boolean isContextRelative() { return contextRelative; } + } diff --git a/web/src/main/java/org/springframework/security/web/DefaultSecurityFilterChain.java b/web/src/main/java/org/springframework/security/web/DefaultSecurityFilterChain.java index d4e5a0e4fa..85d3efeab2 100644 --- a/web/src/main/java/org/springframework/security/web/DefaultSecurityFilterChain.java +++ b/web/src/main/java/org/springframework/security/web/DefaultSecurityFilterChain.java @@ -27,12 +27,14 @@ import java.util.*; * Standard implementation of {@code SecurityFilterChain}. * * @author Luke Taylor - * * @since 3.1 */ public final class DefaultSecurityFilterChain implements SecurityFilterChain { + private static final Log logger = LogFactory.getLog(DefaultSecurityFilterChain.class); + private final RequestMatcher requestMatcher; + private final List filters; public DefaultSecurityFilterChain(RequestMatcher requestMatcher, Filter... filters) { @@ -61,4 +63,5 @@ public final class DefaultSecurityFilterChain implements SecurityFilterChain { public String toString() { return "[ " + requestMatcher + ", " + filters + "]"; } + } diff --git a/web/src/main/java/org/springframework/security/web/FilterChainProxy.java b/web/src/main/java/org/springframework/security/web/FilterChainProxy.java index a27c4dd324..05de25a48f 100644 --- a/web/src/main/java/org/springframework/security/web/FilterChainProxy.java +++ b/web/src/main/java/org/springframework/security/web/FilterChainProxy.java @@ -59,9 +59,9 @@ import java.util.*; * and a list of filters which should be applied to matching requests. Most applications * will only contain a single filter chain, and if you are using the namespace, you don't * have to set the chains explicitly. If you require finer-grained control, you can make - * use of the {@code } namespace element. This defines a URI pattern - * and the list of filters (as comma-separated bean names) which should be applied to - * requests which match the pattern. An example configuration might look like this: + * use of the {@code } namespace element. This defines a URI pattern and the + * list of filters (as comma-separated bean names) which should be applied to requests + * which match the pattern. An example configuration might look like this: * *

          *  <bean id="myfilterChainProxy" class="org.springframework.security.web.FilterChainProxy">
        @@ -136,6 +136,7 @@ import java.util.*;
          * @author Rob Winch
          */
         public class FilterChainProxy extends GenericFilterBean {
        +
         	// ~ Static fields/initializers
         	// =====================================================================================
         
        @@ -144,8 +145,7 @@ public class FilterChainProxy extends GenericFilterBean {
         	// ~ Instance fields
         	// ================================================================================================
         
        -	private final static String FILTER_APPLIED = FilterChainProxy.class.getName().concat(
        -			".APPLIED");
        +	private final static String FILTER_APPLIED = FilterChainProxy.class.getName().concat(".APPLIED");
         
         	private List filterChains;
         
        @@ -175,14 +175,15 @@ public class FilterChainProxy extends GenericFilterBean {
         	}
         
         	@Override
        -	public void doFilter(ServletRequest request, ServletResponse response,
        -			FilterChain chain) throws IOException, ServletException {
        +	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        +			throws IOException, ServletException {
         		boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
         		if (clearContext) {
         			try {
         				request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
         				doFilterInternal(request, response, chain);
        -			} catch (RequestRejectedException e) {
        +			}
        +			catch (RequestRejectedException e) {
         				this.requestRejectedHandler.handle((HttpServletRequest) request, (HttpServletResponse) response, e);
         			}
         			finally {
        @@ -195,21 +196,18 @@ public class FilterChainProxy extends GenericFilterBean {
         		}
         	}
         
        -	private void doFilterInternal(ServletRequest request, ServletResponse response,
        -			FilterChain chain) throws IOException, ServletException {
        +	private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
        +			throws IOException, ServletException {
         
        -		FirewalledRequest fwRequest = firewall
        -				.getFirewalledRequest((HttpServletRequest) request);
        -		HttpServletResponse fwResponse = firewall
        -				.getFirewalledResponse((HttpServletResponse) response);
        +		FirewalledRequest fwRequest = firewall.getFirewalledRequest((HttpServletRequest) request);
        +		HttpServletResponse fwResponse = firewall.getFirewalledResponse((HttpServletResponse) response);
         
         		List filters = getFilters(fwRequest);
         
         		if (filters == null || filters.size() == 0) {
         			if (logger.isDebugEnabled()) {
         				logger.debug(UrlUtils.buildRequestUrl(fwRequest)
        -						+ (filters == null ? " has no matching filters"
        -								: " has an empty filter list"));
        +						+ (filters == null ? " has no matching filters" : " has an empty filter list"));
         			}
         
         			fwRequest.reset();
        @@ -225,7 +223,6 @@ public class FilterChainProxy extends GenericFilterBean {
         
         	/**
         	 * Returns the first filter chain matching the supplied URL.
        -	 *
         	 * @param request the request to match
         	 * @return an ordered array of Filters defining the filter chain
         	 */
        @@ -241,13 +238,11 @@ public class FilterChainProxy extends GenericFilterBean {
         
         	/**
         	 * Convenience method, mainly for testing.
        -	 *
         	 * @param url the URL
         	 * @return matching filter list
         	 */
         	public List getFilters(String url) {
        -		return getFilters(firewall.getFirewalledRequest((new FilterInvocation(url, "GET")
        -				.getRequest())));
        +		return getFilters(firewall.getFirewalledRequest((new FilterInvocation(url, "GET").getRequest())));
         	}
         
         	/**
        @@ -261,7 +256,6 @@ public class FilterChainProxy extends GenericFilterBean {
         	/**
         	 * Used (internally) to specify a validation strategy for the filters in each
         	 * configured chain.
        -	 *
         	 * @param filterChainValidator the validator instance which will be invoked on during
         	 * initialization to check the {@code FilterChainProxy} instance.
         	 */
        @@ -273,7 +267,6 @@ public class FilterChainProxy extends GenericFilterBean {
         	 * Sets the "firewall" implementation which will be used to validate and wrap (or
         	 * potentially reject) the incoming requests. The default implementation should be
         	 * satisfactory for most requirements.
        -	 *
         	 * @param firewall
         	 */
         	public void setFirewall(HttpFirewall firewall) {
        @@ -281,7 +274,8 @@ public class FilterChainProxy extends GenericFilterBean {
         	}
         
         	/**
        -	 * Sets the {@link RequestRejectedHandler} to be used for requests rejected by the firewall.
        +	 * Sets the {@link RequestRejectedHandler} to be used for requests rejected by the
        +	 * firewall.
         	 *
         	 * @since 5.2
         	 * @param requestRejectedHandler the {@link RequestRejectedHandler}
        @@ -310,14 +304,19 @@ public class FilterChainProxy extends GenericFilterBean {
         	 * the additional internal list of filters which match the request.
         	 */
         	private static class VirtualFilterChain implements FilterChain {
        +
         		private final FilterChain originalChain;
        +
         		private final List additionalFilters;
        +
         		private final FirewalledRequest firewalledRequest;
        +
         		private final int size;
        +
         		private int currentPosition = 0;
         
        -		private VirtualFilterChain(FirewalledRequest firewalledRequest,
        -				FilterChain chain, List additionalFilters) {
        +		private VirtualFilterChain(FirewalledRequest firewalledRequest, FilterChain chain,
        +				List additionalFilters) {
         			this.originalChain = chain;
         			this.additionalFilters = additionalFilters;
         			this.size = additionalFilters.size();
        @@ -325,8 +324,7 @@ public class FilterChainProxy extends GenericFilterBean {
         		}
         
         		@Override
        -		public void doFilter(ServletRequest request, ServletResponse response)
        -				throws IOException, ServletException {
        +		public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
         			if (currentPosition == size) {
         				if (logger.isDebugEnabled()) {
         					logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
        @@ -344,25 +342,29 @@ public class FilterChainProxy extends GenericFilterBean {
         				Filter nextFilter = additionalFilters.get(currentPosition - 1);
         
         				if (logger.isDebugEnabled()) {
        -					logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
        -							+ " at position " + currentPosition + " of " + size
        -							+ " in additional filter chain; firing Filter: '"
        +					logger.debug(UrlUtils.buildRequestUrl(firewalledRequest) + " at position " + currentPosition
        +							+ " of " + size + " in additional filter chain; firing Filter: '"
         							+ nextFilter.getClass().getSimpleName() + "'");
         				}
         
         				nextFilter.doFilter(request, response, this);
         			}
         		}
        +
         	}
         
         	public interface FilterChainValidator {
        +
         		void validate(FilterChainProxy filterChainProxy);
        +
         	}
         
         	private static class NullFilterChainValidator implements FilterChainValidator {
        +
         		@Override
         		public void validate(FilterChainProxy filterChainProxy) {
         		}
        +
         	}
         
         }
        diff --git a/web/src/main/java/org/springframework/security/web/FilterInvocation.java b/web/src/main/java/org/springframework/security/web/FilterInvocation.java
        index 97061e1872..1441bcf446 100644
        --- a/web/src/main/java/org/springframework/security/web/FilterInvocation.java
        +++ b/web/src/main/java/org/springframework/security/web/FilterInvocation.java
        @@ -53,6 +53,7 @@ import org.springframework.security.web.util.UrlUtils;
          * @author Rob Winch
          */
         public class FilterInvocation {
        +
         	// ~ Static fields
         	// ==================================================================================================
         	static final FilterChain DUMMY_CHAIN = (req, res) -> {
        @@ -63,14 +64,15 @@ public class FilterInvocation {
         	// ================================================================================================
         
         	private FilterChain chain;
        +
         	private HttpServletRequest request;
        +
         	private HttpServletResponse response;
         
         	// ~ Constructors
         	// ===================================================================================================
         
        -	public FilterInvocation(ServletRequest request, ServletResponse response,
        -			FilterChain chain) {
        +	public FilterInvocation(ServletRequest request, ServletResponse response, FilterChain chain) {
         		if ((request == null) || (response == null) || (chain == null)) {
         			throw new IllegalArgumentException("Cannot pass null values to constructor");
         		}
        @@ -88,16 +90,14 @@ public class FilterInvocation {
         		this(contextPath, servletPath, null, null, method);
         	}
         
        -	public FilterInvocation(String contextPath, String servletPath, String pathInfo,
        -			String query, String method) {
        +	public FilterInvocation(String contextPath, String servletPath, String pathInfo, String query, String method) {
         		DummyRequest request = new DummyRequest();
         		if (contextPath == null) {
         			contextPath = "/cp";
         		}
         		request.setContextPath(contextPath);
         		request.setServletPath(servletPath);
        -		request.setRequestURI(
        -				contextPath + servletPath + (pathInfo == null ? "" : pathInfo));
        +		request.setRequestURI(contextPath + servletPath + (pathInfo == null ? "" : pathInfo));
         		request.setPathInfo(pathInfo);
         		request.setQueryString(query);
         		request.setMethod(method);
        @@ -116,7 +116,6 @@ public class FilterInvocation {
         	 * 

        * The returned URL does not reflect the port number determined from a * {@link org.springframework.security.web.PortResolver}. - * * @return the full URL of this request */ public String getFullRequestUrl() { @@ -133,7 +132,6 @@ public class FilterInvocation { /** * Obtains the web application-specific fragment of the URL. - * * @return the URL, excluding any server name, context path or servlet path */ public String getRequestUrl() { @@ -152,21 +150,29 @@ public class FilterInvocation { public String toString() { return "FilterInvocation: URL: " + getRequestUrl(); } + } class DummyRequest extends HttpServletRequestWrapper { - private static final HttpServletRequest UNSUPPORTED_REQUEST = (HttpServletRequest) Proxy - .newProxyInstance(DummyRequest.class.getClassLoader(), - new Class[] { HttpServletRequest.class }, - new UnsupportedOperationExceptionInvocationHandler()); + + private static final HttpServletRequest UNSUPPORTED_REQUEST = (HttpServletRequest) Proxy.newProxyInstance( + DummyRequest.class.getClassLoader(), new Class[] { HttpServletRequest.class }, + new UnsupportedOperationExceptionInvocationHandler()); private String requestURI; + private String contextPath = ""; + private String servletPath; + private String pathInfo; + private String queryString; + private String method; + private final HttpHeaders headers = new HttpHeaders(); + private final Map parameters = new LinkedHashMap<>(); DummyRequest() { @@ -258,7 +264,7 @@ class DummyRequest extends HttpServletRequestWrapper { @Override public int getIntHeader(String name) { String value = this.headers.getFirst(name); - if (value == null ) { + if (value == null) { return -1; } else { @@ -294,9 +300,11 @@ class DummyRequest extends HttpServletRequestWrapper { public void setParameter(String name, String... values) { this.parameters.put(name, values); } + } final class UnsupportedOperationExceptionInvocationHandler implements InvocationHandler { + private static final float JAVA_VERSION = Float.parseFloat(System.getProperty("java.class.version", "52")); public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { @@ -311,14 +319,9 @@ final class UnsupportedOperationExceptionInvocationHandler implements Invocation return invokeDefaultMethodForJdk8(proxy, method, args); } return MethodHandles.lookup() - .findSpecial( - method.getDeclaringClass(), - method.getName(), - MethodType.methodType(method.getReturnType(), new Class[0]), - method.getDeclaringClass() - ) - .bindTo(proxy) - .invokeWithArguments(args); + .findSpecial(method.getDeclaringClass(), method.getName(), + MethodType.methodType(method.getReturnType(), new Class[0]), method.getDeclaringClass()) + .bindTo(proxy).invokeWithArguments(args); } private Object invokeDefaultMethodForJdk8(Object proxy, Method method, Object[] args) throws Throwable { @@ -326,14 +329,12 @@ final class UnsupportedOperationExceptionInvocationHandler implements Invocation constructor.setAccessible(true); Class clazz = method.getDeclaringClass(); - return constructor.newInstance(clazz) - .in(clazz) - .unreflectSpecial(method, clazz) - .bindTo(proxy) + return constructor.newInstance(clazz).in(clazz).unreflectSpecial(method, clazz).bindTo(proxy) .invokeWithArguments(args); } private boolean isJdk8OrEarlier() { return JAVA_VERSION <= 52; } + } diff --git a/web/src/main/java/org/springframework/security/web/PortMapper.java b/web/src/main/java/org/springframework/security/web/PortMapper.java index ab21cc86a6..94388052de 100644 --- a/web/src/main/java/org/springframework/security/web/PortMapper.java +++ b/web/src/main/java/org/springframework/security/web/PortMapper.java @@ -23,6 +23,7 @@ package org.springframework.security.web; * @author Ben Alex */ public interface PortMapper { + // ~ Methods // ======================================================================================================== @@ -31,9 +32,7 @@ public interface PortMapper { *

        * Returns null if unknown. *

        - * * @param httpsPort - * * @return the HTTP port or null if unknown */ Integer lookupHttpPort(Integer httpsPort); @@ -43,10 +42,9 @@ public interface PortMapper { *

        * Returns null if unknown. *

        - * * @param httpPort - * * @return the HTTPS port or null if unknown */ Integer lookupHttpsPort(Integer httpPort); + } diff --git a/web/src/main/java/org/springframework/security/web/PortMapperImpl.java b/web/src/main/java/org/springframework/security/web/PortMapperImpl.java index f9144ecd52..3789cad848 100644 --- a/web/src/main/java/org/springframework/security/web/PortMapperImpl.java +++ b/web/src/main/java/org/springframework/security/web/PortMapperImpl.java @@ -32,6 +32,7 @@ import org.springframework.util.Assert; * @author colin sampaleanu */ public class PortMapperImpl implements PortMapper { + // ~ Instance fields // ================================================================================================ @@ -84,19 +85,16 @@ public class PortMapperImpl implements PortMapper { * </map> * </property> *
        - * * @param newMappings A Map consisting of String keys and String values, where for * each entry the key is the string representation of an integer HTTP port number, and * the value is the string representation of the corresponding integer HTTPS port * number. - * * @throws IllegalArgumentException if input map does not consist of String keys and * values, each representing an integer port number in the range 1-65535 for that * mapping. */ public void setPortMappings(Map newMappings) { - Assert.notNull(newMappings, - "A valid list of HTTPS port mappings must be provided"); + Assert.notNull(newMappings, "A valid list of HTTPS port mappings must be provided"); this.httpsPortMappings.clear(); @@ -104,11 +102,9 @@ public class PortMapperImpl implements PortMapper { Integer httpPort = Integer.valueOf(entry.getKey()); Integer httpsPort = Integer.valueOf(entry.getValue()); - if ((httpPort < 1) || (httpPort > 65535) - || (httpsPort < 1) || (httpsPort > 65535)) { + if ((httpPort < 1) || (httpPort > 65535) || (httpsPort < 1) || (httpsPort > 65535)) { throw new IllegalArgumentException( - "one or both ports out of legal range: " + httpPort + ", " - + httpsPort); + "one or both ports out of legal range: " + httpPort + ", " + httpsPort); } this.httpsPortMappings.put(httpPort, httpsPort); @@ -118,4 +114,5 @@ public class PortMapperImpl implements PortMapper { throw new IllegalArgumentException("must map at least one port"); } } + } diff --git a/web/src/main/java/org/springframework/security/web/PortResolver.java b/web/src/main/java/org/springframework/security/web/PortResolver.java index ca2417f4ad..fcb8432b97 100644 --- a/web/src/main/java/org/springframework/security/web/PortResolver.java +++ b/web/src/main/java/org/springframework/security/web/PortResolver.java @@ -30,15 +30,15 @@ import javax.servlet.ServletRequest; * @author Ben Alex */ public interface PortResolver { + // ~ Methods // ======================================================================================================== /** * Indicates the port the ServletRequest was received on. - * * @param request that the method should lookup the port for - * * @return the port the request was received on */ int getServerPort(ServletRequest request); + } diff --git a/web/src/main/java/org/springframework/security/web/PortResolverImpl.java b/web/src/main/java/org/springframework/security/web/PortResolverImpl.java index d77bb353a0..1c297ca15b 100644 --- a/web/src/main/java/org/springframework/security/web/PortResolverImpl.java +++ b/web/src/main/java/org/springframework/security/web/PortResolverImpl.java @@ -35,6 +35,7 @@ import javax.servlet.ServletRequest; * @author Ben Alex */ public class PortResolverImpl implements PortResolver { + // ~ Instance fields // ================================================================================================ @@ -73,4 +74,5 @@ public class PortResolverImpl implements PortResolver { Assert.notNull(portMapper, "portMapper cannot be null"); this.portMapper = portMapper; } + } diff --git a/web/src/main/java/org/springframework/security/web/RedirectStrategy.java b/web/src/main/java/org/springframework/security/web/RedirectStrategy.java index 7bd0124459..02e311cfc1 100644 --- a/web/src/main/java/org/springframework/security/web/RedirectStrategy.java +++ b/web/src/main/java/org/springframework/security/web/RedirectStrategy.java @@ -35,6 +35,6 @@ public interface RedirectStrategy { * @param response the response to redirect * @param url the target URL to redirect to, for example "/login" */ - void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) - throws IOException; + void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException; + } diff --git a/web/src/main/java/org/springframework/security/web/SecurityFilterChain.java b/web/src/main/java/org/springframework/security/web/SecurityFilterChain.java index 446de5547c..8ef72b0b67 100644 --- a/web/src/main/java/org/springframework/security/web/SecurityFilterChain.java +++ b/web/src/main/java/org/springframework/security/web/SecurityFilterChain.java @@ -25,9 +25,7 @@ import java.util.*; *

        * Used to configure a {@code FilterChainProxy}. * - * * @author Luke Taylor - * * @since 3.1 */ public interface SecurityFilterChain { @@ -35,4 +33,5 @@ public interface SecurityFilterChain { boolean matches(HttpServletRequest request); List getFilters(); + } diff --git a/web/src/main/java/org/springframework/security/web/WebAttributes.java b/web/src/main/java/org/springframework/security/web/WebAttributes.java index e280fb19e4..38ea04be0e 100644 --- a/web/src/main/java/org/springframework/security/web/WebAttributes.java +++ b/web/src/main/java/org/springframework/security/web/WebAttributes.java @@ -26,6 +26,7 @@ import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator; * @since 3.0.3 */ public final class WebAttributes { + /** * Used to cache an {@code AccessDeniedException} in the request for rendering. * @@ -47,6 +48,7 @@ public final class WebAttributes { * @see WebInvocationPrivilegeEvaluator * @since 3.1.3 */ - public static final String WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE = WebAttributes.class - .getName() + ".WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE"; + public static final String WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE = WebAttributes.class.getName() + + ".WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE"; + } diff --git a/web/src/main/java/org/springframework/security/web/access/AccessDeniedHandler.java b/web/src/main/java/org/springframework/security/web/access/AccessDeniedHandler.java index aa40b8deb5..323b0f2bb5 100644 --- a/web/src/main/java/org/springframework/security/web/access/AccessDeniedHandler.java +++ b/web/src/main/java/org/springframework/security/web/access/AccessDeniedHandler.java @@ -31,20 +31,19 @@ import javax.servlet.http.HttpServletResponse; * @author Ben Alex */ public interface AccessDeniedHandler { + // ~ Methods // ======================================================================================================== /** * Handles an access denied failure. - * * @param request that resulted in an AccessDeniedException * @param response so that the user agent can be advised of the failure * @param accessDeniedException that caused the invocation - * * @throws IOException in the event of an IOException * @throws ServletException in the event of a ServletException */ - void handle(HttpServletRequest request, HttpServletResponse response, - AccessDeniedException accessDeniedException) throws IOException, - ServletException; + void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) + throws IOException, ServletException; + } diff --git a/web/src/main/java/org/springframework/security/web/access/AccessDeniedHandlerImpl.java b/web/src/main/java/org/springframework/security/web/access/AccessDeniedHandlerImpl.java index 742dcb64dc..82f9cc7c59 100644 --- a/web/src/main/java/org/springframework/security/web/access/AccessDeniedHandlerImpl.java +++ b/web/src/main/java/org/springframework/security/web/access/AccessDeniedHandlerImpl.java @@ -43,6 +43,7 @@ import org.springframework.security.web.WebAttributes; * @author Ben Alex */ public class AccessDeniedHandlerImpl implements AccessDeniedHandler { + // ~ Static fields/initializers // ===================================================================================== @@ -57,13 +58,11 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler { // ======================================================================================================== public void handle(HttpServletRequest request, HttpServletResponse response, - AccessDeniedException accessDeniedException) throws IOException, - ServletException { + AccessDeniedException accessDeniedException) throws IOException, ServletException { if (!response.isCommitted()) { if (errorPage != null) { // Put exception into request scope (perhaps of use to a view) - request.setAttribute(WebAttributes.ACCESS_DENIED_403, - accessDeniedException); + request.setAttribute(WebAttributes.ACCESS_DENIED_403, accessDeniedException); // Set the 403 status code. response.setStatus(HttpStatus.FORBIDDEN.value()); @@ -73,8 +72,7 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler { dispatcher.forward(request, response); } else { - response.sendError(HttpStatus.FORBIDDEN.value(), - HttpStatus.FORBIDDEN.getReasonPhrase()); + response.sendError(HttpStatus.FORBIDDEN.value(), HttpStatus.FORBIDDEN.getReasonPhrase()); } } } @@ -82,9 +80,7 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler { /** * The error page to use. Must begin with a "/" and is interpreted relative to the * current context root. - * * @param errorPage the dispatcher path to display - * * @throws IllegalArgumentException if the argument doesn't comply with the above * limitations */ @@ -95,4 +91,5 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler { this.errorPage = errorPage; } + } diff --git a/web/src/main/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluator.java b/web/src/main/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluator.java index 229eeb749a..6bbc035266 100644 --- a/web/src/main/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluator.java +++ b/web/src/main/java/org/springframework/security/web/access/DefaultWebInvocationPrivilegeEvaluator.java @@ -34,13 +34,12 @@ import org.springframework.util.Assert; * @author Luke Taylor * @since 3.0 */ -public class DefaultWebInvocationPrivilegeEvaluator implements - WebInvocationPrivilegeEvaluator { +public class DefaultWebInvocationPrivilegeEvaluator implements WebInvocationPrivilegeEvaluator { + // ~ Static fields/initializers // ===================================================================================== - protected static final Log logger = LogFactory - .getLog(DefaultWebInvocationPrivilegeEvaluator.class); + protected static final Log logger = LogFactory.getLog(DefaultWebInvocationPrivilegeEvaluator.class); // ~ Instance fields // ================================================================================================ @@ -50,11 +49,9 @@ public class DefaultWebInvocationPrivilegeEvaluator implements // ~ Constructors // =================================================================================================== - public DefaultWebInvocationPrivilegeEvaluator( - AbstractSecurityInterceptor securityInterceptor) { + public DefaultWebInvocationPrivilegeEvaluator(AbstractSecurityInterceptor securityInterceptor) { Assert.notNull(securityInterceptor, "SecurityInterceptor cannot be null"); - Assert.isTrue( - FilterInvocation.class.equals(securityInterceptor.getSecureObjectClass()), + Assert.isTrue(FilterInvocation.class.equals(securityInterceptor.getSecureObjectClass()), "AbstractSecurityInterceptor does not support FilterInvocations"); Assert.notNull(securityInterceptor.getAccessDecisionManager(), "AbstractSecurityInterceptor must provide a non-null AccessDecisionManager"); @@ -68,7 +65,6 @@ public class DefaultWebInvocationPrivilegeEvaluator implements /** * Determines whether the user represented by the supplied Authentication * object is allowed to invoke the supplied URI. - * * @param uri the URI excluding the context path (a default context path setting will * be used) */ @@ -85,7 +81,6 @@ public class DefaultWebInvocationPrivilegeEvaluator implements * metadata applies to a given request URI, so generally the contextPath * is unimportant unless you are using a custom * FilterInvocationSecurityMetadataSource. - * * @param uri the URI excluding the context path * @param contextPath the context path (may be null, in which case a default value * will be used). @@ -94,13 +89,11 @@ public class DefaultWebInvocationPrivilegeEvaluator implements * be used in evaluation whether access should be granted. * @return true if access is allowed, false if denied */ - public boolean isAllowed(String contextPath, String uri, String method, - Authentication authentication) { + public boolean isAllowed(String contextPath, String uri, String method, Authentication authentication) { Assert.notNull(uri, "uri parameter is required"); FilterInvocation fi = new FilterInvocation(contextPath, uri, method); - Collection attrs = securityInterceptor - .obtainSecurityMetadataSource().getAttributes(fi); + Collection attrs = securityInterceptor.obtainSecurityMetadataSource().getAttributes(fi); if (attrs == null) { if (securityInterceptor.isRejectPublicInvocations()) { @@ -115,13 +108,11 @@ public class DefaultWebInvocationPrivilegeEvaluator implements } try { - securityInterceptor.getAccessDecisionManager().decide(authentication, fi, - attrs); + securityInterceptor.getAccessDecisionManager().decide(authentication, fi, attrs); } catch (AccessDeniedException unauthorized) { if (logger.isDebugEnabled()) { - logger.debug(fi.toString() + " denied for " + authentication.toString(), - unauthorized); + logger.debug(fi.toString() + " denied for " + authentication.toString(), unauthorized); } return false; @@ -129,4 +120,5 @@ public class DefaultWebInvocationPrivilegeEvaluator implements return true; } + } diff --git a/web/src/main/java/org/springframework/security/web/access/DelegatingAccessDeniedHandler.java b/web/src/main/java/org/springframework/security/web/access/DelegatingAccessDeniedHandler.java index bb4a33a052..812edbcd92 100644 --- a/web/src/main/java/org/springframework/security/web/access/DelegatingAccessDeniedHandler.java +++ b/web/src/main/java/org/springframework/security/web/access/DelegatingAccessDeniedHandler.java @@ -36,13 +36,13 @@ import org.springframework.util.Assert; * */ public final class DelegatingAccessDeniedHandler implements AccessDeniedHandler { + private final LinkedHashMap, AccessDeniedHandler> handlers; private final AccessDeniedHandler defaultHandler; /** * Creates a new instance - * * @param handlers a map of the {@link AccessDeniedException} class to the * {@link AccessDeniedHandler} that should be used. Each is considered in the order * they are specified and only the first {@link AccessDeniedHandler} is ued. @@ -59,10 +59,8 @@ public final class DelegatingAccessDeniedHandler implements AccessDeniedHandler } public void handle(HttpServletRequest request, HttpServletResponse response, - AccessDeniedException accessDeniedException) throws IOException, - ServletException { - for (Entry, AccessDeniedHandler> entry : handlers - .entrySet()) { + AccessDeniedException accessDeniedException) throws IOException, ServletException { + for (Entry, AccessDeniedHandler> entry : handlers.entrySet()) { Class handlerClass = entry.getKey(); if (handlerClass.isAssignableFrom(accessDeniedException.getClass())) { AccessDeniedHandler handler = entry.getValue(); diff --git a/web/src/main/java/org/springframework/security/web/access/ExceptionTranslationFilter.java b/web/src/main/java/org/springframework/security/web/access/ExceptionTranslationFilter.java index 3e3345250c..91fc60bedc 100644 --- a/web/src/main/java/org/springframework/security/web/access/ExceptionTranslationFilter.java +++ b/web/src/main/java/org/springframework/security/web/access/ExceptionTranslationFilter.java @@ -58,13 +58,15 @@ import java.io.IOException; * authenticationEntryPoint will be launched. If they are not an anonymous * user, the filter will delegate to the * {@link org.springframework.security.web.access.AccessDeniedHandler}. By default the - * filter will use {@link org.springframework.security.web.access.AccessDeniedHandlerImpl}. + * filter will use + * {@link org.springframework.security.web.access.AccessDeniedHandlerImpl}. *

        * To use this filter, it is necessary to specify the following properties: *