cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject svn commit: r1207972 - in /cxf/trunk/services/sts/sts-core/src: main/java/org/apache/cxf/sts/operation/ main/java/org/apache/cxf/sts/request/ main/java/org/apache/cxf/sts/token/provider/ main/java/org/apache/cxf/sts/token/validator/ test/java/org/apach...
Date Tue, 29 Nov 2011 17:02:42 GMT
Author: coheigea
Date: Tue Nov 29 17:02:41 2011
New Revision: 1207972

URL: http://svn.apache.org/viewvc?rev=1207972&view=rev
Log:
[CXF-3928] - Add token validation for OnBehalfOf element in TokenIssueOperation
 - Patch applied

Added:
    cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueOnbehalfofUnitTest.java
Modified:
    cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java
    cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java
    cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java
    cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/ReceivedToken.java
    cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java
    cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java
    cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java

Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java?rev=1207972&r1=1207971&r2=1207972&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java Tue Nov 29 17:02:41 2011
@@ -37,7 +37,6 @@ import org.w3c.dom.Element;
 
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.helpers.DOMUtils;
-
 import org.apache.cxf.sts.QNameConstants;
 import org.apache.cxf.sts.RealmParser;
 import org.apache.cxf.sts.STSConstants;
@@ -45,6 +44,8 @@ import org.apache.cxf.sts.STSPropertiesM
 import org.apache.cxf.sts.cache.STSTokenStore;
 import org.apache.cxf.sts.claims.RequestClaimCollection;
 import org.apache.cxf.sts.request.KeyRequirements;
+import org.apache.cxf.sts.request.ReceivedToken;
+import org.apache.cxf.sts.request.ReceivedToken.STATE;
 import org.apache.cxf.sts.request.RequestParser;
 import org.apache.cxf.sts.request.TokenRequirements;
 import org.apache.cxf.sts.service.EncryptionProperties;
@@ -52,6 +53,9 @@ import org.apache.cxf.sts.service.Servic
 import org.apache.cxf.sts.token.provider.TokenProvider;
 import org.apache.cxf.sts.token.provider.TokenProviderParameters;
 import org.apache.cxf.sts.token.provider.TokenReference;
+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.STSException;
 import org.apache.cxf.ws.security.sts.provider.model.LifetimeType;
@@ -72,9 +76,12 @@ import org.apache.ws.security.message.WS
 import org.apache.ws.security.message.WSSecEncryptedKey;
 import org.apache.ws.security.util.XmlSchemaDateFormat;
 
+
+
 /**
  * This abstract class contains some common functionality for different operations.
  */
