cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject [1/5] cxf-fediz git commit: FEDIZ-200 - Make one of logoutEndpoint or logoutEndpointConstraint mandatory in the IDP
Date Thu, 13 Apr 2017 15:01:09 GMT
Repository: cxf-fediz
Updated Branches:
  refs/heads/1.2.x-fixes 66f1ffa4f -> bf5f471d4


FEDIZ-200 - Make one of logoutEndpoint or logoutEndpointConstraint mandatory in the IDP


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

Branch: refs/heads/1.2.x-fixes
Commit: 30e0d900e3eb77f0417cd41708f2340c11310d25
Parents: 66f1ffa
Author: Colm O hEigeartaigh <coheigea@apache.org>
Authored: Thu Apr 13 13:01:12 2017 +0100
Committer: Colm O hEigeartaigh <coheigea@apache.org>
Committed: Thu Apr 13 14:50:03 2017 +0100

----------------------------------------------------------------------
 .../core/processor/FederationProcessorImpl.java |   7 +
 .../core/federation/FederationLogoutTest.java   |  46 +-
 .../idp/beans/EndpointAddressValidator.java     | 128 +++++
 .../fediz/service/idp/domain/Application.java   |  35 +-
 .../cxf/fediz/service/idp/domain/Idp.java       |  15 +-
 .../idp/service/jpa/ApplicationDAOJPAImpl.java  |   6 +-
 .../idp/service/jpa/ApplicationEntity.java      |  20 +
 .../service/idp/service/jpa/IdpDAOJPAImpl.java  |   6 +-
 .../service/idp/service/jpa/IdpEntity.java      |  12 +-
 .../idp/src/main/resources/entities-realma.xml  |  14 +
 .../WEB-INF/federation-validate-request.xml     |  23 +-
 .../apache/cxf/fediz/systests/idp/IdpTest.java  | 533 ++++++++++++++++++-
 .../test/resources/realma/entities-realma.xml   |   2 +
 .../test/resources/realma/entities-realma.xml   |   1 +
 14 files changed, 794 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/30e0d900/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 fbf7600..646f267 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
@@ -538,6 +538,13 @@ public class FederationProcessorImpl extends AbstractFedizProcessor {
                 sb.append(URLEncoder.encode(logoutRedirectTo, "UTF-8"));
             }
 
