You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by as...@apache.org on 2015/03/15 20:18:50 UTC
cxf git commit: First part of [CXF-6267]: issuing and renewing SAML
token functionality into utility
Repository: cxf
Updated Branches:
refs/heads/master e441a15af -> 6bdc9257b
First part of [CXF-6267]: issuing and renewing SAML token functionality into utility
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/6bdc9257
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/6bdc9257
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/6bdc9257
Branch: refs/heads/master
Commit: 6bdc9257b691e140f435a567e0b4f566c71be6cf
Parents: e441a15
Author: Andrei Shakirin <an...@gmail.com>
Authored: Sun Mar 15 20:18:42 2015 +0100
Committer: Andrei Shakirin <an...@gmail.com>
Committed: Sun Mar 15 20:18:42 2015 +0100
----------------------------------------------------------------------
.../IssuedTokenInterceptorProvider.java | 401 +-------------
.../policy/interceptors/STSTokenHelper.java | 538 +++++++++++++++++++
2 files changed, 542 insertions(+), 397 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/6bdc9257/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 5e5b0d1..5761f78 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
@@ -24,40 +24,26 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import javax.xml.namespace.QName;
-import org.w3c.dom.Element;
-import org.apache.cxf.common.logging.LogUtils;
-import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
-import org.apache.cxf.message.MessageUtils;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
-import org.apache.cxf.ws.addressing.AddressingProperties;
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.tokenstore.TokenStore;
-import org.apache.cxf.ws.security.trust.STSClient;
-import org.apache.cxf.ws.security.trust.STSUtils;
import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JInInterceptor;
import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor;
import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JStaxInInterceptor;
import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JStaxOutInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
-import org.apache.cxf.ws.security.wss4j.WSS4JUtils;
import org.apache.cxf.ws.security.wss4j.policyvalidators.IssuedTokenPolicyValidator;
-import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.saml.SAMLKeyInfo;
import org.apache.wss4j.common.saml.SamlAssertionWrapper;
import org.apache.wss4j.dom.WSConstants;
@@ -70,19 +56,13 @@ import org.apache.wss4j.policy.SP11Constants;
import org.apache.wss4j.policy.SP12Constants;
import org.apache.wss4j.policy.SPConstants;
import org.apache.wss4j.policy.model.IssuedToken;
-import org.apache.wss4j.policy.model.Trust10;
-import org.apache.wss4j.policy.model.Trust13;
/**
*
*/
public class IssuedTokenInterceptorProvider extends AbstractPolicyInterceptorProvider {
- private static final Logger LOG = LogUtils.getL7dLogger(IssuedTokenInterceptorProvider.class);
-
private static final long serialVersionUID = -6936475570762840527L;
- private static final String ASSOCIATED_TOKEN =
- IssuedTokenInterceptorProvider.class.getName() + "-" + "Associated_Token";
public IssuedTokenInterceptorProvider() {
super(Arrays.asList(SP11Constants.ISSUED_TOKEN, SP12Constants.ISSUED_TOKEN));
@@ -133,17 +113,6 @@ public class IssuedTokenInterceptorProvider extends AbstractPolicyInterceptorPro
public IssuedTokenOutInterceptor() {
super(Phase.PREPARE_SEND);
}
- private static void mapSecurityProps(Message message, Map<String, Object> ctx) {
- for (String s : SecurityConstants.ALL_PROPERTIES) {
- Object v = message.getContextualProperty(s + ".it");
- if (v == null) {
- v = message.getContextualProperty(s);
- }
- if (!ctx.containsKey(s) && v != null) {
- ctx.put(s, v);
- }
- }
- }
public void handleMessage(Message message) throws Fault {
AssertionInfoMap aim = message.get(AssertionInfoMap.class);
// extract Assertion information
@@ -156,33 +125,14 @@ public class IssuedTokenInterceptorProvider extends AbstractPolicyInterceptorPro
}
if (isRequestor(message)) {
IssuedToken itok = (IssuedToken)ais.iterator().next().getAssertion();
- assertIssuedToken(itok, aim);
- SecurityToken tok = retrieveCachedToken(message);
- if (tok == null) {
- tok = issueToken(message, aim, itok);
- } else {
- tok = renewToken(message, aim, itok, tok);
- }
+ SecurityToken tok = STSTokenHelper.getTokenByWSPolicy(message, itok, aim);
+
if (tok != null) {
+ assertIssuedToken(itok, aim);
for (AssertionInfo ai : ais) {
ai.setAsserted(true);
}
- boolean cacheIssuedToken =
- MessageUtils.getContextualBoolean(
- message, SecurityConstants.CACHE_ISSUED_TOKEN_IN_ENDPOINT, true
- ) && !isOneTimeUse(tok);
- if (cacheIssuedToken) {
- message.getExchange().get(Endpoint.class).put(SecurityConstants.TOKEN, tok);
- message.getExchange().put(SecurityConstants.TOKEN, tok);
- message.getExchange().put(SecurityConstants.TOKEN_ID, tok.getId());
- message.getExchange().get(Endpoint.class).put(SecurityConstants.TOKEN_ID,
- tok.getId());
- } else {
- message.put(SecurityConstants.TOKEN, tok);
- message.put(SecurityConstants.TOKEN_ID, tok.getId());
- }
- WSS4JUtils.getTokenStore(message).add(tok);
}
} else {
//server side should be checked on the way in
@@ -193,350 +143,7 @@ public class IssuedTokenInterceptorProvider extends AbstractPolicyInterceptorPro
assertIssuedToken(itok, aim);
}
}
- }
-
- private Trust10 getTrust10(AssertionInfoMap aim) {
- Collection<AssertionInfo> ais =
- PolicyUtils.getAllAssertionsByLocalname(aim, SPConstants.TRUST_10);
- if (ais.isEmpty()) {
- return null;
- }
- return (Trust10)ais.iterator().next().getAssertion();
- }
- private Trust13 getTrust13(AssertionInfoMap aim) {
- Collection<AssertionInfo> ais =
- PolicyUtils.getAllAssertionsByLocalname(aim, SPConstants.TRUST_13);
- if (ais.isEmpty()) {
- return null;
- }
- return (Trust13)ais.iterator().next().getAssertion();
- }
-
- // 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 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 SecurityToken retrieveCachedToken(Message message) {
- boolean cacheIssuedToken =
- MessageUtils.getContextualBoolean(
- message, SecurityConstants.CACHE_ISSUED_TOKEN_IN_ENDPOINT, 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 = WSS4JUtils.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 = WSS4JUtils.getTokenStore(message).getToken(tokId);
- }
- }
- }
- return tok;
- }
-
- /**
- * Parse ActAs/OnBehalfOf appropriately. See if the required token is stored in the cache.
- */
- private SecurityToken handleDelegation(
- Message message,
- Element onBehalfOfToken,
- Element actAsToken,
- String appliesTo,
- boolean enableAppliesTo
- ) throws Exception {
- TokenStore tokenStore = WSS4JUtils.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) {
- Properties properties = cachedToken.getProperties();
- if (properties != null && properties.containsKey(key)) {
- String associatedToken = properties.getProperty(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) {
- Properties properties = cachedToken.getProperties();
- if (properties != null && properties.containsKey(key)) {
- String associatedToken = properties.getProperty(key);
- SecurityToken issuedToken = tokenStore.getToken(associatedToken);
- if (issuedToken != null) {
- return issuedToken;
- }
- }
- }
- }
- return null;
- }
-
- private 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 void storeDelegationTokens(
- Message message,
- SecurityToken issuedToken,
- Element onBehalfOfToken,
- Element actAsToken,
- String appliesTo,
- boolean enableAppliesTo
- ) throws Exception {
- if (issuedToken == null) {
- return;
- }
- TokenStore tokenStore = WSS4JUtils.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);
- }
- Properties properties = cachedToken.getProperties();
- if (properties == null) {
- properties = new Properties();
- 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);
- }
- Properties properties = cachedToken.getProperties();
- if (properties == null) {
- properties = new Properties();
- cachedToken.setProperties(properties);
- }
- properties.put(key, issuedToken.getId());
- tokenStore.add(cachedToken);
- }
- }
-
- private SecurityToken getTokenFromSTS(
- Message message,
- STSClient client,
- AssertionInfoMap aim,
- AddressingProperties maps,
- IssuedToken itok,
- String appliesTo
- ) throws Exception {
- client.setTrust(getTrust10(aim));
- client.setTrust(getTrust13(aim));
- client.setTemplate(itok.getRequestSecurityTokenTemplate());
- if (itok.getPolicy() != null && itok.getPolicy().getNamespace() != null) {
- client.setWspNamespace(itok.getPolicy().getNamespace());
- }
- if (maps != null && maps.getNamespaceURI() != null) {
- client.setAddressingNamespace(maps.getNamespaceURI());
- }
- if (itok.getClaims() != null) {
- client.setClaims(itok.getClaims());
- }
- return client.requestSecurityToken(appliesTo);
- }
-
- private SecurityToken renewToken(
- Message message,
- AssertionInfoMap aim,
- 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() || tok.isAboutToExpire(imminentExpiry))) {
- return tok;
- }
-
- // Remove token from cache
- message.getExchange().get(Endpoint.class).remove(SecurityConstants.TOKEN);
- message.getExchange().get(Endpoint.class).remove(SecurityConstants.TOKEN_ID);
- message.getExchange().remove(SecurityConstants.TOKEN_ID);
- message.getExchange().remove(SecurityConstants.TOKEN);
- NegotiationUtils.getTokenStore(message).remove(tok.getId());
-
- // If the user has explicitly disabled Renewing then we can't renew a token,
- // so just get a new one
- STSClient client = STSUtils.getClient(message, "sts", itok);
- if (!client.isAllowRenewing()) {
- return issueToken(message, aim, itok);
- }
-
- AddressingProperties maps =
- (AddressingProperties)message
- .get("javax.xml.ws.addressing.context.outbound");
- if (maps == null) {
- maps = (AddressingProperties)message
- .get("javax.xml.ws.addressing.context");
- }
- synchronized (client) {
- try {
- Map<String, Object> ctx = client.getRequestContext();
- mapSecurityProps(message, ctx);
-
- client.setMessage(message);
-
- if (maps != null && maps.getNamespaceURI() != null) {
- client.setAddressingNamespace(maps.getNamespaceURI());
- }
-
- client.setTrust(getTrust10(aim));
- client.setTrust(getTrust13(aim));
-
- client.setTemplate(itok.getRequestSecurityTokenTemplate());
- return client.renewSecurityToken(tok);
- } catch (RuntimeException ex) {
- LOG.log(Level.WARNING, "Error renewing a token", ex);
- boolean issueAfterFailedRenew =
- MessageUtils.getContextualBoolean(
- message, SecurityConstants.STS_ISSUE_AFTER_FAILED_RENEW, true
- );
- if (issueAfterFailedRenew) {
- // Perhaps the STS does not support renewing, so try to issue a new token
- return issueToken(message, aim, itok);
- } else {
- throw ex;
- }
- } catch (Exception ex) {
- LOG.log(Level.WARNING, "Error renewing a token", ex);
- boolean issueAfterFailedRenew =
- MessageUtils.getContextualBoolean(
- message, SecurityConstants.STS_ISSUE_AFTER_FAILED_RENEW, true
- );
- if (issueAfterFailedRenew) {
- // Perhaps the STS does not support renewing, so try to issue a new token
- return issueToken(message, aim, itok);
- } else {
- throw new Fault(ex);
- }
- }
- }
- }
-
- private SecurityToken issueToken(
- Message message,
- AssertionInfoMap aim,
- IssuedToken itok
- ) {
- STSClient client = STSUtils.getClient(message, "sts", itok);
- AddressingProperties maps =
- (AddressingProperties)message
- .get("javax.xml.ws.addressing.context.outbound");
- if (maps == null) {
- maps = (AddressingProperties)message
- .get("javax.xml.ws.addressing.context");
- }
- synchronized (client) {
- try {
- // Transpose ActAs/OnBehalfOf info from original request to the STS client.
- Object token =
- message.getContextualProperty(SecurityConstants.STS_TOKEN_ACT_AS);
- if (token != null) {
- client.setActAs(token);
- }
- token =
- message.getContextualProperty(SecurityConstants.STS_TOKEN_ON_BEHALF_OF);
- if (token != null) {
- client.setOnBehalfOf(token);
- }
- Map<String, Object> ctx = client.getRequestContext();
- mapSecurityProps(message, ctx);
-
- Object o = message.getContextualProperty(SecurityConstants.STS_APPLIES_TO);
- String appliesTo = o == null ? null : o.toString();
- appliesTo = appliesTo == null
- ? message.getContextualProperty(Message.ENDPOINT_ADDRESS).toString()
- : appliesTo;
- boolean enableAppliesTo = client.isEnableAppliesTo();
-
- client.setMessage(message);
- Element onBehalfOfToken = client.getOnBehalfOfToken();
- Element actAsToken = client.getActAsToken();
-
- SecurityToken secToken =
- handleDelegation(
- message, onBehalfOfToken, actAsToken, appliesTo, enableAppliesTo
- );
- if (secToken == null) {
- secToken = getTokenFromSTS(message, client, aim, maps, itok, appliesTo);
- }
- storeDelegationTokens(
- message, secToken, onBehalfOfToken, actAsToken, appliesTo, enableAppliesTo
- );
- return secToken;
- } catch (RuntimeException e) {
- throw e;
- } catch (Exception e) {
- throw new Fault(e);
- }
- }
- }
-
+ }
}
static class IssuedTokenInInterceptor extends AbstractPhaseInterceptor<Message> {
http://git-wip-us.apache.org/repos/asf/cxf/blob/6bdc9257/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/STSTokenHelper.java
----------------------------------------------------------------------
diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/STSTokenHelper.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/STSTokenHelper.java
new file mode 100644
index 0000000..a4d3f41
--- /dev/null
+++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/STSTokenHelper.java
@@ -0,0 +1,538 @@
+/**
+ * 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.policy.interceptors;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Element;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.endpoint.Endpoint;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageUtils;
+import org.apache.cxf.ws.addressing.AddressingProperties;
+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.tokenstore.TokenStore;
+import org.apache.cxf.ws.security.trust.STSClient;
+import org.apache.cxf.ws.security.trust.STSUtils;
+import org.apache.cxf.ws.security.wss4j.WSS4JUtils;
+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.SPConstants;
+import org.apache.wss4j.policy.model.IssuedToken;
+import org.apache.wss4j.policy.model.Trust10;
+import org.apache.wss4j.policy.model.Trust13;
+
+public final class STSTokenHelper {
+ private static final Logger LOG = LogUtils.getL7dLogger(STSTokenHelper.class);
+ private static final String ASSOCIATED_TOKEN =
+ STSTokenHelper.class.getName() + "-" + "Associated_Token";
+
+ private STSTokenHelper() {
+ }
+
+ public static SecurityToken getTokenByWSPolicy(Message message, IssuedToken issuedToken,
+ AssertionInfoMap aim) {
+ TokenRequestParams params = new TokenRequestParams();
+ params.setIssuer(issuedToken.getIssuer());
+ params.setClaims(issuedToken.getClaims());
+ if (issuedToken.getPolicy() != null) {
+ params.setWspNamespace(issuedToken.getPolicy().getNamespace());
+ }
+ params.setTrust10(getTrust10(aim));
+ params.setTrust13(getTrust13(aim));
+ params.setTokenTemplate(issuedToken.getRequestSecurityTokenTemplate());
+
+ return getToken(message, params);
+ }
+
+ 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);
+ }
+
+ boolean cacheIssuedToken =
+ MessageUtils.getContextualBoolean(
+ message,
+ SecurityConstants.CACHE_ISSUED_TOKEN_IN_ENDPOINT,
+ true)
+ && !isOneTimeUse(tok);
+ if (cacheIssuedToken) {
+ message.getExchange().get(Endpoint.class).put(SecurityConstants.TOKEN, tok);
+ message.getExchange().put(SecurityConstants.TOKEN, tok);
+ message.getExchange().put(SecurityConstants.TOKEN_ID, tok.getId());
+ message.getExchange().get(Endpoint.class).put(SecurityConstants.TOKEN_ID,
+ tok.getId());
+ } else {
+ message.put(SecurityConstants.TOKEN, tok);
+ message.put(SecurityConstants.TOKEN_ID, tok.getId());
+ }
+ // ?
+ WSS4JUtils.getTokenStore(message).add(tok);
+
+ return tok;
+ }
+
+ private static SecurityToken retrieveCachedToken(Message message) {
+ boolean cacheIssuedToken =
+ MessageUtils.getContextualBoolean(
+ message,
+ SecurityConstants.CACHE_ISSUED_TOKEN_IN_ENDPOINT,
+ 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 = WSS4JUtils.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 = WSS4JUtils.getTokenStore(message).getToken(tokId);
+ }
+ }
+ }
+ return tok;
+ }
+
+ private static SecurityToken issueToken(Message message, TokenRequestParams params) {
+ AddressingProperties maps =
+ (AddressingProperties)message
+ .get("javax.xml.ws.addressing.context.outbound");
+ if (maps == null) {
+ maps = (AddressingProperties)message
+ .get("javax.xml.ws.addressing.context");
+ }
+ STSClient client = STSUtils.getClientWithIssuer(message, "sts", params.getIssuer());
+ synchronized (client) {
+ try {
+ // Transpose ActAs/OnBehalfOf info from original request to the STS client.
+ Object token =
+ message.getContextualProperty(SecurityConstants.STS_TOKEN_ACT_AS);
+ if (token != null) {
+ client.setActAs(token);
+ }
+ token =
+ message.getContextualProperty(SecurityConstants.STS_TOKEN_ON_BEHALF_OF);
+ if (token != null) {
+ client.setOnBehalfOf(token);
+ }
+ Map<String, Object> ctx = client.getRequestContext();
+ mapSecurityProps(message, ctx);
+
+ Object o = message.getContextualProperty(SecurityConstants.STS_APPLIES_TO);
+ String appliesTo = o == null ? null : o.toString();
+ appliesTo = appliesTo == null
+ ? message.getContextualProperty(Message.ENDPOINT_ADDRESS).toString()
+ : appliesTo;
+ boolean enableAppliesTo = client.isEnableAppliesTo();
+
+ client.setMessage(message);
+ Element onBehalfOfToken = client.getOnBehalfOfToken();
+ Element actAsToken = client.getActAsToken();
+
+ SecurityToken secToken =
+ handleDelegation(
+ message, onBehalfOfToken, actAsToken, appliesTo,
+ enableAppliesTo
+ );
+ if (secToken == null) {
+ secToken = getTokenFromSTS(message, client, maps, appliesTo, params);
+ }
+ storeDelegationTokens(
+ message, secToken, onBehalfOfToken, actAsToken, appliesTo,
+ enableAppliesTo);
+ return secToken;
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new Fault(e);
+ } finally {
+ client.setTrust((Trust10)null);
+ client.setTrust((Trust13)null);
+ client.setTemplate(null);
+ client.setAddressingNamespace(null);
+ }
+ }
+ }
+
+ private static SecurityToken renewToken(
+ Message message,
+ SecurityToken tok,
+ TokenRequestParams params) {
+ 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() || tok.isAboutToExpire(imminentExpiry))) {
+ return tok;
+ }
+
+ // Remove token from cache
+ message.getExchange().get(Endpoint.class).remove(SecurityConstants.TOKEN);
+ message.getExchange().get(Endpoint.class).remove(SecurityConstants.TOKEN_ID);
+ message.getExchange().remove(SecurityConstants.TOKEN_ID);
+ message.getExchange().remove(SecurityConstants.TOKEN);
+ NegotiationUtils.getTokenStore(message).remove(tok.getId());
+
+ // 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);
+ }
+
+ AddressingProperties maps =
+ (AddressingProperties)message
+ .get("javax.xml.ws.addressing.context.outbound");
+ if (maps == null) {
+ maps = (AddressingProperties)message
+ .get("javax.xml.ws.addressing.context");
+ }
+ synchronized (client) {
+ try {
+ Map<String, Object> ctx = client.getRequestContext();
+ mapSecurityProps(message, ctx);
+
+ client.setMessage(message);
+
+ if (maps != null) {
+ client.setAddressingNamespace(maps.getNamespaceURI());
+ }
+
+ client.setTrust(params.getTrust10());
+ client.setTrust(params.getTrust13());
+
+ client.setTemplate(params.getTokenTemplate());
+ return client.renewSecurityToken(tok);
+ } catch (RuntimeException ex) {
+ LOG.log(Level.WARNING, "Error renewing a token", ex);
+ boolean issueAfterFailedRenew =
+ MessageUtils
+ .getContextualBoolean(
+ message,
+ SecurityConstants.STS_ISSUE_AFTER_FAILED_RENEW, true);
+ if (issueAfterFailedRenew) {
+ // Perhaps the STS does not support renewing, so try to issue a new token
+ return issueToken(message, params);
+ } else {
+ throw ex;
+ }
+ } catch (Exception ex) {
+ LOG.log(Level.WARNING, "Error renewing a token", ex);
+ boolean issueAfterFailedRenew =
+ MessageUtils
+ .getContextualBoolean(
+ message,
+ SecurityConstants.STS_ISSUE_AFTER_FAILED_RENEW, true);
+ if (issueAfterFailedRenew) {
+ // Perhaps the STS does not support renewing, so try to issue a new token
+ return issueToken(message, params);
+ } else {
+ throw new Fault(ex);
+ }
+ } finally {
+ client.setTrust((Trust10)null);
+ client.setTrust((Trust13)null);
+ client.setTemplate(null);
+ client.setAddressingNamespace(null);
+ }
+ }
+ }
+
+ // 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");
+ if (v == null) {
+ v = message.getContextualProperty(s);
+ }
+ if (!ctx.containsKey(s) && v != null) {
+ ctx.put(s, v);
+ }
+ }
+ }
+
+ /**
+ * 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 = WSS4JUtils.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) {
+ Properties properties = cachedToken.getProperties();
+ if (properties != null && properties.containsKey(key)) {
+ String associatedToken = properties.getProperty(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) {
+ Properties properties = cachedToken.getProperties();
+ if (properties != null && properties.containsKey(key)) {
+ String associatedToken = properties.getProperty(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 = WSS4JUtils.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);
+ }
+ Properties properties = cachedToken.getProperties();
+ if (properties == null) {
+ properties = new Properties();
+ 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);
+ }
+ Properties properties = cachedToken.getProperties();
+ if (properties == null) {
+ properties = new Properties();
+ cachedToken.setProperties(properties);
+ }
+ properties.put(key, issuedToken.getId());
+ tokenStore.add(cachedToken);
+ }
+ }
+
+ private static SecurityToken getTokenFromSTS(Message message, STSClient client,
+ AddressingProperties maps, String appliesTo,
+ TokenRequestParams params) throws Exception {
+ client.setTrust(params.getTrust10());
+ client.setTrust(params.getTrust13());
+ client.setTemplate(params.getTokenTemplate());
+ if (params.getWspNamespace() != null) {
+ client.setWspNamespace(params.getWspNamespace());
+ }
+ if (maps != null && maps.getNamespaceURI() != null) {
+ client.setAddressingNamespace(maps.getNamespaceURI());
+ }
+ if (params.getClaims() != null) {
+ client.setClaims(params.getClaims());
+ }
+ return client.requestSecurityToken(appliesTo);
+ }
+
+ private static Trust10 getTrust10(AssertionInfoMap aim) {
+ Collection<AssertionInfo> ais =
+ PolicyUtils.getAllAssertionsByLocalname(aim, SPConstants.TRUST_10);
+ if (ais.isEmpty()) {
+ return null;
+ }
+ return (Trust10)ais.iterator().next().getAssertion();
+ }
+
+ private static Trust13 getTrust13(AssertionInfoMap aim) {
+ Collection<AssertionInfo> ais =
+ PolicyUtils.getAllAssertionsByLocalname(aim, SPConstants.TRUST_13);
+ if (ais.isEmpty()) {
+ return null;
+ }
+ return (Trust13)ais.iterator().next().getAssertion();
+ }
+
+ public static class TokenRequestParams {
+ private Element issuer;
+ private Trust10 trust10;
+ private Trust13 trust13;
+ private Element tokenTemplate;
+ private String wspNamespace;
+ private Element claims;
+
+ public Element getIssuer() {
+ return issuer;
+ }
+
+ public void setIssuer(Element issuer) {
+ this.issuer = issuer;
+ }
+
+ public Trust10 getTrust10() {
+ return trust10;
+ }
+
+ public void setTrust10(Trust10 trust10) {
+ this.trust10 = trust10;
+ }
+
+ public Trust13 getTrust13() {
+ return trust13;
+ }
+
+ public void setTrust13(Trust13 trust13) {
+ this.trust13 = trust13;
+ }
+
+ public Element getTokenTemplate() {
+ return tokenTemplate;
+ }
+
+ public void setTokenTemplate(Element tokenTemplate) {
+ this.tokenTemplate = tokenTemplate;
+ }
+
+ public String getWspNamespace() {
+ return wspNamespace;
+ }
+
+ public void setWspNamespace(String wspNamespace) {
+ this.wspNamespace = wspNamespace;
+ }
+
+ public Element getClaims() {
+ return claims;
+ }
+
+ public void setClaims(Element claims) {
+ this.claims = claims;
+ }
+ }
+}
+
+/*
+ * STSClient stsClient = new STSClient(bus); stsClient.setServiceQName(new QName(stsProps.get(STS_NAMESPACE),
+ * stsProps.get(STS_SERVICE_NAME))); Map<String, Object> props = new HashMap<String, Object>(); for
+ * (Map.Entry<String, String> entry : stsProps.entrySet()) { if
+ * (SecurityConstants.ALL_PROPERTIES.contains(entry.getKey())) { props.put(entry.getKey(),
+ * processFileURI(entry.getValue())); } } stsClient.setProperties(props);
+ * stsClient.setWsdlLocation(stsProps.get(STS_WSDL_LOCATION)); stsClient.setEndpointQName(new
+ * QName(stsProps.get(STS_NAMESPACE), stsProps.get(STS_ENDPOINT_NAME)));
+ * stsClient.setAllowRenewingAfterExpiry(true); stsClient.setEnableLifetime(true);
+ * stsClient.setTokenType(SAML2_TOKEN_TYPE); stsClient.setKeyType(BEARER_KEYTYPE); if (token != null) {
+ * stsClient.setActAs(token); } token =
+ * message.getContextualProperty(SecurityConstants.STS_TOKEN_ON_BEHALF_OF); if (token != null) {
+ * stsClient.setOnBehalfOf(token); } Object o =
+ * message.getContextualProperty(SecurityConstants.STS_APPLIES_TO); String appliesTo = null == o ? null :
+ * o.toString(); appliesTo = null == appliesTo ?
+ * message.getContextualProperty(Message.ENDPOINT_ADDRESS).toString() : appliesTo;
+ * stsClient.setMessage(message);
+ */