Add test coverage, fix bugs found by tests.

This commit is contained in:
Marvin S. Addison 2013-12-20 11:21:12 -05:00
parent f9dfd6cf2f
commit 9981e433d7
2 changed files with 91 additions and 19 deletions

View File

@ -139,7 +139,7 @@ public class CasLoginModule implements LoginModule {
/** Unique suffix pattern appended to some service URLs to make them unique. */
protected static final Pattern UNIQUE_SUFFIX_PATTERN =
Pattern.compile(".*;uuid=\\p{XDigit}{8}-\\p{XDigit}{4}-\\p{XDigit}{4}-\\p{XDigit}{4}-\\p{XDigit}{12}");
Pattern.compile("(.*);uuid=\\p{XDigit}{8}-\\p{XDigit}{4}-\\p{XDigit}{4}-\\p{XDigit}{4}-\\p{XDigit}{12}");
/** Logger instance */
protected final Logger logger = LoggerFactory.getLogger(getClass());
@ -327,7 +327,7 @@ public class CasLoginModule implements LoginModule {
final Matcher m = UNIQUE_SUFFIX_PATTERN.matcher(this.service);
if (m.matches()) {
this.servicePrincipal = this.service;
this.service = m.replaceFirst("");
this.service = m.replaceFirst("$1");
} else {
this.servicePrincipal = this.service + createUniqueSuffix();
}

View File

@ -24,6 +24,8 @@ import java.security.acl.Group;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
import org.jasig.cas.client.PublicTestHttpServer;
@ -45,10 +47,6 @@ public class CasLoginModuleTests {
private static final String CONST_CAS_SERVER_URL = "http://localhost:8091/";
private CasLoginModule module;
private Subject subject;
private Map<String, String> options;
/* @AfterClass
@ -58,10 +56,7 @@ public class CasLoginModuleTests {
@Before
public void setUp() throws Exception {
module = new CasLoginModule();
subject = new Subject();
options = new HashMap<String, String>();
options.put("service", "https://service.example.com/webapp");
options.put("ticketValidatorClass", "org.jasig.cas.client.validation.Cas20ServiceTicketValidator");
options.put("casServerUrlPrefix", CONST_CAS_SERVER_URL);
options.put("proxyCallbackUrl", "https://service.example.com/webapp/proxy");
@ -85,6 +80,8 @@ public class CasLoginModuleTests {
+ "</cas:user></cas:authenticationSuccess></cas:serviceResponse>";
server.content = RESPONSE.getBytes(server.encoding);
final CasLoginModule module = new CasLoginModule();
final Subject subject = new Subject();
module.initialize(
subject,
new ServiceAndTicketCallbackHandler(SERVICE, TICKET),
@ -92,11 +89,47 @@ public class CasLoginModuleTests {
options);
module.login();
module.commit();
assertEquals(this.subject.getPrincipals().size(), 3);
assertEquals(TICKET, this.subject.getPrivateCredentials().iterator().next().toString());
assertTrue(hasPrincipalName(this.subject, AssertionPrincipal.class, USERNAME));
assertTrue(hasPrincipalName(this.subject, Group.class, "CallerPrincipal"));
assertTrue(hasPrincipalName(this.subject, Group.class, "Roles"));
assertEquals(subject.getPrincipals().size(), 3);
assertEquals(TICKET, subject.getPrivateCredentials().iterator().next().toString());
assertTrue(hasPrincipalName(subject, Group.class, "CallerPrincipal"));
assertTrue(hasPrincipalName(subject, Group.class, "Roles"));
final AssertionPrincipal principal = getPrincipal(subject, AssertionPrincipal.class);
assertEquals(USERNAME, principal.getName());
final Matcher m = CasLoginModule.UNIQUE_SUFFIX_PATTERN.matcher(principal.getServicePrincipal());
assertTrue(m.matches());
}
/**
* Test JAAS login success.
* @throws Exception On errors.
*/
@Test
public void testLoginSuccessUniquePrincipal() throws Exception {
final String USERNAME = "alice";
final String SERVICE = "https://example.com/service" + CasLoginModule.createUniqueSuffix();
final String TICKET = "ST-100001-aA5Zabcxzpv8Tau1abeZ-srv1";
final String RESPONSE = "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>"
+ "<cas:authenticationSuccess><cas:user>" + USERNAME
+ "</cas:user></cas:authenticationSuccess></cas:serviceResponse>";
server.content = RESPONSE.getBytes(server.encoding);
final CasLoginModule module = new CasLoginModule();
final Subject subject = new Subject();
module.initialize(
subject,
new ServiceAndTicketCallbackHandler(SERVICE, TICKET),
new HashMap<String, Object>(),
options);
module.login();
module.commit();
assertEquals(subject.getPrincipals().size(), 3);
assertEquals(TICKET, subject.getPrivateCredentials().iterator().next().toString());
assertTrue(hasPrincipalName(subject, Group.class, "CallerPrincipal"));
assertTrue(hasPrincipalName(subject, Group.class, "Roles"));
final AssertionPrincipal principal = getPrincipal(subject, AssertionPrincipal.class);
assertEquals(USERNAME, principal.getName());
assertEquals(SERVICE, principal.getServicePrincipal());
}
/**
@ -109,6 +142,9 @@ public class CasLoginModuleTests {
final String TICKET = "ST-200000-aA5Yuvrxzpv8Tau1cYQ7-srv1";
final String RESPONSE = "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'><cas:authenticationFailure code=\"INVALID_TICKET\">Ticket ST-200000-aA5Yuvrxzpv8Tau1cYQ7-srv1 not recognized</cas:authenticationFailure></cas:serviceResponse>";
server.content = RESPONSE.getBytes(server.encoding);
final CasLoginModule module = new CasLoginModule();
final Subject subject = new Subject();
module.initialize(
subject,
new ServiceAndTicketCallbackHandler(SERVICE, TICKET),
@ -131,7 +167,32 @@ public class CasLoginModuleTests {
*/
@Test
public void testLogout() throws Exception {
testLoginSuccess();
final String USERNAME = "username";
final String SERVICE = "https://example.com/service";
final String TICKET = "ST-100000-aA5Yuvrxzpv8Tau1cYQ7-srv1";
final String RESPONSE = "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>"
+ "<cas:authenticationSuccess><cas:user>" + USERNAME
+ "</cas:user></cas:authenticationSuccess></cas:serviceResponse>";
server.content = RESPONSE.getBytes(server.encoding);
final CasLoginModule module = new CasLoginModule();
final Subject subject = new Subject();
module.initialize(
subject,
new ServiceAndTicketCallbackHandler(SERVICE, TICKET),
new HashMap<String, Object>(),
options);
module.login();
module.commit();
assertEquals(subject.getPrincipals().size(), 3);
assertEquals(TICKET, subject.getPrivateCredentials().iterator().next().toString());
assertTrue(hasPrincipalName(subject, Group.class, "CallerPrincipal"));
assertTrue(hasPrincipalName(subject, Group.class, "Roles"));
final AssertionPrincipal principal = getPrincipal(subject, AssertionPrincipal.class);
assertEquals(USERNAME, principal.getName());
final Matcher m = CasLoginModule.UNIQUE_SUFFIX_PATTERN.matcher(principal.getServicePrincipal());
assertTrue(m.matches());
module.logout();
assertEquals(0, subject.getPrincipals().size());
assertEquals(0, subject.getPrivateCredentials().size());
@ -155,6 +216,9 @@ public class CasLoginModuleTests {
options.put("cacheTimeout", "1");
server.content = SUCCESS_RESPONSE.getBytes(server.encoding);
final CasLoginModule module = new CasLoginModule();
final Subject subject = new Subject();
module.initialize(
subject,
new ServiceAndTicketCallbackHandler(SERVICE, TICKET),
@ -162,8 +226,8 @@ public class CasLoginModuleTests {
options);
module.login();
module.commit();
assertEquals(this.subject.getPrincipals().size(), 3);
assertEquals(TICKET, this.subject.getPrivateCredentials().iterator().next().toString());
assertEquals(subject.getPrincipals().size(), 3);
assertEquals(TICKET, subject.getPrivateCredentials().iterator().next().toString());
// Logout should destroy all authenticated state data including assertion cache entries
module.logout();
@ -184,8 +248,8 @@ public class CasLoginModuleTests {
} catch (LoginException e) {
assertEquals(TicketValidationException.class, e.getCause().getClass());
}
assertEquals(0, this.subject.getPrincipals().size());
assertEquals(0, this.subject.getPrivateCredentials().size());
assertEquals(0, subject.getPrincipals().size());
assertEquals(0, subject.getPrivateCredentials().size());
}
/**
@ -210,6 +274,9 @@ public class CasLoginModuleTests {
options.put("cacheTimeout", "1");
server.content = SUCCESS_RESPONSE.getBytes(server.encoding);
final CasLoginModule module = new CasLoginModule();
final Subject subject = new Subject();
module.initialize(
subject,
new ServiceAndTicketCallbackHandler(SERVICE, TICKET),
@ -234,6 +301,11 @@ public class CasLoginModuleTests {
}
}
private <T extends Principal> T getPrincipal(final Subject subject, final Class<T> principalType)
{
return subject.getPrincipals(principalType).iterator().next();
}
private boolean hasPrincipalName(final Subject subject, final Class<? extends Principal> principalClass,
final String name) {
final Set<? extends Principal> principals = subject.getPrincipals(principalClass);