Просмотр исходного кода

Add Factor Tests for Authentication Providers

Issue gh-17933
Josh Cummings 1 неделя назад
Родитель
Сommit
758b35df9c

+ 10 - 0
core/src/test/java/org/springframework/security/authentication/dao/DaoAuthenticationProviderTests.java

@@ -31,6 +31,7 @@ import org.springframework.security.authentication.CredentialsExpiredException;
 import org.springframework.security.authentication.DisabledException;
 import org.springframework.security.authentication.InternalAuthenticationServiceException;
 import org.springframework.security.authentication.LockedException;
+import org.springframework.security.authentication.SecurityAssertions;
 import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.authentication.password.CompromisedPasswordChecker;
@@ -504,6 +505,15 @@ public class DaoAuthenticationProviderTests {
 		assertThat(authentication).isNotNull();
 	}
 
+	@Test
+	void authenticateWhenSuccessThenIssuesFactor() {
+		UserDetails user = PasswordEncodedUser.user();
+		DaoAuthenticationProvider provider = new DaoAuthenticationProvider(withUsers(user));
+		Authentication request = new UsernamePasswordAuthenticationToken("user", "password");
+		Authentication result = provider.authenticate(request);
+		SecurityAssertions.assertThat(result).hasAuthority("FACTOR_PASSWORD");
+	}
+
 	private UserDetailsService withUsers(UserDetails... users) {
 		return new InMemoryUserDetailsManager(users);
 	}

+ 13 - 0
core/src/test/java/org/springframework/security/authentication/ott/OneTimeTokenAuthenticationProviderTests.java

@@ -26,6 +26,7 @@ import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 
 import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.SecurityAssertions;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.userdetails.User;
 import org.springframework.security.core.userdetails.UserDetailsService;
@@ -98,6 +99,18 @@ public class OneTimeTokenAuthenticationProviderTests {
 		assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> this.provider.authenticate(token));
 	}
 
