Revert "Remove CAS module"

This reverts commit caf4c471
This commit is contained in:
hdeadman
2022-12-10 11:39:24 -05:00
committed by Marcus Da Coregio
parent baf2c98c9f
commit b4d3ac6665
44 changed files with 4200 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2002-2016 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.cas.authentication;
import java.util.ArrayList;
import java.util.List;
import org.jasig.cas.client.validation.Assertion;
import org.jasig.cas.client.validation.AssertionImpl;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
/**
* @author Scott Battaglia
* @since 2.0
*
*/
public abstract class AbstractStatelessTicketCacheTests {
protected CasAuthenticationToken getToken() {
List<String> proxyList = new ArrayList<>();
proxyList.add("https://localhost/newPortal/login/cas");
User user = new User("rod", "password", true, true, true, true,
AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"));
final Assertion assertion = new AssertionImpl("rod");
return new CasAuthenticationToken("key", user, "ST-0-ER94xMJmn6pha35CQRoZ",
AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"), user, assertion);
}
}

View File

@@ -0,0 +1,382 @@
/*
* 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.cas.authentication;
import java.util.HashMap;
import java.util.Map;
import org.jasig.cas.client.validation.Assertion;
import org.jasig.cas.client.validation.AssertionImpl;
import org.jasig.cas.client.validation.TicketValidator;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.cas.web.authentication.ServiceAuthenticationDetails;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
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.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.assertj.core.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/**
* Tests {@link CasAuthenticationProvider}.
*
* @author Ben Alex
* @author Scott Battaglia
*/
@SuppressWarnings("unchecked")
public class CasAuthenticationProviderTests {
private UserDetails makeUserDetails() {
return new User("user", "password", true, true, true, true,
AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO"));
}
private UserDetails makeUserDetailsFromAuthoritiesPopulator() {
return new User("user", "password", true, true, true, true,
AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B"));
}
private ServiceProperties makeServiceProperties() {
final ServiceProperties serviceProperties = new ServiceProperties();
serviceProperties.setSendRenew(false);
serviceProperties.setService("http://test.com");
return serviceProperties;
}
@Test
public void statefulAuthenticationIsSuccessful() 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();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER, "ST-123");
token.setDetails("details");
Authentication result = cap.authenticate(token);
// Confirm ST-123 was NOT added to the cache
assertThat(cache.getByTicketId("ST-456") == null).isTrue();
if (!(result instanceof CasAuthenticationToken)) {
fail("Should have returned a CasAuthenticationToken");
}
CasAuthenticationToken casResult = (CasAuthenticationToken) result;
assertThat(casResult.getPrincipal()).isEqualTo(makeUserDetailsFromAuthoritiesPopulator());
assertThat(casResult.getCredentials()).isEqualTo("ST-123");
assertThat(casResult.getAuthorities()).contains(new SimpleGrantedAuthority("ROLE_A"));
assertThat(casResult.getAuthorities()).contains(new SimpleGrantedAuthority("ROLE_B"));
assertThat(casResult.getKeyHash()).isEqualTo(cap.getKey().hashCode());
assertThat(casResult.getDetails()).isEqualTo("details");
// Now confirm the CasAuthenticationToken is automatically re-accepted.
// To ensure TicketValidator not called again, set it to deliver an exception...
cap.setTicketValidator(new MockTicketValidator(false));
Authentication laterResult = cap.authenticate(result);
assertThat(laterResult).isEqualTo(result);
}
@Test
public void statelessAuthenticationIsSuccessful() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
cap.setKey("qwerty");
StatelessTicketCache cache = new MockStatelessTicketCache();
cap.setStatelessTicketCache(cache);
cap.setTicketValidator(new MockTicketValidator(true));
cap.setServiceProperties(makeServiceProperties());
cap.afterPropertiesSet();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, "ST-456");
token.setDetails("details");
Authentication result = cap.authenticate(token);
// Confirm ST-456 was added to the cache
assertThat(cache.getByTicketId("ST-456") != null).isTrue();
if (!(result instanceof CasAuthenticationToken)) {
fail("Should have returned a CasAuthenticationToken");
}
assertThat(result.getPrincipal()).isEqualTo(makeUserDetailsFromAuthoritiesPopulator());
assertThat(result.getCredentials()).isEqualTo("ST-456");
assertThat(result.getDetails()).isEqualTo("details");
// Now try to authenticate again. To ensure TicketValidator not
// called again, set it to deliver an exception...
cap.setTicketValidator(new MockTicketValidator(false));
// Previously created UsernamePasswordAuthenticationToken is OK
Authentication newResult = cap.authenticate(token);
assertThat(newResult.getPrincipal()).isEqualTo(makeUserDetailsFromAuthoritiesPopulator());
assertThat(newResult.getCredentials()).isEqualTo("ST-456");
}
@Test
public void authenticateAllNullService() throws Exception {
String serviceUrl = "https://service/context";
ServiceAuthenticationDetails details = mock(ServiceAuthenticationDetails.class);
given(details.getServiceUrl()).willReturn(serviceUrl);
TicketValidator validator = mock(TicketValidator.class);
given(validator.validate(any(String.class), any(String.class))).willReturn(new AssertionImpl("rod"));
ServiceProperties serviceProperties = makeServiceProperties();
serviceProperties.setAuthenticateAllArtifacts(true);
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
cap.setKey("qwerty");
cap.setTicketValidator(validator);
cap.setServiceProperties(serviceProperties);
cap.afterPropertiesSet();
String ticket = "ST-456";
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, ticket);
Authentication result = cap.authenticate(token);
}
@Test
public void authenticateAllAuthenticationIsSuccessful() throws Exception {
String serviceUrl = "https://service/context";
ServiceAuthenticationDetails details = mock(ServiceAuthenticationDetails.class);
given(details.getServiceUrl()).willReturn(serviceUrl);
TicketValidator validator = mock(TicketValidator.class);
given(validator.validate(any(String.class), any(String.class))).willReturn(new AssertionImpl("rod"));
ServiceProperties serviceProperties = makeServiceProperties();
serviceProperties.setAuthenticateAllArtifacts(true);
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
cap.setKey("qwerty");
cap.setTicketValidator(validator);
cap.setServiceProperties(serviceProperties);
cap.afterPropertiesSet();
String ticket = "ST-456";
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER, ticket);
Authentication result = cap.authenticate(token);
verify(validator).validate(ticket, serviceProperties.getService());
serviceProperties.setAuthenticateAllArtifacts(true);
result = cap.authenticate(token);
verify(validator, times(2)).validate(ticket, serviceProperties.getService());
token.setDetails(details);
result = cap.authenticate(token);
verify(validator).validate(ticket, serviceUrl);
serviceProperties.setAuthenticateAllArtifacts(false);
serviceProperties.setService(null);
cap.setServiceProperties(serviceProperties);
cap.afterPropertiesSet();
result = cap.authenticate(token);
verify(validator, times(2)).validate(ticket, serviceUrl);
token.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest()));
assertThatIllegalStateException().isThrownBy(() -> cap.authenticate(token));
cap.setServiceProperties(null);
cap.afterPropertiesSet();
assertThatIllegalStateException().isThrownBy(() -> cap.authenticate(token));
}
@Test
public void missingTicketIdIsDetected() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
cap.setKey("qwerty");
StatelessTicketCache cache = new MockStatelessTicketCache();
cap.setStatelessTicketCache(cache);
cap.setTicketValidator(new MockTicketValidator(true));
cap.setServiceProperties(makeServiceProperties());
cap.afterPropertiesSet();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER, "");
assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> cap.authenticate(token));
}
@Test
public void invalidKeyIsDetected() throws Exception {
final Assertion assertion = new AssertionImpl("test");
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
cap.setKey("qwerty");
StatelessTicketCache cache = new MockStatelessTicketCache();
cap.setStatelessTicketCache(cache);
cap.setTicketValidator(new MockTicketValidator(true));
cap.setServiceProperties(makeServiceProperties());
cap.afterPropertiesSet();
CasAuthenticationToken token = new CasAuthenticationToken("WRONG_KEY", makeUserDetails(), "credentials",
AuthorityUtils.createAuthorityList("XX"), makeUserDetails(), assertion);
assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> cap.authenticate(token));
}
@Test
public void detectsMissingAuthoritiesPopulator() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setKey("qwerty");
cap.setStatelessTicketCache(new MockStatelessTicketCache());
cap.setTicketValidator(new MockTicketValidator(true));
cap.setServiceProperties(makeServiceProperties());
assertThatIllegalArgumentException().isThrownBy(() -> cap.afterPropertiesSet());
}
@Test
public void detectsMissingKey() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
cap.setStatelessTicketCache(new MockStatelessTicketCache());
cap.setTicketValidator(new MockTicketValidator(true));
cap.setServiceProperties(makeServiceProperties());
assertThatIllegalArgumentException().isThrownBy(() -> cap.afterPropertiesSet());
}
@Test
public void detectsMissingStatelessTicketCache() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
// set this explicitly to null to test failure
cap.setStatelessTicketCache(null);
cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
cap.setKey("qwerty");
cap.setTicketValidator(new MockTicketValidator(true));
cap.setServiceProperties(makeServiceProperties());
assertThatIllegalArgumentException().isThrownBy(() -> cap.afterPropertiesSet());
}
@Test
public void detectsMissingTicketValidator() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
cap.setKey("qwerty");
cap.setStatelessTicketCache(new MockStatelessTicketCache());
cap.setServiceProperties(makeServiceProperties());
assertThatIllegalArgumentException().isThrownBy(() -> cap.afterPropertiesSet());
}
@Test
public void gettersAndSettersMatch() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
cap.setKey("qwerty");
cap.setStatelessTicketCache(new MockStatelessTicketCache());
cap.setTicketValidator(new MockTicketValidator(true));
cap.setServiceProperties(makeServiceProperties());
cap.afterPropertiesSet();
// TODO disabled because why do we need to expose this?
// assertThat(cap.getUserDetailsService() != null).isTrue();
assertThat(cap.getKey()).isEqualTo("qwerty");
assertThat(cap.getStatelessTicketCache() != null).isTrue();
assertThat(cap.getTicketValidator() != null).isTrue();
}
@Test
public void ignoresClassesItDoesNotSupport() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
cap.setKey("qwerty");
cap.setStatelessTicketCache(new MockStatelessTicketCache());
cap.setTicketValidator(new MockTicketValidator(true));
cap.setServiceProperties(makeServiceProperties());
cap.afterPropertiesSet();
TestingAuthenticationToken token = new TestingAuthenticationToken("user", "password", "ROLE_A");
assertThat(cap.supports(TestingAuthenticationToken.class)).isFalse();
// Try it anyway
assertThat(cap.authenticate(token)).isNull();
}
@Test
public void ignoresUsernamePasswordAuthenticationTokensWithoutCasIdentifiersAsPrincipal() throws Exception {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator());
cap.setKey("qwerty");
cap.setStatelessTicketCache(new MockStatelessTicketCache());
cap.setTicketValidator(new MockTicketValidator(true));
cap.setServiceProperties(makeServiceProperties());
cap.afterPropertiesSet();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("some_normal_user",
"password", AuthorityUtils.createAuthorityList("ROLE_A"));
assertThat(cap.authenticate(token)).isNull();
}
@Test
public void supportsRequiredTokens() {
CasAuthenticationProvider cap = new CasAuthenticationProvider();
assertThat(cap.supports(UsernamePasswordAuthenticationToken.class)).isTrue();
assertThat(cap.supports(CasAuthenticationToken.class)).isTrue();
}
private class MockAuthoritiesPopulator implements AuthenticationUserDetailsService {
@Override
public UserDetails loadUserDetails(final Authentication token) throws UsernameNotFoundException {
return makeUserDetailsFromAuthoritiesPopulator();
}
}
private class MockStatelessTicketCache implements StatelessTicketCache {
private Map<String, CasAuthenticationToken> cache = new HashMap<>();
@Override
public CasAuthenticationToken getByTicketId(String serviceTicket) {
return this.cache.get(serviceTicket);
}
@Override
public void putTicketInCache(CasAuthenticationToken token) {
this.cache.put(token.getCredentials().toString(), token);
}
@Override
public void removeTicketFromCache(CasAuthenticationToken token) {
throw new UnsupportedOperationException("mock method not implemented");
}
@Override
public void removeTicketFromCache(String serviceTicket) {
throw new UnsupportedOperationException("mock method not implemented");
}
}
private class MockTicketValidator implements TicketValidator {
private boolean returnTicket;
MockTicketValidator(boolean returnTicket) {
this.returnTicket = returnTicket;
}
@Override
public Assertion validate(final String ticket, final String service) {
if (this.returnTicket) {
return new AssertionImpl("rod");
}
throw new BadCredentialsException("As requested from mock");
}
}
}