+@SuppressWarnings("")
 public abstract class AbstractOperation {
 
     public static final QName TOKEN_TYPE = 
@@ -86,6 +93,7 @@ public abstract class AbstractOperation 
     protected boolean encryptIssuedToken;
     protected List<ServiceMBean> services;
     protected List<TokenProvider> tokenProviders = new ArrayList<TokenProvider>();
+    protected List<TokenValidator> tokenValidators = new ArrayList<TokenValidator>();
     protected boolean returnReferences = true;
     protected STSTokenStore tokenStore;
     
@@ -124,6 +132,14 @@ public abstract class AbstractOperation 
     public List<TokenProvider> getTokenProviders() {
         return tokenProviders;
     }
+
+    public void setTokenValidators(List<TokenValidator> tokenValidators) {
+        this.tokenValidators = tokenValidators;
+    }
+
+    public List<TokenValidator> getTokenValidators() {
+        return tokenValidators;
+    }  
     
     /**
      * Check the arguments from the STSProvider and parse the request.
@@ -487,4 +503,47 @@ public abstract class AbstractOperation 
         return null;
     }
     
+    protected TokenValidatorResponse validateReceivedToken(
+            WebServiceContext context, String realm,
+            TokenRequirements tokenRequirements, ReceivedToken token) {
+        token.setValidationState(STATE.NONE);
+        
+        tokenRequirements.setValidateTarget(token);
+
+        TokenValidatorParameters validatorParameters = new TokenValidatorParameters();
+        validatorParameters.setStsProperties(stsProperties);
+        validatorParameters.setPrincipal(context.getUserPrincipal());
+        validatorParameters.setWebServiceContext(context);
+        validatorParameters.setTokenStore(getTokenStore());
+        validatorParameters.setKeyRequirements(null);
+        validatorParameters.setTokenRequirements(tokenRequirements);
+
+        TokenValidatorResponse tokenResponse = null;
+        for (TokenValidator tokenValidator : tokenValidators) {
+            boolean canHandle = false;
+            if (realm == null) {
+                canHandle = tokenValidator.canHandleToken(token);
+            } else {
+                canHandle = tokenValidator.canHandleToken(token, realm);
+            }
+            if (canHandle) {
+                try {
+                    tokenResponse = tokenValidator.validateToken(validatorParameters);
+                    token.setValidationState(
+                            tokenResponse.isValid() ? STATE.VALID : STATE.INVALID
+                    );
+                    // The parsed principal is set if available. It's up to other components to
+                    // deal with the STATE of the validation
+                    token.setPrincipal(tokenResponse.getPrincipal());
+                } catch (RuntimeException ex) {
+                    LOG.log(Level.WARNING, "Failed to validate the token", ex);
+                    token.setValidationState(STATE.INVALID);
+                }
+                break;
+            }
+        }
+        return tokenResponse;
+    }
+    
+    
 }

Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java?rev=1207972&r1=1207971&r2=1207972&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java Tue Nov 29 17:02:41 2011
@@ -20,8 +20,10 @@
 package org.apache.cxf.sts.operation;
 
 import java.net.URI;
+import java.security.Principal;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -29,11 +31,14 @@ import javax.xml.bind.JAXBElement;
 import javax.xml.ws.WebServiceContext;
 
 import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.sts.IdentityMapper;
 import org.apache.cxf.sts.QNameConstants;
 import org.apache.cxf.sts.claims.ClaimsManager;
 import org.apache.cxf.sts.claims.RequestClaim;
 import org.apache.cxf.sts.claims.RequestClaimCollection;
 import org.apache.cxf.sts.request.KeyRequirements;
+import org.apache.cxf.sts.request.ReceivedToken;
+import org.apache.cxf.sts.request.ReceivedToken.STATE;
 import org.apache.cxf.sts.request.RequestParser;
 import org.apache.cxf.sts.request.TokenRequirements;
 import org.apache.cxf.sts.service.EncryptionProperties;
@@ -41,6 +46,7 @@ import org.apache.cxf.sts.token.provider
 import org.apache.cxf.sts.token.provider.TokenProviderParameters;
 import org.apache.cxf.sts.token.provider.TokenProviderResponse;
 import org.apache.cxf.sts.token.provider.TokenReference;
+import org.apache.cxf.sts.token.validator.TokenValidatorResponse;
 import org.apache.cxf.ws.security.sts.provider.STSException;
 import org.apache.cxf.ws.security.sts.provider.model.BinarySecretType;
 import org.apache.cxf.ws.security.sts.provider.model.EntropyType;
@@ -62,8 +68,8 @@ public class TokenIssueOperation extends
 
     private static final Logger LOG = LogUtils.getL7dLogger(TokenIssueOperation.class);
 
-    private ClaimsManager claimsManager;
-    
+    private ClaimsManager claimsManager; 
+
     public ClaimsManager getClaimsManager() {
         return claimsManager;
     }
@@ -71,11 +77,11 @@ public class TokenIssueOperation extends
     public void setClaimsManager(ClaimsManager claimsManager) {
         this.claimsManager = claimsManager;
     }
-        
-    
+
+
     public RequestSecurityTokenResponseCollectionType issue(
-        RequestSecurityTokenType request,
-        WebServiceContext context
+            RequestSecurityTokenType request,
+            WebServiceContext context
     ) {
         RequestSecurityTokenResponseType response = issueSingle(request, context);
         RequestSecurityTokenResponseCollectionType responseCollection = 
@@ -83,45 +89,89 @@ public class TokenIssueOperation extends
         responseCollection.getRequestSecurityTokenResponse().add(response);
         return responseCollection;
     }
-    
+
     public RequestSecurityTokenResponseType issueSingle(
-        RequestSecurityTokenType request,
-        WebServiceContext context
+            RequestSecurityTokenType request,
+            WebServiceContext context
     ) {
         RequestParser requestParser = parseRequest(request, context);
-        
+
         TokenProviderParameters providerParameters = createTokenProviderParameters(requestParser, context);
-        
+
         // Check if the requested claims can be handled by the configured claim handlers
         RequestClaimCollection requestedClaims = providerParameters.getRequestedClaims();
         if (requestedClaims != null) {
             List<URI> unhandledClaimTypes = new ArrayList<URI>();
             for (RequestClaim requestedClaim : requestedClaims) {
                 if (!claimsManager.getSupportedClaimTypes().contains(requestedClaim.getClaimType()) 
-                    && !requestedClaim.isOptional()) {
+                        && !requestedClaim.isOptional()) {
                     unhandledClaimTypes.add(requestedClaim.getClaimType());
                 }
             }
-        
+
             if (unhandledClaimTypes.size() > 0) {
                 LOG.log(Level.WARNING, "The requested claim " + unhandledClaimTypes.toString() 
-                         + " cannot be fulfilled by the STS.");
+                        + " cannot be fulfilled by the STS.");
                 throw new STSException(
-                    "The requested claim " + unhandledClaimTypes.toString() 
-                    + " cannot be fulfilled by the STS."
+                        "The requested claim " + unhandledClaimTypes.toString() 
+                        + " cannot be fulfilled by the STS."
                 );
             }
         }
-        
+
         providerParameters.setClaimsManager(claimsManager);
-        
-        // create token
+        String realm = providerParameters.getRealm();
+
         TokenRequirements tokenRequirements = requestParser.getTokenRequirements();
         String tokenType = tokenRequirements.getTokenType();
+
+
+        // Validate OnBehalfOf token if present
+        if (providerParameters.getTokenRequirements().getOnBehalfOf() != null) {
+            ReceivedToken validateTarget = providerParameters.getTokenRequirements().getOnBehalfOf();
+            TokenValidatorResponse tokenResponse = validateReceivedToken(
+                    context, realm, tokenRequirements, validateTarget);
+            
+            if (tokenResponse == null) {
+                LOG.fine("No Token Validator has been found that can handle this token");
+
+            } else if (validateTarget.getValidationState().equals(STATE.VALID)) {
+                // Map the principal (if it exists)
+                Principal responsePrincipal = tokenResponse.getPrincipal();
+                if (responsePrincipal != null) {
+                    String targetRealm = providerParameters.getRealm();
+                    String sourceRealm = tokenResponse.getTokenRealm();
+                    IdentityMapper identityMapper = stsProperties.getIdentityMapper();
+                    if (sourceRealm != null && !sourceRealm.equals(targetRealm) && identityMapper != null) {
+                        Principal targetPrincipal = 
+                            identityMapper.mapPrincipal(sourceRealm, responsePrincipal, targetRealm);
+                        validateTarget.setPrincipal(targetPrincipal);
+                    }
+                } 
+            } else {
+                //[TODO] Add plugin for validation out-of-band
+                // Example:
+                // If the requestor is in the possession of a certificate (mutual ssl handshake)
+                // the STS trusts the token sent in OnBehalfOf element
+            }
+            if (tokenResponse != null) {
+                Map<String, Object> additionalProperties = tokenResponse.getAdditionalProperties();
+                if (additionalProperties != null) {
+                    providerParameters.setAdditionalProperties(additionalProperties);
+                }
+            }
+        }
+
+        // create token
         TokenProviderResponse tokenResponse = null;
-        String realm = providerParameters.getRealm();
         for (TokenProvider tokenProvider : tokenProviders) {
-            if (tokenProvider.canHandleToken(tokenType, realm)) {
+            boolean canHandle = false;
+            if (realm == null) {
+                canHandle = tokenProvider.canHandleToken(tokenType);
+            } else {
+                canHandle = tokenProvider.canHandleToken(tokenType, realm);
+            }
+            if (canHandle) {
                 try {
                     tokenResponse = tokenProvider.createToken(providerParameters);
                 } catch (STSException ex) {
@@ -137,8 +187,8 @@ public class TokenIssueOperation extends
         if (tokenResponse == null || tokenResponse.getToken() == null) {
             LOG.log(Level.WARNING, "No token provider found for requested token type: " + tokenType);
             throw new STSException(
-                "No token provider found for requested token type: " + tokenType, 
-                STSException.REQUEST_FAILED
+                    "No token provider found for requested token type: " + tokenType, 
+                    STSException.REQUEST_FAILED
             );
         }
         // prepare response
@@ -147,7 +197,7 @@ public class TokenIssueOperation extends
             EncryptionProperties encryptionProperties = providerParameters.getEncryptionProperties();
             RequestSecurityTokenResponseType response = 
                 createResponse(
-                    encryptionProperties, tokenResponse, tokenRequirements, keyRequirements, context
+                        encryptionProperties, tokenResponse, tokenRequirements, keyRequirements, context
                 );
             return response;
         } catch (Throwable ex) {
@@ -157,15 +207,15 @@ public class TokenIssueOperation extends
     }
 
     private RequestSecurityTokenResponseType createResponse(
-        EncryptionProperties encryptionProperties,
-        TokenProviderResponse tokenResponse, 
-        TokenRequirements tokenRequirements,
-        KeyRequirements keyRequirements,
-        WebServiceContext webServiceContext
+            EncryptionProperties encryptionProperties,
+            TokenProviderResponse tokenResponse, 
+            TokenRequirements tokenRequirements,
+            KeyRequirements keyRequirements,
+            WebServiceContext webServiceContext
     ) throws WSSecurityException {
         RequestSecurityTokenResponseType response = 
             QNameConstants.WS_TRUST_FACTORY.createRequestSecurityTokenResponseType();
-        
+
         String context = tokenRequirements.getContext();
         if (context != null) {
             response.setContext(context);
@@ -203,16 +253,16 @@ public class TokenIssueOperation extends
             } else {
                 requestedAttachedReferenceType = 
                     createRequestedReference(
-                        tokenResponse.getTokenId(), tokenRequirements.getTokenType(), true
+                            tokenResponse.getTokenId(), tokenRequirements.getTokenType(), true
                     );
             }
-    
+
             JAXBElement<RequestedReferenceType> requestedAttachedReference = 
                 QNameConstants.WS_TRUST_FACTORY.createRequestedAttachedReference(
-                    requestedAttachedReferenceType
+                        requestedAttachedReferenceType
                 );
             response.getAny().add(requestedAttachedReference);
-    
+
             // RequestedUnattachedReference
             TokenReference unAttachedReference = tokenResponse.getUnAttachedReference();
             RequestedReferenceType requestedUnattachedReferenceType = null;
@@ -221,17 +271,17 @@ public class TokenIssueOperation extends
             } else {
                 requestedUnattachedReferenceType = 
                     createRequestedReference(
-                        tokenResponse.getTokenId(), tokenRequirements.getTokenType(), false
+                            tokenResponse.getTokenId(), tokenRequirements.getTokenType(), false
                     );
             }
-        
+
             JAXBElement<RequestedReferenceType> requestedUnattachedReference = 
                 QNameConstants.WS_TRUST_FACTORY.createRequestedUnattachedReference(
-                    requestedUnattachedReferenceType
+                        requestedUnattachedReferenceType
                 );
             response.getAny().add(requestedUnattachedReference);
         }
-        
+
         // AppliesTo
         response.getAny().add(tokenRequirements.getAppliesTo());
 
@@ -255,7 +305,7 @@ public class TokenIssueOperation extends
                 QNameConstants.WS_TRUST_FACTORY.createRequestedProofToken(requestedProofTokenType);
             response.getAny().add(requestedProofToken);
         }
-        
+
         // Entropy
         if (tokenResponse.isComputedKey() && tokenResponse.getEntropy() != null) {
             Object token = 
@@ -266,12 +316,12 @@ public class TokenIssueOperation extends
                 QNameConstants.WS_TRUST_FACTORY.createEntropy(entropyType);
             response.getAny().add(entropyElement);
         }
-        
+
         // Lifetime
         LifetimeType lifetime = createLifetime(tokenResponse.getLifetime());
         JAXBElement<LifetimeType> lifetimeType = QNameConstants.WS_TRUST_FACTORY.createLifetime(lifetime);
         response.getAny().add(lifetimeType);
-        
+
         // KeySize
         long keySize = tokenResponse.getKeySize();
         if (keySize <= 0) {
@@ -282,19 +332,19 @@ public class TokenIssueOperation extends
                 QNameConstants.WS_TRUST_FACTORY.createKeySize(keySize);
             response.getAny().add(keySizeType);
         }
-        
+
         return response;
     }
-    
+
     /**
      * Construct a token containing the secret to return to the client. If encryptIssuedToken is set
      * then the token is wrapped in an EncryptedKey DOM element, otherwise it is returned in a 
      * BinarySecretType JAXBElement.
      */
     private Object constructSecretToken(
-        byte[] secret,
-        EncryptionProperties encryptionProperties, 
-        KeyRequirements keyRequirements
+            byte[] secret,
+            EncryptionProperties encryptionProperties, 
+            KeyRequirements keyRequirements
     ) throws WSSecurityException {
         if (encryptIssuedToken) {
             return encryptSecret(secret, encryptionProperties, keyRequirements);
@@ -308,5 +358,5 @@ public class TokenIssueOperation extends
             return binarySecret;
         }
     }
-    
+
 }

Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java?rev=1207972&r1=1207971&r2=1207972&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java Tue Nov 29 17:02:41 2011
@@ -20,8 +20,6 @@
 package org.apache.cxf.sts.operation;
 
 import java.security.Principal;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -32,8 +30,8 @@ import javax.xml.ws.WebServiceContext;
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.sts.IdentityMapper;
 import org.apache.cxf.sts.QNameConstants;
