Repository: cxf Updated Branches: refs/heads/master dd421381b -> 048b46de4
CXF-7315 - Abstract the STS client token caching behaviour to allow the user to plug in a custom implementation Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/048b46de Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/048b46de Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/048b46de Branch: refs/heads/master Commit: 048b46de4b2973bbccbaacf5effe34b06faf3e68 Parents: dd42138 Author: Colm O hEigeartaigh <cohei...@apache.org> Authored: Tue Apr 4 15:59:33 2017 +0100 Committer: Colm O hEigeartaigh <cohei...@apache.org> Committed: Tue Apr 4 15:59:33 2017 +0100 ---------------------------------------------------------------------- .../cxf/rt/security/SecurityConstants.java | 9 +- .../IssuedTokenInterceptorProvider.java | 13 +- .../interceptors/STSTokenOutInterceptor.java | 13 +- .../security/trust/DefaultSTSTokenCacher.java | 180 ++++++++++++++ .../cxf/ws/security/trust/STSTokenCacher.java | 59 +++++ .../ws/security/trust/STSTokenRetriever.java | 236 +++---------------- 6 files changed, 302 insertions(+), 208 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/048b46de/rt/security/src/main/java/org/apache/cxf/rt/security/SecurityConstants.java ---------------------------------------------------------------------- diff --git a/rt/security/src/main/java/org/apache/cxf/rt/security/SecurityConstants.java b/rt/security/src/main/java/org/apache/cxf/rt/security/SecurityConstants.java index 8405371..a3daaa8 100644 --- a/rt/security/src/main/java/org/apache/cxf/rt/security/SecurityConstants.java +++ b/rt/security/src/main/java/org/apache/cxf/rt/security/SecurityConstants.java @@ -344,6 +344,13 @@ public class SecurityConstants { public static final String STS_TOKEN_IMMINENT_EXPIRY_VALUE = "security.sts.token.imminent-expiry-value"; + /** + * An implementation of the STSTokenCacher interface, if you want to plug in custom caching behaviour for + * STS clients. The default value is the DefaultSTSTokenCacher. + */ + public static final String STS_TOKEN_CACHER_IMPL = + "security.sts.token.cacher.impl"; + public static final Set<String> COMMON_PROPERTIES; static { @@ -359,7 +366,7 @@ public class SecurityConstants { DISABLE_STS_CLIENT_WSMEX_CALL_USING_EPR_ADDRESS, STS_TOKEN_CRYPTO, STS_TOKEN_PROPERTIES, STS_TOKEN_USERNAME, STS_TOKEN_ACT_AS, STS_TOKEN_ON_BEHALF_OF, STS_CLIENT, STS_APPLIES_TO, CACHE_ISSUED_TOKEN_IN_ENDPOINT, PREFER_WSMEX_OVER_STS_CLIENT_CONFIG, - STS_TOKEN_IMMINENT_EXPIRY_VALUE + STS_TOKEN_IMMINENT_EXPIRY_VALUE, STS_TOKEN_CACHER_IMPL })); COMMON_PROPERTIES = Collections.unmodifiableSet(s); } http://git-wip-us.apache.org/repos/asf/cxf/blob/048b46de/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 a1c794e..b40e720 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 @@ -32,12 +32,15 @@ import org.apache.cxf.interceptor.Fault; import org.apache.cxf.message.Message; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; +import org.apache.cxf.rt.security.utils.SecurityUtils; import org.apache.cxf.ws.policy.AbstractPolicyInterceptorProvider; import org.apache.cxf.ws.policy.AssertionInfo; import org.apache.cxf.ws.policy.AssertionInfoMap; import org.apache.cxf.ws.security.SecurityConstants; import org.apache.cxf.ws.security.policy.PolicyUtils; import org.apache.cxf.ws.security.tokenstore.SecurityToken; +import org.apache.cxf.ws.security.trust.DefaultSTSTokenCacher; +import org.apache.cxf.ws.security.trust.STSTokenCacher; import org.apache.cxf.ws.security.trust.STSTokenRetriever; import org.apache.cxf.ws.security.trust.STSTokenRetriever.TokenRequestParams; import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JInInterceptor; @@ -130,7 +133,15 @@ public class IssuedTokenInterceptorProvider extends AbstractPolicyInterceptorPro params.setTrust13(NegotiationUtils.getTrust13(aim)); params.setTokenTemplate(itok.getRequestSecurityTokenTemplate()); - SecurityToken tok = STSTokenRetriever.getToken(message, params); + // Get a custom STSTokenCacher implementation if specified + STSTokenCacher tokenCacher = + (STSTokenCacher)SecurityUtils.getSecurityPropertyValue( + SecurityConstants.STS_TOKEN_CACHER_IMPL, message + ); + if (tokenCacher == null) { + tokenCacher = new DefaultSTSTokenCacher(); + } + SecurityToken tok = STSTokenRetriever.getToken(message, params, tokenCacher); if (tok != null) { assertIssuedToken(itok, aim); http://git-wip-us.apache.org/repos/asf/cxf/blob/048b46de/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/STSTokenOutInterceptor.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/STSTokenOutInterceptor.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/STSTokenOutInterceptor.java index ebeae57..3732419 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/STSTokenOutInterceptor.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/STSTokenOutInterceptor.java @@ -31,8 +31,10 @@ import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.apache.cxf.ws.security.SecurityConstants; import org.apache.cxf.ws.security.tokenstore.SecurityToken; +import org.apache.cxf.ws.security.trust.DefaultSTSTokenCacher; import org.apache.cxf.ws.security.trust.STSAuthParams; import org.apache.cxf.ws.security.trust.STSClient; +import org.apache.cxf.ws.security.trust.STSTokenCacher; import org.apache.cxf.ws.security.trust.STSTokenRetriever; import org.apache.cxf.ws.security.trust.STSTokenRetriever.TokenRequestParams; import org.apache.cxf.ws.security.trust.STSUtils; @@ -47,6 +49,7 @@ public class STSTokenOutInterceptor extends AbstractPhaseInterceptor<Message> { private STSClient stsClient; private TokenRequestParams tokenParams; + private STSTokenCacher tokenCacher = new DefaultSTSTokenCacher(); public STSTokenOutInterceptor(STSAuthParams authParams, String stsWsdlLocation, Bus bus) { this(Phase.PREPARE_SEND, authParams, stsWsdlLocation, bus); @@ -77,7 +80,7 @@ public class STSTokenOutInterceptor extends AbstractPhaseInterceptor<Message> { if (stsClient != null) { message.put(SecurityConstants.STS_CLIENT, stsClient); } - SecurityToken tok = STSTokenRetriever.getToken(message, tokenParams); + SecurityToken tok = STSTokenRetriever.getToken(message, tokenParams, tokenCacher); if (tok == null) { LOG.warning("Security token was not retrieved from STS"); } @@ -93,6 +96,14 @@ public class STSTokenOutInterceptor extends AbstractPhaseInterceptor<Message> { return stsClient; } + public STSTokenCacher getTokenCacher() { + return tokenCacher; + } + + public void setTokenCacher(STSTokenCacher tokenCacher) { + this.tokenCacher = tokenCacher; + } + /** * A enumeration to specify authentication mode in communication with STS. * @deprecated use {@link org.apache.cxf.ws.security.trust.STSAuthParams.AuthMode} http://git-wip-us.apache.org/repos/asf/cxf/blob/048b46de/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/DefaultSTSTokenCacher.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/DefaultSTSTokenCacher.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/DefaultSTSTokenCacher.java new file mode 100644 index 0000000..6fc26f0 --- /dev/null +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/DefaultSTSTokenCacher.java @@ -0,0 +1,180 @@ +/** + * 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.ws.security.trust; + +import java.util.HashMap; +import java.util.Map; + +import org.w3c.dom.Element; + +import org.apache.cxf.interceptor.Fault; +import org.apache.cxf.message.Message; +import org.apache.cxf.rt.security.utils.SecurityUtils; +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.tokenstore.TokenStoreUtils; +import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.common.saml.SamlAssertionWrapper; +import org.apache.wss4j.dom.WSConstants; + +public class DefaultSTSTokenCacher implements STSTokenCacher { + + public SecurityToken retrieveToken(Message message) { + boolean cacheIssuedToken = + SecurityUtils.getSecurityPropertyBoolean(SecurityConstants.CACHE_ISSUED_TOKEN_IN_ENDPOINT, + message, + true); + SecurityToken tok = null; + if (cacheIssuedToken) { + tok = (SecurityToken)message.getContextualProperty(SecurityConstants.TOKEN); + if (tok == null) { + String tokId = (String)message.getContextualProperty(SecurityConstants.TOKEN_ID); + if (tokId != null) { + tok = TokenStoreUtils.getTokenStore(message).getToken(tokId); + } + } + } else { + tok = (SecurityToken)message.get(SecurityConstants.TOKEN); + if (tok == null) { + String tokId = (String)message.get(SecurityConstants.TOKEN_ID); + if (tokId != null) { + tok = TokenStoreUtils.getTokenStore(message).getToken(tokId); + } + } + } + return tok; + } + + public SecurityToken retrieveToken(Message message, Element delegationToken, String cacheKey) { + if (delegationToken == null) { + return null; + } + TokenStore tokenStore = TokenStoreUtils.getTokenStore(message); + + // See if the token corresponding to the delegation Token is stored in the cache + // and if it points to an issued token + String id = getIdFromToken(delegationToken); + SecurityToken cachedToken = tokenStore.getToken(id); + if (cachedToken != null) { + Map<String, Object> properties = cachedToken.getProperties(); + if (properties != null && properties.containsKey(cacheKey)) { + String associatedToken = (String)properties.get(cacheKey); + SecurityToken issuedToken = tokenStore.getToken(associatedToken); + if (issuedToken != null) { + return issuedToken; + } + } + } + + return null; + } + + public void storeToken(Message message, SecurityToken securityToken) { + boolean cacheIssuedToken = + SecurityUtils.getSecurityPropertyBoolean(SecurityConstants.CACHE_ISSUED_TOKEN_IN_ENDPOINT, + message, + true) + && !isOneTimeUse(securityToken); + if (cacheIssuedToken) { + message.getExchange().getEndpoint().put(SecurityConstants.TOKEN, securityToken); + message.getExchange().put(SecurityConstants.TOKEN, securityToken); + message.put(SecurityConstants.TOKEN_ELEMENT, securityToken.getToken()); + message.getExchange().put(SecurityConstants.TOKEN_ID, securityToken.getId()); + message.getExchange().getEndpoint().put(SecurityConstants.TOKEN_ID, + securityToken.getId()); + } else { + message.put(SecurityConstants.TOKEN, securityToken); + message.put(SecurityConstants.TOKEN_ID, securityToken.getId()); + message.put(SecurityConstants.TOKEN_ELEMENT, securityToken.getToken()); + } + // ? + TokenStoreUtils.getTokenStore(message).add(securityToken); + } + + public void storeToken(Message message, Element delegationToken, String secTokenId, String cacheKey) { + if (secTokenId == null || delegationToken == null) { + return; + } + + TokenStore tokenStore = TokenStoreUtils.getTokenStore(message); + + String id = getIdFromToken(delegationToken); + SecurityToken cachedToken = tokenStore.getToken(id); + if (cachedToken == null) { + cachedToken = new SecurityToken(id); + cachedToken.setToken(delegationToken); + } + Map<String, Object> properties = cachedToken.getProperties(); + if (properties == null) { + properties = new HashMap<>(); + cachedToken.setProperties(properties); + } + properties.put(cacheKey, secTokenId); + tokenStore.add(cachedToken); + } + + public void removeToken(Message message, SecurityToken securityToken) { + // Remove token from cache + message.getExchange().getEndpoint().remove(SecurityConstants.TOKEN); + message.getExchange().getEndpoint().remove(SecurityConstants.TOKEN_ID); + message.getExchange().remove(SecurityConstants.TOKEN_ID); + message.getExchange().remove(SecurityConstants.TOKEN); + if (securityToken != null) { + TokenStoreUtils.getTokenStore(message).remove(securityToken.getId()); + } + } + + // Check to see if the received token is a SAML2 Token with "OneTimeUse" set. If so, + // it should not be cached on the endpoint, but only on the message. + private static boolean isOneTimeUse(SecurityToken issuedToken) { + Element token = issuedToken.getToken(); + if (token != null && "Assertion".equals(token.getLocalName()) + && WSConstants.SAML2_NS.equals(token.getNamespaceURI())) { + try { + SamlAssertionWrapper assertion = new SamlAssertionWrapper(token); + + if (assertion.getSaml2().getConditions() != null + && assertion.getSaml2().getConditions().getOneTimeUse() != null) { + return true; + } + } catch (WSSecurityException ex) { + throw new Fault(ex); + } + } + + return false; + } + + private static String getIdFromToken(Element token) { + if (token != null) { + // Try to find the "Id" on the token. + if (token.hasAttributeNS(WSConstants.WSU_NS, "Id")) { + return token.getAttributeNS(WSConstants.WSU_NS, "Id"); + } else if (token.hasAttributeNS(null, "ID")) { + return token.getAttributeNS(null, "ID"); + } else if (token.hasAttributeNS(null, "AssertionID")) { + return token.getAttributeNS(null, "AssertionID"); + } + } + return ""; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/048b46de/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenCacher.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenCacher.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenCacher.java new file mode 100644 index 0000000..9a5d128 --- /dev/null +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenCacher.java @@ -0,0 +1,59 @@ +/** + * 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.ws.security.trust; + +import org.w3c.dom.Element; + +import org.apache.cxf.message.Message; +import org.apache.cxf.ws.security.tokenstore.SecurityToken; + +/** + * This interface allows you to plug in some custom logic when storing/retrieving STS tokens in/from the cache + */ +public interface STSTokenCacher { + + /** + * Retrieve a cached STS token + */ + SecurityToken retrieveToken(Message message); + + /** + * Retrieve a cached STS token for a given delegation token Element + */ + SecurityToken retrieveToken(Message message, Element delegationToken, String cacheKey); + + /** + * Store a token in the cache + */ + void storeToken(Message message, SecurityToken securityToken); + + /** + * Store a given delegation token in the cache (or update it if it's already there), with a reference to the + * security token obtained from the STS. + */ + void storeToken(Message message, Element delegationToken, String secTokenId, String cacheKey); + + /** + * Remove a cached STS token + */ + void removeToken(Message message, SecurityToken securityToken); + +} + http://git-wip-us.apache.org/repos/asf/cxf/blob/048b46de/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenRetriever.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenRetriever.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenRetriever.java index f11788b..9e9da18 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenRetriever.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenRetriever.java @@ -19,7 +19,6 @@ package org.apache.cxf.ws.security.trust; -import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; @@ -33,11 +32,6 @@ import org.apache.cxf.rt.security.utils.SecurityUtils; import org.apache.cxf.ws.addressing.AddressingProperties; 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.tokenstore.TokenStoreUtils; -import org.apache.wss4j.common.ext.WSSecurityException; -import org.apache.wss4j.common.saml.SamlAssertionWrapper; -import org.apache.wss4j.dom.WSConstants; import org.apache.wss4j.policy.model.Trust10; import org.apache.wss4j.policy.model.Trust13; @@ -53,63 +47,23 @@ public final class STSTokenRetriever { } public static SecurityToken getToken(Message message, TokenRequestParams params) { - SecurityToken tok = retrieveCachedToken(message); - if (tok == null) { - tok = issueToken(message, params); - } else { - tok = renewToken(message, tok, params); - } + return getToken(message, params, new DefaultSTSTokenCacher()); + } - boolean cacheIssuedToken = - SecurityUtils.getSecurityPropertyBoolean(SecurityConstants.CACHE_ISSUED_TOKEN_IN_ENDPOINT, - message, - true) - && !isOneTimeUse(tok); - if (cacheIssuedToken) { - message.getExchange().getEndpoint().put(SecurityConstants.TOKEN, tok); - message.getExchange().put(SecurityConstants.TOKEN, tok); - message.put(SecurityConstants.TOKEN_ELEMENT, tok.getToken()); - message.getExchange().put(SecurityConstants.TOKEN_ID, tok.getId()); - message.getExchange().getEndpoint().put(SecurityConstants.TOKEN_ID, - tok.getId()); + public static SecurityToken getToken(Message message, TokenRequestParams params, STSTokenCacher tokenCacher) { + SecurityToken tok = tokenCacher.retrieveToken(message); + if (tok == null) { + tok = issueToken(message, params, tokenCacher); } else { - message.put(SecurityConstants.TOKEN, tok); - message.put(SecurityConstants.TOKEN_ID, tok.getId()); - message.put(SecurityConstants.TOKEN_ELEMENT, tok.getToken()); + tok = renewToken(message, tok, params, tokenCacher); } - // ? - TokenStoreUtils.getTokenStore(message).add(tok); - return tok; - } + tokenCacher.storeToken(message, tok); - private static SecurityToken retrieveCachedToken(Message message) { - boolean cacheIssuedToken = - SecurityUtils.getSecurityPropertyBoolean(SecurityConstants.CACHE_ISSUED_TOKEN_IN_ENDPOINT, - message, - true); - SecurityToken tok = null; - if (cacheIssuedToken) { - tok = (SecurityToken)message.getContextualProperty(SecurityConstants.TOKEN); - if (tok == null) { - String tokId = (String)message.getContextualProperty(SecurityConstants.TOKEN_ID); - if (tokId != null) { - tok = TokenStoreUtils.getTokenStore(message).getToken(tokId); - } - } - } else { - tok = (SecurityToken)message.get(SecurityConstants.TOKEN); - if (tok == null) { - String tokId = (String)message.get(SecurityConstants.TOKEN_ID); - if (tokId != null) { - tok = TokenStoreUtils.getTokenStore(message).getToken(tokId); - } - } - } return tok; } - private static SecurityToken issueToken(Message message, TokenRequestParams params) { + private static SecurityToken issueToken(Message message, TokenRequestParams params, STSTokenCacher tokenCacher) { AddressingProperties maps = (AddressingProperties)message .get("javax.xml.ws.addressing.context.outbound"); @@ -152,20 +106,27 @@ public final class STSTokenRetriever { Element onBehalfOfToken = client.getOnBehalfOfToken(); Element actAsToken = client.getActAsToken(); - SecurityToken secToken = - handleDelegation( - message, onBehalfOfToken, actAsToken, appliesTo, - enableAppliesTo - ); + String key = appliesTo; + if (!enableAppliesTo || key == null || "".equals(key)) { + key = ASSOCIATED_TOKEN; + } + // See if the token corresponding to the OnBehalfOf/ActAs Token is stored in the cache + // and if it points to an issued token + SecurityToken secToken = tokenCacher.retrieveToken(message, onBehalfOfToken, key); + if (secToken == null) { + secToken = tokenCacher.retrieveToken(message, actAsToken, key); + } if (secToken != null) { // Check to see whether the delegated token needs to be renewed - secToken = renewToken(message, secToken, params); + secToken = renewToken(message, secToken, params, tokenCacher); } else { secToken = getTokenFromSTS(client, maps, appliesTo, params); } - storeDelegationTokens( - message, secToken, onBehalfOfToken, actAsToken, appliesTo, - enableAppliesTo); + + if (secToken != null) { + tokenCacher.storeToken(message, onBehalfOfToken, secToken.getId(), key); + tokenCacher.storeToken(message, actAsToken, secToken.getId(), key); + } return secToken; } catch (RuntimeException e) { throw e; @@ -183,7 +144,8 @@ public final class STSTokenRetriever { private static SecurityToken renewToken( Message message, SecurityToken tok, - TokenRequestParams params) { + TokenRequestParams params, + STSTokenCacher tokenCacher) { String imminentExpiryValue = (String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.STS_TOKEN_IMMINENT_EXPIRY_VALUE, message); @@ -198,17 +160,13 @@ public final class STSTokenRetriever { } // Remove token from cache - message.getExchange().getEndpoint().remove(SecurityConstants.TOKEN); - message.getExchange().getEndpoint().remove(SecurityConstants.TOKEN_ID); - message.getExchange().remove(SecurityConstants.TOKEN_ID); - message.getExchange().remove(SecurityConstants.TOKEN); - TokenStoreUtils.getTokenStore(message).remove(tok.getId()); + tokenCacher.removeToken(message, tok); // If the user has explicitly disabled Renewing then we can't renew a token, // so just get a new one STSClient client = STSUtils.getClientWithIssuer(message, "sts", params.getIssuer()); if (!client.isAllowRenewing()) { - return issueToken(message, params); + return issueToken(message, params, tokenCacher); } AddressingProperties maps = @@ -241,7 +199,7 @@ public final class STSTokenRetriever { SecurityConstants.STS_ISSUE_AFTER_FAILED_RENEW, message, true); if (issueAfterFailedRenew) { // Perhaps the STS does not support renewing, so try to issue a new token - return issueToken(message, params); + return issueToken(message, params, tokenCacher); } else { throw ex; } @@ -252,7 +210,7 @@ public final class STSTokenRetriever { SecurityConstants.STS_ISSUE_AFTER_FAILED_RENEW, message, true); if (issueAfterFailedRenew) { // Perhaps the STS does not support renewing, so try to issue a new token - return issueToken(message, params); + return issueToken(message, params, tokenCacher); } else { throw new Fault(ex); } @@ -265,27 +223,6 @@ public final class STSTokenRetriever { } } - // Check to see if the received token is a SAML2 Token with "OneTimeUse" set. If so, - // it should not be cached on the endpoint, but only on the message. - private static boolean isOneTimeUse(SecurityToken issuedToken) { - Element token = issuedToken.getToken(); - if (token != null && "Assertion".equals(token.getLocalName()) - && WSConstants.SAML2_NS.equals(token.getNamespaceURI())) { - try { - SamlAssertionWrapper assertion = new SamlAssertionWrapper(token); - - if (assertion.getSaml2().getConditions() != null - && assertion.getSaml2().getConditions().getOneTimeUse() != null) { - return true; - } - } catch (WSSecurityException ex) { - throw new Fault(ex); - } - } - - return false; - } - private static void mapSecurityProps(Message message, Map<String, Object> ctx) { for (String s : SecurityConstants.ALL_PROPERTIES) { Object v = message.getContextualProperty(s + ".it"); @@ -298,117 +235,6 @@ public final class STSTokenRetriever { } } - /** - * Parse ActAs/OnBehalfOf appropriately. See if the required token is stored in the cache. - */ - private static SecurityToken handleDelegation( - Message message, - Element onBehalfOfToken, - Element actAsToken, - String appliesTo, - boolean enableAppliesTo) throws Exception { - TokenStore tokenStore = TokenStoreUtils.getTokenStore(message); - String key = appliesTo; - if (!enableAppliesTo || key == null || "".equals(key)) { - key = ASSOCIATED_TOKEN; - } - // See if the token corresponding to the OnBehalfOf Token is stored in the cache - // and if it points to an issued token - if (onBehalfOfToken != null) { - String id = getIdFromToken(onBehalfOfToken); - SecurityToken cachedToken = tokenStore.getToken(id); - if (cachedToken != null) { - Map<String, Object> properties = cachedToken.getProperties(); - if (properties != null && properties.containsKey(key)) { - String associatedToken = (String)properties.get(key); - SecurityToken issuedToken = tokenStore.getToken(associatedToken); - if (issuedToken != null) { - return issuedToken; - } - } - } - } - - // See if the token corresponding to the ActAs Token is stored in the cache - // and if it points to an issued token - if (actAsToken != null) { - String id = getIdFromToken(actAsToken); - SecurityToken cachedToken = tokenStore.getToken(id); - if (cachedToken != null) { - Map<String, Object> properties = cachedToken.getProperties(); - if (properties != null && properties.containsKey(key)) { - String associatedToken = (String)properties.get(key); - SecurityToken issuedToken = tokenStore.getToken(associatedToken); - if (issuedToken != null) { - return issuedToken; - } - } - } - } - return null; - } - - private static String getIdFromToken(Element token) { - if (token != null) { - // Try to find the "Id" on the token. - if (token.hasAttributeNS(WSConstants.WSU_NS, "Id")) { - return token.getAttributeNS(WSConstants.WSU_NS, "Id"); - } else if (token.hasAttributeNS(null, "ID")) { - return token.getAttributeNS(null, "ID"); - } else if (token.hasAttributeNS(null, "AssertionID")) { - return token.getAttributeNS(null, "AssertionID"); - } - } - return ""; - } - - private static void storeDelegationTokens( - Message message, - SecurityToken issuedToken, - Element onBehalfOfToken, - Element actAsToken, - String appliesTo, - boolean enableAppliesTo) throws Exception { - if (issuedToken == null) { - return; - } - TokenStore tokenStore = TokenStoreUtils.getTokenStore(message); - String key = appliesTo; - if (!enableAppliesTo || key == null || "".equals(key)) { - key = ASSOCIATED_TOKEN; - } - if (onBehalfOfToken != null) { - String id = getIdFromToken(onBehalfOfToken); - SecurityToken cachedToken = tokenStore.getToken(id); - if (cachedToken == null) { - cachedToken = new SecurityToken(id); - cachedToken.setToken(onBehalfOfToken); - } - Map<String, Object> properties = cachedToken.getProperties(); - if (properties == null) { - properties = new HashMap<>(); - cachedToken.setProperties(properties); - } - properties.put(key, issuedToken.getId()); - tokenStore.add(cachedToken); - } - if (actAsToken != null) { - String id = getIdFromToken(actAsToken); - SecurityToken cachedToken = tokenStore.getToken(id); - if (cachedToken == null) { - cachedToken = new SecurityToken(id); - cachedToken.setToken(actAsToken); - } - Map<String, Object> properties = cachedToken.getProperties(); - if (properties == null) { - properties = new HashMap<>(); - cachedToken.setProperties(properties); - } - properties.put(key, issuedToken.getId()); - tokenStore.add(cachedToken); - } - } - private static SecurityToken getTokenFromSTS(STSClient client, AddressingProperties maps, String appliesTo, TokenRequestParams params) throws Exception {