cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject [1/3] cxf git commit: [CXF-6607] - Cached STS-issued tokens are not renewed on expiry in delegation scenario
Date Thu, 24 Sep 2015 14:03:33 GMT
Repository: cxf
Updated Branches:
  refs/heads/3.0.x-fixes 4406f0ee5 -> 6ecda5285


[CXF-6607] - Cached STS-issued tokens are not renewed on expiry in delegation scenario

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


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

Branch: refs/heads/3.0.x-fixes
Commit: 949883baef755e5e25339069621166a420af98de
Parents: 4406f0e
Author: Colm O hEigeartaigh <coheigea@apache.org>
Authored: Thu Sep 24 14:39:23 2015 +0100
Committer: Colm O hEigeartaigh <coheigea@apache.org>
Committed: Thu Sep 24 14:40:25 2015 +0100

----------------------------------------------------------------------
 .../ws/security/trust/STSTokenRetriever.java    | 479 +++++++++++++++++++
 .../cxf/systest/sts/renew/SAMLRenewTest.java    |  13 +
 .../sts/renew/UsernameTokenValidator.java       |  67 +++
 .../apache/cxf/systest/sts/renew/DoubleIt.wsdl  |   3 +
 .../apache/cxf/systest/sts/renew/cxf-client.xml |  34 +-
 .../cxf/systest/sts/renew/cxf-service.xml       |   6 +
 .../cxf/systest/sts/renew/cxf-sts-pop.xml       |   9 +
 7 files changed, 610 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/949883ba/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