View File

@@ -0,0 +1,169 @@
/*
* 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.cas.authentication;
import java.util.Collections;
import java.util.List;
import org.jasig.cas.client.validation.Assertion;
import org.jasig.cas.client.validation.AssertionImpl;
import org.junit.jupiter.api.Test;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Tests {@link CasAuthenticationToken}.
*
* @author Ben Alex
*/
public class CasAuthenticationTokenTests {
private final List<GrantedAuthority> ROLES = AuthorityUtils.createAuthorityList("ROLE_ONE", "ROLE_TWO");
private UserDetails makeUserDetails() {
return makeUserDetails("user");
}
private UserDetails makeUserDetails(final String name) {
return new User(name, "password", true, true, true, true, this.ROLES);
}
@Test
public void testConstructorRejectsNulls() {
Assertion assertion = new AssertionImpl("test");
assertThatIllegalArgumentException().isThrownBy(() -> new CasAuthenticationToken(null, makeUserDetails(),
"Password", this.ROLES, makeUserDetails(), assertion));
assertThatIllegalArgumentException().isThrownBy(
() -> new CasAuthenticationToken("key", null, "Password", this.ROLES, makeUserDetails(), assertion));
assertThatIllegalArgumentException().isThrownBy(() -> new CasAuthenticationToken("key", makeUserDetails(), null,
this.ROLES, makeUserDetails(), assertion));
assertThatIllegalArgumentException().isThrownBy(() -> new CasAuthenticationToken("key", makeUserDetails(),
"Password", this.ROLES, makeUserDetails(), null));
assertThatIllegalArgumentException().isThrownBy(
() -> new CasAuthenticationToken("key", makeUserDetails(), "Password", this.ROLES, null, assertion));
assertThatIllegalArgumentException().isThrownBy(() -> new CasAuthenticationToken("key", makeUserDetails(),
"Password", AuthorityUtils.createAuthorityList("ROLE_1", null), makeUserDetails(), assertion));
}
@Test
public void constructorWhenEmptyKeyThenThrowsException() {
assertThatIllegalArgumentException().isThrownBy(
() -> new CasAuthenticationToken("", "user", "password", Collections.<GrantedAuthority>emptyList(),
new User("user", "password", Collections.<GrantedAuthority>emptyList()), null));
}
@Test
public void testEqualsWhenEqual() {
final Assertion assertion = new AssertionImpl("test");
CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", this.ROLES,
makeUserDetails(), assertion);
CasAuthenticationToken token2 = new CasAuthenticationToken("key", makeUserDetails(), "Password", this.ROLES,
makeUserDetails(), assertion);
assertThat(token2).isEqualTo(token1);
}
@Test
public void testGetters() {
// Build the proxy list returned in the ticket from CAS
final Assertion assertion = new AssertionImpl("test");
CasAuthenticationToken token = new CasAuthenticationToken("key", makeUserDetails(), "Password", this.ROLES,
makeUserDetails(), assertion);
assertThat(token.getKeyHash()).isEqualTo("key".hashCode());
assertThat(token.getPrincipal()).isEqualTo(makeUserDetails());
assertThat(token.getCredentials()).isEqualTo("Password");
assertThat(token.getAuthorities()).contains(new SimpleGrantedAuthority("ROLE_ONE"));
assertThat(token.getAuthorities()).contains(new SimpleGrantedAuthority("ROLE_TWO"));
assertThat(token.getAssertion()).isEqualTo(assertion);
assertThat(token.getUserDetails().getUsername()).isEqualTo(makeUserDetails().getUsername());
}
@Test
public void testNoArgConstructorDoesntExist() {
assertThatExceptionOfType(NoSuchMethodException.class)
.isThrownBy(() -> CasAuthenticationToken.class.getDeclaredConstructor((Class[]) null));
}
@Test
public void testNotEqualsDueToAbstractParentEqualsCheck() {
final Assertion assertion = new AssertionImpl("test");
CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", this.ROLES,
makeUserDetails(), assertion);
CasAuthenticationToken token2 = new CasAuthenticationToken("key", makeUserDetails("OTHER_NAME"), "Password",
this.ROLES, makeUserDetails(), assertion);
assertThat(!token1.equals(token2)).isTrue();
}
@Test
public void testNotEqualsDueToDifferentAuthenticationClass() {
final Assertion assertion = new AssertionImpl("test");
CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", this.ROLES,
makeUserDetails(), assertion);
UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken("Test", "Password",
this.ROLES);
assertThat(!token1.equals(token2)).isTrue();
}
@Test
public void testNotEqualsDueToKey() {
final Assertion assertion = new AssertionImpl("test");
CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", this.ROLES,
makeUserDetails(), assertion);
CasAuthenticationToken token2 = new CasAuthenticationToken("DIFFERENT_KEY", makeUserDetails(), "Password",
this.ROLES, makeUserDetails(), assertion);
assertThat(!token1.equals(token2)).isTrue();
}
@Test
public void testNotEqualsDueToAssertion() {
final Assertion assertion = new AssertionImpl("test");
final Assertion assertion2 = new AssertionImpl("test");
CasAuthenticationToken token1 = new CasAuthenticationToken("key", makeUserDetails(), "Password", this.ROLES,
makeUserDetails(), assertion);
CasAuthenticationToken token2 = new CasAuthenticationToken("key", makeUserDetails(), "Password", this.ROLES,
makeUserDetails(), assertion2);
assertThat(!token1.equals(token2)).isTrue();
}
@Test
public void testSetAuthenticated() {
final Assertion assertion = new AssertionImpl("test");
CasAuthenticationToken token = new CasAuthenticationToken("key", makeUserDetails(), "Password", this.ROLES,
makeUserDetails(), assertion);
assertThat(token.isAuthenticated()).isTrue();
token.setAuthenticated(false);
assertThat(!token.isAuthenticated()).isTrue();
}
@Test
public void testToString() {
final Assertion assertion = new AssertionImpl("test");
CasAuthenticationToken token = new CasAuthenticationToken("key", makeUserDetails(), "Password", this.ROLES,
makeUserDetails(), assertion);
String result = token.toString();
assertThat(result.lastIndexOf("Credentials (Service/Proxy Ticket):") != -1).isTrue();
}
}

