import org.opensaml.common.SAMLObject;
import org.opensaml.common.SAMLObjectBuilder;
import org.opensaml.common.SAMLVersion;
+import org.opensaml.common.binding.encoding.SAMLMessageEncoder;
import org.opensaml.saml1.core.Assertion;
import org.opensaml.saml1.core.AttributeQuery;
import org.opensaml.saml1.core.AttributeStatement;
import org.opensaml.saml2.metadata.RoleDescriptor;
import org.opensaml.saml2.metadata.SPSSODescriptor;
import org.opensaml.saml2.metadata.SSODescriptor;
+import org.opensaml.ws.message.encoder.MessageEncodingException;
import org.opensaml.xml.XMLObjectBuilder;
import org.opensaml.xml.io.Marshaller;
import org.opensaml.xml.io.MarshallingException;
import org.opensaml.xml.security.SecurityHelper;
import org.opensaml.xml.security.credential.Credential;
import org.opensaml.xml.signature.Signature;
+import org.opensaml.xml.signature.SignatureException;
import org.opensaml.xml.signature.Signer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import edu.internet2.middleware.shibboleth.common.attribute.encoding.SAML1NameIdentifierEncoder;
import edu.internet2.middleware.shibboleth.common.attribute.provider.SAML1AttributeAuthority;
import edu.internet2.middleware.shibboleth.common.profile.ProfileException;
+import edu.internet2.middleware.shibboleth.common.profile.provider.BaseSAMLProfileRequestContext;
+import edu.internet2.middleware.shibboleth.common.relyingparty.provider.CryptoOperationRequirementLevel;
import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml1.AbstractSAML1ProfileConfiguration;
import edu.internet2.middleware.shibboleth.idp.profile.AbstractSAMLProfileHandler;
+import edu.internet2.middleware.shibboleth.idp.session.Session;
/** Common implementation details for profile handlers. */
public abstract class AbstractSAML1ProfileHandler extends AbstractSAMLProfileHandler {
signatureBuilder = (XMLObjectBuilder<Signature>) getBuilderFactory().getBuilder(Signature.DEFAULT_ELEMENT_NAME);
}
+ /** {@inheritDoc} */
+ protected void populateRequestContext(BaseSAMLProfileRequestContext requestContext) throws ProfileException {
+ BaseSAML1ProfileRequestContext saml1Request = (BaseSAML1ProfileRequestContext) requestContext;
+ try {
+ super.populateRequestContext(requestContext);
+ } catch (ProfileException e) {
+ if (saml1Request.getFailureStatus() == null) {
+ saml1Request.setFailureStatus(buildStatus(StatusCode.REQUESTER, null, e.getMessage()));
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Populates the request context with the information about the user.
+ *
+ * This method requires the the following request context properties to be populated: inbound message transport,
+ * relying party ID
+ *
+ * This methods populates the following request context properties: user's session, user's principal name, and
+ * service authentication method
+ *
+ * @param requestContext current request context
+ */
+ protected void populateUserInformation(BaseSAMLProfileRequestContext requestContext) {
+ Session userSession = getUserSession(requestContext.getInboundMessageTransport());
+ if (userSession == null) {
+ NameIdentifier subject = (NameIdentifier) requestContext.getSubjectNameIdentifier();
+ if (subject != null && subject.getNameIdentifier() != null) {
+ userSession = getUserSession(subject.getNameIdentifier());
+ }
+ }
+
+ if (userSession != null) {
+ requestContext.setUserSession(userSession);
+ requestContext.setPrincipalName(userSession.getPrincipalName());
+ requestContext.setPrincipalAuthenticationMethod(userSession.getServicesInformation().get(
+ requestContext.getPeerEntityId()).getAuthenticationMethod().getAuthenticationMethod());
+ }
+ }
+
/**
* Checks that the SAML major version for a request is 1.
*
throws ProfileException {
log.debug("Building assertion NameIdentifier to relying party {} for principal {}", requestContext
.getInboundMessageIssuer(), requestContext.getPrincipalName());
- Map<String, BaseAttribute> principalAttributes = requestContext.getPrincipalAttributes();
+ Map<String, BaseAttribute> principalAttributes = requestContext.getAttributes();
if (principalAttributes == null || principalAttributes.isEmpty()) {
log.error("No attributes for principal {}, unable to construct of NameID", requestContext
.getPrincipalName());
if (encoder instanceof SAML1NameIdentifierEncoder) {
nameIdEncoder = (SAML1NameIdentifierEncoder) encoder;
if (supportedNameFormats.contains(nameIdEncoder.getNameFormat())) {
- log.debug("Using attribute {} suppoting name format {} to create the NameIdentifier for principal",
+ log
+ .debug(
+ "Using attribute {} suppoting name format {} to create the NameIdentifier for principal",
attribute.getId(), nameIdEncoder.getNameFormat());
return nameIdEncoder.encode(attribute);
}
}
if (nameFormats.isEmpty()) {
- nameFormats.add("urn:oasis:names:tc:SAML:1.0:nameid-format:unspecified");
+ nameFormats.add("urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified");
}
return nameFormats;
AttributeStatement statment;
if (requestContext.getInboundSAMLMessage() instanceof AttributeQuery) {
statment = attributeAuthority.buildAttributeStatement((AttributeQuery) requestContext
- .getInboundSAMLMessage(), requestContext.getPrincipalAttributes().values());
+ .getInboundSAMLMessage(), requestContext.getAttributes().values());
} else {
- statment = attributeAuthority.buildAttributeStatement(null, requestContext.getPrincipalAttributes()
- .values());
+ statment = attributeAuthority.buildAttributeStatement(null, requestContext.getAttributes().values());
}
- Subject statementSubject = buildSubject(requestContext, subjectConfMethod);
- statment.setSubject(statementSubject);
+ if (statment != null) {
+ Subject statementSubject = buildSubject(requestContext, subjectConfMethod);
+ statment.setSubject(statementSubject);
+ }
return statment;
} catch (AttributeRequestException e) {
boolean signAssertion = false;
RoleDescriptor relyingPartyRole = requestContext.getPeerEntityRoleMetadata();
+ SAMLMessageEncoder encoder = getMessageEncoders().get(requestContext.getPeerEntityEndpoint().getBinding());
AbstractSAML1ProfileConfiguration profileConfig = requestContext.getProfileConfiguration();
- if (profileConfig.getSignAssertions()) {
- signAssertion = true;
- log.debug("IdP relying party configuration {} indicates to sign assertions: {}", requestContext
- .getRelyingPartyConfiguration().getRelyingPartyId(), signAssertion);
+
+ try {
+ if (profileConfig.getSignAssertions() == CryptoOperationRequirementLevel.always
+ || (profileConfig.getSignAssertions() == CryptoOperationRequirementLevel.conditional && !encoder
+ .providesMessageIntegrity(requestContext))) {
+ signAssertion = true;
+ log.debug("IdP relying party configuration {} indicates to sign assertions: {}", requestContext
+ .getRelyingPartyConfiguration().getRelyingPartyId(), signAssertion);
+ }
+ } catch (MessageEncodingException e) {
+ log.error("Unable to determine if outbound encoding {} can provide integrity", encoder.getBindingURI());
+ throw new ProfileException("Unable to determine if outbound message should be signed");
}
if (!signAssertion && relyingPartyRole instanceof SPSSODescriptor) {
} catch (MarshallingException e) {
log.error("Unable to marshall assertion for signing", e);
throw new ProfileException("Unable to marshall assertion for signing", e);
+ } catch (SignatureException e) {
+ log.error("Unable to sign assertion", e);
+ throw new ProfileException("Unable to sign assertion", e);
}
}
}
\ No newline at end of file