new file mode 100644
index 0000000..3b57bda
--- /dev/null
+++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSTokenRetriever.java
@@ -0,0 +1,479 @@
+/**
+ * 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 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.interceptor.Fault;
+import org.apache.cxf.message.Message;
+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;
+
+/**
+ * A Helper utility class to cache STS token and issue or renew the token from STS.
+ */
+public final class STSTokenRetriever {
+    private static final Logger LOG = LogUtils.getL7dLogger(STSTokenRetriever.class);
+    private static final String ASSOCIATED_TOKEN =
+        STSTokenRetriever.class.getName() + "-" + "Associated_Token";
+    
+    private 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);
+        }
+
+        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());
+        } else {
+            message.put(SecurityConstants.TOKEN, tok);
+            message.put(SecurityConstants.TOKEN_ID, tok.getId());
+            message.put(SecurityConstants.TOKEN_ELEMENT, tok.getToken());
+        }
+        // ?
+        TokenStoreUtils.getTokenStore(message).add(tok);
+
+        return 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) {
+        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 =
+                    SecurityUtils.getSecurityPropertyValue(SecurityConstants.STS_TOKEN_ACT_AS,
message);
+                if (token != null) {
+                    client.setActAs(token);
+                }
+                token =
+                    SecurityUtils.getSecurityPropertyValue(SecurityConstants.STS_TOKEN_ON_BEHALF_OF,
message);
+                if (token != null) {
+                    client.setOnBehalfOf(token);
+                }
+                Map<String, Object> ctx = client.getRequestContext();
+                mapSecurityProps(message, ctx);
+
+                Object o = SecurityUtils.getSecurityPropertyValue(SecurityConstants.STS_APPLIES_TO,
message);
+                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) {
+                    // Check to see whether the delegated token needs to be renewed
+                    secToken = renewToken(message, secToken, params);
+                } else {
+                    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)SecurityUtils.getSecurityPropertyValue(SecurityConstants.STS_TOKEN_IMMINENT_EXPIRY_VALUE,

+                                                           message);
+        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().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());
+
+        // 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 =
+                    SecurityUtils.getSecurityPropertyBoolean(
+                                              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);
+                } else {
+                    throw ex;
+                }
+            } catch (Exception ex) {
+                LOG.log(Level.WARNING, "Error renewing a token", ex);
+                boolean issueAfterFailedRenew =
+                    SecurityUtils.getSecurityPropertyBoolean(
+                                              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);
+                } 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 = 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(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);
+    }
+
+    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;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cxf/blob/949883ba/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/renew/SAMLRenewTest.java
----------------------------------------------------------------------
diff --git a/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/renew/SAMLRenewTest.java
b/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/renew/SAMLRenewTest.java
index a2fd15d..9a2c957 100644
--- a/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/renew/SAMLRenewTest.java
+++ b/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/renew/SAMLRenewTest.java
@@ -105,11 +105,21 @@ public class SAMLRenewTest extends AbstractBusClientServerTestBase {
             service.getPort(saml2NoRenewPortQName, DoubleItPortType.class);
         updateAddressPort(saml2NoRenewPort, PORT);
         
+        QName saml2IntermediaryPortQName = new QName(NAMESPACE, "DoubleItTransportSaml2IntermediaryPort");
+        DoubleItPortType saml2IntermediaryPort = 
+            service.getPort(saml2IntermediaryPortQName, DoubleItPortType.class);
+        updateAddressPort(saml2IntermediaryPort, PORT);
+        
+        ((BindingProvider)saml2IntermediaryPort).getRequestContext().put(
+            "security.username", "alice"
+        );
+        
         // Make initial successful invocation(s)
         doubleIt(saml1Port, 25);
         doubleIt(saml1BearerPort, 30);
         doubleIt(saml2Port, 35);
         doubleIt(saml2NoRenewPort, 35);
+        doubleIt(saml2IntermediaryPort, 40);
         
         // Now sleep to expire the token(s)
         Thread.sleep(8 * 1000);
@@ -138,9 +148,12 @@ public class SAMLRenewTest extends AbstractBusClientServerTestBase {
         // Renew should fail here, but it should fall back to issue
         doubleIt(saml2NoRenewPort, 35);
         
+        doubleIt(saml2IntermediaryPort, 40);
+        
         ((java.io.Closeable)saml1Port).close();
         ((java.io.Closeable)saml1BearerPort).close();
         ((java.io.Closeable)saml2Port).close();
+        ((java.io.Closeable)saml2IntermediaryPort).close();
         bus.shutdown(true);
     }
     

http://git-wip-us.apache.org/repos/asf/cxf/blob/949883ba/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/renew/UsernameTokenValidator.java
----------------------------------------------------------------------
diff --git a/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/renew/UsernameTokenValidator.java
b/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/renew/UsernameTokenValidator.java
new file mode 100644
index 0000000..7f0ec75
--- /dev/null
+++ b/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/renew/UsernameTokenValidator.java
@@ -0,0 +1,67 @@
+/**
+ * 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.systest.sts.renew;
+
+import org.apache.cxf.sts.request.ReceivedToken;
+import org.apache.cxf.sts.request.ReceivedToken.STATE;
+import org.apache.cxf.sts.token.validator.TokenValidator;
+import org.apache.cxf.sts.token.validator.TokenValidatorParameters;
+import org.apache.cxf.sts.token.validator.TokenValidatorResponse;
+import org.apache.cxf.ws.security.sts.provider.model.secext.UsernameTokenType;
+import org.apache.wss4j.common.principal.CustomTokenPrincipal;
+
+public class UsernameTokenValidator implements TokenValidator {
+    
+    /**
+     * Return true if this TokenValidator implementation is capable of validating the
+     * ReceivedToken argument.
+     */
+    public boolean canHandleToken(ReceivedToken validateTarget) {
+        return canHandleToken(validateTarget, null);
+    }
+    
+    /**
+     * Return true if this TokenValidator implementation is capable of validating the
+     * ReceivedToken argument. The realm is ignored in this token Validator.
+     */
+    public boolean canHandleToken(ReceivedToken validateTarget, String realm) {
+        return validateTarget.getToken() instanceof UsernameTokenType;
+    }
+    
+    /**
+     * Validate a Token using the given TokenValidatorParameters.
+     */
+    public TokenValidatorResponse validateToken(TokenValidatorParameters tokenParameters)
{
+        TokenValidatorResponse response = new TokenValidatorResponse();
+        ReceivedToken validateTarget = tokenParameters.getToken();
+        validateTarget.setState(STATE.INVALID);
+        response.setToken(validateTarget);
+        
+        UsernameTokenType usernameTokenType = (UsernameTokenType)validateTarget.getToken();
+        // Ignore the fact that no password is provided
+        // Some other requirements must be met to issue a token onbehalfof a subject
+        // whose authentication is not proved
+        validateTarget.setState(STATE.VALID);
+        response.setPrincipal(new CustomTokenPrincipal(usernameTokenType.getUsername().getValue()));
+        
+        return response;
+    }
+
+}
+        

