mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-10-22 02:08:48 +00:00
Add Factory Authority When Authentication Succeeds
Issue gh-17933
This commit is contained in:
parent
9eaadcc70d
commit
e8accd0499
@ -17,14 +17,18 @@
|
||||
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.userdetails.AuthenticationUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
@ -37,6 +41,7 @@ import org.springframework.security.web.authentication.preauth.x509.SubjectDnX50
|
||||
import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor;
|
||||
import org.springframework.security.web.context.RequestAttributeSecurityContextRepository;
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||
|
||||
/**
|
||||
* Adds X509 based pre authentication to an application. Since validating the certificate
|
||||
@ -177,8 +182,12 @@ public final class X509Configurer<H extends HttpSecurityBuilder<H>>
|
||||
public void init(H http) {
|
||||
PreAuthenticatedAuthenticationProvider authenticationProvider = new PreAuthenticatedAuthenticationProvider();
|
||||
authenticationProvider.setPreAuthenticatedUserDetailsService(getAuthenticationUserDetailsService(http));
|
||||
http.authenticationProvider(authenticationProvider)
|
||||
http.authenticationProvider(new AuthorityGrantingAuthenticationProvider(authenticationProvider))
|
||||
.setSharedObject(AuthenticationEntryPoint.class, new Http403ForbiddenEntryPoint());
|
||||
ExceptionHandlingConfigurer<H> exceptions = http.getConfigurer(ExceptionHandlingConfigurer.class);
|
||||
if (exceptions != null) {
|
||||
exceptions.defaultAuthenticationEntryPointFor(new Http403ForbiddenEntryPoint(), AnyRequestMatcher.INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -225,4 +234,31 @@ public final class X509Configurer<H extends HttpSecurityBuilder<H>>
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
|
||||
import org.springframework.security.core.userdetails.UserCache;
|
||||
@ -94,6 +95,8 @@ public abstract class AbstractUserDetailsAuthenticationProvider
|
||||
|
||||
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
|
||||
|
||||
private static final String AUTHORITY = "FACTOR_PASSWORD";
|
||||
|
||||
/**
|
||||
* Allows subclasses to perform any additional checks of a returned (or cached)
|
||||
* <code>UserDetails</code> for a given authentication request. Generally a subclass
|
||||
@ -197,8 +200,12 @@ public abstract class AbstractUserDetailsAuthenticationProvider
|
||||
// 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 = UsernamePasswordAuthenticationToken.authenticated(principal,
|
||||
authentication.getCredentials(), this.authoritiesMapper.mapAuthorities(user.getAuthorities()));
|
||||
UsernamePasswordAuthenticationToken result = UsernamePasswordAuthenticationToken
|
||||
.authenticated(principal, authentication.getCredentials(),
|
||||
this.authoritiesMapper.mapAuthorities(user.getAuthorities()))
|
||||
.toBuilder()
|
||||
.authorities((a) -> a.add(new SimpleGrantedAuthority(AUTHORITY)))
|
||||
.build();
|
||||
result.setDetails(authentication.getDetails());
|
||||
this.logger.debug("Authenticated user");
|
||||
return result;
|
||||
|
@ -16,10 +16,15 @@
|
||||
|
||||
package org.springframework.security.authentication.ott;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
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.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
@ -35,6 +40,8 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public final class OneTimeTokenAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
private static final String AUTHORITY = "FACTOR_OTT";
|
||||
|
||||
private final OneTimeTokenService oneTimeTokenService;
|
||||
|
||||
private final UserDetailsService userDetailsService;
|
||||
@ -56,7 +63,9 @@ public final class OneTimeTokenAuthenticationProvider implements AuthenticationP
|
||||
}
|
||||
try {
|
||||
UserDetails user = this.userDetailsService.loadUserByUsername(consumed.getUsername());
|
||||
OneTimeTokenAuthentication authenticated = new OneTimeTokenAuthentication(user, user.getAuthorities());
|
||||
Collection<GrantedAuthority> authorities = new HashSet<>(user.getAuthorities());
|
||||
authorities.add(new SimpleGrantedAuthority(AUTHORITY));
|
||||
OneTimeTokenAuthentication authenticated = new OneTimeTokenAuthentication(user, authorities);
|
||||
authenticated.setDetails(otpAuthenticationToken.getDetails());
|
||||
return authenticated;
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
@ -50,6 +51,8 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public abstract class AbstractLdapAuthenticationProvider implements AuthenticationProvider, MessageSourceAware {
|
||||
|
||||
private static final String AUTHORITY = "FACTOR_PASSWORD";
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
||||
@ -100,8 +103,11 @@ public abstract class AbstractLdapAuthenticationProvider implements Authenticati
|
||||
UserDetails user) {
|
||||
Object password = this.useAuthenticationRequestCredentials ? authentication.getCredentials()
|
||||
: user.getPassword();
|
||||
UsernamePasswordAuthenticationToken result = UsernamePasswordAuthenticationToken.authenticated(user, password,
|
||||
this.authoritiesMapper.mapAuthorities(user.getAuthorities()));
|
||||
UsernamePasswordAuthenticationToken result = UsernamePasswordAuthenticationToken
|
||||
.authenticated(user, password, this.authoritiesMapper.mapAuthorities(user.getAuthorities()))
|
||||
.toBuilder()
|
||||
.authorities((a) -> a.add(new SimpleGrantedAuthority(AUTHORITY)))
|
||||
.build();
|
||||
result.setDetails(authentication.getDetails());
|
||||
this.logger.debug("Authenticated user");
|
||||
return result;
|
||||
|
@ -17,12 +17,14 @@
|
||||
package org.springframework.security.oauth2.client.authentication;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
|
||||
@ -66,6 +68,8 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class OAuth2LoginAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
private static final String AUTHORITY = "FACTOR_AUTHORIZATION_CODE";
|
||||
|
||||
private final OAuth2AuthorizationCodeAuthenticationProvider authorizationCodeAuthenticationProvider;
|
||||
|
||||
private final OAuth2UserService<OAuth2UserRequest, OAuth2User> userService;
|
||||
@ -118,8 +122,9 @@ public class OAuth2LoginAuthenticationProvider implements AuthenticationProvider
|
||||
Map<String, Object> additionalParameters = authorizationCodeAuthenticationToken.getAdditionalParameters();
|
||||
OAuth2User oauth2User = this.userService.loadUser(new OAuth2UserRequest(
|
||||
loginAuthenticationToken.getClientRegistration(), accessToken, additionalParameters));
|
||||
Collection<? extends GrantedAuthority> mappedAuthorities = this.authoritiesMapper
|
||||
.mapAuthorities(oauth2User.getAuthorities());
|
||||
Collection<GrantedAuthority> authorities = new HashSet<>(oauth2User.getAuthorities());
|
||||
authorities.add(new SimpleGrantedAuthority(AUTHORITY));
|
||||
Collection<? extends GrantedAuthority> mappedAuthorities = this.authoritiesMapper.mapAuthorities(authorities);
|
||||
OAuth2LoginAuthenticationToken authenticationResult = new OAuth2LoginAuthenticationToken(
|
||||
loginAuthenticationToken.getClientRegistration(), loginAuthenticationToken.getAuthorizationExchange(),
|
||||
oauth2User, mappedAuthorities, accessToken, authorizationCodeAuthenticationToken.getRefreshToken());
|
||||
|
@ -17,10 +17,12 @@
|
||||
package org.springframework.security.oauth2.server.resource.authentication;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.jwt.JwtClaimNames;
|
||||
import org.springframework.util.Assert;
|
||||
@ -34,14 +36,16 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class JwtAuthenticationConverter implements Converter<Jwt, AbstractAuthenticationToken> {
|
||||
|
||||
private static final String AUTHORITY = "FACTOR_BEARER";
|
||||
|
||||
private Converter<Jwt, Collection<GrantedAuthority>> jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
|
||||
private String principalClaimName = JwtClaimNames.SUB;
|
||||
|
||||
@Override
|
||||
public final AbstractAuthenticationToken convert(Jwt jwt) {
|
||||
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
|
||||
Collection<GrantedAuthority> authorities = new HashSet<>(this.jwtGrantedAuthoritiesConverter.convert(jwt));
|
||||
authorities.add(new SimpleGrantedAuthority(AUTHORITY));
|
||||
String principalClaimValue = jwt.getClaimAsString(this.principalClaimName);
|
||||
return new JwtAuthenticationToken(jwt, authorities, principalClaimValue);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package org.springframework.security.oauth2.server.resource.authentication;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@ -28,6 +29,7 @@ import org.springframework.security.authentication.AuthenticationServiceExceptio
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;
|
||||
@ -72,6 +74,8 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public final class OpaqueTokenAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
private static final String AUTHORITY = "FACTOR_BEARER";
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final OpaqueTokenIntrospector introspector;
|
||||
@ -149,8 +153,9 @@ public final class OpaqueTokenAuthenticationProvider implements AuthenticationPr
|
||||
Instant exp = authenticatedPrincipal.getAttribute(OAuth2TokenIntrospectionClaimNames.EXP);
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, introspectedToken,
|
||||
iat, exp);
|
||||
return new BearerTokenAuthentication(authenticatedPrincipal, accessToken,
|
||||
authenticatedPrincipal.getAuthorities());
|
||||
Collection<GrantedAuthority> authorities = new HashSet<>(authenticatedPrincipal.getAuthorities());
|
||||
authorities.add(new SimpleGrantedAuthority(AUTHORITY));
|
||||
return new BearerTokenAuthentication(authenticatedPrincipal, accessToken, authorities);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,6 +21,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
@ -59,6 +60,7 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.saml2.core.Saml2Error;
|
||||
import org.springframework.security.saml2.core.Saml2ErrorCodes;
|
||||
import org.springframework.security.saml2.core.Saml2ResponseValidatorResult;
|
||||
@ -111,6 +113,8 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public final class OpenSaml5AuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
private static final String AUTHORITY = "FACTOR_SAML_RESPONSE";
|
||||
|
||||
private final BaseOpenSamlAuthenticationProvider delegate;
|
||||
|
||||
/**
|
||||
@ -899,7 +903,9 @@ public final class OpenSaml5AuthenticationProvider implements AuthenticationProv
|
||||
.attributes(BaseOpenSamlAuthenticationProvider.getAssertionAttributes(assertion))
|
||||
.build();
|
||||
Saml2AuthenticatedPrincipal principal = new DefaultSaml2AuthenticatedPrincipal(username, accessor);
|
||||
Collection<GrantedAuthority> authorities = this.grantedAuthoritiesConverter.convert(assertion);
|
||||
Collection<GrantedAuthority> authorities = new HashSet<>(
|
||||
this.grantedAuthoritiesConverter.convert(assertion));
|
||||
authorities.add(new SimpleGrantedAuthority(AUTHORITY));
|
||||
return new Saml2AssertionAuthentication(principal, accessor, authorities, registrationId);
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@ public class SecurityMockWithAuthoritiesMvcResultMatchersTests {
|
||||
List<SimpleGrantedAuthority> grantedAuthorities = new ArrayList<>();
|
||||
grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
|
||||
grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_SELLER"));
|
||||
grantedAuthorities.add(new SimpleGrantedAuthority("FACTOR_PASSWORD"));
|
||||
this.mockMvc.perform(formLogin()).andExpect(authenticated().withAuthorities(grantedAuthorities));
|
||||
}
|
||||
|
||||
|
@ -16,10 +16,15 @@
|
||||
|
||||
package org.springframework.security.web.webauthn.authentication;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
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.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialUserEntity;
|
||||
@ -39,6 +44,8 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class WebAuthnAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
private static final String AUTHORITY = "FACTOR_WEBAUTHN";
|
||||
|
||||
private final WebAuthnRelyingPartyOperations relyingPartyOperations;
|
||||
|
||||
private final UserDetailsService userDetailsService;
|
||||
@ -65,7 +72,9 @@ public class WebAuthnAuthenticationProvider implements AuthenticationProvider {
|
||||
.authenticate(webAuthnRequest.getWebAuthnRequest());
|
||||
String username = userEntity.getName();
|
||||
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
|
||||
return new WebAuthnAuthentication(userEntity, userDetails.getAuthorities());
|
||||
Collection<GrantedAuthority> authorities = new HashSet<>(userDetails.getAuthorities());
|
||||
authorities.add(new SimpleGrantedAuthority(AUTHORITY));
|
||||
return new WebAuthnAuthentication(userEntity, authorities);
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
throw new BadCredentialsException(ex.getMessage(), ex);
|
||||
|
Loading…
x
Reference in New Issue
Block a user