cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject [4/5] cxf-fediz git commit: FEDIZ-205 - Support creating IdP Metadata for SAML SSO
Date Wed, 09 Aug 2017 14:27:33 GMT
FEDIZ-205 - Support creating IdP Metadata for SAML SSO


Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/4808a7b4
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/4808a7b4
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/4808a7b4

Branch: refs/heads/master
Commit: 4808a7b49a7948e459c57d7ba1d228ea873cdcd7
Parents: 110cac0
Author: Colm O hEigeartaigh <coheigea@apache.org>
Authored: Wed Aug 9 12:41:34 2017 +0100
Committer: Colm O hEigeartaigh <coheigea@apache.org>
Committed: Wed Aug 9 12:41:34 2017 +0100

----------------------------------------------------------------------
 .../cxf/fediz/service/idp/MetadataServlet.java  |  9 +-
 .../service/idp/metadata/IdpMetadataWriter.java | 89 +++++++++++++++++---
 .../cxf/fediz/systests/samlsso/IdpTest.java     | 38 +++++++++
 3 files changed, 121 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/4808a7b4/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/MetadataServlet.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/MetadataServlet.java
b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/MetadataServlet.java
index 1077f8b..f09bd08 100644
--- a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/MetadataServlet.java
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/MetadataServlet.java
@@ -52,7 +52,6 @@ public class MetadataServlet extends HttpServlet {
     private ApplicationContext applicationContext;
     private String realm;
 
-
     @Override
     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException,
         IOException {
@@ -62,6 +61,8 @@ public class MetadataServlet extends HttpServlet {
         ConfigService cs = (ConfigService)getApplicationContext().getBean("config");
         Idp idpConfig = cs.getIDP(realm);
         try {
+            boolean isSamlRequest = request.getQueryString() != null
+                && request.getQueryString().contains("protocol=saml");
             if (request.getServletPath() != null && request.getServletPath().startsWith("/metadata"))
{
                 String parsedRealm =
                     request.getRequestURI().substring(request.getRequestURI().indexOf("/metadata")
@@ -73,7 +74,7 @@ public class MetadataServlet extends HttpServlet {
                 // Default to writing out the metadata for the IdP
                 if (idpConfig.getRealm().equals(parsedRealm) || parsedRealm == null || parsedRealm.isEmpty())
{
                     IdpMetadataWriter mw = new IdpMetadataWriter();
-                    Document metadata = mw.getMetaData(idpConfig);
+                    Document metadata = mw.getMetaData(idpConfig, isSamlRequest);
                     out.write(DOM2Writer.nodeToString(metadata));
                     return;
                 }
@@ -92,7 +93,7 @@ public class MetadataServlet extends HttpServlet {
                 // Otherwise return the Metadata for the Idp
                 LOG.debug(idpConfig.toString());
                 IdpMetadataWriter mw = new IdpMetadataWriter();
-                Document metadata = mw.getMetaData(idpConfig);
+                Document metadata = mw.getMetaData(idpConfig, isSamlRequest);
                 out.write(DOM2Writer.nodeToString(metadata));
             }
         } catch (Exception ex) {
@@ -118,4 +119,6 @@ public class MetadataServlet extends HttpServlet {
         return applicationContext;
     }
 
+
+
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/4808a7b4/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/metadata/IdpMetadataWriter.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/metadata/IdpMetadataWriter.java
b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/metadata/IdpMetadataWriter.java
index 97bcfcb..44eb6cb 100644
--- a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/metadata/IdpMetadataWriter.java
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/metadata/IdpMetadataWriter.java
@@ -46,8 +46,11 @@ public class IdpMetadataWriter {
 
     private static final Logger LOG = LoggerFactory.getLogger(IdpMetadataWriter.class);
 
-    //CHECKSTYLE:OFF
-    public Document getMetaData(Idp config) throws RuntimeException {
+    public Document getMetaData(Idp config) {
+        return getMetaData(config, false);
+    }
+
+    public Document getMetaData(Idp config, boolean saml) {
         try {
             //Return as text/xml
             Crypto crypto = CertsUtils.getCryptoFromFile(config.getCertificate());
@@ -63,12 +66,13 @@ public class IdpMetadataWriter {
             writer.writeAttribute("entityID", config.getIdpUrl().toString());
 
             writer.writeNamespace("md", SAML2_METADATA_NS);
-            writer.writeNamespace("fed", WS_FEDERATION_NS);
-            writer.writeNamespace("wsa", WS_ADDRESSING_NS);
-            writer.writeNamespace("auth", WS_FEDERATION_NS);
             writer.writeNamespace("xsi", SCHEMA_INSTANCE_NS);
 
-            writeFederationMetadata(writer, config, crypto);
+            if (saml) {
+                writeSAMLSSOMetadata(writer, config, crypto);
+            } else {
+                writeFederationMetadata(writer, config, crypto);
+            }
 
             writer.writeEndElement(); // EntityDescriptor
 
@@ -101,13 +105,17 @@ public class IdpMetadataWriter {
         XMLStreamWriter writer, Idp config, Crypto crypto
     ) throws XMLStreamException {
 
+        writer.writeNamespace("fed", WS_FEDERATION_NS);
+        writer.writeNamespace("wsa", WS_ADDRESSING_NS);
+        writer.writeNamespace("auth", WS_FEDERATION_NS);
+
         writer.writeStartElement("md", "RoleDescriptor", WS_FEDERATION_NS);
         writer.writeAttribute(SCHEMA_INSTANCE_NS, "type", "fed:SecurityTokenServiceType");
         writer.writeAttribute("protocolSupportEnumeration", WS_FEDERATION_NS);
-        if (config.getServiceDescription() != null && config.getServiceDescription().length()
> 0 ) {
+        if (config.getServiceDescription() != null && config.getServiceDescription().length()
> 0) {
             writer.writeAttribute("ServiceDescription", config.getServiceDescription());
         }
-        if (config.getServiceDisplayName() != null && config.getServiceDisplayName().length()
> 0 ) {
+        if (config.getServiceDisplayName() != null && config.getServiceDisplayName().length()
> 0) {
             writer.writeAttribute("ServiceDisplayName", config.getServiceDisplayName());
         }
 
@@ -115,11 +123,12 @@ public class IdpMetadataWriter {
         //missing organization, contactperson
 
         //KeyDescriptor
-        writer.writeStartElement("", "KeyDescriptor", SAML2_METADATA_NS);
+        writer.writeStartElement("md", "KeyDescriptor", SAML2_METADATA_NS);
         writer.writeAttribute("use", "signing");
-        writer.writeStartElement("", "KeyInfo", "http://www.w3.org/2000/09/xmldsig#");
-        writer.writeStartElement("", "X509Data", "http://www.w3.org/2000/09/xmldsig#");
-        writer.writeStartElement("", "X509Certificate", "http://www.w3.org/2000/09/xmldsig#");
+        writer.writeStartElement("ds", "KeyInfo", "http://www.w3.org/2000/09/xmldsig#");
+        writer.writeNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");
+        writer.writeStartElement("ds", "X509Data", "http://www.w3.org/2000/09/xmldsig#");
+        writer.writeStartElement("ds", "X509Certificate", "http://www.w3.org/2000/09/xmldsig#");
 
         try {
             String keyAlias = crypto.getDefaultX509Identifier();
@@ -176,5 +185,61 @@ public class IdpMetadataWriter {
         writer.writeEndElement(); // RoleDescriptor
     }
 
+    private void writeSAMLSSOMetadata(
+        XMLStreamWriter writer, Idp config, Crypto crypto
+    ) throws XMLStreamException {
+
+        writer.writeStartElement("md", "IDPSSODescriptor", SAML2_METADATA_NS);
+        writer.writeAttribute("WantAuthnRequestsSigned", "true");
+        writer.writeAttribute("protocolSupportEnumeration", "urn:oasis:names:tc:SAML:2.0:protocol");
+
+        //KeyDescriptor
+        writer.writeStartElement("md", "KeyDescriptor", SAML2_METADATA_NS);
+        writer.writeAttribute("use", "signing");
+        writer.writeStartElement("ds", "KeyInfo", "http://www.w3.org/2000/09/xmldsig#");
+        writer.writeNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");
+        writer.writeStartElement("ds", "X509Data", "http://www.w3.org/2000/09/xmldsig#");
+        writer.writeStartElement("ds", "X509Certificate", "http://www.w3.org/2000/09/xmldsig#");
+
+        try {
+            String keyAlias = crypto.getDefaultX509Identifier();
+            X509Certificate cert = CertsUtils.getX509CertificateFromCrypto(crypto, keyAlias);
+            writer.writeCharacters(Base64.encode(cert.getEncoded()));
+        } catch (Exception ex) {
+            LOG.error("Failed to add certificate information to metadata. Metadata incomplete",
ex);
+        }
+
+        writer.writeEndElement(); // X509Certificate
+        writer.writeEndElement(); // X509Data
+        writer.writeEndElement(); // KeyInfo
+        writer.writeEndElement(); // KeyDescriptor
+
+
+        writer.writeStartElement("md", "NameIDFormat", SAML2_METADATA_NS);
+        writer.writeCharacters("urn:oasis:names:tc:SAML:2.0:nameid-format:persistent");
+        writer.writeEndElement(); // NameIDFormat
+
+        writer.writeStartElement("md", "NameIDFormat", SAML2_METADATA_NS);
+        writer.writeCharacters("urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified");
+        writer.writeEndElement(); // NameIDFormat
+
+        writer.writeStartElement("md", "NameIDFormat", SAML2_METADATA_NS);
+        writer.writeCharacters("urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress");
+        writer.writeEndElement(); // NameIDFormat
+
+        // SingleSignOnService
+        writer.writeStartElement("md", "SingleSignOnService", SAML2_METADATA_NS);
+        writer.writeAttribute("Binding", "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect");
+        writer.writeAttribute("Location", config.getIdpUrl().toString());
+        writer.writeEndElement(); // SingleSignOnService
+
+        // SingleSignOnService
+        writer.writeStartElement("md", "SingleSignOnService", SAML2_METADATA_NS);
+        writer.writeAttribute("Binding", "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
+        writer.writeAttribute("Location", config.getIdpUrl().toString());
+        writer.writeEndElement(); // SingleSignOnService
+
+        writer.writeEndElement(); // IDPSSODescriptor
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/4808a7b4/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/IdpTest.java
----------------------------------------------------------------------
diff --git a/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/IdpTest.java
b/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/IdpTest.java
index 6542eed..d0fa7b9 100644
--- a/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/IdpTest.java
+++ b/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/IdpTest.java
@@ -37,6 +37,7 @@ import javax.servlet.ServletException;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
+import org.w3c.dom.Node;
 
 import com.gargoylesoftware.htmlunit.CookieManager;
 import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
@@ -47,6 +48,7 @@ import com.gargoylesoftware.htmlunit.html.DomElement;
 import com.gargoylesoftware.htmlunit.html.DomNodeList;
 import com.gargoylesoftware.htmlunit.html.HtmlPage;
 import com.gargoylesoftware.htmlunit.util.NameValuePair;
+import com.gargoylesoftware.htmlunit.xml.XmlPage;
 
 import org.apache.catalina.LifecycleException;
 import org.apache.catalina.LifecycleState;
@@ -68,10 +70,12 @@ import org.apache.wss4j.common.crypto.CryptoType;
 import org.apache.wss4j.common.saml.OpenSAMLUtil;
 import org.apache.wss4j.common.util.DOM2Writer;
 import org.apache.wss4j.dom.engine.WSSConfig;
+import org.apache.xml.security.signature.XMLSignature;
 import org.apache.xml.security.utils.Base64;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
+import org.junit.Test;
 import org.opensaml.core.xml.XMLObject;
 import org.opensaml.saml.common.SAMLVersion;
 import org.opensaml.saml.common.SignableSAMLObject;
@@ -216,6 +220,40 @@ public class IdpTest {
 
     }
     */
+
+    @Test
+    public void testIdPMetadata() throws Exception {
+        String url = "https://localhost:" + getIdpHttpsPort()
+            + "/fediz-idp/metadata?protocol=saml";
+
+        final WebClient webClient = new WebClient();
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getOptions().setSSLClientCertificate(
+            this.getClass().getClassLoader().getResource("client.jks"), "storepass", "jks");
+
+        final XmlPage rpPage = webClient.getPage(url);
+        final String xmlContent = rpPage.asXml();
+        Assert.assertTrue(xmlContent.startsWith("<md:EntityDescriptor"));
+
+        // Now validate the Signature
+        Document doc = rpPage.getXmlDocument();
+
+        doc.getDocumentElement().setIdAttributeNS(null, "ID", true);
+
+        Node signatureNode =
+            DOMUtils.getChild(doc.getDocumentElement(), "Signature");
+        Assert.assertNotNull(signatureNode);
+
+        XMLSignature signature = new XMLSignature((Element)signatureNode, "");
+        org.apache.xml.security.keys.KeyInfo ki = signature.getKeyInfo();
+        Assert.assertNotNull(ki);
+        Assert.assertNotNull(ki.getX509Certificate());
+
+        Assert.assertTrue(signature.checkSignatureValue(ki.getX509Certificate()));
+
+        webClient.close();
+    }
+
     @org.junit.Test
     public void testSuccessfulInvokeOnIdP() throws Exception {
         OpenSAMLUtil.initSamlEngine();


Mime
View raw message