+            String realm = resolveWTRealm(request, config);
+            LOG.debug("wtrealm={}", realm);
+
+            // add wtrealm parameter
+            sb.append('&').append(FederationConstants.PARAM_TREALM).append('=').append(URLEncoder
+                                                                                           .encode(realm, "UTF-8"));
+
             redirectURL = redirectURL + "?" + sb.toString();
         } catch (Exception ex) {
             LOG.error("Failed to create SignInRequest", ex);

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/30e0d900/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
index 36a6d96..fd2163e 100644
--- 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
@@ -105,8 +105,9 @@ public class FederationLogoutTest {
         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";
+        String expectedRedirectToIdP =
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Flogout%2Findex.html"
+            + "&wtrealm=target+realm";
         resp.sendRedirect(expectedRedirectToIdP);
         EasyMock.expectLastCall();
         EasyMock.replay(resp);
@@ -119,7 +120,7 @@ public class FederationLogoutTest {
         
         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_URI).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);
@@ -129,8 +130,9 @@ public class FederationLogoutTest {
         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%2Fwreply.html";
+        String expectedRedirectToIdP =
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=" + URLEncoder.encode(REPLY_URL, "UTF-8")
+            + "&wtrealm=target+realm";
         resp.sendRedirect(expectedRedirectToIdP);
         EasyMock.expectLastCall();
         EasyMock.replay(resp);
@@ -153,14 +155,15 @@ public class FederationLogoutTest {
         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";
+        String expectedRedirectToIdP =
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Flogout%2Findex.html"
+            + "&wtrealm=target+realm";
         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");
@@ -177,8 +180,9 @@ public class FederationLogoutTest {
         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";
+        String expectedRedirectToIdP =
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Flogout%2Findex.html"
+            + "&wtrealm=target+realm";
         resp.sendRedirect(expectedRedirectToIdP);
         EasyMock.expectLastCall();
         EasyMock.replay(resp);
@@ -202,8 +206,9 @@ public class FederationLogoutTest {
         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";
+        String expectedRedirectToIdP =
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Findex.html"
+            + "&wtrealm=target+realm";
         resp.sendRedirect(expectedRedirectToIdP);
         EasyMock.expectLastCall();
         EasyMock.replay(resp);
@@ -217,7 +222,7 @@ public class FederationLogoutTest {
         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_URI).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");
@@ -227,8 +232,9 @@ public class FederationLogoutTest {
         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%2Fwreply.html";
+        String expectedRedirectToIdP =
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=" + URLEncoder.encode(REPLY_URL, "UTF-8")
+            + "&wtrealm=target+realm";
         resp.sendRedirect(expectedRedirectToIdP);
         EasyMock.expectLastCall();
         EasyMock.replay(resp);
@@ -252,8 +258,9 @@ public class FederationLogoutTest {
         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";
+        String expectedRedirectToIdP =
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Findex.html"
+            + "&wtrealm=target+realm";
         resp.sendRedirect(expectedRedirectToIdP);
         EasyMock.expectLastCall();
         EasyMock.replay(resp);
@@ -277,8 +284,9 @@ public class FederationLogoutTest {
         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";
+        String expectedRedirectToIdP =
+            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Findex.html"
+            + "&wtrealm=target+realm";
         resp.sendRedirect(expectedRedirectToIdP);
         EasyMock.expectLastCall();
         EasyMock.replay(resp);

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/30e0d900/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/EndpointAddressValidator.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/EndpointAddressValidator.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/EndpointAddressValidator.java
new file mode 100644
index 0000000..536a2e6
--- /dev/null
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/EndpointAddressValidator.java
@@ -0,0 +1,128 @@
+/**
+ * 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;
+
+import java.util.regex.Matcher;
+
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.webflow.execution.RequestContext;
+
+/**
+ * This class is responsible to validate the 'wreply' parameter for WS-Federation, or else the
+ * AssertionConsumer URL address for SAML SSO, by comparing it to a regular expression.
+ */
+@Component
+public class EndpointAddressValidator {
+
+    private static final Logger LOG = LoggerFactory.getLogger(EndpointAddressValidator.class);
+
+    public boolean isValidSigninAddress(RequestContext context, String endpointAddress, String realm)
+        throws Exception {
+        if (endpointAddress == null) {
+            return true;
+        }
+
+        Idp idpConfig = (Idp) WebUtils.getAttributeFromFlowScope(context, "idpConfig");
+        Application serviceConfig = idpConfig.findApplication(realm);
+        if (serviceConfig == null) {
+            LOG.warn("No service config found for " + realm);
+            return false;
+        }
+
+        return validateSigninEndpointAddress(serviceConfig, endpointAddress);
+    }
+
+    public boolean isValidSignoutAddress(RequestContext context, String endpointAddress, String realm)
+        throws Exception {
+        System.out.println("EA: " + endpointAddress + " " + realm);
+        if (endpointAddress == null) {
+            return true;
+        }
+
+        Idp idpConfig = (Idp) WebUtils.getAttributeFromFlowScope(context, "idpConfig");
+        if (idpConfig.isDisableLogoutAddressValidation()) {
+            return true;
+        }
+
+        Application serviceConfig = idpConfig.findApplication(realm);
+        if (serviceConfig == null) {
+            LOG.warn("No service config found for " + realm);
+            return false;
+        }
+
+        return validateSignoutEndpointAddress(serviceConfig, endpointAddress);
+    }
+
+    private boolean validateSigninEndpointAddress(Application serviceConfig, String endpointAddress) {
+        if (serviceConfig.getPassiveRequestorEndpoint() == null
+            && serviceConfig.getCompiledPassiveRequestorEndpointConstraint() == null) {
+            LOG.error("Either the 'passiveRequestorEndpoint' or the 'passiveRequestorEndpointConstraint' "
+                + "configuration values must be specified for the application");
+        } else if (serviceConfig.getPassiveRequestorEndpoint() != null
+            && serviceConfig.getPassiveRequestorEndpoint().equals(endpointAddress)) {
+            LOG.debug("The supplied endpoint address {} matches the configured passive requestor endpoint value",
+                      endpointAddress);
+            return true;
+        } else if (serviceConfig.getCompiledPassiveRequestorEndpointConstraint() != null) {
+            Matcher matcher =
+                serviceConfig.getCompiledPassiveRequestorEndpointConstraint().matcher(endpointAddress);
+            if (matcher.matches()) {
+                return true;
+            } else {
+                LOG.error("The endpointAddress value of {} does not match any of the passive requestor values",
+                          endpointAddress);
+            }
+        }
+
+        return false;
+    }
+
+    private boolean validateSignoutEndpointAddress(Application serviceConfig, String endpointAddress) {
+        System.out.println("HERE");
+        if (serviceConfig.getLogoutEndpoint() == null
+            && serviceConfig.getCompiledLogoutEndpointConstraint() == null) {
+            LOG.error("Either the 'logoutEndpoint' or the 'logoutEndpointConstraint' "
+                + "configuration values must be specified for the application");
+        } else if (serviceConfig.getLogoutEndpoint() != null
+            && serviceConfig.getLogoutEndpoint().equals(endpointAddress)) {
+            LOG.debug("The supplied endpoint address {} matches the configured logout endpoint value",
+                      endpointAddress);
+            return true;
+        } else if (serviceConfig.getCompiledLogoutEndpointConstraint() != null) {
+            Matcher matcher =
+                serviceConfig.getCompiledLogoutEndpointConstraint().matcher(endpointAddress);
+            if (matcher.matches()) {
+                return true;
+            } else {
+                LOG.error("The endpointAddress value of {} does not match any of the logout address values",
+                          endpointAddress);
+            }
+        }
+        
+        System.out.println("RET FALSE");
+
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/30e0d900/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 43c7e8a..fca01e1 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
@@ -34,6 +34,7 @@ import javax.xml.bind.annotation.XmlType;
 @XmlType(propOrder = {"realm", "role", "serviceDisplayName", "serviceDescription", "protocol",
                       "tokenType", "lifeTime", "encryptionCertificate", "requestedClaims",
                       "policyNamespace", "passiveRequestorEndpoint", "passiveRequestorEndpointConstraint", "id" })
+                      "logoutEndpoint", "logoutEndpointConstraint"})
 public class Application implements Serializable {
         
     private static final long serialVersionUID = 5644327504861846964L;
@@ -90,8 +91,13 @@ public class Application implements Serializable {
     // A regular expression constraint on the passiveRequestorEndpoint
     private String passiveRequestorEndpointConstraint;
     private Pattern compiledPassiveRequestorEndpointConstraint;
-    
-    
+
+    private String logoutEndpoint;
+
+    // A regular expression constraint on the logoutEndpoint
+    private String logoutEndpointConstraint;
+    private Pattern compiledLogoutEndpointConstraint;
+
     @XmlAttribute
     public int getId() {
         return id;
@@ -216,4 +222,29 @@ public class Application implements Serializable {
     public Pattern getCompiledPassiveRequestorEndpointConstraint() {
         return compiledPassiveRequestorEndpointConstraint;
     }
+
+    public String getLogoutEndpoint() {
+        return logoutEndpoint;
+    }
+
+    public void setLogoutEndpoint(String logoutEndpoint) {
+        this.logoutEndpoint = logoutEndpoint;
+    }
+
+    public String getLogoutEndpointConstraint() {
+        return logoutEndpointConstraint;
+    }
+
+    public void setLogoutEndpointConstraint(String logoutEndpointConstraint) {
+        this.logoutEndpointConstraint = logoutEndpointConstraint;
+        if (logoutEndpointConstraint != null) {
+            compiledLogoutEndpointConstraint = Pattern.compile(logoutEndpointConstraint);
+        } else {
+            compiledLogoutEndpointConstraint = null;
+        }
+    }
+
+    public Pattern getCompiledLogoutEndpointConstraint() {
+        return compiledLogoutEndpointConstraint;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/30e0d900/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/Idp.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/Idp.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/Idp.java
index 389348b..bc4fe27 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/Idp.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/domain/Idp.java
@@ -35,7 +35,8 @@ import javax.xml.bind.annotation.XmlType;
 @XmlType(propOrder = {"realm", "uri", "serviceDisplayName", "serviceDescription", "idpUrl", "stsUrl",
                      "certificate", "certificatePassword", "provideIdpList", "useCurrentIdp", "hrds",
                      "rpSingleSignOutConfirmation", "supportedProtocols", "tokenTypesOffered", "claimTypesOffered",
-                     "authenticationURIs", "applications", "trustedIdps", "id", "rpSingleSignOutCleanupConfirmation" })
+                     "authenticationURIs", "applications", "trustedIdps", "id", "rpSingleSignOutCleanupConfirmation",
+                     "disableLogoutAddressValidation"})
 public class Idp implements Serializable {
 
     private static final long serialVersionUID = -5570301342547139039L;
@@ -117,7 +118,9 @@ public class Idp implements Serializable {
     
     // Is explicit confirmation required when the "cleanup" URL is called
     private boolean rpSingleSignOutCleanupConfirmation;
-    
+
+    private boolean disableLogoutAddressValidation;
+
     @XmlAttribute
     public int getId() {
         return id;
@@ -301,4 +304,12 @@ public class Idp implements Serializable {
         this.rpSingleSignOutCleanupConfirmation = rpSingleSignOutCleanupConfirmation;
     }
 
+    public boolean isDisableLogoutAddressValidation() {
+        return disableLogoutAddressValidation;
+    }
+
+    public void setDisableLogoutAddressValidation(boolean disableLogoutAddressValidation) {
+        this.disableLogoutAddressValidation = disableLogoutAddressValidation;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/30e0d900/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 4829764..5f56a4d 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
@@ -201,6 +201,8 @@ public class ApplicationDAOJPAImpl implements ApplicationDAO {
         entity.setPolicyNamespace(application.getPolicyNamespace());
         entity.setPassiveRequestorEndpoint(application.getPassiveRequestorEndpoint());
         entity.setPassiveRequestorEndpointConstraint(application.getPassiveRequestorEndpointConstraint());
+        entity.setLogoutEndpoint(application.getLogoutEndpoint());
+        entity.setLogoutEndpointConstraint(entity.getLogoutEndpointConstraint());
     }
     
     public static Application entity2domain(ApplicationEntity entity, List<String> expandList) {
@@ -217,7 +219,9 @@ public class ApplicationDAOJPAImpl implements ApplicationDAO {
         application.setPolicyNamespace(entity.getPolicyNamespace());
         application.setPassiveRequestorEndpoint(entity.getPassiveRequestorEndpoint());
         application.setPassiveRequestorEndpointConstraint(entity.getPassiveRequestorEndpointConstraint());
-        
+        application.setLogoutEndpoint(entity.getLogoutEndpoint());
+        application.setLogoutEndpointConstraint(entity.getLogoutEndpointConstraint());
+
         if (expandList != null && (expandList.contains("all") || expandList.contains("claims"))) {
             for (ApplicationClaimEntity item : entity.getRequestedClaims()) {
                 RequestClaim claim = entity2domain(item);

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/30e0d900/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 e450132..7175a7d 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
@@ -85,6 +85,11 @@ public class ApplicationEntity {
     // A regular expression constraint on the passiveRequestorEndpoint
     private String passiveRequestorEndpointConstraint;
 
+    private String logoutEndpoint;
+
+    // A regular expression constraint on the logoutEndpoint
+    private String logoutEndpointConstraint;
+
 
     public int getId() {
         return id;
@@ -190,4 +195,19 @@ public class ApplicationEntity {
         this.passiveRequestorEndpointConstraint = passiveRequestorEndpointConstraint;
     }
 
+    public String getLogoutEndpoint() {
+        return logoutEndpoint;
+    }
+
+    public void setLogoutEndpoint(String logoutEndpoint) {
+        this.logoutEndpoint = logoutEndpoint;
+    }
+
+    public String getLogoutEndpointConstraint() {
+        return logoutEndpointConstraint;
+    }
+
+    public void setLogoutEndpointConstraint(String logoutEndpointConstraint) {
+        this.logoutEndpointConstraint = logoutEndpointConstraint;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/30e0d900/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpDAOJPAImpl.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpDAOJPAImpl.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpDAOJPAImpl.java
index c553400..502568f 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpDAOJPAImpl.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpDAOJPAImpl.java
@@ -294,7 +294,8 @@ public class IdpDAOJPAImpl implements IdpDAO {
         entity.setUseCurrentIdp(idp.isUseCurrentIdp());
         entity.setRpSingleSignOutConfirmation(idp.isRpSingleSignOutConfirmation());
         entity.setRpSingleSignOutCleanupConfirmation(idp.isRpSingleSignOutCleanupConfirmation());
-        
+        entity.setDisableLogoutAddressValidation(idp.isDisableLogoutAddressValidation());
+
         entity.getAuthenticationURIs().clear();
         for (Map.Entry<String, String> item : idp.getAuthenticationURIs().entrySet()) {
             entity.getAuthenticationURIs().put(item.getKey(), item.getValue());
@@ -328,7 +329,8 @@ public class IdpDAOJPAImpl implements IdpDAO {
         idp.setUseCurrentIdp(entity.isUseCurrentIdp());
         idp.setRpSingleSignOutConfirmation(entity.isRpSingleSignOutConfirmation());
         idp.setRpSingleSignOutCleanupConfirmation(entity.isRpSingleSignOutCleanupConfirmation());
-        
+        idp.setDisableLogoutAddressValidation(entity.isDisableLogoutAddressValidation());
+
         if (expandList != null && (expandList.contains("all") || expandList.contains("applications"))) {
             for (ApplicationEntity item : entity.getApplications()) {
                 Application application = ApplicationDAOJPAImpl.entity2domain(item, expandList);

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/30e0d900/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpEntity.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpEntity.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpEntity.java
index 1eda135..0ea23f4 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpEntity.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpEntity.java
@@ -134,9 +134,11 @@ public class IdpEntity {
 
     // ServiceDescription
     private String serviceDescription;
-    
+
     private boolean rpSingleSignOutCleanupConfirmation;
 
+    private boolean disableLogoutAddressValidation;
+
 
     public int getId() {
         return id;
@@ -298,4 +300,12 @@ public class IdpEntity {
         this.rpSingleSignOutCleanupConfirmation = rpSingleSignOutCleanupConfirmation;
     }
 
+    public boolean isDisableLogoutAddressValidation() {
+        return disableLogoutAddressValidation;
+    }
+
+    public void setDisableLogoutAddressValidation(boolean disableLogoutAddressValidation) {
+        this.disableLogoutAddressValidation = disableLogoutAddressValidation;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/30e0d900/services/idp/src/main/resources/entities-realma.xml
----------------------------------------------------------------------
diff --git a/services/idp/src/main/resources/entities-realma.xml b/services/idp/src/main/resources/entities-realma.xml
index 2965df9..cdb116f 100644
--- a/services/idp/src/main/resources/entities-realma.xml
+++ b/services/idp/src/main/resources/entities-realma.xml
@@ -105,6 +105,20 @@
         <property name="lifeTime" value="3600" />
         <property name="passiveRequestorEndpointConstraint" 
                   value="https://localhost:?(\d)*/.*" />
+        <property name="logoutEndpointConstraint" value="https://localhost:?(\d)*/.*" />
+    </bean>
+	
+	<bean id="srv-oidc" class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationEntity">
+        <property name="realm" value="urn:org:apache:cxf:fediz:oidc" />
+        <property name="protocol" value="http://docs.oasis-open.org/wsfed/federation/200706" />
+        <property name="serviceDisplayName" value="OIDC Provider" />
+        <property name="serviceDescription" value="OpenID Connect Provider" />
+        <property name="role" value="ApplicationServiceType" />
+        <property name="tokenType" value="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0" />
+        <property name="lifeTime" value="3600" />
+        <property name="passiveRequestorEndpointConstraint" value="https://localhost:?(\d)*/fediz-oidc/.*" />
+        <property name="logoutEndpointConstraint" value="https://localhost:?(\d)*/.*" />
+>>>>>>> 5eba7a0... FEDIZ-200 - Make one of logoutEndpoint or logoutEndpointConstraint mandatory in the IDP
     </bean>
     
     <bean class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationClaimEntity">

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/30e0d900/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml
----------------------------------------------------------------------
diff --git a/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml b/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml
index 733d5d3..d37b13a 100644
--- a/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml
+++ b/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml
@@ -40,7 +40,7 @@
         </on-entry>
         <if
             test="requestParameters.wa == 'wsignout1.0' or requestParameters.wa == 'wsignoutcleanup1.0'"
-            then="selectSignOutProcess" />
+            then="validateWReplyForSignout" />
         <if
             test="requestParameters.wa == 'wsignin1.0'" then="selectWsFedProcess" 
             else="selectSAMLProcess" /> 
@@ -63,15 +63,16 @@
     </decision-state>
     
     <action-state id="validateWReplyForSignout">
-        <evaluate expression="commonsURLValidator.isValid(flowRequestContext, flowScope.wreply)"/>
+        <on-entry>
+            <evaluate expression="@org.apache.cxf.fediz.service.idp.util.WebUtils@getHttpHeader(flowRequestContext, 'Referer')" result="flowScope.wreply"/>
+        </on-entry>
+        <evaluate expression="commonsURLValidator.isValid(flowRequestContext, flowScope.wreply)
+                              and endpointAddressValidator.isValidSignoutAddress(flowRequestContext, flowScope.wreply, flowScope.wtrealm)"/>
         <transition on="yes" to="selectSignOutProcess" />
-        <transition on="no" to="viewBadRequest" />
+        <transition on="no" to="viewBadRequestAndLogout" />
     </action-state>
 	
     <decision-state id="selectSignOutProcess">
-        <on-entry>
-            <evaluate expression="@org.apache.cxf.fediz.service.idp.util.WebUtils@getHttpHeader(flowRequestContext, 'Referer')" result="flowScope.wreply"/>
-        </on-entry>
         <if
             test="requestParameters.wa == 'wsignout1.0' and flowScope.idpConfig.rpSingleSignOutConfirmation == true
             or requestParameters.wa == 'wsignoutcleanup1.0' and flowScope.idpConfig.rpSingleSignOutCleanupConfirmation == true"
@@ -185,6 +186,16 @@
         </on-entry>
     </end-state>
 
+	<end-state id="viewBadRequestAndLogout" view="genericerror">
+		<on-entry>
+			<evaluate expression="homeRealmReminder.removeCookie(flowRequestContext)" />
+			<evaluate expression="logoutAction.submit(flowRequestContext)" />
+			<evaluate
+				expression="externalContext.nativeResponse.setStatus(400,flowRequestContext.currentTransition.toString())" />
+			<!--<set name="requestScope.reason" value="flowRequestContext.currentTransition" />-->
+		</on-entry>
+	</end-state>
+
     <!-- abnormal exit point : Http 500 Internal Server Error -->
     <end-state id="scInternalServerError" view="genericerror">
         <on-entry>

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/30e0d900/systests/idp/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java
----------------------------------------------------------------------
diff --git a/systests/idp/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java b/systests/idp/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java
index b0e5816..61d10ff 100644
--- a/systests/idp/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java
+++ b/systests/idp/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java
@@ -84,7 +84,7 @@ public class IdpTest {
         WSSConfig.init();
     }
 
-    private static Tomcat startServer(boolean idp, String port) 
+    private static Tomcat startServer(boolean idp, String port)
         throws ServletException, LifecycleException, IOException {
         Tomcat server = new Tomcat();
         server.setPort(0);
@@ -127,7 +127,7 @@ public class IdpTest {
     public static void cleanup() {
         shutdownServer(idpServer);
     }
-    
+
     private static void shutdownServer(Tomcat server) {
         try {
             if (server != null && server.getServer() != null
@@ -190,7 +190,7 @@ public class IdpTest {
 
         Assert.assertNotNull(wresult);
     }
-    
+
     @org.junit.Test
     public void testSuccessfulSSOInvokeOnIdP() throws Exception {
         String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?";
@@ -206,7 +206,7 @@ public class IdpTest {
         final WebClient webClient = new WebClient();
         webClient.getOptions().setUseInsecureSSL(true);
         webClient.addRequestHeader("Authorization", "Basic " + Base64.encode((user + ":" + password).getBytes()));
-        
+
         //
         // First invocation
         //
@@ -228,14 +228,14 @@ public class IdpTest {
         }
 
         Assert.assertNotNull(wresult);
-        
+
         //
         // Second invocation - change the credentials to make sure the session is set up correctly
-        // 
+        //
 
         webClient.removeRequestHeader("Authorization");
         webClient.addRequestHeader("Authorization", "Basic " + Base64.encode(("mallory" + ":" + password).getBytes()));
-        
+
         webClient.getOptions().setJavaScriptEnabled(false);
         idpPage = webClient.getPage(url);
         webClient.getOptions().setJavaScriptEnabled(true);
@@ -253,6 +253,7 @@ public class IdpTest {
         }
 
         Assert.assertNotNull(wresult);
+
     }
 
     @Test
@@ -420,7 +421,7 @@ public class IdpTest {
             Assert.assertEquals(ex.getStatusCode(), 400);
         }
     }
-    
+
     // Send an unknown wa value
     @org.junit.Test
     public void testBadWa() throws Exception {
@@ -448,7 +449,7 @@ public class IdpTest {
             Assert.assertEquals(ex.getStatusCode(), 400);
         }
     }
-    
+
     // Send an unknown whr value
     @org.junit.Test
     public void testBadWHR() throws Exception {
@@ -476,7 +477,7 @@ public class IdpTest {
             Assert.assertEquals(ex.getStatusCode(), 500);
         }
     }
-    
+
     // Send an unknown wtrealm value
     @org.junit.Test
     public void testBadWtRealm() throws Exception {
@@ -504,7 +505,7 @@ public class IdpTest {
             Assert.assertEquals(ex.getStatusCode(), 400);
         }
     }
-    
+
     // Send an malformed wreply value
     @org.junit.Test
     public void testMalformedWReply() throws Exception {
@@ -532,7 +533,7 @@ public class IdpTest {
             Assert.assertEquals(ex.getStatusCode(), 400);
         }
     }
-    
+
     // Send a bad wreply value
     @org.junit.Test
     public void testBadWReply() throws Exception {
@@ -540,7 +541,7 @@ public class IdpTest {
         url += "wa=wsignin1.0";
         url += "&whr=urn:org:apache:cxf:fediz:idp:realm-A";
         url += "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld";
-        String wreply = "https://www.apache.org:" + getRpHttpsPort() + "/" 
+        String wreply = "https://www.apache.org:" + getRpHttpsPort() + "/"
             + getServletContextName() + "/secure/fedservlet";
         url += "&wreply=" + wreply;
 
@@ -561,7 +562,7 @@ public class IdpTest {
             Assert.assertEquals(ex.getStatusCode(), 400);
         }
     }
-    
+
     @org.junit.Test
     public void testValidWReplyWrongApplication() throws Exception {
         String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?";
@@ -588,7 +589,7 @@ public class IdpTest {
             Assert.assertEquals(ex.getStatusCode(), 400);
         }
     }
-    
+
     @org.junit.Test
     public void testWReplyExactMatchingSuccess() throws Exception {
         String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?";
@@ -610,14 +611,14 @@ public class IdpTest {
         webClient.getOptions().setJavaScriptEnabled(false);
         webClient.getPage(url);
     }
-    
+
     @org.junit.Test
     public void testWReplyExactMatchingFailure() throws Exception {
         String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?";
         url += "wa=wsignin1.0";
         url += "&whr=urn:org:apache:cxf:fediz:idp:realm-A";
         url += "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld3";
-        String wreply = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() 
+        String wreply = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName()
             + "/secure/fedservlet/blah";
         url += "&wreply=" + wreply;
 
@@ -638,7 +639,7 @@ public class IdpTest {
             Assert.assertEquals(ex.getStatusCode(), 400);
         }
     }
-    
+
     @org.junit.Test
     public void testNoEndpointAddressOrConstraint() throws Exception {
         String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?";
@@ -666,8 +667,8 @@ public class IdpTest {
             Assert.assertEquals(ex.getStatusCode(), 400);
         }
     }
-    
-    // Send a bad wreply value. This will pass the reg ex validation but fail the commons-validator 
+
+    // Send a bad wreply value. This will pass the reg ex validation but fail the commons-validator
     // validation
     @org.junit.Test
     public void testWReplyWithDoubleSlashes() throws Exception {
@@ -675,7 +676,7 @@ public class IdpTest {
         url += "wa=wsignin1.0";
         url += "&whr=urn:org:apache:cxf:fediz:idp:realm-A";
         url += "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld";
-        String wreply = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() 
+        String wreply = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName()
             + "/secure//fedservlet";
         url += "&wreply=" + wreply;
 
@@ -697,4 +698,494 @@ public class IdpTest {
         }
     }
     
+    @Test
+    public void testIdPLogout() throws Exception {
+
+        // 1. First let's login to the IdP
+        String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?";
+        url += "wa=wsignin1.0";
+        url += "&whr=urn:org:apache:cxf:fediz:idp:realm-A";
+        url += "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld";
+        String wreply = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + "/secure/fedservlet";
+        url += "&wreply=" + wreply;
+
+        String user = "alice";
+        String password = "ecila";
+
+        CookieManager cookieManager = new CookieManager();
+
+        WebClient webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getCredentialsProvider().setCredentials(
+            new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())),
+            new UsernamePasswordCredentials(user, password));
+
+        webClient.getOptions().setJavaScriptEnabled(false);
+        HtmlPage idpPage = webClient.getPage(url);
+        webClient.getOptions().setJavaScriptEnabled(true);
+        Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
+        webClient.close();
+
+        // 2. now we logout from IdP
+        String idpLogoutUrl = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?wa="
+            + FederationConstants.ACTION_SIGNOUT;
+
+        webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        idpPage = webClient.getPage(idpLogoutUrl);
+
+        Assert.assertEquals("IDP SignOut Confirmation Response Page", idpPage.getTitleText());
+
+        HtmlForm form = idpPage.getFormByName("signoutconfirmationresponseform");
+        HtmlSubmitInput button = form.getInputByName("_eventId_submit");
+        button.click();
+
+        webClient.close();
+
+        // 3. now we try to access the idp without authentication but with the existing cookies
+        // to see if we are really logged out
+        webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
+        idpPage = webClient.getPage(url);
+
+        Assert.assertEquals(401, idpPage.getWebResponse().getStatusCode());
+
+        webClient.close();
+    }
+
+    @Test
+    public void testIdPLogoutCleanup() throws Exception {
+
+        // 1. First let's login to the IdP
+        String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?";
+        url += "wa=wsignin1.0";
+        url += "&whr=urn:org:apache:cxf:fediz:idp:realm-A";
+        url += "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld";
+        String wreply = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + "/secure/fedservlet";
+        url += "&wreply=" + wreply;
+
+        String user = "alice";
+        String password = "ecila";
+
+        CookieManager cookieManager = new CookieManager();
+
+        WebClient webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getCredentialsProvider().setCredentials(
+            new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())),
+            new UsernamePasswordCredentials(user, password));
+
+        webClient.getOptions().setJavaScriptEnabled(false);
+        HtmlPage idpPage = webClient.getPage(url);
+        webClient.getOptions().setJavaScriptEnabled(true);
+        Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
+        webClient.close();
+
+        // 2. now we logout from IdP
+        String idpLogoutUrl = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?wa="
+            + FederationConstants.ACTION_SIGNOUT_CLEANUP;
+
+        webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        idpPage = webClient.getPage(idpLogoutUrl);
+
+        Assert.assertEquals("IDP SignOut Response Page", idpPage.getTitleText());
+
+        webClient.close();
+
+        // 3. now we try to access the idp without authentication but with the existing cookies
+        // to see if we are really logged out
+        webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
+        idpPage = webClient.getPage(url);
+
+        Assert.assertEquals(401, idpPage.getWebResponse().getStatusCode());
+
+        webClient.close();
+    }
+
+    @Test
+    public void testIdPLogoutCleanupWithBadWReply() throws Exception {
+
+        // 1. First let's login to the IdP
+        String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?";
+        url += "wa=wsignin1.0";
+        url += "&whr=urn:org:apache:cxf:fediz:idp:realm-A";
+        url += "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld";
+        String wreply = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + "/secure/fedservlet";
+        url += "&wreply=" + wreply;
+
+        String user = "alice";
+        String password = "ecila";
+
+        CookieManager cookieManager = new CookieManager();
+
+        WebClient webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getCredentialsProvider().setCredentials(
+            new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())),
+            new UsernamePasswordCredentials(user, password));
+
+        webClient.getOptions().setJavaScriptEnabled(false);
+        HtmlPage idpPage = webClient.getPage(url);
+        webClient.getOptions().setJavaScriptEnabled(true);
+        Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
+        webClient.close();
+
+        // 2. now we logout from IdP using a bad wreply
+        String badWReply = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName()
+            + "/secure//fedservlet";
+        String idpLogoutUrl = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?wa="
+            + FederationConstants.ACTION_SIGNOUT_CLEANUP;
+        idpLogoutUrl += "&wreply=" + badWReply;
+
+        webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        try {
+            webClient.getPage(idpLogoutUrl);
+            Assert.fail("Failure expected on a bad wreply value");
+        } catch (FailingHttpStatusCodeException ex) {
+            Assert.assertEquals(ex.getStatusCode(), 400);
+        }
+
+        webClient.close();
+
+        // 3. now we try to access the idp without authentication but with the existing cookies
+        // to see if we are really logged out. Even though an error was thrown on a bad wreply, we should still
+        // be logged out
+        webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
+        idpPage = webClient.getPage(url);
+
+        Assert.assertEquals(401, idpPage.getWebResponse().getStatusCode());
+
+        webClient.close();
+    }
+
+    @Test
+    public void testIdPLogoutWithWreplyConstraint() throws Exception {
+
+        // 1. First let's login to the IdP
+        String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?";
+        url += "wa=wsignin1.0";
+        url += "&whr=urn:org:apache:cxf:fediz:idp:realm-A";
+        url += "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld";
+        String wreply = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + "/secure/fedservlet";
+        url += "&wreply=" + wreply;
+
+        String user = "alice";
+        String password = "ecila";
+
+        CookieManager cookieManager = new CookieManager();
+
+        WebClient webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getCredentialsProvider().setCredentials(
+            new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())),
+            new UsernamePasswordCredentials(user, password));
+
+        webClient.getOptions().setJavaScriptEnabled(false);
+        HtmlPage idpPage = webClient.getPage(url);
+        webClient.getOptions().setJavaScriptEnabled(true);
+        Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
+        webClient.close();
+
+        // 2. now we logout from IdP
+        String logoutWReply = "https://localhost:12345";
+        String idpLogoutUrl = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?wa="
+            + FederationConstants.ACTION_SIGNOUT + "&wreply=" + logoutWReply
+            + "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld";
+
+        webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        idpPage = webClient.getPage(idpLogoutUrl);
+
+        Assert.assertEquals("IDP SignOut Confirmation Response Page", idpPage.getTitleText());
+
+        HtmlForm form = idpPage.getFormByName("signoutconfirmationresponseform");
+        HtmlSubmitInput button = form.getInputByName("_eventId_submit");
+        button.click();
+
+        webClient.close();
+
+        // 3. now we try to access the idp without authentication but with the existing cookies
+        // to see if we are really logged out
+        webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
+        idpPage = webClient.getPage(url);
+
+        Assert.assertEquals(401, idpPage.getWebResponse().getStatusCode());
+
+        webClient.close();
+    }
+
+    @Test
+    public void testIdPLogoutWithWreplyBadAddress() throws Exception {
+
+        // 1. First let's login to the IdP
+        String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?";
+        url += "wa=wsignin1.0";
+        url += "&whr=urn:org:apache:cxf:fediz:idp:realm-A";
+        url += "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld";
+        String wreply = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + "/secure/fedservlet";
+        url += "&wreply=" + wreply;
+
+        String user = "alice";
+        String password = "ecila";
+
+        CookieManager cookieManager = new CookieManager();
+
+        WebClient webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getCredentialsProvider().setCredentials(
+            new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())),
+            new UsernamePasswordCredentials(user, password));
+
+        webClient.getOptions().setJavaScriptEnabled(false);
+        HtmlPage idpPage = webClient.getPage(url);
+        webClient.getOptions().setJavaScriptEnabled(true);
+        Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
+        webClient.close();
+
+        // 2. now we logout from IdP
+        String logoutWReply = "https://localhost:123456";
+        String idpLogoutUrl = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?wa="
+            + FederationConstants.ACTION_SIGNOUT + "&wreply=" + logoutWReply
+            + "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld";
+
+        webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        try {
+            webClient.getPage(idpLogoutUrl);
+            Assert.fail("Failure expected on a non-matching wreply address");
+        } catch (FailingHttpStatusCodeException ex) {
+            Assert.assertEquals(ex.getStatusCode(), 400);
+        }
+
+        webClient.close();
+    }
+
+    @Test
+    public void testIdPLogoutWithNoRealm() throws Exception {
+
+        // 1. First let's login to the IdP
+        String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?";
+        url += "wa=wsignin1.0";
+        url += "&whr=urn:org:apache:cxf:fediz:idp:realm-A";
+        url += "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld";
+        String wreply = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + "/secure/fedservlet";
+        url += "&wreply=" + wreply;
+
+        String user = "alice";
+        String password = "ecila";
+
+        CookieManager cookieManager = new CookieManager();
+
+        WebClient webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getCredentialsProvider().setCredentials(
+            new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())),
+            new UsernamePasswordCredentials(user, password));
+
+        webClient.getOptions().setJavaScriptEnabled(false);
+        HtmlPage idpPage = webClient.getPage(url);
+        webClient.getOptions().setJavaScriptEnabled(true);
+        Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
+        webClient.close();
+
+        // 2. now we logout from IdP
+        String logoutWReply = "https://localhost:12345";
+        String idpLogoutUrl = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?wa="
+            + FederationConstants.ACTION_SIGNOUT + "&wreply=" + logoutWReply;
+
+        webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        try {
+            webClient.getPage(idpLogoutUrl);
+            Assert.fail("Failure expected on a non-matching wreply address");
+        } catch (FailingHttpStatusCodeException ex) {
+            Assert.assertEquals(ex.getStatusCode(), 400);
+        }
+
+        webClient.close();
+    }
+
+    @Test
+    public void testIdPLogoutWithWreplyAddress() throws Exception {
+
+        // 1. First let's login to the IdP
+        String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?";
+        url += "wa=wsignin1.0";
+        url += "&whr=urn:org:apache:cxf:fediz:idp:realm-A";
+        url += "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld3";
+        String wreply = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + "/secure/fedservlet";
+        url += "&wreply=" + wreply;
+
+        String user = "alice";
+        String password = "ecila";
+
+        CookieManager cookieManager = new CookieManager();
+
+        WebClient webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getCredentialsProvider().setCredentials(
+            new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())),
+            new UsernamePasswordCredentials(user, password));
+
+        webClient.getOptions().setJavaScriptEnabled(false);
+        HtmlPage idpPage = webClient.getPage(url);
+        webClient.getOptions().setJavaScriptEnabled(true);
+        Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
+        webClient.close();
+
+        // 2. now we logout from IdP
+        String logoutWReply = "https://localhost:12345";
+        String idpLogoutUrl = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?wa="
+            + FederationConstants.ACTION_SIGNOUT + "&wreply=" + logoutWReply
+            + "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld3";
+
+        webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        idpPage = webClient.getPage(idpLogoutUrl);
+
+        Assert.assertEquals("IDP SignOut Confirmation Response Page", idpPage.getTitleText());
+
+        HtmlForm form = idpPage.getFormByName("signoutconfirmationresponseform");
+        HtmlSubmitInput button = form.getInputByName("_eventId_submit");
+        button.click();
+
+        webClient.close();
+
+        // 3. now we try to access the idp without authentication but with the existing cookies
+        // to see if we are really logged out
+        webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
+        idpPage = webClient.getPage(url);
+
+        Assert.assertEquals(401, idpPage.getWebResponse().getStatusCode());
+
+        webClient.close();
+    }
+
+    @Test
+    public void testIdPLogoutWithBadAddress() throws Exception {
+
+        // 1. First let's login to the IdP
+        String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?";
+        url += "wa=wsignin1.0";
+        url += "&whr=urn:org:apache:cxf:fediz:idp:realm-A";
+        url += "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld3";
+        String wreply = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + "/secure/fedservlet";
+        url += "&wreply=" + wreply;
+
+        String user = "alice";
+        String password = "ecila";
+
+        CookieManager cookieManager = new CookieManager();
+
+        WebClient webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getCredentialsProvider().setCredentials(
+            new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())),
+            new UsernamePasswordCredentials(user, password));
+
+        webClient.getOptions().setJavaScriptEnabled(false);
+        HtmlPage idpPage = webClient.getPage(url);
+        webClient.getOptions().setJavaScriptEnabled(true);
+        Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
+        webClient.close();
+
+        // 2. now we logout from IdP
+        String logoutWReply = "https://localhost:123456";
+        String idpLogoutUrl = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?wa="
+            + FederationConstants.ACTION_SIGNOUT + "&wreply=" + logoutWReply
+            + "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld3";
+
+        webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        try {
+            webClient.getPage(idpLogoutUrl);
+            Assert.fail("Failure expected on a non-matching wreply address");
+        } catch (FailingHttpStatusCodeException ex) {
+            Assert.assertEquals(ex.getStatusCode(), 400);
+        }
+
+        webClient.close();
+    }
+
+    @Test
+    public void testIdPLogoutWithNoConfiguredConstraint() throws Exception {
+
+        // 1. First let's login to the IdP
+        String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?";
+        url += "wa=wsignin1.0";
+        url += "&whr=urn:org:apache:cxf:fediz:idp:realm-A";
+        url += "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld2";
+        String wreply = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + "/secure2/fedservlet";
+        url += "&wreply=" + wreply;
+
+        String user = "alice";
+        String password = "ecila";
+
+        CookieManager cookieManager = new CookieManager();
+
+        WebClient webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        webClient.getCredentialsProvider().setCredentials(
+            new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())),
+            new UsernamePasswordCredentials(user, password));
+
+        webClient.getOptions().setJavaScriptEnabled(false);
+        HtmlPage idpPage = webClient.getPage(url);
+        webClient.getOptions().setJavaScriptEnabled(true);
+        Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
+        webClient.close();
+
+        // 2. now we logout from IdP
+        String logoutWReply = "https://localhost:12345";
+        String idpLogoutUrl = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/federation?wa="
+            + FederationConstants.ACTION_SIGNOUT + "&wreply=" + logoutWReply
+            + "&wtrealm=urn:org:apache:cxf:fediz:fedizhelloworld2";
+
+        webClient = new WebClient();
+        webClient.setCookieManager(cookieManager);
+        webClient.getOptions().setUseInsecureSSL(true);
+        try {
+            webClient.getPage(idpLogoutUrl);
+            Assert.fail("Failure expected on a non-matching wreply address");
+        } catch (FailingHttpStatusCodeException ex) {
+            Assert.assertEquals(ex.getStatusCode(), 400);
+        }
+
+        webClient.close();
+    }
+
+>>>>>>> 5eba7a0... FEDIZ-200 - Make one of logoutEndpoint or logoutEndpointConstraint mandatory in the IDP
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/30e0d900/systests/idp/src/test/resources/realma/entities-realma.xml
----------------------------------------------------------------------
diff --git a/systests/idp/src/test/resources/realma/entities-realma.xml b/systests/idp/src/test/resources/realma/entities-realma.xml
index 76008b1..51ca9df 100644
--- a/systests/idp/src/test/resources/realma/entities-realma.xml
+++ b/systests/idp/src/test/resources/realma/entities-realma.xml
@@ -108,6 +108,7 @@
         <property name="tokenType" value="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0" />
         <property name="lifeTime" value="3600" />
         <property name="passiveRequestorEndpointConstraint" value="https://localhost:(\d)*/(\w)*helloworld(\w)*/secure/.*"/>
+        <property name="logoutEndpointConstraint" value="https://localhost:(\d)*" />
     </bean>
     
     <bean id="srv-fedizhelloworld2" class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationEntity">
@@ -132,6 +133,7 @@
         <property name="lifeTime" value="3600" />
         <property name="passiveRequestorEndpoint" 
                   value="https://localhost:${rp.https.port}/fedizhelloworld/secure/fedservlet" />
+        <property name="logoutEndpoint" value="https://localhost:12345" />
     </bean>
     
     <bean id="srv-fedizhelloworld4" class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationEntity">

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/30e0d900/systests/tomcat7/src/test/resources/realma/entities-realma.xml
----------------------------------------------------------------------
diff --git a/systests/tomcat7/src/test/resources/realma/entities-realma.xml b/systests/tomcat7/src/test/resources/realma/entities-realma.xml
index f947274..95bfc9d 100644
--- a/systests/tomcat7/src/test/resources/realma/entities-realma.xml
+++ b/systests/tomcat7/src/test/resources/realma/entities-realma.xml
@@ -106,6 +106,7 @@
         <property name="lifeTime" value="3600" />
         <property name="passiveRequestorEndpointConstraint" 
                   value="https://localhost:(\d)*/(\w)*helloworld(\w)*/secure/.*" />
+        <property name="logoutEndpointConstraint" value="https://localhost:?(\d)*/.*" />
     </bean>
     
     <bean class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationClaimEntity">


Mime
View raw message