This is an automated email from the ASF dual-hosted git repository. coheigea pushed a commit to branch 1.4.x-fixes in repository https://gitbox.apache.org/repos/asf/cxf-fediz.git
commit f099ba26d25bcf4bc8d1143d19981c348c0d3e02 Author: Colm O hEigeartaigh <cohei...@apache.org> AuthorDate: Thu May 17 17:09:12 2018 +0100 Add support to redirect the SAML SSO RP when the session expires --- .../fediz/core/processor/SAMLProcessorImpl.java | 10 ++-- .../core/samlsso/SAMLSSOResponseValidator.java | 4 +- .../fediz/systests/samlsso/Tomcat8PluginTest.java | 52 +++++++++++++++++- .../cxf/fediz/integrationtests/AbstractTests.java | 14 +++-- .../cxf/fediz/integrationtests/TomcatTest.java | 62 ++++++++++++++++++++++ 5 files changed, 129 insertions(+), 13 deletions(-) diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java index 374f659..638dd8a 100644 --- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java @@ -112,10 +112,6 @@ public class SAMLProcessorImpl extends AbstractFedizProcessor { LOG.error("Invalid RelayState"); throw new ProcessingException(TYPE.INVALID_REQUEST); } - if (requestState == null) { - LOG.error("Missing Request State"); - throw new ProcessingException(TYPE.INVALID_REQUEST); - } return requestState; } @@ -265,9 +261,9 @@ public class SAMLProcessorImpl extends AbstractFedizProcessor { ((SAMLProtocol)config.getProtocol()).isDoNotEnforceKnownIssuer(); ssoResponseValidator.setEnforceKnownIssuer(!doNotEnforceKnownIssuer); - ssoResponseValidator.setIssuerIDP(requestState.getIdpServiceAddress()); - ssoResponseValidator.setRequestId(requestState.getRequestId()); - ssoResponseValidator.setSpIdentifier(requestState.getIssuerId()); + ssoResponseValidator.setIssuerIDP(requestState != null ? requestState.getIdpServiceAddress() : null); + ssoResponseValidator.setRequestId(requestState != null ? requestState.getRequestId() : null); + ssoResponseValidator.setSpIdentifier(requestState != null ? requestState.getIssuerId() : null); ssoResponseValidator.setEnforceAssertionsSigned(true); ssoResponseValidator.setReplayCache(config.getTokenReplayCache()); diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOResponseValidator.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOResponseValidator.java index 1541b89..fbbc6dc 100644 --- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOResponseValidator.java +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOResponseValidator.java @@ -160,7 +160,7 @@ public class SAMLSSOResponseValidator { } // Issuer value must match (be contained in) Issuer IDP - if (enforceKnownIssuer && !issuerIDP.startsWith(issuer.getValue())) { + if (enforceKnownIssuer && issuerIDP != null && !issuerIDP.startsWith(issuer.getValue())) { LOG.debug("Issuer value: " + issuer.getValue() + " does not match issuer IDP: " + issuerIDP); throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity"); @@ -268,7 +268,7 @@ public class SAMLSSOResponseValidator { throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity"); } List<AudienceRestriction> audienceRestrs = conditions.getAudienceRestrictions(); - if (!matchSaml2AudienceRestriction(spIdentifier, audienceRestrs)) { + if (spIdentifier != null && !matchSaml2AudienceRestriction(spIdentifier, audienceRestrs)) { LOG.debug("Assertion does not contain unique subject provider identifier " + spIdentifier + " in the audience restriction conditions"); throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity"); diff --git a/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/Tomcat8PluginTest.java b/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/Tomcat8PluginTest.java index 3fe901f..5f0ebdd 100644 --- a/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/Tomcat8PluginTest.java +++ b/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/samlsso/Tomcat8PluginTest.java @@ -223,7 +223,7 @@ public class Tomcat8PluginTest extends AbstractTests { DomNodeList<DomElement> results = idpPage.getElementsByTagName("input"); for (DomElement result : results) { - if (getTokenNameFromForm().equals(result.getAttributeNS(null, "name"))) { + if (getTokenName().equals(result.getAttributeNS(null, "name"))) { String value = result.getAttributeNS(null, "value"); // Decode response @@ -259,5 +259,55 @@ public class Tomcat8PluginTest extends AbstractTests { webClient.close(); } + + @Test + public void testAliceModifiedContext() throws Exception { + + String url = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + + "/secure/fedservlet"; + String user = "alice"; + String password = "ecila"; + + // Get the initial token + CookieManager cookieManager = new CookieManager(); + final 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); + final HtmlPage idpPage = webClient.getPage(url); + webClient.getOptions().setJavaScriptEnabled(true); + Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText()); + + // Parse the form to get the token (wresult) + DomNodeList<DomElement> results = idpPage.getElementsByTagName("input"); + + for (DomElement result : results) { + if (getContextName().equals(result.getAttributeNS(null, "name"))) { + // Now modify the context + String value = result.getAttributeNS(null, "value"); + value = "H" + value; + result.setAttributeNS(null, "value", value); + } + } + + // Invoke back on the RP + + final HtmlForm form = idpPage.getFormByName(getLoginFormName()); + final HtmlSubmitInput button = form.getInputByName("_eventId_submit"); + + try { + button.click(); + Assert.fail("Failure expected on a modified context"); + } catch (FailingHttpStatusCodeException ex) { + // Request Timeout expected here, as the context isn't known - the session is presumed to have expired + Assert.assertTrue(408 == ex.getStatusCode()); + } + + webClient.close(); + } } diff --git a/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/AbstractTests.java b/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/AbstractTests.java index 03aee17..8cb8abf 100644 --- a/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/AbstractTests.java +++ b/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/AbstractTests.java @@ -79,7 +79,7 @@ public abstract class AbstractTests { return "samlsigninresponseform"; } - protected String getTokenNameFromForm() { + protected String getTokenName() { if (isWSFederation()) { return "wresult"; } @@ -87,6 +87,14 @@ public abstract class AbstractTests { return "SAMLResponse"; } + protected String getContextName() { + if (isWSFederation()) { + return "wctx"; + } + + return "RelayState"; + } + @Test public void testAlice() throws Exception { String url = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() @@ -600,13 +608,13 @@ public abstract class AbstractTests { DomNodeList<DomElement> results = idpPage.getElementsByTagName("input"); for (DomElement result : results) { - if (getTokenNameFromForm().equals(result.getAttributeNS(null, "name"))) { + if (getTokenName().equals(result.getAttributeNS(null, "name"))) { // Now modify the Signature String value = result.getAttributeNS(null, "value"); if (value.contains("alice")) { value = value.replace("alice", "bob"); } else { - value += "H"; + value = "H" + value; } result.setAttributeNS(null, "value", value); } diff --git a/systests/tomcat8/src/test/java/org/apache/cxf/fediz/integrationtests/TomcatTest.java b/systests/tomcat8/src/test/java/org/apache/cxf/fediz/integrationtests/TomcatTest.java index 7e2a2d9..a37dd09 100644 --- a/systests/tomcat8/src/test/java/org/apache/cxf/fediz/integrationtests/TomcatTest.java +++ b/systests/tomcat8/src/test/java/org/apache/cxf/fediz/integrationtests/TomcatTest.java @@ -34,9 +34,21 @@ import org.apache.catalina.connector.Connector; import org.apache.catalina.startup.Tomcat; import org.apache.commons.io.IOUtils; import org.apache.cxf.fediz.tomcat8.FederationAuthenticator; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.Test; + +import com.gargoylesoftware.htmlunit.CookieManager; +import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; +import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.html.DomElement; +import com.gargoylesoftware.htmlunit.html.DomNodeList; +import com.gargoylesoftware.htmlunit.html.HtmlForm; +import com.gargoylesoftware.htmlunit.html.HtmlPage; +import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput; public class TomcatTest extends AbstractTests { @@ -168,5 +180,55 @@ public class TomcatTest extends AbstractTests { public String getServletContextName() { return "fedizhelloworld"; } + + @Test + public void testAliceModifiedContext() throws Exception { + + String url = "https://localhost:" + getRpHttpsPort() + "/" + getServletContextName() + + "/secure/fedservlet"; + String user = "alice"; + String password = "ecila"; + + // Get the initial token + CookieManager cookieManager = new CookieManager(); + final 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); + final HtmlPage idpPage = webClient.getPage(url); + webClient.getOptions().setJavaScriptEnabled(true); + Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText()); + + // Parse the form to get the token (wresult) + DomNodeList<DomElement> results = idpPage.getElementsByTagName("input"); + + for (DomElement result : results) { + if (getContextName().equals(result.getAttributeNS(null, "name"))) { + // Now modify the context + String value = result.getAttributeNS(null, "value"); + value = "H" + value; + result.setAttributeNS(null, "value", value); + } + } + + // Invoke back on the RP + + final HtmlForm form = idpPage.getFormByName(getLoginFormName()); + final HtmlSubmitInput button = form.getInputByName("_eventId_submit"); + + try { + button.click(); + Assert.fail("Failure expected on a modified context"); + } catch (FailingHttpStatusCodeException ex) { + // Request Timeout expected here, as the context isn't known - the session is presumed to have expired + Assert.assertTrue(408 == ex.getStatusCode()); + } + + webClient.close(); + } } -- To stop receiving notification emails like this one, please contact cohei...@apache.org.