cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject [2/3] cxf-fediz git commit: FEDIZ-186 - Add new logoutRedirectToConstraint plugin configuration parameter
Date Wed, 21 Dec 2016 15:11:22 GMT
FEDIZ-186 - Add new logoutRedirectToConstraint plugin configuration parameter


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

Branch: refs/heads/1.3.x-fixes
Commit: 90f41b6019d2b11f931e7d757e4bbcdf8b175b98
Parents: b5c8d8e
Author: Colm O hEigeartaigh <coheigea@apache.org>
Authored: Wed Dec 21 14:54:00 2016 +0000
Committer: Colm O hEigeartaigh <coheigea@apache.org>
Committed: Wed Dec 21 15:07:17 2016 +0000

----------------------------------------------------------------------
 .../cxf/fediz/core/config/FedizContext.java     |   8 +
 .../cxf/fediz/core/handler/LogoutHandler.java   |  31 +-
 .../core/processor/FederationProcessorImpl.java |  43 ++-
 .../src/main/resources/schemas/FedizConfig.xsd  |  11 +
 .../core/federation/FederationLogoutTest.java   | 357 +++++++++++++++++++
 .../test/resources/fediz_test_config_logout.xml |  88 +++++
 6 files changed, 520 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/90f41b60/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java
b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java
index 537b137..3a329e1 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/FedizContext.java
@@ -30,6 +30,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Properties;
+import java.util.regex.Pattern;
 
 import org.apache.cxf.fediz.core.config.jaxb.CertificateStores;
 import org.apache.cxf.fediz.core.config.jaxb.ContextConfig;
