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 <[email protected]>
Authored: Thu Sep 24 14:39:23 2015 +0100
Committer: Colm O hEigeartaigh <[email protected]>
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"/>

Reply via email to