+import org.apache.cxf.sts.RealmParser;
 import org.apache.cxf.sts.STSConstants;
-import org.apache.cxf.sts.request.KeyRequirements;
 import org.apache.cxf.sts.request.ReceivedToken;
 import org.apache.cxf.sts.request.RequestParser;
 import org.apache.cxf.sts.request.TokenRequirements;
@@ -41,8 +39,6 @@ import org.apache.cxf.sts.token.provider
 import org.apache.cxf.sts.token.provider.TokenProviderParameters;
 import org.apache.cxf.sts.token.provider.TokenProviderResponse;
 import org.apache.cxf.sts.token.provider.TokenReference;
-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.STSException;
 import org.apache.cxf.ws.security.sts.provider.model.LifetimeType;
@@ -61,23 +57,13 @@ public class TokenValidateOperation exte
 
     private static final Logger LOG = LogUtils.getL7dLogger(TokenValidateOperation.class);
 
-    private List<TokenValidator> tokenValidators = new ArrayList<TokenValidator>();
-    
-    public void setTokenValidators(List<TokenValidator> tokenValidators) {
-        this.tokenValidators = tokenValidators;
-    }
-    
-    public List<TokenValidator> getTokenValidators() {
-        return tokenValidators;
-    }
-    
+   
     public RequestSecurityTokenResponseType validate(
         RequestSecurityTokenType request, 
         WebServiceContext context
     ) {
         RequestParser requestParser = parseRequest(request, context);
         
-        KeyRequirements keyRequirements = requestParser.getKeyRequirements();
         TokenRequirements tokenRequirements = requestParser.getTokenRequirements();
         
         ReceivedToken validateTarget = tokenRequirements.getValidateTarget();
@@ -92,31 +78,16 @@ public class TokenValidateOperation exte
             );
         }
         
