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 d762ed7992..79a2265962 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 @@ -17,18 +17,15 @@ package org.springframework.security.config.annotation.web.configurers; import jakarta.servlet.http.HttpServletRequest; -import org.jspecify.annotations.Nullable; import org.springframework.context.ApplicationContext; import org.springframework.security.authentication.AuthenticationDetailsSource; import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.AuthenticationUserDetailsService; import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper; import org.springframework.security.core.userdetails.UserDetailsService; @@ -182,7 +179,8 @@ public final class X509Configurer> public void init(H http) { PreAuthenticatedAuthenticationProvider authenticationProvider = new PreAuthenticatedAuthenticationProvider(); authenticationProvider.setPreAuthenticatedUserDetailsService(getAuthenticationUserDetailsService(http)); - http.authenticationProvider(new AuthorityGrantingAuthenticationProvider(authenticationProvider)) + authenticationProvider.setGrantedAuthoritySupplier(() -> AuthorityUtils.createAuthorityList("FACTOR_X509")); + http.authenticationProvider(authenticationProvider) .setSharedObject(AuthenticationEntryPoint.class, new Http403ForbiddenEntryPoint()); ExceptionHandlingConfigurer exceptions = http.getConfigurer(ExceptionHandlingConfigurer.class); if (exceptions != null) { @@ -234,31 +232,4 @@ public final class X509Configurer> return context.getBeanProvider(type).getIfUnique(); } - private static final class AuthorityGrantingAuthenticationProvider implements AuthenticationProvider { - - private final AuthenticationProvider delegate; - - private AuthorityGrantingAuthenticationProvider(AuthenticationProvider delegate) { - this.delegate = delegate; - } - - @Override - public @Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException { - Authentication result = this.delegate.authenticate(authentication); - if (result == null) { - return result; - } - return result - .toBuilder() - .authorities((a) -> a.add(new SimpleGrantedAuthority("FACTOR_X509"))) - .build(); - } - - @Override - public boolean supports(Class authentication) { - return true; - } - - } - } diff --git a/web/src/main/java/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationProvider.java b/web/src/main/java/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationProvider.java index 486847778b..6c767b892e 100644 --- a/web/src/main/java/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationProvider.java +++ b/web/src/main/java/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationProvider.java @@ -16,6 +16,11 @@ package org.springframework.security.web.authentication.preauth; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.function.Supplier; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jspecify.annotations.Nullable; @@ -28,6 +33,7 @@ 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.GrantedAuthority; import org.springframework.security.core.userdetails.AuthenticationUserDetailsService; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsChecker; @@ -57,6 +63,8 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker(); + private Supplier> grantedAuthoritySupplier = List::of; + private boolean throwExceptionWhenTokenRejected; private int order = -1; // default: same as non-ordered @@ -98,8 +106,10 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro UserDetails userDetails = this.preAuthenticatedUserDetailsService .loadUserDetails((PreAuthenticatedAuthenticationToken) authentication); this.userDetailsChecker.check(userDetails); + Collection authorities = new LinkedHashSet<>(userDetails.getAuthorities()); + authorities.addAll(this.grantedAuthoritySupplier.get()); PreAuthenticatedAuthenticationToken result = new PreAuthenticatedAuthenticationToken(userDetails, - authentication.getCredentials(), userDetails.getAuthorities()); + authentication.getCredentials(), authorities); result.setDetails(authentication.getDetails()); return result; } @@ -142,6 +152,14 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro this.userDetailsChecker = userDetailsChecker; } + /** + * Sets authorities that this provider should grant once authentication completes + * @param grantedAuthoritySupplier the supplier that grants authorities + */ + public void setGrantedAuthoritySupplier(Supplier> grantedAuthoritySupplier) { + this.grantedAuthoritySupplier = grantedAuthoritySupplier; + } + @Override public int getOrder() { return this.order;