package org.jboss.seam.security.external.saml; import java.util.GregorianCalendar; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.inject.Instance; import javax.inject.Inject; import org.jboss.seam.security.external.dialogues.api.Dialogue; import org.jboss.seam.security.external.jaxb.samlv2.assertion.AssertionType; import org.jboss.seam.security.external.jaxb.samlv2.assertion.AudienceRestrictionType; import org.jboss.seam.security.external.jaxb.samlv2.assertion.AuthnContextType; import org.jboss.seam.security.external.jaxb.samlv2.assertion.AuthnStatementType; import org.jboss.seam.security.external.jaxb.samlv2.assertion.ConditionsType; import org.jboss.seam.security.external.jaxb.samlv2.assertion.NameIDType; import org.jboss.seam.security.external.jaxb.samlv2.assertion.SubjectConfirmationDataType; import org.jboss.seam.security.external.jaxb.samlv2.assertion.SubjectConfirmationType; import org.jboss.seam.security.external.jaxb.samlv2.assertion.SubjectType; import org.jboss.seam.security.external.jaxb.samlv2.protocol.AuthnRequestType; import org.jboss.seam.security.external.jaxb.samlv2.protocol.LogoutRequestType; import org.jboss.seam.security.external.jaxb.samlv2.protocol.ObjectFactory; import org.jboss.seam.security.external.jaxb.samlv2.protocol.RequestAbstractType; import org.jboss.seam.security.external.jaxb.samlv2.protocol.ResponseType; import org.jboss.seam.security.external.jaxb.samlv2.protocol.StatusCodeType; import org.jboss.seam.security.external.jaxb.samlv2.protocol.StatusResponseType; import org.jboss.seam.security.external.jaxb.samlv2.protocol.StatusType; import org.jboss.seam.security.external.saml.api.SamlIdpSession; import org.jboss.seam.security.external.saml.api.SamlNameId; import org.jboss.seam.security.external.saml.idp.SamlIdpSessionImpl; /** * @author Marcel Kolsteren */ @ApplicationScoped public class SamlMessageFactory { private static final int ASSERTION_VALIDITY_IN_MINUTES = 5; @Inject private Instance<SamlEntityBean> samlEntityBean; @Inject private Dialogue dialogue; @Inject private Instance<SamlDialogue> samlDialogue; private ObjectFactory objectFactory = new ObjectFactory(); private org.jboss.seam.security.external.jaxb.samlv2.assertion.ObjectFactory assertionObjectFactory = new org.jboss.seam.security.external.jaxb.samlv2.assertion.ObjectFactory(); public StatusResponseType createStatusResponse(String statusCode, String statusMessage) { StatusResponseType response = objectFactory.createStatusResponseType(); fillStatusResponseFields(response, statusCode, statusMessage); return response; } public AuthnRequestType createAuthnRequest() { AuthnRequestType authnRequest = objectFactory.createAuthnRequestType(); fillRequestAbstractTypeFields(authnRequest); // Fill in the optional fields that indicate where and how the response // should be delivered. authnRequest.setAssertionConsumerServiceURL(samlEntityBean.get().getServiceURL(SamlServiceType.SAML_ASSERTION_CONSUMER_SERVICE)); authnRequest.setProtocolBinding(SamlConstants.HTTP_POST_BINDING); return authnRequest; } public ResponseType createResponse(SamlIdpSession session, SamlEndpoint externalSamlEndpoint) { ResponseType response = objectFactory.createResponseType(); fillStatusResponseFields(response, SamlConstants.STATUS_SUCCESS, null); AssertionType assertion = assertionObjectFactory.createAssertionType(); response.getAssertionOrEncryptedAssertion().add(assertion); SubjectType subject = assertionObjectFactory.createSubjectType(); assertion.setSubject(subject); NameIDType nameID = assertionObjectFactory.createNameIDType(); subject.getContent().add(assertionObjectFactory.createNameID(nameID)); nameID.setValue(session.getPrincipal().getNameId().getValue()); nameID.setFormat(session.getPrincipal().getNameId().getFormat()); nameID.setNameQualifier(session.getPrincipal().getNameId().getQualifier()); SubjectConfirmationType subjectConfirmation = assertionObjectFactory.createSubjectConfirmationType(); subject.getContent().add(assertionObjectFactory.createSubjectConfirmation(subjectConfirmation)); subjectConfirmation.setMethod(SamlConstants.CONFIRMATION_METHOD_BEARER); subjectConfirmation.setNameID(nameID); SubjectConfirmationDataType subjectConfirmationData = assertionObjectFactory.createSubjectConfirmationDataType(); subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData); subjectConfirmationData.setRecipient(externalSamlEndpoint.getLocation()); subjectConfirmationData.setNotOnOrAfter(SamlUtils.getXMLGregorianCalendarNowPlusDuration(GregorianCalendar.MINUTE, ASSERTION_VALIDITY_IN_MINUTES)); subjectConfirmationData.setInResponseTo(samlDialogue.get().getExternalProviderMessageId()); ConditionsType conditions = assertionObjectFactory.createConditionsType(); assertion.setConditions(conditions); AudienceRestrictionType audienceRestriction = assertionObjectFactory.createAudienceRestrictionType(); conditions.getConditionOrAudienceRestrictionOrOneTimeUse().add(audienceRestriction); audienceRestriction.getAudience().add(samlDialogue.get().getExternalProvider().getEntityId()); AuthnStatementType authnStatement = assertionObjectFactory.createAuthnStatementType(); assertion.getStatementOrAuthnStatementOrAuthzDecisionStatement().add(authnStatement); authnStatement.setAuthnInstant(SamlUtils.getXMLGregorianCalendarNow()); authnStatement.setSessionIndex(((SamlIdpSessionImpl) session).getSessionIndex()); AuthnContextType authnContext = assertionObjectFactory.createAuthnContextType(); authnStatement.setAuthnContext(authnContext); authnContext.getContent().add(assertionObjectFactory.createAuthnContextDeclRef(SamlConstants.AC_PASSWORD_PROTECTED_TRANSPORT)); return response; } public LogoutRequestType createLogoutRequest(SamlNameId samlNameId, String sessionIndex) { LogoutRequestType logoutRequest = objectFactory.createLogoutRequestType(); fillRequestAbstractTypeFields(logoutRequest); NameIDType nameID = assertionObjectFactory.createNameIDType(); nameID.setValue(samlNameId.getValue()); nameID.setFormat(samlNameId.getFormat()); nameID.setNameQualifier(samlNameId.getQualifier()); logoutRequest.setNameID(nameID); logoutRequest.getSessionIndex().add(sessionIndex); return logoutRequest; } private void fillRequestAbstractTypeFields(RequestAbstractType request) { request.setID(dialogue.getId()); request.setIssueInstant(SamlUtils.getXMLGregorianCalendarNow()); NameIDType issuer = assertionObjectFactory.createNameIDType(); issuer.setValue(samlEntityBean.get().getEntityId()); request.setIssuer(issuer); request.setVersion(SamlConstants.VERSION_2_0); } private void fillStatusResponseFields(StatusResponseType response, String statusCode, String statusMessage) { response.setID(dialogue.getId()); response.setIssueInstant(SamlUtils.getXMLGregorianCalendarNow()); NameIDType issuer = assertionObjectFactory.createNameIDType(); issuer.setValue(samlEntityBean.get().getEntityId()); response.setIssuer(issuer); response.setVersion(SamlConstants.VERSION_2_0); response.setInResponseTo(samlDialogue.get().getExternalProviderMessageId()); StatusCodeType statusCodeJaxb = objectFactory.createStatusCodeType(); statusCodeJaxb.setValue(statusCode); StatusType statusType = objectFactory.createStatusType(); statusType.setStatusCode(statusCodeJaxb); if (statusMessage != null) { statusType.setStatusMessage(statusMessage); } response.setStatus(statusType); } }