package org.cloudfoundry.identity.uaa.provider.saml.idp;
import org.cloudfoundry.identity.uaa.constants.OriginKeys;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.opensaml.common.SAMLException;
import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.Attribute;
import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.saml2.core.NameIDType;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.core.Subject;
import org.opensaml.saml2.core.SubjectConfirmation;
import org.opensaml.saml2.core.SubjectConfirmationData;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
import org.opensaml.ws.message.encoder.MessageEncodingException;
import org.opensaml.xml.ConfigurationException;
import org.opensaml.xml.io.MarshallingException;
import org.opensaml.xml.schema.XSString;
import org.opensaml.xml.security.SecurityException;
import org.opensaml.xml.signature.SignatureException;
import org.springframework.security.core.Authentication;
import org.springframework.security.saml.context.SAMLMessageContext;
import java.util.List;
import java.util.UUID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class IdpWebSsoProfileImplTest {
private final SamlTestUtils samlTestUtils = new SamlTestUtils();
@Before
public void setup() throws ConfigurationException {
samlTestUtils.initialize();
}
@Test
public void testBuildResponseForSamlRequestWithPersistentNameID() throws MessageEncodingException, SAMLException,
MetadataProviderException, SecurityException, MarshallingException, SignatureException {
IdpWebSsoProfileImpl profile = new IdpWebSsoProfileImpl();
String authenticationId = UUID.randomUUID().toString();
Authentication authentication = samlTestUtils.mockUaaAuthentication(authenticationId);
SAMLMessageContext context = samlTestUtils.mockSamlMessageContext(
samlTestUtils.mockAuthnRequest(NameIDType.PERSISTENT));
IdpWebSSOProfileOptions options = new IdpWebSSOProfileOptions();
options.setAssertionsSigned(false);
profile.buildResponse(authentication, context, options);
AuthnRequest request = (AuthnRequest) context.getInboundSAMLMessage();
Response response = (Response) context.getOutboundSAMLMessage();
Assertion assertion = response.getAssertions().get(0);
Subject subject = assertion.getSubject();
assertEquals(authenticationId, subject.getNameID().getValue());
assertEquals(NameIDType.PERSISTENT, subject.getNameID().getFormat());
SubjectConfirmation subjectConfirmation = subject.getSubjectConfirmations().get(0);
SubjectConfirmationData subjectConfirmationData = subjectConfirmation.getSubjectConfirmationData();
assertEquals(request.getID(), subjectConfirmationData.getInResponseTo());
verifyAssertionAttributes(authenticationId, assertion);
}
@Test
public void testBuildResponseForSamlRequestWithUnspecifiedNameID() throws MessageEncodingException, SAMLException,
MetadataProviderException, SecurityException, MarshallingException, SignatureException {
IdpWebSsoProfileImpl profile = new IdpWebSsoProfileImpl();
String authenticationId = UUID.randomUUID().toString();
Authentication authentication = samlTestUtils.mockUaaAuthentication(authenticationId);
SAMLMessageContext context = samlTestUtils.mockSamlMessageContext(
samlTestUtils.mockAuthnRequest(NameIDType.UNSPECIFIED));
IdpWebSSOProfileOptions options = new IdpWebSSOProfileOptions();
options.setAssertionsSigned(false);
profile.buildResponse(authentication, context, options);
AuthnRequest request = (AuthnRequest) context.getInboundSAMLMessage();
Response response = (Response) context.getOutboundSAMLMessage();
Assertion assertion = response.getAssertions().get(0);
Subject subject = assertion.getSubject();
assertEquals("marissa", subject.getNameID().getValue());
assertEquals(NameIDType.UNSPECIFIED, subject.getNameID().getFormat());
SubjectConfirmation subjectConfirmation = subject.getSubjectConfirmations().get(0);
SubjectConfirmationData subjectConfirmationData = subjectConfirmation.getSubjectConfirmationData();
assertEquals(request.getID(), subjectConfirmationData.getInResponseTo());
verifyAssertionAttributes(authenticationId, assertion);
}
@Test
public void testBuildResponseForSamlRequestWithEmailAddressNameID() throws MessageEncodingException, SAMLException,
MetadataProviderException, SecurityException, MarshallingException, SignatureException {
IdpWebSsoProfileImpl profile = new IdpWebSsoProfileImpl();
String authenticationId = UUID.randomUUID().toString();
Authentication authentication = samlTestUtils.mockUaaAuthentication(authenticationId);
SAMLMessageContext context = samlTestUtils.mockSamlMessageContext(
samlTestUtils.mockAuthnRequest(NameIDType.EMAIL));
IdpWebSSOProfileOptions options = new IdpWebSSOProfileOptions();
options.setAssertionsSigned(false);
profile.buildResponse(authentication, context, options);
AuthnRequest request = (AuthnRequest) context.getInboundSAMLMessage();
Response response = (Response) context.getOutboundSAMLMessage();
Assertion assertion = response.getAssertions().get(0);
Subject subject = assertion.getSubject();
assertEquals("marissa@testing.org", subject.getNameID().getValue());
assertEquals(NameIDType.EMAIL, subject.getNameID().getFormat());
SubjectConfirmation subjectConfirmation = subject.getSubjectConfirmations().get(0);
SubjectConfirmationData subjectConfirmationData = subjectConfirmation.getSubjectConfirmationData();
assertEquals(request.getID(), subjectConfirmationData.getInResponseTo());
verifyAssertionAttributes(authenticationId, assertion);
}
@Test
public void testBuildResponse() throws MessageEncodingException, SAMLException, MetadataProviderException,
SecurityException, MarshallingException, SignatureException {
IdpWebSsoProfileImpl profile = new IdpWebSsoProfileImpl();
String authenticationId = UUID.randomUUID().toString();
Authentication authentication = samlTestUtils.mockUaaAuthentication(authenticationId);
SAMLMessageContext context = samlTestUtils.mockSamlMessageContext();
IdpWebSSOProfileOptions options = new IdpWebSSOProfileOptions();
options.setAssertionsSigned(false);
profile.buildResponse(authentication, context, options);
AuthnRequest request = (AuthnRequest) context.getInboundSAMLMessage();
Response response = (Response) context.getOutboundSAMLMessage();
assertEquals(request.getID(), response.getInResponseTo());
Assertion assertion = response.getAssertions().get(0);
Subject subject = assertion.getSubject();
assertEquals("marissa", subject.getNameID().getValue());
assertEquals(NameIDType.UNSPECIFIED, subject.getNameID().getFormat());
SubjectConfirmation subjectConfirmation = subject.getSubjectConfirmations().get(0);
SubjectConfirmationData subjectConfirmationData = subjectConfirmation.getSubjectConfirmationData();
assertEquals(request.getID(), subjectConfirmationData.getInResponseTo());
verifyAssertionAttributes(authenticationId, assertion);
}
private void verifyAssertionAttributes(String authenticationId, Assertion assertion) {
List<Attribute> attributes = assertion.getAttributeStatements().get(0).getAttributes();
assertAttributeValue(attributes, "email", "marissa@testing.org");
assertAttributeValue(attributes, "id", authenticationId);
assertAttributeValue(attributes, "name", "marissa");
assertAttributeValue(attributes, "origin", OriginKeys.UAA);
assertAttributeValue(attributes, "zoneId", "uaa");
}
private void assertAttributeValue(List<Attribute> attributeList, String name, String expectedValue) {
for (Attribute attribute : attributeList) {
if (attribute.getName().equals(name)) {
if (1 != attribute.getAttributeValues().size()) {
Assert.fail(String.format("More than one attribute value with name of '%s'.", name));
}
XSString xsString = (XSString) attribute.getAttributeValues().get(0);
Assert.assertEquals(String.format("Attribute mismatch for '%s'.", name), expectedValue,
xsString.getValue());
return;
}
}
Assert.fail(String.format("No attribute value with name of '%s'.", name));
}
@Test
public void testBuildResponseWithSignedAssertion() throws MessageEncodingException, SAMLException,
MetadataProviderException, SecurityException, MarshallingException, SignatureException {
IdpWebSsoProfileImpl profile = new IdpWebSsoProfileImpl();
String authenticationId = UUID.randomUUID().toString();
Authentication authentication = samlTestUtils.mockUaaAuthentication(authenticationId);
SAMLMessageContext context = samlTestUtils.mockSamlMessageContext();
IdpWebSSOProfileOptions options = new IdpWebSSOProfileOptions();
options.setAssertionsSigned(true);
profile.buildResponse(authentication, context, options);
AuthnRequest request = (AuthnRequest) context.getInboundSAMLMessage();
Response response = (Response) context.getOutboundSAMLMessage();
Assertion assertion = response.getAssertions().get(0);
Subject subject = assertion.getSubject();
assertEquals("marissa", subject.getNameID().getValue());
SubjectConfirmation subjectConfirmation = subject.getSubjectConfirmations().get(0);
SubjectConfirmationData subjectConfirmationData = subjectConfirmation.getSubjectConfirmationData();
assertEquals(request.getID(), subjectConfirmationData.getInResponseTo());
verifyAssertionAttributes(authenticationId, assertion);
assertNotNull(assertion.getSignature());
}
}