[FEDIZ-165] - Part II
Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/cc8708e1 Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/cc8708e1 Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/cc8708e1 Branch: refs/heads/master Commit: cc8708e1bac7bac8fdf1f1ac30c8a54272d2f004 Parents: a616dc6 Author: Colm O hEigeartaigh <[email protected]> Authored: Wed Apr 13 16:18:54 2016 +0100 Committer: Colm O hEigeartaigh <[email protected]> Committed: Wed Apr 13 16:18:54 2016 +0100 ---------------------------------------------------------------------- .../idp/beans/samlsso/LocalRedirectCreator.java | 54 ++++++++++ .../WEB-INF/flows/saml-validate-request.xml | 9 +- .../apache/cxf/fediz/systests/idp/IdpTest.java | 108 +++++++++++++++++++ 3 files changed, 164 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/cc8708e1/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/LocalRedirectCreator.java ---------------------------------------------------------------------- diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/LocalRedirectCreator.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/LocalRedirectCreator.java new file mode 100644 index 0000000..9dfd626 --- /dev/null +++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/LocalRedirectCreator.java @@ -0,0 +1,54 @@ +/** + * 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.samlsso; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +import org.apache.cxf.fediz.service.idp.domain.Idp; +import org.apache.cxf.fediz.service.idp.util.WebUtils; +import org.springframework.stereotype.Component; +import org.springframework.webflow.execution.RequestContext; + +/** + * Parse the parameters to create the URL for local redirection + */ +@Component +public class LocalRedirectCreator { + + public String createRedirectURL(RequestContext context, Idp idp) throws UnsupportedEncodingException { + StringBuilder redirectURL = new StringBuilder(); + redirectURL.append(idp.getIdpUrl().toString()).append("?"); + + String relayState = (String)WebUtils.getAttributeFromFlowScope(context, "RelayState"); + redirectURL.append("RelayState=").append(relayState).append("&"); + String samlRequest = (String)WebUtils.getAttributeFromFlowScope(context, "SAMLRequest"); + redirectURL.append("SAMLRequest=").append(URLEncoder.encode(samlRequest, "UTF-8")); + + String signature = (String)WebUtils.getAttributeFromFlowScope(context, "Signature"); + if (signature != null) { + redirectURL.append("&"); + redirectURL.append("Signature=").append(URLEncoder.encode(signature, "UTF-8")); + } + + return redirectURL.toString(); + } + + +} http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/cc8708e1/services/idp/src/main/webapp/WEB-INF/flows/saml-validate-request.xml ---------------------------------------------------------------------- diff --git a/services/idp/src/main/webapp/WEB-INF/flows/saml-validate-request.xml b/services/idp/src/main/webapp/WEB-INF/flows/saml-validate-request.xml index 6c156ac..6808554 100644 --- a/services/idp/src/main/webapp/WEB-INF/flows/saml-validate-request.xml +++ b/services/idp/src/main/webapp/WEB-INF/flows/saml-validate-request.xml @@ -147,13 +147,8 @@ <end-state id="redirectToLocalIDP" view="externalRedirect:${flowScope.localIdpUrl}"> <on-entry> - <evaluate expression="@java.net.URLEncoder@encode(flowScope.SAMLRequest)" - result="flowScope.encodedRequest"/> - <set name="flowScope.localIdpUrl" - value="flowScope.idpConfig.idpUrl - +'?RelayState='+flowScope.RelayState - +'&SAMLRequest='+flowScope.encodedRequest"> - </set> + <evaluate expression="localRedirectCreator.createRedirectURL(flowRequestContext, flowScope.idpConfig)" + result="flowScope.localIdpUrl"/> </on-entry> </end-state> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/cc8708e1/systests/samlsso/src/test/java/org/apache/cxf/fediz/systests/idp/IdpTest.java ---------------------------------------------------------------------- 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 c8356ee..86e9628 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 @@ -566,6 +566,114 @@ public class IdpTest { webClient.close(); } + @org.junit.Test + public void testSuccessfulSSOInvokeOnIdPWithForceAuthnSeparateSignature() throws Exception { + OpenSAMLUtil.initSamlEngine(); + + // 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.setForceAuthn(Boolean.TRUE); + authnRequest.setDestination("https://localhost:" + getIdpHttpsPort() + "/fediz-idp/saml"); + + Element authnRequestElement = OpenSAMLUtil.toDom(authnRequest, doc); + String authnRequestEncoded = encodeAuthnRequest(authnRequestElement); + + String urlEncodedRequest = URLEncoder.encode(authnRequestEncoded, "UTF-8"); + + String relayState = UUID.randomUUID().toString(); + + // Sign request + Crypto crypto = CryptoFactory.getInstance("stsKeystoreA.properties"); + + CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS); + cryptoType.setAlias("realma"); + + // Get the private key + PrivateKey privateKey = crypto.getPrivateKey("realma", "realma"); + + java.security.Signature signature = java.security.Signature.getInstance("SHA1withRSA"); + signature.initSign(privateKey); + + String requestToSign = SSOConstants.SAML_REQUEST + "=" + urlEncodedRequest; + requestToSign += "&" + SSOConstants.RELAY_STATE + "=" + relayState; + requestToSign += "&" + SSOConstants.SIG_ALG + "=" + + URLEncoder.encode(SSOConstants.RSA_SHA1, StandardCharsets.UTF_8.name()); + + signature.update(requestToSign.getBytes(StandardCharsets.UTF_8)); + byte[] signBytes = signature.sign(); + + String encodedSignature = Base64.encode(signBytes); + + String url = "https://localhost:" + getIdpHttpsPort() + "/fediz-idp/saml/up?"; + url += SSOConstants.RELAY_STATE + "=" + relayState; + url += "&" + SSOConstants.SAML_REQUEST + "=" + urlEncodedRequest; + url += "&" + SSOConstants.SIGNATURE + "=" + URLEncoder.encode(encodedSignature, StandardCharsets.UTF_8.name()); + + String user = "alice"; + String password = "ecila"; + + final WebClient webClient = new WebClient(); + webClient.getOptions().setUseInsecureSSL(true); + webClient.getCredentialsProvider().setCredentials( + new AuthScope("localhost", Integer.parseInt(getIdpHttpsPort())), + new UsernamePasswordCredentials(user, password)); + + // + // First invocation + // + + 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()); + + // Check claims + String parsedResponse = DOM2Writer.nodeToString(samlResponse.getDOM().getOwnerDocument()); + String claim = ClaimTypes.FIRSTNAME.toString(); + Assert.assertTrue(parsedResponse.contains(claim)); + claim = ClaimTypes.LASTNAME.toString(); + Assert.assertTrue(parsedResponse.contains(claim)); + claim = ClaimTypes.EMAILADDRESS.toString(); + Assert.assertTrue(parsedResponse.contains(claim)); + + // + // Second invocation + // + + webClient.getOptions().setJavaScriptEnabled(false); + idpPage = webClient.getPage(url); + webClient.getOptions().setJavaScriptEnabled(true); + Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText()); + + samlResponse = parseSAMLResponse(idpPage, relayState, consumerURL, authnRequest.getID()); + expected = "urn:oasis:names:tc:SAML:2.0:status:Success"; + Assert.assertEquals(expected, samlResponse.getStatus().getStatusCode().getValue()); + + // Check claims + parsedResponse = DOM2Writer.nodeToString(samlResponse.getDOM().getOwnerDocument()); + claim = ClaimTypes.FIRSTNAME.toString(); + Assert.assertTrue(parsedResponse.contains(claim)); + claim = ClaimTypes.LASTNAME.toString(); + Assert.assertTrue(parsedResponse.contains(claim)); + claim = ClaimTypes.EMAILADDRESS.toString(); + Assert.assertTrue(parsedResponse.contains(claim)); + + webClient.close(); + } + // // Negative tests //
