cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject [1/4] cxf git commit: Refactor how we extract "IDs" from delegation tokens when used for caching
Date Wed, 05 Apr 2017 12:20:32 GMT
Repository: cxf
Updated Branches:
  refs/heads/3.0.x-fixes 2b56bf00a -> 750b01a6e


Refactor how we extract "IDs" from delegation tokens when used for caching

# Conflicts:
#	rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/DefaultSTSTokenCacher.java


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/262d17c5
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/262d17c5
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/262d17c5

Branch: refs/heads/3.0.x-fixes
Commit: 262d17c5a3588acc28ff2a2ae5dc5280b35e6fb2
Parents: 2b56bf0
Author: Colm O hEigeartaigh <coheigea@apache.org>
Authored: Wed Apr 5 11:01:21 2017 +0100
Committer: Colm O hEigeartaigh <coheigea@apache.org>
Committed: Wed Apr 5 12:51:09 2017 +0100

----------------------------------------------------------------------
 .../security/trust/DefaultSTSTokenCacher.java   | 210 +++++++++++++++++++
 1 file changed, 210 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/262d17c5/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..c2699fc
--- /dev/null
+++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/DefaultSTSTokenCacher.java
@@ -0,0 +1,210 @@
+/**
+ * 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.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+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.common.util.XMLUtils;
+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;
+    }
+
+    // Get an id from the token that is unique to that token
+    private static String getIdFromToken(Element token) {
+        if (token != null) {
+            // For SAML tokens get the ID/AssertionID
+            if ("Assertion".equals(token.getLocalName())
+                && WSConstants.SAML2_NS.equals(token.getNamespaceURI())) {
+                return token.getAttributeNS(null, "ID");
+            } else if ("Assertion".equals(token.getLocalName())
+                && WSConstants.SAML_NS.equals(token.getNamespaceURI())) {
+                return token.getAttributeNS(null, "AssertionID");
+            }
+
+            // For UsernameTokens get the username
+            if (WSConstants.USERNAME_TOKEN_LN.equals(token.getLocalName())
+                && WSConstants.WSSE_NS.equals(token.getNamespaceURI())) {
+                Element usernameElement =
+                    XMLUtils.getDirectChildElement(token, WSConstants.USERNAME_LN, WSConstants.WSSE_NS);
+                if (usernameElement != null) {
+                    return XMLUtils.getElementText(usernameElement);
+                }
+            }
+
+            // For BinarySecurityTokens take the hash of the value
+            if (WSConstants.BINARY_TOKEN_LN.equals(token.getLocalName())
+                && WSConstants.WSSE_NS.equals(token.getNamespaceURI())) {
+                String text = XMLUtils.getElementText(token);
+                if (text != null && !"".equals(text)) {
+                    try {
+                        MessageDigest digest = MessageDigest.getInstance("SHA-256");
+                        byte[] bytes = digest.digest(text.getBytes());
+                        return Base64.getMimeEncoder().encodeToString(bytes);
+                    } catch (NoSuchAlgorithmException e) {
+                        // SHA-256 must be supported so not going to happen...
+                    }
+                }
+            }
+        }
+        return "";
+    }
+
+}
\ No newline at end of file


Mime
View raw message