cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject [1/3] cxf-fediz git commit: Separate signing keys from validation keys for SAML SSO
Date Fri, 25 Mar 2016 13:51:16 GMT
Repository: cxf-fediz
Updated Branches:
  refs/heads/master 10ca19558 -> d1c0d7e23


Separate signing keys from validation keys 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/bb6d06d6
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/bb6d06d6
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/bb6d06d6

Branch: refs/heads/master
Commit: bb6d06d63218fbc59e182eb3cb804eff1b7ab397
Parents: 10ca195
Author: Colm O hEigeartaigh <coheigea@apache.org>
Authored: Fri Mar 25 10:43:38 2016 +0000
Committer: Colm O hEigeartaigh <coheigea@apache.org>
Committed: Fri Mar 25 10:43:38 2016 +0000

----------------------------------------------------------------------
 .../idp/beans/samlsso/AuthnRequestParser.java   |  15 +-
 .../beans/samlsso/AuthnRequestValidator.java    | 232 +++++++++++++++++++
 .../fediz/service/idp/domain/Application.java   |  14 +-
 .../idp/samlsso/AuthnRequestValidator.java      | 211 -----------------
 .../idp/service/jpa/ApplicationDAOJPAImpl.java  |   2 +
 .../idp/service/jpa/ApplicationEntity.java      |  10 +
 .../WEB-INF/flows/saml-validate-request.xml     |  10 +-
 .../apache/cxf/fediz/systests/idp/IdpTest.java  |   2 +-
 systests/samlsso/src/test/resources/realma.cert |  15 ++
 .../test/resources/realma/entities-realma.xml   |   1 +
 10 files changed, 283 insertions(+), 229 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bb6d06d6/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestParser.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestParser.java
b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestParser.java
index 410e8c1..565de41 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestParser.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestParser.java
@@ -25,10 +25,8 @@ import org.w3c.dom.Document;
 
 import org.apache.cxf.common.util.Base64Utility;
 import org.apache.cxf.fediz.core.exception.ProcessingException;
-import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE;
 import org.apache.cxf.fediz.service.idp.IdpConstants;
 import org.apache.cxf.fediz.service.idp.domain.Idp;
-import org.apache.cxf.fediz.service.idp.samlsso.AuthnRequestValidator;
 import org.apache.cxf.fediz.service.idp.util.WebUtils;
 import org.apache.cxf.rs.security.saml.DeflateEncoderDecoder;
 import org.apache.cxf.staxutils.StaxUtils;