http://git-wip-us.apache.org/repos/asf/cxf/blob/949883ba/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/DoubleIt.wsdl
----------------------------------------------------------------------
diff --git a/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/DoubleIt.wsdl
b/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/DoubleIt.wsdl
index b586a48..ff4eb32 100644
--- a/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/DoubleIt.wsdl
+++ b/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/DoubleIt.wsdl
@@ -77,6 +77,9 @@
         <wsdl:port name="DoubleItTransportSaml2NoRenewPort" binding="tns:DoubleItTransportSaml2Binding">
             <soap:address location="https://localhost:8081/doubleit/services/doubleittransportsaml2norenew"/>
         </wsdl:port>
+        <wsdl:port name="DoubleItTransportSaml2IntermediaryPort" binding="tns:DoubleItTransportSaml2Binding">
+            <soap:address location="https://localhost:8081/doubleit/services/doubleittransportsaml2intermediary"/>
+        </wsdl:port>
     </wsdl:service>
     <wsp:Policy wsu:Id="DoubleItBindingTransportSaml1Policy">
         <wsp:ExactlyOne>

http://git-wip-us.apache.org/repos/asf/cxf/blob/949883ba/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-client.xml
----------------------------------------------------------------------
diff --git a/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-client.xml
b/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-client.xml
index 487f44f..9e36aa3 100644
--- a/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-client.xml
+++ b/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-client.xml
@@ -96,7 +96,7 @@
         </jaxws:properties>
     </jaxws:client>
     
-     <bean id="saml2STSNoRenewClient" class="org.apache.cxf.ws.security.trust.STSClient">
+    <bean id="saml2STSNoRenewClient" class="org.apache.cxf.ws.security.trust.STSClient">
         <constructor-arg ref="cxf"/>
         <property name="wsdlLocation" value="https://localhost:${testutil.ports.renew.STSServerPOP}/SecurityTokenService/TransportSoap12?wsdl"/>
         <property name="serviceName" value="{http://docs.oasis-open.org/ws-sx/ws-trust/200512/}SecurityTokenService"/>
@@ -122,6 +122,38 @@
             <entry key="ws-security.sts.client" value-ref="saml2STSNoRenewClient" />
         </jaxws:properties>
     </jaxws:client>
+    
+    <bean id="delegationCallbackHandler" class="org.apache.cxf.ws.security.trust.delegation.WSSUsernameCallbackHandler"/>
+    
+    <bean id="saml2STSIntermediaryClient" class="org.apache.cxf.ws.security.trust.STSClient">
+        <constructor-arg ref="cxf"/>
+        <property name="wsdlLocation" value="https://localhost:${testutil.ports.renew.STSServerPOP}/SecurityTokenService/Transport?wsdl"/>
+        <property name="serviceName" value="{http://docs.oasis-open.org/ws-sx/ws-trust/200512/}SecurityTokenService"/>
+        <property name="endpointName" value="{http://docs.oasis-open.org/ws-sx/ws-trust/200512/}Transport_Port"/>
+        <property name="ttl" value="8"/>
+        <property name="enableLifetime" value="true"/>
+        <property name="allowRenewingAfterExpiry" value="true"/>
+        <property name="onBehalfOf" ref="delegationCallbackHandler"/>
+        <property name="properties">
+            <map>
+                <entry key="security.sts.token.username" value="myclientkey"/>
+                <entry key="security.sts.token.properties" value="clientKeystore.properties"/>
+                <entry key="security.sts.token.usecert" value="true"/>
+            </map>
+        </property>
+    </bean>
+    
+    <jaxws:client name="{http://www.example.org/contract/DoubleIt}DoubleItTransportSaml2IntermediaryPort"
createdFromAPI="true">
+        <jaxws:properties>
+            <entry key="security.username" value="alice"/>
+            <entry key="security.callback-handler" value="org.apache.cxf.systest.sts.common.CommonCallbackHandler"/>
+            <entry key="security.signature.properties" value="clientKeystore.properties"/>
+            <entry key="security.signature.username" value="myclientkey"/>
+            <entry key="security.sts.client" value-ref="saml2STSIntermediaryClient" />
+            <entry key="ws-security.cache.issued.token.in.endpoint" value="false"/>
+        </jaxws:properties>
+    </jaxws:client>
+    
     <http:conduit name="https://localhost:.*">
         <http:tlsClientParameters disableCNCheck="true">
             <sec:trustManagers>

