You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by jb...@apache.org on 2016/01/04 19:56:39 UTC
cxf-fediz git commit: [FEDIZ-141] Adding SAML Post Binding Systest
Repository: cxf-fediz
Updated Branches:
refs/heads/master 35ab83126 -> 728e7bb80
[FEDIZ-141] Adding SAML Post Binding Systest
Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/728e7bb8
Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/728e7bb8
Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/728e7bb8
Branch: refs/heads/master
Commit: 728e7bb801c6a5b749ede68e002cc51f2bea6005
Parents: 35ab831
Author: Jan Bernhardt <jb...@talend.com>
Authored: Mon Jan 4 18:25:36 2016 +0100
Committer: Jan Bernhardt <jb...@talend.com>
Committed: Mon Jan 4 19:56:17 2016 +0100
----------------------------------------------------------------------
.../cxf/fediz/samlsso/example/SamlSso.java | 83 +++++++++++++++-----
.../src/main/resources/TemplateSAMLResponse.xml | 29 +++++++
systests/federation/samlsso/pom.xml | 8 ++
.../cxf/fediz/integrationtests/SAMLSSOTest.java | 48 ++++++++++-
.../src/test/resources/entities-realma.xml | 24 +++++-
.../test/resources/fediz_config_saml_sso.xml | 30 +++++++
6 files changed, 197 insertions(+), 25 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/728e7bb8/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SamlSso.java
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SamlSso.java b/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SamlSso.java
index cf43784..4d62d87 100644
--- a/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SamlSso.java
+++ b/systests/federation/samlIdpWebapp/src/main/java/org/apache/cxf/fediz/samlsso/example/SamlSso.java
@@ -23,24 +23,34 @@ package org.apache.cxf.fediz.samlsso.example;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
import java.util.Collections;
+import java.util.zip.DataFormatException;
+import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
+import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.stream.XMLStreamException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+
+import org.apache.cxf.common.util.Base64Exception;
import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.apache.cxf.rs.security.saml.DeflateEncoderDecoder;
import org.apache.cxf.staxutils.StaxUtils;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.crypto.CryptoFactory;
+import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.saml.OpenSAMLUtil;
import org.apache.wss4j.common.saml.SAMLCallback;
import org.apache.wss4j.common.saml.SAMLUtil;
@@ -72,17 +82,18 @@ public class SamlSso {
docBuilderFactory.setNamespaceAware(true);
}
+ @POST
+ public javax.ws.rs.core.Response login(@FormParam("SAMLRequest") String samlRequest,
+ @FormParam("RelayState") String relayState) throws Exception {
+
+ return login(samlRequest, relayState, "POST");
+ }
+
@GET
public javax.ws.rs.core.Response login(@QueryParam("SAMLRequest") String samlRequest,
- @QueryParam("RelayState") String relayState) throws Exception {
-
- byte[] deflatedToken = Base64Utility.decode(samlRequest);
- InputStream tokenStream = new DeflateEncoderDecoder().inflateToken(deflatedToken);
+ @QueryParam("RelayState") String relayState, @QueryParam("binding") String binding) throws Exception {
- Document responseDoc = StaxUtils.read(new InputStreamReader(tokenStream, "UTF-8"));
- AuthnRequest request =
- (AuthnRequest)OpenSAMLUtil.fromDom(responseDoc.getDocumentElement());
- System.out.println(DOM2Writer.nodeToString(responseDoc));
+ AuthnRequest request = extractRequest(samlRequest);
String racs = request.getAssertionConsumerServiceURL();
String requestIssuer = request.getIssuer().getValue();
@@ -91,20 +102,19 @@ public class SamlSso {
Element response = createResponse(request.getID(), racs, requestIssuer);
String responseStr = encodeResponse(response);
- // Perform Redirect to RACS
- UriBuilder ub = UriBuilder.fromUri(racs);
- ub.queryParam("SAMLResponse", responseStr);
- ub.queryParam("RelayState", relayState);
-
- return javax.ws.rs.core.Response.seeOther(ub.build()).build();
+ if ("REDIRECT".equals(binding)) {
+ return redirectResponse(relayState, racs, responseStr);
+ } else {
+ return postBindingResponse(relayState, racs, responseStr);
+ }
}
-
+
@Context
public void setMessageContext(MessageContext mc) {
this.messageContext = mc;
}
-
- private Element createResponse(String requestID, String racs, String requestIssuer) throws Exception {
+
+ protected Element createResponse(String requestID, String racs, String requestIssuer) throws Exception {
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
@@ -153,8 +163,8 @@ public class SamlSso {
return policyElement;
}
-
- private String encodeResponse(Element response) throws IOException {
+
+ protected String encodeResponse(Element response) throws IOException {
String responseMessage = DOM2Writer.nodeToString(response);
System.out.println("RESP: " + responseMessage);
@@ -163,6 +173,41 @@ public class SamlSso {
return Base64Utility.encode(deflatedBytes);
}
+
+ protected AuthnRequest extractRequest(String samlRequest) throws Base64Exception, DataFormatException,
+ XMLStreamException, UnsupportedEncodingException, WSSecurityException {
+ byte[] deflatedToken = Base64Utility.decode(samlRequest);
+ InputStream tokenStream = new DeflateEncoderDecoder().inflateToken(deflatedToken);
+
+ Document responseDoc = StaxUtils.read(new InputStreamReader(tokenStream, "UTF-8"));
+ AuthnRequest request =
+ (AuthnRequest)OpenSAMLUtil.fromDom(responseDoc.getDocumentElement());
+ System.out.println(DOM2Writer.nodeToString(responseDoc));
+ return request;
+ }
+
+ protected javax.ws.rs.core.Response postBindingResponse(String relayState, String racs, String responseStr)
+ throws IOException {
+ InputStream inputStream = this.getClass().getResourceAsStream("/TemplateSAMLResponse.xml");
+ String responseTemplate = IOUtils.toString(inputStream, "UTF-8");
+ inputStream.close();
+
+ // Perform Redirect to RACS
+ responseTemplate = responseTemplate.replace("%RESPONSE_URL%", racs);
+ responseTemplate = responseTemplate.replace("%SAMLResponse%", responseStr);
+ responseTemplate = responseTemplate.replace("%RelayState%", relayState);
+
+ return javax.ws.rs.core.Response.ok(responseTemplate).type(MediaType.TEXT_HTML).build();
+ }
+
+ protected javax.ws.rs.core.Response redirectResponse(String relayState, String racs, String responseStr) {
+ // Perform Redirect to RACS
+ UriBuilder ub = UriBuilder.fromUri(racs);
+ ub.queryParam("SAMLResponse", responseStr);
+ ub.queryParam("RelayState", relayState);
+
+ return javax.ws.rs.core.Response.seeOther(ub.build()).build();
+ }
}
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/728e7bb8/systests/federation/samlIdpWebapp/src/main/resources/TemplateSAMLResponse.xml
----------------------------------------------------------------------
diff --git a/systests/federation/samlIdpWebapp/src/main/resources/TemplateSAMLResponse.xml b/systests/federation/samlIdpWebapp/src/main/resources/TemplateSAMLResponse.xml
new file mode 100644
index 0000000..027a712
--- /dev/null
+++ b/systests/federation/samlIdpWebapp/src/main/resources/TemplateSAMLResponse.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <title>SAML IDP Response Form</title>
+ </head>
+ <body onload="document.forms[0].submit()">
+ <noscript>
+ <p>
+ <strong>Note:</strong>
+ Since your browser does not support JavaScript,
+ you must press the Continue button once to proceed.
+ </p>
+ </noscript>
+ <form name="signinresponseform" action="%RESPONSE_URL%" method="post">
+ <div>
+ <input type="hidden" name="RelayState" value="%RelayState%" />
+ <input type="hidden" name="SAMLResponse"
+ value="%SAMLResponse%" />
+ </div>
+ <noscript>
+ <div>
+ <input type="submit" name="_eventId_submit" value="Continue" />
+ </div>
+ </noscript>
+ </form>
+ </body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/728e7bb8/systests/federation/samlsso/pom.xml
----------------------------------------------------------------------
diff --git a/systests/federation/samlsso/pom.xml b/systests/federation/samlsso/pom.xml
index e604932..116527c 100644
--- a/systests/federation/samlsso/pom.xml
+++ b/systests/federation/samlsso/pom.xml
@@ -178,6 +178,14 @@
<overWrite>true</overWrite>
<outputDirectory>target/tomcat/rp/webapps/simpleWebapp</outputDirectory>
</artifactItem>
+ <artifactItem>
+ <groupId>org.apache.cxf.fediz.systests.webapps</groupId>
+ <artifactId>fediz-systests-webapps-simple</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ <overWrite>true</overWrite>
+ <outputDirectory>target/tomcat/rp/webapps/simpleWebapp2</outputDirectory>
+ </artifactItem>
</artifactItems>
<outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>
<overWriteSnapshots>true</overWriteSnapshots>
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/728e7bb8/systests/federation/samlsso/src/test/java/org/apache/cxf/fediz/integrationtests/SAMLSSOTest.java
----------------------------------------------------------------------
diff --git a/systests/federation/samlsso/src/test/java/org/apache/cxf/fediz/integrationtests/SAMLSSOTest.java b/systests/federation/samlsso/src/test/java/org/apache/cxf/fediz/integrationtests/SAMLSSOTest.java
index 39311a6..8c0510a 100644
--- a/systests/federation/samlsso/src/test/java/org/apache/cxf/fediz/integrationtests/SAMLSSOTest.java
+++ b/systests/federation/samlsso/src/test/java/org/apache/cxf/fediz/integrationtests/SAMLSSOTest.java
@@ -186,6 +186,8 @@ public class SAMLSSOTest {
+ "test-classes" + File.separator + "fediz_config_saml_sso.xml");
cxt.getPipeline().addValve(fa);
+ cxt = rpServer.addWebapp("/fedizhelloworld-post-binding", "simpleWebapp2");
+ cxt.getPipeline().addValve(fa);
rpServer.start();
} catch (Exception e) {
@@ -241,7 +243,38 @@ public class SAMLSSOTest {
String password = "ECILA";
final String bodyTextContent =
- login(url, user, password, idpSamlSSOHttpsPort, idpHttpsPort);
+ login(url, user, password, idpSamlSSOHttpsPort, idpHttpsPort, false);
+
+ Assert.assertTrue("Principal not alice",
+ bodyTextContent.contains("userPrincipal=alice"));
+ Assert.assertTrue("User " + user + " does not have role Admin",
+ bodyTextContent.contains("role:Admin=false"));
+ Assert.assertTrue("User " + user + " does not have role Manager",
+ bodyTextContent.contains("role:Manager=false"));
+ Assert.assertTrue("User " + user + " must have role User",
+ bodyTextContent.contains("role:User=true"));
+
+ String claim = ClaimTypes.FIRSTNAME.toString();
+ Assert.assertTrue("User " + user + " claim " + claim + " is not 'Alice'",
+ bodyTextContent.contains(claim + "=Alice"));
+ claim = ClaimTypes.LASTNAME.toString();
+ Assert.assertTrue("User " + user + " claim " + claim + " is not 'Smith'",
+ bodyTextContent.contains(claim + "=Smith"));
+ claim = ClaimTypes.EMAILADDRESS.toString();
+ Assert.assertTrue("User " + user + " claim " + claim + " is not 'alice@realma.org'",
+ bodyTextContent.contains(claim + "=alice@realma.org"));
+ }
+
+ @org.junit.Test
+ public void testSAMLSSOPostBinding() throws Exception {
+ String url = "https://localhost:" + getRpHttpsPort() + "/fedizhelloworld-post-binding/secure/fedservlet";
+ // System.out.println("URL: " + url);
+ // Thread.sleep(60 * 2 * 1000);
+ String user = "ALICE"; // realm b credentials
+ String password = "ECILA";
+
+ final String bodyTextContent =
+ login(url, user, password, idpSamlSSOHttpsPort, idpHttpsPort, true);
Assert.assertTrue("Principal not alice",
bodyTextContent.contains("userPrincipal=alice"));
@@ -264,7 +297,7 @@ public class SAMLSSOTest {
}
private static String login(String url, String user, String password,
- String idpPort, String rpIdpPort) throws IOException {
+ String idpPort, String rpIdpPort, boolean postBinding) throws IOException {
//
// Access the RP + get redirected to the IdP for "realm a". Then get redirected to the IdP for
// "realm b".
@@ -278,8 +311,15 @@ public class SAMLSSOTest {
new UsernamePasswordCredentials(user, password));
webClient.getOptions().setJavaScriptEnabled(false);
- final HtmlPage idpPage = webClient.getPage(url);
- webClient.getOptions().setJavaScriptEnabled(true);
+ HtmlPage idpPage = webClient.getPage(url);
+
+ if (postBinding) {
+ Assert.assertEquals("SAML IDP Response Form", idpPage.getTitleText());
+ final HtmlForm form = idpPage.getFormByName("signinresponseform");
+ final HtmlSubmitInput button = form.getInputByName("_eventId_submit");
+ idpPage = button.click();
+ }
+
Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText());
// Now redirect back to the RP
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/728e7bb8/systests/federation/samlsso/src/test/resources/entities-realma.xml
----------------------------------------------------------------------
diff --git a/systests/federation/samlsso/src/test/resources/entities-realma.xml b/systests/federation/samlsso/src/test/resources/entities-realma.xml
index 86fd540..145d1a8 100644
--- a/systests/federation/samlsso/src/test/resources/entities-realma.xml
+++ b/systests/federation/samlsso/src/test/resources/entities-realma.xml
@@ -71,6 +71,7 @@
<property name="trustedIdps">
<util:list>
<ref bean="trusted-idp-realmB" />
+ <ref bean="trusted-idp-realmC" />
</util:list>
</property>
<property name="claimTypesOffered">
@@ -87,7 +88,7 @@
class="org.apache.cxf.fediz.service.idp.service.jpa.TrustedIdpEntity">
<property name="realm" value="urn:org:apache:cxf:fediz:idp:realm-B" />
<property name="cacheTokens" value="true" />
- <property name="url" value="https://localhost:${idp.samlsso.https.port}/idp/samlsso" />
+ <property name="url" value="https://localhost:${idp.samlsso.https.port}/idp/samlsso?binding=REDIRECT" />
<property name="certificate" value="realmb.cert" />
<property name="trustType" value="PEER_TRUST" />
<property name="protocol" value="urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser" />
@@ -101,6 +102,25 @@
</util:map>
</property>
</bean>
+
+ <bean id="trusted-idp-realmC"
+ class="org.apache.cxf.fediz.service.idp.service.jpa.TrustedIdpEntity">
+ <property name="realm" value="urn:org:apache:cxf:fediz:idp:realm-C" />
+ <property name="cacheTokens" value="true" />
+ <property name="url" value="https://localhost:${idp.samlsso.https.port}/idp/samlsso" />
+ <property name="certificate" value="realmb.cert" />
+ <property name="trustType" value="PEER_TRUST" />
+ <property name="protocol" value="urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser" />
+ <property name="federationType" value="FEDERATE_IDENTITY" />
+ <property name="name" value="Realm C" />
+ <property name="description" value="SAML Web Profile - Response POST Binding" />
+ <property name="parameters">
+ <util:map>
+ <entry key="sign.request" value="true" />
+ <entry key="support.deflate.encoding" value="true" />
+ </util:map>
+ </property>
+ </bean>
<bean id="srv-fedizhelloworld" class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationEntity">
<property name="realm" value="urn:org:apache:cxf:fediz:fedizhelloworld" />
@@ -111,7 +131,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/.*" />
+ value="https://localhost:(\d)*/(\w)*helloworld.*/secure/.*" />
</bean>
<bean class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationClaimEntity">
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/728e7bb8/systests/federation/samlsso/src/test/resources/fediz_config_saml_sso.xml
----------------------------------------------------------------------
diff --git a/systests/federation/samlsso/src/test/resources/fediz_config_saml_sso.xml b/systests/federation/samlsso/src/test/resources/fediz_config_saml_sso.xml
index 7bd3cb7..89f158b 100644
--- a/systests/federation/samlsso/src/test/resources/fediz_config_saml_sso.xml
+++ b/systests/federation/samlsso/src/test/resources/fediz_config_saml_sso.xml
@@ -52,5 +52,35 @@
<logoutURL>/secure/logout</logoutURL>
<logoutRedirectTo>/index.html</logoutRedirectTo>
</contextConfig>
+ <contextConfig name="/fedizhelloworld-post-binding">
+ <audienceUris>
+ <audienceItem>urn:org:apache:cxf:fediz:fedizhelloworld</audienceItem>
+ </audienceUris>
+ <certificateStores>
+ <trustManager>
+ <keyStore file="test-classes/clienttrust.jks"
+ password="storepass" type="JKS" />
+ </trustManager>
+ </certificateStores>
+ <trustedIssuers>
+ <issuer certificateValidation="PeerTrust" />
+ </trustedIssuers>
+ <maximumClockSkew>1000</maximumClockSkew>
+ <protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:type="federationProtocolType" version="1.0.0">
+ <realm>urn:org:apache:cxf:fediz:fedizhelloworld</realm>
+ <issuer>https://localhost:${idp.https.port}/fediz-idp/federation</issuer>
+ <roleDelimiter>,</roleDelimiter>
+ <roleURI>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role</roleURI>
+ <freshness>10</freshness>
+ <homeRealm type="String">urn:org:apache:cxf:fediz:idp:realm-C</homeRealm>
+ <claimTypesRequested>
+ <claimType type="a particular claim type"
+ optional="true" />
+ </claimTypesRequested>
+ </protocol>
+ <logoutURL>/secure/logout</logoutURL>
+ <logoutRedirectTo>/index.html</logoutRedirectTo>
+ </contextConfig>
</FedizConfig>