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 e11a731235dd6a4873c5a146fcd9fe5805843c6b Author: Colm O hEigeartaigh <[email protected]> AuthorDate: Fri Jul 13 15:57:22 2018 +0100 FEDIZ-221 - Check NonOnOrAfter with LogoutRequests --- .../idp/beans/samlsso/AuthnRequestParser.java | 5 + .../service/idp/samlsso/SAMLLogoutRequest.java | 11 ++ .../org/apache/cxf/fediz/systests/idp/IdpTest.java | 112 +++++++++++++++++++++ 3 files changed, 128 insertions(+) diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestParser.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestParser.java index b120d89..4d5ce10 100644 --- a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestParser.java +++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestParser.java @@ -26,6 +26,7 @@ import java.nio.charset.StandardCharsets; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.List; import org.w3c.dom.Document; @@ -121,6 +122,10 @@ public class AuthnRequestParser { WebUtils.putAttributeInFlowScope(context, IdpConstants.SAML_AUTHN_REQUEST, authnRequest); } else if (parsedRequest instanceof LogoutRequest) { SAMLLogoutRequest logoutRequest = new SAMLLogoutRequest((LogoutRequest)parsedRequest); + if (logoutRequest.getNotOnOrAfter() != null && (new Date()).after(logoutRequest.getNotOnOrAfter())) { + LOG.debug("The LogoutRequest is expired"); + throw new ProcessingException(TYPE.BAD_REQUEST); + } WebUtils.putAttributeInFlowScope(context, IdpConstants.SAML_LOGOUT_REQUEST, logoutRequest); } diff --git a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/samlsso/SAMLLogoutRequest.java b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/samlsso/SAMLLogoutRequest.java index 9e47764..c894190 100644 --- a/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/samlsso/SAMLLogoutRequest.java +++ b/services/idp-core/src/main/java/org/apache/cxf/fediz/service/idp/samlsso/SAMLLogoutRequest.java @@ -19,6 +19,8 @@ package org.apache.cxf.fediz.service.idp.samlsso; +import java.util.Date; + import org.opensaml.saml.saml2.core.LogoutRequest; /** @@ -32,9 +34,13 @@ public class SAMLLogoutRequest extends SAMLAbstractRequest { private static final long serialVersionUID = 4353024755428346545L; private String subjectNameId; + private Date notOnOrAfter; public SAMLLogoutRequest(LogoutRequest logoutRequest) { super(logoutRequest); + if (logoutRequest.getNotOnOrAfter() != null) { + notOnOrAfter = logoutRequest.getNotOnOrAfter().toDate(); + } if (logoutRequest.getNameID() != null) { subjectNameId = logoutRequest.getNameID().getValue(); @@ -44,4 +50,9 @@ public class SAMLLogoutRequest extends SAMLAbstractRequest { public String getSubjectNameId() { return subjectNameId; } + + public Date getNotOnOrAfter() { + return notOnOrAfter; + } + } diff --git a/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java b/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java index d3b5636..eaf25dd 100644 --- a/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java +++ b/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java @@ -31,6 +31,7 @@ import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.UUID; import javax.servlet.ServletException; @@ -1752,6 +1753,117 @@ public class IdpTest { webClient.close(); } + @org.junit.Test + public void testIdpLogoutRequestExpired() throws Exception { + OpenSAMLUtil.initSamlEngine(); + + // 1. First let's login to the IdP + + // Create SAML AuthnRequest + Document doc = DOMUtils.createDocument(); + doc.appendChild(doc.createElement("root")); + // Create the AuthnRequest + String consumerURL = "https://localhost:" + getRpHttpsPort() + "/" + + getServletContextName() + "/secure/fedservlet"; + AuthnRequest authnRequest = + new DefaultAuthnRequestBuilder().createAuthnRequest( + null, "urn:org:apache:cxf:fediz:fedizhelloworld", consumerURL + ); + authnRequest.setDestination("https://localhost:" + getIdpHttpsPort() + "/fediz-idp/saml"); + signAuthnRequest(authnRequest); + + Element authnRequestElement = OpenSAMLUtil.toDom(authnRequest, doc); + String authnRequestEncoded = encodeAuthnRequest(authnRequestElement); + + String urlEncodedRequest = URLEncoder.encode(authnRequestEncoded, "UTF-8"); + + String relayState = UUID.randomUUID().toString(); + String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/saml?"; + url += SSOConstants.RELAY_STATE + "=" + relayState; + url += "&" + SSOConstants.SAML_REQUEST + "=" + urlEncodedRequest; + + 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()); + + org.opensaml.saml.saml2.core.Response samlResponse = + parseSAMLResponse(idpPage, relayState, consumerURL, authnRequest.getID()); + String expected = "urn:oasis:names:tc:SAML:2.0:status:Success"; + Assert.assertEquals(expected, samlResponse.getStatus().getStatusCode().getValue()); + NameID nameID = samlResponse.getAssertions().get(0).getSubject().getNameID(); + Assert.assertNotNull(nameID); + nameID.detach(); + + webClient.close(); + + // 2. now we logout from IdP + + // Create SAML LogoutRequest + doc = DOMUtils.createDocument(); + doc.appendChild(doc.createElement("root")); + + Issuer issuer = SamlpRequestComponentBuilder.createIssuer("urn:org:apache:cxf:fediz:fedizhelloworld"); + String destination = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/saml"; + Date now = new Date(); + now.setTime(now.getTime() - (60L * 1000L)); + LogoutRequest logoutRequest = + SamlpRequestComponentBuilder.createLogoutRequest(SAMLVersion.VERSION_20, issuer, destination, + null, now, null, nameID); + + signAuthnRequest(logoutRequest); + + Element logoutRequestElement = OpenSAMLUtil.toDom(logoutRequest, doc); + String logoutRequestEncoded = encodeAuthnRequest(logoutRequestElement); + + urlEncodedRequest = URLEncoder.encode(logoutRequestEncoded, "UTF-8"); + + relayState = UUID.randomUUID().toString(); + String logoutURL = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/saml?"; + logoutURL += SSOConstants.RELAY_STATE + "=" + relayState; + logoutURL += "&" + SSOConstants.SAML_REQUEST + "=" + urlEncodedRequest; + + 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); + try { + webClient.getPage(logoutURL); + Assert.fail("Authentication failure expected"); + } 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 - it should work OK as our LogoutRequest was expired + webClient = new WebClient(); + webClient.setCookieManager(cookieManager); + webClient.getOptions().setUseInsecureSSL(true); + webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); + idpPage = webClient.getPage(url); + + Assert.assertEquals(200, idpPage.getWebResponse().getStatusCode()); + + webClient.close(); + } + private String encodeAuthnRequest(Element authnRequest) throws IOException { String requestMessage = DOM2Writer.nodeToString(authnRequest);