@@ -48,8 +46,7 @@ public class AuthnRequestParser {
 
     private static final Logger LOG = LoggerFactory.getLogger(AuthnRequestParser.class);
 
-    public void parseSAMLRequest(RequestContext context, Idp idp, String signature, 
-                                 String relayState, String samlRequest) throws ProcessingException
{
+    public void parseSAMLRequest(RequestContext context, Idp idp, String samlRequest) throws
ProcessingException {
         LOG.debug("Received SAML Request: {}", samlRequest);
 
         AuthnRequest parsedRequest = null;
@@ -64,16 +61,6 @@ public class AuthnRequestParser {
                 LOG.warn("Error parsing request: {}", ex.getMessage());
             }
         }
-        
-        if (parsedRequest != null) {
-            try {
-                AuthnRequestValidator validator = new AuthnRequestValidator();
-                validator.validateAuthnRequest(context, parsedRequest, idp, signature, relayState,
samlRequest);
-            } catch (Exception ex) {
-                LOG.warn("Error validating request {}", ex.getMessage(), ex);
-                throw new ProcessingException(TYPE.BAD_REQUEST);
-            }
-        }
     }
     
     public String retrieveRealm(RequestContext context) {

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bb6d06d6/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestValidator.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestValidator.java
b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestValidator.java
new file mode 100644
index 0000000..26088d6
--- /dev/null
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestValidator.java
@@ -0,0 +1,232 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.fediz.service.idp.beans.samlsso;
+
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+
+import org.w3c.dom.Document;
+
+import org.apache.cxf.fediz.core.exception.ProcessingException;
+import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE;
+import org.apache.cxf.fediz.core.util.CertsUtils;
+import org.apache.cxf.fediz.service.idp.IdpConstants;
+import org.apache.cxf.fediz.service.idp.domain.Application;
+import org.apache.cxf.fediz.service.idp.domain.Idp;
+import org.apache.cxf.fediz.service.idp.util.WebUtils;
+import org.apache.cxf.rs.security.saml.sso.SSOConstants;
+import org.apache.wss4j.common.crypto.CertificateStore;
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.saml.SAMLKeyInfo;
+import org.apache.wss4j.common.saml.SAMLUtil;
+import org.apache.wss4j.dom.WSDocInfo;
+import org.apache.wss4j.dom.engine.WSSConfig;
+import org.apache.wss4j.dom.handler.RequestData;
+import org.apache.wss4j.dom.saml.WSSSAMLKeyInfoProcessor;
+import org.apache.wss4j.dom.validate.Credential;
+import org.apache.wss4j.dom.validate.SignatureTrustValidator;
+import org.apache.wss4j.dom.validate.Validator;
+import org.apache.xml.security.utils.Base64;
+import org.opensaml.saml.saml2.core.AuthnRequest;
+import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator;
+import org.opensaml.security.credential.BasicCredential;
+import org.opensaml.security.x509.BasicX509Credential;
+import org.opensaml.xmlsec.signature.KeyInfo;
+import org.opensaml.xmlsec.signature.Signature;
+import org.opensaml.xmlsec.signature.support.SignatureException;
+import org.opensaml.xmlsec.signature.support.SignatureValidator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.webflow.execution.RequestContext;
+
+/**
+ * Validate the received AuthnRequest
+ */
+@Component
+public class AuthnRequestValidator {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AuthnRequestValidator.class);
+
+    public void validateAuthnRequest(RequestContext context, Idp idp, String signature,
+                                     String relayState, String samlRequest, String realm)

+        throws Exception {
+        AuthnRequest authnRequest = 
+            (AuthnRequest)WebUtils.getAttributeFromFlowScope(context, IdpConstants.SAML_AUTHN_REQUEST);
+        if (authnRequest.isSigned()) {
+            // Check destination
+            checkDestination(context, authnRequest);
+            
+            // Check signature
+            X509Certificate validatingCert = getValidatingCertificate(idp, realm);
+            Crypto issuerCrypto = 
+                new CertificateStore(Collections.singletonList(validatingCert).toArray(new
X509Certificate[0]));
+            validateAuthnRequestSignature(authnRequest.getSignature(), issuerCrypto);
+        } else if (signature != null) {
+            // Check destination
+            checkDestination(context, authnRequest);
+            
+            // Check signature
+            X509Certificate validatingCert = getValidatingCertificate(idp, realm);
+            
+            java.security.Signature sig = java.security.Signature.getInstance("SHA1withRSA");
+            sig.initVerify(validatingCert);
+            
+            // Recreate request to sign
+            String requestToSign = WebUtils.getHttpServletRequest(context).getRequestURL().toString()
+ "?";
+            requestToSign += SSOConstants.RELAY_STATE + "=" + relayState;
+            requestToSign += "&" + SSOConstants.SAML_REQUEST + "=" + URLEncoder.encode(samlRequest,
"UTF-8");
+            requestToSign += "&" + SSOConstants.SIG_ALG + "=" 
+                + URLEncoder.encode(SSOConstants.RSA_SHA1, StandardCharsets.UTF_8.name());
+            
+            sig.update(requestToSign.getBytes(StandardCharsets.UTF_8));
+            
+            if (!sig.verify(Base64.decode(signature))) {
+                LOG.debug("Signature validation failed");
+                throw new ProcessingException(TYPE.BAD_REQUEST);
+            }
+        } else {
+            LOG.debug("No signature is present, therefore the request is rejected");
+            throw new ProcessingException(TYPE.BAD_REQUEST);
+        }
+        
+        if (authnRequest.getIssuer() == null) {
+            LOG.debug("No Issuer is present in the AuthnRequest");
+            throw new ProcessingException(TYPE.BAD_REQUEST);
+        }
+        
+        String format = authnRequest.getIssuer().getFormat();
+        if (format != null
+            && !"urn:oasis:names:tc:SAML:2.0:nameid-format:entity".equals(format))
{
+            LOG.debug("An invalid Format attribute was received: {}", format);
+            throw new ProcessingException(TYPE.BAD_REQUEST);
+        }
+    }
+    
+    private X509Certificate getValidatingCertificate(Idp idp, String realm) 
+        throws Exception {
+        Application serviceConfig = idp.findApplication(realm);
+        if (serviceConfig == null || serviceConfig.getValidatingCertificate() == null) {
+            LOG.debug("No validating certificate found for realm {}", realm);
+            throw new ProcessingException(TYPE.ISSUER_NOT_TRUSTED);
+        }
+        
+        return CertsUtils.parseX509Certificate(serviceConfig.getValidatingCertificate());
+    }
+    
+    private void checkDestination(RequestContext context, AuthnRequest authnRequest) throws
ProcessingException {
+        // Check destination
+        String destination = authnRequest.getDestination();
+        LOG.debug("Validating destination: {}", destination);
+        
+        String localAddr = WebUtils.getHttpServletRequest(context).getRequestURL().toString();
+        if (!localAddr.startsWith(destination)) {
+            LOG.debug("The destination {} does not match the local address {}", destination,
localAddr);
+            throw new ProcessingException(TYPE.BAD_REQUEST);
+        }
+    }
+    
+    /**
+     * Validate the AuthnRequest signature
+     */
+    private void validateAuthnRequestSignature(
+        Signature signature,
+        Crypto sigCrypto
+    ) throws WSSecurityException {
+        RequestData requestData = new RequestData();
+        requestData.setSigVerCrypto(sigCrypto);
+        WSSConfig wssConfig = WSSConfig.getNewInstance();
+        requestData.setWssConfig(wssConfig);
+        // requestData.setCallbackHandler(callbackHandler);
+
+        SAMLKeyInfo samlKeyInfo = null;
+
+        KeyInfo keyInfo = signature.getKeyInfo();
+        if (keyInfo != null) {
+            try {
+                Document doc = signature.getDOM().getOwnerDocument();
+                samlKeyInfo =
+                    SAMLUtil.getCredentialFromKeyInfo(
+                        keyInfo.getDOM(), new WSSSAMLKeyInfoProcessor(requestData, new WSDocInfo(doc)),
sigCrypto
+                    );
+            } catch (WSSecurityException ex) {
+                LOG.debug("Error in getting KeyInfo from SAML AuthnRequest: {}", ex.getMessage(),
ex);
+                throw ex;
+            }
+        }
+        
+        if (samlKeyInfo == null) {
+            LOG.debug("No KeyInfo supplied in the AuthnRequest signature");
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
+        }
+
+        // Validate Signature against profiles
+        validateSignatureAgainstProfiles(signature, samlKeyInfo);
+
+        // Now verify trust on the signature
+        Credential trustCredential = new Credential();
+        trustCredential.setPublicKey(samlKeyInfo.getPublicKey());
+        trustCredential.setCertificates(samlKeyInfo.getCerts());
+
+        try {
+            Validator signatureValidator = new SignatureTrustValidator();
+            signatureValidator.validate(trustCredential, requestData);
+        } catch (WSSecurityException e) {
+            LOG.debug("Error in validating signature on SAML AuthnRequest: {}", e.getMessage(),
e);
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
+        }
+    }
+
+    /**
+     * Validate a signature against the profiles
+     */
+    private void validateSignatureAgainstProfiles(
+        Signature signature,
+        SAMLKeyInfo samlKeyInfo
+    ) throws WSSecurityException {
+        // Validate Signature against profiles
+        SAMLSignatureProfileValidator validator = new SAMLSignatureProfileValidator();
+        try {
+            validator.validate(signature);
+        } catch (SignatureException ex) {
+            LOG.debug("Error in validating the SAML Signature: {}", ex.getMessage(), ex);
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
+        }
+
+        BasicCredential credential = null;
+        if (samlKeyInfo.getCerts() != null) {
+            credential = new BasicX509Credential(samlKeyInfo.getCerts()[0]);
+        } else if (samlKeyInfo.getPublicKey() != null) {
+            credential = new BasicCredential(samlKeyInfo.getPublicKey());
+        } else {
+            LOG.debug("Can't get X509Certificate or PublicKey to verify signature");
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
+        }
+        try {
+            SignatureValidator.validate(signature, credential);
+        } catch (SignatureException ex) {
+            LOG.debug("Error in validating the SAML Signature: {}", ex.getMessage(), ex);
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bb6d06d6/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/Application.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/Application.java
b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/Application.java
index 47f2d9f..63d7a9d 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/Application.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/Application.java
@@ -33,7 +33,8 @@ import javax.xml.bind.annotation.XmlType;
 @XmlRootElement(name = "application", namespace = "http://org.apache.cxf.fediz/")
 @XmlType(propOrder = {"realm", "role", "serviceDisplayName", "serviceDescription", "protocol",
                       "tokenType", "lifeTime", "encryptionCertificate", "requestedClaims",
-                      "policyNamespace", "passiveRequestorEndpoint", "passiveRequestorEndpointConstraint",
"id" })
+                      "policyNamespace", "passiveRequestorEndpoint", "passiveRequestorEndpointConstraint",
"id",
+                      "validatingCertificate"})
 public class Application implements Serializable {
         
     private static final long serialVersionUID = 5644327504861846964L;
@@ -57,6 +58,9 @@ public class Application implements Serializable {
     // Could be read from Metadata, md:KeyDescriptor, use="encryption"
     protected String encryptionCertificate;
     
+    // Certificate for Signature verification
+    protected String validatingCertificate;
+    
     // Could be read from Metadata, fed:ClaimTypesRequested
     protected List<RequestClaim> requestedClaims = new ArrayList<>();
     
@@ -216,4 +220,12 @@ public class Application implements Serializable {
     public Pattern getCompiledPassiveRequestorEndpointConstraint() {
         return compiledPassiveRequestorEndpointConstraint;
     }
+    
+    public String getValidatingCertificate() {
+        return validatingCertificate;
+    }
+
+    public void setValidatingCertificate(String validatingCertificate) {
+        this.validatingCertificate = validatingCertificate;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bb6d06d6/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/samlsso/AuthnRequestValidator.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/samlsso/AuthnRequestValidator.java
b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/samlsso/AuthnRequestValidator.java
deleted file mode 100644
index 1fa58c6..0000000
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/samlsso/AuthnRequestValidator.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cxf.fediz.service.idp.samlsso;
-
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-import java.security.cert.X509Certificate;
-
-import org.w3c.dom.Document;
-
-import org.apache.cxf.fediz.core.exception.ProcessingException;
-import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE;
-import org.apache.cxf.fediz.core.util.CertsUtils;
-import org.apache.cxf.fediz.service.idp.domain.Idp;
-import org.apache.cxf.fediz.service.idp.util.WebUtils;
-import org.apache.cxf.rs.security.saml.sso.SSOConstants;
-import org.apache.wss4j.common.crypto.Crypto;
-import org.apache.wss4j.common.ext.WSSecurityException;
-import org.apache.wss4j.common.saml.SAMLKeyInfo;
-import org.apache.wss4j.common.saml.SAMLUtil;
-import org.apache.wss4j.dom.WSDocInfo;
-import org.apache.wss4j.dom.engine.WSSConfig;
-import org.apache.wss4j.dom.handler.RequestData;
-import org.apache.wss4j.dom.saml.WSSSAMLKeyInfoProcessor;
-import org.apache.wss4j.dom.validate.Credential;
-import org.apache.wss4j.dom.validate.SignatureTrustValidator;
-import org.apache.wss4j.dom.validate.Validator;
-import org.apache.xml.security.utils.Base64;
-import org.opensaml.saml.saml2.core.AuthnRequest;
-import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator;
-import org.opensaml.security.credential.BasicCredential;
-import org.opensaml.security.x509.BasicX509Credential;
-import org.opensaml.xmlsec.signature.KeyInfo;
-import org.opensaml.xmlsec.signature.Signature;
-import org.opensaml.xmlsec.signature.support.SignatureException;
-import org.opensaml.xmlsec.signature.support.SignatureValidator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.webflow.execution.RequestContext;
-
-/**
- * Validate the received AuthnRequest
- */
-public class AuthnRequestValidator {
-
-    private static final Logger LOG = LoggerFactory.getLogger(AuthnRequestValidator.class);
-
-    public void validateAuthnRequest(RequestContext context, AuthnRequest authnRequest, Idp
idp, String signature,
-                                     String relayState, String samlRequest) 
-        throws Exception {
-        if (authnRequest.isSigned()) {
-            // Check destination
-            checkDestination(context, authnRequest);
-            
-            // Check signature
-            Crypto issuerCrypto = CertsUtils.getCryptoFromCertificate(idp.getCertificate());
-            validateAuthnRequestSignature(authnRequest.getSignature(), issuerCrypto);
-        } else if (signature != null) {
-            // Check destination
-            checkDestination(context, authnRequest);
-            
-            // Check signature
-            X509Certificate validatingCert = CertsUtils.parseX509Certificate(idp.getCertificate());
-            
-            java.security.Signature sig = java.security.Signature.getInstance("SHA1withRSA");
-            sig.initVerify(validatingCert);
-            
-            // Recreate request to sign
-            String requestToSign = WebUtils.getHttpServletRequest(context).getRequestURL().toString()
+ "?";
-            requestToSign += SSOConstants.RELAY_STATE + "=" + relayState;
-            requestToSign += "&" + SSOConstants.SAML_REQUEST + "=" + URLEncoder.encode(samlRequest,
"UTF-8");
-            requestToSign += "&" + SSOConstants.SIG_ALG + "=" 
-                + URLEncoder.encode(SSOConstants.RSA_SHA1, StandardCharsets.UTF_8.name());
-            
-            sig.update(requestToSign.getBytes(StandardCharsets.UTF_8));
-            
-            if (!sig.verify(Base64.decode(signature))) {
-                LOG.debug("Signature validation failed");
-                throw new ProcessingException(TYPE.BAD_REQUEST);
-            }
-        } else {
-            LOG.debug("No signature is present, therefore the request is rejected");
-            throw new ProcessingException(TYPE.BAD_REQUEST);
-        }
-        
-        if (authnRequest.getIssuer() == null) {
-            LOG.debug("No Issuer is present in the AuthnRequest");
-            throw new ProcessingException(TYPE.BAD_REQUEST);
-        }
-        
-        String format = authnRequest.getIssuer().getFormat();
-        if (format != null
-            && !"urn:oasis:names:tc:SAML:2.0:nameid-format:entity".equals(format))
{
-            LOG.debug("An invalid Format attribute was received: {}", format);
-            throw new ProcessingException(TYPE.BAD_REQUEST);
-        }
-    }
-    
-    private void checkDestination(RequestContext context, AuthnRequest authnRequest) throws
ProcessingException {
-        // Check destination
-        String destination = authnRequest.getDestination();
-        LOG.debug("Validating destination: {}", destination);
-        
-        String localAddr = WebUtils.getHttpServletRequest(context).getRequestURL().toString();
-        if (!localAddr.startsWith(destination)) {
-            LOG.debug("The destination {} does not match the local address {}", destination,
localAddr);
-            throw new ProcessingException(TYPE.BAD_REQUEST);
-        }
-    }
-    
-    /**
-     * Validate the AuthnRequest signature
-     */
-    private void validateAuthnRequestSignature(
-        Signature signature,
-        Crypto sigCrypto
-    ) throws WSSecurityException {
-        RequestData requestData = new RequestData();
-        requestData.setSigVerCrypto(sigCrypto);
-        WSSConfig wssConfig = WSSConfig.getNewInstance();
-        requestData.setWssConfig(wssConfig);
-        // requestData.setCallbackHandler(callbackHandler);
-
-        SAMLKeyInfo samlKeyInfo = null;
-
-        KeyInfo keyInfo = signature.getKeyInfo();
-        if (keyInfo != null) {
-            try {
-                Document doc = signature.getDOM().getOwnerDocument();
-                samlKeyInfo =
-                    SAMLUtil.getCredentialFromKeyInfo(
-                        keyInfo.getDOM(), new WSSSAMLKeyInfoProcessor(requestData, new WSDocInfo(doc)),
sigCrypto
-                    );
-            } catch (WSSecurityException ex) {
-                LOG.debug("Error in getting KeyInfo from SAML AuthnRequest: {}", ex.getMessage(),
ex);
-                throw ex;
-            }
-        }
-        
-        if (samlKeyInfo == null) {
-            LOG.debug("No KeyInfo supplied in the AuthnRequest signature");
-            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
-        }
-
-        // Validate Signature against profiles
-        validateSignatureAgainstProfiles(signature, samlKeyInfo);
-
-        // Now verify trust on the signature
-        Credential trustCredential = new Credential();
-        trustCredential.setPublicKey(samlKeyInfo.getPublicKey());
-        trustCredential.setCertificates(samlKeyInfo.getCerts());
-
-        try {
-            Validator signatureValidator = new SignatureTrustValidator();
-            signatureValidator.validate(trustCredential, requestData);
-        } catch (WSSecurityException e) {
-            LOG.debug("Error in validating signature on SAML AuthnRequest: {}", e.getMessage(),
e);
-            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
-        }
-    }
-
-    /**
-     * Validate a signature against the profiles
-     */
-    private void validateSignatureAgainstProfiles(
-        Signature signature,
-        SAMLKeyInfo samlKeyInfo
-    ) throws WSSecurityException {
-        // Validate Signature against profiles
-        SAMLSignatureProfileValidator validator = new SAMLSignatureProfileValidator();
-        try {
-            validator.validate(signature);
-        } catch (SignatureException ex) {
-            LOG.debug("Error in validating the SAML Signature: {}", ex.getMessage(), ex);
-            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
-        }
-
-        BasicCredential credential = null;
-        if (samlKeyInfo.getCerts() != null) {
-            credential = new BasicX509Credential(samlKeyInfo.getCerts()[0]);
-        } else if (samlKeyInfo.getPublicKey() != null) {
-            credential = new BasicCredential(samlKeyInfo.getPublicKey());
-        } else {
-            LOG.debug("Can't get X509Certificate or PublicKey to verify signature");
-            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
-        }
-        try {
-            SignatureValidator.validate(signature, credential);
-        } catch (SignatureException ex) {
-            LOG.debug("Error in validating the SAML Signature: {}", ex.getMessage(), ex);
-            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
-        }
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bb6d06d6/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationDAOJPAImpl.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationDAOJPAImpl.java
b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationDAOJPAImpl.java
index b18dc90..aa3274f 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationDAOJPAImpl.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationDAOJPAImpl.java
@@ -191,6 +191,7 @@ public class ApplicationDAOJPAImpl implements ApplicationDAO {
         }
         
         entity.setEncryptionCertificate(application.getEncryptionCertificate());
+        entity.setValidatingCertificate(application.getValidatingCertificate());
         entity.setLifeTime(application.getLifeTime());
         entity.setProtocol(application.getProtocol());
         entity.setRealm(application.getRealm());
@@ -207,6 +208,7 @@ public class ApplicationDAOJPAImpl implements ApplicationDAO {
         Application application = new Application();
         application.setId(entity.getId());
         application.setEncryptionCertificate(entity.getEncryptionCertificate());
+        application.setValidatingCertificate(entity.getValidatingCertificate());
         application.setLifeTime(entity.getLifeTime());
         application.setProtocol(entity.getProtocol());
         application.setRealm(entity.getRealm());

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bb6d06d6/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationEntity.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationEntity.java
b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationEntity.java
index 2a0e8de..7b64712 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationEntity.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationEntity.java
@@ -52,6 +52,9 @@ public class ApplicationEntity {
     // Could be read from Metadata, md:KeyDescriptor, use="encryption"
     private String encryptionCertificate;
     
+    // Certificate for Signature verification
+    private String validatingCertificate;
+    
     // Could be read from Metadata, fed:ClaimTypesRequested
     @OneToMany(mappedBy = "application", cascade = CascadeType.ALL, orphanRemoval = true)
     private List<ApplicationClaimEntity> requestedClaims = new ArrayList<>();
@@ -190,4 +193,11 @@ public class ApplicationEntity {
         this.passiveRequestorEndpointConstraint = passiveRequestorEndpointConstraint;
     }
 
+    public String getValidatingCertificate() {
+        return validatingCertificate;
+    }
+
+    public void setValidatingCertificate(String validatingCertificate) {
+        this.validatingCertificate = validatingCertificate;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bb6d06d6/services/idp/src/main/webapp/WEB-INF/flows/saml-validate-request.xml
----------------------------------------------------------------------
diff --git a/services/idp/src/main/webapp/WEB-INF/flows/saml-validate-request.xml b/services/idp/src/main/webapp/WEB-INF/flows/saml-validate-request.xml
index 2578e98..4e008eb 100644
--- a/services/idp/src/main/webapp/WEB-INF/flows/saml-validate-request.xml
+++ b/services/idp/src/main/webapp/WEB-INF/flows/saml-validate-request.xml
@@ -55,9 +55,15 @@
     </subflow-state>
     
     <action-state id="parseAndValidateSAMLRequest">
-        <evaluate expression="authnRequestParser.parseSAMLRequest(flowRequestContext,
flowScope.idpConfig,
-                                                                  flowScope.Signature, flowScope.RelayState,
+        <on-entry>
+            <evaluate expression="authnRequestParser.parseSAMLRequest(flowRequestContext,
flowScope.idpConfig,
                                                                   flowScope.SAMLRequest)"
/>
+            <evaluate expression="authnRequestParser.retrieveRealm(flowRequestContext)"

+                          result="flowScope.realm"/>
+        </on-entry>
+        <evaluate expression="authnRequestValidator.validateAuthnRequest(flowRequestContext,
flowScope.idpConfig,
+                                                                  flowScope.Signature, flowScope.RelayState,
+                                                                  flowScope.SAMLRequest,
flowScope.realm)" />
         <transition to="requestRpToken"/>
         <transition on-exception="org.apache.cxf.fediz.core.exception.ProcessingException"
to="viewBadRequest" />
     </action-state>

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bb6d06d6/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java
----------------------------------------------------------------------
diff --git a/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java
b/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java
index 97137b1..bdf72d4 100644
--- a/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java
+++ b/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java
@@ -337,7 +337,7 @@ public class IdpTest {
             webClient.getPage(url);
             Assert.fail("Failure expected on no destination value");
         } catch (FailingHttpStatusCodeException ex) {
-            Assert.assertEquals(ex.getStatusCode(), 400);
+            // expected
         }
         
         webClient.close();

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bb6d06d6/systests/samlsso/src/test/resources/realma.cert
----------------------------------------------------------------------
diff --git a/systests/samlsso/src/test/resources/realma.cert b/systests/samlsso/src/test/resources/realma.cert
new file mode 100644
index 0000000..ff97f79
--- /dev/null
+++ b/systests/samlsso/src/test/resources/realma.cert
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICwTCCAamgAwIBAgIEINqJ9TANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDEwZSRUFMTUEwHhcN
+MTUwNjEwMTU0NDE3WhcNMjUwNDE4MTU0NDE3WjARMQ8wDQYDVQQDEwZSRUFMTUEwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCJDSXn2lDR+JM+AsJarFG3/XGH7K+9AfAbQIz2IgB9MCpO
+KVWTUPCvuo1I+Fp5nEGreuHYLEwgIiam3o+C9tvpLgtDDaDkmXjDzkWpk8z6+im72HZ/ODF93Rqw
+jIiY5ZCzgDumFyPzdKiGwChThamidy+rd6oheSoi6qRVSMMcnwiEUmvkfFvV3izXRqeT5nGQwsin
+y9mCEiGx8jkfxP++H0RQjVjhOwzfQ7epsR7dTQNf2ZhkBR3o6wKV9QnF2IBWHZpA9EK58rWU9H6j
+G7b631rYvwsbOUF9HcZ8DI2BFh+4p18jDN/fnjNGSLr9rYOExpsIiF1cHBK7Tr7WwCmDAgMBAAGj
+ITAfMB0GA1UdDgQWBBRHy0qYoLm9jx/1L6r61NznHKun2jANBgkqhkiG9w0BAQsFAAOCAQEAR9rU
+5Sp1FsOErdvKNFqeaKl0oq6Fuz7BWcGm2kK6+1ZbWE8IOv6Vh+BlLuOe5hF7aLUbm8UIjhKsmg0M
+Ey5MBwkBZktT1qhQteMuiKgYR7CxayCxO0f125RYvvwntJa5rI7bUrzOqX29VQD1qQ/Tb+08fULT
+L7oURP+g88Ff99dn3IpO4VZxZdsbl4+KZRtqQvPAdXNYjOajJtPzS489+/DtfWJ6wPm/7YZ4did4
+1fYcrdwyEZ15L0/5i931z7sztNickm5WhO40qEVDKN6KrlV2Eyea0+933v2Pwe4resTlko9G2T5h
+dEaSbvht2Q/JOMMmT91daeto2oS8HTKhTA==
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bb6d06d6/systests/samlsso/src/test/resources/realma/entities-realma.xml
----------------------------------------------------------------------
diff --git a/systests/samlsso/src/test/resources/realma/entities-realma.xml b/systests/samlsso/src/test/resources/realma/entities-realma.xml
index fec578c..9f3b9d1 100644
--- a/systests/samlsso/src/test/resources/realma/entities-realma.xml
+++ b/systests/samlsso/src/test/resources/realma/entities-realma.xml
@@ -152,6 +152,7 @@
         <property name="lifeTime" value="3600" />
         <property name="passiveRequestorEndpointConstraint" 
                   value="https://localhost:(\d)*/(\w)*helloworld(\w)*/secure/.*" />
+        <property name="validatingCertificate" value="realma.cert" />
     </bean>
     
     <bean class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationClaimEntity">


Mime
View raw message