http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6fef44bb/systests/federation/samlsso/src/test/resources/realmb/idp-servlet.xml ---------------------------------------------------------------------- diff --git a/systests/federation/samlsso/src/test/resources/realmb/idp-servlet.xml b/systests/federation/samlsso/src/test/resources/realmb/idp-servlet.xml deleted file mode 100644 index e557819..0000000 --- a/systests/federation/samlsso/src/test/resources/realmb/idp-servlet.xml +++ /dev/null @@ -1,120 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - 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. ---> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:webflow="http://www.springframework.org/schema/webflow-config" - xmlns:p="http://www.springframework.org/schema/p" - xmlns:context="http://www.springframework.org/schema/context" - xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-3.1.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.1.xsd - http://www.springframework.org/schema/webflow-config - http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd"> - - <context:property-placeholder location="classpath:realm.properties" /> - - <context:component-scan base-package="org.apache.cxf.fediz.service.idp.beans" /> - - <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping" - p:flowRegistry-ref="flowRegistry" p:order="2"> - </bean> - - <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter" - p:flowExecutor-ref="flowExecutor" /> - - <webflow:flow-executor id="flowExecutor" - flow-registry="flowRegistry"> - <webflow:flow-execution-attributes> - <webflow:always-redirect-on-pause - value="false" /> - </webflow:flow-execution-attributes> - - <webflow:flow-execution-listeners> - <webflow:listener ref="securityFlowExecutionListener" /> - </webflow:flow-execution-listeners> - </webflow:flow-executor> - - <bean id="securityFlowExecutionListener" - class="org.springframework.webflow.security.SecurityFlowExecutionListener"> - <property name="accessDecisionManager" ref="accessDecisionManager" /> - </bean> - - <bean id="accessDecisionManager" - class="org.springframework.security.access.vote.AffirmativeBased"> - <property name="decisionVoters"> - <list> - <bean - class="org.springframework.security.access.vote.RoleVoter"> - <property name="rolePrefix" value="ROLE_" /> - </bean> - <bean - class="org.springframework.security.access.vote.AuthenticatedVoter" /> - </list> - </property> - </bean> - - <webflow:flow-registry id="flowRegistry" - flow-builder-services="builder"> - <webflow:flow-location - path="/WEB-INF/flows/federation-validate-request.xml" id="federation" /> - <webflow:flow-location - path="/WEB-INF/flows/federation-validate-request.xml" id="federation/up" /> - <webflow:flow-location path="/WEB-INF/flows/federation-signin-request.xml" - id="signinRequest" /> - <webflow:flow-location path="/WEB-INF/flows/federation-signin-response.xml" - id="signinResponse" /> - - <webflow:flow-location path="/WEB-INF/flows/saml-validate-request.xml" id="saml" /> - <webflow:flow-location path="/WEB-INF/flows/saml-validate-request.xml" id="saml/up" /> - <webflow:flow-location path="/WEB-INF/flows/saml-signin-request.xml" id="signinSAMLRequest" /> - </webflow:flow-registry> - - <webflow:flow-builder-services id="builder" - view-factory-creator="viewFactoryCreator" expression-parser="expressionParser" /> - - <bean id="expressionParser" - class="org.springframework.webflow.expression.WebFlowOgnlExpressionParser" /> - - <bean id="viewFactoryCreator" - class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator"> - <property name="viewResolvers"> - <list> - <ref local="viewResolver" /> - </list> - </property> - </bean> - - <bean id="viewResolver" - class="org.springframework.web.servlet.view.InternalResourceViewResolver"> - <property name="prefix" value="/WEB-INF/views/" /> - <property name="suffix" value=".jsp" /> - </bean> - - <bean id="stsClientForRpAction" - class="org.apache.cxf.fediz.service.idp.beans.STSClientAction"> - <property name="wsdlLocation" - value="https://localhost:0/fediz-idp-sts-realmb/${realm.STS_URI}/STSServiceTransport?wsdl" /> - <property name="wsdlEndpoint" value="Transport_Port" /> - <property name="tokenType" - value="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0" /> - </bean> - -</beans>
http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6fef44bb/systests/federation/samlsso/src/test/resources/realmb/persistence.properties ---------------------------------------------------------------------- diff --git a/systests/federation/samlsso/src/test/resources/realmb/persistence.properties b/systests/federation/samlsso/src/test/resources/realmb/persistence.properties deleted file mode 100644 index 2628714..0000000 --- a/systests/federation/samlsso/src/test/resources/realmb/persistence.properties +++ /dev/null @@ -1,15 +0,0 @@ -#jpa.driverClassName=org.apache.derby.jdbc.ClientDriver -#jpa.url=jdbc:derby://localhost:1527/Fediz -#jpa.username=admin -#jpa.password=admin -#jpa.defaultData=true -#jpa.platform=DerbyDictionary - - -jpa.driverClassName=org.hsqldb.jdbcDriver -#jpa.url=jdbc:hsqldb:target/fediz/db/myDB;shutdown=true -jpa.url=jdbc:hsqldb:target/db/realmb/myDB;shutdown=true -jpa.username=sa -jpa.password= -jpa.defaultData=true -jpa.platform=HSQLDictionary \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6fef44bb/systests/federation/samlsso/src/test/resources/realmb/realm.properties ---------------------------------------------------------------------- diff --git a/systests/federation/samlsso/src/test/resources/realmb/realm.properties b/systests/federation/samlsso/src/test/resources/realmb/realm.properties deleted file mode 100644 index 41d04cd..0000000 --- a/systests/federation/samlsso/src/test/resources/realmb/realm.properties +++ /dev/null @@ -1,6 +0,0 @@ -realm.STS_URI=REALMB -realmA.port=${idp.https.port} -realmB.port=${idp.realmb.https.port} -idp-config=idp-config-realmb.xml -db-load-config=entities-realmb.xml -realm-uri=urn:org:apache:cxf:fediz:idp:realm-B http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6fef44bb/systests/federation/samlsso/src/test/resources/realmb/security-config.xml ---------------------------------------------------------------------- diff --git a/systests/federation/samlsso/src/test/resources/realmb/security-config.xml b/systests/federation/samlsso/src/test/resources/realmb/security-config.xml deleted file mode 100644 index 78e50c8..0000000 --- a/systests/federation/samlsso/src/test/resources/realmb/security-config.xml +++ /dev/null @@ -1,135 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - 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. ---> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:security="http://www.springframework.org/schema/security" - xmlns:context="http://www.springframework.org/schema/context" - xsi:schemaLocation=" - http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context.xsd - http://www.springframework.org/schema/security - http://www.springframework.org/schema/security/spring-security-3.1.xsd - "> - - <context:property-placeholder location="classpath:realm.properties"/> - - <!-- DISABLE in production as it might log confidential information about the user --> - <!-- <security:debug /> --> - - <!-- Configure Spring Security --> - - <!-- If enabled, you can't access the Service layer within the Spring Webflow --> - <!-- The user has no role during the login phase of WS-Federation --> - <security:global-method-security pre-post-annotations="enabled"/> - - <security:http pattern="/services/rs/**" use-expressions="true" authentication-manager-ref="restAuthenticationManager"> - <security:custom-filter after="CHANNEL_FILTER" ref="stsPortFilter" /> - <security:custom-filter after="SERVLET_API_SUPPORT_FILTER" ref="entitlementsEnricher" /> - <security:intercept-url pattern="/services/rs/**" access="isAuthenticated()"/> - <security:http-basic /> - </security:http> - - <bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" /> - - <bean id="defaultPasswordEncoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder" /> - - <security:authentication-manager id="restAuthenticationManager"> - <security:authentication-provider> - <!-- <security:password-encoder ref="defaultPasswordEncoder"/>--> - <!-- <security:password-encoder hash="sha-256" base64="true" />--> - <!-- - <security:password-encoder hash="sha-256" base64="true"> - <security:salt-source user-property="username"/> - </security:password-encoder> - --> - <security:user-service properties="classpath:/users.properties" /> - </security:authentication-provider> - <security:authentication-provider ref="stsAuthProvider" /> - </security:authentication-manager> - - <!-- Redirects to a dedicated http config --> - <bean id="fedizEntryPoint" class="org.apache.cxf.fediz.service.idp.FedizEntryPoint"> - <property name="realm" value="urn:org:apache:cxf:fediz:idp:realm-B" /> - <property name="configService" ref="config" /> - </bean> - - <!-- Main entry point --> - <security:http pattern="/federation" use-expressions="true" entry-point-ref="fedizEntryPoint"> - <security:custom-filter after="CHANNEL_FILTER" ref="stsPortFilter" /> - <security:custom-filter after="SERVLET_API_SUPPORT_FILTER" ref="entitlementsEnricher" /> - <security:intercept-url pattern="/FederationMetadata/2007-06/FederationMetadata.xml" access="isAnonymous() or isAuthenticated()" /> - </security:http> - - <!-- HTTP/BA entry point --> - <security:http pattern="/federation/up" use-expressions="true"> - <security:custom-filter after="CHANNEL_FILTER" ref="stsPortFilter" /> - <security:custom-filter after="SERVLET_API_SUPPORT_FILTER" ref="entitlementsEnricher" /> - <security:intercept-url pattern="/FederationMetadata/2007-06/FederationMetadata.xml" access="isAnonymous() or isAuthenticated()" /> - - <security:http-basic /> - <security:logout delete-cookies="FEDIZ_HOME_REALM" invalidate-session="true" /> - </security:http> - - <!-- Main entry point --> - <security:http pattern="/saml" use-expressions="true" entry-point-ref="fedizEntryPoint"> - <security:custom-filter after="CHANNEL_FILTER" ref="stsPortFilter" /> - <security:custom-filter after="SERVLET_API_SUPPORT_FILTER" ref="entitlementsEnricher" /> - </security:http> - - <!-- HTTP/BA entry point --> - <security:http pattern="/saml/up/**" use-expressions="true"> - <security:intercept-url requires-channel="https" pattern="/saml/up/login*" access="isAnonymous() or isAuthenticated()" /> - <security:custom-filter after="CHANNEL_FILTER" ref="stsPortFilter" /> - <security:custom-filter after="SERVLET_API_SUPPORT_FILTER" ref="entitlementsEnricher" /> - - <security:http-basic /> - <!--security:form-login login-page='/federation/up/login' - login-processing-url="/federation/up/login.do" - authentication-failure-url="/federation/up/login?error" - default-target-url="/" - username-parameter="username" - password-parameter="password" - /--> - <security:logout logout-url="/saml/up/logout" - logout-success-url="/saml/up/login?out" - delete-cookies="FEDIZ_HOME_REALM,JSESSIONID" - invalidate-session="true" - /> - </security:http> - - <security:authentication-manager> - <security:authentication-provider ref="stsAuthProvider" /> - </security:authentication-manager> - - <bean id="stsPortFilter" class="org.apache.cxf.fediz.service.idp.STSPortFilter" /> - - <bean id="entitlementsEnricher" class="org.apache.cxf.fediz.service.idp.service.security.GrantedAuthorityEntitlements" /> - - <bean id="stsAuthProvider" class="org.apache.cxf.fediz.service.idp.STSUPAuthenticationProvider"> - <property name="wsdlLocation" value="https://localhost:0/fediz-idp-sts-realmb/${realm.STS_URI}/STSServiceTransportUT?wsdl"/> - <property name="wsdlEndpoint" value="TransportUT_Port"/> - <property name="wsdlService" value="SecurityTokenService"/> - <property name="appliesTo" value="urn:fediz:idp"/> - <property name="tokenType" value="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"/> - </bean> - -</beans> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6fef44bb/systests/federation/wsfed/pom.xml ---------------------------------------------------------------------- diff --git a/systests/federation/wsfed/pom.xml b/systests/federation/wsfed/pom.xml index 3ce1c62..41cdcb0 100644 --- a/systests/federation/wsfed/pom.xml +++ b/systests/federation/wsfed/pom.xml @@ -128,6 +128,7 @@ <portNames> <portName>idp.https.port</portName> <portName>idp.realmb.https.port</portName> + <portName>idp.samlsso.https.port</portName> <portName>rp.https.port</portName> </portNames> </configuration> @@ -187,6 +188,14 @@ <outputDirectory>target/tomcat/idprealmb/webapps/fediz-idp-sts-realmb</outputDirectory> </artifactItem> <artifactItem> + <groupId>org.apache.cxf.fediz.systests.federation</groupId> + <artifactId>fediz-systests-federation-samlIdpWebapp</artifactId> + <version>${project.version}</version> + <type>war</type> + <overWrite>true</overWrite> + <outputDirectory>target/tomcat/idpsamlsso/webapps/idpsaml</outputDirectory> + </artifactItem> + <artifactItem> <groupId>org.apache.cxf.fediz.systests</groupId> <artifactId>fediz-systests-tests</artifactId> <version>${project.version}</version> @@ -287,6 +296,7 @@ <wt.headless>true</wt.headless> <idp.https.port>${idp.https.port}</idp.https.port> <idp.realmb.https.port>${idp.realmb.https.port}</idp.realmb.https.port> + <idp.samlsso.https.port>${idp.samlsso.https.port}</idp.samlsso.https.port> <rp.https.port>${rp.https.port}</rp.https.port> </systemPropertyVariables> <includes> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6fef44bb/systests/federation/wsfed/src/test/java/org/apache/cxf/fediz/integrationtests/WSFedTest.java ---------------------------------------------------------------------- diff --git a/systests/federation/wsfed/src/test/java/org/apache/cxf/fediz/integrationtests/WSFedTest.java b/systests/federation/wsfed/src/test/java/org/apache/cxf/fediz/integrationtests/WSFedTest.java index 1a72589..b7ac194 100644 --- a/systests/federation/wsfed/src/test/java/org/apache/cxf/fediz/integrationtests/WSFedTest.java +++ b/systests/federation/wsfed/src/test/java/org/apache/cxf/fediz/integrationtests/WSFedTest.java @@ -26,6 +26,10 @@ import java.net.URLEncoder; import javax.servlet.ServletException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + import com.gargoylesoftware.htmlunit.CookieManager; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.DomElement; @@ -33,6 +37,7 @@ import com.gargoylesoftware.htmlunit.html.DomNodeList; import com.gargoylesoftware.htmlunit.html.HtmlForm; import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput; +import com.gargoylesoftware.htmlunit.xml.XmlPage; import org.apache.catalina.Context; import org.apache.catalina.LifecycleException; @@ -40,27 +45,36 @@ import org.apache.catalina.LifecycleState; import org.apache.catalina.connector.Connector; import org.apache.catalina.startup.Tomcat; import org.apache.cxf.fediz.core.ClaimTypes; +import org.apache.cxf.fediz.core.util.DOMUtils; import org.apache.cxf.fediz.tomcat7.FederationAuthenticator; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.xml.security.keys.KeyInfo; +import org.apache.xml.security.signature.XMLSignature; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.Test; /** - * This is a test for federation in the IdP. The RP application is configured to use a home realm of "realm b". The - * client gets redirected to the IdP for "realm a", which in turn redirects to the IdP for "realm b". The user - * authenticates + is redirected back to the IdP for "realm a" to get a SAML token from the STS + then back to the - * application. + * This is a test for federation using a WS-Federation enabled web application. The web application is configured + * to use a different realm to that of the IdP. The IdP then redirects to a third party IdP for authentication. + * The third party IdPs that are tested are as follows: + * - WS-Federation (Fediz) + * - SAML SSO (Fediz) + * - SAML SSO (custom webapp - supports POST binding as well) + * - OIDC (custom webapp) */ public class WSFedTest { static String idpHttpsPort; static String idpRealmbHttpsPort; + static String idpSamlSSOHttpsPort; static String rpHttpsPort; private static Tomcat idpServer; private static Tomcat idpRealmbServer; + private static Tomcat idpSamlSSOServer; private static Tomcat rpServer; @BeforeClass @@ -78,15 +92,18 @@ public class WSFedTest { Assert.assertNotNull("Property 'idp.https.port' null", idpHttpsPort); idpRealmbHttpsPort = System.getProperty("idp.realmb.https.port"); Assert.assertNotNull("Property 'idp.realmb.https.port' null", idpRealmbHttpsPort); + idpSamlSSOHttpsPort = System.getProperty("idp.samlsso.https.port"); + Assert.assertNotNull("Property 'idp.samlsso.https.port' null", idpSamlSSOHttpsPort); rpHttpsPort = System.getProperty("rp.https.port"); Assert.assertNotNull("Property 'rp.https.port' null", rpHttpsPort); - idpServer = startServer(true, false, idpHttpsPort); - idpRealmbServer = startServer(false, true, idpRealmbHttpsPort); - rpServer = startServer(false, false, rpHttpsPort); + idpServer = startServer(true, false, false, idpHttpsPort); + idpRealmbServer = startServer(false, true, false, idpRealmbHttpsPort); + idpSamlSSOServer = startServer(false, false, true, idpSamlSSOHttpsPort); + rpServer = startServer(false, false, false, rpHttpsPort); } - private static Tomcat startServer(boolean idp, boolean realmb, String port) + private static Tomcat startServer(boolean idp, boolean realmb, boolean samlSSOIdP, String port) throws ServletException, LifecycleException, IOException { Tomcat server = new Tomcat(); server.setPort(0); @@ -98,6 +115,8 @@ public class WSFedTest { server.getHost().setAppBase("tomcat/idp/webapps"); } else if (realmb) { server.getHost().setAppBase("tomcat/idprealmb/webapps"); + } else if (samlSSOIdP) { + server.getHost().setAppBase("tomcat/idpsamlsso/webapps"); } else { server.getHost().setAppBase("tomcat/rp/webapps"); } @@ -132,14 +151,29 @@ public class WSFedTest { File idpWebapp = new File(baseDir + File.separator + server.getHost().getAppBase(), "fediz-idp-realmb"); server.addWebapp("/fediz-idp-realmb", idpWebapp.getAbsolutePath()); + } else if (samlSSOIdP) { + File idpWebapp = new File(baseDir + File.separator + server.getHost().getAppBase(), "idpsaml"); + server.addWebapp("/idp", idpWebapp.getAbsolutePath()); } else { File rpWebapp = new File(baseDir + File.separator + server.getHost().getAppBase(), "simpleWebapp"); - Context cxt = server.addWebapp("/fedizhelloworld", rpWebapp.getAbsolutePath()); + Context cxt = server.addWebapp("/wsfed", rpWebapp.getAbsolutePath()); FederationAuthenticator fa = new FederationAuthenticator(); fa.setConfigFile(currentDir + File.separator + "target" + File.separator + "test-classes" + File.separator + "fediz_config_wsfed.xml"); cxt.getPipeline().addValve(fa); + + rpWebapp = new File(baseDir + File.separator + server.getHost().getAppBase(), "simpleWebapp"); + cxt = server.addWebapp("/samlsso", rpWebapp.getAbsolutePath()); + cxt.getPipeline().addValve(fa); + + rpWebapp = new File(baseDir + File.separator + server.getHost().getAppBase(), "simpleWebapp"); + cxt = server.addWebapp("/samlssocustom", rpWebapp.getAbsolutePath()); + cxt.getPipeline().addValve(fa); + + rpWebapp = new File(baseDir + File.separator + server.getHost().getAppBase(), "simpleWebapp"); + cxt = server.addWebapp("/samlssocustompost", rpWebapp.getAbsolutePath()); + cxt.getPipeline().addValve(fa); } server.start(); @@ -151,6 +185,7 @@ public class WSFedTest { public static void cleanup() { shutdownServer(idpServer); shutdownServer(idpRealmbServer); + shutdownServer(idpSamlSSOServer); shutdownServer(rpServer); } @@ -185,8 +220,8 @@ public class WSFedTest { } @org.junit.Test - public void testWSFed() throws Exception { - String url = "https://localhost:" + getRpHttpsPort() + "/fedizhelloworld/secure/fedservlet"; + public void testWSFederation() throws Exception { + String url = "https://localhost:" + getRpHttpsPort() + "/wsfed/secure/fedservlet"; // System.out.println(url); // Thread.sleep(60 * 2 * 1000); String user = "ALICE"; // realm b credentials @@ -215,6 +250,132 @@ public class WSFedTest { bodyTextContent.contains(claim + "[email protected]")); } + @org.junit.Test + public void testSAMLSSOFedizIdP() throws Exception { + String url = "https://localhost:" + getRpHttpsPort() + "/samlsso/secure/fedservlet"; + // System.out.println(url); + // Thread.sleep(60 * 2 * 1000); + String user = "ALICE"; // realm b credentials + String password = "ECILA"; + + final String bodyTextContent = + login(url, user, password, getIdpRealmbHttpsPort(), getIdpHttpsPort(), true); + + 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 '[email protected]'", + bodyTextContent.contains(claim + "[email protected]")); + } + + @org.junit.Test + public void testSAMLSSOCustom() throws Exception { + String url = "https://localhost:" + getRpHttpsPort() + "/samlssocustom/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, 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 '[email protected]'", + bodyTextContent.contains(claim + "[email protected]")); + } + + @org.junit.Test + public void testSAMLSSOCustomPostBinding() throws Exception { + String url = "https://localhost:" + getRpHttpsPort() + "/samlssocustompost/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")); + 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 '[email protected]'", + bodyTextContent.contains(claim + "[email protected]")); + } + + @Test + public void testSAMLSSOIdPServiceMetadata() throws Exception { + String url = "https://localhost:" + getIdpHttpsPort() + + "/fediz-idp/metadata/urn:org:apache:cxf:fediz:idp:realm-B"; + + final WebClient webClient = new WebClient(); + webClient.getOptions().setUseInsecureSSL(true); + webClient.getOptions().setSSLClientCertificate( + this.getClass().getClassLoader().getResource("client.jks"), "storepass", "jks"); + + final XmlPage rpPage = webClient.getPage(url); + final String xmlContent = rpPage.asXml(); + Assert.assertTrue(xmlContent.startsWith("<md:EntityDescriptor")); + + // Now validate the Signature + Document doc = rpPage.getXmlDocument(); + + doc.getDocumentElement().setIdAttributeNS(null, "ID", true); + + Node signatureNode = + DOMUtils.getChild(doc.getDocumentElement(), "Signature"); + Assert.assertNotNull(signatureNode); + + XMLSignature signature = new XMLSignature((Element)signatureNode, ""); + KeyInfo ki = signature.getKeyInfo(); + Assert.assertNotNull(ki); + Assert.assertNotNull(ki.getX509Certificate()); + + Assert.assertTrue(signature.checkSignatureValue(ki.getX509Certificate())); + + webClient.close(); + } + private static String login(String url, String user, String password, String idpPort, String rpIdpPort) throws IOException { // @@ -282,5 +443,47 @@ public class WSFedTest { return rpPage.getBody().getTextContent(); } + private static String login(String url, String user, String password, + 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". + // + final WebClient webClient = new WebClient(); + CookieManager cookieManager = new CookieManager(); + webClient.setCookieManager(cookieManager); + webClient.getOptions().setUseInsecureSSL(true); + webClient.getCredentialsProvider().setCredentials( + new AuthScope("localhost", Integer.parseInt(idpPort)), + new UsernamePasswordCredentials(user, password)); + + webClient.getOptions().setJavaScriptEnabled(false); + HtmlPage idpPage = webClient.getPage(url); + + if (postBinding) { + Assert.assertTrue("SAML IDP Response Form".equals(idpPage.getTitleText()) + || "IDP SignIn Response Form".equals(idpPage.getTitleText())); + for (HtmlForm form : idpPage.getForms()) { + String name = form.getAttributeNS(null, "name"); + if ("signinresponseform".equals(name) || "samlsigninresponseform".equals(name)) { + final HtmlSubmitInput button = form.getInputByName("_eventId_submit"); + idpPage = button.click(); + } + } + } + + Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText()); + + // Now redirect back to the RP + final HtmlForm form = idpPage.getFormByName("signinresponseform"); + + final HtmlSubmitInput button = form.getInputByName("_eventId_submit"); + + final HtmlPage rpPage = button.click(); + Assert.assertEquals("WS Federation Systests Examples", rpPage.getTitleText()); + + webClient.close(); + return rpPage.getBody().getTextContent(); + } } http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6fef44bb/systests/federation/wsfed/src/test/resources/fediz_config_wsfed.xml ---------------------------------------------------------------------- diff --git a/systests/federation/wsfed/src/test/resources/fediz_config_wsfed.xml b/systests/federation/wsfed/src/test/resources/fediz_config_wsfed.xml index 7bd3cb7..b9f47e4 100644 --- a/systests/federation/wsfed/src/test/resources/fediz_config_wsfed.xml +++ b/systests/federation/wsfed/src/test/resources/fediz_config_wsfed.xml @@ -22,7 +22,7 @@ keystore (tomcat-rp.jks) for this task; alternatively you may wish to use a Fediz-specific keystore instead. --> <FedizConfig> - <contextConfig name="/fedizhelloworld"> + <contextConfig name="/wsfed"> <audienceUris> <audienceItem>urn:org:apache:cxf:fediz:fedizhelloworld</audienceItem> </audienceUris> @@ -52,5 +52,95 @@ <logoutURL>/secure/logout</logoutURL> <logoutRedirectTo>/index.html</logoutRedirectTo> </contextConfig> + <contextConfig name="/samlsso"> + <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> + <contextConfig name="/samlssocustom"> + <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-D</homeRealm> + <claimTypesRequested> + <claimType type="a particular claim type" + optional="true" /> + </claimTypesRequested> + </protocol> + <logoutURL>/secure/logout</logoutURL> + <logoutRedirectTo>/index.html</logoutRedirectTo> + </contextConfig> + <contextConfig name="/samlssocustompost"> + <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-E</homeRealm> + <claimTypesRequested> + <claimType type="a particular claim type" + optional="true" /> + </claimTypesRequested> + </protocol> + <logoutURL>/secure/logout</logoutURL> + <logoutRedirectTo>/index.html</logoutRedirectTo> + </contextConfig> </FedizConfig> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6fef44bb/systests/federation/wsfed/src/test/resources/realma/entities-realma.xml ---------------------------------------------------------------------- diff --git a/systests/federation/wsfed/src/test/resources/realma/entities-realma.xml b/systests/federation/wsfed/src/test/resources/realma/entities-realma.xml index 4cca3ec..2cdc6f2 100644 --- a/systests/federation/wsfed/src/test/resources/realma/entities-realma.xml +++ b/systests/federation/wsfed/src/test/resources/realma/entities-realma.xml @@ -65,6 +65,9 @@ <property name="trustedIdps"> <util:list> <ref bean="trusted-idp-realmB" /> + <ref bean="trusted-idp-realmC" /> + <ref bean="trusted-idp-realmD" /> + <ref bean="trusted-idp-realmE" /> </util:list> </property> <property name="claimTypesOffered"> @@ -89,6 +92,62 @@ <property name="name" value="Realm B" /> <property name="description" value="Realm B description" /> </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="issuer" value="urn:org:apache:cxf:fediz:idp:realm-B" /> + <property name="cacheTokens" value="true" /> + <property name="url" value="https://localhost:${idp.realmb.https.port}/fediz-idp-realmb/saml/up" /> + <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 B" /> + <property name="description" value="Realm B description" /> + <property name="parameters"> + <util:map> + <entry key="sign.request" value="true" /> + </util:map> + </property> + </bean> + + <bean id="trusted-idp-realmD" + class="org.apache.cxf.fediz.service.idp.service.jpa.TrustedIdpEntity"> + <property name="realm" value="urn:org:apache:cxf:fediz:idp:realm-D" /> + <property name="cacheTokens" value="true" /> + <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" /> + <property name="federationType" value="FEDERATE_IDENTITY" /> + <property name="name" value="Realm D" /> + <property name="description" value="Realm D description" /> + <property name="parameters"> + <util:map> + <entry key="sign.request" value="true" /> + <entry key="support.deflate.encoding" value="true" /> + </util:map> + </property> + </bean> + + <bean id="trusted-idp-realmE" + class="org.apache.cxf.fediz.service.idp.service.jpa.TrustedIdpEntity"> + <property name="realm" value="urn:org:apache:cxf:fediz:idp:realm-E" /> + <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 E" /> + <property name="description" value="SAML Web Profile - Response POST Binding" /> + <property name="parameters"> + <util:map> + <entry key="sign.request" 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" /> @@ -99,7 +158,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)*/secure/.*" /> </bean> <bean class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationClaimEntity"> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6fef44bb/systests/federation/wsfed/src/test/resources/realmb/entities-realmb.xml ---------------------------------------------------------------------- diff --git a/systests/federation/wsfed/src/test/resources/realmb/entities-realmb.xml b/systests/federation/wsfed/src/test/resources/realmb/entities-realmb.xml index fc203fb..5734ab9 100644 --- a/systests/federation/wsfed/src/test/resources/realmb/entities-realmb.xml +++ b/systests/federation/wsfed/src/test/resources/realmb/entities-realmb.xml @@ -37,10 +37,9 @@ <property name="idpUrl" value="https://localhost:${idp.realmb.https.port}/fediz-idp-realmb/federation" /> <property name="supportedProtocols"> <util:list> - <value>http://docs.oasis-open.org/wsfed/federation/200706 - </value> - <value>http://docs.oasis-open.org/ws-sx/ws-trust/200512 - </value> + <value>http://docs.oasis-open.org/wsfed/federation/200706</value> + <value>http://docs.oasis-open.org/ws-sx/ws-trust/200512</value> + <value>urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser</value> </util:list> </property> <property name="tokenTypesOffered"> @@ -79,6 +78,7 @@ <property name="role" value="SecurityTokenServiceType" /> <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="validatingCertificate" value="realma.cert" /> </bean> <bean id="claim_role" http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6fef44bb/systests/federation/wsfed/src/test/resources/realmb/idp-servlet.xml ---------------------------------------------------------------------- diff --git a/systests/federation/wsfed/src/test/resources/realmb/idp-servlet.xml b/systests/federation/wsfed/src/test/resources/realmb/idp-servlet.xml index 0a68517..e557819 100644 --- a/systests/federation/wsfed/src/test/resources/realmb/idp-servlet.xml +++ b/systests/federation/wsfed/src/test/resources/realmb/idp-servlet.xml @@ -81,6 +81,10 @@ id="signinRequest" /> <webflow:flow-location path="/WEB-INF/flows/federation-signin-response.xml" id="signinResponse" /> + + <webflow:flow-location path="/WEB-INF/flows/saml-validate-request.xml" id="saml" /> + <webflow:flow-location path="/WEB-INF/flows/saml-validate-request.xml" id="saml/up" /> + <webflow:flow-location path="/WEB-INF/flows/saml-signin-request.xml" id="signinSAMLRequest" /> </webflow:flow-registry> <webflow:flow-builder-services id="builder" http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6fef44bb/systests/federation/wsfed/src/test/resources/realmb/security-config.xml ---------------------------------------------------------------------- diff --git a/systests/federation/wsfed/src/test/resources/realmb/security-config.xml b/systests/federation/wsfed/src/test/resources/realmb/security-config.xml index e59ace7..6ddfb89 100644 --- a/systests/federation/wsfed/src/test/resources/realmb/security-config.xml +++ b/systests/federation/wsfed/src/test/resources/realmb/security-config.xml @@ -88,6 +88,32 @@ <security:http-basic /> <security:logout delete-cookies="FEDIZ_HOME_REALM" invalidate-session="true" /> </security:http> + + <security:http pattern="/saml" use-expressions="true" entry-point-ref="fedizEntryPoint"> + <security:custom-filter after="CHANNEL_FILTER" ref="stsPortFilter" /> + <security:custom-filter after="SERVLET_API_SUPPORT_FILTER" ref="entitlementsEnricher" /> + </security:http> + + <!-- HTTP/BA entry point --> + <security:http pattern="/saml/up/**" use-expressions="true"> + <security:intercept-url requires-channel="https" pattern="/saml/up/login*" access="isAnonymous() or isAuthenticated()" /> + <security:custom-filter after="CHANNEL_FILTER" ref="stsPortFilter" /> + <security:custom-filter after="SERVLET_API_SUPPORT_FILTER" ref="entitlementsEnricher" /> + + <security:http-basic /> + <!--security:form-login login-page='/federation/up/login' + login-processing-url="/federation/up/login.do" + authentication-failure-url="/federation/up/login?error" + default-target-url="/" + username-parameter="username" + password-parameter="password" + /--> + <security:logout logout-url="/saml/up/logout" + logout-success-url="/saml/up/login?out" + delete-cookies="FEDIZ_HOME_REALM,JSESSIONID" + invalidate-session="true" + /> + </security:http> <security:authentication-manager> <security:authentication-provider ref="stsAuthProvider" />
