parent
758b35df9c
commit
6e7a181eac
|
@ -16,6 +16,9 @@
|
||||||
|
|
||||||
package org.springframework.security.cas.authentication;
|
package org.springframework.security.cas.authentication;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.apereo.cas.client.validation.Assertion;
|
import org.apereo.cas.client.validation.Assertion;
|
||||||
|
@ -35,7 +38,9 @@ import org.springframework.security.authentication.BadCredentialsException;
|
||||||
import org.springframework.security.cas.ServiceProperties;
|
import org.springframework.security.cas.ServiceProperties;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
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.GrantedAuthoritiesMapper;
|
||||||
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
|
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
|
||||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||||
|
@ -64,6 +69,8 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
|
private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
|
||||||
|
|
||||||
|
private static final String AUTHORITY = "FACTOR_CAS";
|
||||||
|
|
||||||
@SuppressWarnings("NullAway.Init")
|
@SuppressWarnings("NullAway.Init")
|
||||||
private AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService;
|
private AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService;
|
||||||
|
|
||||||
|
@ -141,8 +148,10 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
|
||||||
Assertion assertion = this.ticketValidator.validate(credentials.toString(), getServiceUrl(authentication));
|
Assertion assertion = this.ticketValidator.validate(credentials.toString(), getServiceUrl(authentication));
|
||||||
UserDetails userDetails = loadUserByAssertion(assertion);
|
UserDetails userDetails = loadUserByAssertion(assertion);
|
||||||
this.userDetailsChecker.check(userDetails);
|
this.userDetailsChecker.check(userDetails);
|
||||||
return new CasAuthenticationToken(this.key, userDetails, credentials,
|
Collection<GrantedAuthority> authorities = new ArrayList<>(
|
||||||
this.authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), userDetails, assertion);
|
this.authoritiesMapper.mapAuthorities(userDetails.getAuthorities()));
|
||||||
|
authorities.add(new SimpleGrantedAuthority(AUTHORITY));
|
||||||
|
return new CasAuthenticationToken(this.key, userDetails, credentials, authorities, userDetails, assertion);
|
||||||
}
|
}
|
||||||
catch (TicketValidationException ex) {
|
catch (TicketValidationException ex) {
|
||||||
throw new BadCredentialsException(ex.getMessage(), ex);
|
throw new BadCredentialsException(ex.getMessage(), ex);
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
|
import org.springframework.security.authentication.SecurityAssertions;
|
||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.cas.ServiceProperties;
|
import org.springframework.security.cas.ServiceProperties;
|
||||||
|
@ -346,6 +347,22 @@ public class CasAuthenticationProviderTests {
|
||||||
assertThat(checkCount.get()).isEqualTo(1);
|
assertThat(checkCount.get()).isEqualTo(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void authenticateWhenSuccessfulThenIssuesFactor() throws Exception {
|
||||||
|
CasAuthenticationProvider cap = new CasAuthenticationProvider();
|
||||||
|
cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
|
||||||
|
cap.setKey("qwerty");
|
||||||
|
StatelessTicketCache cache = new MockStatelessTicketCache();
|
||||||
|
cap.setStatelessTicketCache(cache);
|
||||||
|
cap.setServiceProperties(makeServiceProperties());
|
||||||
|
cap.setTicketValidator(new MockTicketValidator(true));
|
||||||
|
cap.afterPropertiesSet();
|
||||||
|
CasServiceTicketAuthenticationToken token = CasServiceTicketAuthenticationToken.stateful("ST-123");
|
||||||
|
token.setDetails("details");
|
||||||
|
Authentication result = cap.authenticate(token);
|
||||||
|
SecurityAssertions.assertThat(result).hasAuthority("FACTOR_CAS");
|
||||||
|
}
|
||||||
|
|
||||||
private class MockAuthoritiesPopulator implements AuthenticationUserDetailsService {
|
private class MockAuthoritiesPopulator implements AuthenticationUserDetailsService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.springframework.http.MediaType;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
import org.springframework.mock.web.MockHttpSession;
|
import org.springframework.mock.web.MockHttpSession;
|
||||||
|
import org.springframework.security.authentication.SecurityAssertions;
|
||||||
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
|
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
|
||||||
import org.springframework.security.config.test.SpringTestContext;
|
import org.springframework.security.config.test.SpringTestContext;
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||||
|
@ -322,8 +323,10 @@ public class OAuth2LoginBeanDefinitionParserTests {
|
||||||
verify(this.authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), authenticationCaptor.capture());
|
verify(this.authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), authenticationCaptor.capture());
|
||||||
Authentication authentication = authenticationCaptor.getValue();
|
Authentication authentication = authenticationCaptor.getValue();
|
||||||
assertThat(authentication.getPrincipal()).isInstanceOf(OAuth2User.class);
|
assertThat(authentication.getPrincipal()).isInstanceOf(OAuth2User.class);
|
||||||
assertThat(authentication.getAuthorities()).hasSize(1);
|
SecurityAssertions.assertThat(authentication)
|
||||||
assertThat(authentication.getAuthorities()).first()
|
.roles()
|
||||||
|
.hasSize(1)
|
||||||
|
.first()
|
||||||
.isInstanceOf(SimpleGrantedAuthority.class)
|
.isInstanceOf(SimpleGrantedAuthority.class)
|
||||||
.hasToString("ROLE_OAUTH2_USER");
|
.hasToString("ROLE_OAUTH2_USER");
|
||||||
// re-setup for OIDC test
|
// re-setup for OIDC test
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.security.authentication.dao;
|
package org.springframework.security.authentication.dao;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
@ -204,7 +204,7 @@ public abstract class AbstractUserDetailsAuthenticationProvider
|
||||||
// so subsequent attempts are successful even with encoded passwords.
|
// so subsequent attempts are successful even with encoded passwords.
|
||||||
// Also ensure we return the original getDetails(), so that future
|
// Also ensure we return the original getDetails(), so that future
|
||||||
// authentication events after cache expiry contain the details
|
// authentication events after cache expiry contain the details
|
||||||
Collection<GrantedAuthority> authorities = new ArrayList<>(
|
Collection<GrantedAuthority> authorities = new LinkedHashSet<>(
|
||||||
this.authoritiesMapper.mapAuthorities(user.getAuthorities()));
|
this.authoritiesMapper.mapAuthorities(user.getAuthorities()));
|
||||||
authorities.add(new SimpleGrantedAuthority(AUTHORITY));
|
authorities.add(new SimpleGrantedAuthority(AUTHORITY));
|
||||||
UsernamePasswordAuthenticationToken result = UsernamePasswordAuthenticationToken.authenticated(principal,
|
UsernamePasswordAuthenticationToken result = UsernamePasswordAuthenticationToken.authenticated(principal,
|
||||||
|
|
|
@ -45,6 +45,7 @@ import org.springframework.security.authentication.jaas.event.JaasAuthentication
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.security.core.session.SessionDestroyedEvent;
|
import org.springframework.security.core.session.SessionDestroyedEvent;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
@ -120,6 +121,8 @@ import org.springframework.util.ObjectUtils;
|
||||||
public abstract class AbstractJaasAuthenticationProvider implements AuthenticationProvider,
|
public abstract class AbstractJaasAuthenticationProvider implements AuthenticationProvider,
|
||||||
ApplicationEventPublisherAware, InitializingBean, ApplicationListener<SessionDestroyedEvent> {
|
ApplicationEventPublisherAware, InitializingBean, ApplicationListener<SessionDestroyedEvent> {
|
||||||
|
|
||||||
|
private static final String AUTHORITY = "FACTOR_PASSWORD";
|
||||||
|
|
||||||
private ApplicationEventPublisher applicationEventPublisher = (event) -> {
|
private ApplicationEventPublisher applicationEventPublisher = (event) -> {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -210,6 +213,7 @@ public abstract class AbstractJaasAuthenticationProvider implements Authenticati
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
authorities.add(new SimpleGrantedAuthority(AUTHORITY));
|
||||||
return authorities;
|
return authorities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,10 @@ public final class SecurityAssertions {
|
||||||
return authorities().has(new Condition<>(test, "contains %s", Arrays.toString(authorities)));
|
return authorities().has(new Condition<>(test, "contains %s", Arrays.toString(authorities)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CollectionAssert<GrantedAuthority> roles() {
|
||||||
|
return authorities().filteredOn((authority) -> authority.getAuthority().startsWith("ROLE_"));
|
||||||
|
}
|
||||||
|
|
||||||
public CollectionAssert<GrantedAuthority> authorities() {
|
public CollectionAssert<GrantedAuthority> authorities() {
|
||||||
return new CollectionAssert<>(this.authentication.getAuthorities());
|
return new CollectionAssert<>(this.authentication.getAuthorities());
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||||
import org.springframework.core.io.FileSystemResource;
|
import org.springframework.core.io.FileSystemResource;
|
||||||
import org.springframework.security.authentication.LockedException;
|
import org.springframework.security.authentication.LockedException;
|
||||||
|
import org.springframework.security.authentication.SecurityAssertions;
|
||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
@ -224,7 +225,9 @@ public class JaasAuthenticationProviderTests {
|
||||||
"password");
|
"password");
|
||||||
assertThat(this.jaasProvider.supports(UsernamePasswordAuthenticationToken.class)).isTrue();
|
assertThat(this.jaasProvider.supports(UsernamePasswordAuthenticationToken.class)).isTrue();
|
||||||
Authentication auth = this.jaasProvider.authenticate(token);
|
Authentication auth = this.jaasProvider.authenticate(token);
|
||||||
assertThat(auth.getAuthorities()).withFailMessage("Only ROLE_TEST1 and ROLE_TEST2 should have been returned")
|
SecurityAssertions.assertThat(auth)
|
||||||
|
.roles()
|
||||||
|
.withFailMessage("Only ROLE_TEST1 and ROLE_TEST2 should have been returned")
|
||||||
.hasSize(2);
|
.hasSize(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,6 +237,13 @@ public class JaasAuthenticationProviderTests {
|
||||||
.authenticate(new TestingAuthenticationToken("foo", "bar", AuthorityUtils.NO_AUTHORITIES))).isNull();
|
.authenticate(new TestingAuthenticationToken("foo", "bar", AuthorityUtils.NO_AUTHORITIES))).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void authenticateWhenSuccessThenIssuesFactor() {
|
||||||
|
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password");
|
||||||
|
Authentication result = this.jaasProvider.authenticate(token);
|
||||||
|
SecurityAssertions.assertThat(result).hasAuthority("FACTOR_PASSWORD");
|
||||||
|
}
|
||||||
|
|
||||||
private static class MockLoginContext extends LoginContext {
|
private static class MockLoginContext extends LoginContext {
|
||||||
|
|
||||||
boolean loggedOut = false;
|
boolean loggedOut = false;
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.security.ldap.authentication;
|
package org.springframework.security.ldap.authentication;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
@ -104,7 +104,7 @@ public abstract class AbstractLdapAuthenticationProvider implements Authenticati
|
||||||
UserDetails user) {
|
UserDetails user) {
|
||||||
Object password = this.useAuthenticationRequestCredentials ? authentication.getCredentials()
|
Object password = this.useAuthenticationRequestCredentials ? authentication.getCredentials()
|
||||||
: user.getPassword();
|
: user.getPassword();
|
||||||
Collection<GrantedAuthority> authorities = new ArrayList<>(
|
Collection<GrantedAuthority> authorities = new LinkedHashSet<>(
|
||||||
this.authoritiesMapper.mapAuthorities(user.getAuthorities()));
|
this.authoritiesMapper.mapAuthorities(user.getAuthorities()));
|
||||||
authorities.add(new SimpleGrantedAuthority(AUTHORITY));
|
authorities.add(new SimpleGrantedAuthority(AUTHORITY));
|
||||||
UsernamePasswordAuthenticationToken result = UsernamePasswordAuthenticationToken.authenticated(user, password,
|
UsernamePasswordAuthenticationToken result = UsernamePasswordAuthenticationToken.authenticated(user, password,
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.springframework.security.oauth2.client.authentication;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AuthenticationProvider;
|
import org.springframework.security.authentication.AuthenticationProvider;
|
||||||
|
@ -123,8 +124,9 @@ public class OAuth2LoginAuthenticationProvider implements AuthenticationProvider
|
||||||
OAuth2User oauth2User = this.userService.loadUser(new OAuth2UserRequest(
|
OAuth2User oauth2User = this.userService.loadUser(new OAuth2UserRequest(
|
||||||
loginAuthenticationToken.getClientRegistration(), accessToken, additionalParameters));
|
loginAuthenticationToken.getClientRegistration(), accessToken, additionalParameters));
|
||||||
Collection<GrantedAuthority> authorities = new HashSet<>(oauth2User.getAuthorities());
|
Collection<GrantedAuthority> authorities = new HashSet<>(oauth2User.getAuthorities());
|
||||||
authorities.add(new SimpleGrantedAuthority(AUTHORITY));
|
Collection<GrantedAuthority> mappedAuthorities = new LinkedHashSet<>(
|
||||||
Collection<? extends GrantedAuthority> mappedAuthorities = this.authoritiesMapper.mapAuthorities(authorities);
|
this.authoritiesMapper.mapAuthorities(authorities));
|
||||||
|
mappedAuthorities.add(new SimpleGrantedAuthority(AUTHORITY));
|
||||||
OAuth2LoginAuthenticationToken authenticationResult = new OAuth2LoginAuthenticationToken(
|
OAuth2LoginAuthenticationToken authenticationResult = new OAuth2LoginAuthenticationToken(
|
||||||
loginAuthenticationToken.getClientRegistration(), loginAuthenticationToken.getAuthorizationExchange(),
|
loginAuthenticationToken.getClientRegistration(), loginAuthenticationToken.getAuthorizationExchange(),
|
||||||
oauth2User, mappedAuthorities, accessToken, authorizationCodeAuthenticationToken.getRefreshToken());
|
oauth2User, mappedAuthorities, accessToken, authorizationCodeAuthenticationToken.getRefreshToken());
|
||||||
|
|
|
@ -59,6 +59,7 @@ import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyCollection;
|
import static org.mockito.ArgumentMatchers.anyCollection;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link OAuth2LoginAuthenticationProvider}.
|
* Tests for {@link OAuth2LoginAuthenticationProvider}.
|
||||||
|
@ -190,7 +191,8 @@ public class OAuth2LoginAuthenticationProviderTests {
|
||||||
this.authenticationProvider.setAuthoritiesMapper(authoritiesMapper);
|
this.authenticationProvider.setAuthoritiesMapper(authoritiesMapper);
|
||||||
OAuth2LoginAuthenticationToken authentication = (OAuth2LoginAuthenticationToken) this.authenticationProvider
|
OAuth2LoginAuthenticationToken authentication = (OAuth2LoginAuthenticationToken) this.authenticationProvider
|
||||||
.authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange));
|
.authenticate(new OAuth2LoginAuthenticationToken(this.clientRegistration, this.authorizationExchange));
|
||||||
assertThat(authentication.getAuthorities()).isEqualTo(mappedAuthorities);
|
verify(authoritiesMapper).mapAuthorities(any());
|
||||||
|
SecurityAssertions.assertThat(authentication).authorities().containsAll(mappedAuthorities);
|
||||||
}
|
}
|
||||||
|
|
||||||
// gh-5368
|
// gh-5368
|
||||||
|
|
Loading…
Reference in New Issue