import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
import edu.internet2.middleware.shibboleth.metadata.Metadata;
import edu.internet2.middleware.shibboleth.metadata.MetadataException;
-import edu.internet2.middleware.shibboleth.metadata.SPSSODescriptor;
/**
* Delivers core IdP functionality (Attribute resolution, ARP filtering, Metadata lookup, Signing, Mapping between local &
return spMapper;
}
- public static void addSignatures(SAMLResponse response, RelyingParty relyingParty, EntityDescriptor provider,
- boolean signResponse) throws SAMLException {
+ public static void signAssertions(SAMLAssertion[] assertions, RelyingParty relyingParty)
+ throws InvalidCryptoException, SAMLException {
- if (provider != null) {
- boolean signAssertions = false;
-
- SPSSODescriptor sp = provider.getSPSSODescriptor(org.opensaml.XML.SAML11_PROTOCOL_ENUM);
- if (sp == null) {
- log.info("Inappropriate metadata for provider: " + provider.getId() + ". Expected SPSSODescriptor.");
- }
- if (sp.getWantAssertionsSigned()) {
- signAssertions = true;
- }
-
- if (signAssertions && relyingParty.getIdentityProvider().getSigningCredential() != null
- && relyingParty.getIdentityProvider().getSigningCredential().getPrivateKey() != null) {
-
- Iterator assertions = response.getAssertions();
-
- while (assertions.hasNext()) {
- SAMLAssertion assertion = (SAMLAssertion) assertions.next();
- String assertionAlgorithm;
- if (relyingParty.getIdentityProvider().getSigningCredential().getCredentialType() == Credential.RSA) {
- assertionAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
- } else if (relyingParty.getIdentityProvider().getSigningCredential().getCredentialType() == Credential.DSA) {
- assertionAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_DSA;
- } else {
- throw new InvalidCryptoException(SAMLException.RESPONDER,
- "The Shibboleth IdP currently only supports signing with RSA and DSA keys.");
- }
-
- assertion.sign(assertionAlgorithm, relyingParty.getIdentityProvider().getSigningCredential()
- .getPrivateKey(), Arrays.asList(relyingParty.getIdentityProvider().getSigningCredential()
- .getX509CertificateChain()));
- }
- }
+ if (relyingParty.getIdentityProvider().getSigningCredential() == null
+ || relyingParty.getIdentityProvider().getSigningCredential().getPrivateKey() == null) {
+ // TODO error out
}
- // Sign the response, if appropriate
- if (signResponse && relyingParty.getIdentityProvider().getSigningCredential() != null
- && relyingParty.getIdentityProvider().getSigningCredential().getPrivateKey() != null) {
-
- String responseAlgorithm;
+ for (int i = 0; i < assertions.length; i++) {
+ String assertionAlgorithm;
if (relyingParty.getIdentityProvider().getSigningCredential().getCredentialType() == Credential.RSA) {
- responseAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
+ assertionAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
} else if (relyingParty.getIdentityProvider().getSigningCredential().getCredentialType() == Credential.DSA) {
- responseAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_DSA;
+ assertionAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_DSA;
} else {
throw new InvalidCryptoException(SAMLException.RESPONDER,
"The Shibboleth IdP currently only supports signing with RSA and DSA keys.");
}
- response.sign(responseAlgorithm, relyingParty.getIdentityProvider().getSigningCredential().getPrivateKey(),
- Arrays.asList(relyingParty.getIdentityProvider().getSigningCredential().getX509CertificateChain()));
+ assertions[i].sign(assertionAlgorithm, relyingParty.getIdentityProvider().getSigningCredential()
+ .getPrivateKey(), Arrays.asList(relyingParty.getIdentityProvider().getSigningCredential()
+ .getX509CertificateChain()));
+ }
+ }
+
+ public static void signResponse(SAMLResponse response, RelyingParty relyingParty) throws SAMLException {
+
+ // Make sure we have an appropriate credential
+ if (relyingParty.getIdentityProvider().getSigningCredential() == null
+ || relyingParty.getIdentityProvider().getSigningCredential().getPrivateKey() == null) {
+
+ // TODO error
}
+
+ // Sign the response
+ String responseAlgorithm;
+ if (relyingParty.getIdentityProvider().getSigningCredential().getCredentialType() == Credential.RSA) {
+ responseAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
+ } else if (relyingParty.getIdentityProvider().getSigningCredential().getCredentialType() == Credential.DSA) {
+ responseAlgorithm = XMLSignature.ALGO_ID_SIGNATURE_DSA;
+ } else {
+ throw new InvalidCryptoException(SAMLException.RESPONDER,
+ "The Shibboleth IdP currently only supports signing with RSA and DSA keys.");
+ }
+
+ response.sign(responseAlgorithm, relyingParty.getIdentityProvider().getSigningCredential().getPrivateKey(),
+ Arrays.asList(relyingParty.getIdentityProvider().getSigningCredential().getX509CertificateChain()));
}
protected void addFederationProvider(Element element) {
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
+import java.util.List;
import java.util.Vector;
import javax.servlet.RequestDispatcher;
}
// Grab the metadata for the provider
- EntityDescriptor provider = support.lookup(relyingParty.getProviderId());
+ EntityDescriptor descriptor = support.lookup(relyingParty.getProviderId());
// Make sure that the selected relying party configuration is appropriate for this
// acceptance URL
String acceptanceURL = request.getParameter("shire");
if (!relyingParty.isLegacyProvider()) {
- if (provider == null) {
+ if (descriptor == null) {
log.info("No metadata found for provider: (" + relyingParty.getProviderId() + ").");
relyingParty = support.getServiceProviderMapper().getRelyingParty(null);
} else {
- if (isValidAssertionConsumerURL(provider, acceptanceURL)) {
+ if (isValidAssertionConsumerURL(descriptor, acceptanceURL)) {
log.info("Supplied consumer URL validated for this provider.");
} else {
log.error("Assertion consumer service URL (" + acceptanceURL + ") is NOT valid for provider ("
ArrayList assertions = new ArrayList();
// Is this artifact or POST?
- boolean artifactProfile = useArtifactProfile(provider, acceptanceURL, relyingParty);
-
- // TODO make sure we support adding signatures to attribute assertion
+ boolean artifactProfile = useArtifactProfile(descriptor, acceptanceURL, relyingParty);
// Package attributes for push, if necessary - don't attempt this for legacy providers (they don't support
// it)
}
}
- // TODO do assertion signing for artifact stuff
-
// SAML Artifact profile - don't even attempt this for legacy providers (they don't support it)
if (!relyingParty.isLegacyProvider() && artifactProfile) {
- respondWithArtifact(request, response, support, principal, relyingParty, provider, acceptanceURL,
+ respondWithArtifact(request, response, support, principal, relyingParty, descriptor, acceptanceURL,
nameId, authenticationMethod, authNSubject, assertions);
// SAML POST profile
} else {
- respondWithPOST(request, response, support, principal, relyingParty, provider, acceptanceURL, nameId,
+ respondWithPOST(request, response, support, principal, relyingParty, descriptor, acceptanceURL, nameId,
authenticationMethod, authNSubject, assertions);
}
} catch (InvalidClientDataException e) {
}
private void respondWithArtifact(HttpServletRequest request, HttpServletResponse response,
- IdPProtocolSupport support, AuthNPrincipal principal, RelyingParty relyingParty, EntityDescriptor provider,
- String acceptanceURL, SAMLNameIdentifier nameId, String authenticationMethod, SAMLSubject authNSubject,
- ArrayList assertions) throws SAMLException, IOException, UnsupportedEncodingException {
+ IdPProtocolSupport support, AuthNPrincipal principal, RelyingParty relyingParty,
+ EntityDescriptor descriptor, String acceptanceURL, SAMLNameIdentifier nameId, String authenticationMethod,
+ SAMLSubject authNSubject, List assertions) throws SAMLException, IOException, UnsupportedEncodingException {
log.debug("Responding with Artifact profile.");
authNSubject.addConfirmationMethod(SAMLSubject.CONF_ARTIFACT);
- assertions.add(generateAuthNAssertion(request, relyingParty, provider, nameId, authenticationMethod, new Date(
- System.currentTimeMillis()), authNSubject));
+ assertions.add(generateAuthNAssertion(request, relyingParty, descriptor, nameId, authenticationMethod,
+ new Date(System.currentTimeMillis()), authNSubject));
+
+ // Sign the assertions, if necessary
+ boolean metaDataIndicatesSignAssertions = false;
+ if (descriptor != null) {
+ SPSSODescriptor sp = descriptor.getSPSSODescriptor(org.opensaml.XML.SAML11_PROTOCOL_ENUM);
+ if (sp != null) {
+ if (sp.getWantAssertionsSigned()) {
+ metaDataIndicatesSignAssertions = true;
+ }
+ }
+ }
+ if (relyingParty.wantsAssertionsSigned() || metaDataIndicatesSignAssertions) {
+ IdPProtocolSupport.signAssertions((SAMLAssertion[]) assertions.toArray(new SAMLAssertion[0]), relyingParty);
+ }
// Create artifacts for each assertion
ArrayList artifacts = new ArrayList();
}
private void respondWithPOST(HttpServletRequest request, HttpServletResponse response, IdPProtocolSupport support,
- AuthNPrincipal principal, RelyingParty relyingParty, EntityDescriptor provider, String acceptanceURL,
- SAMLNameIdentifier nameId, String authenticationMethod, SAMLSubject authNSubject, ArrayList assertions)
+ AuthNPrincipal principal, RelyingParty relyingParty, EntityDescriptor descriptor, String acceptanceURL,
+ SAMLNameIdentifier nameId, String authenticationMethod, SAMLSubject authNSubject, List assertions)
throws SAMLException, IOException, ServletException {
log.debug("Responding with POST profile.");
authNSubject.addConfirmationMethod(SAMLSubject.CONF_BEARER);
- assertions.add(generateAuthNAssertion(request, relyingParty, provider, nameId, authenticationMethod, new Date(
- System.currentTimeMillis()), authNSubject));
+ assertions.add(generateAuthNAssertion(request, relyingParty, descriptor, nameId, authenticationMethod,
+ new Date(System.currentTimeMillis()), authNSubject));
+
+ // Sign the assertions, if necessary
+ boolean metaDataIndicatesSignAssertions = false;
+ if (descriptor != null) {
+ SPSSODescriptor sp = descriptor.getSPSSODescriptor(org.opensaml.XML.SAML11_PROTOCOL_ENUM);
+ if (sp != null) {
+ if (sp.getWantAssertionsSigned()) {
+ metaDataIndicatesSignAssertions = true;
+ }
+ }
+ }
+ if (relyingParty.wantsAssertionsSigned() || metaDataIndicatesSignAssertions) {
+ IdPProtocolSupport.signAssertions((SAMLAssertion[]) assertions.toArray(new SAMLAssertion[0]), relyingParty);
+ }
// Set attributes needed by form
request.setAttribute("acceptanceURL", acceptanceURL);
SAMLResponse samlResponse = new SAMLResponse(null, acceptanceURL, assertions, null);
- IdPProtocolSupport.addSignatures(samlResponse, relyingParty, provider, true);
+ IdPProtocolSupport.signResponse(samlResponse, relyingParty);
createPOSTForm(request, response, samlResponse.toBase64());
}
private SAMLAssertion generateAuthNAssertion(HttpServletRequest request, RelyingParty relyingParty,
- EntityDescriptor provider, SAMLNameIdentifier nameId, String authenticationMethod, Date authTime,
+ EntityDescriptor descriptor, SAMLNameIdentifier nameId, String authenticationMethod, Date authTime,
SAMLSubject subject) throws SAMLException, IOException {
Document doc = org.opensaml.XML.parserPool.newDocument();
/**
* Boolean indication of which browser profile is in effect. "true" indicates Artifact and "false" indicates POST.
*/
- private static boolean useArtifactProfile(EntityDescriptor provider, String acceptanceURL, RelyingParty relyingParty) {
+ private static boolean useArtifactProfile(EntityDescriptor descriptor, String acceptanceURL,
+ RelyingParty relyingParty) {
boolean artifactMeta = false;
boolean postMeta = false;
// Look at the metadata bindings, if we can find them
- if (provider != null) {
- SPSSODescriptor sp = provider.getSPSSODescriptor(org.opensaml.XML.SAML11_PROTOCOL_ENUM);
+ if (descriptor != null) {
+ SPSSODescriptor sp = descriptor.getSPSSODescriptor(org.opensaml.XML.SAML11_PROTOCOL_ENUM);
if (sp != null) {
/**
* Boolean indication of whethere or not a given assertion consumer URL is valid for a given SP.
*/
- private static boolean isValidAssertionConsumerURL(EntityDescriptor provider, String shireURL)
+ private static boolean isValidAssertionConsumerURL(EntityDescriptor descriptor, String shireURL)
throws InvalidClientDataException {
- SPSSODescriptor sp = provider.getSPSSODescriptor(org.opensaml.XML.SAML11_PROTOCOL_ENUM);
+ SPSSODescriptor sp = descriptor.getSPSSODescriptor(org.opensaml.XML.SAML11_PROTOCOL_ENUM);
if (sp == null) {
log.info("Inappropriate metadata for provider.");
return false;