cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject cxf-fediz git commit: FEDIZ-200 - Make one of logoutEndpoint or logoutEndpointConstraint mandatory in the IDP
Date Thu, 13 Apr 2017 12:01:24 GMT
Repository: cxf-fediz
Updated Branches:
  refs/heads/master 87fd3dfce -> c49a9e28d


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/c49a9e28
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/c49a9e28
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/c49a9e28

Branch: refs/heads/master
Commit: c49a9e28d11ec450bbd3d56efa07b1a5dd54481f
Parents: 87fd3df
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 13:01:12 2017 +0100

----------------------------------------------------------------------
 .../core/processor/FederationProcessorImpl.java |   7 +
 .../core/federation/FederationLogoutTest.java   |  37 ++-
 .../idp/beans/EndpointAddressValidator.java     | 124 ++++++++
 .../idp/beans/PassiveRequestorValidator.java    |  76 -----
 .../fediz/service/idp/domain/Application.java   |  33 +-
 .../cxf/fediz/service/idp/domain/Idp.java       |  14 +-
 .../idp/service/jpa/ApplicationDAOJPAImpl.java  |   4 +
 .../idp/service/jpa/ApplicationEntity.java      |  21 ++
 .../service/idp/service/jpa/IdpDAOJPAImpl.java  |   2 +
 .../service/idp/service/jpa/IdpEntity.java      |  12 +-
 .../idp/src/main/resources/entities-realma.xml  |   2 +
 .../flows/federation-validate-request.xml       |   3 +-
 .../webapp/WEB-INF/flows/signin-request.xml     |   2 +-
 .../apache/cxf/fediz/systests/idp/IdpTest.java  | 313 +++++++++++++++++++
 .../test/resources/realma/entities-realma.xml   |   2 +
 .../test/resources/realma/entities-realma.xml   |   1 +
 .../test/resources/realma/entities-realma.xml   |   1 +
 17 files changed, 559 insertions(+), 95 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c49a9e28/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 83d2d1b..4bd5741 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"));
