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 34BE411728 for ; Wed, 24 Sep 2014 14:37:23 +0000 (UTC) Received: (qmail 1409 invoked by uid 500); 24 Sep 2014 14:37:23 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 1349 invoked by uid 500); 24 Sep 2014 14:37:23 -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 1339 invoked by uid 99); 24 Sep 2014 14:37:23 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 24 Sep 2014 14:37:23 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id B95CE8AF54B; Wed, 24 Sep 2014 14:37:22 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: coheigea@apache.org To: commits@cxf.apache.org Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: git commit: [CXF-5975] - Add support for renewing tokens "about to expire" Date: Wed, 24 Sep 2014 14:37:22 +0000 (UTC) Repository: cxf Updated Branches: refs/heads/3.0.x-fixes 8e9487499 -> 073d2dd84 [CXF-5975] - Add support for renewing tokens "about to expire" Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/073d2dd8 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/073d2dd8 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/073d2dd8 Branch: refs/heads/3.0.x-fixes Commit: 073d2dd843e2c3b56ae1837b588cac52b3d257b9 Parents: 8e94874 Author: Colm O hEigeartaigh Authored: Wed Sep 24 15:36:16 2014 +0100 Committer: Colm O hEigeartaigh Committed: Wed Sep 24 15:37:15 2014 +0100 ---------------------------------------------------------------------- .../cxf/ws/security/SecurityConstants.java | 14 ++++++- .../IssuedTokenInterceptorProvider.java | 9 +++- .../ws/security/tokenstore/SecurityToken.java | 14 +++++++ .../tokenstore/MemoryTokenStoreTest.java | 15 +++++++ .../cxf/systest/sts/caching/CachingTest.java | 43 ++++++++++++++++++++ 5 files changed, 93 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/073d2dd8/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java index b8833d2..6ecaee2 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java @@ -570,6 +570,18 @@ public final class SecurityConstants { * client credentials. */ public static final String DELEGATED_CREDENTIAL = "ws-security.delegated.credential"; + + /** + * This is the value in seconds within which a token is considered to be expired by the + * client. When a cached token (from a STS) is retrieved by the client, it is considered + * to be expired if it will expire in a time less than the value specified by this tag. + * This prevents token expiry when the message is en route / being processed by the + * service. When the token is found to be expired then it will be renewed via the STS. + * + * The default value is 10 (seconds). Specify 0 to avoid this check. + */ + public static final String STS_TOKEN_IMMINENT_EXPIRY_VALUE = + "ws-security.sts.token.imminent-expiry-value"; // // Internal tags @@ -602,7 +614,7 @@ public final class SecurityConstants { SAML_ONE_TIME_USE_CACHE_INSTANCE, ENABLE_STREAMING_SECURITY, RETURN_SECURITY_ERROR, CACHE_IDENTIFIER, CACHE_ISSUED_TOKEN_IN_ENDPOINT, PREFER_WSMEX_OVER_STS_CLIENT_CONFIG, DELEGATED_CREDENTIAL, KERBEROS_USE_CREDENTIAL_DELEGATION, - KERBEROS_IS_USERNAME_IN_SERVICENAME_FORM + KERBEROS_IS_USERNAME_IN_SERVICENAME_FORM, STS_TOKEN_IMMINENT_EXPIRY_VALUE })); ALL_PROPERTIES = Collections.unmodifiableSet(s); } http://git-wip-us.apache.org/repos/asf/cxf/blob/073d2dd8/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java index 7f9fd85..5b63621 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/IssuedTokenInterceptorProvider.java @@ -400,8 +400,15 @@ public class IssuedTokenInterceptorProvider extends AbstractPolicyInterceptorPro IssuedToken itok, SecurityToken tok ) { + String imminentExpiryValue = + (String)message.getContextualProperty(SecurityConstants.STS_TOKEN_IMMINENT_EXPIRY_VALUE); + long imminentExpiry = 10L; + if (imminentExpiryValue != null) { + imminentExpiry = Long.parseLong(imminentExpiryValue); + } + // If the token has not expired then we don't need to renew it - if (!tok.isExpired()) { + if (!(tok.isExpired() || tok.isAboutToExpire(imminentExpiry))) { return tok; } http://git-wip-us.apache.org/repos/asf/cxf/blob/073d2dd8/rt/ws/security/src/main/java/org/apache/cxf/ws/security/tokenstore/SecurityToken.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/tokenstore/SecurityToken.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/tokenstore/SecurityToken.java index 23694f3..7a74b35 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/tokenstore/SecurityToken.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/tokenstore/SecurityToken.java @@ -384,6 +384,20 @@ public class SecurityToken implements Serializable { } return false; } + + /** + * Return whether this SecurityToken is about to expire or not + */ + public boolean isAboutToExpire(long secondsToExpiry) { + if (expires != null && secondsToExpiry > 0) { + Date rightNow = new Date(); + rightNow.setTime(rightNow.getTime() + (secondsToExpiry * 1000L)); + if (expires.before(rightNow)) { + return true; + } + } + return false; + } /** * @param expires The expires to set. http://git-wip-us.apache.org/repos/asf/cxf/blob/073d2dd8/rt/ws/security/src/test/java/org/apache/cxf/ws/security/tokenstore/MemoryTokenStoreTest.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/test/java/org/apache/cxf/ws/security/tokenstore/MemoryTokenStoreTest.java b/rt/ws/security/src/test/java/org/apache/cxf/ws/security/tokenstore/MemoryTokenStoreTest.java index 40260d1..9a12f63 100644 --- a/rt/ws/security/src/test/java/org/apache/cxf/ws/security/tokenstore/MemoryTokenStoreTest.java +++ b/rt/ws/security/src/test/java/org/apache/cxf/ws/security/tokenstore/MemoryTokenStoreTest.java @@ -18,6 +18,8 @@ */ package org.apache.cxf.ws.security.tokenstore; +import java.util.Date; + import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageImpl; import org.apache.cxf.ws.security.SecurityConstants; @@ -68,4 +70,17 @@ public class MemoryTokenStoreTest extends org.junit.Assert { store.remove(token2.getId()); assertTrue(store.getTokenIdentifiers().size() == 0); } + + @org.junit.Test + public void testTokenExpiry() { + SecurityToken token = new SecurityToken(); + + Date expires = new Date(); + expires.setTime(expires.getTime() + (5L * 60L * 1000L)); + token.setExpires(expires); + + assertFalse(token.isExpired()); + assertFalse(token.isAboutToExpire(100L)); + assertTrue(token.isAboutToExpire((5L * 60L * 1000L) + 1L)); + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/073d2dd8/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/caching/CachingTest.java ---------------------------------------------------------------------- diff --git a/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/caching/CachingTest.java b/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/caching/CachingTest.java index 151fae5..93e77ee 100644 --- a/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/caching/CachingTest.java +++ b/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/caching/CachingTest.java @@ -19,6 +19,7 @@ package org.apache.cxf.systest.sts.caching; import java.net.URL; +import java.util.Date; import javax.xml.namespace.QName; import javax.xml.ws.BindingProvider; @@ -36,6 +37,8 @@ import org.apache.cxf.systest.sts.common.SecurityTestUtil; import org.apache.cxf.systest.sts.deployment.STSServer; import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase; import org.apache.cxf.ws.security.SecurityConstants; +import org.apache.cxf.ws.security.tokenstore.SecurityToken; +import org.apache.cxf.ws.security.tokenstore.TokenStore; import org.apache.cxf.ws.security.trust.STSClient; import org.example.contract.doubleit.DoubleItPortType; import org.junit.BeforeClass; @@ -163,6 +166,46 @@ public class CachingTest extends AbstractBusClientServerTestBase { bus.shutdown(true); } + @org.junit.Test + public void testImminentExpiry() throws Exception { + + SpringBusFactory bf = new SpringBusFactory(); + URL busFile = CachingTest.class.getResource("cxf-client.xml"); + + Bus bus = bf.createBus(busFile.toString()); + SpringBusFactory.setDefaultBus(bus); + SpringBusFactory.setThreadDefaultBus(bus); + + URL wsdl = CachingTest.class.getResource("DoubleIt.wsdl"); + Service service = Service.create(wsdl, SERVICE_QNAME); + QName portQName = new QName(NAMESPACE, "DoubleItTransportSAML1Port"); + DoubleItPortType port = + service.getPort(portQName, DoubleItPortType.class); + ((BindingProvider)port).getRequestContext().put("thread.local.request.context", "true"); + updateAddressPort(port, PORT); + + // Make a successful invocation + doubleIt(port, 25); + + Client client = ClientProxy.getClient(port); + Endpoint ep = client.getEndpoint(); + String id = (String)ep.get(SecurityConstants.TOKEN_ID); + TokenStore store = (TokenStore)ep.getEndpointInfo().getProperty(TokenStore.class.getName()); + SecurityToken tok = store.getToken(id); + assertNotNull(tok); + + // Make the token "about to expire" + Date expiredDate = new Date(); + expiredDate.setTime(expiredDate.getTime() + 5000L); + tok.setExpires(expiredDate); + assertTrue(tok.isAboutToExpire(10L)); + + doubleIt(port, 25); + + ((java.io.Closeable)port).close(); + bus.shutdown(true); + } + private void clearSTSClient(BindingProvider p, Bus bus) throws BusException, EndpointException { p.getRequestContext().put(SecurityConstants.STS_CLIENT, new STSClient(bus)); }