You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2015/03/16 18:51:29 UTC

[1/4] cxf-fediz git commit: Adding a switch to sign a request to a trusted IdP

Repository: cxf-fediz
Updated Branches:
  refs/heads/master ecd25ab9d -> 799afc9a2


Adding a switch to sign a request to a trusted IdP


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

Branch: refs/heads/master
Commit: fd366100082d221c1c8b75cc85552b6d04ee4afc
Parents: ecd25ab
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Mar 16 15:55:50 2015 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Mar 16 15:55:50 2015 +0000

----------------------------------------------------------------------
 .../cxf/fediz/service/idp/domain/TrustedIdp.java       | 13 ++++++++++++-
 .../service/idp/service/jpa/TrustedIdpEntity.java      | 11 +++++++++++
 .../cxf/fediz/service/idp/util/MetadataWriter.java     |  3 ++-
 3 files changed, 25 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/fd366100/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustedIdp.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustedIdp.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustedIdp.java
index dbdea59..6469372 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustedIdp.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/TrustedIdp.java
@@ -26,7 +26,7 @@ import javax.xml.bind.annotation.XmlType;
 
 @XmlRootElement(name = "trustedIdp", namespace = "http://org.apache.cxf.fediz/")
 @XmlType(propOrder = {"realm", "url", "name", "description", "protocol", "trustType",
-                      "certificate", "federationType", "cacheTokens", "logo", "id" })
+                      "certificate", "federationType", "cacheTokens", "logo", "id", "signRequest" })
 //@XmlAttribute on Id must be set on getter, not on attribute, otherwise error
 public class TrustedIdp implements Serializable {
 
@@ -68,6 +68,9 @@ public class TrustedIdp implements Serializable {
     
     //optional (to provide a list of IDPs)
     protected String logo;
+    
+    // Whether to sign a request to the trusted IdP or not
+    private boolean signRequest;
 
     
     @XmlAttribute
@@ -158,6 +161,14 @@ public class TrustedIdp implements Serializable {
     public void setTrustType(TrustType trustType) {
         this.trustType = trustType;
     }
+
+    public boolean isSignRequest() {
+        return signRequest;
+    }
+
+    public void setSignRequest(boolean signRequest) {
+        this.signRequest = signRequest;
+    }
                
 
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/fd366100/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpEntity.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpEntity.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpEntity.java
index 7f41186..11785c7 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpEntity.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpEntity.java
@@ -76,6 +76,9 @@ public class TrustedIdpEntity {
     //optional (to provide a list of IDPs)
     private String logo;
     
+    // Whether to sign a request to the trusted IdP or not
+    private boolean signRequest;
+    
 
     public int getId() {
         return id;
@@ -165,4 +168,12 @@ public class TrustedIdpEntity {
         this.trustType = trustType;
     }
 
+    public boolean isSignRequest() {
+        return signRequest;
+    }
+
+    public void setSignRequest(boolean signRequest) {
+        this.signRequest = signRequest;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/fd366100/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/util/MetadataWriter.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/util/MetadataWriter.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/util/MetadataWriter.java
index bc34ab4..bcc7e37 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/util/MetadataWriter.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/util/MetadataWriter.java
@@ -104,7 +104,8 @@ public class MetadataWriter {
             writer.writeStartElement("", "X509Certificate", "http://www.w3.org/2000/09/xmldsig#");
             
             try {
-                X509Certificate cert = CertsUtils.getX509Certificate(crypto, null);
+                String keyAlias = crypto.getDefaultX509Identifier();
+                X509Certificate cert = CertsUtils.getX509Certificate(crypto, keyAlias);
                 writer.writeCharacters(Base64.encode(cert.getEncoded()));
             } catch (Exception ex) {
                 LOG.error("Failed to add certificate information to metadata. Metadata incomplete", ex);


[3/4] cxf-fediz git commit: Systest update as part of last commit

Posted by co...@apache.org.
Systest update as part of last commit


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

Branch: refs/heads/master
Commit: a18bc7c1667deaf9af6c352e0ae764a20ce95f31
Parents: 03d9a99
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Mar 16 16:24:50 2015 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Mar 16 16:24:50 2015 +0000

----------------------------------------------------------------------
 systests/federation/samlsso/src/test/resources/entities-realma.xml | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/a18bc7c1/systests/federation/samlsso/src/test/resources/entities-realma.xml
----------------------------------------------------------------------
diff --git a/systests/federation/samlsso/src/test/resources/entities-realma.xml b/systests/federation/samlsso/src/test/resources/entities-realma.xml
index 8f8f319..649b88c 100644
--- a/systests/federation/samlsso/src/test/resources/entities-realma.xml
+++ b/systests/federation/samlsso/src/test/resources/entities-realma.xml
@@ -88,6 +88,7 @@
         <property name="federationType" value="FEDERATE_IDENTITY" />
         <property name="name" value="Realm B" />
         <property name="description" value="Realm B description" />
+        <property name="signRequest" value="true" />
     </bean>
 
     <bean id="srv-fedizhelloworld" class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationEntity">


[4/4] cxf-fediz git commit: Properly validate SAML SSO responses

Posted by co...@apache.org.
Properly validate SAML SSO responses


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

Branch: refs/heads/master
Commit: 799afc9a2ad771eebc42533c6d4727642948ca42
Parents: a18bc7c
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Mar 16 17:45:50 2015 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Mar 16 17:45:50 2015 +0000

----------------------------------------------------------------------
 .../TrustedIdpSAMLProtocolHandler.java          | 222 +++++++------------
 1 file changed, 80 insertions(+), 142 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/799afc9a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
index 18465f8..2cc03c3 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
@@ -19,7 +19,6 @@
 
 package org.apache.cxf.fediz.service.idp.protocols;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -29,6 +28,8 @@ import java.net.URL;
 import java.net.URLEncoder;
 import java.security.PrivateKey;
 import java.security.Signature;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.util.zip.DataFormatException;
 
@@ -38,10 +39,12 @@ import javax.ws.rs.core.UriBuilder;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
+
 import org.apache.cxf.common.util.Base64Exception;
 import org.apache.cxf.common.util.Base64Utility;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.fediz.core.FederationConstants;
+import org.apache.cxf.fediz.core.exception.ProcessingException;
 import org.apache.cxf.fediz.core.util.CertsUtils;
 import org.apache.cxf.fediz.service.idp.domain.Idp;
 import org.apache.cxf.fediz.service.idp.domain.TrustedIdp;
@@ -52,15 +55,18 @@ import org.apache.cxf.jaxrs.utils.ExceptionUtils;
 import org.apache.cxf.rs.security.saml.DeflateEncoderDecoder;
 import org.apache.cxf.rs.security.saml.sso.AuthnRequestBuilder;
 import org.apache.cxf.rs.security.saml.sso.DefaultAuthnRequestBuilder;
+import org.apache.cxf.rs.security.saml.sso.SAMLProtocolResponseValidator;
+import org.apache.cxf.rs.security.saml.sso.SAMLSSOResponseValidator;
 import org.apache.cxf.rs.security.saml.sso.SSOConstants;
+import org.apache.cxf.rs.security.saml.sso.SSOValidatorResponse;
 import org.apache.cxf.staxutils.StaxUtils;
 import org.apache.cxf.ws.security.tokenstore.SecurityToken;
+import org.apache.wss4j.common.crypto.CertificateStore;
 import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.crypto.Merlin;
 import org.apache.wss4j.common.ext.WSSecurityException;
 import org.apache.wss4j.common.saml.OpenSAMLUtil;
 import org.apache.wss4j.common.util.DOM2Writer;
-import org.apache.wss4j.common.util.XMLUtils;
-import org.apache.wss4j.dom.WSConstants;
 import org.apache.xml.security.stax.impl.util.IDGenerator;
 import org.apache.xml.security.utils.Base64;
 import org.opensaml.saml2.core.AuthnRequest;
@@ -147,37 +153,29 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
     public SecurityToken mapSignInResponse(RequestContext context, Idp idp, TrustedIdp trustedIdp) {
 
         try {
-            String relayState = (String) WebUtils.getAttributeFromFlowScope(context,
-                                                                            SSOConstants.RELAY_STATE);
+            //String relayState = (String) WebUtils.getAttributeFromFlowScope(context,
+            //                                                                SSOConstants.RELAY_STATE);
             // TODO Validate RelayState
-            System.out.println("RS: " + relayState);
 
             String encodedSAMLResponse = (String) WebUtils.getAttributeFromFlowScope(context, 
                                                                                      SSOConstants.SAML_RESPONSE);
             
             // Read the response + convert to an OpenSAML Response Object
-            Element responseElement = readSAMLResponse(false, encodedSAMLResponse);
-            // org.opensaml.saml2.core.Response samlResponse = convertToResponse(responseElement);
-
+            org.opensaml.saml2.core.Response samlResponse = readSAMLResponse(encodedSAMLResponse);
+            
+            Crypto crypto = getCrypto(trustedIdp.getCertificate());
+            validateSamlResponseProtocol(samlResponse, crypto);
             // Validate the Response
-            /*
-             * TODOvalidateSamlResponseProtocol(samlResponse);
             SSOValidatorResponse validatorResponse = 
-                validateSamlSSOResponse(false, samlResponse, requestState);
+                validateSamlSSOResponse(samlResponse, idp, trustedIdp, context);
 
-            String assertion = validatorResponse.getAssertion();
-            SamlAssertionWrapper wrapper = new SamlAssertionWrapper(assertion);
-            */
-            Element assertionElement = 
-                XMLUtils.getDirectChildElement(responseElement, "Assertion", WSConstants.SAML2_NS);
             // Create new Security token with new id. 
             // Parameters for freshness computation are copied from original IDP_TOKEN
             String id = IDGenerator.generateID("_");
-            SecurityToken idpToken = new SecurityToken(id);
-                // new SecurityToken(id, new Date(), validatorResponse.getSessionNotOnOrAfter());
-            // TODO new Date() above incorrect
+            SecurityToken idpToken = 
+                new SecurityToken(id, validatorResponse.getCreated(), validatorResponse.getSessionNotOnOrAfter());
 
-            idpToken.setToken(assertionElement);
+            idpToken.setToken(validatorResponse.getAssertionElement());
             // LOG.info("[IDP_TOKEN={}] for user '{}' created from [RP_TOKEN={}] issued by home realm [{}/{}]",
             //         id, wfResp.getUsername(), wfResp.getUniqueTokenId(), whr, wfResp.getIssuer());
             //.debug("Created date={}", wfResp.getTokenCreated());
@@ -213,7 +211,7 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
         Idp config,
         UriBuilder ub
     ) throws Exception {
-        Crypto crypto = CertsUtils.createCrypto(config.getCertificate());
+        Crypto crypto = getCrypto(config.getCertificate());
         if (crypto == null) {
             LOG.error("No crypto instance of properties file configured for signature");
             throw new IllegalStateException("Invalid IdP configuration");
@@ -261,44 +259,57 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
         ub.queryParam(SSOConstants.SIGNATURE, URLEncoder.encode(encodedSignature, "UTF-8"));
     }
 
-
-    private Element readSAMLResponse(
-        boolean postBinding, String samlResponse
-    ) {
+    private Crypto getCrypto(String certificate) throws ProcessingException {
+        if (certificate == null) {
+            return null;
+        }
+        
+        // First see if it's a certificate file
+        InputStream is = null;
+        try {
+            is = Merlin.loadInputStream(Thread.currentThread().getContextClassLoader(), certificate);
+        
+            CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+            X509Certificate cert = (X509Certificate) certFactory.generateCertificate(is);
+            return new CertificateStore(new X509Certificate[]{cert});
+        } catch (WSSecurityException ex) {
+            LOG.error("Failed to load keystore " + certificate, ex);
+            throw new RuntimeException("Failed to load keystore " + certificate);
+        } catch (IOException ex) {
+            LOG.error("Failed to read keystore", ex);
+            throw new RuntimeException("Failed to read keystore");
+        } catch (CertificateException ex) {
+            // This is ok as it could be a WSS4J properties file
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                    // Do nothing
+                }
+            }
+        }
+        
+        // Maybe it's a WSS4J properties file...
+        return CertsUtils.createCrypto(certificate);
+    }
+    
+    private org.opensaml.saml2.core.Response readSAMLResponse(String samlResponse) {
         if (StringUtils.isEmpty(samlResponse)) {
             throw ExceptionUtils.toBadRequestException(null, null);
         }
 
         String samlResponseDecoded = samlResponse;
-        /*
-            // URL Decoding only applies for the re-direct binding
-            if (!postBinding) {
-            try {
-                samlResponseDecoded = URLDecoder.decode(samlResponse, "UTF-8");
-                } catch (UnsupportedEncodingException e) {
-                    throw ExceptionUtils.toBadRequestException(null, null);
-                }
-            }
-         */
+        
         InputStream tokenStream = null;
-        // (isSupportBase64Encoding()) { TODO
         try {
             byte[] deflatedToken = Base64Utility.decode(samlResponseDecoded);
-            tokenStream = !postBinding //&& isSupportDeflateEncoding() 
-                ? new DeflateEncoderDecoder().inflateToken(deflatedToken)
-                    : new ByteArrayInputStream(deflatedToken); 
+            tokenStream = new DeflateEncoderDecoder().inflateToken(deflatedToken); 
         } catch (Base64Exception ex) {
             throw ExceptionUtils.toBadRequestException(ex, null);
         } catch (DataFormatException ex) {
             throw ExceptionUtils.toBadRequestException(ex, null);
         }
-        /*} else { TODO
-            try {
-                tokenStream = new ByteArrayInputStream(samlResponseDecoded.getBytes("UTF-8"));
-            } catch (UnsupportedEncodingException ex) {
-                throw ExceptionUtils.toBadRequestException(ex, null);
-            }
-        }*/
 
         Document responseDoc = null;
         try {
@@ -306,17 +317,12 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
         } catch (Exception ex) {
             throw new WebApplicationException(400);
         }
-
+        
         LOG.debug("Received response: " + DOM2Writer.nodeToString(responseDoc.getDocumentElement()));
         
-        return responseDoc.getDocumentElement();
-
-    }
-    
-    protected org.opensaml.saml2.core.Response convertToResponse(Element samlResponseElement) {
         XMLObject responseObject = null;
         try {
-            responseObject = OpenSAMLUtil.fromDom(samlResponseElement);
+            responseObject = OpenSAMLUtil.fromDom(responseDoc.getDocumentElement());
         } catch (WSSecurityException ex) {
             throw ExceptionUtils.toBadRequestException(ex, null);
         }
@@ -324,122 +330,54 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
             throw ExceptionUtils.toBadRequestException(null, null);
         }
         return (org.opensaml.saml2.core.Response)responseObject;
-    }
 
+    }
+    
     /**
      * Validate the received SAML Response as per the protocol
-    protected void validateSamlResponseProtocol(
-        org.opensaml.saml2.core.Response samlResponse
+     */
+    private void validateSamlResponseProtocol(
+        org.opensaml.saml2.core.Response samlResponse, Crypto crypto
     ) {
         try {
             SAMLProtocolResponseValidator protocolValidator = new SAMLProtocolResponseValidator();
-            protocolValidator.setKeyInfoMustBeAvailable(true); // TODO
-            protocolValidator.validateSamlResponse(samlResponse, getSignatureCrypto(), null);
+            protocolValidator.setKeyInfoMustBeAvailable(true);
+            protocolValidator.validateSamlResponse(samlResponse, crypto, null);
         } catch (WSSecurityException ex) {
             LOG.debug(ex.getMessage(), ex);
+            ex.printStackTrace();
             throw ExceptionUtils.toBadRequestException(null, null);
         }
     }
-    */
+    
     /**
      * Validate the received SAML Response as per the Web SSO profile
-    protected SSOValidatorResponse validateSamlSSOResponse(
-        boolean postBinding,
+     */
+    private SSOValidatorResponse validateSamlSSOResponse(
         org.opensaml.saml2.core.Response samlResponse,
         Idp idp, 
-        TrustedIdp trustedIdp
+        TrustedIdp trustedIdp,
+        RequestContext requestContext
     ) {
         try {
             SAMLSSOResponseValidator ssoResponseValidator = new SAMLSSOResponseValidator();
-            ssoResponseValidator.setAssertionConsumerURL(idp.getIdpUrl());
+            ssoResponseValidator.setAssertionConsumerURL(idp.getIdpUrl().toString());
 
-            // ssoResponseValidator.setClientAddress(client_ip);
+            HttpServletRequest servletRequest = WebUtils.getHttpServletRequest(requestContext);
+            ssoResponseValidator.setClientAddress(servletRequest.getRemoteAddr());
 
             ssoResponseValidator.setIssuerIDP(trustedIdp.getUrl());
-            // ssoResponseValidator.setRequestId(requestState.getSamlRequestId());
+            // TODO ssoResponseValidator.setRequestId(requestState.getSamlRequestId());
             ssoResponseValidator.setSpIdentifier(idp.getRealm());
-            ssoResponseValidator.setEnforceAssertionsSigned(true); // TODO
-            // ssoResponseValidator.setEnforceKnownIssuer(enforceKnownIssuer);
+            ssoResponseValidator.setEnforceAssertionsSigned(true);
+            ssoResponseValidator.setEnforceKnownIssuer(true);
 
-            return ssoResponseValidator.validateSamlResponse(samlResponse, postBinding);
+            return ssoResponseValidator.validateSamlResponse(samlResponse, false);
         } catch (WSSecurityException ex) {
             LOG.debug(ex.getMessage(), ex);
             throw ExceptionUtils.toBadRequestException(ex, null);
         }
     }
-    */
-
-/*
-    private FedizContext getFedizContext(Idp idpConfig,
-                                         TrustedIdp trustedIdpConfig) throws ProcessingException {
-
-        ContextConfig config = new ContextConfig();
-
-        config.setName("whatever");
-
-        // Configure certificate store
-        String certificate = trustedIdpConfig.getCertificate();
-        boolean isCertificateLocation = !certificate.startsWith("-----BEGIN CERTIFICATE");
-        if (isCertificateLocation) {
-            CertificateStores certStores = new CertificateStores();
-            TrustManagersType tm0 = new TrustManagersType();
-            KeyStoreType ks0 = new KeyStoreType();
-            ks0.setType("PEM");
-            // ks0.setType("JKS");
-            // ks0.setPassword("changeit");
-            ks0.setFile(trustedIdpConfig.getCertificate());
-            tm0.setKeyStore(ks0);
-            certStores.getTrustManager().add(tm0);
-            config.setCertificateStores(certStores);
-        }
-
-        // Configure trusted IDP
-        TrustedIssuers trustedIssuers = new TrustedIssuers();
-        TrustedIssuerType ti0 = new TrustedIssuerType();
-        ti0.setCertificateValidation(ValidationType.PEER_TRUST);
-        ti0.setName(trustedIdpConfig.getName());
-        // ti0.setSubject(".*CN=www.sts.com.*");
-        trustedIssuers.getIssuer().add(ti0);
-        config.setTrustedIssuers(trustedIssuers);
-
-        FederationProtocolType protocol = new FederationProtocolType();
-        config.setProtocol(protocol);
-
-        AudienceUris audienceUris = new AudienceUris();
-        audienceUris.getAudienceItem().add(idpConfig.getRealm());
-        config.setAudienceUris(audienceUris);
-
-        FedizContext fedContext = new FedizContext(config);
-        if (!isCertificateLocation) {
-            CertificateStore cs = null;
-
-            X509Certificate cert;
-            try {
-                cert = parseCertificate(trustedIdpConfig.getCertificate());
-            } catch (Exception ex) {
-                LOG.error("Failed to parse trusted certificate", ex);
-                throw new ProcessingException("Failed to parse trusted certificate");
-            }
-            cs = new CertificateStore(Collections.singletonList(cert).toArray(new X509Certificate[0]));
-
-            TrustManager tm = new TrustManager(cs);
-            fedContext.getCertificateStores().add(tm);
-        }
 
-        fedContext.init();
-        return fedContext;
-    }
-
-    private X509Certificate parseCertificate(String certificate)
-        throws CertificateException, Base64DecodingException {
-
-        //before decoding we need to get rod off the prefix and suffix
-        byte [] decoded = Base64.decode(certificate.replaceAll("-----BEGIN CERTIFICATE-----", "").
-                                        replaceAll("-----END CERTIFICATE-----", ""));
-
-        return (X509Certificate)CertificateFactory.getInstance("X.509").
-            generateCertificate(new ByteArrayInputStream(decoded));
-    }
-*/
 
 }


[2/4] cxf-fediz git commit: Add the ability to sign SAML SSO requests

Posted by co...@apache.org.
Add the ability to sign SAML SSO requests


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

Branch: refs/heads/master
Commit: 03d9a99c93dccf8d4faf17722ef26d0e7d858f30
Parents: fd36610
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Mar 16 16:24:16 2015 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Mar 16 16:24:16 2015 +0000

----------------------------------------------------------------------
 .../TrustedIdpSAMLProtocolHandler.java          | 102 +++++++++++++++----
 .../idp/service/jpa/TrustedIdpDAOJPAImpl.java   |   5 +-
 2 files changed, 85 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/03d9a99c/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
index e1b8879..18465f8 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java
@@ -27,6 +27,9 @@ import java.io.UnsupportedEncodingException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLEncoder;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.cert.X509Certificate;
 import java.util.zip.DataFormatException;
 
 import javax.servlet.http.HttpServletRequest;
@@ -39,6 +42,7 @@ import org.apache.cxf.common.util.Base64Exception;
 import org.apache.cxf.common.util.Base64Utility;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.fediz.core.FederationConstants;
+import org.apache.cxf.fediz.core.util.CertsUtils;
 import org.apache.cxf.fediz.service.idp.domain.Idp;
 import org.apache.cxf.fediz.service.idp.domain.TrustedIdp;
 import org.apache.cxf.fediz.service.idp.spi.TrustedIdpProtocolHandler;
@@ -51,12 +55,14 @@ import org.apache.cxf.rs.security.saml.sso.DefaultAuthnRequestBuilder;
 import org.apache.cxf.rs.security.saml.sso.SSOConstants;
 import org.apache.cxf.staxutils.StaxUtils;
 import org.apache.cxf.ws.security.tokenstore.SecurityToken;
+import org.apache.wss4j.common.crypto.Crypto;
 import org.apache.wss4j.common.ext.WSSecurityException;
 import org.apache.wss4j.common.saml.OpenSAMLUtil;
 import org.apache.wss4j.common.util.DOM2Writer;
 import org.apache.wss4j.common.util.XMLUtils;
 import org.apache.wss4j.dom.WSConstants;
 import org.apache.xml.security.stax.impl.util.IDGenerator;
+import org.apache.xml.security.utils.Base64;
 import org.opensaml.saml2.core.AuthnRequest;
 import org.opensaml.xml.XMLObject;
 import org.slf4j.Logger;
@@ -100,9 +106,9 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
                 authnRequestBuilder.createAuthnRequest(
                     null, idp.getRealm(), idp.getIdpUrl().toString()
                 );
-            // if (isSignRequest()) {
-            //    authnRequest.setDestination(idpServiceAddress);
-            //}
+            if (trustedIdp.isSignRequest()) {
+                authnRequest.setDestination(trustedIdp.getUrl());
+            }
             Element authnRequestElement = OpenSAMLUtil.toDom(authnRequest, doc);
             String authnRequestEncoded = encodeAuthnRequest(authnRequestElement);
 
@@ -116,15 +122,13 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
             if (wctx != null) {
                 ub.queryParam(SSOConstants.RELAY_STATE, wctx);
             }
-            //if (isSignRequest()) {
-            //    signRequest(urlEncodedRequest, info.getRelayState(), ub);
-            //}
-
-            /*context.abortWith(Response.seeOther(ub.build())
-                           .header(HttpHeaders.CACHE_CONTROL, "no-cache, no-store")
-                           .header("Pragma", "no-cache") 
-                           .build());*/
+            if (trustedIdp.isSignRequest()) {
+                signRequest(urlEncodedRequest, wctx, idp, ub);
+            }
 
+            // TODO How to set headers here?
+            // .header(HttpHeaders.CACHE_CONTROL, "no-cache, no-store")
+            // .header("Pragma", "no-cache") 
             return ub.build().toURL();
         } catch (MalformedURLException ex) {
             LOG.error("Invalid Redirect URL for Trusted Idp", ex);
@@ -139,15 +143,6 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
     }
 
 
-    protected String encodeAuthnRequest(Element authnRequest) throws IOException {
-        String requestMessage = DOM2Writer.nodeToString(authnRequest);
-
-        DeflateEncoderDecoder encoder = new DeflateEncoderDecoder();
-        byte[] deflatedBytes = encoder.deflateToken(requestMessage.getBytes("UTF-8"));
-
-        return Base64Utility.encode(deflatedBytes);
-    }
-
     @Override
     public SecurityToken mapSignInResponse(RequestContext context, Idp idp, TrustedIdp trustedIdp) {
 
@@ -199,6 +194,73 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler
             throw new IllegalStateException("Unexpected exception occured: " + ex.getMessage());
         }
     }
+    
+    private String encodeAuthnRequest(Element authnRequest) throws IOException {
+        String requestMessage = DOM2Writer.nodeToString(authnRequest);
+
+        DeflateEncoderDecoder encoder = new DeflateEncoderDecoder();
+        byte[] deflatedBytes = encoder.deflateToken(requestMessage.getBytes("UTF-8"));
+
+        return Base64Utility.encode(deflatedBytes);
+    }
+    
+    /**
+     * Sign a request according to the redirect binding spec for Web SSO
+     */
+    private void signRequest(
+        String authnRequest,
+        String relayState,
+        Idp config,
+        UriBuilder ub
+    ) throws Exception {
+        Crypto crypto = CertsUtils.createCrypto(config.getCertificate());
+        if (crypto == null) {
+            LOG.error("No crypto instance of properties file configured for signature");
+            throw new IllegalStateException("Invalid IdP configuration");
+        }
+        
+        String alias = crypto.getDefaultX509Identifier();
+        X509Certificate cert = CertsUtils.getX509Certificate(crypto, alias);
+        if (cert == null) {
+            LOG.error("No cert was found to sign the request using alias: " + alias);
+            throw new IllegalStateException("Invalid IdP configuration");
+        }
+
+        String sigAlgo = SSOConstants.RSA_SHA1;
+        String pubKeyAlgo = cert.getPublicKey().getAlgorithm();
+        String jceSigAlgo = "SHA1withRSA";
+        LOG.debug("automatic sig algo detection: " + pubKeyAlgo);
+        if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
+            sigAlgo = SSOConstants.DSA_SHA1;
+            jceSigAlgo = "SHA1withDSA";
+        }
+        LOG.debug("Using Signature algorithm " + sigAlgo);
+        
+        ub.queryParam(SSOConstants.SIG_ALG, URLEncoder.encode(sigAlgo, "UTF-8"));
+        
+        // Get the password
+        String password = config.getCertificatePassword();
+        
+        // Get the private key
+        PrivateKey privateKey = crypto.getPrivateKey(alias, password);
+        
+        // Sign the request
+        Signature signature = Signature.getInstance(jceSigAlgo);
+        signature.initSign(privateKey);
+       
+        String requestToSign = 
+            SSOConstants.SAML_REQUEST + "=" + authnRequest + "&"
+            + SSOConstants.RELAY_STATE + "=" + relayState + "&"
+            + SSOConstants.SIG_ALG + "=" + URLEncoder.encode(sigAlgo, "UTF-8");
+
+        signature.update(requestToSign.getBytes("UTF-8"));
+        byte[] signBytes = signature.sign();
+        
+        String encodedSignature = Base64.encode(signBytes);
+        
+        ub.queryParam(SSOConstants.SIGNATURE, URLEncoder.encode(encodedSignature, "UTF-8"));
+    }
+
 
     private Element readSAMLResponse(
         boolean postBinding, String samlResponse

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/03d9a99c/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpDAOJPAImpl.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpDAOJPAImpl.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpDAOJPAImpl.java
index 8d0f208..a7b5472 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpDAOJPAImpl.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/TrustedIdpDAOJPAImpl.java
@@ -54,8 +54,7 @@ public class TrustedIdpDAOJPAImpl implements TrustedIdpDAO {
         Query query = null;
         query = em.createQuery("select t from TrustedIDP t");
         
-        //@SuppressWarnings("rawtypes")
-        List idpEntities = query
+        List<?> idpEntities = query
             .setFirstResult(start)
             .setMaxResults(size)
             .getResultList();
@@ -130,6 +129,7 @@ public class TrustedIdpDAOJPAImpl implements TrustedIdpDAO {
         entity.setRealm(trustedIDP.getRealm());
         entity.setTrustType(trustedIDP.getTrustType());
         entity.setUrl(trustedIDP.getUrl());
+        entity.setSignRequest(trustedIDP.isSignRequest());
     }
     
     public static TrustedIdp entity2domain(TrustedIdpEntity entity) {
@@ -145,6 +145,7 @@ public class TrustedIdpDAOJPAImpl implements TrustedIdpDAO {
         trustedIDP.setRealm(entity.getRealm());
         trustedIDP.setTrustType(entity.getTrustType());
         trustedIDP.setUrl(entity.getUrl());
+        trustedIDP.setSignRequest(entity.isSignRequest());
         return trustedIDP;
     }