cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject git commit: [CXF-5362] Support for collocating RACS with endpoints
Date Mon, 31 Mar 2014 16:36:23 GMT
Repository: cxf
Updated Branches:
  refs/heads/master b3288ed94 -> 1026909f9


[CXF-5362] Support for collocating RACS with endpoints


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

Branch: refs/heads/master
Commit: 1026909f918661c6d25080a9932f4d63af017a31
Parents: b3288ed
Author: Sergey Beryozkin <sberyozkin@talend.com>
Authored: Mon Mar 31 17:35:55 2014 +0100
Committer: Sergey Beryozkin <sberyozkin@talend.com>
Committed: Mon Mar 31 17:35:55 2014 +0100

----------------------------------------------------------------------
 ...AbstractRequestAssertionConsumerHandler.java | 311 +++++++++++++++++++
 .../saml/sso/AbstractServiceProviderFilter.java |   3 +
 .../sso/RequestAssertionConsumerFilter.java     |  83 +++++
 .../sso/RequestAssertionConsumerService.java    | 292 +----------------
 4 files changed, 407 insertions(+), 282 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/1026909f/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
new file mode 100644
index 0000000..75d634c
--- /dev/null
+++ b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractRequestAssertionConsumerHandler.java
@@ -0,0 +1,311 @@
+/**
+ * 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.rs.security.saml.sso;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.Date;
+import java.util.ResourceBundle;
+import java.util.UUID;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.zip.DataFormatException;
+
+import javax.annotation.PreDestroy;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+
+import org.w3c.dom.Document;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.common.i18n.BundleUtils;
+import org.apache.cxf.common.logging.LogUtils;
+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.jaxrs.ext.MessageContext;
+import org.apache.cxf.jaxrs.utils.ExceptionUtils;
+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;
+import org.apache.cxf.staxutils.StaxUtils;
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.saml.OpenSAMLUtil;
+import org.apache.wss4j.common.util.DOM2Writer;
+import org.opensaml.xml.XMLObject;
+
+public abstract class AbstractRequestAssertionConsumerHandler extends AbstractSSOSpHandler
{
+    private static final Logger LOG = 
+        LogUtils.getL7dLogger(AbstractRequestAssertionConsumerHandler.class);
+    private static final ResourceBundle BUNDLE = 
+        BundleUtils.getBundle(AbstractRequestAssertionConsumerHandler.class);
+    
+    private boolean supportDeflateEncoding = true;
+    private boolean supportBase64Encoding = true;
+    private boolean enforceAssertionsSigned = true;
+    private boolean enforceKnownIssuer = true;
+    private boolean keyInfoMustBeAvailable = true;
+    private TokenReplayCache<String> replayCache;
+
+    private MessageContext messageContext;
+    
+    @Context 
+    public void setMessageContext(MessageContext mc) {
+        this.messageContext = mc;
+    }
+    
+    public void setSupportDeflateEncoding(boolean deflate) {
+        supportDeflateEncoding = deflate;
+    }
+    public boolean isSupportDeflateEncoding() {
+        return supportDeflateEncoding;
+    }
+    
+    public void setReplayCache(TokenReplayCache<String> replayCache) {
+        this.replayCache = replayCache;
+    }
+    
+    public TokenReplayCache<String> getReplayCache() {
+        if (replayCache == null) {
+            Bus bus = (Bus)messageContext.getContextualProperty(Bus.class.getName());
+            replayCache = new EHCacheTokenReplayCache(bus);
+        }
+        return replayCache;
+    }
+    
+    /**
+     * Enforce that Assertions must be signed if the POST binding was used. The default is
true.
+     */
+    public void setEnforceAssertionsSigned(boolean enforceAssertionsSigned) {
+        this.enforceAssertionsSigned = enforceAssertionsSigned;
+    }
+    
+    /**
+     * Enforce that the Issuer of the received Response/Assertion is known to this RACS.
The
+     * default is true.
+     */
+    public void setEnforceKnownIssuer(boolean enforceKnownIssuer) {
+        this.enforceKnownIssuer = enforceKnownIssuer;
+    }
+    
+    public void setSupportBase64Encoding(boolean supportBase64Encoding) {
+        this.supportBase64Encoding = supportBase64Encoding;
+    }
+    public boolean isSupportBase64Encoding() {
+        return supportBase64Encoding;
+    }
+    
+    @PreDestroy
+    @Override
+    public void close() {
+        if (replayCache != null) {
+            try {
+                replayCache.close();
+            } catch (IOException ex) {
+                LOG.warning("Replay cache can not be closed: " + ex.getMessage());
+            }
+        }
+        super.close();
+    }
+    
+    protected String createSecurityContext(RequestState requestState,
+                                           String encodedSamlResponse,
+                                           String relayState,
+                                           boolean postBinding) {
+           
+        org.opensaml.saml2.core.Response samlResponse = 
+               readSAMLResponse(postBinding, encodedSamlResponse);
+
+        // Validate the Response
+        validateSamlResponseProtocol(samlResponse);
+        SSOValidatorResponse validatorResponse = 
+            validateSamlSSOResponse(postBinding, samlResponse, requestState);
+           
+        // Set the security context
+        String securityContextKey = UUID.randomUUID().toString();
+           
+        long currentTime = System.currentTimeMillis();
+        Date notOnOrAfter = validatorResponse.getSessionNotOnOrAfter();
+        long expiresAt = 0;
+        if (notOnOrAfter != null) {
+            expiresAt = notOnOrAfter.getTime();
+        } else {
+            expiresAt = currentTime + getStateTimeToLive(); 
+        }
+           
+        ResponseState responseState = 
+            new ResponseState(validatorResponse.getAssertion(),
+                              relayState, 
+                              requestState.getWebAppContext(),
+                              requestState.getWebAppDomain(),
+                              currentTime, 
+                              expiresAt);
+        getStateProvider().setResponseState(securityContextKey, responseState);
+           
+        String contextCookie = createCookie(SSOConstants.SECURITY_CONTEXT_TOKEN,
+                                            securityContextKey,
+                                            requestState.getWebAppContext(),
+                                            requestState.getWebAppDomain());
+           
+        return contextCookie;
+           
+    }
+    
+    protected RequestState processRelayState(String relayState) {
+        if (relayState == null) {
+            reportError("MISSING_RELAY_STATE");
+            throw ExceptionUtils.toBadRequestException(null, null);
+        }
+        if (relayState.getBytes().length < 0 || relayState.getBytes().length > 80)
{
+            reportError("INVALID_RELAY_STATE");
+            throw ExceptionUtils.toBadRequestException(null, null);
+        }
+        RequestState requestState = getStateProvider().removeRequestState(relayState);
+        if (requestState == null) {
+            reportError("MISSING_REQUEST_STATE");
+            throw ExceptionUtils.toBadRequestException(null, null);
+        }
+        if (isStateExpired(requestState.getCreatedAt(), 0)) {
+            reportError("EXPIRED_REQUEST_STATE");
+            throw ExceptionUtils.toBadRequestException(null, null);
+        }
+        return requestState;
+    }
+    
+    private org.opensaml.saml2.core.Response readSAMLResponse(
+        boolean postBinding,
+        String samlResponse
+    ) {
+        if (StringUtils.isEmpty(samlResponse)) {
+            reportError("MISSING_SAML_RESPONSE");
+            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;
+        if (isSupportBase64Encoding()) {
+            try {
+                byte[] deflatedToken = Base64Utility.decode(samlResponseDecoded);
+                tokenStream = !postBinding && isSupportDeflateEncoding() 
+                    ? new DeflateEncoderDecoder().inflateToken(deflatedToken)
+                    : new ByteArrayInputStream(deflatedToken); 
+            } catch (Base64Exception ex) {
+                throw ExceptionUtils.toBadRequestException(ex, null);
+            } catch (DataFormatException ex) {
+                throw ExceptionUtils.toBadRequestException(ex, null);
+            }
+        } else {
+            try {
+                tokenStream = new ByteArrayInputStream(samlResponseDecoded.getBytes("UTF-8"));
+            } catch (UnsupportedEncodingException ex) {
+                throw ExceptionUtils.toBadRequestException(ex, null);
+            }
+        }
+        
+        Document responseDoc = null;
+        try {
+            responseDoc = StaxUtils.read(new InputStreamReader(tokenStream, "UTF-8"));
+        } catch (Exception ex) {
+            throw new WebApplicationException(400);
+        }
+        
+        LOG.fine("Received response: " + DOM2Writer.nodeToString(responseDoc.getDocumentElement()));
+        
+        XMLObject responseObject = null;
+        try {
+            responseObject = OpenSAMLUtil.fromDom(responseDoc.getDocumentElement());
+        } catch (WSSecurityException ex) {
+            throw ExceptionUtils.toBadRequestException(ex, null);
+        }
+        if (!(responseObject instanceof org.opensaml.saml2.core.Response)) {
+            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
+    ) {
+        try {
+            SAMLProtocolResponseValidator protocolValidator = new SAMLProtocolResponseValidator();
+            protocolValidator.setKeyInfoMustBeAvailable(keyInfoMustBeAvailable);
+            protocolValidator.validateSamlResponse(samlResponse, getSignatureCrypto(), getCallbackHandler());
+        } catch (WSSecurityException ex) {
+            LOG.log(Level.FINE, ex.getMessage(), ex);
+            reportError("INVALID_SAML_RESPONSE");
+            throw ExceptionUtils.toBadRequestException(null, null);
+        }
+    }
+    
+    /**
+     * Validate the received SAML Response as per the Web SSO profile
+     */
+    protected SSOValidatorResponse validateSamlSSOResponse(
+        boolean postBinding,
+        org.opensaml.saml2.core.Response samlResponse,
+        RequestState requestState
+    ) {
+        try {
+            SAMLSSOResponseValidator ssoResponseValidator = new SAMLSSOResponseValidator();
+            ssoResponseValidator.setAssertionConsumerURL(
+                messageContext.getUriInfo().getAbsolutePath().toString());
+
+            ssoResponseValidator.setClientAddress(
+                 messageContext.getHttpServletRequest().getRemoteAddr());
+
+            ssoResponseValidator.setIssuerIDP(requestState.getIdpServiceAddress());
+            ssoResponseValidator.setRequestId(requestState.getSamlRequestId());
+            ssoResponseValidator.setSpIdentifier(requestState.getIssuerId());
+            ssoResponseValidator.setEnforceAssertionsSigned(enforceAssertionsSigned);
+            ssoResponseValidator.setEnforceKnownIssuer(enforceKnownIssuer);
+            ssoResponseValidator.setReplayCache(getReplayCache());
+
+            return ssoResponseValidator.validateSamlResponse(samlResponse, postBinding);
+        } catch (WSSecurityException ex) {
+            reportError("INVALID_SAML_RESPONSE");
+            throw ExceptionUtils.toBadRequestException(ex, null);
+        }
+    }
+    
+    protected void reportError(String code) {
+        org.apache.cxf.common.i18n.Message errorMsg = 
+            new org.apache.cxf.common.i18n.Message(code, BUNDLE);
+        LOG.warning(errorMsg.toString());
+    }
+    
+    public void setKeyInfoMustBeAvailable(boolean keyInfoMustBeAvailable) {
+        this.keyInfoMustBeAvailable = keyInfoMustBeAvailable;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/1026909f/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 2d4ec04..597d6a8 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
@@ -31,6 +31,8 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.annotation.PreDestroy;
+import javax.annotation.Priority;
+import javax.ws.rs.Priorities;
 import javax.ws.rs.container.ContainerRequestFilter;
 import javax.ws.rs.container.PreMatching;
 import javax.ws.rs.core.Cookie;
@@ -61,6 +63,7 @@ import org.apache.wss4j.common.saml.SamlAssertionWrapper;
 import org.opensaml.saml2.core.AuthnRequest;
 
 @PreMatching
+@Priority(Priorities.AUTHENTICATION + 1)
 public abstract class AbstractServiceProviderFilter extends AbstractSSOSpHandler 
     implements ContainerRequestFilter {
     

http://git-wip-us.apache.org/repos/asf/cxf/blob/1026909f/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerFilter.java
b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerFilter.java
new file mode 100644
index 0000000..49f572d
--- /dev/null
+++ b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerFilter.java
@@ -0,0 +1,83 @@
+/**
+ * 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.rs.security.saml.sso;
+
+import java.io.IOException;
+
+import javax.annotation.Priority;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+import org.apache.cxf.rs.security.saml.sso.state.RequestState;
+
+@PreMatching
+@Priority(Priorities.AUTHENTICATION)
+public class RequestAssertionConsumerFilter extends AbstractRequestAssertionConsumerHandler

+    implements ContainerRequestFilter {
+
+    @Override
+    public void filter(ContainerRequestContext ct) throws IOException {
+        String httpMethod = ct.getMethod();
+        if (HttpMethod.GET.equals(httpMethod)) {
+            MultivaluedMap<String, String> params = ct.getUriInfo().getQueryParameters();
+            processParams(ct, params, false);
+        } else if (HttpMethod.POST.equals(httpMethod) 
+            && MediaType.APPLICATION_FORM_URLENCODED_TYPE.isCompatible(ct.getMediaType()))
{
+            String strForm = IOUtils.toString(ct.getEntityStream());
+            MultivaluedMap<String, String> params = JAXRSUtils.getStructuredParams(strForm,
"&", false, false);
+            processParams(ct, params, true);
+        } else {
+            ct.abortWith(Response.status(400).build());
+        }
+        
+    }
+    
+    protected void processParams(ContainerRequestContext ct,
+                                 MultivaluedMap<String, String> params, 
+                                 boolean postBinding) {
+        String encodedSamlResponse = params.getFirst(SSOConstants.SAML_RESPONSE);
+        String relayState = params.getFirst(SSOConstants.RELAY_STATE); 
+        RequestState requestState = processRelayState(relayState);
+        String targetUri = requestState.getTargetAddress();
+        if (targetUri != null 
+            && targetUri.startsWith(ct.getUriInfo().getRequestUri().toString()))
{
+            reportError("INVALID_TARGET_URI");
+            ct.abortWith(Response.status(400).build());
+            return;
+        }
+            
+        
+        String contextCookie = createSecurityContext(requestState,
+                                                     encodedSamlResponse,
+                                                     relayState,
+                                                     postBinding);
+        ct.getHeaders().add(HttpHeaders.COOKIE, contextCookie);
+        
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/1026909f/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java
b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java
index 15c62c2..5b594e4 100644
--- a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java
+++ b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java
@@ -18,112 +18,22 @@
  */
 package org.apache.cxf.rs.security.saml.sso;
 
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
 import java.net.URI;
-import java.util.Date;
-import java.util.ResourceBundle;
-import java.util.UUID;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.zip.DataFormatException;
 
-import javax.annotation.PreDestroy;
 import javax.ws.rs.FormParam;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
-import org.w3c.dom.Document;
-
-import org.apache.cxf.Bus;
-import org.apache.cxf.common.i18n.BundleUtils;
-import org.apache.cxf.common.logging.LogUtils;
-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.jaxrs.ext.MessageContext;
 import org.apache.cxf.jaxrs.utils.ExceptionUtils;
-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;
-import org.apache.cxf.staxutils.StaxUtils;
-import org.apache.wss4j.common.ext.WSSecurityException;
-import org.apache.wss4j.common.saml.OpenSAMLUtil;
-import org.apache.wss4j.common.util.DOM2Writer;
-import org.opensaml.xml.XMLObject;
 
 @Path("sso")
-public class RequestAssertionConsumerService extends AbstractSSOSpHandler {
-    private static final Logger LOG = 
-        LogUtils.getL7dLogger(RequestAssertionConsumerService.class);
-    private static final ResourceBundle BUNDLE = 
-        BundleUtils.getBundle(RequestAssertionConsumerService.class);
-    
-    private boolean supportDeflateEncoding = true;
-    private boolean supportBase64Encoding = true;
-    private boolean enforceAssertionsSigned = true;
-    private boolean enforceKnownIssuer = true;
-    private boolean keyInfoMustBeAvailable = true;
-    private TokenReplayCache<String> replayCache;
-
-    private MessageContext messageContext;
-    
-    @Context 
-    public void setMessageContext(MessageContext mc) {
-        this.messageContext = mc;
-    }
-    
-    public void setSupportDeflateEncoding(boolean deflate) {
-        supportDeflateEncoding = deflate;
-    }
-    public boolean isSupportDeflateEncoding() {
-        return supportDeflateEncoding;
-    }
-    
-    public void setReplayCache(TokenReplayCache<String> replayCache) {
-        this.replayCache = replayCache;
-    }
-    
-    public TokenReplayCache<String> getReplayCache() {
-        if (replayCache == null) {
-            Bus bus = (Bus)messageContext.getContextualProperty(Bus.class.getName());
-            replayCache = new EHCacheTokenReplayCache(bus);
-        }
-        return replayCache;
-    }
-    
-    /**
-     * Enforce that Assertions must be signed if the POST binding was used. The default is
true.
-     */
-    public void setEnforceAssertionsSigned(boolean enforceAssertionsSigned) {
-        this.enforceAssertionsSigned = enforceAssertionsSigned;
-    }
-    
-    /**
-     * Enforce that the Issuer of the received Response/Assertion is known to this RACS.
The
-     * default is true.
-     */
-    public void setEnforceKnownIssuer(boolean enforceKnownIssuer) {
-        this.enforceKnownIssuer = enforceKnownIssuer;
-    }
-    
-    public void setSupportBase64Encoding(boolean supportBase64Encoding) {
-        this.supportBase64Encoding = supportBase64Encoding;
-    }
-    public boolean isSupportBase64Encoding() {
-        return supportBase64Encoding;
-    }
-    
+public class RequestAssertionConsumerService extends AbstractRequestAssertionConsumerHandler
{
     @POST
     @Produces(MediaType.APPLICATION_FORM_URLENCODED)
     public Response processSamlResponse(@FormParam(SSOConstants.SAML_RESPONSE) String encodedSamlResponse,
@@ -138,191 +48,19 @@ public class RequestAssertionConsumerService extends AbstractSSOSpHandler
{
         return doProcessSamlResponse(encodedSamlResponse, relayState, false);
     }
     
-    @PreDestroy
-    @Override
-    public void close() {
-        if (replayCache != null) {
-            try {
-                replayCache.close();
-            } catch (IOException ex) {
-                LOG.warning("Replay cache can not be closed: " + ex.getMessage());
-            }
-        }
-        super.close();
-    }
-    
     protected Response doProcessSamlResponse(String encodedSamlResponse,
-                                          String relayState,
-                                          boolean postBinding) {
+                                             String relayState,
+                                             boolean postBinding) {
         RequestState requestState = processRelayState(relayState);
-        URI targetURI = getTargetURI(requestState.getTargetAddress());
-        
-        org.opensaml.saml2.core.Response samlResponse = 
-            readSAMLResponse(postBinding, encodedSamlResponse);
-
-        // Validate the Response
-        validateSamlResponseProtocol(samlResponse);
-        SSOValidatorResponse validatorResponse = 
-            validateSamlSSOResponse(postBinding, samlResponse, requestState);
-        
-        // Set the security context
-        String securityContextKey = UUID.randomUUID().toString();
-        
-        long currentTime = System.currentTimeMillis();
-        Date notOnOrAfter = validatorResponse.getSessionNotOnOrAfter();
-        long expiresAt = 0;
-        if (notOnOrAfter != null) {
-            expiresAt = notOnOrAfter.getTime();
-        } else {
-            expiresAt = currentTime + getStateTimeToLive(); 
-        }
-        
-        ResponseState responseState = 
-            new ResponseState(validatorResponse.getAssertion(),
-                              relayState, 
-                              requestState.getWebAppContext(),
-                              requestState.getWebAppDomain(),
-                              currentTime, 
-                              expiresAt);
-        getStateProvider().setResponseState(securityContextKey, responseState);
-        
-        String contextCookie = createCookie(SSOConstants.SECURITY_CONTEXT_TOKEN,
-                                            securityContextKey,
-                                            requestState.getWebAppContext(),
-                                            requestState.getWebAppDomain());
-        
+       
+        String contextCookie = createSecurityContext(requestState,
+                                                    encodedSamlResponse,
+                                                   relayState,
+                                                   postBinding);
+       
         // Finally, redirect to the service provider endpoint
+        URI targetURI = getTargetURI(requestState.getTargetAddress());
         return Response.seeOther(targetURI).header("Set-Cookie", contextCookie).build();
-        
-    }
-    
-    private RequestState processRelayState(String relayState) {
-        if (relayState == null) {
-            reportError("MISSING_RELAY_STATE");
-            throw ExceptionUtils.toBadRequestException(null, null);
-        }
-        if (relayState.getBytes().length < 0 || relayState.getBytes().length > 80)
{
-            reportError("INVALID_RELAY_STATE");
-            throw ExceptionUtils.toBadRequestException(null, null);
-        }
-        RequestState requestState = getStateProvider().removeRequestState(relayState);
-        if (requestState == null) {
-            reportError("MISSING_REQUEST_STATE");
-            throw ExceptionUtils.toBadRequestException(null, null);
-        }
-        if (isStateExpired(requestState.getCreatedAt(), 0)) {
-            reportError("EXPIRED_REQUEST_STATE");
-            throw ExceptionUtils.toBadRequestException(null, null);
-        }
-        return requestState;
-    }
-    
-    private org.opensaml.saml2.core.Response readSAMLResponse(
-        boolean postBinding,
-        String samlResponse
-    ) {
-        if (StringUtils.isEmpty(samlResponse)) {
-            reportError("MISSING_SAML_RESPONSE");
-            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;
-        if (isSupportBase64Encoding()) {
-            try {
-                byte[] deflatedToken = Base64Utility.decode(samlResponseDecoded);
-                tokenStream = !postBinding && isSupportDeflateEncoding() 
-                    ? new DeflateEncoderDecoder().inflateToken(deflatedToken)
-                    : new ByteArrayInputStream(deflatedToken); 
-            } catch (Base64Exception ex) {
-                throw ExceptionUtils.toBadRequestException(ex, null);
-            } catch (DataFormatException ex) {
-                throw ExceptionUtils.toBadRequestException(ex, null);
-            }
-        } else {
-            try {
-                tokenStream = new ByteArrayInputStream(samlResponseDecoded.getBytes("UTF-8"));
-            } catch (UnsupportedEncodingException ex) {
-                throw ExceptionUtils.toBadRequestException(ex, null);
-            }
-        }
-        
-        Document responseDoc = null;
-        try {
-            responseDoc = StaxUtils.read(new InputStreamReader(tokenStream, "UTF-8"));
-        } catch (Exception ex) {
-            throw new WebApplicationException(400);
-        }
-        
-        LOG.fine("Received response: " + DOM2Writer.nodeToString(responseDoc.getDocumentElement()));
-        
-        XMLObject responseObject = null;
-        try {
-            responseObject = OpenSAMLUtil.fromDom(responseDoc.getDocumentElement());
-        } catch (WSSecurityException ex) {
-            throw ExceptionUtils.toBadRequestException(ex, null);
-        }
-        if (!(responseObject instanceof org.opensaml.saml2.core.Response)) {
-            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
-    ) {
-        try {
-            SAMLProtocolResponseValidator protocolValidator = new SAMLProtocolResponseValidator();
-            protocolValidator.setKeyInfoMustBeAvailable(keyInfoMustBeAvailable);
-            protocolValidator.validateSamlResponse(samlResponse, getSignatureCrypto(), getCallbackHandler());
-        } catch (WSSecurityException ex) {
-            LOG.log(Level.FINE, ex.getMessage(), ex);
-            reportError("INVALID_SAML_RESPONSE");
-            throw ExceptionUtils.toBadRequestException(null, null);
-        }
-    }
-    
-    /**
-     * Validate the received SAML Response as per the Web SSO profile
-     */
-    protected SSOValidatorResponse validateSamlSSOResponse(
-        boolean postBinding,
-        org.opensaml.saml2.core.Response samlResponse,
-        RequestState requestState
-    ) {
-        try {
-            SAMLSSOResponseValidator ssoResponseValidator = new SAMLSSOResponseValidator();
-            ssoResponseValidator.setAssertionConsumerURL(
-                messageContext.getUriInfo().getAbsolutePath().toString());
-
-            ssoResponseValidator.setClientAddress(
-                 messageContext.getHttpServletRequest().getRemoteAddr());
-
-            ssoResponseValidator.setIssuerIDP(requestState.getIdpServiceAddress());
-            ssoResponseValidator.setRequestId(requestState.getSamlRequestId());
-            ssoResponseValidator.setSpIdentifier(requestState.getIssuerId());
-            ssoResponseValidator.setEnforceAssertionsSigned(enforceAssertionsSigned);
-            ssoResponseValidator.setEnforceKnownIssuer(enforceKnownIssuer);
-            ssoResponseValidator.setReplayCache(getReplayCache());
-
-            return ssoResponseValidator.validateSamlResponse(samlResponse, postBinding);
-        } catch (WSSecurityException ex) {
-            reportError("INVALID_SAML_RESPONSE");
-            throw ExceptionUtils.toBadRequestException(ex, null);
-        }
     }
     
     private URI getTargetURI(String targetAddress) {
@@ -337,14 +75,4 @@ public class RequestAssertionConsumerService extends AbstractSSOSpHandler
{
         }
         throw ExceptionUtils.toBadRequestException(null, null);
     }
-    
-    private void reportError(String code) {
-        org.apache.cxf.common.i18n.Message errorMsg = 
-            new org.apache.cxf.common.i18n.Message(code, BUNDLE);
-        LOG.warning(errorMsg.toString());
-    }
-    
-    public void setKeyInfoMustBeAvailable(boolean keyInfoMustBeAvailable) {
-        this.keyInfoMustBeAvailable = keyInfoMustBeAvailable;
-    }
 }


Mime
View raw message