+	@Test
+	void authenticateWhenSuccessThenIssuesFactor() {
+		given(this.oneTimeTokenService.consume(any()))
+			.willReturn(new DefaultOneTimeToken(TOKEN, USERNAME, Instant.now().plusSeconds(120)));
+		given(this.userDetailsService.loadUserByUsername(anyString()))
+			.willReturn(new User(USERNAME, PASSWORD, List.of()));
+		OneTimeTokenAuthenticationToken token = new OneTimeTokenAuthenticationToken(TOKEN);
+
+		Authentication authentication = this.provider.authenticate(token);
+		SecurityAssertions.assertThat(authentication).hasAuthority("FACTOR_OTT");
+	}
+
 	@Test
 	void constructorWhenOneTimeTokenServiceIsNullThenThrowIllegalArgumentException() {
 		// @formatter:off

+ 11 - 0
ldap/src/test/java/org/springframework/security/ldap/authentication/LdapAuthenticationProviderTests.java

@@ -26,6 +26,7 @@ import org.springframework.ldap.core.DirContextOperations;
 import org.springframework.ldap.support.LdapNameBuilder;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.authentication.InternalAuthenticationServiceException;
+import org.springframework.security.authentication.SecurityAssertions;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.GrantedAuthority;
@@ -156,6 +157,16 @@ public class LdapAuthenticationProviderTests {
 			.isSameAs(expectedCause);
 	}
 
+	@Test
+	void authenticateWhenSuccessThenIssuesFactor() {
+		MockAuthenticator authenticator = new MockAuthenticator();
+		MockAuthoritiesPopulator populator = new MockAuthoritiesPopulator();
+		LdapAuthenticationProvider ldapProvider = new LdapAuthenticationProvider(authenticator, populator);
+		UsernamePasswordAuthenticationToken request = new UsernamePasswordAuthenticationToken("ben", "benspassword");
+		Authentication result = ldapProvider.authenticate(request);
+		SecurityAssertions.assertThat(result).hasAuthority("FACTOR_PASSWORD");
+	}
+
 	class MockAuthenticator implements LdapAuthenticator {
 
 		@Override

+ 14 - 0
oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/authentication/OAuth2LoginAuthenticationProviderTests.java

@@ -29,6 +29,8 @@ import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.stubbing.Answer;
 
+import org.springframework.security.authentication.SecurityAssertions;
+import org.springframework.security.core.Authentication;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.AuthorityUtils;
 import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
@@ -48,6 +50,7 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResp
 import org.springframework.security.oauth2.core.endpoint.TestOAuth2AuthorizationRequests;
 import org.springframework.security.oauth2.core.endpoint.TestOAuth2AuthorizationResponses;
 import org.springframework.security.oauth2.core.user.OAuth2User;
+import org.springframework.security.oauth2.core.user.TestOAuth2Users;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -206,6 +209,17 @@ public class OAuth2LoginAuthenticationProviderTests {
 			.containsAllEntriesOf(accessTokenResponse.getAdditionalParameters());
 	}
 
+	@Test
+	public void authenticateWhenLoginSuccessThenIssuesFactor() {
+		OAuth2AccessTokenResponse accessTokenResponse = accessTokenSuccessResponse();
+		given(this.accessTokenResponseClient.getTokenResponse(any())).willReturn(accessTokenResponse);
+		given(this.userService.loadUser(any())).willReturn(TestOAuth2Users.create());
+		Authentication request = new OAuth2LoginAuthenticationToken(this.clientRegistration,
+				this.authorizationExchange);
+		Authentication result = this.authenticationProvider.authenticate(request);
+		SecurityAssertions.assertThat(result).hasAuthority("FACTOR_AUTHORIZATION_CODE");
+	}
+
 	private OAuth2AccessTokenResponse accessTokenSuccessResponse() {
 		Instant expiresAt = Instant.now().plusSeconds(5);
 		Set<String> scopes = new LinkedHashSet<>(Arrays.asList("scope1", "scope2"));

+ 8 - 0
oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationConverterTests.java

@@ -24,6 +24,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.core.convert.converter.Converter;
 import org.springframework.security.authentication.AbstractAuthenticationToken;
 import org.springframework.security.authentication.SecurityAssertions;
+import org.springframework.security.core.Authentication;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.security.oauth2.jwt.Jwt;
@@ -110,4 +111,11 @@ public class JwtAuthenticationConverterTests {
 		assertThat(authentication.getName()).isEqualTo("100");
 	}
 
+	@Test
+	public void convertWhenDefaultsThenIssuesFactor() {
+		Jwt jwt = TestJwts.jwt().build();
+		Authentication result = this.jwtAuthenticationConverter.convert(jwt);
+		SecurityAssertions.assertThat(result).hasAuthority("FACTOR_BEARER");
+	}
+
 }

+ 11 - 0
oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProviderTests.java

@@ -146,6 +146,17 @@ public class OpaqueTokenAuthenticationProviderTests {
 		verifyNoMoreInteractions(introspector, authenticationConverter);
 	}
 
+	@Test
+	void authenticateWhenSuccessThenIssuesFactor() {
+		OAuth2AuthenticatedPrincipal principal = TestOAuth2AuthenticatedPrincipals.active();
+		OpaqueTokenIntrospector introspector = mock(OpaqueTokenIntrospector.class);
+		given(introspector.introspect(any())).willReturn(principal);
+		OpaqueTokenAuthenticationProvider provider = new OpaqueTokenAuthenticationProvider(introspector);
+		Authentication request = new BearerTokenAuthenticationToken("token");
+		Authentication result = provider.authenticate(request);
+		SecurityAssertions.assertThat(result).hasAuthority("FACTOR_BEARER");
+	}
+
 	static Predicate<GrantedAuthority> isScope() {
 		return (a) -> a.getAuthority().startsWith("SCOPE_");
 	}

+ 8 - 0
saml2/saml2-service-provider/src/opensaml5Test/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml5AuthenticationProviderTests.java

@@ -985,6 +985,14 @@ public class OpenSaml5AuthenticationProviderTests {
 		assertThatExceptionOfType(Saml2AuthenticationException.class).isThrownBy(() -> provider.authenticate(token));
 	}
 
+	@Test
+	public void authenticateWhenSuccessThenIssuesFactor() {
+		Response response = TestOpenSamlObjects.signedResponseWithOneAssertion();
+		Authentication request = token(response, verifying(registration()));
+		Authentication result = this.provider.authenticate(request);
+		SecurityAssertions.assertThat(result).hasAuthority("FACTOR_SAML_RESPONSE");
+	}
+
 	private <T extends XMLObject> T build(QName qName) {
 		return (T) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(qName).buildObject(qName);
 	}

+ 22 - 0
web/src/test/java/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationProviderTests.java

@@ -16,12 +16,18 @@
 
 package org.springframework.security.web.authentication.preauth;
 
+import java.util.Collection;
+import java.util.function.Supplier;
+
 import org.junit.jupiter.api.Test;
 
+import org.springframework.security.authentication.SecurityAssertions;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.AuthorityUtils;
 import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
+import org.springframework.security.core.userdetails.PasswordEncodedUser;
 import org.springframework.security.core.userdetails.User;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -29,6 +35,9 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 
 /**
  * @author TSARDD
@@ -89,6 +98,19 @@ public class PreAuthenticatedAuthenticationProviderTests {
 		assertThatExceptionOfType(UsernameNotFoundException.class).isThrownBy(() -> provider.authenticate(request));
 	}
 
+	@Test
+	void authenticateWhenSuccessThenIssuesFactor() {
+		UserDetails ud = PasswordEncodedUser.user();
+		PreAuthenticatedAuthenticationProvider provider = getProvider(ud);
+		Supplier<Collection<GrantedAuthority>> authorities = mock(Supplier.class);
+		given(authorities.get()).willReturn(AuthorityUtils.createAuthorityList("FACTOR"));
+		provider.setGrantedAuthoritySupplier(authorities);
+		Authentication request = new PreAuthenticatedAuthenticationToken(ud.getUsername(), ud.getPassword());
+		Authentication result = provider.authenticate(request);
+		SecurityAssertions.assertThat(result).hasAuthority("FACTOR");
+		verify(authorities).get();
+	}
+
 	@Test
 	public final void supportsArbitraryObject() throws Exception {
 		PreAuthenticatedAuthenticationProvider provider = getProvider(null);

+ 61 - 0
webauthn/src/test/java/org/springframework/security/web/webauthn/authentication/WebAuthnAuthenticationProviderTests.java

@@ -0,0 +1,61 @@
+/*
+ * Copyright 2004-present 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.web.webauthn.authentication;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.security.authentication.SecurityAssertions;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.userdetails.PasswordEncodedUser;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
+import org.springframework.security.web.webauthn.api.PublicKeyCredential;
+import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
+import org.springframework.security.web.webauthn.api.TestAuthenticationAssertionResponses;
+import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialRequestOptions;
+import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialUserEntities;
+import org.springframework.security.web.webauthn.api.TestPublicKeyCredentials;
+import org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest;
+import org.springframework.security.web.webauthn.management.WebAuthnRelyingPartyOperations;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.mock;
+
+class WebAuthnAuthenticationProviderTests {
+
+	@Test
+	void authenticateWhenSuccessThenIssuesFactor() {
+		WebAuthnRelyingPartyOperations operations = mock(WebAuthnRelyingPartyOperations.class);
+		UserDetailsService users = mock(UserDetailsService.class);
+		PublicKeyCredentialRequestOptions options = TestPublicKeyCredentialRequestOptions.create().build();
+		AuthenticatorAssertionResponse response = TestAuthenticationAssertionResponses
+			.createAuthenticatorAssertionResponse()
+			.build();
+		PublicKeyCredential<AuthenticatorAssertionResponse> credentials = TestPublicKeyCredentials
+			.createPublicKeyCredential(response)
+			.build();
+		Authentication request = new WebAuthnAuthenticationRequestToken(
+				new RelyingPartyAuthenticationRequest(options, credentials));
+		WebAuthnAuthenticationProvider provider = new WebAuthnAuthenticationProvider(operations, users);
+		given(users.loadUserByUsername(any())).willReturn(PasswordEncodedUser.user());
+		given(operations.authenticate(any())).willReturn(TestPublicKeyCredentialUserEntities.userEntity().build());
+		Authentication result = provider.authenticate(request);
+		SecurityAssertions.assertThat(result).hasAuthority("FACTOR_WEBAUTHN");
+	}
+
+}