FEDIZ-182 - Add support for bridging from SAML SSO -> OIDC
Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/0b04bdd5 Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/0b04bdd5 Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/0b04bdd5 Branch: refs/heads/master Commit: 0b04bdd50c6da961cf54b060bb600c38599a66b1 Parents: f20a014 Author: Colm O hEigeartaigh <[email protected]> Authored: Mon Dec 5 13:02:14 2016 +0000 Committer: Colm O hEigeartaigh <[email protected]> Committed: Mon Dec 5 13:02:14 2016 +0000 ---------------------------------------------------------------------- .../WEB-INF/flows/saml-validate-request.xml | 14 +- .../cxf/fediz/integrationtests/SAMLSSOTest.java | 75 +++++++- .../samlsso/src/test/resources/cxf-service.xml | 2 +- .../src/test/resources/fediz_config_wsfed.xml | 176 ------------------- .../test/resources/realma/entities-realma.xml | 25 ++- .../src/test/resources/rp/cxf-service.xml | 25 +++ 6 files changed, 129 insertions(+), 188 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/0b04bdd5/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 7cda428..36ac3a8 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 @@ -28,7 +28,7 @@ </on-entry> <if test="requestParameters.wa == 'wsignin1.0'" then="selectWsFedProcess" /> <if test="requestParameters.SAMLRequest != null or requestParameters.SAMLResponse != null" - then="selectSAMLProcess" else="viewBadRequest" + then="selectSAMLProcess" else="selectOIDCAuthorizationCodeFlowProcess" /> </decision-state> @@ -62,6 +62,18 @@ then="viewBadRequest" else="signinResponse" /> </decision-state> + <decision-state id="selectOIDCAuthorizationCodeFlowProcess"> + <on-entry> + <set name="flowScope.state" value="requestParameters.state" /> + <set name="flowScope.request_context" value="requestParameters.state" /> + <set name="flowScope.code" value="requestParameters.code" /> + </on-entry> + <if test="requestParameters.code == null or requestParameters.code.isEmpty()" + then="viewBadRequest" /> + <if test="requestParameters.state == null or requestParameters.state.isEmpty()" + then="viewBadRequest" else="signinResponse" /> + </decision-state> + <subflow-state id="signinSAMLRequest" subflow="signinSAMLRequest"> <input name="idpConfig" value="flowScope.idpConfig" /> <input name="SAMLRequest" value="flowScope.SAMLRequest" /> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/0b04bdd5/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 61f79d6..a3d9dff 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 @@ -22,14 +22,19 @@ package org.apache.cxf.fediz.integrationtests; import java.io.File; import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; import javax.servlet.ServletException; import com.gargoylesoftware.htmlunit.CookieManager; +import com.gargoylesoftware.htmlunit.HttpMethod; import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.WebRequest; import com.gargoylesoftware.htmlunit.html.HtmlForm; import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput; +import com.gargoylesoftware.htmlunit.util.NameValuePair; import com.gargoylesoftware.htmlunit.xml.XmlPage; import org.apache.catalina.LifecycleException; @@ -149,12 +154,6 @@ public class SAMLSSOTest { } else { File rpWebapp = new File(baseDir + File.separator + server.getHost().getAppBase(), "samlssoWebapp"); server.addWebapp("/samlsso", rpWebapp.getAbsolutePath()); - - /* - rpWebapp = new File(baseDir + File.separator + server.getHost().getAppBase(), "simpleWebapp"); - cxt = server.addWebapp("/oidc", rpWebapp.getAbsolutePath()); - cxt.getPipeline().addValve(fa); - */ } server.start(); @@ -229,6 +228,19 @@ public class SAMLSSOTest { Assert.assertTrue(bodyTextContent.contains("This is the double number response")); } + + @org.junit.Test + public void testOIDC() throws Exception { + String url = "https://localhost:" + getRpHttpsPort() + "/samlsso/app3/services/25"; + String user = "ALICE"; // realm b credentials + String password = "ECILA"; + + final String bodyTextContent = + loginOIDC(url, user, password, idpOIDCHttpsPort, idpHttpsPort); + + Assert.assertTrue(bodyTextContent.contains("This is the double number response")); + } + private static String login(String url, String user, String password, String idpPort, String rpIdpPort) throws IOException { @@ -300,7 +312,6 @@ public class SAMLSSOTest { Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText()); - System.out.println("IDP: " + idpPage.asXml()); // Now redirect back to the RP final HtmlForm form = idpPage.getFormByName("samlsigninresponseform"); @@ -312,4 +323,54 @@ public class SAMLSSOTest { return rpPage.asXml(); } + private static String loginOIDC(String url, String user, String password, + String idpPort, String rpIdpPort) 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); + + // The decision page is returned as XML for some reason. So parse it and send a form response back. + HtmlPage oidcIdpConfirmationPage = webClient.getPage(url); + final HtmlForm oidcForm = oidcIdpConfirmationPage.getForms().get(0); + + WebRequest request = new WebRequest(new URL(oidcForm.getActionAttribute()), HttpMethod.POST); + + request.setRequestParameters(new ArrayList<NameValuePair>()); + String clientId = oidcForm.getInputByName("client_id").getValueAttribute(); + request.getRequestParameters().add(new NameValuePair("client_id", clientId)); + String redirectUri = oidcForm.getInputByName("redirect_uri").getValueAttribute(); + request.getRequestParameters().add(new NameValuePair("redirect_uri", redirectUri)); + String scope = oidcForm.getInputByName("scope").getValueAttribute(); + request.getRequestParameters().add(new NameValuePair("scope", scope)); + String state = oidcForm.getInputByName("state").getValueAttribute(); + request.getRequestParameters().add(new NameValuePair("state", state)); + String authToken = oidcForm.getInputByName("session_authenticity_token").getValueAttribute(); + request.getRequestParameters().add(new NameValuePair("session_authenticity_token", authToken)); + request.getRequestParameters().add(new NameValuePair("oauthDecision", "allow")); + + HtmlPage idpPage = webClient.getPage(request); + + Assert.assertEquals("IDP SignIn Response Form", idpPage.getTitleText()); + + // Now redirect back to the RP + final HtmlForm form = idpPage.getFormByName("samlsigninresponseform"); + + final HtmlSubmitInput button = form.getInputByName("_eventId_submit"); + + final XmlPage rpPage = button.click(); + + webClient.close(); + return rpPage.asXml(); + } + } http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/0b04bdd5/systests/federation/samlsso/src/test/resources/cxf-service.xml ---------------------------------------------------------------------- diff --git a/systests/federation/samlsso/src/test/resources/cxf-service.xml b/systests/federation/samlsso/src/test/resources/cxf-service.xml index a03d3fa..eba2446 100644 --- a/systests/federation/samlsso/src/test/resources/cxf-service.xml +++ b/systests/federation/samlsso/src/test/resources/cxf-service.xml @@ -63,7 +63,7 @@ <constructor-arg><value>Fediz IdP</value></constructor-arg> <property name="redirectUris"> <util:list value-type="java.lang.String"> - <value>https://localhost:${idp.https.port}/fediz-idp/federation</value> + <value>https://localhost:${idp.https.port}/fediz-idp/saml</value> </util:list> </property> <property name="allowedGrantTypes"> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/0b04bdd5/systests/federation/samlsso/src/test/resources/fediz_config_wsfed.xml ---------------------------------------------------------------------- diff --git a/systests/federation/samlsso/src/test/resources/fediz_config_wsfed.xml b/systests/federation/samlsso/src/test/resources/fediz_config_wsfed.xml deleted file mode 100644 index c63530b..0000000 --- a/systests/federation/samlsso/src/test/resources/fediz_config_wsfed.xml +++ /dev/null @@ -1,176 +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. ---> -<!-- Place in Tomcat conf folder or other location as designated in this sample's webapp/META-INF/context.xml file. - Keystore referenced below must have IDP STS' public cert included in it. This example re-uses the Tomcat SSL - keystore (tomcat-rp.jks) for this task; alternatively you may wish to use a Fediz-specific keystore instead. ---> -<FedizConfig> - <contextConfig name="/wsfed"> - <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-B</homeRealm> - <claimTypesRequested> - <claimType type="a particular claim type" - optional="true" /> - </claimTypesRequested> - </protocol> - <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> - <contextConfig name="/oidc"> - <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-F</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/0b04bdd5/systests/federation/samlsso/src/test/resources/realma/entities-realma.xml ---------------------------------------------------------------------- diff --git a/systests/federation/samlsso/src/test/resources/realma/entities-realma.xml b/systests/federation/samlsso/src/test/resources/realma/entities-realma.xml index c0dd89b..6e840f5 100644 --- a/systests/federation/samlsso/src/test/resources/realma/entities-realma.xml +++ b/systests/federation/samlsso/src/test/resources/realma/entities-realma.xml @@ -61,6 +61,7 @@ <util:list> <ref bean="srv-fedizhelloworld-realmB" /> <ref bean="srv-fedizhelloworld-realmC" /> + <ref bean="srv-fedizhelloworld-realmD" /> </util:list> </property> <property name="trustedIdps"> @@ -116,7 +117,7 @@ <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-F" /> + <property name="realm" value="urn:org:apache:cxf:fediz:idp:realm-D" /> <property name="cacheTokens" value="true" /> <property name="url" value="https://localhost:${idp.oidc.https.port}/idpoidc/services/authorize" /> <property name="certificate" value="realmb.cert" /> @@ -138,7 +139,7 @@ <property name="realm" value="urn:org:apache:cxf:fediz:fedizhelloworld:realm-B" /> <property name="protocol" value="http://docs.oasis-open.org/wsfed/federation/200706" /> <property name="serviceDisplayName" value="Fedizhelloworld" /> - <property name="serviceDescription" value="Web Application to illustrate WS-Federation" /> + <property name="serviceDescription" value="Web Application to illustrate SAML SSO" /> <property name="role" value="ApplicationServiceType" /> <property name="tokenType" value="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0" /> <property name="lifeTime" value="3600" /> @@ -151,7 +152,20 @@ <property name="realm" value="urn:org:apache:cxf:fediz:fedizhelloworld:realm-C" /> <property name="protocol" value="http://docs.oasis-open.org/wsfed/federation/200706" /> <property name="serviceDisplayName" value="Fedizhelloworld" /> - <property name="serviceDescription" value="Web Application to illustrate WS-Federation" /> + <property name="serviceDescription" value="Web Application to illustrate SAML SSO" /> + <property name="role" value="ApplicationServiceType" /> + <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)*/racs/.*" /> + <property name="validatingCertificate" value="realma.cert" /> + </bean> + + <bean id="srv-fedizhelloworld-realmD" class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationEntity"> + <property name="realm" value="urn:org:apache:cxf:fediz:fedizhelloworld:realm-D" /> + <property name="protocol" value="http://docs.oasis-open.org/wsfed/federation/200706" /> + <property name="serviceDisplayName" value="Fedizhelloworld" /> + <property name="serviceDescription" value="Web Application to illustrate SAML SSO" /> <property name="role" value="ApplicationServiceType" /> <property name="tokenType" value="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0" /> <property name="lifeTime" value="3600" /> @@ -171,6 +185,11 @@ <property name="optional" value="false" /> </bean> <bean class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationClaimEntity"> + <property name="application" ref="srv-fedizhelloworld-realmD" /> + <property name="claim" ref="claim_role" /> + <property name="optional" value="false" /> + </bean> + <bean class="org.apache.cxf.fediz.service.idp.service.jpa.ApplicationClaimEntity"> <property name="application" ref="srv-fedizhelloworld-realmB" /> <property name="claim" ref="claim_givenname" /> <property name="optional" value="false" /> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/0b04bdd5/systests/federation/samlsso/src/test/resources/rp/cxf-service.xml ---------------------------------------------------------------------- diff --git a/systests/federation/samlsso/src/test/resources/rp/cxf-service.xml b/systests/federation/samlsso/src/test/resources/rp/cxf-service.xml index 6f8d70a..11f179d 100644 --- a/systests/federation/samlsso/src/test/resources/rp/cxf-service.xml +++ b/systests/federation/samlsso/src/test/resources/rp/cxf-service.xml @@ -111,6 +111,31 @@ <ref bean="authorizationInterceptor"/> </jaxrs:inInterceptors> </jaxrs:server> + + <bean id="ssoFilterApp3" class="org.apache.cxf.rs.security.saml.sso.SamlRedirectBindingFilter"> + <property name="idpServiceAddress" value="https://localhost:${idp.https.port}/fediz-idp/saml/up"/> + <property name="assertionConsumerServiceAddress" + value="/racs/sso"/> + <property name="stateProvider" ref="stateManager"/> + <property name="addEndpointAddressToContext" value="true"/> + <property name="signRequest" value="true"/> + <property name="signaturePropertiesFile" value="stsKeystoreA.properties"/> + <property name="callbackHandler" ref="callbackHandler"/> + <property name="signatureUsername" value="realma" /> + <property name="issuerId" value="urn:org:apache:cxf:fediz:fedizhelloworld:realm-D" /> + </bean> + + <jaxrs:server address="/app3"> + <jaxrs:serviceBeans> + <ref bean="serviceBean"/> + </jaxrs:serviceBeans> + <jaxrs:providers> + <ref bean="ssoFilterApp3"/> + </jaxrs:providers> + <jaxrs:inInterceptors> + <ref bean="authorizationInterceptor"/> + </jaxrs:inInterceptors> + </jaxrs:server> <bean id="consumerService" class="org.apache.cxf.rs.security.saml.sso.RequestAssertionConsumerService"> <property name="stateProvider" ref="stateManager"/>