http://git-wip-us.apache.org/repos/asf/cxf/blob/949883ba/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-service.xml
----------------------------------------------------------------------
diff --git a/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-service.xml
b/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-service.xml
index 53572b0..bfc7b09 100644
--- a/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-service.xml
+++ b/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-service.xml
@@ -48,6 +48,12 @@
             <entry key="ws-security.signature.properties" value="serviceKeystore.properties"/>
         </jaxws:properties>
     </jaxws:endpoint>
+    <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt" id="doubleittransportsaml2intermediary"
implementor="org.apache.cxf.systest.sts.common.DoubleItPortTypeImpl" endpointName="s:DoubleItTransportSaml2IntermediaryPort"
serviceName="s:DoubleItService" depends-on="ClientAuthHttpsSettings" address="https://localhost:${testutil.ports.renew.Server}/doubleit/services/doubleittransportsaml2intermediary"
wsdlLocation="org/apache/cxf/systest/sts/renew/DoubleIt.wsdl">
+        <jaxws:properties>
+            <entry key="security.callback-handler" value="org.apache.cxf.systest.sts.common.CommonCallbackHandler"/>
+            <entry key="security.signature.properties" value="serviceKeystore.properties"/>
+        </jaxws:properties>
+    </jaxws:endpoint>
     <httpj:engine-factory id="ClientAuthHttpsSettings" bus="cxf">
         <httpj:engine port="${testutil.ports.renew.Server}">
             <httpj:tlsServerParameters>

http://git-wip-us.apache.org/repos/asf/cxf/blob/949883ba/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-sts-pop.xml
----------------------------------------------------------------------
diff --git a/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-sts-pop.xml
b/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-sts-pop.xml
index ed4c5e3..21600a6 100644
--- a/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-sts-pop.xml
+++ b/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/renew/cxf-sts-pop.xml
@@ -24,6 +24,12 @@
             <cxf:logging/>
         </cxf:features>
     </cxf:bus>
+    
+    <bean id="utDelegationHandler" class="org.apache.cxf.sts.token.delegation.UsernameTokenDelegationHandler"/>
+    <util:list id="delegationHandlers">
+        <ref bean="utDelegationHandler"/>
+    </util:list>
+    
     <bean id="transportSTSProviderBean" class="org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider">
         <property name="issueOperation" ref="transportIssueDelegate"/>
         <property name="validateOperation" ref="transportValidateDelegate"/>
@@ -35,6 +41,8 @@
         <property name="stsProperties" ref="transportSTSProperties"/>
         <property name="claimsManager" ref="claimsManager"/>
         <property name="tokenStore" ref="defaultTokenStore"/>
+        <property name="delegationHandlers" ref="delegationHandlers"/>
+        <property name="tokenValidators" ref="transportTokenValidators"/>
     </bean>
     <bean id="transportValidateDelegate" class="org.apache.cxf.sts.operation.TokenValidateOperation">
         <property name="tokenProviders" ref="transportTokenProviders"/>
@@ -55,6 +63,7 @@
     </util:list>
     <util:list id="transportTokenValidators">
         <ref bean="transportSamlTokenValidator"/>
+        <bean class="org.apache.cxf.systest.sts.renew.UsernameTokenValidator"/>
     </util:list>
     <util:list id="transportTokenRenewers">
         <ref bean="transportSamlTokenRenewer"/>


Mime
View raw message