-        TokenValidatorParameters validatorParameters = new TokenValidatorParameters();
-        validatorParameters.setStsProperties(stsProperties);
-        validatorParameters.setPrincipal(context.getUserPrincipal());
-        validatorParameters.setWebServiceContext(context);
-        validatorParameters.setTokenStore(getTokenStore());
+        // Get the realm of the request
+        String realm = null;
+        if (stsProperties.getRealmParser() != null) {
+            RealmParser realmParser = stsProperties.getRealmParser();
+            realm = realmParser.parseRealm(context);
+        }
         
-        validatorParameters.setKeyRequirements(keyRequirements);
-        validatorParameters.setTokenRequirements(tokenRequirements);
+        TokenValidatorResponse tokenResponse = validateReceivedToken(
+                context, realm, tokenRequirements, validateTarget);
         
-        //
-        // Validate token
-        //
-        TokenValidatorResponse tokenResponse = null;
-        for (TokenValidator tokenValidator : tokenValidators) {
-            if (tokenValidator.canHandleToken(validateTarget)) {
-                try {
-                    tokenResponse = tokenValidator.validateToken(validatorParameters);
-                } catch (RuntimeException ex) {
-                    LOG.log(Level.WARNING, "", ex);
-                    tokenResponse = new TokenValidatorResponse();
-                    tokenResponse.setValid(false);
-                }
-                break;
-            }
-        }
         if (tokenResponse == null) {
             LOG.fine("No Token Validator has been found that can handle this token");
             tokenResponse = new TokenValidatorResponse();
@@ -151,9 +122,15 @@ public class TokenValidateOperation exte
             if (additionalProperties != null) {
                 providerParameters.setAdditionalProperties(additionalProperties);
             }
-            String realm = providerParameters.getRealm();
+            realm = providerParameters.getRealm();
             for (TokenProvider tokenProvider : tokenProviders) {
-                if (tokenProvider.canHandleToken(tokenType, realm)) {
+                boolean canHandle = false;
+                if (realm == null) {
+                    canHandle = tokenProvider.canHandleToken(tokenType);
+                } else {
+                    canHandle = tokenProvider.canHandleToken(tokenType, realm);
+                }
+                if (canHandle) {
                     try {
                         tokenProviderResponse = tokenProvider.createToken(providerParameters);
                     } catch (STSException ex) {

Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/ReceivedToken.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/ReceivedToken.java?rev=1207972&r1=1207971&r2=1207972&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/ReceivedToken.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/ReceivedToken.java Tue Nov 29 17:02:41 2011
@@ -18,6 +18,7 @@
  */
 package org.apache.cxf.sts.request;
 
+import java.security.Principal;
 import java.util.logging.Logger;
 
 import javax.xml.bind.JAXBElement;
@@ -41,6 +42,11 @@ public class ReceivedToken {
     private boolean isBinarySecurityToken;
     private boolean isUsernameToken;
     private boolean isDOMElement;
+    private String tokenContext; // WS-Security, OnBehalfOf, ActAs
+    private STATE validationState;
+    private Principal principal;
+    
+    public enum STATE { VALID, INVALID, NONE };
     
     public ReceivedToken(Object receivedToken) throws STSException {
         if (receivedToken instanceof JAXBElement<?>) {
@@ -104,4 +110,28 @@ public class ReceivedToken {
         this.isDOMElement = domElement;
     }
     
+    public String getTokenContext() {
+        return tokenContext;
+    }
+
+    public void setTokenContext(String tokenContext) {
+        this.tokenContext = tokenContext;
+    }
+
+    public STATE getValidationState() {
+        return validationState;
+    }
+
+    public void setValidationState(STATE validationState) {
+        this.validationState = validationState;
+    }
+
+    public Principal getPrincipal() {
+        return principal;
+    }
+
+    public void setPrincipal(Principal principal) {
+        this.principal = principal;
+    }
+    
 }
\ No newline at end of file

Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java?rev=1207972&r1=1207971&r2=1207972&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java Tue Nov 29 17:02:41 2011
@@ -31,16 +31,15 @@ import org.apache.cxf.sts.STSConstants;
 import org.apache.cxf.sts.STSPropertiesMBean;
 import org.apache.cxf.sts.request.KeyRequirements;
 import org.apache.cxf.sts.request.ReceivedToken;
+import org.apache.cxf.sts.request.ReceivedToken.STATE;
 import org.apache.cxf.sts.request.TokenRequirements;
 import org.apache.cxf.sts.service.EncryptionProperties;
 import org.apache.cxf.ws.security.sts.provider.STSException;
-import org.apache.ws.security.SAMLTokenPrincipal;
 import org.apache.ws.security.WSConstants;
 import org.apache.ws.security.WSSecurityException;
 import org.apache.ws.security.components.crypto.Crypto;
 import org.apache.ws.security.components.crypto.CryptoType;
 import org.apache.ws.security.message.WSSecEncryptedKey;
-import org.apache.ws.security.saml.ext.AssertionWrapper;
 import org.apache.ws.security.saml.ext.bean.KeyInfoBean;
 import org.apache.ws.security.saml.ext.bean.KeyInfoBean.CERT_IDENTIFIER;
 import org.apache.ws.security.saml.ext.bean.SubjectBean;
@@ -84,16 +83,11 @@ public class DefaultSubjectProvider impl
         Principal principal = null;
         ReceivedToken receivedToken = providerParameters.getTokenRequirements().getOnBehalfOf();
         //[TODO] ActAs support
-        if (receivedToken != null && receivedToken.isDOMElement()) {
-            LOG.fine("Received token is DOM element: " + receivedToken.isDOMElement());
-            Element receivedTokenElement = (Element)receivedToken.getToken();
-            try {
-                AssertionWrapper assertion = new AssertionWrapper(receivedTokenElement);
-                principal = new SAMLTokenPrincipal(assertion);
-            } catch (WSSecurityException e) {
-                LOG.log(Level.WARNING, "Failed to parse OnBehalfOf element", e);
-                throw new STSException("Unknown OnBehalfOf element", STSException.REQUEST_FAILED);
-            }
+        //TokenValidator in IssueOperation has validated the ReceivedToken
+        //if validation was successful, the principal was set in ReceivedToken 
+        if (receivedToken != null && receivedToken.getPrincipal() != null 
+                && receivedToken.getValidationState().equals(STATE.VALID)) {
+            principal = receivedToken.getPrincipal();
         } else {
             principal = providerParameters.getPrincipal();
         }

Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java?rev=1207972&r1=1207971&r2=1207972&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java Tue Nov 29 17:02:41 2011
@@ -137,6 +137,9 @@ public class SAMLTokenValidator implemen
             Element validateTargetElement = (Element)validateTarget.getToken();
             AssertionWrapper assertion = new AssertionWrapper(validateTargetElement);
             
+            SAMLTokenPrincipal samlPrincipal = new SAMLTokenPrincipal(assertion);
+            response.setPrincipal(samlPrincipal);
+            
             SecurityToken secToken = null;
             if (tokenParameters.getTokenStore() != null) {
                 int hash = 0;
@@ -212,8 +215,6 @@ public class SAMLTokenValidator implemen
                 }
             }
             
-            SAMLTokenPrincipal samlPrincipal = new SAMLTokenPrincipal(assertion);
-            response.setPrincipal(samlPrincipal);
             response.setTokenRealm(tokenRealm);
             response.setValid(true);
         } catch (WSSecurityException ex) {

Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java?rev=1207972&r1=1207971&r2=1207972&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java Tue Nov 29 17:02:41 2011
@@ -44,6 +44,7 @@ import org.apache.cxf.sts.token.realm.Us
 import org.apache.cxf.ws.security.sts.provider.model.secext.UsernameTokenType;
 import org.apache.cxf.ws.security.tokenstore.SecurityToken;
 
+import org.apache.ws.security.CustomTokenPrincipal;
 import org.apache.ws.security.WSConstants;
 import org.apache.ws.security.WSSConfig;
 import org.apache.ws.security.WSSecurityException;
@@ -167,6 +168,8 @@ public class UsernameTokenValidator impl
             boolean bspCompliant = wssConfig.isWsiBSPCompliant();
             UsernameToken ut = 
                 new UsernameToken(usernameTokenElement, allowNamespaceQualifiedPasswordTypes, bspCompliant);
+            // The parsed principal is set independent whether validation is successful or not
+            response.setPrincipal(new CustomTokenPrincipal(ut.getName()));
             if (ut.getPassword() == null) {
                 return response;
             }

Added: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueOnbehalfofUnitTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueOnbehalfofUnitTest.java?rev=1207972&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueOnbehalfofUnitTest.java (added)
+++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueOnbehalfofUnitTest.java Tue Nov 29 17:02:41 2011
@@ -0,0 +1,516 @@
+/**
+ * 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.sts.operation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.apache.cxf.jaxws.context.WebServiceContextImpl;
+import org.apache.cxf.jaxws.context.WrappedMessageContext;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.sts.QNameConstants;
+import org.apache.cxf.sts.STSConstants;
+import org.apache.cxf.sts.STSPropertiesMBean;
+import org.apache.cxf.sts.StaticSTSProperties;
+import org.apache.cxf.sts.common.PasswordCallbackHandler;
+import org.apache.cxf.sts.request.KeyRequirements;
+import org.apache.cxf.sts.request.TokenRequirements;
+import org.apache.cxf.sts.service.EncryptionProperties;
+import org.apache.cxf.sts.service.ServiceMBean;
+import org.apache.cxf.sts.service.StaticService;
+import org.apache.cxf.sts.token.provider.SAMLTokenProvider;
+import org.apache.cxf.sts.token.provider.TokenProvider;
+import org.apache.cxf.sts.token.provider.TokenProviderParameters;
+import org.apache.cxf.sts.token.provider.TokenProviderResponse;
+import org.apache.cxf.sts.token.realm.SAMLRealm;
+import org.apache.cxf.sts.token.validator.IssuerSAMLRealmCodec;
+import org.apache.cxf.sts.token.validator.SAMLTokenValidator;
+import org.apache.cxf.sts.token.validator.TokenValidator;
+import org.apache.cxf.sts.token.validator.UsernameTokenValidator;
+import org.apache.cxf.ws.security.sts.provider.STSException;
+import org.apache.cxf.ws.security.sts.provider.model.OnBehalfOfType;
+import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenResponseCollectionType;
+import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenResponseType;
+import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenType;
+import org.apache.cxf.ws.security.sts.provider.model.RequestedSecurityTokenType;
+import org.apache.cxf.ws.security.sts.provider.model.secext.AttributedString;
+import org.apache.cxf.ws.security.sts.provider.model.secext.PasswordString;
+import org.apache.cxf.ws.security.sts.provider.model.secext.UsernameTokenType;
+import org.apache.ws.security.CustomTokenPrincipal;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.saml.ext.builder.SAML2Constants;
+import org.apache.ws.security.util.DOM2Writer;
+
+
+/**
+ * Some unit tests for the issue operation.
+ */
+public class IssueOnbehalfofUnitTest extends org.junit.Assert {
+
+    public static final QName REQUESTED_SECURITY_TOKEN = 
+        QNameConstants.WS_TRUST_FACTORY.createRequestedSecurityToken(null).getName();
+    
+    /**
+     * Test to successfully issue a SAML 2 token on-behalf-of a SAML 2 token
+     */
+    @org.junit.Test
+    public void testIssueSaml2TokenOnBehalfOfSaml2() throws Exception {
+        TokenIssueOperation issueOperation = new TokenIssueOperation();
+
+        // Add Token Provider
+        List<TokenProvider> providerList = new ArrayList<TokenProvider>();
+        providerList.add(new SAMLTokenProvider());
+        issueOperation.setTokenProviders(providerList);
+        
+        // Add Token Validator
+        List<TokenValidator> validatorList = new ArrayList<TokenValidator>();
+        validatorList.add(new SAMLTokenValidator());
+        issueOperation.setTokenValidators(validatorList);
+
+        // Add Service
+        ServiceMBean service = new StaticService();
+        service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy"));
+        issueOperation.setServices(Collections.singletonList(service));
+
+        // Add STSProperties object
+        STSPropertiesMBean stsProperties = new StaticSTSProperties();
+        Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+        stsProperties.setEncryptionCrypto(crypto);
+        stsProperties.setSignatureCrypto(crypto);
+        stsProperties.setEncryptionUsername("myservicekey");
+        stsProperties.setSignatureUsername("mystskey");
+        stsProperties.setCallbackHandler(new PasswordCallbackHandler());
+        stsProperties.setIssuer("STS");
+        issueOperation.setStsProperties(stsProperties);
+
+        // Mock up a request
+        RequestSecurityTokenType request = new RequestSecurityTokenType();
+        JAXBElement<String> tokenType = 
+            new JAXBElement<String>(
+                    QNameConstants.TOKEN_TYPE, String.class, WSConstants.WSS_SAML2_TOKEN_TYPE
+            );
+        request.getAny().add(tokenType);
+
+        // Get a SAML Token via the SAMLTokenProvider
+        CallbackHandler callbackHandler = new PasswordCallbackHandler();
+        Element samlToken = 
+            createSAMLAssertion(WSConstants.WSS_SAML2_TOKEN_TYPE, crypto, "mystskey", callbackHandler);
+        Document doc = samlToken.getOwnerDocument();
+        samlToken = (Element)doc.appendChild(samlToken);
+        OnBehalfOfType onbehalfof = new OnBehalfOfType();
+        onbehalfof.setAny(samlToken);
+
+        JAXBElement<OnBehalfOfType> onbehalfofType = 
+            new JAXBElement<OnBehalfOfType>(
+                    QNameConstants.ON_BEHALF_OF, OnBehalfOfType.class, onbehalfof
+            );
+        request.getAny().add(onbehalfofType);
+
+        // Mock up message context
+        MessageImpl msg = new MessageImpl();
+        WrappedMessageContext msgCtx = new WrappedMessageContext(msg);
+        WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx);
+
+        // Issue a token
+        RequestSecurityTokenResponseCollectionType response = 
+            issueOperation.issue(request, webServiceContext);
+        List<RequestSecurityTokenResponseType> securityTokenResponse = 
+            response.getRequestSecurityTokenResponse();
+        assertTrue(!securityTokenResponse.isEmpty());
+    }
+    
+    
+    /**
+     * Test to successfully issue a SAML 2 token on-behalf-of a UsernameToken
+     */
+    @org.junit.Test
+    public void testIssueSaml2TokenOnBehalfOfUsernameToken() throws Exception {
+        TokenIssueOperation issueOperation = new TokenIssueOperation();
+
+        // Add Token Provider
+        List<TokenProvider> providerList = new ArrayList<TokenProvider>();
+        providerList.add(new SAMLTokenProvider());
+        issueOperation.setTokenProviders(providerList);
+        
+        // Add Token Validator
+        List<TokenValidator> validatorList = new ArrayList<TokenValidator>();
+        validatorList.add(new UsernameTokenValidator());
+        issueOperation.setTokenValidators(validatorList);
+
+        // Add Service
+        ServiceMBean service = new StaticService();
+        service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy"));
+        issueOperation.setServices(Collections.singletonList(service));
+
+        // Add STSProperties object
+        STSPropertiesMBean stsProperties = new StaticSTSProperties();
+        Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+        stsProperties.setEncryptionCrypto(crypto);
+        stsProperties.setSignatureCrypto(crypto);
+        stsProperties.setEncryptionUsername("myservicekey");
+        stsProperties.setSignatureUsername("mystskey");
+        stsProperties.setCallbackHandler(new PasswordCallbackHandler());
+        stsProperties.setIssuer("STS");
+        issueOperation.setStsProperties(stsProperties);
+
+        // Mock up a request
+        RequestSecurityTokenType request = new RequestSecurityTokenType();
+        JAXBElement<String> tokenType = 
+            new JAXBElement<String>(
+                    QNameConstants.TOKEN_TYPE, String.class, WSConstants.WSS_SAML2_TOKEN_TYPE
+            );
+        request.getAny().add(tokenType);
+
+        
+        // Create a UsernameToken
+        JAXBElement<UsernameTokenType> usernameTokenType = createUsernameToken("alice", "clarinet");
+        OnBehalfOfType onbehalfof = new OnBehalfOfType();
+        onbehalfof.setAny(usernameTokenType);
+        
+        JAXBElement<OnBehalfOfType> onbehalfofType = 
+            new JAXBElement<OnBehalfOfType>(
+                    QNameConstants.ON_BEHALF_OF, OnBehalfOfType.class, onbehalfof
+            );
+        request.getAny().add(onbehalfofType);
+        
+
+        // Mock up message context
+        MessageImpl msg = new MessageImpl();
+        WrappedMessageContext msgCtx = new WrappedMessageContext(msg);
+        WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx);
+
+        // Issue a token
+        RequestSecurityTokenResponseCollectionType response = 
+            issueOperation.issue(request, webServiceContext);
+        List<RequestSecurityTokenResponseType> securityTokenResponse = 
+            response.getRequestSecurityTokenResponse();
+        assertTrue(!securityTokenResponse.isEmpty());
+    }
+    
+    /**
+     * Test to successfully issue a SAML 2 token on-behalf-of a UsernameToken
+     */
+    @org.junit.Test
+    public void testIssueSaml2TokenOnBehalfOfInvalidUsernameToken() throws Exception {
+        TokenIssueOperation issueOperation = new TokenIssueOperation();
+
+        // Add Token Provider
+        List<TokenProvider> providerList = new ArrayList<TokenProvider>();
+        providerList.add(new SAMLTokenProvider());
+        issueOperation.setTokenProviders(providerList);
+        
+        // Add Token Validator
+        List<TokenValidator> validatorList = new ArrayList<TokenValidator>();
+        validatorList.add(new UsernameTokenValidator());
+        issueOperation.setTokenValidators(validatorList);
+
+        // Add Service
+        ServiceMBean service = new StaticService();
+        service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy"));
+        issueOperation.setServices(Collections.singletonList(service));
+
+        // Add STSProperties object
+        STSPropertiesMBean stsProperties = new StaticSTSProperties();
+        Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+        stsProperties.setEncryptionCrypto(crypto);
+        stsProperties.setSignatureCrypto(crypto);
+        stsProperties.setEncryptionUsername("myservicekey");
+        stsProperties.setSignatureUsername("mystskey");
+        stsProperties.setCallbackHandler(new PasswordCallbackHandler());
+        stsProperties.setIssuer("STS");
+        issueOperation.setStsProperties(stsProperties);
+
+        // Mock up a request
+        RequestSecurityTokenType request = new RequestSecurityTokenType();
+        JAXBElement<String> tokenType = 
+            new JAXBElement<String>(
+                    QNameConstants.TOKEN_TYPE, String.class, WSConstants.WSS_SAML2_TOKEN_TYPE
+            );
+        request.getAny().add(tokenType);
+
+        
+        // Create a UsernameToken without password
+        JAXBElement<UsernameTokenType> usernameTokenType = createUsernameToken("alice", null);
+        OnBehalfOfType onbehalfof = new OnBehalfOfType();
+        onbehalfof.setAny(usernameTokenType);
+        
+        JAXBElement<OnBehalfOfType> onbehalfofType = 
+            new JAXBElement<OnBehalfOfType>(
+                    QNameConstants.ON_BEHALF_OF, OnBehalfOfType.class, onbehalfof
+            );
+        request.getAny().add(onbehalfofType);
+        
+
+        // Mock up message context
+        MessageImpl msg = new MessageImpl();
+        WrappedMessageContext msgCtx = new WrappedMessageContext(msg);
+        WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx);
+
+        // Issue a token - this will fail as the UsernameToken validation fails
+        try {
+            issueOperation.issue(request, webServiceContext);
+            fail("Failure expected as no principal is available to create SAML assertion");
+        } catch (STSException ex) {
+            // expected
+        }
+    }
+    
+
+    /**
+     * Test to successfully issue a SAML 2 token (realm "B") on-behalf-of a SAML 2 token
+     * on-behalf-of token is issued by realm "A".
+     */
+    @org.junit.Test
+    public void testIssueSaml2TokenOnBehalfOfSaml2DifferentRealm() throws Exception {
+        TokenIssueOperation issueOperation = new TokenIssueOperation();
+        
+        // Add Token Provider
+        List<TokenProvider> providerList = new ArrayList<TokenProvider>();
+        SAMLTokenProvider samlTokenProvider = new SAMLTokenProvider();
+        providerList.add(samlTokenProvider);
+        issueOperation.setTokenProviders(providerList);
+        
+        // Add Token Validator
+        List<TokenValidator> validatorList = new ArrayList<TokenValidator>();
+        SAMLTokenValidator samlTokenValidator = new SAMLTokenValidator();
+        samlTokenValidator.setSamlRealmCodec(new IssuerSAMLRealmCodec());
+        validatorList.add(samlTokenValidator);
+        issueOperation.setTokenValidators(validatorList);
+
+        // Add Service
+        ServiceMBean service = new StaticService();
+        service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy"));
+        issueOperation.setServices(Collections.singletonList(service));
+        
+        // Add STSProperties object
+        STSPropertiesMBean stsProperties = new StaticSTSProperties();
+        Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+        stsProperties.setEncryptionCrypto(crypto);
+        stsProperties.setSignatureCrypto(crypto);
+        stsProperties.setEncryptionUsername("myservicekey");
+        stsProperties.setSignatureUsername("mystskey");
+        stsProperties.setCallbackHandler(new PasswordCallbackHandler());
+        stsProperties.setIssuer("STS");
+        stsProperties.setRealmParser(new CustomRealmParser());
+        stsProperties.setIdentityMapper(new CustomIdentityMapper());
+        issueOperation.setStsProperties(stsProperties);
+        
+        Map<String, SAMLRealm> realms = getSamlRealms();
+        
+        // Mock up a request
+        RequestSecurityTokenType request = new RequestSecurityTokenType();
+        JAXBElement<String> tokenType = 
+            new JAXBElement<String>(
+                QNameConstants.TOKEN_TYPE, String.class, WSConstants.WSS_SAML2_TOKEN_TYPE
+            );
+        request.getAny().add(tokenType);
+        
+        // Get a SAML Token via the SAMLTokenProvider
+        CallbackHandler callbackHandler = new PasswordCallbackHandler();
+        Element samlToken = 
+            createSAMLAssertion(WSConstants.WSS_SAML2_TOKEN_TYPE, crypto, "mystskey",
+                    callbackHandler, realms);
+        Document doc = samlToken.getOwnerDocument();
+        samlToken = (Element)doc.appendChild(samlToken);
+        OnBehalfOfType onbehalfof = new OnBehalfOfType();
+        onbehalfof.setAny(samlToken);
+
+        JAXBElement<OnBehalfOfType> onbehalfofType = 
+            new JAXBElement<OnBehalfOfType>(
+                    QNameConstants.ON_BEHALF_OF, OnBehalfOfType.class, onbehalfof
+            );
+        request.getAny().add(onbehalfofType);
+        
+        // Mock up message context
+        MessageImpl msg = new MessageImpl();
+        WrappedMessageContext msgCtx = new WrappedMessageContext(msg);
+        msgCtx.put("url", "https");
+        WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx);
+        
+        // Validate a token - this will fail as the tokenProvider doesn't understand how to handle
+        // realm "B"
+        //try {
+        //    issueOperation.issue(request, webServiceContext);
+        //} catch (STSException ex) {
+        //    // expected
+        //}
+        
+        samlTokenProvider.setRealmMap(realms);
+        
+        RequestSecurityTokenResponseCollectionType response = 
+            issueOperation.issue(request, webServiceContext);
+        List<RequestSecurityTokenResponseType> securityTokenResponseList = 
+            response.getRequestSecurityTokenResponse();
+
+        assertTrue(!securityTokenResponseList.isEmpty());       
+        RequestSecurityTokenResponseType securityTokenResponse = securityTokenResponseList.get(0);
+        
+        // Test the generated token.
+        Element assertion = null;
+        for (Object tokenObject : securityTokenResponse.getAny()) {
+            if (tokenObject instanceof JAXBElement<?>
+                && REQUESTED_SECURITY_TOKEN.equals(((JAXBElement<?>)tokenObject).getName())) {
+                RequestedSecurityTokenType rstType = 
+                    (RequestedSecurityTokenType)((JAXBElement<?>)tokenObject).getValue();
+                assertion = (Element)rstType.getAny();
+                break;
+            }
+        }
+        
+        assertNotNull(assertion);
+        String tokenString = DOM2Writer.nodeToString(assertion);
+        assertTrue(tokenString.contains("AttributeStatement"));
+        assertTrue(tokenString.contains("ALICE"));
+        assertTrue(tokenString.contains(SAML2Constants.CONF_BEARER));
+    }
+    
+
+    /*
+     * Mock up an SAML assertion element
+     */
+    private Element createSAMLAssertion(
+            String tokenType, Crypto crypto, String signatureUsername, CallbackHandler callbackHandler
+    ) throws WSSecurityException {
+        return createSAMLAssertion(tokenType, crypto, signatureUsername, callbackHandler, null);
+    }
+    
+    /*
+     * Mock up an SAML assertion element
+     */
+    private Element createSAMLAssertion(
+            String tokenType, Crypto crypto, String signatureUsername, CallbackHandler callbackHandler,
+            Map<String, SAMLRealm> realms
+    ) throws WSSecurityException {
+        SAMLTokenProvider samlTokenProvider = new SAMLTokenProvider();
+        samlTokenProvider.setRealmMap(realms);
+        
+        TokenProviderParameters providerParameters = 
+            createProviderParameters(
+                    tokenType, STSConstants.BEARER_KEY_KEYTYPE, crypto, signatureUsername, callbackHandler
+            );
+        if (realms != null) {
+            providerParameters.setRealm("A");
+        }
+        TokenProviderResponse providerResponse = samlTokenProvider.createToken(providerParameters);
+        assertTrue(providerResponse != null);
+        assertTrue(providerResponse.getToken() != null && providerResponse.getTokenId() != null);
+
+        return providerResponse.getToken();
+    }
+
+    private TokenProviderParameters createProviderParameters(
+            String tokenType, String keyType, Crypto crypto, 
+            String signatureUsername, CallbackHandler callbackHandler
+    ) throws WSSecurityException {
+        TokenProviderParameters parameters = new TokenProviderParameters();
+
+        TokenRequirements tokenRequirements = new TokenRequirements();
+        tokenRequirements.setTokenType(tokenType);
+        parameters.setTokenRequirements(tokenRequirements);
+
+        KeyRequirements keyRequirements = new KeyRequirements();
+        keyRequirements.setKeyType(keyType);
+        parameters.setKeyRequirements(keyRequirements);
+
+        parameters.setPrincipal(new CustomTokenPrincipal("alice"));
+        // Mock up message context
+        MessageImpl msg = new MessageImpl();
+        WrappedMessageContext msgCtx = new WrappedMessageContext(msg);
+        WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx);
+        parameters.setWebServiceContext(webServiceContext);
+
+        parameters.setAppliesToAddress("http://dummy-service.com/dummy");
+
+        // Add STSProperties object
+        StaticSTSProperties stsProperties = new StaticSTSProperties();
+        stsProperties.setSignatureCrypto(crypto);
+        stsProperties.setSignatureUsername(signatureUsername);
+        stsProperties.setCallbackHandler(callbackHandler);
+        stsProperties.setIssuer("STS");
+        parameters.setStsProperties(stsProperties);
+
+        parameters.setEncryptionProperties(new EncryptionProperties());
+
+        return parameters;
+    }
+
+    private JAXBElement<UsernameTokenType> createUsernameToken(String name, String password) {
+        UsernameTokenType usernameToken = new UsernameTokenType();
+        AttributedString username = new AttributedString();
+        username.setValue(name);
+        usernameToken.setUsername(username);
+        
+        // Add a password
+        if (password != null) {
+            PasswordString passwordString = new PasswordString();
+            passwordString.setValue(password);
+            passwordString.setType(WSConstants.PASSWORD_TEXT);
+            JAXBElement<PasswordString> passwordType = 
+                new JAXBElement<PasswordString>(
+                        QNameConstants.PASSWORD, PasswordString.class, passwordString
+                );
+            usernameToken.getAny().add(passwordType);
+        }
+        
+        JAXBElement<UsernameTokenType> tokenType = 
+            new JAXBElement<UsernameTokenType>(
+                QNameConstants.USERNAME_TOKEN, UsernameTokenType.class, usernameToken
+            );
+        
+        return tokenType;
+    }
+    
+    private Map<String, SAMLRealm> getSamlRealms() {
+        // Create Realms
+        Map<String, SAMLRealm> samlRealms = new HashMap<String, SAMLRealm>();
+        SAMLRealm samlRealm = new SAMLRealm();
+        samlRealm.setIssuer("A-Issuer");
+        samlRealms.put("A", samlRealm);
+        samlRealm = new SAMLRealm();
+        samlRealm.setIssuer("B-Issuer");
+        samlRealms.put("B", samlRealm);
+        return samlRealms;
+    }
+
+    private Properties getEncryptionProperties() {
+        Properties properties = new Properties();
+        properties.put(
+                "org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin"
+        );
+        properties.put("org.apache.ws.security.crypto.merlin.keystore.password", "stsspass");
+        properties.put("org.apache.ws.security.crypto.merlin.keystore.file", "stsstore.jks");
+
+        return properties;
+    }
+
+
+}



Mime
View raw message