Take the application realm from the SAML AuthnRequest Issuer
Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/6abaf271 Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/6abaf271 Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/6abaf271 Branch: refs/heads/master Commit: 6abaf2715c007a5d1a14f89c4ec859b4dd30b6aa Parents: d1adf65 Author: Colm O hEigeartaigh <cohei...@apache.org> Authored: Tue Mar 15 15:29:42 2016 +0000 Committer: Colm O hEigeartaigh <cohei...@apache.org> Committed: Tue Mar 15 15:29:42 2016 +0000 ---------------------------------------------------------------------- .../service/idp/beans/STSClientAction.java | 24 +- .../beans/samlsso/AuthnRequestRealmParser.java | 81 +++++ .../flows/federation-validate-request.xml | 2 +- .../WEB-INF/flows/saml-validate-request.xml | 8 +- systests/samlsso/out.txt | 312 ++++++++++--------- .../apache/cxf/fediz/systests/idp/IdpTest.java | 47 ++- .../test/resources/realma/entities-realma.xml | 5 - 7 files changed, 300 insertions(+), 179 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6abaf271/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/STSClientAction.java ---------------------------------------------------------------------- diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/STSClientAction.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/STSClientAction.java index 6b4e07d..3efd103 100644 --- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/STSClientAction.java +++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/STSClientAction.java @@ -177,16 +177,14 @@ public class STSClientAction { } /** - * @param context - * the webflow request context + * @param realm The client/application realm + * @param context the webflow request context * @return a serialized RP security token * @throws Exception */ - public String submit(RequestContext context) + public String submit(String realm, RequestContext context) throws Exception { - String wtrealm = (String)WebUtils.getAttributeFromFlowScope(context, FederationConstants.PARAM_TREALM); - SecurityToken idpToken = getSecurityToken(context); Idp idpConfig = (Idp) WebUtils.getAttributeFromFlowScope(context, IDP_CONFIG); @@ -196,9 +194,9 @@ public class STSClientAction { IdpSTSClient sts = new IdpSTSClient(cxfBus); sts.setAddressingNamespace(HTTP_WWW_W3_ORG_2005_08_ADDRESSING); - Application serviceConfig = idpConfig.findApplication(wtrealm); + Application serviceConfig = idpConfig.findApplication(realm); if (serviceConfig == null) { - LOG.warn("No service config found for " + wtrealm); + LOG.warn("No service config found for " + realm); throw new ProcessingException(TYPE.BAD_REQUEST); } @@ -245,7 +243,7 @@ public class STSClientAction { sts.setWspNamespace(serviceConfig.getPolicyNamespace()); } - LOG.debug("TokenType {} set for realm {}", sts.getTokenType(), wtrealm); + LOG.debug("TokenType {} set for realm {}", sts.getTokenType(), realm); sts.setKeyType(stsKeyType); if (HTTP_DOCS_OASIS_OPEN_ORG_WS_SX_WS_TRUST_200512_PUBLICKEY.equals(stsKeyType)) { @@ -273,22 +271,22 @@ public class STSClientAction { if (serviceConfig.getRequestedClaims() != null && serviceConfig.getRequestedClaims().size() > 0) { addClaims(sts, serviceConfig.getRequestedClaims()); - LOG.debug("Requested claims set for {}", wtrealm); + LOG.debug("Requested claims set for {}", realm); } sts.setEnableLifetime(true); - setLifetime(sts, serviceConfig, wtrealm); + setLifetime(sts, serviceConfig, realm); sts.setOnBehalfOf(idpToken.getToken()); if (!(serviceConfig.getProtocol() == null || FederationConstants.WS_FEDERATION_NS.equals(serviceConfig.getProtocol()))) { - LOG.error("Protocol {} not supported for realm {} ", serviceConfig.getProtocol(), wtrealm); + LOG.error("Protocol {} not supported for realm {} ", serviceConfig.getProtocol(), realm); throw new ProcessingException(TYPE.BAD_REQUEST); } String rpToken = null; try { - rpToken = sts.requestSecurityTokenResponse(wtrealm); + rpToken = sts.requestSecurityTokenResponse(realm); } catch (SoapFault ex) { LOG.error("Error in retrieving a token", ex.getMessage()); if (ex.getFaultCode() != null @@ -302,7 +300,7 @@ public class STSClientAction { String id = getIdFromToken(rpToken); LOG.info("[RP_TOKEN={}] successfully created for realm [{}] on behalf of [IDP_TOKEN={}]", - id, wtrealm, idpToken.getId()); + id, realm, idpToken.getId()); } return StringEscapeUtils.escapeXml11(rpToken); } http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6abaf271/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestRealmParser.java ---------------------------------------------------------------------- diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestRealmParser.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestRealmParser.java new file mode 100644 index 0000000..8319821 --- /dev/null +++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/samlsso/AuthnRequestRealmParser.java @@ -0,0 +1,81 @@ +/** + * 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.InputStream; +import java.io.InputStreamReader; + +import org.w3c.dom.Document; + +import org.apache.cxf.common.util.Base64Utility; +import org.apache.cxf.rs.security.saml.DeflateEncoderDecoder; +import org.apache.cxf.rs.security.saml.sso.SSOConstants; +import org.apache.cxf.staxutils.StaxUtils; +import org.apache.wss4j.common.saml.OpenSAMLUtil; +import org.apache.wss4j.common.util.DOM2Writer; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.webflow.execution.RequestContext; + +/** + * Parse the received AuthnRequest and extract the home realm of the request from the Issuer + * value. + */ +@Component +public class AuthnRequestRealmParser { + + private static final Logger LOG = LoggerFactory.getLogger(AuthnRequestRealmParser.class); + + public String retrieveRealm(RequestContext context) { + String samlRequest = context.getFlowScope().getString(SSOConstants.SAML_REQUEST); + LOG.debug("Received SAML Request: {}", samlRequest); + + if (samlRequest != null) { + try { + AuthnRequest parsedRequest = extractRequest(samlRequest); + if (parsedRequest.getIssuer() != null) { + String issuer = parsedRequest.getIssuer().getValue(); + LOG.debug("Parsed SAML AuthnRequest Issuer: {}", issuer); + return issuer; + } + } catch (Exception ex) { + LOG.warn("Error parsing request: {}", ex.getMessage()); + return null; + } + } + + LOG.debug("No SamlRequest available to be parsed"); + return null; + } + + private AuthnRequest extractRequest(String samlRequest) throws Exception { + 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()); + if (LOG.isDebugEnabled()) { + LOG.debug(DOM2Writer.nodeToString(responseDoc)); + } + return request; + } +} http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6abaf271/services/idp/src/main/webapp/WEB-INF/flows/federation-validate-request.xml ---------------------------------------------------------------------- diff --git a/services/idp/src/main/webapp/WEB-INF/flows/federation-validate-request.xml b/services/idp/src/main/webapp/WEB-INF/flows/federation-validate-request.xml index 8c020df..b22f48e 100644 --- a/services/idp/src/main/webapp/WEB-INF/flows/federation-validate-request.xml +++ b/services/idp/src/main/webapp/WEB-INF/flows/federation-validate-request.xml @@ -136,7 +136,7 @@ <!-- produce RP security token (as String type) --> <action-state id="requestRpToken"> <on-entry> - <evaluate expression="stsClientForRpAction.submit(flowRequestContext)" + <evaluate expression="stsClientForRpAction.submit(flowScope.wtrealm, flowRequestContext)" result="flowScope.rpToken"/> </on-entry> <evaluate expression="signinParametersCacheAction.storeRPConfigInSession(flowRequestContext)" /> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/6abaf271/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 8070ecd..f5734b6 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 @@ -37,8 +37,8 @@ <subflow-state id="signinSAMLRequest" subflow="signinSAMLRequest"> <input name="idpConfig" value="flowScope.idpConfig" /> - <input name="wauth" value="flowScope.wauth" /> - <input name="whr" value="flowScope.whr" /> + <input name="SAMLRequest" value="flowScope.SAMLRequest" /> + <input name="RelayState" value="flowScope.RelayState" /> <output name="whr" /> <output name="idpToken" /> @@ -58,7 +58,9 @@ <!-- produce RP security token (as String type) --> <action-state id="requestRpToken"> <on-entry> - <evaluate expression="stsClientForRpAction.submit(flowRequestContext)" + <evaluate expression="authnRequestRealmParser.retrieveRealm(flowRequestContext)" + result="flowScope.realm"/> + <evaluate expression="stsClientForRpAction.submit(flowScope.realm, flowRequestContext)" result="flowScope.rpToken"/> </on-entry> <evaluate expression="signinParametersCacheAction.storeRPConfigInSession(flowRequestContext)"/>