Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A6CF890AA for ; Wed, 16 May 2012 14:49:25 +0000 (UTC) Received: (qmail 33295 invoked by uid 500); 16 May 2012 14:49:25 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 33224 invoked by uid 500); 16 May 2012 14:49:25 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 33171 invoked by uid 99); 16 May 2012 14:49:25 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 16 May 2012 14:49:25 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 16 May 2012 14:49:20 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 5A4C82388860; Wed, 16 May 2012 14:48:59 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1339203 - in /cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso: ./ state/ Date: Wed, 16 May 2012 14:48:59 -0000 To: commits@cxf.apache.org From: coheigea@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120516144859.5A4C82388860@eris.apache.org> Author: coheigea Date: Wed May 16 14:48:58 2012 New Revision: 1339203 URL: http://svn.apache.org/viewvc?rev=1339203&view=rev Log: Add an expires field to the ResponseState extracted from an AuthenticationStatement SessionNotOnOrAfter value Added: cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SSOValidatorResponse.java - copied, changed from r1339160, cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SSOConstants.java Modified: cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractSSOSpHandler.java cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLSSOResponseValidator.java cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SSOConstants.java cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/state/ResponseState.java Modified: cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractSSOSpHandler.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractSSOSpHandler.java?rev=1339203&r1=1339202&r2=1339203&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractSSOSpHandler.java (original) +++ cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractSSOSpHandler.java Wed May 16 14:48:58 2012 @@ -63,8 +63,17 @@ public class AbstractSSOSpHandler { return contextCookie; } - protected boolean isStateExpired(long stateCreatedAt) { - return new Date().after(new Date(stateCreatedAt + getStateTimeToLive())); + protected boolean isStateExpired(long stateCreatedAt, long expiresAt) { + Date currentTime = new Date(); + if (currentTime.after(new Date(stateCreatedAt + getStateTimeToLive()))) { + return true; + } + + if (expiresAt > 0 && currentTime.after(new Date(expiresAt))) { + return true; + } + + return false; } public void setStateProvider(SPStateManager stateProvider) { Modified: cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java?rev=1339203&r1=1339202&r2=1339203&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java (original) +++ cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java Wed May 16 14:48:58 2012 @@ -110,7 +110,7 @@ public abstract class AbstractServicePro reportError("MISSING_RESPONSE_STATE"); return false; } - if (isStateExpired(responseState.getCreatedAt())) { + if (isStateExpired(responseState.getCreatedAt(), responseState.getExpiresAt())) { reportError("EXPIRED_RESPONSE_STATE"); getStateProvider().removeResponseState(contextKey); return false; Modified: cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java?rev=1339203&r1=1339202&r2=1339203&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java (original) +++ cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/RequestAssertionConsumerService.java Wed May 16 14:48:58 2012 @@ -26,6 +26,7 @@ import java.io.UnsupportedEncodingExcept import java.net.URI; import java.net.URL; import java.net.URLDecoder; +import java.util.Date; import java.util.Properties; import java.util.ResourceBundle; import java.util.UUID; @@ -117,13 +118,22 @@ public class RequestAssertionConsumerSer org.opensaml.saml2.core.Response samlResponse = readSAMLResponse(true, encodedSamlResponse); - validateSamlResponse(true, samlResponse, requestState); + // Validate the Response + validateSamlResponseProtocol(samlResponse); + SSOValidatorResponse validatorResponse = + validateSamlSSOResponse(true, samlResponse, requestState); // Set the security context String securityContextKey = UUID.randomUUID().toString(); long currentTime = System.currentTimeMillis(); - ResponseState responseState = new ResponseState(relayState, currentTime); + Date notOnOrAfter = validatorResponse.getSessionNotOnOrAfter(); + long expiresAt = 0; + if (notOnOrAfter != null) { + expiresAt = notOnOrAfter.getTime(); + } + ResponseState responseState = + new ResponseState(relayState, currentTime, expiresAt); getStateProvider().setResponseState(securityContextKey, responseState); String contextCookie = createCookie(SSOConstants.SECURITY_CONTEXT_TOKEN, @@ -145,13 +155,22 @@ public class RequestAssertionConsumerSer org.opensaml.saml2.core.Response samlResponse = readSAMLResponse(false, encodedSamlResponse); - validateSamlResponse(false, samlResponse, requestState); + // Validate the Response + validateSamlResponseProtocol(samlResponse); + SSOValidatorResponse validatorResponse = + validateSamlSSOResponse(false, samlResponse, requestState); // Set the security context String securityContextKey = UUID.randomUUID().toString(); long currentTime = System.currentTimeMillis(); - ResponseState responseState = new ResponseState(relayState, currentTime); + Date notOnOrAfter = validatorResponse.getSessionNotOnOrAfter(); + long expiresAt = 0; + if (notOnOrAfter != null) { + expiresAt = notOnOrAfter.getTime(); + } + ResponseState responseState = + new ResponseState(relayState, currentTime, expiresAt); getStateProvider().setResponseState(securityContextKey, responseState); String contextCookie = createCookie(SSOConstants.SECURITY_CONTEXT_TOKEN, @@ -177,7 +196,7 @@ public class RequestAssertionConsumerSer reportError("MISSING_REQUEST_STATE"); throw new WebApplicationException(400); } - if (isStateExpired(requestState.getCreatedAt())) { + if (isStateExpired(requestState.getCreatedAt(), 0)) { reportError("EXPIRED_REQUEST_STATE"); throw new WebApplicationException(400); } @@ -241,28 +260,43 @@ public class RequestAssertionConsumerSer return (org.opensaml.saml2.core.Response)responseObject; } - protected void validateSamlResponse( + /** + * Validate the received SAML Response as per the protocol + */ + protected void validateSamlResponseProtocol( + org.opensaml.saml2.core.Response samlResponse + ) { + try { + SAMLProtocolResponseValidator protocolValidator = new SAMLProtocolResponseValidator(); + protocolValidator.validateSamlResponse(samlResponse, getSignatureCrypto(), null); + } catch (WSSecurityException ex) { + reportError("INVALID_SAML_RESPONSE"); + throw new WebApplicationException(400); + } + } + + /** + * Validate the received SAML Response as per the Web SSO profile + */ + protected SSOValidatorResponse validateSamlSSOResponse( boolean postBinding, org.opensaml.saml2.core.Response samlResponse, RequestState requestState ) { try { - SAMLProtocolResponseValidator protocolValidator = new SAMLProtocolResponseValidator(); - protocolValidator.validateSamlResponse(samlResponse, getSignatureCrypto(), null); - SAMLSSOResponseValidator ssoResponseValidator = new SAMLSSOResponseValidator(); ssoResponseValidator.setAssertionConsumerURL((String)jaxrsContext.get(Message.REQUEST_URL)); - + HttpServletRequest httpRequest = (HttpServletRequest)jaxrsContext.get(AbstractHTTPDestination.HTTP_REQUEST); ssoResponseValidator.setClientAddress(httpRequest.getRemoteAddr()); - + ssoResponseValidator.setIssuerIDP(requestState.getIdpServiceAddress()); ssoResponseValidator.setRequestId(requestState.getSamlRequestId()); ssoResponseValidator.setSpIdentifier(requestState.getIssuerId()); - + // TODO post binding - ssoResponseValidator.validateSamlResponse(samlResponse, false); + return ssoResponseValidator.validateSamlResponse(samlResponse, false); } catch (WSSecurityException ex) { reportError("INVALID_SAML_RESPONSE"); throw new WebApplicationException(400); Modified: cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLSSOResponseValidator.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLSSOResponseValidator.java?rev=1339203&r1=1339202&r2=1339203&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLSSOResponseValidator.java (original) +++ cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SAMLSSOResponseValidator.java Wed May 16 14:48:58 2012 @@ -18,6 +18,7 @@ */ package org.apache.cxf.rs.security.saml.sso; +import java.util.Date; import java.util.List; import java.util.logging.Logger; @@ -25,15 +26,12 @@ import org.apache.cxf.common.logging.Log import org.apache.ws.security.WSSecurityException; import org.apache.ws.security.saml.ext.builder.SAML2Constants; import org.opensaml.saml2.core.AudienceRestriction; +import org.opensaml.saml2.core.AuthnStatement; /** * Validate a SAML 2.0 Protocol Response according to the Web SSO profile. The Response * should be validated by the SAMLProtocolResponseValidator first. * - * TODO If an used to establish a security context for the principal contains a -SessionNotOnOrAfter attribute, the security context SHOULD be discarded once this time is -reached - TODO The service provider MUST ensure that bearer assertions are not replayed, by maintaining the set of used ID values for the length of time for which the assertion would be considered valid based on the NotOnOrAfter attribute in the . @@ -52,9 +50,10 @@ public class SAMLSSOResponseValidator { * Validate a SAML 2 Protocol Response * @param samlResponse * @param postBinding + * @return a SSOValidatorResponse object * @throws WSSecurityException */ - public void validateSamlResponse( + public SSOValidatorResponse validateSamlResponse( org.opensaml.saml2.core.Response samlResponse, boolean postBinding ) throws WSSecurityException { @@ -78,6 +77,7 @@ public class SAMLSSOResponseValidator { // Validate Assertions boolean foundValidSubject = false; + Date sessionNotOnOrAfter = null; for (org.opensaml.saml2.core.Assertion assertion : samlResponse.getAssertions()) { // Check the Issuer if (assertion.getIssuer() == null) { @@ -99,6 +99,12 @@ public class SAMLSSOResponseValidator { if (validateAuthenticationSubject(subject)) { validateAudienceRestrictionCondition(assertion.getConditions()); foundValidSubject = true; + // Store Session NotOnOrAfter + for (AuthnStatement authnStatment : assertion.getAuthnStatements()) { + if (authnStatment.getSessionNotOnOrAfter() != null) { + sessionNotOnOrAfter = authnStatment.getSessionNotOnOrAfter().toDate(); + } + } } } @@ -109,6 +115,12 @@ public class SAMLSSOResponseValidator { + "the Subject Confirmation criteria"); throw new WSSecurityException(WSSecurityException.FAILURE, "invalidSAMLsecurity"); } + + SSOValidatorResponse validatorResponse = new SSOValidatorResponse(); + validatorResponse.setResponseId(samlResponse.getID()); + validatorResponse.setSessionNotOnOrAfter(sessionNotOnOrAfter); + + return validatorResponse; } /** Modified: cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SSOConstants.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SSOConstants.java?rev=1339203&r1=1339202&r2=1339203&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SSOConstants.java (original) +++ cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SSOConstants.java Wed May 16 14:48:58 2012 @@ -23,7 +23,7 @@ public final class SSOConstants { public static final String SAML_RESPONSE = "SAMLResponse"; public static final String RELAY_STATE = "RelayState"; public static final String SECURITY_CONTEXT_TOKEN = "org.apache.cxf.websso.context"; - public static final long DEFAULT_STATE_TIME = 2 * 60 * 1000; + public static final long DEFAULT_STATE_TIME = 2L * 60L * 1000L; private SSOConstants() { Copied: cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SSOValidatorResponse.java (from r1339160, cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SSOConstants.java) URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SSOValidatorResponse.java?p2=cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SSOValidatorResponse.java&p1=cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SSOConstants.java&r1=1339160&r2=1339203&rev=1339203&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SSOConstants.java (original) +++ cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SSOValidatorResponse.java Wed May 16 14:48:58 2012 @@ -18,14 +18,28 @@ */ package org.apache.cxf.rs.security.saml.sso; -public final class SSOConstants { - public static final String SAML_REQUEST = "SAMLRequest"; - public static final String SAML_RESPONSE = "SAMLResponse"; - public static final String RELAY_STATE = "RelayState"; - public static final String SECURITY_CONTEXT_TOKEN = "org.apache.cxf.websso.context"; - public static final long DEFAULT_STATE_TIME = 2 * 60 * 1000; +import java.util.Date; + +/** + * Some information that encapsulates a successful validation by the SAMLSSOResponseValidator + */ +public class SSOValidatorResponse { + private Date sessionNotOnOrAfter; + private String responseId; + + public Date getSessionNotOnOrAfter() { + return sessionNotOnOrAfter; + } + public void setSessionNotOnOrAfter(Date sessionNotOnOrAfter) { + this.sessionNotOnOrAfter = sessionNotOnOrAfter; + } + + public String getResponseId() { + return responseId; + } - private SSOConstants() { + public void setResponseId(String responseId) { + this.responseId = responseId; } } Modified: cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/state/ResponseState.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/state/ResponseState.java?rev=1339203&r1=1339202&r2=1339203&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/state/ResponseState.java (original) +++ cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/state/ResponseState.java Wed May 16 14:48:58 2012 @@ -22,15 +22,21 @@ public class ResponseState { private String relayState; private long createdAt; + private long expiresAt; - public ResponseState(String relayState, long createdAt) { + public ResponseState(String relayState, long createdAt, long expiresAt) { this.relayState = relayState; this.createdAt = createdAt; + this.expiresAt = expiresAt; } public long getCreatedAt() { return createdAt; } + + public long getExpiresAt() { + return expiresAt; + } public String getRelayState() { return relayState;