+
             String signOutQuery = resolveSignOutQuery(request, config);
             LOG.debug("SignIn Query: {}", signOutQuery);
 

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c49a9e28/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 13bc2ad..3599a29 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,7 +105,8 @@ public class FederationLogoutTest {
 
         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";
+            "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);
@@ -129,7 +130,8 @@ public class FederationLogoutTest {
 
         HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
         String expectedRedirectToIdP =
-            "http://url_to_the_issuer?wa=wsignout1.0&wreply=" + URLEncoder.encode(REPLY_URL, "UTF-8");
+            "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,13 +155,14 @@ public class FederationLogoutTest {
 
         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";
+            "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 testSignoutValidatorWithWReply() throws Exception {
         FedizContext config = getFederationConfigurator().getFedizContext("ROOT5");
@@ -177,7 +180,8 @@ public class FederationLogoutTest {
 
         HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
         String expectedRedirectToIdP =
-            "http://url_to_the_issuer?wa=wsignout1.0&wreply=" + URLEncoder.encode(REPLY_URL, "UTF-8");
+            "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);
@@ -201,7 +205,8 @@ public class FederationLogoutTest {
 
         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";
+            "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);
@@ -225,7 +230,8 @@ public class FederationLogoutTest {
 
         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";
+            "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);
@@ -249,7 +255,8 @@ public class FederationLogoutTest {
 
         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";
+            "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);
@@ -274,7 +281,8 @@ public class FederationLogoutTest {
 
         HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
         String expectedRedirectToIdP =
-            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Findex.html";
+            "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);
@@ -299,7 +307,8 @@ public class FederationLogoutTest {
 
         HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
         String expectedRedirectToIdP =
-            "http://url_to_the_issuer?wa=wsignout1.0&wreply=" + URLEncoder.encode(REPLY_URL, "UTF-8");
+            "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);
@@ -324,7 +333,8 @@ public class FederationLogoutTest {
 
         HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
         String expectedRedirectToIdP =
-            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Findex.html";
+            "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);
@@ -349,7 +359,8 @@ public class FederationLogoutTest {
 
         HttpServletResponse resp = EasyMock.createMock(HttpServletResponse.class);
         String expectedRedirectToIdP =
-            "http://url_to_the_issuer?wa=wsignout1.0&wreply=https%3A%2F%2Flocalhost%2Fsecure%2Findex.html";
+            "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);
@@ -445,7 +456,7 @@ public class FederationLogoutTest {
         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"
-            + "&custom=param";
+            + "&wtrealm=target+realm&custom=param";
         resp.sendRedirect(expectedRedirectToIdP);
         EasyMock.expectLastCall();
         EasyMock.replay(resp);

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c49a9e28/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/EndpointAddressValidator.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/EndpointAddressValidator.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/EndpointAddressValidator.java
new file mode 100644
index 0000000..de193b8
--- /dev/null
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/EndpointAddressValidator.java
@@ -0,0 +1,124 @@
+/**
+ * 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 {
+        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) {
+        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);
+            }
+        }
+
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c49a9e28/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/PassiveRequestorValidator.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/PassiveRequestorValidator.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/PassiveRequestorValidator.java
deleted file mode 100644
index 7ef61b2..0000000
--- a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/PassiveRequestorValidator.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cxf.fediz.service.idp.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 PassiveRequestorValidator {
-
-    private static final Logger LOG = LoggerFactory.getLogger(PassiveRequestorValidator.class);
-
-    public boolean isValid(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;
-        }
-
-        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;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c49a9e28/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Application.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Application.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Application.java
index 1373000..2ade3d1 100644
--- a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Application.java
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Application.java
@@ -34,7 +34,7 @@ import javax.xml.bind.annotation.XmlType;
 @XmlType(propOrder = {"realm", "role", "serviceDisplayName", "serviceDescription", "protocol",
                       "tokenType", "lifeTime", "encryptionCertificate", "requestedClaims",
                       "policyNamespace", "passiveRequestorEndpoint", "passiveRequestorEndpointConstraint", "id",
-                      "validatingCertificate", "enableAppliesTo"})
+                      "validatingCertificate", "enableAppliesTo", "logoutEndpoint", "logoutEndpointConstraint"})
 public class Application implements Serializable {
 
     private static final long serialVersionUID = 5644327504861846964L;
@@ -98,6 +98,12 @@ public class Application implements Serializable {
     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() {
@@ -239,4 +245,29 @@ public class Application implements Serializable {
     public void setEnableAppliesTo(boolean useAudienceRestriction) {
         this.enableAppliesTo = useAudienceRestriction;
     }
+
+    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/c49a9e28/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Idp.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Idp.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Idp.java
index 2fc7a64..c41348c 100644
--- a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Idp.java
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/domain/Idp.java
@@ -36,7 +36,7 @@ import javax.xml.bind.annotation.XmlType;
                      "certificate", "certificatePassword", "provideIdpList", "useCurrentIdp", "hrds",
                      "rpSingleSignOutConfirmation", "supportedProtocols", "tokenTypesOffered", "claimTypesOffered",
                      "authenticationURIs", "applications", "trustedIdps", "id", "rpSingleSignOutCleanupConfirmation",
-                     "automaticRedirectToRpAfterLogout"})
+                     "automaticRedirectToRpAfterLogout", "disableLogoutAddressValidation"})
 public class Idp implements Serializable {
 
     private static final long serialVersionUID = -5570301342547139039L;
@@ -118,9 +118,11 @@ public class Idp implements Serializable {
 
     // Is explicit confirmation required when the "cleanup" URL is called
     private boolean rpSingleSignOutCleanupConfirmation;
-    
+
     private boolean automaticRedirectToRpAfterLogout;
 
+    private boolean disableLogoutAddressValidation;
+
     @XmlAttribute
     public int getId() {
         return id;
@@ -312,4 +314,12 @@ public class Idp implements Serializable {
         this.automaticRedirectToRpAfterLogout = automaticRedirectToRpAfterLogout;
     }
 
+    public boolean isDisableLogoutAddressValidation() {
+        return disableLogoutAddressValidation;
+    }
+
+    public void setDisableLogoutAddressValidation(boolean disableLogoutAddressValidation) {
+        this.disableLogoutAddressValidation = disableLogoutAddressValidation;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c49a9e28/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationDAOJPAImpl.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationDAOJPAImpl.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationDAOJPAImpl.java
index b8480a6..e5b3dac 100644
--- a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationDAOJPAImpl.java
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationDAOJPAImpl.java
@@ -203,6 +203,8 @@ public class ApplicationDAOJPAImpl implements ApplicationDAO {
         entity.setPassiveRequestorEndpoint(application.getPassiveRequestorEndpoint());
         entity.setPassiveRequestorEndpointConstraint(application.getPassiveRequestorEndpointConstraint());
         entity.setEnableAppliesTo(application.isEnableAppliesTo());
+        entity.setLogoutEndpoint(application.getLogoutEndpoint());
+        entity.setLogoutEndpointConstraint(entity.getLogoutEndpointConstraint());
     }
 
     public static Application entity2domain(ApplicationEntity entity, List<String> expandList) {
@@ -221,6 +223,8 @@ public class ApplicationDAOJPAImpl implements ApplicationDAO {
         application.setPassiveRequestorEndpoint(entity.getPassiveRequestorEndpoint());
         application.setPassiveRequestorEndpointConstraint(entity.getPassiveRequestorEndpointConstraint());
         application.setEnableAppliesTo(entity.isEnableAppliesTo());
+        application.setLogoutEndpoint(entity.getLogoutEndpoint());
+        application.setLogoutEndpointConstraint(entity.getLogoutEndpointConstraint());
 
         if (expandList != null && (expandList.contains("all") || expandList.contains("claims"))) {
             for (ApplicationClaimEntity item : entity.getRequestedClaims()) {

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c49a9e28/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationEntity.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationEntity.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationEntity.java
index 9907add..a6c930a 100644
--- a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationEntity.java
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/ApplicationEntity.java
@@ -91,6 +91,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;
@@ -211,4 +216,20 @@ public class ApplicationEntity {
     public void setEnableAppliesTo(boolean enableAppliesTo) {
         this.enableAppliesTo = enableAppliesTo;
     }
+
+    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/c49a9e28/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpDAOJPAImpl.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpDAOJPAImpl.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpDAOJPAImpl.java
index f2a23bd..5458d67 100644
--- a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpDAOJPAImpl.java
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpDAOJPAImpl.java
@@ -295,6 +295,7 @@ public class IdpDAOJPAImpl implements IdpDAO {
         entity.setRpSingleSignOutConfirmation(idp.isRpSingleSignOutConfirmation());
         entity.setRpSingleSignOutCleanupConfirmation(idp.isRpSingleSignOutCleanupConfirmation());
         entity.setAutomaticRedirectToRpAfterLogout(idp.isAutomaticRedirectToRpAfterLogout());
+        entity.setDisableLogoutAddressValidation(idp.isDisableLogoutAddressValidation());
 
         entity.getAuthenticationURIs().clear();
         for (Map.Entry<String, String> item : idp.getAuthenticationURIs().entrySet()) {
@@ -330,6 +331,7 @@ public class IdpDAOJPAImpl implements IdpDAO {
         idp.setRpSingleSignOutConfirmation(entity.isRpSingleSignOutConfirmation());
         idp.setRpSingleSignOutCleanupConfirmation(entity.isRpSingleSignOutCleanupConfirmation());
         idp.setAutomaticRedirectToRpAfterLogout(entity.isAutomaticRedirectToRpAfterLogout());
+        idp.setDisableLogoutAddressValidation(entity.isDisableLogoutAddressValidation());
 
         if (expandList != null && (expandList.contains("all") || expandList.contains("applications"))) {
             for (ApplicationEntity item : entity.getApplications()) {

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c49a9e28/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpEntity.java
----------------------------------------------------------------------
diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpEntity.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpEntity.java
index af1ee49..60b09d9 100644
--- a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpEntity.java
+++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/service/jpa/IdpEntity.java
@@ -136,9 +136,11 @@ public class IdpEntity {
     private String serviceDescription;
 
     private boolean rpSingleSignOutCleanupConfirmation;
-    
+
     private boolean automaticRedirectToRpAfterLogout;
 
+    private boolean disableLogoutAddressValidation;
+
 
     public int getId() {
         return id;
@@ -308,4 +310,12 @@ public class IdpEntity {
         this.automaticRedirectToRpAfterLogout = automaticRedirectToRpAfterLogout;
     }
 
+    public boolean isDisableLogoutAddressValidation() {
+        return disableLogoutAddressValidation;
+    }
+
+    public void setDisableLogoutAddressValidation(boolean disableLogoutAddressValidation) {
+        this.disableLogoutAddressValidation = disableLogoutAddressValidation;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c49a9e28/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 c1e4058..2a9c3d6 100644
--- a/services/idp/src/main/resources/entities-realma.xml
+++ b/services/idp/src/main/resources/entities-realma.xml
@@ -106,6 +106,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)*/.*" />
+        <property name="logoutEndpointConstraint" value="https://localhost:?(\d)*/.*" />
     </bean>
 	
 	<bean id="srv-oidc" class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationEntity">
@@ -117,6 +118,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)*/fediz-oidc/.*" />
+        <property name="logoutEndpointConstraint" value="https://localhost:?(\d)*/.*" />
     </bean>
     
     <bean class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationClaimEntity">

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c49a9e28/services/idp/src/main/webapp/WEB-INF/flows/federation-validate-request.xml
----------------------------------------------------------------------
diff --git a/services/idp/src/main/webapp/WEB-INF/flows/federation-validate-request.xml b/services/idp/src/main/webapp/WEB-INF/flows/federation-validate-request.xml
index 6d90263..6e7fc80 100644
--- a/services/idp/src/main/webapp/WEB-INF/flows/federation-validate-request.xml
+++ b/services/idp/src/main/webapp/WEB-INF/flows/federation-validate-request.xml
@@ -80,7 +80,8 @@
     </decision-state>
     
     <action-state id="validateWReplyForSignout">
-        <evaluate expression="commonsURLValidator.isValid(flowRequestContext, flowScope.wreply)"/>
+        <evaluate expression="commonsURLValidator.isValid(flowRequestContext, flowScope.wreply)
+                              and endpointAddressValidator.isValidSignoutAddress(flowRequestContext, flowScope.wreply, flowScope.wtrealm)"/>
         <transition on="yes" to="selectSignOutProcess" />
         <transition on="no" to="viewBadRequestAndLogout" />
     </action-state>

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c49a9e28/services/idp/src/main/webapp/WEB-INF/flows/signin-request.xml
----------------------------------------------------------------------
diff --git a/services/idp/src/main/webapp/WEB-INF/flows/signin-request.xml b/services/idp/src/main/webapp/WEB-INF/flows/signin-request.xml
index 2a7b125..81144e2 100644
--- a/services/idp/src/main/webapp/WEB-INF/flows/signin-request.xml
+++ b/services/idp/src/main/webapp/WEB-INF/flows/signin-request.xml
@@ -84,7 +84,7 @@
     
     <action-state id="validateReturnAddress">
         <evaluate expression="commonsURLValidator.isValid(flowRequestContext, flowScope.return_address)
-                              and passiveRequestorValidator.isValid(flowRequestContext, flowScope.return_address, flowScope.realm)"/>
+                              and endpointAddressValidator.isValidSigninAddress(flowRequestContext, flowScope.return_address, flowScope.realm)"/>
         <transition on="yes" to="requestRpToken" />
         <transition on="no" to="viewBadRequest" />
     </action-state>

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c49a9e28/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 3a90ab5..10a6ce7 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
@@ -915,4 +915,317 @@ public class IdpTest {
         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();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c49a9e28/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 b78c09c..13269db 100644
--- a/systests/idp/src/test/resources/realma/entities-realma.xml
+++ b/systests/idp/src/test/resources/realma/entities-realma.xml
@@ -109,6 +109,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 id="srv-fedizhelloworld2" class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationEntity">
@@ -133,6 +134,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/c49a9e28/systests/oidc/src/test/resources/realma/entities-realma.xml
----------------------------------------------------------------------
diff --git a/systests/oidc/src/test/resources/realma/entities-realma.xml b/systests/oidc/src/test/resources/realma/entities-realma.xml
index d366ba0..a879dfb 100644
--- a/systests/oidc/src/test/resources/realma/entities-realma.xml
+++ b/systests/oidc/src/test/resources/realma/entities-realma.xml
@@ -37,6 +37,7 @@
         <property name="idpUrl" value="https://localhost:${idp.https.port}/fediz-idp/federation" />
         <property name="rpSingleSignOutConfirmation" value="false"/>
         <property name="automaticRedirectToRpAfterLogout" value="true"/>
+        <property name="disableLogoutAddressValidation" value="true"/>
         <property name="supportedProtocols">
             <util:list>
                 <value>http://docs.oasis-open.org/wsfed/federation/200706

http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c49a9e28/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 88f2b93..10565ab 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