committed by
Marcus Da Coregio
parent
baf2c98c9f
commit
b4d3ac6665
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
15
cas/src/test/resources/logback-test.xml
Normal file
15
cas/src/test/resources/logback-test.xml
Normal 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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user