cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r...@apache.org
Subject [11/33] cxf git commit: Support the IdP initiated SAML SSO flow
Date Sat, 13 Aug 2016 21:30:49 GMT
Support the IdP initiated SAML SSO flow


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

Branch: refs/heads/master-jaxrs-2.1
Commit: cf461e4c0805b187b43b5514fd08131fdd3fe601
Parents: 6583010
Author: Colm O hEigeartaigh <coheigea@apache.org>
Authored: Wed Aug 10 11:55:20 2016 +0100
Committer: Colm O hEigeartaigh <coheigea@apache.org>
Committed: Wed Aug 10 11:55:20 2016 +0100

----------------------------------------------------------------------
 ...AbstractRequestAssertionConsumerHandler.java | 54 ++++++++++++++++++++
 .../security/saml/sso/AbstractSSOSpHandler.java | 36 +++++++++++++
 .../saml/sso/AbstractServiceProviderFilter.java | 46 +++++------------
 .../saml/sso/SAMLSSOResponseValidator.java      |  3 ++
 4 files changed, 106 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/cf461e4c/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractRequestAssertionConsumerHandler.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractRequestAssertionConsumerHandler.java
b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractRequestAssertionConsumerHandler.java
index 3c110a1..0e801f3 100644
--- a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractRequestAssertionConsumerHandler.java
+++ b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractRequestAssertionConsumerHandler.java
@@ -45,6 +45,7 @@ import org.apache.cxf.common.util.Base64Utility;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.jaxrs.ext.MessageContext;
 import org.apache.cxf.jaxrs.utils.ExceptionUtils;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 import org.apache.cxf.rs.security.saml.DeflateEncoderDecoder;
 import org.apache.cxf.rs.security.saml.sso.state.RequestState;
 import org.apache.cxf.rs.security.saml.sso.state.ResponseState;
@@ -69,6 +70,8 @@ public abstract class AbstractRequestAssertionConsumerHandler extends AbstractSS
     private TokenReplayCache<String> replayCache;
 
     private MessageContext messageContext;
+    private String applicationURL;
+    private boolean parseApplicationURLFromRelayState;
     
     @Context 
     public void setMessageContext(MessageContext mc) {
@@ -201,6 +204,31 @@ public abstract class AbstractRequestAssertionConsumerHandler extends
AbstractSS
     }
     
     protected RequestState processRelayState(String relayState) {
+        if (isSupportUnsolicited()) {
+            String urlToForwardTo = applicationURL;
+            if (relayState != null && relayState.getBytes().length > 0 &&
relayState.getBytes().length < 80) {
+                // First see if we have a valid RequestState
+                RequestState requestState = getStateProvider().removeRequestState(relayState);
+                if (requestState != null && !isStateExpired(requestState.getCreatedAt(),
0)) {
+                    return requestState;
+                }
+                
+                // Otherwise get the application URL from the RelayState if supported
+                if (parseApplicationURLFromRelayState) {
+                    urlToForwardTo = relayState;
+                }
+            }
+            
+            // Otherwise create a new one for the IdP initiated case
+            return new RequestState(urlToForwardTo,
+                                    getIdpServiceAddress(),
+                                    null,
+                                    getIssuerId(JAXRSUtils.getCurrentMessage()),
+                                    "/",
+                                    null,
+                                    new Date().getTime());
+        }
+        
         if (relayState == null) {
             reportError("MISSING_RELAY_STATE");
             throw ExceptionUtils.toBadRequestException(null, null);
@@ -218,6 +246,7 @@ public abstract class AbstractRequestAssertionConsumerHandler extends
AbstractSS
             reportError("EXPIRED_REQUEST_STATE");
             throw ExceptionUtils.toBadRequestException(null, null);
         }
+
         return requestState;
     }
     
@@ -348,4 +377,29 @@ public abstract class AbstractRequestAssertionConsumerHandler extends
AbstractSS
     public void setEnforceResponseSigned(boolean enforceResponseSigned) {
         this.enforceResponseSigned = enforceResponseSigned;
     }