@@ -69,6 +70,7 @@ public class FedizContext implements Closeable {
     private KeyManager keyManager;
     private KeyManager decryptionKeyManager;
     private ClassLoader classloader;
+    private Pattern logoutRedirectToConstraint;
     
 
     public FedizContext(ContextConfig config) {
@@ -170,6 +172,12 @@ public class FedizContext implements Closeable {
         return config.getLogoutRedirectTo();
     }
     
+    public Pattern getLogoutRedirectToConstraint() {
+        if (logoutRedirectToConstraint == null && config.getLogoutRedirectToConstraint()
!= null) {
+            logoutRedirectToConstraint = Pattern.compile(config.getLogoutRedirectToConstraint());
+        }
+        return logoutRedirectToConstraint;
+    }
     
     public KeyManager getSigningKey() {
         

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/90f41b60/plugins/core/src/main/java/org/apache/cxf/fediz/core/handler/LogoutHandler.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/handler/LogoutHandler.java
b/plugins/core/src/main/java/org/apache/cxf/fediz/core/handler/LogoutHandler.java
index 79d6fce..b547b00 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/handler/LogoutHandler.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/handler/LogoutHandler.java
@@ -23,6 +23,8 @@ import java.io.InputStream;
 import java.net.URLEncoder;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
@@ -88,18 +90,31 @@ public class LogoutHandler implements RequestHandler<Boolean> {
     protected boolean signoutCleanup(HttpServletRequest request, HttpServletResponse response)
{
         LOG.info("SignOutCleanup request found. Terminating user session.");
         request.getSession().invalidate();
+        
         String wreply = request.getParameter(FederationConstants.PARAM_REPLY);
+        Pattern logoutRedirectToConstraint = fedizConfig.getLogoutRedirectToConstraint();
+        
         if (wreply != null && !wreply.isEmpty()) {
-            try {
-                LOG.debug("Redirecting user after logout to: {}", wreply);
-                response.sendRedirect(URLEncoder.encode(wreply, "UTF-8"));
-            } catch (IOException e) {
-                LOG.error("Error redirecting user after logout: {}", e.getMessage());
+            if (logoutRedirectToConstraint == null) {
+                LOG.debug("No regular expression constraint configured for logout. Ignoring
wreply parameter");
+            } else {
+                Matcher matcher = logoutRedirectToConstraint.matcher(wreply);
+                if (matcher.matches()) {
+                    try {
+                        LOG.debug("Redirecting user after logout to: {}", wreply);
+                        response.sendRedirect(URLEncoder.encode(wreply, "UTF-8"));
+                        return true;
+                    } catch (IOException e) {
+                        LOG.error("Error redirecting user after logout: {}", e.getMessage());
+                    }
+                } else {
+                    LOG.warn("The received wreply address {} does not match the configured
constraint {}",
+                             wreply, logoutRedirectToConstraint);
+                }
             }
-        } else {
-            LOG.debug("No wreply parameter was set in logout action. Returning logout image");
-            writeLogoutImage(response);
         }
+        
+        writeLogoutImage(response);
         return true;
     }
 

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/90f41b60/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java
b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java
index b82777b..5cb626e 100644
--- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java
+++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/FederationProcessorImpl.java
@@ -34,6 +34,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
@@ -499,21 +501,42 @@ public class FederationProcessorImpl extends AbstractFedizProcessor
{
             StringBuilder sb = new StringBuilder();
             sb.append(FederationConstants.PARAM_ACTION).append('=').append(FederationConstants.ACTION_SIGNOUT);
 
-            String logoutRedirectTo = request.getParameter(FederationConstants.PARAM_REPLY);
-            if (logoutRedirectTo == null || logoutRedirectTo.isEmpty()) {
-                logoutRedirectTo = config.getLogoutRedirectTo();
-            }
-            if (logoutRedirectTo != null && !logoutRedirectTo.isEmpty()) {
-
-                if (logoutRedirectTo.startsWith("/")) {
-                    logoutRedirectTo = extractFullContextPath(request).concat(logoutRedirectTo.substring(1));
+            // Match the 'wreply' parameter against the constraint
+            String logoutRedirectTo = null;
+            Pattern logoutRedirectToConstraint = config.getLogoutRedirectToConstraint();
+            if (request.getParameter(FederationConstants.PARAM_REPLY) != null) {
+                if (logoutRedirectToConstraint == null) {
+                    LOG.debug("No regular expression constraint configured for logout. Ignoring
wreply parameter");
                 } else {
-                    logoutRedirectTo = extractFullContextPath(request).concat(logoutRedirectTo);
+                    Matcher matcher = 
+                        logoutRedirectToConstraint.matcher(request.getParameter(FederationConstants.PARAM_REPLY));
+                    if (matcher.matches()) {
+                        logoutRedirectTo = request.getParameter(FederationConstants.PARAM_REPLY);
+                    } else {
+                        LOG.warn("The received wreply address {} does not match the configured
constraint {}",
+                                 logoutRedirectTo, logoutRedirectToConstraint);
+                    }
                 }
-
+            }
+            
+            if (logoutRedirectTo != null && !logoutRedirectTo.isEmpty()) {
                 LOG.debug("wreply={}", logoutRedirectTo);
                 sb.append('&').append(FederationConstants.PARAM_REPLY).append('=');
                 sb.append(URLEncoder.encode(logoutRedirectTo, "UTF-8"));
+            } else {
+                logoutRedirectTo = config.getLogoutRedirectTo();
+                if (logoutRedirectTo != null && !logoutRedirectTo.isEmpty()) {
+    
+                    if (logoutRedirectTo.startsWith("/")) {
+                        logoutRedirectTo = extractFullContextPath(request).concat(logoutRedirectTo.substring(1));
+                    } else {
+                        logoutRedirectTo = extractFullContextPath(request).concat(logoutRedirectTo);
+                    }
+    
+                    LOG.debug("wreply={}", logoutRedirectTo);
+                    sb.append('&').append(FederationConstants.PARAM_REPLY).append('=');
+                    sb.append(URLEncoder.encode(logoutRedirectTo, "UTF-8"));
+                }
             }
 
             redirectURL = redirectURL + "?" + sb.toString();

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/90f41b60/plugins/core/src/main/resources/schemas/FedizConfig.xsd
----------------------------------------------------------------------
diff --git a/plugins/core/src/main/resources/schemas/FedizConfig.xsd b/plugins/core/src/main/resources/schemas/FedizConfig.xsd
index b556e8b..47b3a98 100644
--- a/plugins/core/src/main/resources/schemas/FedizConfig.xsd
+++ b/plugins/core/src/main/resources/schemas/FedizConfig.xsd
@@ -27,6 +27,7 @@
                 <xs:element ref="protocol" />
                 <xs:element ref="logoutURL" minOccurs="0" />
                 <xs:element ref="logoutRedirectTo" minOccurs="0" />
+                <xs:element ref="logoutRedirectToConstraint" minOccurs="0" />
             </xs:sequence>
             <xs:attribute name="name" use="required" type="xs:string" />
 
@@ -143,6 +144,16 @@
             </xs:documentation>
         </xs:annotation>
     </xs:element>
+    
+    <xs:element name="logoutRedirectToConstraint" type="xs:string">
+        <xs:annotation>
+            <xs:documentation>A regular expression constraint on the 'wreply' parameter,
which is used to obtain the URL to 
+                navigate to after successful logout. If the constraint is not specified,
then the 'wreply' parameter is ignored 
+                and instead the URL is taken from the "logoutRedirectTo" configuration option.
+                Example: 'https://localhost:12345/logout.*/'
+            </xs:documentation>
+        </xs:annotation>
+    </xs:element>
 
     <xs:complexType name="federationProtocolType">
         <xs:complexContent>

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/90f41b60/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationLogoutTest.java
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationLogoutTest.java
b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationLogoutTest.java
new file mode 100644
index 0000000..dedc9f4
--- /dev/null
+++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/federation/FederationLogoutTest.java
@@ -0,0 +1,357 @@
+/**
+ * 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.core.federation;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLEncoder;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.cxf.fediz.common.SecurityTestUtil;
+import org.apache.cxf.fediz.core.FederationConstants;
+import org.apache.cxf.fediz.core.config.FedizConfigurator;
+import org.apache.cxf.fediz.core.config.FedizContext;
+import org.apache.cxf.fediz.core.handler.LogoutHandler;
+import org.easymock.EasyMock;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+
+/**
+ * Some tests for logout for WS-Federation
+ */
+public class FederationLogoutTest {
+    private static final String LOGOUT_URL = "https://localhost/fedizhelloworld/secure/logout";
+    private static final String LOGOUT_URI = "/secure/logout";
+    private static final String REPLY_URL = "https://localhost/fedizhelloworld/secure/wreply.html";
+    private static final String BAD_REPLY_URL = "https://localhost/fedizhelloworld/secure/badreply.html";
+    
+    private static final String CONFIG_FILE = "fediz_test_config_logout.xml";
+    
+    private static FedizConfigurator configurator;
+    private static DocumentBuilderFactory docBuilderFactory;
+    
+    static {
+        docBuilderFactory = DocumentBuilderFactory.newInstance();
+        docBuilderFactory.setNamespaceAware(true);
+    }
+    
+    
+    @BeforeClass
+    public static void init() {
+        getFederationConfigurator();
+        Assert.assertNotNull(configurator);
+    }
+    
+    @AfterClass
+    public static void cleanup() {
+        SecurityTestUtil.cleanup();
+    }
+    
+
+    private static FedizConfigurator getFederationConfigurator() {
+        if (configurator != null) {
+            return configurator;
+        }
+        try {
+            configurator = new FedizConfigurator();
+            final URL resource = Thread.currentThread().getContextClassLoader()
+                    .getResource(CONFIG_FILE);
+            File f = new File(resource.toURI());
+            configurator.loadConfig(f);
+            return configurator;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+    
+    @org.junit.Test
+    public void testSignoutCustomURL() throws Exception {
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION)).andReturn(null).anyTimes();
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(null);
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(LOGOUT_URL));
+        EasyMock.expect(req.getRequestURI()).andReturn(LOGOUT_URI);
+        EasyMock.expect(req.getContextPath()).andReturn(LOGOUT_URI);
+        EasyMock.replay(req);
+        
+        LogoutHandler logoutHandler = new LogoutHandler(config);
+        Assert.assertTrue(logoutHandler.canHandleRequest(req));
+        
+        HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+        String expectedRedirectToIdP = 
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Flogout%2Findex.html";
+        resp.sendRedirect(expectedRedirectToIdP);
+        EasyMock.expectLastCall();
+        EasyMock.replay(resp);
+        logoutHandler.handleRequest(req, resp);
+    }
+    
+    @org.junit.Test
+    public void testSignoutCustomURLWithWReply() throws Exception {
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION)).andReturn(null).anyTimes();
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(REPLY_URL).anyTimes();
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(LOGOUT_URL));
+        EasyMock.expect(req.getRequestURI()).andReturn(LOGOUT_URI);
+        EasyMock.expect(req.getContextPath()).andReturn(LOGOUT_URI);
+        EasyMock.replay(req);
+        
+        LogoutHandler logoutHandler = new LogoutHandler(config);
+        Assert.assertTrue(logoutHandler.canHandleRequest(req));
+        
+        HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+        String expectedRedirectToIdP = 
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=" + URLEncoder.encode(REPLY_URL,
"UTF-8");
+        resp.sendRedirect(expectedRedirectToIdP);
+        EasyMock.expectLastCall();
+        EasyMock.replay(resp);
+        logoutHandler.handleRequest(req, resp);
+    }
+    
+    @org.junit.Test
+    public void testSignoutCustomURLWithBadWReply() throws Exception {
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION)).andReturn(null).anyTimes();
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(BAD_REPLY_URL).anyTimes();
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(LOGOUT_URL));
+        EasyMock.expect(req.getRequestURI()).andReturn(LOGOUT_URI);
+        EasyMock.expect(req.getContextPath()).andReturn(LOGOUT_URI);
+        EasyMock.replay(req);
+        
+        LogoutHandler logoutHandler = new LogoutHandler(config);
+        Assert.assertTrue(logoutHandler.canHandleRequest(req));
+        
+        HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+        String expectedRedirectToIdP = 
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Flogout%2Findex.html";
+        resp.sendRedirect(expectedRedirectToIdP);
+        EasyMock.expectLastCall();
+        EasyMock.replay(resp);
+        logoutHandler.handleRequest(req, resp);
+    }
+    
+    @org.junit.Test
+    public void testSignoutCustomURLWithNoConfiguredConstraint() throws Exception {
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT2");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION)).andReturn(null).anyTimes();
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(REPLY_URL).anyTimes();
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(LOGOUT_URL));
+        EasyMock.expect(req.getRequestURI()).andReturn(LOGOUT_URI);
+        EasyMock.expect(req.getContextPath()).andReturn(LOGOUT_URI);
+        EasyMock.replay(req);
+        
+        LogoutHandler logoutHandler = new LogoutHandler(config);
+        Assert.assertTrue(logoutHandler.canHandleRequest(req));
+        
+        HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+        String expectedRedirectToIdP = 
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Flogout%2Findex.html";
+        resp.sendRedirect(expectedRedirectToIdP);
+        EasyMock.expectLastCall();
+        EasyMock.replay(resp);
+        logoutHandler.handleRequest(req, resp);
+    }
+    
+    @org.junit.Test
+    public void testSignoutAction() throws Exception {
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION))
+            .andReturn(FederationConstants.ACTION_SIGNOUT).anyTimes();
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(null);
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer("https://localhost/fedizhelloworld/secure"));
+        EasyMock.expect(req.getRequestURI()).andReturn("/secure");
+        EasyMock.expect(req.getContextPath()).andReturn("/secure");
+        EasyMock.replay(req);
+        
+        LogoutHandler logoutHandler = new LogoutHandler(config);
+        Assert.assertTrue(logoutHandler.canHandleRequest(req));
+        
+        HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+        String expectedRedirectToIdP = 
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Findex.html";
+        resp.sendRedirect(expectedRedirectToIdP);
+        EasyMock.expectLastCall();
+        EasyMock.replay(resp);
+        logoutHandler.handleRequest(req, resp);
+    }
+    
+    @org.junit.Test
+    public void testSignoutActionWithWReply() throws Exception {
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION))
+            .andReturn(FederationConstants.ACTION_SIGNOUT).anyTimes();
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(REPLY_URL).anyTimes();
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer("https://localhost/fedizhelloworld/secure"));
+        EasyMock.expect(req.getRequestURI()).andReturn("/secure");
+        EasyMock.expect(req.getContextPath()).andReturn("/secure");
+        EasyMock.replay(req);
+        
+        LogoutHandler logoutHandler = new LogoutHandler(config);
+        Assert.assertTrue(logoutHandler.canHandleRequest(req));
+        
+        HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+        String expectedRedirectToIdP = 
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=" + URLEncoder.encode(REPLY_URL,
"UTF-8");
+        resp.sendRedirect(expectedRedirectToIdP);
+        EasyMock.expectLastCall();
+        EasyMock.replay(resp);
+        logoutHandler.handleRequest(req, resp);
+    }
+    
+    @org.junit.Test
+    public void testSignoutActionWithBadWReply() throws Exception {
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION))
+            .andReturn(FederationConstants.ACTION_SIGNOUT).anyTimes();
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(BAD_REPLY_URL).anyTimes();
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer("https://localhost/fedizhelloworld/secure"));
+        EasyMock.expect(req.getRequestURI()).andReturn("/secure");
+        EasyMock.expect(req.getContextPath()).andReturn("/secure");
+        EasyMock.replay(req);
+        
+        LogoutHandler logoutHandler = new LogoutHandler(config);
+        Assert.assertTrue(logoutHandler.canHandleRequest(req));
+        
+        HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+        String expectedRedirectToIdP = 
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Findex.html";
+        resp.sendRedirect(expectedRedirectToIdP);
+        EasyMock.expectLastCall();
+        EasyMock.replay(resp);
+        logoutHandler.handleRequest(req, resp);
+    }
+    
+    @org.junit.Test
+    public void testSignoutActionWithNoConfiguredConstraint() throws Exception {
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT2");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION))
+        .andReturn(FederationConstants.ACTION_SIGNOUT).anyTimes();
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(REPLY_URL).anyTimes();
+        EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer("https://localhost/fedizhelloworld/secure"));
+        EasyMock.expect(req.getRequestURI()).andReturn("/secure");
+        EasyMock.expect(req.getContextPath()).andReturn("/secure");
+        EasyMock.replay(req);
+        
+        LogoutHandler logoutHandler = new LogoutHandler(config);
+        Assert.assertTrue(logoutHandler.canHandleRequest(req));
+        
+        HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+        String expectedRedirectToIdP = 
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Findex.html";
+        resp.sendRedirect(expectedRedirectToIdP);
+        EasyMock.expectLastCall();
+        EasyMock.replay(resp);
+        logoutHandler.handleRequest(req, resp);
+    }
+    
+    @org.junit.Test
+    public void testSignoutCleanupWithWReply() throws Exception {
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        HttpSession session =  EasyMock.createMock(HttpSession.class);
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION))
+            .andReturn(FederationConstants.ACTION_SIGNOUT_CLEANUP).anyTimes();
+        EasyMock.expect(req.getSession()).andReturn(session);
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(REPLY_URL).anyTimes();
+        EasyMock.replay(req);
+        
+        LogoutHandler logoutHandler = new LogoutHandler(config);
+        Assert.assertTrue(logoutHandler.canHandleRequest(req));
+        
+        HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+        String expectedRedirect = URLEncoder.encode(REPLY_URL, "UTF-8");
+        resp.sendRedirect(expectedRedirect);
+        EasyMock.expectLastCall();
+        EasyMock.replay(resp);
+        logoutHandler.handleRequest(req, resp);
+    }
+    
+    @org.junit.Test
+    public void testSignoutCleanupWithBadWReply() throws Exception {
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        HttpSession session =  EasyMock.createMock(HttpSession.class);
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION))
+            .andReturn(FederationConstants.ACTION_SIGNOUT_CLEANUP).anyTimes();
+        EasyMock.expect(req.getSession()).andReturn(session);
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(BAD_REPLY_URL).anyTimes();
+        EasyMock.replay(req);
+        
+        LogoutHandler logoutHandler = new LogoutHandler(config);
+        Assert.assertTrue(logoutHandler.canHandleRequest(req));
+        
+        HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+        resp.setContentType("image/jpeg");
+        ServletOutputStream outputStream = EasyMock.createMock(ServletOutputStream.class);
+        EasyMock.expect(resp.getOutputStream()).andReturn(outputStream);
+        EasyMock.expectLastCall();
+        EasyMock.replay(resp);
+        logoutHandler.handleRequest(req, resp);
+    }
+    
+    @org.junit.Test
+    public void testSignoutCleanupWithNoConfiguredConstraint() throws Exception {
+        FedizContext config = getFederationConfigurator().getFedizContext("ROOT2");
+        
+        HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class);
+        HttpSession session =  EasyMock.createMock(HttpSession.class);
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_ACTION))
+            .andReturn(FederationConstants.ACTION_SIGNOUT_CLEANUP).anyTimes();
+        EasyMock.expect(req.getSession()).andReturn(session);
+        EasyMock.expect(req.getParameter(FederationConstants.PARAM_REPLY)).andReturn(REPLY_URL).anyTimes();
+        EasyMock.replay(req);
+        
+        LogoutHandler logoutHandler = new LogoutHandler(config);
+        Assert.assertTrue(logoutHandler.canHandleRequest(req));
+        
+        HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
+        resp.setContentType("image/jpeg");
+        ServletOutputStream outputStream = EasyMock.createMock(ServletOutputStream.class);
+        EasyMock.expect(resp.getOutputStream()).andReturn(outputStream);
+        EasyMock.expectLastCall();
+        EasyMock.replay(resp);
+        logoutHandler.handleRequest(req, resp);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/90f41b60/plugins/core/src/test/resources/fediz_test_config_logout.xml
----------------------------------------------------------------------
diff --git a/plugins/core/src/test/resources/fediz_test_config_logout.xml b/plugins/core/src/test/resources/fediz_test_config_logout.xml
new file mode 100644
index 0000000..030281e
--- /dev/null
+++ b/plugins/core/src/test/resources/fediz_test_config_logout.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<FedizConfig>
+	<contextConfig name="ROOT">
+		<audienceUris>
+			<audienceItem>http://host_one:port/url</audienceItem>
+		</audienceUris>
+		<certificateStores>
+			<trustManager>
+				<keyStore file="ststrust.jks" password="storepass"
+					type="JKS" />
+			</trustManager>		
+		</certificateStores>
+		<trustedIssuers>
+			<issuer certificateValidation="PeerTrust" />
+		</trustedIssuers>
+
+		<maximumClockSkew>1000</maximumClockSkew>
+		<protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+			xsi:type="federationProtocolType" version="1.2">
+			<realm>target realm</realm>
+			<issuer>http://url_to_the_issuer</issuer>
+			<roleDelimiter>;</roleDelimiter>
+			<roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI>
+			<authenticationType value="some auth type" type="String" />
+			<freshness>10000</freshness>
+			<reply>reply value</reply>
+			<request>REQUEST</request>
+			<claimTypesRequested>
+				<claimType type="a particular claim type" optional="true" />
+			</claimTypesRequested>
+		</protocol>
+		<logoutURL>secure/logout</logoutURL>
+        <logoutRedirectTo>/index.html</logoutRedirectTo>
+        <logoutRedirectToConstraint>.*wreply.html</logoutRedirectToConstraint>
+	</contextConfig>
+	
+	<contextConfig name="ROOT2">
+		<audienceUris>
+			<audienceItem>http://host_one:port/url</audienceItem>
+		</audienceUris>
+		<certificateStores>
+			<trustManager>
+				<keyStore file="ststrust.jks" password="storepass"
+					type="JKS" />
+			</trustManager>		
+		</certificateStores>
+		<trustedIssuers>
+			<issuer certificateValidation="PeerTrust" />
+		</trustedIssuers>
+
+		<maximumClockSkew>1000</maximumClockSkew>
+		<protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+			xsi:type="federationProtocolType" version="1.2">
+			<realm>target realm</realm>
+			<issuer>http://url_to_the_issuer</issuer>
+			<roleDelimiter>;</roleDelimiter>
+			<roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI>
+			<authenticationType value="some auth type" type="String" />
+			<freshness>10000</freshness>
+			<reply>reply value</reply>
+			<request>REQUEST</request>
+			<claimTypesRequested>
+				<claimType type="a particular claim type" optional="true" />
+			</claimTypesRequested>
+		</protocol>
+		<logoutURL>secure/logout</logoutURL>
+        <logoutRedirectTo>/index.html</logoutRedirectTo>
+	</contextConfig>
+	
+</FedizConfig>


Mime
View raw message