Added support for some more options for the SAML protocol
Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/5966160a Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/5966160a Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/5966160a Branch: refs/heads/master Commit: 5966160a29a38bdd6ba5ff670d3596a87b0ee1f0 Parents: 7d4abd3 Author: Colm O hEigeartaigh <[email protected]> Authored: Tue Sep 30 10:06:30 2014 +0100 Committer: Colm O hEigeartaigh <[email protected]> Committed: Tue Sep 30 10:06:30 2014 +0100 ---------------------------------------------------------------------- .../apache/cxf/fediz/core/config/Protocol.java | 2 +- .../cxf/fediz/core/config/SAMLProtocol.java | 16 +++ .../fediz/core/processor/SAMLProcessorImpl.java | 14 +- .../core/samlsso/SAMLSSOResponseValidator.java | 3 +- .../src/main/resources/schemas/FedizConfig.xsd | 4 + .../samlsso/SAMLResponseConformanceTest.java | 141 +++++++++++++++++++ .../fediz/integrationtests/AbstractTests.java | 2 +- 7 files changed, 176 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/5966160a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/Protocol.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/Protocol.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/Protocol.java index 6900891..8f82cdf 100644 --- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/Protocol.java +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/Protocol.java @@ -164,7 +164,7 @@ public abstract class Protocol { } protected Object loadCallbackType(CallbackType cbt, String name) { - if (cbt == null) { + if (cbt == null || cbt.getValue() == null) { return null; } if (cbt.getType() == null || cbt.getType().equals(ArgumentType.STRING)) { http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/5966160a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java index adeb1f6..ee59a70 100644 --- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/config/SAMLProtocol.java @@ -90,5 +90,21 @@ public class SAMLProtocol extends Protocol { this.authnRequestBuilder = authnRequestBuilder; } + public boolean isDisableDeflateEncoding() { + return getSAMLProtocol().isDisableDeflateEncoding(); + } + + public void setDisableDeflateEncoding(boolean disableDeflateEncoding) { + getSAMLProtocol().setDisableDeflateEncoding(disableDeflateEncoding); + } + + public boolean isDoNotEnforceKnownIssuer() { + return getSAMLProtocol().isDoNotEnforceKnownIssuer(); + } + + public void setDoNotEnforceKnownIssuer(boolean doNotEnforceKnownIssuer) { + getSAMLProtocol().setDoNotEnforceKnownIssuer(doNotEnforceKnownIssuer); + } + } http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/5966160a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java index 304b6cb..0bb1fd8 100644 --- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/processor/SAMLProcessorImpl.java @@ -19,6 +19,7 @@ package org.apache.cxf.fediz.core.processor; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; @@ -126,13 +127,17 @@ public class SAMLProcessorImpl extends AbstractFedizProcessor { InputStream tokenStream = null; try { byte[] deflatedToken = Base64.decode(request.getResponseToken()); - tokenStream = CompressionUtils.inflate(deflatedToken); + if (protocol.isDisableDeflateEncoding()) { + tokenStream = new ByteArrayInputStream(deflatedToken); + } else { + tokenStream = CompressionUtils.inflate(deflatedToken); + } } catch (DataFormatException ex) { throw new ProcessingException(TYPE.INVALID_REQUEST); } catch (Base64DecodingException e) { throw new ProcessingException(TYPE.INVALID_REQUEST); } - + Document doc = null; Element el = null; try { @@ -247,12 +252,15 @@ public class SAMLProcessorImpl extends AbstractFedizProcessor { String requestURL = request.getRequestURL().toString(); ssoResponseValidator.setAssertionConsumerURL(requestURL); ssoResponseValidator.setClientAddress(request.getRemoteAddr()); + + boolean doNotEnforceKnownIssuer = + ((SAMLProtocol)config.getProtocol()).isDoNotEnforceKnownIssuer(); + ssoResponseValidator.setEnforceKnownIssuer(!doNotEnforceKnownIssuer); ssoResponseValidator.setIssuerIDP(requestState.getIdpServiceAddress()); ssoResponseValidator.setRequestId(requestState.getRequestId()); ssoResponseValidator.setSpIdentifier(requestState.getIssuerId()); ssoResponseValidator.setEnforceAssertionsSigned(true); - ssoResponseValidator.setEnforceKnownIssuer(true); ssoResponseValidator.setReplayCache(config.getTokenReplayCache()); return ssoResponseValidator.validateSamlResponse(samlResponse, false); http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/5966160a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOResponseValidator.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOResponseValidator.java b/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOResponseValidator.java index 92cf01d..86bb005 100644 --- a/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOResponseValidator.java +++ b/plugins/core/src/main/java/org/apache/cxf/fediz/core/samlsso/SAMLSSOResponseValidator.java @@ -245,7 +245,8 @@ public class SAMLSSOResponseValidator { // InResponseTo must match the AuthnRequest request Id if (requestId != null && !requestId.equals(subjectConfData.getInResponseTo())) { - LOG.debug("The InResponseTo String does match the original request id " + requestId); + LOG.debug("The InResponseTo String " + subjectConfData.getInResponseTo() + + " does match the original request id " + requestId); throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity"); } http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/5966160a/plugins/core/src/main/resources/schemas/FedizConfig.xsd ---------------------------------------------------------------------- diff --git a/plugins/core/src/main/resources/schemas/FedizConfig.xsd b/plugins/core/src/main/resources/schemas/FedizConfig.xsd index 4d4c1f9..d26ad25 100644 --- a/plugins/core/src/main/resources/schemas/FedizConfig.xsd +++ b/plugins/core/src/main/resources/schemas/FedizConfig.xsd @@ -111,6 +111,8 @@ <xs:sequence> <xs:element ref="signRequest" /> <xs:element ref="authnRequestBuilder"/> + <xs:element ref="disableDeflateEncoding"/> + <xs:element ref="doNotEnforceKnownIssuer"/> </xs:sequence> <xs:attribute name="version" use="required" type="xs:string" /> </xs:extension> @@ -125,6 +127,8 @@ <xs:element name="signRequest" type="xs:boolean" /> <xs:element name="authnRequestBuilder" type="xs:string" /> + <xs:element name="disableDeflateEncoding" type="xs:boolean"/> + <xs:element name="doNotEnforceKnownIssuer" type="xs:boolean"/> <xs:complexType name="protocolType" abstract="true"> <xs:sequence> http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/5966160a/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLResponseConformanceTest.java ---------------------------------------------------------------------- diff --git a/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLResponseConformanceTest.java b/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLResponseConformanceTest.java index 08c3090..1c698c6 100644 --- a/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLResponseConformanceTest.java +++ b/plugins/core/src/test/java/org/apache/cxf/fediz/core/samlsso/SAMLResponseConformanceTest.java @@ -41,6 +41,7 @@ import org.apache.cxf.fediz.core.RequestState; import org.apache.cxf.fediz.core.SAML2CallbackHandler; import org.apache.cxf.fediz.core.config.FedizConfigurator; import org.apache.cxf.fediz.core.config.FedizContext; +import org.apache.cxf.fediz.core.config.SAMLProtocol; import org.apache.cxf.fediz.core.exception.ProcessingException; import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE; import org.apache.cxf.fediz.core.processor.FedizProcessor; @@ -974,6 +975,146 @@ public class SAMLResponseConformanceTest { } } + @org.junit.Test + public void testIssuerEnforcementFailure() throws Exception { + // Mock up a Request + FedizContext config = getFederationConfigurator().getFedizContext("ROOT"); + + String requestId = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8"); + + String relayState = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8"); + RequestState requestState = new RequestState(TEST_REQUEST_URL, + TEST_IDP_ISSUER, + requestId, + TEST_REQUEST_URL, + (String)config.getProtocol().getIssuer(), + null, + relayState, + System.currentTimeMillis()); + + // Create SAML Response + SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler(); + callbackHandler.setAlsoAddAuthnStatement(true); + callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR); + callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER); + callbackHandler.setIssuer(TEST_IDP_ISSUER + "/other-issuer"); + callbackHandler.setSubjectName(TEST_USER); + + ConditionsBean cp = new ConditionsBean(); + AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean(); + audienceRestriction.getAudienceURIs().add(TEST_REQUEST_URL); + cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction)); + callbackHandler.setConditions(cp); + + // Subject Confirmation Data + SubjectConfirmationDataBean subjectConfirmationData = new SubjectConfirmationDataBean(); + subjectConfirmationData.setAddress(TEST_CLIENT_ADDRESS); + subjectConfirmationData.setInResponseTo(requestId); + subjectConfirmationData.setNotAfter(new DateTime().plusMinutes(5)); + subjectConfirmationData.setRecipient(TEST_REQUEST_URL); + callbackHandler.setSubjectConfirmationData(subjectConfirmationData); + + SAMLCallback samlCallback = new SAMLCallback(); + SAMLUtil.doSAMLCallback(callbackHandler, samlCallback); + SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback); + + Issuer issuer = + SAML2PResponseComponentBuilder.createIssuer(assertion.getIssuerString()); + + Element response = createSamlResponse(assertion, "mystskey", true, requestId, issuer); + String responseStr = encodeResponse(response); + + HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class); + EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(TEST_REQUEST_URL)); + EasyMock.expect(req.getRemoteAddr()).andReturn(TEST_CLIENT_ADDRESS); + EasyMock.replay(req); + + FedizRequest wfReq = new FedizRequest(); + wfReq.setResponseToken(responseStr); + wfReq.setState(relayState); + wfReq.setRequest(req); + wfReq.setRequestState(requestState); + + // Failure expected on an unknown issuer value + FedizProcessor wfProc = new SAMLProcessorImpl(); + try { + wfProc.processRequest(wfReq, config); + fail("Failure expected"); + } catch (ProcessingException ex) { + if (!TYPE.INVALID_REQUEST.equals(ex.getType())) { + fail("Expected ProcessingException with INVALID_REQUEST type"); + } + } + } + + @org.junit.Test + public void testIssuerEnforcementDisable() throws Exception { + // Mock up a Request + FedizContext config = getFederationConfigurator().getFedizContext("ROOT"); + + String requestId = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8"); + + String relayState = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8"); + RequestState requestState = new RequestState(TEST_REQUEST_URL, + TEST_IDP_ISSUER, + requestId, + TEST_REQUEST_URL, + (String)config.getProtocol().getIssuer(), + null, + relayState, + System.currentTimeMillis()); + + // Create SAML Response + SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler(); + callbackHandler.setAlsoAddAuthnStatement(true); + callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR); + callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER); + callbackHandler.setIssuer(TEST_IDP_ISSUER + "/other-issuer"); + callbackHandler.setSubjectName(TEST_USER); + + ConditionsBean cp = new ConditionsBean(); + AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean(); + audienceRestriction.getAudienceURIs().add(TEST_REQUEST_URL); + cp.setAudienceRestrictions(Collections.singletonList(audienceRestriction)); + callbackHandler.setConditions(cp); + + // Subject Confirmation Data + SubjectConfirmationDataBean subjectConfirmationData = new SubjectConfirmationDataBean(); + subjectConfirmationData.setAddress(TEST_CLIENT_ADDRESS); + subjectConfirmationData.setInResponseTo(requestId); + subjectConfirmationData.setNotAfter(new DateTime().plusMinutes(5)); + subjectConfirmationData.setRecipient(TEST_REQUEST_URL); + callbackHandler.setSubjectConfirmationData(subjectConfirmationData); + + SAMLCallback samlCallback = new SAMLCallback(); + SAMLUtil.doSAMLCallback(callbackHandler, samlCallback); + SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback); + + Issuer issuer = + SAML2PResponseComponentBuilder.createIssuer(assertion.getIssuerString()); + + Element response = createSamlResponse(assertion, "mystskey", true, requestId, issuer); + String responseStr = encodeResponse(response); + + HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class); + EasyMock.expect(req.getRequestURL()).andReturn(new StringBuffer(TEST_REQUEST_URL)); + EasyMock.expect(req.getRemoteAddr()).andReturn(TEST_CLIENT_ADDRESS); + EasyMock.replay(req); + + FedizRequest wfReq = new FedizRequest(); + wfReq.setResponseToken(responseStr); + wfReq.setState(relayState); + wfReq.setRequest(req); + wfReq.setRequestState(requestState); + + // Disable the issuer enforcement check + FedizProcessor wfProc = new SAMLProcessorImpl(); + ((SAMLProtocol)config.getProtocol()).setDoNotEnforceKnownIssuer(true); + Assert.assertTrue(((SAMLProtocol)config.getProtocol()).isDoNotEnforceKnownIssuer()); + FedizResponse wfRes = wfProc.processRequest(wfReq, config); + Assert.assertEquals("Principal name wrong", TEST_USER, wfRes.getUsername()); + + } private Element createSamlResponse(SamlAssertionWrapper assertion, String alias, boolean sign, String requestID, Issuer issuer) http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/5966160a/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/AbstractTests.java ---------------------------------------------------------------------- diff --git a/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/AbstractTests.java b/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/AbstractTests.java index 0892d9e..af799f5 100644 --- a/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/AbstractTests.java +++ b/systests/tests/src/test/java/org/apache/cxf/fediz/integrationtests/AbstractTests.java @@ -313,7 +313,7 @@ public abstract class AbstractTests { final XmlPage rpPage = webClient.getPage(url); final String xmlContent = rpPage.asXml(); - Assert.assertTrue(xmlContent.startsWith("<EntityDescriptor")); + Assert.assertTrue(xmlContent.startsWith("<md:EntityDescriptor")); // Now validate the Signature Document doc = rpPage.getXmlDocument();
