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:30 UTC

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

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;
     }