+
+    public String getApplicationURL() {
+        return applicationURL;
+    }
+
+    /**
+     * Set the Application URL to forward to, for the unsolicited IdP case.
+     * @param applicationURL
+     */
+    public void setApplicationURL(String applicationURL) {
+        this.applicationURL = applicationURL;
+    }
+
+    public boolean isParseApplicationURLFromRelayState() {
+        return parseApplicationURLFromRelayState;
+    }
+
+    /**
+     * Whether to parse the application URL to forward to from the RelayState, for the unsolicted
IdP case.
+     * @param parseApplicationURLFromRelayState
+     */
+    public void setParseApplicationURLFromRelayState(boolean parseApplicationURLFromRelayState)
{
+        this.parseApplicationURLFromRelayState = parseApplicationURLFromRelayState;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/cf461e4c/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractSSOSpHandler.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractSSOSpHandler.java
b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractSSOSpHandler.java
index dd0a516..11a5b0c 100644
--- a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractSSOSpHandler.java
+++ b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractSSOSpHandler.java
@@ -28,7 +28,9 @@ import javax.annotation.PreDestroy;
 import javax.security.auth.callback.CallbackHandler;
 
 import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.jaxrs.impl.UriInfoImpl;
 import org.apache.cxf.jaxrs.utils.HttpUtils;
+import org.apache.cxf.message.Message;
 import org.apache.cxf.rs.security.saml.sso.state.SPStateManager;
 import org.apache.cxf.rt.security.utils.SecurityUtils;
 import org.apache.wss4j.common.crypto.Crypto;
@@ -47,6 +49,9 @@ public class AbstractSSOSpHandler {
     private CallbackHandler callbackHandler;
     private String callbackHandlerClass;
     private String signatureUsername;
+    private String idpServiceAddress;
+    private String issuerId;
+    private boolean supportUnsolicited;
     
     static {
         OpenSAMLUtil.initSamlEngine();
@@ -203,4 +208,35 @@ public class AbstractSSOSpHandler {
         return signatureUsername;
     }
     
+    public void setIdpServiceAddress(String idpServiceAddress) {
+        this.idpServiceAddress = idpServiceAddress;
+    }
+
+    public String getIdpServiceAddress() {
+        return idpServiceAddress;
+    }
+    
+    public void setIssuerId(String issuerId) {
+        this.issuerId = issuerId;
+    }
+    
+    protected String getIssuerId(Message m) {
+        if (issuerId == null) {
+            return new UriInfoImpl(m).getBaseUri().toString();
+        } else {
+            return issuerId;
+        }
+    }
+    
+    public boolean isSupportUnsolicited() {
+        return supportUnsolicited;
+    }
+
+    /**
+     * Whether to support unsolicited IdP initiated login or not. The default
+     * is false.
+     */
+    public void setSupportUnsolicited(boolean supportUnsolicited) {
+        this.supportUnsolicited = supportUnsolicited;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/cf461e4c/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java
b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java
index 3d88dc8..edb2a9a 100644
--- a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java
+++ b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java
@@ -75,8 +75,6 @@ public abstract class AbstractServiceProviderFilter extends AbstractSSOSpHandler
     protected static final ResourceBundle BUNDLE = 
         BundleUtils.getBundle(AbstractServiceProviderFilter.class);
     
-    private String idpServiceAddress;
-    private String issuerId;
     private String assertionConsumerServiceAddress;
     private AuthnRequestBuilder authnRequestBuilder = new DefaultAuthnRequestBuilder();
     private boolean signRequest;
@@ -106,31 +104,11 @@ public abstract class AbstractServiceProviderFilter extends AbstractSSOSpHandler
         this.assertionConsumerServiceAddress = assertionConsumerServiceAddress;
     }
 
-    public void setIssuerId(String issuerId) {
-        this.issuerId = issuerId;
-    }
-    
-    public void setIdpServiceAddress(String idpServiceAddress) {
-        this.idpServiceAddress = idpServiceAddress;
-    }
-
-    public String getIdpServiceAddress() {
-        return idpServiceAddress;
-    }
-    
     @PreDestroy
     public void close() {
         super.close();
     }
     
-    private String getIssuerId(Message m) {
-        if (issuerId == null) {
-            return new UriInfoImpl(m).getBaseUri().toString();
-        } else {
-            return issuerId;
-        }
-    }
-    
     protected boolean checkSecurityContext(Message m) {
         HttpHeaders headers = new HttpHeadersImpl(m);
         Map<String, Cookie> cookies = headers.getCookies();
@@ -142,16 +120,18 @@ public abstract class AbstractServiceProviderFilter extends AbstractSSOSpHandler
             return false;    
         }
         
-        Cookie relayStateCookie = cookies.get(SSOConstants.RELAY_STATE);
-        if (relayStateCookie == null) {
-            reportError("MISSING_RELAY_COOKIE");
-            return false;
-        }
-        String originalRelayState = responseState.getRelayState();
-        if (!originalRelayState.equals(relayStateCookie.getValue())) {
-            // perhaps the response state should also be removed
-            reportError("INVALID_RELAY_STATE");
-            return false;
+        if (!isSupportUnsolicited()) {
+            Cookie relayStateCookie = cookies.get(SSOConstants.RELAY_STATE);
+            if (relayStateCookie == null) {
+                reportError("MISSING_RELAY_COOKIE");
+                return false;
+            }
+            String originalRelayState = responseState.getRelayState();
+            if (!originalRelayState.equals(relayStateCookie.getValue())) {
+                // perhaps the response state should also be removed
+                reportError("INVALID_RELAY_STATE");
+                return false;
+            }
         }
         try {
             String assertion = responseState.getAssertion();
@@ -241,7 +221,7 @@ public abstract class AbstractServiceProviderFilter extends AbstractSSOSpHandler
                 m, getIssuerId(m), getAbsoluteAssertionServiceAddress(m)
             );
         if (isSignRequest()) {
-            authnRequest.setDestination(idpServiceAddress);
+            authnRequest.setDestination(getIdpServiceAddress());
             signAuthnRequest(authnRequest);
         }
         Element authnRequestElement = OpenSAMLUtil.toDom(authnRequest, doc);

http://git-wip-us.apache.org/repos/asf/cxf/blob/cf461e4c/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLSSOResponseValidator.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLSSOResponseValidator.java
b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLSSOResponseValidator.java
index c95e773..25083c1 100644
--- a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLSSOResponseValidator.java
+++ b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLSSOResponseValidator.java
@@ -262,6 +262,9 @@ public class SAMLSSOResponseValidator {
         if (requestId != null && !requestId.equals(subjectConfData.getInResponseTo()))
{
             LOG.fine("The InResponseTo String does match the original request id " + requestId);
             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
+        } else if (requestId == null && subjectConfData.getInResponseTo() != null)
{
+            LOG.fine("No InResponseTo String is allowed for the unsolicted case");
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
         }
         
     }


Mime
View raw message