View File

@@ -0,0 +1,46 @@
/*
* 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.cas.authentication;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test cases for the @link {@link NullStatelessTicketCache}
*
* @author Scott Battaglia
*
*/
public class NullStatelessTicketCacheTests extends AbstractStatelessTicketCacheTests {
private StatelessTicketCache cache = new NullStatelessTicketCache();
@Test
public void testGetter() {
assertThat(this.cache.getByTicketId(null)).isNull();
assertThat(this.cache.getByTicketId("test")).isNull();
}
@Test
public void testInsertAndGet() {
final CasAuthenticationToken token = getToken();
this.cache.putTicketInCache(token);
assertThat(this.cache.getByTicketId((String) token.getCredentials())).isNull();
}
}

View File

@@ -0,0 +1,65 @@
/*
* 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.cas.authentication;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Tests
* {@link org.springframework.security.cas.authentication.SpringCacheBasedTicketCache}.
*
* @author Marten Deinum
* @since 3.2
*/
public class SpringCacheBasedTicketCacheTests extends AbstractStatelessTicketCacheTests {
private static CacheManager cacheManager;
@BeforeAll
public static void initCacheManaer() {
cacheManager = new ConcurrentMapCacheManager();
cacheManager.getCache("castickets");
}
@Test
public void testCacheOperation() throws Exception {
SpringCacheBasedTicketCache cache = new SpringCacheBasedTicketCache(cacheManager.getCache("castickets"));
final CasAuthenticationToken token = getToken();
// Check it gets stored in the cache
cache.putTicketInCache(token);
assertThat(cache.getByTicketId("ST-0-ER94xMJmn6pha35CQRoZ")).isEqualTo(token);
// Check it gets removed from the cache
cache.removeTicketFromCache(getToken());
assertThat(cache.getByTicketId("ST-0-ER94xMJmn6pha35CQRoZ")).isNull();
// Check it doesn't return values for null or unknown service tickets
assertThat(cache.getByTicketId(null)).isNull();
assertThat(cache.getByTicketId("UNKNOWN_SERVICE_TICKET")).isNull();
}
@Test
public void testStartupDetectsMissingCache() throws Exception {
assertThatIllegalArgumentException().isThrownBy(() -> new SpringCacheBasedTicketCache(null));
}
}

