Repository: cxf-fediz Updated Branches: refs/heads/master e434cfaa7 -> 113a2f8ba
Adding initial support for SAML SSO in the webflow Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/bab0283d Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/bab0283d Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/bab0283d Branch: refs/heads/master Commit: bab0283da7944a6d89e6ff8f1aa4997ed583cd52 Parents: e434cfa Author: Colm O hEigeartaigh <[email protected]> Authored: Thu Feb 26 12:26:39 2015 +0000 Committer: Colm O hEigeartaigh <[email protected]> Committed: Thu Feb 26 12:26:39 2015 +0000 ---------------------------------------------------------------------- .../idp/beans/SigninParametersCacheAction.java | 6 ++++ .../TrustedIdpSAMLProtocolHandler.java | 36 ++++++++++++-------- .../WEB-INF/federation-signin-request.xml | 1 + .../WEB-INF/federation-signin-response.xml | 2 ++ .../WEB-INF/federation-validate-request.xml | 10 ++++-- 5 files changed, 39 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bab0283d/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/SigninParametersCacheAction.java ---------------------------------------------------------------------- diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/SigninParametersCacheAction.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/SigninParametersCacheAction.java index 636bcb2..b1525df 100644 --- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/SigninParametersCacheAction.java +++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/beans/SigninParametersCacheAction.java @@ -24,6 +24,7 @@ import java.util.Map; import java.util.UUID; import org.apache.cxf.fediz.core.FederationConstants; +import org.apache.cxf.fediz.core.SAMLSSOConstants; import org.apache.cxf.fediz.core.exception.ProcessingException; import org.apache.cxf.fediz.service.idp.domain.Application; import org.apache.cxf.fediz.service.idp.domain.Idp; @@ -66,6 +67,11 @@ public class SigninParametersCacheAction { public void restore(RequestContext context) { String uuidKey = (String)WebUtils.getAttributeFromFlowScope(context, FederationConstants.PARAM_CONTEXT); + + // TODO Abstract the concept of a context to cater for either protocol + if (uuidKey == null) { + uuidKey = (String)WebUtils.getAttributeFromFlowScope(context, SAMLSSOConstants.RELAY_STATE); + } @SuppressWarnings("unchecked") Map<String, Object> signinParams = (Map<String, Object>)WebUtils.getAttributeFromExternalContext(context, uuidKey); http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bab0283d/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java ---------------------------------------------------------------------- diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java index c9fd7d0..e1b8879 100644 --- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java +++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpSAMLProtocolHandler.java @@ -27,7 +27,6 @@ import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; -import java.util.UUID; import java.util.zip.DataFormatException; import javax.servlet.http.HttpServletRequest; @@ -36,10 +35,10 @@ import javax.ws.rs.core.UriBuilder; 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.common.util.StringUtils; +import org.apache.cxf.fediz.core.FederationConstants; import org.apache.cxf.fediz.service.idp.domain.Idp; import org.apache.cxf.fediz.service.idp.domain.TrustedIdp; import org.apache.cxf.fediz.service.idp.spi.TrustedIdpProtocolHandler; @@ -54,8 +53,9 @@ import org.apache.cxf.staxutils.StaxUtils; import org.apache.cxf.ws.security.tokenstore.SecurityToken; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.saml.OpenSAMLUtil; -import org.apache.wss4j.common.saml.SamlAssertionWrapper; import org.apache.wss4j.common.util.DOM2Writer; +import org.apache.wss4j.common.util.XMLUtils; +import org.apache.wss4j.dom.WSConstants; import org.apache.xml.security.stax.impl.util.IDGenerator; import org.opensaml.saml2.core.AuthnRequest; import org.opensaml.xml.XMLObject; @@ -106,14 +106,16 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler Element authnRequestElement = OpenSAMLUtil.toDom(authnRequest, doc); String authnRequestEncoded = encodeAuthnRequest(authnRequestElement); - String relayState = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8"); - String urlEncodedRequest = URLEncoder.encode(authnRequestEncoded, "UTF-8"); UriBuilder ub = UriBuilder.fromUri(trustedIdp.getUrl()); ub.queryParam(SSOConstants.SAML_REQUEST, urlEncodedRequest); - ub.queryParam(SSOConstants.RELAY_STATE, relayState); + + String wctx = context.getFlowScope().getString(FederationConstants.PARAM_CONTEXT); + if (wctx != null) { + ub.queryParam(SSOConstants.RELAY_STATE, wctx); + } //if (isSignRequest()) { // signRequest(urlEncodedRequest, info.getRelayState(), ub); //} @@ -157,8 +159,10 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler String encodedSAMLResponse = (String) WebUtils.getAttributeFromFlowScope(context, SSOConstants.SAML_RESPONSE); - org.opensaml.saml2.core.Response samlResponse = - readSAMLResponse(false, encodedSAMLResponse); + + // Read the response + convert to an OpenSAML Response Object + Element responseElement = readSAMLResponse(false, encodedSAMLResponse); + // org.opensaml.saml2.core.Response samlResponse = convertToResponse(responseElement); // Validate the Response /* @@ -169,9 +173,8 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler String assertion = validatorResponse.getAssertion(); SamlAssertionWrapper wrapper = new SamlAssertionWrapper(assertion); */ - SamlAssertionWrapper wrapper = - new SamlAssertionWrapper(samlResponse.getAssertions().get(0)); - + Element assertionElement = + XMLUtils.getDirectChildElement(responseElement, "Assertion", WSConstants.SAML2_NS); // Create new Security token with new id. // Parameters for freshness computation are copied from original IDP_TOKEN String id = IDGenerator.generateID("_"); @@ -179,7 +182,7 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler // new SecurityToken(id, new Date(), validatorResponse.getSessionNotOnOrAfter()); // TODO new Date() above incorrect - idpToken.setToken(wrapper.toDOM(DOMUtils.newDocument())); + idpToken.setToken(assertionElement); // LOG.info("[IDP_TOKEN={}] for user '{}' created from [RP_TOKEN={}] issued by home realm [{}/{}]", // id, wfResp.getUsername(), wfResp.getUniqueTokenId(), whr, wfResp.getIssuer()); //.debug("Created date={}", wfResp.getTokenCreated()); @@ -197,7 +200,7 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler } } - private org.opensaml.saml2.core.Response readSAMLResponse( + private Element readSAMLResponse( boolean postBinding, String samlResponse ) { if (StringUtils.isEmpty(samlResponse)) { @@ -243,10 +246,15 @@ public class TrustedIdpSAMLProtocolHandler implements TrustedIdpProtocolHandler } LOG.debug("Received response: " + DOM2Writer.nodeToString(responseDoc.getDocumentElement())); + + return responseDoc.getDocumentElement(); + } + + protected org.opensaml.saml2.core.Response convertToResponse(Element samlResponseElement) { XMLObject responseObject = null; try { - responseObject = OpenSAMLUtil.fromDom(responseDoc.getDocumentElement()); + responseObject = OpenSAMLUtil.fromDom(samlResponseElement); } catch (WSSecurityException ex) { throw ExceptionUtils.toBadRequestException(ex, null); } http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bab0283d/services/idp/src/main/webapp/WEB-INF/federation-signin-request.xml ---------------------------------------------------------------------- diff --git a/services/idp/src/main/webapp/WEB-INF/federation-signin-request.xml b/services/idp/src/main/webapp/WEB-INF/federation-signin-request.xml index 48d876d..2fe2795 100644 --- a/services/idp/src/main/webapp/WEB-INF/federation-signin-request.xml +++ b/services/idp/src/main/webapp/WEB-INF/federation-signin-request.xml @@ -185,6 +185,7 @@ </on-entry> <output name="whr" value="flowScope.whr" /> <output name="wctx" value="flowScope.wctx" /> + <output name="RelayState" value="flowScope.RelayState" /> </end-state> </flow> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bab0283d/services/idp/src/main/webapp/WEB-INF/federation-signin-response.xml ---------------------------------------------------------------------- diff --git a/services/idp/src/main/webapp/WEB-INF/federation-signin-response.xml b/services/idp/src/main/webapp/WEB-INF/federation-signin-response.xml index 3feef6e..e060b46 100644 --- a/services/idp/src/main/webapp/WEB-INF/federation-signin-response.xml +++ b/services/idp/src/main/webapp/WEB-INF/federation-signin-response.xml @@ -27,6 +27,8 @@ <input name="wctx" /> <input name="wauth" /> <input name="wresult" /> + <input name="RelayState" /> + <input name="SAMLResponse" /> <on-start> <!-- restore 'wreply','wtrealm','whr' for current 'wctx' --> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/bab0283d/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml ---------------------------------------------------------------------- diff --git a/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml b/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml index d4a3a21..690f5c5 100644 --- a/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml +++ b/services/idp/src/main/webapp/WEB-INF/federation-validate-request.xml @@ -32,17 +32,19 @@ <set name="flowScope.whr" value="requestParameters.whr" /> <set name="flowScope.wresult" value="requestParameters.wresult" /> <set name="flowScope.wreq" value="requestParameters.wreq" /> + <set name="flowScope.RelayState" value="requestParameters.RelayState" /> + <set name="flowScope.SAMLResponse" value="requestParameters.SAMLResponse" /> <evaluate expression="requestScope.getString('wauth','default')" result="flowScope.wauth" /> <set name="flowScope.idpConfig" value="config.getIDP(null)" /> </on-entry> - <if test="requestParameters.wa == null" then="viewBadRequest" /> + <!-- <if test="requestParameters.wa == null" then="viewBadRequest" /> <if test="requestParameters.wa != 'wsignin1.0' and requestParameters.wa != 'wsignout1.0' and requestParameters.wa != 'wsignoutcleanup1.0'" then="viewBadRequest" /> <if test="requestParameters.wa == 'wsignout1.0' or requestParameters.wa == 'wsignoutcleanup1.0'" - then="selectSignOutProcess" /> + then="selectSignOutProcess" /> --> <if test="requestParameters.wtrealm == null or requestParameters.wtrealm.length() == 0" then="viewBadRequest" else="selectSigninProcess" /> @@ -74,6 +76,7 @@ <output name="whr" /> <output name="wctx" /> + <output name="RelayState" /> <output name="idpToken" /> <transition on="requestRpToken" to="requestRpToken"> @@ -86,6 +89,7 @@ <transition on="redirectToTrustedIDP" to="processTrustedIdpProtocol"> <set name="flowScope.whr" value="currentEvent.attributes.whr" /> <set name="flowScope.wctx" value="currentEvent.attributes.wctx" /> + <set name="flowScope.RelayState" value="currentEvent.attributes.RelayState" /> </transition> <transition on="redirectToLocalIDP" to="redirectToLocalIDP"> <set name="flowScope.wctx" value="currentEvent.attributes.wctx" /> @@ -98,6 +102,8 @@ <input name="wctx" value="flowScope.wctx" /> <input name="wauth" value="flowScope.wauth" /> <input name="wresult" value="flowScope.wresult" /> + <input name="RelayState" value="flowScope.RelayState" /> + <input name="SAMLResponse" value="flowScope.SAMLResponse" /> <output name="wtrealm" /> <output name="wreply" />
