1
0
mirror of synced 2026-05-22 21:33:16 +00:00

Move FACTOR_ constants to FactorGrantedAuthority

Previously GrantedAuthorities had an implicit package tangle because it
was located in ~.core and FactorGrantedAuthority is in ~.core.authority
and FactorGrantedAuthority's authority property was implicitly expected
to be constants found in `GrantedAuthorities`.

This commit moves the constants to the FactorGrantedAuthority which
resolves this tangle. It wasn't initially done because
FactorGrantedAuthority did not exist at that time.

Closes gh-18030
This commit is contained in:
Rob Winch
2025-10-08 14:26:46 -05:00
parent e290c98e97
commit d18431a78d
78 changed files with 271 additions and 307 deletions
@@ -36,7 +36,6 @@ import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthorities;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.authority.FactorGrantedAuthority;
@@ -100,7 +99,7 @@ public abstract class AbstractUserDetailsAuthenticationProvider
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
private static final String AUTHORITY = GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY;
private static final String AUTHORITY = FactorGrantedAuthority.PASSWORD_AUTHORITY;
/**
* Allows subclasses to perform any additional checks of a returned (or cached)
@@ -44,7 +44,6 @@ import org.springframework.security.authentication.jaas.event.JaasAuthentication
import org.springframework.security.authentication.jaas.event.JaasAuthenticationSuccessEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthorities;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.FactorGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
@@ -122,7 +121,7 @@ import org.springframework.util.ObjectUtils;
public abstract class AbstractJaasAuthenticationProvider implements AuthenticationProvider,
ApplicationEventPublisherAware, InitializingBean, ApplicationListener<SessionDestroyedEvent> {
private static final String AUTHORITY = GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY;
private static final String AUTHORITY = FactorGrantedAuthority.PASSWORD_AUTHORITY;
private ApplicationEventPublisher applicationEventPublisher = (event) -> {
};
@@ -23,7 +23,6 @@ import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthorities;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.FactorGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
@@ -41,7 +40,7 @@ import org.springframework.util.Assert;
*/
public final class OneTimeTokenAuthenticationProvider implements AuthenticationProvider {
private static final String AUTHORITY = GrantedAuthorities.FACTOR_OTT_AUTHORITY;
private static final String AUTHORITY = FactorGrantedAuthority.OTT_AUTHORITY;
private final OneTimeTokenService oneTimeTokenService;
@@ -1,78 +0,0 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* 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.core;
/**
* Constants for {@link GrantedAuthority}.
*
* @author Rob Winch
* @since 7.0
*/
public final class GrantedAuthorities {
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that OAuth2
* Authorization Code was used to authenticate.
*/
public static final String FACTOR_AUTHORIZATION_CODE_AUTHORITY = "FACTOR_AUTHORIZATION_CODE";
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that bearer
* authentication was used to authenticate.
*/
public static final String FACTOR_BEARER_AUTHORITY = "FACTOR_BEARER";
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that CAS was
* used to authenticate.
*/
public static final String FACTOR_CAS_AUTHORITY = "FACTOR_CAS";
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that one time
* token was used to authenticate.
*/
public static final String FACTOR_OTT_AUTHORITY = "FACTOR_OTT";
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that a password
* was used to authenticate.
*/
public static final String FACTOR_PASSWORD_AUTHORITY = "FACTOR_PASSWORD";
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that SAML was
* used to authenticate.
*/
public static final String FACTOR_SAML_RESPONSE_AUTHORITY = "FACTOR_SAML_RESPONSE";
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that WebAuthn
* was used to authenticate.
*/
public static final String FACTOR_WEBAUTHN_AUTHORITY = "FACTOR_WEBAUTHN";
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that X509 was
* used to authenticate.
*/
public static final String FACTOR_X509_AUTHORITY = "FACTOR_X509";
private GrantedAuthorities() {
}
}
@@ -34,6 +34,54 @@ import org.springframework.util.Assert;
*/
public final class FactorGrantedAuthority implements GrantedAuthority {
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that OAuth2
* Authorization Code was used to authenticate.
*/
public static final String AUTHORIZATION_CODE_AUTHORITY = "FACTOR_AUTHORIZATION_CODE";
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that bearer
* authentication was used to authenticate.
*/
public static final String BEARER_AUTHORITY = "FACTOR_BEARER";
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that CAS was
* used to authenticate.
*/
public static final String CAS_AUTHORITY = "FACTOR_CAS";
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that one time
* token was used to authenticate.
*/
public static final String OTT_AUTHORITY = "FACTOR_OTT";
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that a password
* was used to authenticate.
*/
public static final String PASSWORD_AUTHORITY = "FACTOR_PASSWORD";
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that SAML was
* used to authenticate.
*/
public static final String SAML_RESPONSE_AUTHORITY = "FACTOR_SAML_RESPONSE";
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that WebAuthn
* was used to authenticate.
*/
public static final String WEBAUTHN_AUTHORITY = "FACTOR_WEBAUTHN";
/**
* The standard {@link GrantedAuthority#getAuthority()} that indicates that X509 was
* used to authenticate.
*/
public static final String X509_AUTHORITY = "FACTOR_X509";
private static final long serialVersionUID = 1998010439847123984L;
private final String authority;
@@ -38,9 +38,9 @@ import org.springframework.security.authentication.password.CompromisedPasswordC
import org.springframework.security.authentication.password.CompromisedPasswordDecision;
import org.springframework.security.authentication.password.CompromisedPasswordException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthorities;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.FactorGrantedAuthority;
import org.springframework.security.core.userdetails.PasswordEncodedUser;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
@@ -512,7 +512,7 @@ public class DaoAuthenticationProviderTests {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider(withUsers(user));
Authentication request = new UsernamePasswordAuthenticationToken("user", "password");
Authentication result = provider.authenticate(request);
SecurityAssertions.assertThat(result).hasAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY);
SecurityAssertions.assertThat(result).hasAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY);
}
private UserDetailsService withUsers(UserDetails... users) {
@@ -40,9 +40,9 @@ import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthorities;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.FactorGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.session.SessionDestroyedEvent;
@@ -242,7 +242,7 @@ public class JaasAuthenticationProviderTests {
public void authenticateWhenSuccessThenIssuesFactor() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password");
Authentication result = this.jaasProvider.authenticate(token);
SecurityAssertions.assertThat(result).hasAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY);
SecurityAssertions.assertThat(result).hasAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY);
}
private static class MockLoginContext extends LoginContext {
@@ -28,7 +28,7 @@ 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.GrantedAuthorities;
import org.springframework.security.core.authority.FactorGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -109,7 +109,7 @@ public class OneTimeTokenAuthenticationProviderTests {
OneTimeTokenAuthenticationToken token = new OneTimeTokenAuthenticationToken(TOKEN);
Authentication authentication = this.provider.authenticate(token);
SecurityAssertions.assertThat(authentication).hasAuthority(GrantedAuthorities.FACTOR_OTT_AUTHORITY);
SecurityAssertions.assertThat(authentication).hasAuthority(FactorGrantedAuthority.OTT_AUTHORITY);
}
@Test
@@ -26,7 +26,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthorities;
import org.springframework.security.core.authority.FactorGrantedAuthority;
import static org.assertj.core.api.Assertions.assertThat;
@@ -43,11 +42,11 @@ class AllFactorsAuthorizationManagerTests {
private static final Object DOES_NOT_MATTER = new Object();
private static RequiredFactor REQUIRED_PASSWORD = RequiredFactor
.withAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY)
.withAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY)
.build();
private static RequiredFactor EXPIRING_PASSWORD = RequiredFactor
.withAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY)
.withAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY)
.validDuration(Duration.ofHours(1))
.build();
@@ -67,10 +66,10 @@ class AllFactorsAuthorizationManagerTests {
@Test
void authorizeWhenConsumerGranted() {
AllFactorsAuthorizationManager<Object> allFactors = AllFactorsAuthorizationManager.builder()
.requiredFactor((required) -> required.authority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY))
.requiredFactor((required) -> required.authority(FactorGrantedAuthority.PASSWORD_AUTHORITY))
.build();
FactorGrantedAuthority passwordFactor = FactorGrantedAuthority
.withAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY)
.withAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY)
.issuedAt(Instant.now())
.build();
Authentication authentication = new TestingAuthenticationToken("user", "password", passwordFactor);
@@ -171,7 +170,7 @@ class AllFactorsAuthorizationManagerTests {
Duration expiresIn = Duration.ofHours(1);
Instant justExpired = now.minus(expiresIn);
Clock clock = Clock.fixed(now, ZoneId.systemDefault());
RequiredFactor expiringPassword = RequiredFactor.withAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY)
RequiredFactor expiringPassword = RequiredFactor.withAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY)
.validDuration(expiresIn)
.build();
AllFactorsAuthorizationManager<Object> allFactors = AllFactorsAuthorizationManager.builder()
@@ -193,7 +192,7 @@ class AllFactorsAuthorizationManagerTests {
Duration expiresIn = Duration.ofHours(1);
Instant justExpired = now.minus(expiresIn).plus(Duration.ofNanos(1));
Clock clock = Clock.fixed(now, ZoneId.systemDefault());
RequiredFactor expiringPassword = RequiredFactor.withAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY)
RequiredFactor expiringPassword = RequiredFactor.withAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY)
.validDuration(expiresIn)
.build();
AllFactorsAuthorizationManager<Object> allFactors = AllFactorsAuthorizationManager.builder()
@@ -21,7 +21,7 @@ import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.security.core.GrantedAuthorities;
import org.springframework.security.core.authority.FactorGrantedAuthority;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
@@ -42,7 +42,7 @@ class FactorAuthorizationDecisionTests {
@Test
void isGrantedWhenNotEmptyThenFalse() {
RequiredFactor requiredPassword = RequiredFactor.withAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY)
RequiredFactor requiredPassword = RequiredFactor.withAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY)
.build();
RequiredFactorError missingPassword = RequiredFactorError.createMissing(requiredPassword);
FactorAuthorizationDecision decision = new FactorAuthorizationDecision(List.of(missingPassword));
@@ -51,7 +51,7 @@ class FactorAuthorizationDecisionTests {
@Test
void getFactorErrors() {
RequiredFactor requiredPassword = RequiredFactor.withAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY)
RequiredFactor requiredPassword = RequiredFactor.withAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY)
.build();
RequiredFactorError missingPassword = RequiredFactorError.createMissing(requiredPassword);
List<RequiredFactorError> factorErrors = List.of(missingPassword);
@@ -67,7 +67,7 @@ class FactorAuthorizationDecisionTests {
@Test
void constructorWhenContainsNullThenThrowIllegalArgumentException() {
RequiredFactor requiredPassword = RequiredFactor.withAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY)
RequiredFactor requiredPassword = RequiredFactor.withAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY)
.build();
RequiredFactorError missingPassword = RequiredFactorError.createMissing(requiredPassword);
List<RequiredFactorError> hasNullValue = Arrays.asList(missingPassword, null);
@@ -20,7 +20,7 @@ import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.security.core.GrantedAuthorities;
import org.springframework.security.core.authority.FactorGrantedAuthority;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
@@ -37,16 +37,16 @@ class MapRequiredAuthoritiesRepositoryTests {
private String username = "user";
private List<String> authorities = List.of(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY,
GrantedAuthorities.FACTOR_OTT_AUTHORITY);
private List<String> authorities = List.of(FactorGrantedAuthority.PASSWORD_AUTHORITY,
FactorGrantedAuthority.OTT_AUTHORITY);
@Test
void workflow() {
this.repository.saveRequiredAuthorities(this.username, this.authorities);
assertThat(this.repository.findRequiredAuthorities(this.username))
.containsExactlyInAnyOrderElementsOf(this.authorities);
List<String> otherAuthorities = List.of(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY,
GrantedAuthorities.FACTOR_WEBAUTHN_AUTHORITY);
List<String> otherAuthorities = List.of(FactorGrantedAuthority.PASSWORD_AUTHORITY,
FactorGrantedAuthority.WEBAUTHN_AUTHORITY);
this.repository.saveRequiredAuthorities(this.username, otherAuthorities);
assertThat(this.repository.findRequiredAuthorities(this.username))
.containsExactlyInAnyOrderElementsOf(otherAuthorities);
@@ -20,7 +20,7 @@ import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.springframework.security.core.GrantedAuthorities;
import org.springframework.security.core.authority.FactorGrantedAuthority;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
@@ -34,7 +34,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
class RequiredFactorErrorTests {
public static final RequiredFactor REQUIRED_FACTOR = RequiredFactor
.withAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY)
.withAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY)
.validDuration(Duration.ofHours(1))
.build();
@@ -56,7 +56,7 @@ class RequiredFactorErrorTests {
@Test
void createExpiredWhenNullValidDurationThenIllegalArgumentException() {
RequiredFactor requiredPassword = RequiredFactor.withAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY)
RequiredFactor requiredPassword = RequiredFactor.withAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY)
.build();
assertThatIllegalArgumentException().isThrownBy(() -> RequiredFactorError.createExpired(requiredPassword));
}
@@ -20,7 +20,7 @@ import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.springframework.security.core.GrantedAuthorities;
import org.springframework.security.core.authority.FactorGrantedAuthority;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
@@ -41,19 +41,19 @@ class RequiredFactorTests {
@Test
void withAuthorityThenEquals() {
RequiredFactor requiredPassword = RequiredFactor.withAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY)
RequiredFactor requiredPassword = RequiredFactor.withAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY)
.build();
assertThat(requiredPassword.getAuthority()).isEqualTo(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY);
assertThat(requiredPassword.getAuthority()).isEqualTo(FactorGrantedAuthority.PASSWORD_AUTHORITY);
assertThat(requiredPassword.getValidDuration()).isNull();
}
@Test
void builderValidDurationThenEquals() {
Duration validDuration = Duration.ofMinutes(1);
RequiredFactor requiredPassword = RequiredFactor.withAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY)
RequiredFactor requiredPassword = RequiredFactor.withAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY)
.validDuration(validDuration)
.build();
assertThat(requiredPassword.getAuthority()).isEqualTo(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY);
assertThat(requiredPassword.getAuthority()).isEqualTo(FactorGrantedAuthority.PASSWORD_AUTHORITY);
assertThat(requiredPassword.getValidDuration()).isEqualTo(validDuration);
}