diff --git a/ivy.xml b/ivy.xml
index 4fc432d..ef31f6e 100644
--- a/ivy.xml
+++ b/ivy.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/pom.xml b/pom.xml
index d6b07d8..45e9f41 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,8 +10,8 @@
org.opensaml
- opensaml
- 2.6.4
+ opensaml-saml-impl
+ 3.1.1
\ No newline at end of file
diff --git a/src/main/java/com/lastpass/saml/IdPConfig.java b/src/main/java/com/lastpass/saml/IdPConfig.java
index 65d450b..764b637 100644
--- a/src/main/java/com/lastpass/saml/IdPConfig.java
+++ b/src/main/java/com/lastpass/saml/IdPConfig.java
@@ -26,23 +26,23 @@
import java.io.FileInputStream;
import java.io.InputStream;
-import org.opensaml.Configuration;
-import org.opensaml.xml.parse.BasicParserPool;
-import org.opensaml.xml.io.UnmarshallerFactory;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.IDPSSODescriptor;
-import org.opensaml.saml2.metadata.SingleSignOnService;
-import org.opensaml.saml2.metadata.KeyDescriptor;
-import org.opensaml.xml.signature.KeyInfo;
-import org.opensaml.xml.signature.X509Data;
-import org.opensaml.xml.signature.X509Certificate;
-import org.opensaml.xml.security.credential.UsageType;
-import org.opensaml.common.xml.SAMLConstants;
-
import javax.xml.bind.DatatypeConverter;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.xml.BasicParserPool;
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.config.SAMLConfiguration;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
+import org.opensaml.saml.saml2.metadata.KeyDescriptor;
+import org.opensaml.saml.saml2.metadata.SingleSignOnService;
+import org.opensaml.security.credential.UsageType;
+import org.opensaml.xmlsec.signature.KeyInfo;
+import org.opensaml.xmlsec.signature.X509Certificate;
+import org.opensaml.xmlsec.signature.X509Data;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
/**
@@ -110,30 +110,27 @@ private void init(InputStream inputStream)
{
BasicParserPool parsers = new BasicParserPool();
parsers.setNamespaceAware(true);
+ try {
+ parsers.initialize();
+ } catch (ComponentInitializationException e) {
+ throw new SAMLException("Failed to initialize BasicParserPool", e);
+ }
EntityDescriptor edesc;
try {
- Document doc = parsers.parse(inputStream);
- Element root = doc.getDocumentElement();
-
- UnmarshallerFactory unmarshallerFactory =
- Configuration.getUnmarshallerFactory();
-
- edesc = (EntityDescriptor) unmarshallerFactory
- .getUnmarshaller(root)
- .unmarshall(root);
+ edesc = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream(parsers, inputStream);
}
- catch (org.opensaml.xml.parse.XMLParserException e) {
+ catch (XMLParserException e) {
throw new SAMLException(e);
}
- catch (org.opensaml.xml.io.UnmarshallingException e) {
+ catch (UnmarshallingException e) {
throw new SAMLException(e);
}
// fetch idp information
IDPSSODescriptor idpDesc = edesc.getIDPSSODescriptor(
- "urn:oasis:names:tc:SAML:2.0:protocol");
+ SAMLConstants.SAML20P_NS);
if (idpDesc == null)
throw new SAMLException("No IDP SSO descriptor found");
diff --git a/src/main/java/com/lastpass/saml/SAMLClient.java b/src/main/java/com/lastpass/saml/SAMLClient.java
index 3991722..be6d1a0 100644
--- a/src/main/java/com/lastpass/saml/SAMLClient.java
+++ b/src/main/java/com/lastpass/saml/SAMLClient.java
@@ -17,41 +17,11 @@
*/
package com.lastpass.saml;
-import org.opensaml.Configuration;
-import org.opensaml.saml2.core.Response;
-import org.opensaml.saml2.core.Subject;
-import org.opensaml.saml2.core.Conditions;
-import org.opensaml.saml2.core.AuthnStatement;
-import org.opensaml.saml2.core.AuthnRequest;
-import org.opensaml.saml2.core.Assertion;
-import org.opensaml.saml2.core.Issuer;
-import org.opensaml.saml2.core.Audience;
-import org.opensaml.saml2.core.AudienceRestriction;
-import org.opensaml.saml2.core.StatusCode;
-import org.opensaml.saml2.core.SubjectConfirmation;
-import org.opensaml.saml2.core.SubjectConfirmationData;
-
-import org.opensaml.saml2.core.AttributeStatement;
-import org.opensaml.saml2.core.Attribute;
-
-import org.opensaml.common.SAMLObjectBuilder;
-
-import org.opensaml.xml.parse.BasicParserPool;
-import org.opensaml.xml.io.MarshallingException;
-import org.opensaml.xml.security.credential.BasicCredential;
-import org.opensaml.xml.signature.SignatureValidator;
-import org.opensaml.xml.signature.Signature;
-import org.opensaml.xml.validation.ValidationException;
-import org.opensaml.xml.XMLObjectBuilderFactory;
-import org.opensaml.xml.XMLObject;
+
import org.joda.time.DateTime;
-import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import org.w3c.dom.ls.DOMImplementationLS;
-import org.w3c.dom.ls.LSSerializer;
-import org.xml.sax.InputSource;
import java.io.StringReader;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
@@ -63,6 +33,34 @@
import java.util.zip.Deflater;
import javax.xml.bind.DatatypeConverter;
+import javax.xml.bind.ValidationException;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.xml.BasicParserPool;
+import net.shibboleth.utilities.java.support.xml.SerializeSupport;
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.saml2.core.Assertion;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.AttributeStatement;
+import org.opensaml.saml.saml2.core.Audience;
+import org.opensaml.saml.saml2.core.AudienceRestriction;
+import org.opensaml.saml.saml2.core.AuthnRequest;
+import org.opensaml.saml.saml2.core.AuthnStatement;
+import org.opensaml.saml.saml2.core.Conditions;
+import org.opensaml.saml.saml2.core.Issuer;
+import org.opensaml.saml.saml2.core.Response;
+import org.opensaml.saml.saml2.core.StatusCode;
+import org.opensaml.saml.saml2.core.Subject;
+import org.opensaml.saml.saml2.core.SubjectConfirmation;
+import org.opensaml.saml.saml2.core.SubjectConfirmationData;
+import org.opensaml.security.credential.BasicCredential;
+import org.opensaml.xmlsec.signature.Signature;
+import org.opensaml.xmlsec.signature.support.SignatureException;
+import org.opensaml.xmlsec.signature.support.SignatureValidator;
/**
@@ -90,12 +88,13 @@ public class SAMLClient
{
private SPConfig spConfig;
private IdPConfig idpConfig;
- private SignatureValidator sigValidator;
private BasicParserPool parsers;
+ private final BasicCredential cred;
/* do date comparisons +/- this many seconds */
private static final int slack = 300;
+
/**
* Create a new SAMLClient, using the IdPConfig for
* endpoints and validation.
@@ -106,15 +105,17 @@ public SAMLClient(SPConfig spConfig, IdPConfig idpConfig)
this.spConfig = spConfig;
this.idpConfig = idpConfig;
- BasicCredential cred = new BasicCredential();
- cred.setEntityId(idpConfig.getEntityId());
- cred.setPublicKey(idpConfig.getCert().getPublicKey());
-
- sigValidator = new SignatureValidator(cred);
+ cred = new BasicCredential(idpConfig.getCert().getPublicKey());
+ cred.setEntityId(idpConfig.getEntityId());
// create xml parsers
parsers = new BasicParserPool();
parsers.setNamespaceAware(true);
+ try {
+ parsers.initialize();
+ } catch (ComponentInitializationException e) {
+ throw new SAMLException("Failed to initialize BasicParserPool", e);
+ }
}
/**
@@ -141,26 +142,18 @@ private Response parseResponse(String authnResponse)
throws SAMLException
{
try {
- Document doc = parsers.getBuilder()
- .parse(new InputSource(new StringReader(authnResponse)));
+ XMLObject obj
+ = XMLObjectSupport.
+ unmarshallFromReader(parsers, new StringReader(authnResponse));
- Element root = doc.getDocumentElement();
- return (Response) Configuration.getUnmarshallerFactory()
- .getUnmarshaller(root)
- .unmarshall(root);
- }
- catch (org.opensaml.xml.parse.XMLParserException e) {
- throw new SAMLException(e);
+ return (Response) obj;
}
- catch (org.opensaml.xml.io.UnmarshallingException e) {
+ catch (XMLParserException e) {
throw new SAMLException(e);
}
- catch (org.xml.sax.SAXException e) {
+ catch (UnmarshallingException e) {
throw new SAMLException(e);
- }
- catch (java.io.IOException e) {
- throw new SAMLException(e);
- }
+ }
}
private void validate(Response response)
@@ -168,13 +161,19 @@ private void validate(Response response)
{
// response signature must match IdP's key, if present
Signature sig = response.getSignature();
- if (sig != null)
- sigValidator.validate(sig);
+ if (sig != null)
+ {
+ try {
+ SignatureValidator.validate(sig, cred);
+ } catch (SignatureException ex) {
+ throw new ValidationException("Signature validation failed", ex);
+ }
+ }
// response must be successful
if (response.getStatus() == null ||
response.getStatus().getStatusCode() == null ||
- !(StatusCode.SUCCESS_URI
+ !(StatusCode.SUCCESS
.equals(response.getStatus().getStatusCode().getValue()))) {
throw new ValidationException(
"Response has an unsuccessful status code");
@@ -208,7 +207,11 @@ private void validate(Response response)
"Assertion must be signed");
sig = assertion.getSignature();
- sigValidator.validate(sig);
+ try {
+ SignatureValidator.validate(sig, cred);
+ } catch (SignatureException e) {
+ throw new ValidationException("Assertion signature validation failed", e);
+ }
// Assertion must contain an authnstatement
// with an unexpired session
@@ -323,15 +326,12 @@ private void validate(Response response)
private String createAuthnRequest(String requestId)
throws SAMLException
{
- XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
-
SAMLObjectBuilder builder =
- (SAMLObjectBuilder) builderFactory
- .getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME);
+ (SAMLObjectBuilder)
+ XMLObjectSupport.getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME);
SAMLObjectBuilder issuerBuilder =
- (SAMLObjectBuilder) builderFactory
- .getBuilder(Issuer.DEFAULT_ELEMENT_NAME);
+ (SAMLObjectBuilder) XMLObjectSupport.getBuilder(Issuer.DEFAULT_ELEMENT_NAME);
AuthnRequest request = builder.buildObject();
request.setAssertionConsumerServiceURL(spConfig.getAcs().toString());
@@ -344,18 +344,9 @@ private String createAuthnRequest(String requestId)
request.setIssuer(issuer);
try {
- // samlobject to xml dom object
- Element elem = Configuration.getMarshallerFactory()
- .getMarshaller(request)
- .marshall(request);
-
- // and to a string...
- Document document = elem.getOwnerDocument();
- DOMImplementationLS domImplLS = (DOMImplementationLS) document
- .getImplementation();
- LSSerializer serializer = domImplLS.createLSSerializer();
- serializer.getDomConfig().setParameter("xml-declaration", false);
- return serializer.writeToString(elem);
+ Element element = XMLObjectSupport.marshall(request);
+
+ return SerializeSupport.nodeToString(element);
}
catch (MarshallingException e) {
throw new SAMLException(e);
diff --git a/src/main/java/com/lastpass/saml/SAMLInit.java b/src/main/java/com/lastpass/saml/SAMLInit.java
index 518671f..54121f3 100644
--- a/src/main/java/com/lastpass/saml/SAMLInit.java
+++ b/src/main/java/com/lastpass/saml/SAMLInit.java
@@ -17,8 +17,8 @@
*/
package com.lastpass.saml;
-import org.opensaml.DefaultBootstrap;
-import org.opensaml.xml.ConfigurationException;
+import org.opensaml.core.config.InitializationException;
+import org.opensaml.core.config.InitializationService;
/**
* Library initialization routines.
@@ -35,8 +35,8 @@ public static void initialize()
throws SAMLException
{
try {
- DefaultBootstrap.bootstrap();
- } catch (ConfigurationException e) {
+ InitializationService.initialize();
+ } catch (InitializationException e) {
throw new SAMLException(e);
}
}
diff --git a/src/main/java/com/lastpass/saml/SPConfig.java b/src/main/java/com/lastpass/saml/SPConfig.java
index 35fabec..5921db3 100644
--- a/src/main/java/com/lastpass/saml/SPConfig.java
+++ b/src/main/java/com/lastpass/saml/SPConfig.java
@@ -20,14 +20,17 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
-
-import org.opensaml.Configuration;
-import org.opensaml.xml.parse.BasicParserPool;
-import org.opensaml.xml.io.UnmarshallerFactory;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.saml2.metadata.AssertionConsumerService;
-import org.opensaml.common.xml.SAMLConstants;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.xml.BasicParserPool;
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+import org.opensaml.core.config.Configuration;
+import org.opensaml.core.xml.io.UnmarshallerFactory;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -102,30 +105,27 @@ private void init(InputStream inputStream)
{
BasicParserPool parsers = new BasicParserPool();
parsers.setNamespaceAware(true);
+ try {
+ parsers.initialize();
+ } catch (ComponentInitializationException e) {
+ throw new SAMLException("Failed to initialize BasicParserPool", e);
+ }
EntityDescriptor edesc;
try {
- Document doc = parsers.parse(inputStream);
- Element root = doc.getDocumentElement();
-
- UnmarshallerFactory unmarshallerFactory =
- Configuration.getUnmarshallerFactory();
-
- edesc = (EntityDescriptor) unmarshallerFactory
- .getUnmarshaller(root)
- .unmarshall(root);
+ edesc = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream(parsers, inputStream);
}
- catch (org.opensaml.xml.parse.XMLParserException e) {
+ catch (XMLParserException e) {
throw new SAMLException(e);
}
- catch (org.opensaml.xml.io.UnmarshallingException e) {
+ catch (UnmarshallingException e) {
throw new SAMLException(e);
}
// fetch sp information
SPSSODescriptor spDesc = edesc.getSPSSODescriptor(
- "urn:oasis:names:tc:SAML:2.0:protocol");
+ SAMLConstants.SAML20P_NS);
if (spDesc == null)
throw new SAMLException("No SP SSO descriptor found");