View File

@@ -0,0 +1,153 @@
/*
* Copyright 2015-2016 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.cas.jackson2;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jasig.cas.client.authentication.AttributePrincipalImpl;
import org.jasig.cas.client.validation.Assertion;
import org.jasig.cas.client.validation.AssertionImpl;
import org.json.JSONException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.security.cas.authentication.CasAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.jackson2.SecurityJackson2Modules;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Jitendra Singh
* @since 4.2
*/
public class CasAuthenticationTokenMixinTests {
private static final String KEY = "casKey";
private static final String PASSWORD = "\"1234\"";
private static final Date START_DATE = new Date();
private static final Date END_DATE = new Date();
public static final String AUTHORITY_JSON = "{\"@class\": \"org.springframework.security.core.authority.SimpleGrantedAuthority\", \"authority\": \"ROLE_USER\"}";
public static final String AUTHORITIES_SET_JSON = "[\"java.util.Collections$UnmodifiableSet\", [" + AUTHORITY_JSON
+ "]]";
public static final String AUTHORITIES_ARRAYLIST_JSON = "[\"java.util.Collections$UnmodifiableRandomAccessList\", ["
+ AUTHORITY_JSON + "]]";
// @formatter:off
public static final String USER_JSON = "{"
+ "\"@class\": \"org.springframework.security.core.userdetails.User\", "
+ "\"username\": \"admin\","
+ " \"password\": " + PASSWORD + ", "
+ "\"accountNonExpired\": true, "
+ "\"accountNonLocked\": true, "
+ "\"credentialsNonExpired\": true, "
+ "\"enabled\": true, "
+ "\"authorities\": " + AUTHORITIES_SET_JSON
+ "}";
// @formatter:on
private static final String CAS_TOKEN_JSON = "{"
+ "\"@class\": \"org.springframework.security.cas.authentication.CasAuthenticationToken\", "
+ "\"keyHash\": " + KEY.hashCode() + "," + "\"principal\": " + USER_JSON + ", " + "\"credentials\": "
+ PASSWORD + ", " + "\"authorities\": " + AUTHORITIES_ARRAYLIST_JSON + "," + "\"userDetails\": " + USER_JSON
+ "," + "\"authenticated\": true, " + "\"details\": null," + "\"assertion\": {"
+ "\"@class\": \"org.jasig.cas.client.validation.AssertionImpl\", " + "\"principal\": {"
+ "\"@class\": \"org.jasig.cas.client.authentication.AttributePrincipalImpl\", "
+ "\"name\": \"assertName\", " + "\"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}, "
+ "\"proxyGrantingTicket\": null, " + "\"proxyRetriever\": null" + "}, "
+ "\"validFromDate\": [\"java.util.Date\", " + START_DATE.getTime() + "], "
+ "\"validUntilDate\": [\"java.util.Date\", " + END_DATE.getTime() + "],"
+ "\"authenticationDate\": [\"java.util.Date\", " + START_DATE.getTime() + "], "
+ "\"attributes\": {\"@class\": \"java.util.Collections$EmptyMap\"}" + "}" + "}";
private static final String CAS_TOKEN_CLEARED_JSON = CAS_TOKEN_JSON.replaceFirst(PASSWORD, "null");
protected ObjectMapper mapper;
@BeforeEach
public void setup() {
this.mapper = new ObjectMapper();
ClassLoader loader = getClass().getClassLoader();
this.mapper.registerModules(SecurityJackson2Modules.getModules(loader));
}
@Test
public void serializeCasAuthenticationTest() throws JsonProcessingException, JSONException {
CasAuthenticationToken token = createCasAuthenticationToken();
String actualJson = this.mapper.writeValueAsString(token);
JSONAssert.assertEquals(CAS_TOKEN_JSON, actualJson, true);
}
@Test
public void serializeCasAuthenticationTestAfterEraseCredentialInvoked()
throws JsonProcessingException, JSONException {
CasAuthenticationToken token = createCasAuthenticationToken();
token.eraseCredentials();
String actualJson = this.mapper.writeValueAsString(token);
JSONAssert.assertEquals(CAS_TOKEN_CLEARED_JSON, actualJson, true);
}
@Test
public void deserializeCasAuthenticationTestAfterEraseCredentialInvoked() throws Exception {
CasAuthenticationToken token = this.mapper.readValue(CAS_TOKEN_CLEARED_JSON, CasAuthenticationToken.class);
assertThat(((UserDetails) token.getPrincipal()).getPassword()).isNull();
}
@Test
public void deserializeCasAuthenticationTest() throws IOException {
CasAuthenticationToken token = this.mapper.readValue(CAS_TOKEN_JSON, CasAuthenticationToken.class);
assertThat(token).isNotNull();
assertThat(token.getPrincipal()).isNotNull().isInstanceOf(User.class);
assertThat(((User) token.getPrincipal()).getUsername()).isEqualTo("admin");
assertThat(((User) token.getPrincipal()).getPassword()).isEqualTo("1234");
assertThat(token.getUserDetails()).isNotNull().isInstanceOf(User.class);
assertThat(token.getAssertion()).isNotNull().isInstanceOf(AssertionImpl.class);
assertThat(token.getKeyHash()).isEqualTo(KEY.hashCode());
assertThat(token.getUserDetails().getAuthorities()).extracting(GrantedAuthority::getAuthority)
.containsOnly("ROLE_USER");
assertThat(token.getAssertion().getAuthenticationDate()).isEqualTo(START_DATE);
assertThat(token.getAssertion().getValidFromDate()).isEqualTo(START_DATE);
assertThat(token.getAssertion().getValidUntilDate()).isEqualTo(END_DATE);
assertThat(token.getAssertion().getPrincipal().getName()).isEqualTo("assertName");
assertThat(token.getAssertion().getAttributes()).hasSize(0);
}
private CasAuthenticationToken createCasAuthenticationToken() {
User principal = new User("admin", "1234", Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));
Collection<? extends GrantedAuthority> authorities = Collections
.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
Assertion assertion = new AssertionImpl(new AttributePrincipalImpl("assertName"), START_DATE, END_DATE,
START_DATE, Collections.<String, Object>emptyMap());
return new CasAuthenticationToken(KEY, principal, principal.getPassword(), authorities,
new User("admin", "1234", authorities), assertion);
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2002-2017 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.cas.userdetails;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.validation.Assertion;
import org.junit.jupiter.api.Test;
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* @author Luke Taylor
*/
public class GrantedAuthorityFromAssertionAttributesUserDetailsServiceTests {
@Test
public void correctlyExtractsNamedAttributesFromAssertionAndConvertsThemToAuthorities() {
GrantedAuthorityFromAssertionAttributesUserDetailsService uds = new GrantedAuthorityFromAssertionAttributesUserDetailsService(
new String[] { "a", "b", "c", "d" });
uds.setConvertToUpperCase(false);
Assertion assertion = mock(Assertion.class);
AttributePrincipal principal = mock(AttributePrincipal.class);
Map<String, Object> attributes = new HashMap<>();
attributes.put("a", Arrays.asList("role_a1", "role_a2"));
attributes.put("b", "role_b");
attributes.put("c", "role_c");
attributes.put("d", null);
attributes.put("someother", "unused");
given(assertion.getPrincipal()).willReturn(principal);
given(principal.getAttributes()).willReturn(attributes);
given(principal.getName()).willReturn("somebody");
CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken(assertion, "ticket");
UserDetails user = uds.loadUserDetails(token);
Set<String> roles = AuthorityUtils.authorityListToSet(user.getAuthorities());
assertThat(roles).containsExactlyInAnyOrder("role_a1", "role_a2", "role_b", "role_c");
}
}

View File

@@ -0,0 +1,98 @@
/*
* 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.cas.web;
import java.net.URLEncoder;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.cas.ServiceProperties;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Tests {@link CasAuthenticationEntryPoint}.
*
* @author Ben Alex
*/
public class CasAuthenticationEntryPointTests {
@Test
public void testDetectsMissingLoginFormUrl() throws Exception {
CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
ep.setServiceProperties(new ServiceProperties());
assertThatIllegalArgumentException().isThrownBy(ep::afterPropertiesSet)
.withMessage("loginUrl must be specified");
}
@Test
public void testDetectsMissingServiceProperties() throws Exception {
CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
ep.setLoginUrl("https://cas/login");
assertThatIllegalArgumentException().isThrownBy(ep::afterPropertiesSet)
.withMessage("serviceProperties must be specified");
}
@Test
public void testGettersSetters() {
CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
ep.setLoginUrl("https://cas/login");
assertThat(ep.getLoginUrl()).isEqualTo("https://cas/login");
ep.setServiceProperties(new ServiceProperties());
assertThat(ep.getServiceProperties() != null).isTrue();
}
@Test
public void testNormalOperationWithRenewFalse() throws Exception {
ServiceProperties sp = new ServiceProperties();
sp.setSendRenew(false);
sp.setService("https://mycompany.com/bigWebApp/login/cas");
CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
ep.setLoginUrl("https://cas/login");
ep.setServiceProperties(sp);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/some_path");
MockHttpServletResponse response = new MockHttpServletResponse();
ep.afterPropertiesSet();
ep.commence(request, response, null);
assertThat(
"https://cas/login?service=" + URLEncoder.encode("https://mycompany.com/bigWebApp/login/cas", "UTF-8"))
.isEqualTo(response.getRedirectedUrl());
}
@Test
public void testNormalOperationWithRenewTrue() throws Exception {
ServiceProperties sp = new ServiceProperties();
sp.setSendRenew(true);
sp.setService("https://mycompany.com/bigWebApp/login/cas");
CasAuthenticationEntryPoint ep = new CasAuthenticationEntryPoint();
ep.setLoginUrl("https://cas/login");
ep.setServiceProperties(sp);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/some_path");
MockHttpServletResponse response = new MockHttpServletResponse();
ep.afterPropertiesSet();
ep.commence(request, response, null);
assertThat("https://cas/login?service="
+ URLEncoder.encode("https://mycompany.com/bigWebApp/login/cas", "UTF-8") + "&renew=true")
.isEqualTo(response.getRedirectedUrl());
}
}

View File

@@ -0,0 +1,199 @@
/*
* 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.cas.web;
import jakarta.servlet.FilterChain;
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
* Tests {@link CasAuthenticationFilter}.
*
* @author Ben Alex
* @author Rob Winch
*/
public class CasAuthenticationFilterTests {
@AfterEach
public void tearDown() {
SecurityContextHolder.clearContext();
}
@Test
public void testGettersSetters() {
CasAuthenticationFilter filter = new CasAuthenticationFilter();
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
filter.setProxyReceptorUrl("/someurl");
filter.setServiceProperties(new ServiceProperties());
}
@Test
public void testNormalOperation() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setServletPath("/login/cas");
request.addParameter("ticket", "ST-0-ER94xMJmn6pha35CQRoZ");
CasAuthenticationFilter filter = new CasAuthenticationFilter();
filter.setAuthenticationManager((a) -> a);
assertThat(filter.requiresAuthentication(request, new MockHttpServletResponse())).isTrue();
Authentication result = filter.attemptAuthentication(request, new MockHttpServletResponse());
assertThat(result != null).isTrue();
}
@Test
public void testNullServiceTicketHandledGracefully() throws Exception {
CasAuthenticationFilter filter = new CasAuthenticationFilter();
filter.setAuthenticationManager((a) -> {
throw new BadCredentialsException("Rejected");
});
assertThatExceptionOfType(AuthenticationException.class).isThrownBy(
() -> filter.attemptAuthentication(new MockHttpServletRequest(), new MockHttpServletResponse()));
}
@Test
public void testRequiresAuthenticationFilterProcessUrl() {
String url = "/login/cas";
CasAuthenticationFilter filter = new CasAuthenticationFilter();
filter.setFilterProcessesUrl(url);
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
request.setServletPath(url);
assertThat(filter.requiresAuthentication(request, response)).isTrue();
}
@Test
public void testRequiresAuthenticationProxyRequest() {
CasAuthenticationFilter filter = new CasAuthenticationFilter();
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
request.setServletPath("/pgtCallback");
assertThat(filter.requiresAuthentication(request, response)).isFalse();
filter.setProxyReceptorUrl(request.getServletPath());
assertThat(filter.requiresAuthentication(request, response)).isFalse();
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
assertThat(filter.requiresAuthentication(request, response)).isTrue();
request.setServletPath("/other");
assertThat(filter.requiresAuthentication(request, response)).isFalse();
}
@Test
public void testRequiresAuthenticationAuthAll() {
ServiceProperties properties = new ServiceProperties();
properties.setAuthenticateAllArtifacts(true);
String url = "/login/cas";
CasAuthenticationFilter filter = new CasAuthenticationFilter();
filter.setFilterProcessesUrl(url);
filter.setServiceProperties(properties);
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
request.setServletPath(url);
assertThat(filter.requiresAuthentication(request, response)).isTrue();
request.setServletPath("/other");
assertThat(filter.requiresAuthentication(request, response)).isFalse();
request.setParameter(properties.getArtifactParameter(), "value");
assertThat(filter.requiresAuthentication(request, response)).isTrue();
SecurityContextHolder.getContext().setAuthentication(new AnonymousAuthenticationToken("key", "principal",
AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS")));
assertThat(filter.requiresAuthentication(request, response)).isTrue();
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("un", "principal"));
assertThat(filter.requiresAuthentication(request, response)).isTrue();
SecurityContextHolder.getContext()
.setAuthentication(new TestingAuthenticationToken("un", "principal", "ROLE_ANONYMOUS"));
assertThat(filter.requiresAuthentication(request, response)).isFalse();
}
@Test
public void testAuthenticateProxyUrl() throws Exception {
CasAuthenticationFilter filter = new CasAuthenticationFilter();
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
request.setServletPath("/pgtCallback");
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
filter.setProxyReceptorUrl(request.getServletPath());
assertThat(filter.attemptAuthentication(request, response)).isNull();
}
@Test
public void testDoFilterAuthenticateAll() throws Exception {
AuthenticationSuccessHandler successHandler = mock(AuthenticationSuccessHandler.class);
AuthenticationManager manager = mock(AuthenticationManager.class);
Authentication authentication = new TestingAuthenticationToken("un", "pwd", "ROLE_USER");
given(manager.authenticate(any(Authentication.class))).willReturn(authentication);
ServiceProperties serviceProperties = new ServiceProperties();
serviceProperties.setAuthenticateAllArtifacts(true);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setParameter("ticket", "ST-1-123");
request.setServletPath("/authenticate");
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain chain = mock(FilterChain.class);
CasAuthenticationFilter filter = new CasAuthenticationFilter();
filter.setServiceProperties(serviceProperties);
filter.setAuthenticationSuccessHandler(successHandler);
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
filter.setAuthenticationManager(manager);
filter.afterPropertiesSet();
filter.doFilter(request, response, chain);
assertThat(SecurityContextHolder.getContext().getAuthentication()).isNotNull()
.withFailMessage("Authentication should not be null");
verify(chain).doFilter(request, response);
verifyZeroInteractions(successHandler);
// validate for when the filterProcessUrl matches
filter.setFilterProcessesUrl(request.getServletPath());
SecurityContextHolder.clearContext();
filter.doFilter(request, response, chain);
verifyNoMoreInteractions(chain);
verify(successHandler).onAuthenticationSuccess(request, response, authentication);
}
// SEC-1592
@Test
public void testChainNotInvokedForProxyReceptor() throws Exception {
CasAuthenticationFilter filter = new CasAuthenticationFilter();
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain chain = mock(FilterChain.class);
request.setServletPath("/pgtCallback");
filter.setProxyGrantingTicketStorage(mock(ProxyGrantingTicketStorage.class));
filter.setProxyReceptorUrl(request.getServletPath());
filter.doFilter(request, response, chain);
verifyZeroInteractions(chain);
}
}

View File

@@ -0,0 +1,67 @@
/*
* 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.cas.web;
import org.junit.jupiter.api.Test;
import org.springframework.security.cas.SamlServiceProperties;
import org.springframework.security.cas.ServiceProperties;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Tests {@link ServiceProperties}.
*
* @author Ben Alex
*/
public class ServicePropertiesTests {
@Test
public void detectsMissingService() throws Exception {
ServiceProperties sp = new ServiceProperties();
assertThatIllegalArgumentException().isThrownBy(sp::afterPropertiesSet);
}
@Test
public void nullServiceWhenAuthenticateAllTokens() throws Exception {
ServiceProperties sp = new ServiceProperties();
sp.setAuthenticateAllArtifacts(true);
assertThatIllegalArgumentException().isThrownBy(sp::afterPropertiesSet);
sp.setAuthenticateAllArtifacts(false);
assertThatIllegalArgumentException().isThrownBy(sp::afterPropertiesSet);
}
@Test
public void testGettersSetters() throws Exception {
ServiceProperties[] sps = { new ServiceProperties(), new SamlServiceProperties() };
for (ServiceProperties sp : sps) {
sp.setSendRenew(false);
assertThat(sp.isSendRenew()).isFalse();
sp.setSendRenew(true);
assertThat(sp.isSendRenew()).isTrue();
sp.setArtifactParameter("notticket");
assertThat(sp.getArtifactParameter()).isEqualTo("notticket");
sp.setServiceParameter("notservice");
assertThat(sp.getServiceParameter()).isEqualTo("notservice");
sp.setService("https://mycompany.com/service");
assertThat(sp.getService()).isEqualTo("https://mycompany.com/service");
sp.afterPropertiesSet();
}
}
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright 2011-2016 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.cas.web.authentication;
import java.util.regex.Pattern;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.web.util.UrlUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Rob Winch
*/
public class DefaultServiceAuthenticationDetailsTests {
private DefaultServiceAuthenticationDetails details;
private MockHttpServletRequest request;
private Pattern artifactPattern;
private String casServiceUrl;
private ConfigurableApplicationContext context;
@BeforeEach
public void setUp() {
this.casServiceUrl = "https://localhost:8443/j_spring_security_cas";
this.request = new MockHttpServletRequest();
this.request.setScheme("https");
this.request.setServerName("localhost");
this.request.setServerPort(8443);
this.request.setRequestURI("/cas-sample/secure/");
this.artifactPattern = DefaultServiceAuthenticationDetails
.createArtifactPattern(ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER);
}
@AfterEach
public void cleanup() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void getServiceUrlNullQuery() throws Exception {
this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, this.request, this.artifactPattern);
assertThat(this.details.getServiceUrl()).isEqualTo(UrlUtils.buildFullRequestUrl(this.request));
}
@Test
public void getServiceUrlTicketOnlyParam() throws Exception {
this.request.setQueryString("ticket=123");
this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, this.request, this.artifactPattern);
String serviceUrl = this.details.getServiceUrl();
this.request.setQueryString(null);
assertThat(serviceUrl).isEqualTo(UrlUtils.buildFullRequestUrl(this.request));
}
@Test
public void getServiceUrlTicketFirstMultiParam() throws Exception {
this.request.setQueryString("ticket=123&other=value");
this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, this.request, this.artifactPattern);
String serviceUrl = this.details.getServiceUrl();
this.request.setQueryString("other=value");
assertThat(serviceUrl).isEqualTo(UrlUtils.buildFullRequestUrl(this.request));
}
@Test
public void getServiceUrlTicketLastMultiParam() throws Exception {
this.request.setQueryString("other=value&ticket=123");
this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, this.request, this.artifactPattern);
String serviceUrl = this.details.getServiceUrl();
this.request.setQueryString("other=value");
assertThat(serviceUrl).isEqualTo(UrlUtils.buildFullRequestUrl(this.request));
}
@Test
public void getServiceUrlTicketMiddleMultiParam() throws Exception {
this.request.setQueryString("other=value&ticket=123&last=this");
this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, this.request, this.artifactPattern);
String serviceUrl = this.details.getServiceUrl();
this.request.setQueryString("other=value&last=this");
assertThat(serviceUrl).isEqualTo(UrlUtils.buildFullRequestUrl(this.request));
}
@Test
public void getServiceUrlDoesNotUseHostHeader() throws Exception {
this.casServiceUrl = "https://example.com/j_spring_security_cas";
this.request.setServerName("evil.com");
this.details = new DefaultServiceAuthenticationDetails(this.casServiceUrl, this.request, this.artifactPattern);
assertThat(this.details.getServiceUrl()).isEqualTo("https://example.com/cas-sample/secure/");
}
@Test
public void getServiceUrlDoesNotUseHostHeaderExplicit() {
this.casServiceUrl = "https://example.com/j_spring_security_cas";
this.request.setServerName("evil.com");
ServiceAuthenticationDetails details = loadServiceAuthenticationDetails(
"defaultserviceauthenticationdetails-explicit.xml");
assertThat(details.getServiceUrl()).isEqualTo("https://example.com/cas-sample/secure/");
}
private ServiceAuthenticationDetails loadServiceAuthenticationDetails(String resourceName) {
this.context = new GenericXmlApplicationContext(getClass(), resourceName);
ServiceAuthenticationDetailsSource source = this.context.getBean(ServiceAuthenticationDetailsSource.class);
return source.buildDetails(this.request);
}
}

View File

@@ -0,0 +1,15 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.springframework.security" level="${sec.log.level:-WARN}"/>
<root level="${root.level:-WARN}">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://example.com/j_spring_security_cas"/>
<property name="sendRenew" value="false"/>
</bean>
<bean id="serviceProperties2"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://example2.com/j_spring_security_cas"/>
<property name="sendRenew" value="false"/>
</bean>
<bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource">
<constructor-arg ref="serviceProperties"/>
</bean>
</beans>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://example.com/j_spring_security_cas"/>
<property name="sendRenew" value="false"/>
</bean>
<bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"/>
</beans>